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

@ -144,12 +144,7 @@ public sealed class GameWindowLiveEntityCompositionTests
typeof(LiveEntityAnimationRuntimeView<LiveEntityAnimationState>)
.GetFields(BindingFlags.Instance | BindingFlags.NonPublic),
field => field.Name == "_runtime");
FieldInfo remoteRuntime = Assert.Single(
typeof(LiveEntityRemoteMotionRuntimeView<RemoteMotion>)
.GetFields(BindingFlags.Instance | BindingFlags.NonPublic),
field => field.Name == "_runtime");
Assert.Equal(typeof(ILiveEntityRuntimeSource), animationRuntime.FieldType);
Assert.Equal(typeof(ILiveEntityRuntimeSource), remoteRuntime.FieldType);
FieldInfo[] projectileFields = typeof(ProjectileController).GetFields(
BindingFlags.Instance | BindingFlags.NonPublic);
@ -192,7 +187,7 @@ public sealed class GameWindowLiveEntityCompositionTests
source,
StringComparison.Ordinal);
Assert.DoesNotContain(
"new LiveEntityRemoteMotionRuntimeView<RemoteMotion>(() =>",
"LiveEntityRemoteMotionRuntimeView",
source,
StringComparison.Ordinal);
Assert.Contains("new DatProjectileSetupResolver", livePresentation);

View file

@ -371,7 +371,11 @@ public sealed class LiveEntityHydrationControllerTests
LiveEntityRecord record = fixture.Record;
WorldEntity entity = record.WorldEntity!;
var body = new PhysicsBody();
record.PhysicsBody = body;
Assert.Same(
body,
fixture.Runtime.GetOrCreatePhysicsBody(
record.ServerGuid,
_ => body));
fixture.Relationships.OnUnparentAction = _ =>
fixture.Runtime.WithdrawLiveEntityProjection(record)
? ChildUnparentDisposition.Completed

View file

@ -874,7 +874,7 @@ public sealed class LiveEntityLifecycleStressTests
_animations.TryGetValue(id, out Animation? animation) ? animation : null;
}
private sealed class TestRemoteMotion : ILiveEntityRemotePlacementRuntime
private sealed class TestRemoteMotion : IRuntimeRemotePlacement
{
private uint _cellId;
private Func<uint>? _readCell;

View file

@ -710,8 +710,8 @@ public sealed class LiveEntityPhysicsHostOwnershipTests
interruptCurrentMovement);
private sealed class HostConsumerMotion :
ILiveEntityRemoteMotionRuntime,
ILiveEntityPhysicsHostConsumer
IRuntimeRemoteMotion,
IRuntimePhysicsHostConsumer
{
private Func<IPhysicsObjHost?>? _read;
public PhysicsBody Body { get; } = new();
@ -725,8 +725,8 @@ public sealed class LiveEntityPhysicsHostOwnershipTests
}
private sealed class ThrowingCellConsumerMotion :
ILiveEntityRemoteMotionRuntime,
ILiveEntityCanonicalRuntimeConsumer
IRuntimeRemoteMotion,
IRuntimeCanonicalPhysicsConsumer
{
private bool _failOnce = true;
public PhysicsBody Body { get; } = new();
@ -748,14 +748,14 @@ public sealed class LiveEntityPhysicsHostOwnershipTests
private sealed class AlternatingBodyMotion(
PhysicsBody first,
PhysicsBody second) : ILiveEntityRemoteMotionRuntime
PhysicsBody second) : IRuntimeRemoteMotion
{
private int _reads;
public PhysicsBody Body => _reads++ == 0 ? first : second;
}
private sealed class SequenceBodyMotion(params PhysicsBody[] bodies) :
ILiveEntityRemoteMotionRuntime
IRuntimeRemoteMotion
{
public int ReadCount { get; private set; }
@ -771,8 +771,8 @@ public sealed class LiveEntityPhysicsHostOwnershipTests
}
private sealed class CallbackCanonicalMotion(Action callback) :
ILiveEntityRemoteMotionRuntime,
ILiveEntityCanonicalRuntimeConsumer
IRuntimeRemoteMotion,
IRuntimeCanonicalPhysicsConsumer
{
public PhysicsBody Body { get; } = new();

View file

@ -48,7 +48,7 @@ public sealed class LiveEntityRuntimeTests
private sealed class EffectProfile : ILiveEntityEffectProfile { }
private sealed class RemoteMotionRuntime : ILiveEntityRemoteMotionRuntime
private sealed class RemoteMotionRuntime : IRuntimeRemoteMotion
{
public PhysicsBody Body { get; } = new();
}
@ -1156,43 +1156,6 @@ public sealed class LiveEntityRuntimeTests
Assert.False(remote.Body.TransientState.HasFlag(TransientStateFlags.Active));
}
[Fact]
public void MovementActivation_ReactivatesExactIncarnation_ButStaticIsNoOp()
{
const uint ordinaryGuid = 0x70000050u;
const uint staticGuid = 0x70000051u;
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
LiveEntityRecord ordinary = RegisterProjection(
runtime,
Spawn(ordinaryGuid, 1, 1, 0x01010001u));
var ordinaryRemote = new RemoteMotionRuntime();
runtime.SetRemoteMotionRuntime(ordinaryGuid, ordinaryRemote);
ordinary.ObjectClock.Deactivate();
ordinaryRemote.Body.TransientState &= ~TransientStateFlags.Active;
Assert.True(runtime.TryActivateOrdinaryObject(ordinaryGuid, ordinaryRemote));
Assert.True(ordinary.ObjectClock.IsActive);
Assert.True(ordinaryRemote.Body.TransientState.HasFlag(TransientStateFlags.Active));
LiveEntityRecord staticRecord = RegisterProjection(
runtime,
Spawn(
staticGuid,
1,
1,
0x01010001u,
PhysicsStateFlags.Static));
var staticRemote = new RemoteMotionRuntime();
runtime.SetRemoteMotionRuntime(staticGuid, staticRemote);
Assert.False(runtime.TryActivateOrdinaryObject(staticGuid, staticRemote));
Assert.False(staticRecord.ObjectClock.IsActive);
Assert.False(staticRemote.Body.TransientState.HasFlag(TransientStateFlags.Active));
}
[Fact]
public void AuthoritativeVector_WakesOrdinaryClockButPreservesStaticActivity()
{

View file

@ -244,6 +244,10 @@ public sealed class RuntimeEntityOwnershipTests
Assert.Contains(
viewFields,
field => field.FieldType == typeof(IRuntimeInventoryView));
Assert.DoesNotContain(
viewFields,
field => field.FieldType == typeof(LiveEntityRuntime)
|| field.FieldType == typeof(ClientObjectTable));
Assert.DoesNotContain(
typeof(CurrentGameRuntimeViewAdapter).GetNestedTypes(
BindingFlags.NonPublic),
@ -271,6 +275,21 @@ public sealed class RuntimeEntityOwnershipTests
Assert.DoesNotContain("_entityObjects.PublishEntity", liveSource);
Assert.DoesNotContain("_directory.TryApply", liveSource);
Assert.DoesNotContain("_directory.RemoveActive", liveSource);
string viewSource = File.ReadAllText(Path.Combine(
root,
"src",
"AcDream.App",
"Runtime",
"CurrentGameRuntimeViewAdapter.cs"));
Assert.Contains(
"_entityView.MaterializedCount",
viewSource,
StringComparison.Ordinal);
Assert.DoesNotContain(
"_entities.MaterializedCount",
viewSource,
StringComparison.Ordinal);
}
private static bool IsPresentationType(Type type)