Disconnect/kick prompt with reason, reconnect after world reset with retries; stop mass 'consumed' deletes on scene reload

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-27 16:31:40 +02:00
co-authored by Claude Opus 5.5
parent 90c1af4513
commit 31e630dccb
4 changed files with 137 additions and 38 deletions
+53 -7
View File
@@ -594,6 +594,9 @@ namespace MSCO
string centerMessage; // große Meldung in der Bildmitte
float centerMessageUntil;
float reconnectAt;
int reconnectAttempts;
const int MaxReconnectAttempts = 5;
const float ReconnectRetrySeconds = 6f;
void ConnectToServer(string host, int port, string displayName, int maxPlayers)
{
@@ -817,14 +820,22 @@ namespace MSCO
steam.Tick();
// Nach reset-world o.ä.: im Hauptmenü automatisch wieder mit demselben Server verbinden
if (reconnectMessage != null && session == null && MenuHelper.InMenu && Time.realtimeSinceStartup >= reconnectAt)
// Nach reset-world o.ä.: im Hauptmenü automatisch wieder mit demselben Server verbinden. Mehrere Versuche -
// der Server kann nach einem Neustart noch ein paar Sekunden brauchen.
if (reconnectMessage != null && session == null && MenuHelper.InMenu && !checkingServer
&& Time.realtimeSinceStartup >= reconnectAt)
{
string message = reconnectMessage;
reconnectMessage = null;
if (lastServerHost != null)
if (lastServerHost == null || reconnectAttempts >= MaxReconnectAttempts)
{
SetStatus(message);
DisconnectNotice = "Could not reconnect to the server after " + reconnectAttempts + " attempts. " +
"Try again from the server browser.";
reconnectMessage = null;
reconnectAttempts = 0;
}
else
{
reconnectAttempts++;
reconnectAt = Time.realtimeSinceStartup + ReconnectRetrySeconds;
JoinServer(lastServerHost, lastServerPort, lastServerName, lastServerMax);
}
}
@@ -909,6 +920,30 @@ namespace MSCO
public string DisconnectNotice { get; private set; }
public void ClearDisconnectNotice() { DisconnectNotice = null; }
public bool IsReconnecting { get { return reconnectMessage != null && session == null; } }
public int ReconnectAttempt { get { return reconnectAttempts; } }
public int ReconnectMaxAttempts { get { return MaxReconnectAttempts; } }
/// <summary>Automatisches Neu-Verbinden abbrechen (Knopf im Reconnect-Fenster).</summary>
public void CancelReconnect()
{
reconnectMessage = null;
reconnectAttempts = 0;
SetStatus("Reconnect cancelled");
}
/// <summary>Überschrift für das Trennungs-Fenster.</summary>
public string DisconnectTitle
{
get
{
string r = (DisconnectNotice ?? "").ToLower();
if (r.Contains("banned")) return "BANNED";
if (r.Contains("kick")) return "KICKED";
if (r.Contains("shutting down") || r.Contains("server stopped") || r.Contains("shut down")) return "SERVER CLOSED";
if (r.Contains("could not reconnect")) return "RECONNECT FAILED";
return "DISCONNECTED";
}
}
bool worldSynced; // Server: Weltzustand angewendet
@@ -1120,6 +1155,8 @@ namespace MSCO
AddPlayer(id, r.ReadString(), id == localId);
}
handshakeDone = true;
reconnectMessage = null; // (wieder) verbunden
reconnectAttempts = 0;
SetStatus(dedicated ? "Connected to server - loading..." : "Connected - waiting for host to start...");
break;
}
@@ -1127,8 +1164,17 @@ namespace MSCO
case MsgType.Reject:
{
string why = r.ReadString();
serverReason = why; // für den Hinweis im Hauptmenü (Kick, Ban, Server voll, Shutdown ...)
serverReason = why; // für das Fenster im Hauptmenü (Kick, Ban, Server voll, Shutdown ...)
if (why.ToLower().Contains("banned")) reconnectMessage = null; // gebannt: nicht weiter versuchen
session.Close((dedicated || connectingToServer ? "Rejected by server: " : "Rejected by host: ") + why);
if (MenuHelper.InGame)
{
// Im Spiel: Grund erst groß anzeigen, dann ins Hauptmenü (dort kommt das Fenster mit OK)
centerMessage = why;
centerMessageUntil = Time.realtimeSinceStartup + 3f;
reconnectHoldUntil = Time.realtimeSinceStartup + 2.5f;
return;
}
OnSessionEnded(session.CloseReason);
break;
}