Satsuma: sync part state from CARPARTS/Database, paint, late-installed parts, more controls

- VehicleStateSync also tracks the CARPARTS and Database roots (wear, damaged
  parts, tire wear, oilpan oil, battery charge, carb/ignition settings,
  suspension, odometer); the Satsuma's driver is authoritative for them
- Paint colors (FsmColor) as four float channels (compatible with old servers)
  and applied to the part's material
- FSMs are re-examined when a part is installed/removed (path changes);
  before, anything not on the car at the first scan was never synced
- ControlSync: handbrake, sun visors, seat recline, seat belt, CD player,
  interior light; pending states for controls not found yet
- Late joiners: job/shop values and switch states from the server snapshot;
  P2P host resends all switch states every 15 s

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-02 14:10:42 +02:00
co-authored by Claude Opus 5.5
parent 0b2834282d
commit 3b83644ce9
6 changed files with 221 additions and 34 deletions
+14 -1
View File
@@ -65,6 +65,7 @@ namespace MSCO
readonly TrafficSync traffic = new TrafficSync();
readonly HingeSync hinges = new HingeSync();
readonly ControlSync controls = new ControlSync();
float nextControlResync;
readonly Toasts toasts = new Toasts();
float nextNeedsSend;
const float NeedsInterval = 10f;
@@ -1940,7 +1941,16 @@ namespace MSCO
PartEnd("crash damage sync");
// Zündung, Motor, Licht, Choke ... der Fahrzeuge
PartStart();
try { if (objects.ScanComplete && localPlayer != null) controls.Update(objects, localId, localPlayer.position, SendGame); }
try
{
if (objects.ScanComplete && localPlayer != null) controls.Update(objects, localId, localPlayer.position, SendGame);
// P2P: der Host gleicht regelmäßig alle Schalter ab (später Beigetretene, verlorene Nachrichten)
if (objects.ScanComplete && IsHost && !dedicated && Time.time >= nextControlResync)
{
nextControlResync = Time.time + 15f;
controls.ResendAll(objects, localId, SendGame);
}
}
catch (System.Exception e) { ReportError("vehicle controls sync", e); }
PartEnd("vehicle controls sync");
// Türen, Motorhaube, Kofferraum der Fahrzeuge
@@ -2188,6 +2198,9 @@ namespace MSCO
int needs = PlayerNeeds.Apply(r);
if (needs > 0) MscoLog.Info("[MSCO] Your own hunger/thirst/... restored (" + needs + " values)");
}
// Jobs/Laden und Schalter (Licht, Zündung, Motor ...) - Server ab 2.9.2
if (r.BaseStream.Length - r.BaseStream.Position >= 4) worldVars.Handle(r);
if (r.BaseStream.Length - r.BaseStream.Position >= 4) controls.Handle(r, objects, localId);
// Abgebaute Teile und gespawnte Items sind jetzt eigene Objekte: erfassen, dann alle Positionen setzen
yield return null;