refactor(runtime): close simulation ownership

Move remote-motion construction, CreateObject vector initialization, final simulation-component retirement, and the combined J5 ownership ledger into Runtime. Delete App compatibility views and moved-state reconstruction while preserving the existing graphical projection and retail update order.
This commit is contained in:
Erik 2026-07-26 15:53:31 +02:00
parent c30a3efeb0
commit cdee7a4b49
57 changed files with 1013 additions and 410 deletions

View file

@ -340,6 +340,49 @@ public sealed class RuntimePhysicsStateTests
Assert.Equal(0, first.Physics.Engine.LandblockCount);
}
[Fact]
public void TerminalDisposalClearsLandblocksShadowsAndWorksets()
{
var lifetime = new RuntimeEntityObjectLifetime();
RuntimeEntityRecord record =
lifetime.Entities.AddActive(Spawn(0x70000041u, 1));
lifetime.Physics.AcknowledgeSpatialProjection(
record,
spatial: true);
RuntimeCollisionAdmission admission =
lifetime.Physics.BeginCollisionAdmission(0x0101FFFFu);
lifetime.Physics.AdmitCollisionAssets(
admission,
CollisionAssets(0x0101FFFFu));
_ = lifetime.Physics.CompleteCollisionAdmission(admission);
lifetime.Physics.Engine.ShadowObjects.Register(
entityId: record.LocalEntityId!.Value,
gfxObjId: 0x01000001u,
worldPos: new Vector3(10f, 20f, 5f),
rotation: Quaternion.Identity,
radius: 0.5f,
worldOffsetX: 0f,
worldOffsetY: 0f,
landblockId: 0x0101FFFFu,
seedCellId: 0x01010001u,
isStatic: false);
Assert.False(lifetime.Physics.CaptureOwnership().IsConverged);
Assert.True(
lifetime.Physics.Engine.ShadowObjects
.RetainedRegistrationCount > 0);
lifetime.Dispose();
RuntimePhysicsOwnershipSnapshot retired =
lifetime.Physics.CaptureOwnership();
Assert.True(retired.IsConverged);
Assert.Equal(0, retired.LandblockCount);
Assert.Equal(0, retired.RetainedShadowRegistrationCount);
Assert.Equal(0, retired.SpatialRootCount);
}
[Fact]
public void RemoteBindingOwnsCanonicalBodyCellAndTypedCellPublication()
{
@ -368,6 +411,66 @@ public sealed class RuntimePhysicsStateTests
Assert.Equal(0, lifetime.Physics.SpatialRemoteCount);
}
[Fact]
public void BuiltInRemoteConstructionInstallsCreateVectorsOnlyOnce()
{
using var lifetime = new RuntimeEntityObjectLifetime();
RuntimeEntityRecord record = lifetime.Entities.AddActive(
Spawn(
0x70000042u,
1,
velocity: new Vector3(40f, 0f, 0f),
angularVelocity: new Vector3(0f, 0f, 2f)));
RemoteMotion remote =
lifetime.Physics.GetOrCreateRemoteMotion(record);
Assert.Equal(new Vector3(40f, 0f, 0f), remote.Body.Velocity);
Assert.Equal(new Vector3(0f, 0f, 2f), remote.Body.Omega);
remote.Body.set_velocity(new Vector3(8f, 0f, 0f));
remote.Body.Omega = new Vector3(0f, 0f, 3f);
Assert.Same(
remote,
lifetime.Physics.GetOrCreateRemoteMotion(record));
Assert.Equal(new Vector3(8f, 0f, 0f), remote.Body.Velocity);
Assert.Equal(new Vector3(0f, 0f, 3f), remote.Body.Omega);
}
[Fact]
public void BuiltInMovementActivationUsesExactRuntimeIncarnation()
{
using var lifetime = new RuntimeEntityObjectLifetime();
RuntimeEntityRecord ordinary =
lifetime.Entities.AddActive(Spawn(0x70000043u, 1));
RemoteMotion ordinaryRemote =
lifetime.Physics.GetOrCreateRemoteMotion(ordinary);
ordinary.ObjectClock.Deactivate();
ordinaryRemote.Body.TransientState &=
~TransientStateFlags.Active;
ordinaryRemote.Movement.ActivatePhysicsObject!();
Assert.True(ordinary.ObjectClock.IsActive);
Assert.True(ordinaryRemote.Body.IsActive);
RuntimeEntityRecord staticRecord =
lifetime.Entities.AddActive(Spawn(0x70000044u, 1));
lifetime.Entities.SetFinalPhysicsState(
staticRecord,
PhysicsStateFlags.Static);
RemoteMotion staticRemote =
lifetime.Physics.GetOrCreateRemoteMotion(staticRecord);
staticRecord.ObjectClock.Deactivate();
staticRemote.Body.TransientState &=
~TransientStateFlags.Active;
staticRemote.Movement.ActivatePhysicsObject!();
Assert.False(staticRecord.ObjectClock.IsActive);
Assert.False(staticRemote.Body.IsActive);
}
[Fact]
public void RemotePhysicsTickUsesCanonicalRuntimeAndPublishesPoseSnapshot()
{
@ -523,7 +626,11 @@ public sealed class RuntimePhysicsStateTests
0u);
}
private static WorldSession.EntitySpawn Spawn(uint guid, ushort instance)
private static WorldSession.EntitySpawn Spawn(
uint guid,
ushort instance,
Vector3? velocity = null,
Vector3? angularVelocity = null)
{
var position = new CreateObject.ServerPosition(
0x0101FFFFu,
@ -559,9 +666,9 @@ public sealed class RuntimePhysicsStateTests
Friction: null,
Elasticity: null,
Translucency: null,
Velocity: null,
Velocity: velocity,
Acceleration: null,
AngularVelocity: null,
AngularVelocity: angularVelocity,
DefaultScriptType: null,
DefaultScriptIntensity: null,
Timestamps: timestamps);