Server closes connections gracefully so kick/ban/reset/shutdown messages arrive; status dot and HUD yellow until really connected (also while reconnecting)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-27 11:00:06 +02:00
co-authored by Claude Opus 5.5
parent 08844b18ac
commit 57e1d3d3a8
3 changed files with 70 additions and 8 deletions
+15 -7
View File
@@ -79,7 +79,7 @@ public sealed class GameServer
public void EnqueueCommand(string line) => commands.Enqueue(line);
int JoinedCount => clients.Values.Count(c => c.State == ClientState.Joined);
int JoinedCount => clients.Values.Count(c => c.State == ClientState.Joined && !c.Conn.IsClosing); // gerade getrennte zählen nicht mehr
// ---------------------------------------------------------------- Start / Schleife
@@ -142,8 +142,16 @@ public sealed class GameServer
{
// Grund mitschicken: die Spieler sehen ihn im Hauptmenü
if (c.State == ClientState.Joined) c.Conn.Send(MsgType.Reject, Wire.Build(w => w.Write("The server was shut down.")));
c.Conn.Close("Server shutting down");
c.Conn.CloseAfterSend("Server shutting down");
}
// Kurz warten, bis die Spieler die Meldung gelesen haben (sauber trennen statt hart abbrechen)
var waitUntil = DateTime.UtcNow.AddSeconds(1.5);
while (DateTime.UtcNow < waitUntil && clients.Values.Any(c => !c.Conn.IsClosed))
{
foreach (var c in clients.Values) c.Conn.Poll();
Thread.Sleep(20);
}
foreach (var c in clients.Values) c.Conn.Close("Server shutting down");
listener.Stop();
SaveWorld();
if (!offline)
@@ -272,7 +280,7 @@ public sealed class GameServer
w.Write(names.Count);
foreach (string n in names) w.Write(n);
}));
c.Conn.Close("Info query");
c.Conn.CloseAfterSend("Info query");
return;
case MsgType.Hello:
@@ -404,8 +412,8 @@ public sealed class GameServer
c.SteamVerified = steam.Enabled && !c.SteamId.StartsWith("name:");
foreach (var other in clients.Values)
{
if (other == c || other.State != ClientState.Joined || other.SteamId != c.SteamId) continue;
if (c.SteamVerified) other.Conn.Close("Joined from another location"); // echter Account: alte Verbindung trennen
if (other == c || other.State != ClientState.Joined || other.Conn.IsClosing || other.SteamId != c.SteamId) continue;
if (c.SteamVerified) other.Conn.CloseAfterSend("Joined from another location"); // echter Account: alte Verbindung trennen
else { Reject(c, "A player with this identity is already connected"); return; }
}
@@ -440,7 +448,7 @@ public sealed class GameServer
void Reject(Client c, string reason)
{
c.Conn.Send(MsgType.Reject, Wire.Build(w => w.Write(reason)));
c.Conn.Close(reason);
c.Conn.CloseAfterSend(reason);
Log($"Rejected {c.Name} ({c.Conn.RemoteAddress}): {reason}");
}
@@ -472,7 +480,7 @@ public sealed class GameServer
foreach (var c in clients.Values.Where(x => x.State == ClientState.Joined).ToList())
{
c.Conn.Send(MsgType.Reconnect, Wire.Build(w => w.Write(message)));
c.Conn.Close("Reconnect after world change");
c.Conn.CloseAfterSend("Reconnect after world change");
count++;
}
if (count > 0) Log($"{count} player(s) will reconnect");