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 10:59:50 +02:00
co-authored by Claude Opus 5.5
parent 0ae4dae28d
commit bdaedcc1e8
2 changed files with 26 additions and 5 deletions
+4 -3
View File
@@ -527,7 +527,8 @@ namespace MSCO
{ {
Rect row = GUILayoutUtility.GetRect(10, 32, GUILayout.ExpandWidth(true)); Rect row = GUILayoutUtility.GetRect(10, 32, GUILayout.ExpandWidth(true));
GUI.Box(new Rect(row.x, row.y, row.width, row.height - 4), GUIContent.none, rowBox); GUI.Box(new Rect(row.x, row.y, row.width, row.height - 4), GUIContent.none, rowBox);
GUI.DrawTexture(new Rect(row.x + 12, row.y + 11, 8, 8), texOnline); // Eigener Punkt gelb, solange man noch lädt/synchronisiert; grün, wenn man wirklich im Spiel ist
GUI.DrawTexture(new Rect(row.x + 12, row.y + 11, 8, 8), p.IsLocal && !mp.IsFullyConnected ? texPending : texOnline);
GUI.Label(new Rect(row.x + 30, row.y, row.width - 150, row.height - 2), p.Name, rowNameStyle); GUI.Label(new Rect(row.x + 30, row.y, row.width - 150, row.height - 2), p.Name, rowNameStyle);
string tag = p.Id == NetSession.HostId ? "HOST" : ""; string tag = p.Id == NetSession.HostId ? "HOST" : "";
if (p.IsLocal) tag = tag.Length > 0 ? tag + " · YOU" : "YOU"; if (p.IsLocal) tag = tag.Length > 0 ? tag + " · YOU" : "YOU";
@@ -555,7 +556,7 @@ namespace MSCO
void DrawStatusBar(MultiplayerManager mp, Rect r) void DrawStatusBar(MultiplayerManager mp, Rect r)
{ {
GUI.Box(r, GUIContent.none, sidebarBox); GUI.Box(r, GUIContent.none, sidebarBox);
Texture2D dot = mp.IsPeerReady ? texOnline : mp.IsInSession ? texPending : texMuted; Texture2D dot = mp.IsFullyConnected ? texOnline : mp.IsInSession || mp.IsReconnecting ? texPending : texMuted;
GUI.DrawTexture(new Rect(r.x + 18, r.y + (r.height - 8) / 2f, 8, 8), dot); GUI.DrawTexture(new Rect(r.x + 18, r.y + (r.height - 8) / 2f, 8, 8), dot);
GUI.Label(new Rect(r.x + 36, r.y, r.width - 180, r.height), mp.Status, statusStyle); GUI.Label(new Rect(r.x + 36, r.y, r.width - 180, r.height), mp.Status, statusStyle);
if (GUI.Button(new Rect(r.xMax - 118, r.y + 6, 106, r.height - 12), "MINIMIZE", tabStyle)) if (GUI.Button(new Rect(r.xMax - 118, r.y + 6, 106, r.height - 12), "MINIMIZE", tabStyle))
@@ -568,7 +569,7 @@ namespace MSCO
ScreenRect = r; ScreenRect = r;
GUI.Box(r, GUIContent.none, sidebarBox); GUI.Box(r, GUIContent.none, sidebarBox);
GUI.Box(new Rect(r.x + 10, r.yMax - 3, r.width - 20, 3), GUIContent.none, accentBox); GUI.Box(new Rect(r.x + 10, r.yMax - 3, r.width - 20, 3), GUIContent.none, accentBox);
Texture2D dot = mp.IsPeerReady ? texOnline : mp.IsInSession ? texPending : texMuted; Texture2D dot = mp.IsFullyConnected ? texOnline : mp.IsInSession || mp.IsReconnecting ? texPending : texMuted;
Texture2D logo = Branding.LogoTexture; Texture2D logo = Branding.LogoTexture;
if (logo != null) GUI.DrawTexture(new Rect(r.x + 8, r.y + 4, 22, 22), logo); if (logo != null) GUI.DrawTexture(new Rect(r.x + 8, r.y + 4, 22, 22), logo);
GUI.DrawTexture(new Rect(r.x + 36, r.y + 11, 8, 8), dot); GUI.DrawTexture(new Rect(r.x + 36, r.y + 11, 8, 8), dot);
+22 -2
View File
@@ -860,6 +860,23 @@ namespace MSCO
public string DisconnectNotice { get; private set; } public string DisconnectNotice { get; private set; }
public void ClearDisconnectNotice() { DisconnectNotice = null; } public void ClearDisconnectNotice() { DisconnectNotice = null; }
public bool IsReconnecting { get { return reconnectMessage != null && session == null; } } public bool IsReconnecting { get { return reconnectMessage != null && session == null; } }
bool worldSynced; // Server: Weltzustand angewendet
/// <summary>
/// Wirklich verbunden (grüner Punkt): Host sobald die Sitzung läuft; auf einem Server erst, wenn man im Spiel ist
/// und der Weltzustand angewendet wurde; bei P2P als Client, wenn man im Spiel ist. Vorher gelb.
/// </summary>
public bool IsFullyConnected
{
get
{
if (session == null) return false;
if (session.IsHost) return true;
if (!handshakeDone || !MenuHelper.InGame) return false;
return !dedicated || worldSynced;
}
}
public string ReconnectMessage { get { return reconnectMessage; } } public string ReconnectMessage { get { return reconnectMessage; } }
/// <summary>Technische Gründe in verständliche Sätze übersetzen.</summary> /// <summary>Technische Gründe in verständliche Sätze übersetzen.</summary>
@@ -893,6 +910,7 @@ namespace MSCO
if (session != null && session.IsSteam) steam.Leave(); if (session != null && session.IsSteam) steam.Leave();
session = null; session = null;
handshakeDone = false; handshakeDone = false;
worldSynced = false;
pingMs = -1f; pingMs = -1f;
teleportToHost = false; teleportToHost = false;
dedicated = false; dedicated = false;
@@ -1333,6 +1351,7 @@ namespace MSCO
doorSync.Reset(); doorSync.Reset();
FsmSync.Reset(); FsmSync.Reset();
readySent = false; readySent = false;
worldSynced = false;
if (session != null) SetStatus(session.IsHost ? "Hosting" : "Connected"); if (session != null) SetStatus(session.IsHost ? "Hosting" : "Connected");
} }
else if (MenuHelper.InMenu) else if (MenuHelper.InMenu)
@@ -1597,6 +1616,7 @@ namespace MSCO
if (objects.ApplySnapshotPose(p.Key, p.Value.Position, p.Value.Rotation)) applied++; if (objects.ApplySnapshotPose(p.Key, p.Value.Position, p.Value.Rotation)) applied++;
if (spawned > 0) MscoLog.Info(spawned + " spawned item(s) restored"); if (spawned > 0) MscoLog.Info(spawned + " spawned item(s) restored");
worldSynced = true;
MscoLog.Info("[MSCO] World synced: " + applied + "/" + objectCount + " objects, " + eventCount + " part/bolt actions"); MscoLog.Info("[MSCO] World synced: " + applied + "/" + objectCount + " objects, " + eventCount + " part/bolt actions");
SetStatus("Connected"); SetStatus("Connected");
} }
@@ -1729,13 +1749,13 @@ namespace MSCO
void DrawHud() void DrawHud()
{ {
// Statuszeile oben in der Mitte (links oben ist die Spielanzeige) // Statuszeile oben in der Mitte (links oben ist die Spielanzeige)
string state = IsPeerReady ? "CONNECTED" : "WAITING"; string state = IsFullyConnected ? "CONNECTED" : IsPeerReady ? "SYNCING..." : "WAITING";
string text = "MSCO • " + state + " • " + (dedicated ? "Server" : IsHost ? "Host" : "Client") + " • " + string text = "MSCO • " + state + " • " + (dedicated ? "Server" : IsHost ? "Host" : "Client") + " • " +
players.Count + " player(s) • " + objects.Count + " synced objects"; players.Count + " player(s) • " + objects.Count + " synced objects";
var rect = new Rect((Screen.width - 520) / 2f, 6, 520, 24); var rect = new Rect((Screen.width - 520) / 2f, 6, 520, 24);
if (hudBox == null) hudBox = UiTheme.Panel9(new Color(0.06f, 0.06f, 0.07f, 0.85f), 8); if (hudBox == null) hudBox = UiTheme.Panel9(new Color(0.06f, 0.06f, 0.07f, 0.85f), 8);
GUI.Box(rect, GUIContent.none, hudBox); GUI.Box(rect, GUIContent.none, hudBox);
hudStyle.normal.textColor = IsPeerReady ? new Color(0.24f, 0.84f, 0.55f) : new Color(0.95f, 0.76f, 0.11f); hudStyle.normal.textColor = IsFullyConnected ? new Color(0.24f, 0.84f, 0.55f) : new Color(0.95f, 0.76f, 0.11f);
GUI.Label(rect, text, hudStyle); GUI.Label(rect, text, hudStyle);
DrawNameTags(); DrawNameTags();