From aa9b3a1038e5b8c7c528c8dacfeb4e0fe6d8e324 Mon Sep 17 00:00:00 2001 From: Santoshh-25 Date: Mon, 2 Feb 2026 01:24:50 +0530 Subject: [PATCH] Fix: re-enable server creation after client disconnect --- Netcode/NetControlPanelLow.cs | 284 +++++++++++++++++----------------- 1 file changed, 144 insertions(+), 140 deletions(-) diff --git a/Netcode/NetControlPanelLow.cs b/Netcode/NetControlPanelLow.cs index 493923d..52f8004 100644 --- a/Netcode/NetControlPanelLow.cs +++ b/Netcode/NetControlPanelLow.cs @@ -7,145 +7,149 @@ namespace Framework.Netcode; public abstract partial class NetControlPanelLow : Control - where TGameClient : GodotClient, new() - where TGameServer : GodotServer, new() + where TGameClient : GodotClient, new() + where TGameServer : GodotServer, new() { - // API - public Net Net { get; private set; } - - // Exports - [Export] private LineEdit _usernameLineEdit; - [Export] private LineEdit _ipLineEdit; - [Export] private Button _startServerBtn; - [Export] private Button _stopServerBtn; - [Export] private Button _startClientBtn; - [Export] private Button _stopClientBtn; - - // Config - protected abstract ENetOptions Options { get; set; } - protected virtual int DefaultMaxClients { get; } = 100; - protected virtual string DefaultLocalIp { get; } = "127.0.0.1"; - protected virtual ushort DefaultPort { get; } = 25565; - - // Fields - private string _username = ""; - private ushort _port; - private string _ip; - - // Godot Lifecycle - public override void _Ready() - { - _port = DefaultPort; - _ip = DefaultLocalIp; - - ServerFactory serverFactory = new(() => new TGameServer()); - ClientFactory clientFactory = new(() => new TGameClient()); - - Net = new Net(clientFactory, serverFactory); - - // Setup buttons - _startServerBtn.Pressed += OnStartServerPressed; - _stopServerBtn.Pressed += Net.StopServer; - _startClientBtn.Pressed += OnStartClientBtnPressed; - _stopClientBtn.Pressed += Net.StopClient; - - // Setup input events - _ipLineEdit.TextChanged += OnIpChanged; - _usernameLineEdit.TextChanged += OnUsernameChanged; - - Net.ClientCreated += OnClientCreated; - Net.ClientDestroyed += OnClientDestroyed; - } - - public override void _Process(double delta) - { - Net.Client?.HandlePackets(); - } - - public override void _ExitTree() - { - _startServerBtn.Pressed -= OnStartServerPressed; - _stopServerBtn.Pressed -= Net.StopServer; - _startClientBtn.Pressed -= OnStartClientBtnPressed; - _stopClientBtn.Pressed -= Net.StopClient; - - _ipLineEdit.TextChanged -= OnIpChanged; - _usernameLineEdit.TextChanged -= OnUsernameChanged; - - Net.ClientCreated -= OnClientCreated; - Net.ClientDestroyed -= OnClientDestroyed; - Net = null; - } - - // UI Callbacks - private void OnStartServerPressed() => Net.StartServer(_port, DefaultMaxClients, Options); - - private async void OnStartClientBtnPressed() - { - await Net.StartClient(_ip, _port); - } - - private void OnIpChanged(string text) - { - _ip = FetchIpFromString(text, ref _port); - } - - private void OnUsernameChanged(string text) - { - _username = text.IsAlphaNumeric() ? text : _username; - } - - private void OnClientCreated(GodotClient client) - { - client.Connected += OnClientConnected; - client.Disconnected += OnClientDisconnected; - } - - private void OnClientDestroyed(GodotClient client) - { - client.Connected -= OnClientConnected; - client.Disconnected -= OnClientDisconnected; - } - - private void OnClientConnected() - { - if (!Net.Server.IsRunning) - { - _startServerBtn.Disabled = true; - _stopServerBtn.Disabled = true; - } - - GetTree().UnfocusCurrentControl(); - } - - private void OnClientDisconnected(DisconnectOpcode opcode) - { - _startServerBtn.Disabled = false; - _stopServerBtn.Disabled = false; - } - - // Private Static Methods - private static string FetchIpFromString(string ipString, ref ushort port) - { - string[] parts = ipString.Split(":"); - string ip = parts[0]; - - if (parts.Length > 1 && ushort.TryParse(parts[1], out ushort foundPort)) - { - port = foundPort; - } - - return ip; - } - - // Records - private record ClientFactory(Func Creator) : IGameClientFactory - { - public GodotClient CreateClient() => Creator(); - } - - private record ServerFactory(Func Creator) : IGameServerFactory - { - public GodotServer CreateServer() => Creator(); - } + // API + public Net Net { get; private set; } + + // Exports + [Export] private LineEdit _usernameLineEdit; + [Export] private LineEdit _ipLineEdit; + [Export] private Button _startServerBtn; + [Export] private Button _stopServerBtn; + [Export] private Button _startClientBtn; + [Export] private Button _stopClientBtn; + + // Config + protected abstract ENetOptions Options { get; set; } + protected virtual int DefaultMaxClients { get; } = 100; + protected virtual string DefaultLocalIp { get; } = "127.0.0.1"; + protected virtual ushort DefaultPort { get; } = 25565; + + // Fields + private string _username = ""; + private ushort _port; + private string _ip; + + // Godot Lifecycle + public override void _Ready() + { + _port = DefaultPort; + _ip = DefaultLocalIp; + + ServerFactory serverFactory = new(() => new TGameServer()); + ClientFactory clientFactory = new(() => new TGameClient()); + + Net = new Net(clientFactory, serverFactory); + + // Setup buttons + _startServerBtn.Pressed += OnStartServerPressed; + _stopServerBtn.Pressed += Net.StopServer; + _startClientBtn.Pressed += OnStartClientBtnPressed; + _stopClientBtn.Pressed += Net.StopClient; + + // Setup input events + _ipLineEdit.TextChanged += OnIpChanged; + _usernameLineEdit.TextChanged += OnUsernameChanged; + + Net.ClientCreated += OnClientCreated; + Net.ClientDestroyed += OnClientDestroyed; + } + + public override void _Process(double delta) + { + Net.Client?.HandlePackets(); + } + + public override void _ExitTree() + { + _startServerBtn.Pressed -= OnStartServerPressed; + _stopServerBtn.Pressed -= Net.StopServer; + _startClientBtn.Pressed -= OnStartClientBtnPressed; + _stopClientBtn.Pressed -= Net.StopClient; + + _ipLineEdit.TextChanged -= OnIpChanged; + _usernameLineEdit.TextChanged -= OnUsernameChanged; + + Net.ClientCreated -= OnClientCreated; + Net.ClientDestroyed -= OnClientDestroyed; + Net = null; + } + + // UI Callbacks + private void OnStartServerPressed() => Net.StartServer(_port, DefaultMaxClients, Options); + + private async void OnStartClientBtnPressed() + { + await Net.StartClient(_ip, _port); + } + + private void OnIpChanged(string text) + { + _ip = FetchIpFromString(text, ref _port); + } + + private void OnUsernameChanged(string text) + { + _username = text.IsAlphaNumeric() ? text : _username; + } + + private void OnClientCreated(GodotClient client) + { + client.Connected += OnClientConnected; + client.Disconnected += OnClientDisconnected; + } + + private void OnClientDestroyed(GodotClient client) + { + client.Connected -= OnClientConnected; + client.Disconnected -= OnClientDisconnected; + + //Re-enable server buttons when client is destroyed + _startServerBtn.Disabled = false; + _stopServerBtn.Disabled = false; + } + + private void OnClientConnected() + { + if (!Net.Server.IsRunning) + { + _startServerBtn.Disabled = true; + _stopServerBtn.Disabled = true; + } + + GetTree().UnfocusCurrentControl(); + } + + private void OnClientDisconnected(DisconnectOpcode opcode) + { + _startServerBtn.Disabled = false; + _stopServerBtn.Disabled = false; + } + + // Private Static Methods + private static string FetchIpFromString(string ipString, ref ushort port) + { + string[] parts = ipString.Split(":"); + string ip = parts[0]; + + if (parts.Length > 1 && ushort.TryParse(parts[1], out ushort foundPort)) + { + port = foundPort; + } + + return ip; + } + + // Records + private record ClientFactory(Func Creator) : IGameClientFactory + { + public GodotClient CreateClient() => Creator(); + } + + private record ServerFactory(Func Creator) : IGameServerFactory + { + public GodotServer CreateServer() => Creator(); + } }