test(phys): Task 6 regression — Deregister clears _entityShapes cache

Adds the regression pin for the _entityShapes cleanup that fca0a13
already implemented (Task 4 folded Task 6's Deregister change in for
the multi-part tests to pass). Verifies that a stray UpdatePosition
after Deregister is a no-op — entity is NOT resurrected via the
_entityShapes rebuild path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-05-24 15:22:30 +02:00
parent d5ffb0331b
commit 3e5dc8ce4c

View file

@ -193,4 +193,28 @@ public class ShadowObjectRegistryMultiPartTests
Assert.True(found0 && found1,
"Expected both parts at new world positions (50, 10, 50) and (51, 10, 50)");
}
[Fact]
public void Deregister_ClearsEntityShapesCache_NoStaleUpdatePositionRebuild()
{
// A6.P4 door fix (2026-05-24) regression: after Deregister, a stray
// UpdatePosition with the same entityId must NOT resurrect the entity
// via the _entityShapes path. The Deregister cleanup added in Task 4
// (which folded Task 6 into the multi-part registration commit) clears
// _entityShapes[entityId] alongside the cell-list cleanup.
var reg = new ShadowObjectRegistry();
const uint doorEntityId = 0x000F4244u;
reg.RegisterMultiPart(doorEntityId, new Vector3(132.6f, 17.1f, 94.08f),
Quaternion.Identity, DoorShapes(), 0x10008u,
EntityCollisionFlags.None, OffX, OffY, LbId);
reg.Deregister(doorEntityId);
// Stray UpdatePosition should be a no-op now (no entry to find AND
// no _entityShapes entry to rebuild from).
reg.UpdatePosition(doorEntityId, new Vector3(200f, 200f, 50f),
Quaternion.Identity, OffX, OffY, LbId);
Assert.Equal(0, reg.TotalRegistered);
}
}