fix(physics): #92 — seed resolver with server cell id at player-mode entry
EnterPlayerModeNow computed the initial cellId from landblock prefix + hardcoded low byte 0x0001 (outdoor sentinel) and passed only the low 16 bits to PhysicsEngine.Resolve. When the server places the player INSIDE a building (spawn cell id e.g. 0xA9B4015A indoor), the sentinel forced the outdoor seed branch — for the first several ticks CheckBuildingTransit hadn't yet picked up the interior cell (it depends on the sphere overlapping the destination cell's BSP), the player was classified outdoor, indoor BSP queries didn't run, and exterior walls were passable until enough inward motion finally promoted them. User-visible symptom: "logged in inside the inn, ran out through the exterior wall; ran back in and the walls now block." Fix: use spawn.Position.LandblockId (the server's authoritative full cell id with landblock prefix) when available; fall back to the old sentinel only if the spawn record is missing (defensive — shouldn't fire in live play since OnLiveEntitySpawnedLocked writes _lastSpawnByGuid before EnterPlayerModeNow can possibly run). 1147 + 8 baseline maintained. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7ac8f544a7
commit
23ab17362a
1 changed files with 31 additions and 4 deletions
|
|
@ -10106,11 +10106,38 @@ public sealed class GameWindow : IDisposable
|
|||
_playerController.StepDownHeight = 0.4f;
|
||||
Console.WriteLine($"physics: player step heights — defaulting to 0.4 m (no setup dat)");
|
||||
}
|
||||
int plbX = _liveCenterX + (int)MathF.Floor(playerEntity.Position.X / 192f);
|
||||
int plbY = _liveCenterY + (int)MathF.Floor(playerEntity.Position.Y / 192f);
|
||||
uint pinitCellId = ((uint)plbX << 24) | ((uint)plbY << 16) | 0x0001u;
|
||||
// Issue #92 (2026-05-20): seed the resolver with the SERVER's
|
||||
// authoritative cell id from the spawn message instead of a
|
||||
// hardcoded outdoor sentinel (`landblockPrefix | 0x0001`). When
|
||||
// the player logs in INSIDE a building (server reports an indoor
|
||||
// cell like `0xA9B4015A`), the old sentinel forced the resolver
|
||||
// into the outdoor seed branch — for the first several ticks
|
||||
// CheckBuildingTransit hadn't yet picked up the interior cell,
|
||||
// so the player was classified outdoor, indoor BSP queries
|
||||
// didn't run, and exterior walls were passable until the player
|
||||
// moved far enough INWARD that the sphere overlap eventually
|
||||
// promoted them. Visible symptom: "logged in inside the inn,
|
||||
// ran out through the exterior wall."
|
||||
//
|
||||
// Fall back to the old sentinel when no spawn record is cached
|
||||
// (defensive — should never fire in live play because the
|
||||
// _lastSpawnByGuid entry was written by OnLiveEntitySpawnedLocked
|
||||
// before EnterPlayerModeNow could possibly be reached).
|
||||
uint pinitCellId;
|
||||
if (_lastSpawnByGuid.TryGetValue(_playerServerGuid, out var playerSpawn)
|
||||
&& playerSpawn.Position is { } spawnPos
|
||||
&& spawnPos.LandblockId != 0)
|
||||
{
|
||||
pinitCellId = spawnPos.LandblockId;
|
||||
}
|
||||
else
|
||||
{
|
||||
int plbX = _liveCenterX + (int)MathF.Floor(playerEntity.Position.X / 192f);
|
||||
int plbY = _liveCenterY + (int)MathF.Floor(playerEntity.Position.Y / 192f);
|
||||
pinitCellId = ((uint)plbX << 24) | ((uint)plbY << 16) | 0x0001u;
|
||||
}
|
||||
var initResult = _physicsEngine.Resolve(
|
||||
playerEntity.Position, pinitCellId & 0xFFFFu,
|
||||
playerEntity.Position, pinitCellId,
|
||||
System.Numerics.Vector3.Zero, 100f);
|
||||
_playerController.SetPosition(initResult.Position, initResult.CellId);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue