Inventory management focused game written in Godot / C#
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

130 lines
4.0 KiB

public partial class MultiplayerMenu : MarginContainer
{
enum Status
{
Disconnected,
ConnectionFailed,
HostingFailed,
Connecting,
Connected,
Hosting,
}
Status _status = Status.Disconnected;
[Export] public Label StatusLabel { get; set; }
[ExportGroup("When Disconnected")]
[Export] public Container WhenDisconnected { get; set; }
[Export] public LineEdit AddressInput { get; set; }
[Export] public SpinBox PortInput { get; set; }
[Export] public Button ConnectButton { get; set; }
[Export] public Button HostButton { get; set; }
[ExportGroup("When Server")]
[Export] public Container WhenServer { get; set; }
[Export] public LineEdit PortDisplay { get; set; }
[ExportGroup("When Connected")]
[Export] public Container WhenConnected { get; set; }
[Export] public Label PlayersLabel { get; set; }
[Export] public Button DisconnectButton { get; set; }
public override void _Ready()
{
PortDisplay.AddThemeColorOverride("font_uneditable_color", PortDisplay.GetThemeColor("font_color"));
Multiplayer.ConnectedToServer += () => UpdateStatus(Status.Connected);
Multiplayer.ConnectionFailed += () => UpdateStatus(Status.ConnectionFailed);
Multiplayer.ServerDisconnected += () => UpdateStatus(Status.Disconnected);
Game.Instance.MultiplayerManager.PlayerJoined += _ => UpdatePlayerCount();
Game.Instance.MultiplayerManager.PlayerLeft += _ => UpdatePlayerCount();
}
void UpdateStatus(Status status)
{
_status = status;
StatusLabel.Text = status switch {
Status.Disconnected => "Disconnected",
Status.ConnectionFailed => "Connection failed!",
Status.HostingFailed => "Hosting failed!",
Status.Connecting => "Connecting ...",
Status.Connected => "Connected",
Status.Hosting => "Hosting",
_ => throw new InvalidOperationException(),
};
StatusLabel.LabelSettings.FontColor = (status switch {
Status.Disconnected => Colors.DarkGray,
Status.ConnectionFailed => Colors.Red,
Status.HostingFailed => Colors.Red,
Status.Connecting => Colors.Yellow,
Status.Connected => Colors.Green,
Status.Hosting => Colors.Green,
_ => throw new InvalidOperationException(),
}).Lerp(StatusLabel.GetThemeColor("font_color"), 0.5f);
WhenDisconnected.Visible = status < Status.Connecting;
WhenServer.Visible = status == Status.Hosting;
WhenConnected.Visible = status >= Status.Connecting;
DisconnectButton.Text = status == Status.Hosting ? "Close Server" : "Disconnect";
UpdatePlayerCount();
}
void UpdatePlayerCount()
{
PlayersLabel.Text = _status switch {
< Status.Connecting => "Singleplayer",
Status.Connecting => "??? Players",
> Status.Connecting => ((Func<string>)(() => {
var players = Game.Instance.MultiplayerManager.Players.GetChildCount();
return $"{players} {(players != 1 ? "Players" : "Player")}";
}))(),
};
}
public void OnShowAddressToggled(bool toggledOn)
{
AddressInput.Secret = !toggledOn;
AddressInput.VirtualKeyboardType = toggledOn
? LineEdit.VirtualKeyboardTypeEnum.Default
: LineEdit.VirtualKeyboardTypeEnum.Password;
}
public void OnConnectPressed()
{
var address = AddressInput.Text;
if (address == "") address = AddressInput.PlaceholderText;
ushort port;
var colonIndex = address.LastIndexOf(':');
if (colonIndex >= 0) {
if (!ushort.TryParse(address[(colonIndex+1)..], out port)) port = 0;
address = address[..colonIndex];
} else {
port = ushort.Parse(AddressInput.PlaceholderText.Split(':')[1]);
}
Game.Instance.MultiplayerManager.Connect(address, port);
UpdateStatus(Status.Connecting);
}
public void OnHostPressed()
{
var port = (ushort)RoundToInt(PortInput.Value);
if (Game.Instance.MultiplayerManager.CreateServer(port)) {
PortDisplay.Text = port.ToString();
UpdateStatus(Status.Hosting);
} else
UpdateStatus(Status.HostingFailed);
}
public void OnDisconnectPressed()
{
Game.Instance.MultiplayerManager.Disconnect();
UpdateStatus(Status.Disconnected);
}
}