fix(physics): hold retail cell across inner retries

This commit is contained in:
Erik 2026-07-31 12:40:50 +02:00
parent 67d1e9b331
commit 4ca7230b36
4 changed files with 168 additions and 83 deletions

View file

@ -292,7 +292,7 @@ public class IndoorContactPlaneRetentionTests
t.SpherePath.SetCheckPos(newPos, IndoorCellId);
// Simulate FindEnvCollisions as the physics loop calls it.
t.FindEnvCollisions(engine);
t.FindEnvCollisions(engine, IndoorCellId);
}
// ── Assert ────────────────────────────────────────────────────────────

View file

@ -190,39 +190,68 @@ public sealed class TransitionInsertIntoCellRetryTests
}
[Fact]
public void NoDataCache_CrossLandblockRepick_UsesRefreshedPrimaryCell()
public void NestedRetry_FixesPrimaryCellUntilNextOuterAttempt()
{
PhysicsEngine engine = BuildCrossLandblockEngine();
PhysicsEngine engine = BuildEngine(preparedFlat: false);
var cells = new List<uint>();
var phases = new List<TransitionCellCollisionPhase>();
int environmentCalls = 0;
const uint nextOuterCell = 0xA9B40002u;
engine.TransitionCellCollisionTestHook =
(_, phase, cellId, actual) =>
(transition, phase, cellId, actual) =>
{
phases.Add(phase);
cells.Add(cellId);
if (phase == TransitionCellCollisionPhase.Environment)
{
environmentCalls++;
if (environmentCalls == 1)
{
transition.SpherePath.SetCheckPos(
transition.SpherePath.CheckPos,
nextOuterCell);
}
if (environmentCalls <= 3)
return TransitionState.Adjusted;
}
return actual;
};
Vector3 current = new(191.99f, 10f, 5f);
Vector3 target = new(192.01f, 10f, 5f);
Vector3 current = new(10f, 10f, 5f);
Vector3 target = current + new Vector3(0.05f, 0f, 0f);
ResolveResult result = ResolveAirborne(
engine,
current,
target,
0xA9B40039u);
Cell);
Assert.True(result.Ok);
Assert.Equal(target, result.Position);
Assert.Equal(0xAAB40001u, result.CellId);
Assert.Equal(
new[]
{
TransitionCellCollisionPhase.Environment,
TransitionCellCollisionPhase.Environment,
TransitionCellCollisionPhase.Environment,
TransitionCellCollisionPhase.Environment,
TransitionCellCollisionPhase.Building,
TransitionCellCollisionPhase.Objects,
},
phases);
Assert.All(cells, cellId => Assert.Equal(0xAAB40001u, cellId));
Assert.Equal(
new[]
{
Cell,
Cell,
Cell,
nextOuterCell,
nextOuterCell,
nextOuterCell,
},
cells);
}
private static ResolveResult ResolveAirborne(
@ -309,26 +338,4 @@ public sealed class TransitionInsertIntoCellRetryTests
return engine;
}
private static PhysicsEngine BuildCrossLandblockEngine()
{
var engine = new PhysicsEngine { DataCache = null };
var heights = new byte[81];
var heightTable = new float[256];
Array.Fill(heightTable, -1000f);
engine.AddLandblock(
0xA9B4FFFFu,
new TerrainSurface(heights, heightTable),
Array.Empty<CellSurface>(),
Array.Empty<PortalPlane>(),
0f,
0f);
engine.AddLandblock(
0xAAB4FFFFu,
new TerrainSurface(heights, heightTable),
Array.Empty<CellSurface>(),
Array.Empty<PortalPlane>(),
192f,
0f);
return engine;
}
}