Keep kick reason and reconnect intent across MSCLoader's mod reload on returning to the menu

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-27 17:31:47 +02:00
co-authored by Claude Opus 5.5
parent 526f9e9c77
commit 09c85e3d96
2 changed files with 78 additions and 0 deletions
+2
View File
@@ -33,6 +33,8 @@ Server und Mod müssen beide 2.8 sein (Server: `git pull && docker compose up -d
Nach Kick, Ban oder eigenem Trennen wird nicht neu verbunden
**Behoben**
- Nach Kick/Reset kam weder das Fenster mit dem Grund noch das automatische Neu-Verbinden: MSCLoader lädt beim Wechsel
ins Hauptmenü alle Mods neu und damit ging der Zustand verloren. Er wird jetzt vorher gesichert und danach fortgesetzt
- Absturz („NaN … collider“) und abfallende Teile am Satsuma: Türen/Haube/Kofferraum wurden gegen das Scharnier an
ihre Position teleportiert – das erzeugte riesige Kräfte. Jetzt zieht die Feder des Scharniers sie sanft auf den Winkel
- Beim anderen Spieler „orgelte“ der Anlasser endlos: erzwungene Geräusche/Lichter werden losgelassen, sobald keine
+76
View File
@@ -128,6 +128,7 @@ namespace MSCO
};
FsmSync.Init();
SafetyPatches.Apply(); // verhindert den Absturz durch Kreis in der Objekt-Hierarchie
RestorePendingState();
discord.Start();
steam.Created += OnSteamLobbyCreated;
@@ -833,6 +834,7 @@ namespace MSCO
menuButtonsHidden = MenuHelper.HideGameMenuButtons() > 0;
}
UpdateOverlayKeys();
PersistPendingState(); // Kick-Grund / Neu-Verbinden über das Neuladen der Mods hinweg merken
MscoLog.Drain(overlays.Log); // alle Mod-Meldungen in die MSCO-Konsole (F7)
UpdatePresence();
@@ -939,6 +941,79 @@ namespace MSCO
/// <summary>Warum man zuletzt getrennt wurde - wird im Hauptmenü angezeigt, bis man OK drückt.</summary>
public string DisconnectNotice { get; private set; }
// ---------------------------------------------------------------- Über Neuladen hinweg merken
// Beim Wechsel ins Hauptmenü lädt MSCLoader alle Mods neu - dabei ginge der Kick-Grund bzw. "bitte neu
// verbinden" verloren, bevor man das Menü überhaupt sieht. Deshalb in den PlayerPrefs sichern.
const string PrefNotice = "MSCO_PendingNotice";
const string PrefReconnect = "MSCO_PendingReconnect";
const double NoticeMaxAgeMinutes = 10;
const double ReconnectMaxAgeMinutes = 3;
string savedNotice, savedReconnect;
int savedAttempts = -1;
void PersistPendingState()
{
if (ReferenceEquals(savedNotice, DisconnectNotice) && ReferenceEquals(savedReconnect, reconnectMessage)
&& savedAttempts == reconnectAttempts) return;
savedNotice = DisconnectNotice;
savedReconnect = reconnectMessage;
savedAttempts = reconnectAttempts;
string now = System.DateTime.UtcNow.Ticks.ToString();
try
{
if (DisconnectNotice != null) PlayerPrefs.SetString(PrefNotice, now + "\n" + DisconnectNotice);
else PlayerPrefs.DeleteKey(PrefNotice);
if (reconnectMessage != null && lastServerHost != null)
PlayerPrefs.SetString(PrefReconnect, string.Join("\n", new[]
{
now, lastServerHost, lastServerPort.ToString(), lastServerName ?? "", lastServerMax.ToString(),
reconnectAttempts.ToString(), reconnectMessage
}));
else PlayerPrefs.DeleteKey(PrefReconnect);
PlayerPrefs.Save();
}
catch (System.Exception e) { MscoLog.Warning("Could not remember the disconnect state: " + e.Message); }
}
static bool Fresh(string ticks, double maxMinutes)
{
long t;
return long.TryParse(ticks, out t) && (System.DateTime.UtcNow - new System.DateTime(t)).TotalMinutes < maxMinutes;
}
void RestorePendingState()
{
try
{
string[] notice = PlayerPrefs.GetString(PrefNotice, "").Split(new[] { '\n' }, 2);
if (notice.Length == 2 && Fresh(notice[0], NoticeMaxAgeMinutes)) DisconnectNotice = notice[1];
string[] rc = PlayerPrefs.GetString(PrefReconnect, "").Split(new[] { '\n' }, 7);
int port, max, attempts;
if (rc.Length == 7 && Fresh(rc[0], ReconnectMaxAgeMinutes) && int.TryParse(rc[2], out port)
&& int.TryParse(rc[4], out max) && int.TryParse(rc[5], out attempts))
{
lastServerHost = rc[1];
lastServerPort = port;
lastServerName = rc[3].Length > 0 ? rc[3] : null;
lastServerMax = max;
reconnectAttempts = attempts;
reconnectMessage = rc[6];
reconnectAt = Time.realtimeSinceStartup + 2f; // erst das Menü fertig laden lassen
DisconnectNotice = null;
MscoLog.Info("[MSCO] Continuing reconnect to " + lastServerHost + ":" + lastServerPort);
}
}
catch (System.Exception e) { MscoLog.Warning("Could not restore the disconnect state: " + e.Message); }
savedNotice = DisconnectNotice;
savedReconnect = reconnectMessage;
savedAttempts = reconnectAttempts;
// Einmal gelesen = erledigt; neu gespeichert wird bei der nächsten Änderung
PlayerPrefs.DeleteKey(PrefNotice);
PlayerPrefs.DeleteKey(PrefReconnect);
if (DisconnectNotice != null || reconnectMessage != null) { savedNotice = null; savedReconnect = null; savedAttempts = -1; }
}
public void ClearDisconnectNotice() { DisconnectNotice = null; }
public bool IsReconnecting { get { return reconnectMessage != null && session == null; } }
public int ReconnectAttempt { get { return reconnectAttempts; } }
@@ -1057,6 +1132,7 @@ namespace MSCO
if (wasClientInGame)
{
SetStatus("Disconnected from host: " + reason);
PersistPendingState(); // MSCLoader lädt die Mods im Menü neu - vorher sichern
Application.LoadLevel(MenuHelper.MenuScene);
}
}