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

@ -2,6 +2,7 @@ using AcDream.Core.Items;
using AcDream.Core.Net;
using AcDream.Core.Net.Messages;
using AcDream.Core.Physics;
using AcDream.Runtime.Physics;
namespace AcDream.Runtime.Entities;
@ -74,6 +75,21 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
uint firstLocalEntityId = RuntimeEntityDirectory.FirstLocalEntityId)
{
Entities = new RuntimeEntityDirectory(firstLocalEntityId);
Physics = new RuntimePhysicsState(Entities);
Objects = new ClientObjectTable();
var views = new RuntimeEntityObjectViews(Entities, Objects);
EntityView = views.Entities;
InventoryView = views.Inventory;
Events = new RuntimeEntityObjectEventStream(Entities, Objects);
}
internal RuntimeEntityObjectLifetime(
PhysicsDataCache physicsDataCache,
uint firstLocalEntityId = RuntimeEntityDirectory.FirstLocalEntityId)
{
ArgumentNullException.ThrowIfNull(physicsDataCache);
Entities = new RuntimeEntityDirectory(firstLocalEntityId);
Physics = new RuntimePhysicsState(Entities, physicsDataCache);
Objects = new ClientObjectTable();
var views = new RuntimeEntityObjectViews(Entities, Objects);
EntityView = views.Entities;
@ -82,6 +98,7 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
}
public RuntimeEntityDirectory Entities { get; }
public RuntimePhysicsState Physics { get; }
public ClientObjectTable Objects { get; }
public IRuntimeEntityView EntityView { get; }
public IRuntimeInventoryView InventoryView { get; }
@ -324,6 +341,10 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
Entities.RetainTeardown(canonical);
try
{
Physics.RemoveSpatialProjection(canonical);
Entities.SetRemoteMotion(canonical, null);
Entities.SetRemoteMotionBindingInProgress(canonical, false);
Entities.SetRequiresRemotePlacementRuntime(canonical, false);
Entities.SetPhysicsHost(canonical, null);
Entities.SetPhysicsBody(canonical, null);
Entities.SetPhysicsBodyAcquisitionInProgress(canonical, false);
@ -960,6 +981,7 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
{
_disposed = true;
Events.Dispose();
Physics.Dispose();
}
if (failures is not null)