Pause game input while typing (chat/console/admin); isolate sync subsystems so one error doesn't stop everything

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-26 23:56:14 +02:00
co-authored by Claude Opus 5.5
parent f4d154d4a5
commit d7a9479baa
2 changed files with 103 additions and 23 deletions
+58 -22
View File
@@ -1233,7 +1233,7 @@ namespace MSCO
StartCoroutine(ApplyWorldSnapshot(snapshot));
}
if (MSCO.PassengerKey != null && MSCO.PassengerKey.GetKeybindDown())
if (MSCO.PassengerKey != null && !overlays.AnyOpen && MSCO.PassengerKey.GetKeybindDown())
{
string result = passenger.Toggle(localPlayer, playerCamera, objects, players);
if (result != null)
@@ -1246,58 +1246,94 @@ namespace MSCO
bool ready = IsPeerReady;
if (ready)
{
// Jedes Teilsystem einzeln abgesichert: ein Fehler in einem (z.B. an einem gerade zerstörten Objekt)
// soll nicht den ganzen Sync stoppen
sendTimer += Time.unscaledDeltaTime; // läuft auch im Pausenmenü (timeScale = 0) weiter
if (sendTimer >= SendInterval)
{
sendTimer = 0f;
SendGame(MsgType.Player, BuildLocalState().Serialize());
try { SendGame(MsgType.Player, BuildLocalState().Serialize()); }
catch (System.Exception e) { ReportError("player state", e); }
}
objects.Update(localPlayer, Time.deltaTime);
vehicleFx.Update(objects, SendGame, Time.deltaTime);
worldSync.Update(IsWorldAuthority, SendGame, Time.unscaledDeltaTime);
try { objects.Update(localPlayer, Time.deltaTime); }
catch (System.Exception e) { ReportError("object sync", e); }
try { vehicleFx.Update(objects, SendGame, Time.deltaTime); }
catch (System.Exception e) { ReportError("vehicle lights/sound", e); }
try { worldSync.Update(IsWorldAuthority, SendGame, Time.unscaledDeltaTime); }
catch (System.Exception e) { ReportError("time/weather sync", e); }
// Geld erst beobachten, wenn das Spiel fertig geladen ist
if (objects.ScanComplete) moneySync.Begin();
moneySync.Update(SendGame);
try
{
if (objects.ScanComplete) moneySync.Begin();
moneySync.Update(SendGame);
}
catch (System.Exception e) { ReportError("money sync", e); }
// Türen, Tore, Hauben (z.B. Garagentor)
if (objects.ScanComplete) doorSync.Update(SendGame);
try { if (objects.ScanComplete) doorSync.Update(SendGame); }
catch (System.Exception e) { ReportError("door sync", e); }
// Gesamtzustand der Fahrzeuge (Tank, Öl, Schrauben, Verschleiß ...)
if (objects.ScanComplete) vehicleState.Update(objects, localId, SendGame);
// Gesamtzustand der Fahrzeuge (Tank, Öl, Verschleiß ...)
try { if (objects.ScanComplete) vehicleState.Update(objects, localId, SendGame); }
catch (System.Exception e) { ReportError("vehicle state sync", e); }
}
foreach (PlayerInfo p in players.Values)
{
if (p.Avatar == null) continue;
p.Avatar.Tick(Time.unscaledDeltaTime);
try
{
p.Avatar.Tick(Time.unscaledDeltaTime);
// Gehaltenes Item an die Hand der Figur setzen
Vector3 pos;
Quaternion rot;
if (p.Avatar.TryGetHeldPose(out pos, out rot))
objects.ApplyAvatarHold(p.Id, p.Avatar.HeldId, pos, rot);
// Gehaltenes Item an die Hand der Figur setzen
Vector3 pos;
Quaternion rot;
if (p.Avatar.TryGetHeldPose(out pos, out rot))
objects.ApplyAvatarHold(p.Id, p.Avatar.HeldId, pos, rot);
}
catch (System.Exception e) { ReportError("player figure", e); }
}
// Abgefangene Schraub-/Montage-Aktionen verschicken
FsmSync.Enabled = ready;
FsmSync.Tick();
foreach (FsmEventMsg msg in FsmSync.Outbox) SendGame(MsgType.FsmEvent, msg.Serialize());
try
{
FsmSync.Enabled = ready;
FsmSync.Tick();
foreach (FsmEventMsg msg in FsmSync.Outbox) SendGame(MsgType.FsmEvent, msg.Serialize());
}
catch (System.Exception e) { ReportError("part/bolt sync", e); }
FsmSync.Outbox.Clear();
}
readonly Dictionary<string, float> lastErrorReport = new Dictionary<string, float>();
/// <summary>Fehler eines Teilsystems melden (höchstens alle 30 s pro Teilsystem, damit das Log nicht vollläuft).</summary>
void ReportError(string what, System.Exception e)
{
float now = Time.realtimeSinceStartup, last;
if (lastErrorReport.TryGetValue(what, out last) && now - last < 30f) return;
lastErrorReport[what] = now;
ModConsole.Error("[MSCO] " + what + " failed: " + e);
overlays.Log("Error in " + what + ": " + e.Message);
}
void FixedUpdate()
{
if (IsPeerReady && MenuHelper.InGame) objects.FixedUpdate();
if (!IsPeerReady || !MenuHelper.InGame) return;
try { objects.FixedUpdate(); }
catch (System.Exception e) { ReportError("object movement", e); }
}
void LateUpdate()
{
InputLock.KeepCursorFree(); // das Spiel sperrt den Zeiger im selben Frame evtl. wieder
// Nach den Spiel-FSMs, damit Lichter/Motorgeräusch der Fahrzeuge anderer gewinnen
if (IsPeerReady && MenuHelper.InGame) vehicleFx.Apply(objects);
try { if (IsPeerReady && MenuHelper.InGame) vehicleFx.Apply(objects); }
catch (System.Exception e) { ReportError("vehicle lights/sound", e); }
// Beifahrer nach der Fahrzeugbewegung auf den Sitz setzen
if (localPlayer != null && MenuHelper.InGame) passenger.LateUpdate(localPlayer, playerCamera, objects);
try { if (localPlayer != null && MenuHelper.InGame) passenger.LateUpdate(localPlayer, playerCamera, objects); }
catch (System.Exception e) { ReportError("passenger", e); }
}
/// <summary>