Join: replay part actions first, then rescan and place objects (detached parts no longer stuck in the car); rescan right after remote disassembly; lift out bodies that keep getting flung
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+30
-3
@@ -41,6 +41,7 @@ namespace MSCO
|
||||
bool dedicated; // verbunden mit einem dedizierten Server
|
||||
bool connectingToServer; // Verbindungsaufbau zu einem dedizierten Server läuft
|
||||
bool readySent; // Server: Weltzustand schon angefordert
|
||||
bool rescanSoon; // nach einer Abbau-Aktion neue lose Teile sofort erfassen
|
||||
byte[] pendingSnapshot; // Server: Weltzustand, wartet auf Objekt-Suchlauf
|
||||
const int SnapshotEventsPerFrame = 20;
|
||||
readonly ServerBrowser browser = new ServerBrowser();
|
||||
@@ -1041,8 +1042,14 @@ namespace MSCO
|
||||
objects.Handle(from, type, r);
|
||||
break;
|
||||
case MsgType.FsmEvent:
|
||||
FsmSync.Apply(FsmEventMsg.Deserialize(r));
|
||||
{
|
||||
FsmEventMsg msg = FsmEventMsg.Deserialize(r);
|
||||
FsmSync.Apply(msg);
|
||||
// Ein Teil wurde abgebaut: gleich als loses Objekt erfassen, damit es der Hand des Mitspielers
|
||||
// folgt, statt Sekunden lang im Auto zu stecken (die Physik würde es samt Auto wegschleudern)
|
||||
if (msg.EventName == "DISASSEMBLE" || msg.EventName == "REMOVE" || msg.EventName == "UNINSTALL") rescanSoon = true;
|
||||
break;
|
||||
}
|
||||
case MsgType.WorldTime:
|
||||
worldSync.Apply(r);
|
||||
break;
|
||||
@@ -1218,6 +1225,11 @@ namespace MSCO
|
||||
}
|
||||
|
||||
if (teleportToHost) TryTeleportToHost();
|
||||
if (rescanSoon && objects.ScanComplete)
|
||||
{
|
||||
rescanSoon = false;
|
||||
objects.ScanNow();
|
||||
}
|
||||
|
||||
// Dedizierter Server: nach dem ersten Objekt-Suchlauf den Weltzustand anfordern und anwenden
|
||||
if (dedicated && handshakeDone && !readySent && objects.ScanComplete)
|
||||
@@ -1365,14 +1377,16 @@ namespace MSCO
|
||||
if (localPlayer != null) localPlayer.position = spawn + Vector3.up * 0.2f;
|
||||
}
|
||||
|
||||
// Positionen erst merken: sie werden NACH den Montage-Aktionen gesetzt. Sonst steckt ein Teil, das eine
|
||||
// nachgespielte Aktion vom Auto löst, noch im Auto - die Physik schleudert es dann samt Auto weg.
|
||||
int objectCount = r.ReadInt32();
|
||||
int applied = 0;
|
||||
var poses = new List<KeyValuePair<int, Pose>>(objectCount);
|
||||
for (int i = 0; i < objectCount; i++)
|
||||
{
|
||||
int id = r.ReadInt32();
|
||||
var pos = new Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle());
|
||||
var rot = new Quaternion(r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle());
|
||||
if (objects.ApplySnapshotPose(id, pos, rot)) applied++;
|
||||
poses.Add(new KeyValuePair<int, Pose>(id, new Pose { Position = pos, Rotation = rot }));
|
||||
}
|
||||
|
||||
int eventCount = r.ReadInt32();
|
||||
@@ -1383,6 +1397,13 @@ namespace MSCO
|
||||
if ((i + 1) % SnapshotEventsPerFrame == 0) yield return null; // nicht alles in einem Frame
|
||||
}
|
||||
|
||||
// Abgebaute Teile sind jetzt eigene Objekte: erfassen, dann alle Positionen setzen
|
||||
yield return null;
|
||||
objects.ScanNow();
|
||||
int applied = 0;
|
||||
foreach (KeyValuePair<int, Pose> p in poses)
|
||||
if (objects.ApplySnapshotPose(p.Key, p.Value.Position, p.Value.Rotation)) applied++;
|
||||
|
||||
// Geld: Summe aller Änderungen seit dem Spielstand des Servers
|
||||
if (r.BaseStream.Length - r.BaseStream.Position >= 4) moneySync.Apply(r.ReadSingle());
|
||||
|
||||
@@ -1400,6 +1421,12 @@ namespace MSCO
|
||||
SetStatus("Connected");
|
||||
}
|
||||
|
||||
struct Pose
|
||||
{
|
||||
public Vector3 Position;
|
||||
public Quaternion Rotation;
|
||||
}
|
||||
|
||||
/// <summary>Sobald die erste Position des Hosts da ist: seitlich neben ihn stellen.</summary>
|
||||
void TryTeleportToHost()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user