refactor(runtime): own per-session physics simulation

Move the sole PhysicsEngine, production cache, collision admissions, canonical bodies and hosts, remote components, ordinary/remote worksets, simulation, cell commits, and shadow synchronization under RuntimeEntityObjectLifetime. Keep App as the prepared-asset, animation-input, and render-projection adapter while preserving the named-retail update and collision order.

Add exact-incarnation, object-clock, callback-reentrancy, GUID-reuse, two-runtime isolation, source ownership, collision publication, and graphical projection coverage. Release build and the complete 8,588-test solution pass.

Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
Erik 2026-07-26 13:39:57 +02:00
parent 0dc3bfdeff
commit 7e6033d0ad
39 changed files with 3685 additions and 1722 deletions

View file

@ -19,13 +19,13 @@ public sealed class LiveEntityOrdinaryPhysicsUpdaterTests
[Fact]
public void CompleteRootFrame_CrossesTransitionAndCommitsCanonicalCell()
{
PhysicsEngine physics = BuildBoundaryEngine();
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0xA9B4FFFFu));
spatial.AddLandblock(EmptyLandblock(0xAAB4FFFFu));
var live = LiveEntityRuntimeFixture.Create(
spatial,
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
PopulateBoundaryEngine(live.Physics.Engine);
LiveEntityRecord record = live.RegisterAndMaterializeProjection(
Spawn(),
id => new WorldEntity
@ -40,7 +40,7 @@ public sealed class LiveEntityOrdinaryPhysicsUpdaterTests
});
WorldEntity entity = Assert.IsType<WorldEntity>(record.WorldEntity);
var remote = new AcDream.App.Physics.RemoteMotion
var remote = new AcDream.Runtime.Physics.RemoteMotion
{
CellId = SourceCell,
};
@ -56,7 +56,7 @@ public sealed class LiveEntityOrdinaryPhysicsUpdaterTests
ulong epoch = record.ObjectClockEpoch;
var updater = new LiveEntityOrdinaryPhysicsUpdater(
physics,
live.Physics,
(_, _) => (0.48f, 1.835f));
var rootFrame = new Frame
{
@ -106,7 +106,7 @@ public sealed class LiveEntityOrdinaryPhysicsUpdaterTests
ParentCellId = SourceCell,
});
WorldEntity entity = Assert.IsType<WorldEntity>(record.WorldEntity);
var remote = new AcDream.App.Physics.RemoteMotion
var remote = new AcDream.Runtime.Physics.RemoteMotion
{
CellId = SourceCell,
};
@ -123,7 +123,7 @@ public sealed class LiveEntityOrdinaryPhysicsUpdaterTests
new NullAnimationLoader());
Vector3 retainedEntityPosition = entity.Position;
var updater = new LiveEntityOrdinaryPhysicsUpdater(
new PhysicsEngine(),
live.Physics,
(_, _) => (0.48f, 1.835f));
Assert.False(updater.Tick(
@ -149,7 +149,7 @@ public sealed class LiveEntityOrdinaryPhysicsUpdaterTests
Assert.Equal(retainedEntityPosition, entity.Position);
}
private static PhysicsEngine BuildBoundaryEngine()
private static void PopulateBoundaryEngine(PhysicsEngine engine)
{
static TerrainSurface FlatTerrain()
{
@ -159,7 +159,6 @@ public sealed class LiveEntityOrdinaryPhysicsUpdaterTests
return new TerrainSurface(heights, table);
}
var engine = new PhysicsEngine { DataCache = new PhysicsDataCache() };
engine.AddLandblock(
0xA9B4FFFFu,
FlatTerrain(),
@ -174,7 +173,6 @@ public sealed class LiveEntityOrdinaryPhysicsUpdaterTests
Array.Empty<PortalPlane>(),
192f,
0f);
return engine;
}
private static LoadedLandblock EmptyLandblock(uint landblockId) =>