Passenger: player colliders off while riding (they pushed seats/parts out, physics crashed); last position: not overwritten by the save's start point, invalid positions ignored, saved when a player leaves

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-27 09:51:37 +02:00
co-authored by Claude Opus 5.5
parent 4d58b776cd
commit ba396146f2
3 changed files with 38 additions and 6 deletions
+23 -1
View File
@@ -115,6 +115,26 @@ try
alice.Send(MsgType.Chat, Wire.Build(w => w.Write(new string('x', 5000))));
var longChat = await bob.WaitFor(MsgType.Chat, 800);
Check(longChat == null, "Huge chat messages are not relayed");
Console.WriteLine("== Last position (spawn)");
var pos1 = await TestClient.Join("Walker", 0, null);
pos1.Send(MsgType.Player, PlayerPos(-15.6f, -0.3f, 7f)); // Startpunkt des Spielstands (Toilette) - vor Ready
pos1.Send(MsgType.Ready, Array.Empty<byte>());
Check(Snapshot.Parse(await pos1.WaitFor(MsgType.WorldSnapshot)).Spawn == null, "Position before joining is not stored (no spawn yet)");
pos1.Send(MsgType.Player, PlayerPos(-15.6f, -0.3f, 7f)); // direkt nach Ready: noch nicht übernehmen
await Task.Delay(8500);
pos1.Send(MsgType.Player, PlayerPos(250f, 3f, -120f)); // echte Position nach dem Umsetzen
await Task.Delay(300);
pos1.Send(MsgType.Player, PlayerPos(2.7e9f, 9.4e10f, -8.5e8f)); // weggeschleudert - darf nicht gespeichert werden
await Task.Delay(300);
pos1.Close();
await Task.Delay(500);
var pos2 = await TestClient.Join("Walker", 0, null);
pos2.Send(MsgType.Ready, Array.Empty<byte>());
var spawn = Snapshot.Parse(await pos2.WaitFor(MsgType.WorldSnapshot)).Spawn;
Check(spawn != null && Math.Abs(spawn[0] - 250f) < 0.01f && Math.Abs(spawn[2] + 120f) < 0.01f,
"Rejoining returns the last real position, not the save's start point or a flung-away one: " + (spawn == null ? "none" : string.Join(", ", spawn)));
pos2.Close();
}
catch (Exception e)
{
@@ -128,6 +148,7 @@ Thread.Sleep(300);
try { Directory.Delete(dir, true); } catch { }
return failed == 0 ? 0 : 1;
static byte[] PlayerPos(float x, float y, float z) => Wire.Build(w => { w.Write(x); w.Write(y); w.Write(z); w.Write(0f); });
static string ReadString(byte[] p) => new BinaryReader(new MemoryStream(p)).ReadString();
static string ReadStringAfterSender(byte[] p) { var r = new BinaryReader(new MemoryStream(p)); r.ReadInt32(); return r.ReadString(); }
@@ -147,6 +168,7 @@ sealed class Snapshot
public bool Ok;
public string Info;
public HashSet<int> ObjectIds = new();
public float[] Spawn;
public int Vars = -1;
public static Snapshot Parse(byte[] data)
@@ -156,7 +178,7 @@ sealed class Snapshot
try
{
var r = new BinaryReader(new MemoryStream(data));
if (r.ReadBoolean()) { r.ReadSingle(); r.ReadSingle(); r.ReadSingle(); }
if (r.ReadBoolean()) s.Spawn = new[] { r.ReadSingle(), r.ReadSingle(), r.ReadSingle() };
int objects = r.ReadInt32();
for (int i = 0; i < objects; i++) { s.ObjectIds.Add(r.ReadInt32()); for (int k = 0; k < 7; k++) r.ReadSingle(); }
int events = r.ReadInt32();