refactor(runtime): own canonical entity and object lifetime

Introduce one presentation-free RuntimeEntityObjectLifetime for the exact entity directory and ClientObjectTable. Make GameWindow, graphical projections, retained UI, interaction, session routing, create/delete integration, and reset borrow that owner while preserving synchronous retail ordering, dormant retention, and retry semantics.

Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-26 05:54:46 +02:00
parent d9bf4c4960
commit 5ef8b5371d
40 changed files with 712 additions and 170 deletions

View file

@ -97,7 +97,7 @@ public sealed class CombatAttackTargetSourceTests
0x0101_FFFFu,
new LandBlock(),
Array.Empty<WorldEntity>()));
Runtime = new LiveEntityRuntime(spatial, new Resources());
Runtime = LiveEntityRuntimeFixture.Create(spatial, new Resources());
var identity = new LocalPlayerIdentityState { ServerGuid = Player };
Targets = new CombatAttackTargetSource(
Selection,

View file

@ -150,7 +150,7 @@ public sealed class LivePresentationCompositionTests
Assert.Contains("d.PortalTunnelFallback.AcquirePrepared(", phase);
}
private static LiveEntityRuntime Runtime() => new(
private static LiveEntityRuntime Runtime() => LiveEntityRuntimeFixture.Create(
new GpuWorldState(),
new DelegateLiveEntityResourceLifecycle(static _ => { }, static _ => { }));

View file

@ -50,7 +50,7 @@ public sealed class WorldSelectionQueryTests
0x0101_FFFFu,
new LandBlock(),
Array.Empty<WorldEntity>()));
Runtime = new LiveEntityRuntime(spatial, new Resources());
Runtime = LiveEntityRuntimeFixture.Create(spatial, new Resources());
Scene = new RetailSelectionScene(new GeometrySource(Mesh()));
Query = new WorldSelectionQuery(
Runtime,

View file

@ -0,0 +1,50 @@
using AcDream.App.Streaming;
using AcDream.App.World;
using AcDream.Runtime.Entities;
namespace AcDream.App.Tests;
/// <summary>
/// Explicit isolated lifetime-group seam for App projection tests. Production
/// composition supplies its session-owned group from GameWindow; focused tests
/// use a fresh group per runtime so identity never leaks between fixtures.
/// </summary>
internal static class LiveEntityRuntimeFixture
{
public static LiveEntityRuntime Create(
GpuWorldState spatial,
ILiveEntityResourceLifecycle resources,
uint firstLocalEntityId = RuntimeEntityDirectory.FirstLocalEntityId)
{
var lifetime = new RuntimeEntityObjectLifetime(firstLocalEntityId);
return new LiveEntityRuntime(spatial, resources, lifetime);
}
public static LiveEntityRuntime Create(
GpuWorldState spatial,
ILiveEntityResourceLifecycle resources,
Action<LiveEntityRecord> tearDownRuntimeComponents,
uint firstLocalEntityId = RuntimeEntityDirectory.FirstLocalEntityId)
{
var lifetime = new RuntimeEntityObjectLifetime(firstLocalEntityId);
return new LiveEntityRuntime(
spatial,
resources,
tearDownRuntimeComponents,
lifetime);
}
public static LiveEntityRuntime Create(
GpuWorldState spatial,
ILiveEntityResourceLifecycle resources,
ILiveEntityRuntimeComponentLifecycle runtimeComponentLifecycle,
uint firstLocalEntityId = RuntimeEntityDirectory.FirstLocalEntityId)
{
var lifetime = new RuntimeEntityObjectLifetime(firstLocalEntityId);
return new LiveEntityRuntime(
spatial,
resources,
runtimeComponentLifecycle,
lifetime);
}
}

View file

@ -210,7 +210,7 @@ public sealed class LiveSessionResetPlanTests
landblock,
new LandBlock(),
new List<WorldEntity> { staticEntity }));
var live = new LiveEntityRuntime(spatial, new FailingOnceResources());
var live = LiveEntityRuntimeFixture.Create(spatial, new FailingOnceResources());
WorldSession.EntitySpawn spawn = Spawn(playerA, 1, 1, 0x01010001u);
live.RegisterLiveEntity(spawn);
live.MaterializeLiveEntity(

View file

@ -315,7 +315,7 @@ public sealed class LiveEntityInboundAuthorityGateTests
accepted.VelocityAuthorityVersion));
}
private static LiveEntityRuntime Runtime() => new(
private static LiveEntityRuntime Runtime() => LiveEntityRuntimeFixture.Create(
new GpuWorldState(),
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));

View file

@ -23,7 +23,7 @@ public sealed class LiveEntityOrdinaryPhysicsUpdaterTests
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0xA9B4FFFFu));
spatial.AddLandblock(EmptyLandblock(0xAAB4FFFFu));
var live = new LiveEntityRuntime(
var live = LiveEntityRuntimeFixture.Create(
spatial,
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
LiveEntityRecord record = live.RegisterAndMaterializeProjection(
@ -90,7 +90,7 @@ public sealed class LiveEntityOrdinaryPhysicsUpdaterTests
{
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0xA9B4FFFFu));
var live = new LiveEntityRuntime(
var live = LiveEntityRuntimeFixture.Create(
spatial,
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
LiveEntityRecord record = live.RegisterAndMaterializeProjection(

View file

@ -1457,7 +1457,7 @@ public sealed class ProjectileControllerTests
{
if (loadInitialLandblock)
Spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
Live = new LiveEntityRuntime(Spatial, Resources);
Live = LiveEntityRuntimeFixture.Create(Spatial, Resources);
Engine = physicsEngine ?? new PhysicsEngine();
Origin.Recenter(1, 1);
Controller = new ProjectileController(

View file

@ -692,7 +692,7 @@ public sealed class RemotePhysicsUpdaterTests
0x0101FFFFu,
new LandBlock(),
Array.Empty<WorldEntity>()));
var live = new LiveEntityRuntime(
var live = LiveEntityRuntimeFixture.Create(
spatial,
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
BindHiddenRemote(live, firstGuid);
@ -840,7 +840,7 @@ public sealed class RemotePhysicsUpdaterTests
0xA9B4FFFFu,
new LandBlock(),
Array.Empty<WorldEntity>()));
Live = new LiveEntityRuntime(
Live = LiveEntityRuntimeFixture.Create(
Spatial,
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }),
record =>

View file

@ -87,7 +87,7 @@ public sealed class RemoteTeleportControllerTests
const uint destinationCell = 0xAAB40001u;
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0xA9B4FFFFu));
var live = new LiveEntityRuntime(spatial, new Resources());
var live = LiveEntityRuntimeFixture.Create(spatial, new Resources());
live.RegisterLiveEntity(Spawn(guid, sourceCell));
WorldEntity entity = live.MaterializeLiveEntity(
guid,
@ -228,7 +228,7 @@ public sealed class RemoteTeleportControllerTests
const uint sourceCell = 0xA9B40039u;
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0xA9B4FFFFu));
var live = new LiveEntityRuntime(spatial, new Resources());
var live = LiveEntityRuntimeFixture.Create(spatial, new Resources());
live.RegisterLiveEntity(Spawn(guid, sourceCell));
WorldEntity entity = live.MaterializeLiveEntity(
guid,
@ -319,7 +319,7 @@ public sealed class RemoteTeleportControllerTests
Vector3 sourcePosition = new(191f, 10f, 50f);
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0xA9B4FFFFu));
var live = new LiveEntityRuntime(spatial, new Resources());
var live = LiveEntityRuntimeFixture.Create(spatial, new Resources());
live.RegisterLiveEntity(Spawn(guid, sourceCell));
WorldEntity entity = live.MaterializeLiveEntity(
guid,
@ -1101,7 +1101,7 @@ public sealed class RemoteTeleportControllerTests
]));
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0xA9B4FFFFu));
var live = new LiveEntityRuntime(spatial, resources);
var live = LiveEntityRuntimeFixture.Create(spatial, resources);
live.RegisterLiveEntity(Spawn(guid, sourceCell));
WorldEntity entity = live.MaterializeLiveEntity(
guid,
@ -1179,7 +1179,7 @@ public sealed class RemoteTeleportControllerTests
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0xA9B4FFFFu));
spatial.AddLandblock(EmptyLandblock(0xAAB4FFFFu));
var live = new LiveEntityRuntime(spatial, new Resources());
var live = LiveEntityRuntimeFixture.Create(spatial, new Resources());
live.RegisterLiveEntity(Spawn(guid, sourceCell));
WorldEntity entity = live.MaterializeLiveEntity(
guid,
@ -1383,7 +1383,7 @@ public sealed class RemoteTeleportControllerTests
internal RollbackFixture(bool celllessSource = false)
{
Spatial.AddLandblock(EmptyLandblock(SourceLandblock));
Live = new LiveEntityRuntime(Spatial, new Resources());
Live = LiveEntityRuntimeFixture.Create(Spatial, new Resources());
Live.RegisterLiveEntity(Spawn(Guid, SourceCell));
Entity = Live.MaterializeLiveEntity(
Guid,

View file

@ -1161,7 +1161,7 @@ public sealed class EquippedChildProjectionWithdrawalTests
(Cell & 0xFFFF0000u) | 0xFFFFu,
new LandBlock(),
Array.Empty<WorldEntity>()));
Live = new LiveEntityRuntime(
Live = LiveEntityRuntimeFixture.Create(
Spatial,
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }),
_lifecycle);

View file

@ -17,7 +17,7 @@ public sealed class LiveAppearanceAnimationTests
public void Capture_UsesCanonicalRecordEntityAndAnimationOwner()
{
const uint guid = 0x70000002u;
var runtime = new AcDream.App.World.LiveEntityRuntime(
var runtime = LiveEntityRuntimeFixture.Create(
new AcDream.App.Streaming.GpuWorldState(),
new AcDream.App.World.DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
var spawn = new AcDream.Core.Net.WorldSession.EntitySpawn(
@ -118,7 +118,7 @@ public sealed class LiveAppearanceAnimationTests
0x0101FFFFu,
new LandBlock(),
Array.Empty<WorldEntity>()));
var runtime = new LiveEntityRuntime(
var runtime = LiveEntityRuntimeFixture.Create(
spatial,
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
WorldSession.EntitySpawn first = Spawn(guid, cell, instance: 1);

View file

@ -440,7 +440,7 @@ public sealed class LiveEntityAnimationPresenterTests
0x0101FFFFu,
new LandBlock(),
Array.Empty<WorldEntity>()));
var live = new LiveEntityRuntime(
var live = LiveEntityRuntimeFixture.Create(
spatial,
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
return Add(live, guid, partCount, scale, withSequencer);

View file

@ -679,7 +679,7 @@ public sealed class LiveEntityAnimationSchedulerTests
0x0101FFFFu,
new LandBlock(),
Array.Empty<WorldEntity>()));
var live = new LiveEntityRuntime(
var live = LiveEntityRuntimeFixture.Create(
spatial,
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
LiveEntityRecord record = live.RegisterAndMaterializeProjection(
@ -800,7 +800,7 @@ public sealed class LiveEntityAnimationSchedulerTests
0x0101FFFFu,
new LandBlock(),
Array.Empty<WorldEntity>()));
var live = new LiveEntityRuntime(
var live = LiveEntityRuntimeFixture.Create(
spatial,
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
LiveEntityRecord record = live.RegisterAndMaterializeProjection(

View file

@ -286,7 +286,7 @@ public sealed class LiveEntityCreateSupersessionRecoveryTests
0x0101FFFFu,
new DatReaderWriter.DBObjs.LandBlock(),
Array.Empty<WorldEntity>()));
return new LiveEntityRuntime(
return LiveEntityRuntimeFixture.Create(
spatial,
resources,
new DelegateLiveEntityRuntimeComponentLifecycle(_ => { }));

View file

@ -357,7 +357,7 @@ public sealed class LiveRenderProjectionJournalTests
var resources = new DelegateLiveEntityResourceLifecycle(
static _ => { },
entity => sink?.OnResourceUnregister(entity));
var runtime = new LiveEntityRuntime(state, resources);
var runtime = LiveEntityRuntimeFixture.Create(state, resources);
var journal = new RenderProjectionJournal(
RenderSceneGeneration.FromRaw(1));
var projections = new LiveRenderProjectionJournal(

View file

@ -55,7 +55,7 @@ public sealed class EntityEffectControllerTests
0x0101FFFFu,
new LandBlock(),
Array.Empty<WorldEntity>()));
Runtime = new LiveEntityRuntime(
Runtime = LiveEntityRuntimeFixture.Create(
Spatial,
new NoopResources(),
record => _controller?.OnLiveEntityUnregistered(record));

View file

@ -151,7 +151,7 @@ public sealed class LiveEntityLightControllerTests
0x0101FFFFu,
new LandBlock(),
Array.Empty<WorldEntity>()));
Runtime = new LiveEntityRuntime(Spatial, new NoopResources(), _ => { });
Runtime = LiveEntityRuntimeFixture.Create(Spatial, new NoopResources(), _ => { });
Sink = new LightingHookSink(Lights, Poses);
Controller = new LiveEntityLightController(
Runtime,

View file

@ -185,7 +185,7 @@ public sealed class CurrentGameRuntimeAdapterTests
public Harness()
{
Identity = new LocalPlayerIdentityState();
Entities = new LiveEntityRuntime(
Entities = LiveEntityRuntimeFixture.Create(
new GpuWorldState(),
new NoopEntityResources());
Objects = new ClientObjectTable();

View file

@ -579,7 +579,7 @@ public sealed class GpuWorldStateVisibilityTests
const uint landblock = 0x0101FFFFu;
const uint cell = 0x01010001u;
var state = new GpuWorldState();
var runtime = new LiveEntityRuntime(
var runtime = LiveEntityRuntimeFixture.Create(
state,
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
WorldSession.EntitySpawn first = Spawn(0x70000011u, cell);
@ -624,7 +624,7 @@ public sealed class GpuWorldStateVisibilityTests
landblock,
new LandBlock(),
Array.Empty<WorldEntity>()));
var runtime = new LiveEntityRuntime(
var runtime = LiveEntityRuntimeFixture.Create(
state,
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
WorldSession.EntitySpawn spawn = Spawn(guid, cell);

View file

@ -396,7 +396,7 @@ public sealed class LocalPlayerTeleportControllerTests
0x2021FFFFu,
new DatReaderWriter.DBObjs.LandBlock(),
Array.Empty<WorldEntity>()));
var runtime = new LiveEntityRuntime(world, new NullResources());
var runtime = LiveEntityRuntimeFixture.Create(world, new NullResources());
runtime.RegisterLiveEntity(Spawn(guid, cell));
WorldEntity entity = runtime.MaterializeLiveEntity(
guid,
@ -479,7 +479,7 @@ public sealed class LocalPlayerTeleportControllerTests
destinationCell & 0xFFFF0000u | 0xFFFFu,
new DatReaderWriter.DBObjs.LandBlock(),
Array.Empty<WorldEntity>()));
var runtime = new LiveEntityRuntime(world, new NullResources());
var runtime = LiveEntityRuntimeFixture.Create(world, new NullResources());
runtime.RegisterLiveEntity(Spawn(guid, sourceCell));
WorldEntity entity = runtime.MaterializeLiveEntity(
guid,

View file

@ -506,7 +506,9 @@ public sealed class StreamingFrameControllerTests
}
private static LiveEntityRuntime Runtime(GpuWorldState state) =>
new(state, new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
LiveEntityRuntimeFixture.Create(
state,
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
private static LoadedLandblock EmptyLandblock(uint landblock) =>
new(landblock, new LandBlock(), Array.Empty<WorldEntity>());

View file

@ -110,7 +110,7 @@ public sealed class DeferredLiveEntityRuntimeComponentLifecycleTests
{
const uint guid = 0x70000002u;
var bridge = new DeferredLiveEntityRuntimeComponentLifecycle();
var runtime = new LiveEntityRuntime(
var runtime = LiveEntityRuntimeFixture.Create(
new GpuWorldState(),
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }),
bridge);
@ -136,7 +136,7 @@ public sealed class DeferredLiveEntityRuntimeComponentLifecycleTests
private static LiveEntityRecord CreateRecord()
{
var runtime = new LiveEntityRuntime(
var runtime = LiveEntityRuntimeFixture.Create(
new GpuWorldState(),
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
return runtime.RegisterAndMaterializeProjection(

View file

@ -1828,7 +1828,8 @@ public sealed class LiveEntityHydrationControllerTests
private sealed class Fixture : IDisposable
{
public readonly List<string> Operations = [];
public readonly ClientObjectTable Objects = new();
public readonly RuntimeEntityObjectLifetime EntityObjects = new();
public ClientObjectTable Objects => EntityObjects.Objects;
public readonly RecordingResources Resources;
public readonly LiveEntityRuntime Runtime;
public readonly RecordingMaterializer Materializer;
@ -1861,7 +1862,8 @@ public sealed class LiveEntityHydrationControllerTests
Runtime = new LiveEntityRuntime(
spatial,
Resources,
Teardown);
Teardown,
EntityObjects);
Materializer = new RecordingMaterializer(Runtime, Operations);
Relationships = new RecordingRelationships(Operations);
Ready = new RecordingReadyPublisher(Operations);
@ -1887,13 +1889,13 @@ public sealed class LiveEntityHydrationControllerTests
};
var deletion = new LiveEntityDeletionController(
Runtime,
Objects,
EntityObjects,
Teardown,
identity,
Dormant);
Controller = new LiveEntityHydrationController(
Runtime,
Objects,
EntityObjects,
new object(),
Materializer,
Relationships,

View file

@ -328,7 +328,7 @@ public sealed class LiveEntityLifecycleStressTests
randomUnit: () => 0.5,
canAdvanceOwner: ownerId => _effects?.CanAdvanceOwner(ownerId) ?? true);
Runtime = new LiveEntityRuntime(
Runtime = LiveEntityRuntimeFixture.Create(
Spatial,
new DelegateLiveEntityResourceLifecycle(
entity =>
@ -489,7 +489,7 @@ public sealed class LiveEntityLifecycleStressTests
EntityEffectController? effects = null;
LiveEntityPresentationController? presentation = null;
RemoteTeleportController? teleport = null;
Runtime = new LiveEntityRuntime(
Runtime = LiveEntityRuntimeFixture.Create(
Spatial,
new DelegateLiveEntityResourceLifecycle(
entity =>

View file

@ -630,10 +630,10 @@ public sealed class LiveEntityPhysicsHostOwnershipTests
private static LiveEntityRuntime Runtime(Action<LiveEntityRecord>? teardown = null) =>
teardown is null
? new LiveEntityRuntime(
? LiveEntityRuntimeFixture.Create(
new GpuWorldState(),
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }))
: new LiveEntityRuntime(
: LiveEntityRuntimeFixture.Create(
new GpuWorldState(),
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }),
teardown);

View file

@ -426,7 +426,7 @@ public sealed class LiveEntityPresentationControllerTests
const uint pendingCell = 0x02020001u;
var spatial = new GpuWorldState();
var shadows = new ShadowObjectRegistry();
var runtime = new LiveEntityRuntime(
var runtime = LiveEntityRuntimeFixture.Create(
spatial,
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
runtime.RegisterLiveEntity(Fixture.Spawn(
@ -487,7 +487,7 @@ public sealed class LiveEntityPresentationControllerTests
const uint pendingCell = 0x02020001u;
var spatial = new GpuWorldState();
var shadows = new ShadowObjectRegistry();
var runtime = new LiveEntityRuntime(
var runtime = LiveEntityRuntimeFixture.Create(
spatial,
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
runtime.RegisterLiveEntity(Fixture.Spawn(
@ -667,7 +667,7 @@ public sealed class LiveEntityPresentationControllerTests
0x0101FFFFu,
new LandBlock(),
Array.Empty<WorldEntity>()));
Runtime = new LiveEntityRuntime(
Runtime = LiveEntityRuntimeFixture.Create(
Spatial,
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }));
WorldSession.EntitySpawn spawn = Spawn(initialState);

View file

@ -196,7 +196,7 @@ public sealed class LiveEntityProjectionWithdrawalControllerTests
new LandBlock(),
Array.Empty<WorldEntity>()));
var lifecycle = new DeferredLiveEntityRuntimeComponentLifecycle();
Live = new LiveEntityRuntime(
Live = LiveEntityRuntimeFixture.Create(
Spatial,
new DelegateLiveEntityResourceLifecycle(_ => { }, _ => { }),
lifecycle);

View file

@ -22,7 +22,7 @@ public sealed class LiveEntityRuntimeTests
public void RuntimeSlot_BindsExactlyOnceWithoutOwningEntityState()
{
var spatial = new GpuWorldState();
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
var slot = new LiveEntityRuntimeSlot();
Assert.Null(slot.Current);
@ -176,7 +176,7 @@ public sealed class LiveEntityRuntimeTests
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
spatial.AddLandblock(EmptyLandblock(0x0102FFFFu));
var resources = new RecordingResources();
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
WorldSession.EntitySpawn spawn = Spawn(0x70000001u, 1, 1, 0x01010001u);
LiveEntityRegistrationResult registered = runtime.RegisterLiveEntity(spawn);
@ -213,7 +213,7 @@ public sealed class LiveEntityRuntimeTests
const uint guid = 0x70000071u;
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
WorldSession.EntitySpawn spawn = Spawn(
guid,
instance: 1,
@ -325,7 +325,7 @@ public sealed class LiveEntityRuntimeTests
const uint guid = 0x70000074u;
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
runtime.RegisterLiveEntity(Spawn(
guid,
instance: 1,
@ -417,7 +417,7 @@ public sealed class LiveEntityRuntimeTests
const uint guid = 0x70000070u;
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
WorldSession.EntitySpawn spawn = Spawn(guid, 1, 1, 0x01010001u);
runtime.RegisterLiveEntity(spawn);
WorldEntity entity = runtime.MaterializeLiveEntity(
@ -476,7 +476,7 @@ public sealed class LiveEntityRuntimeTests
const uint guid = 0x70000071u;
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
WorldEntity entity = runtime.MaterializeLiveEntity(
guid,
@ -513,7 +513,7 @@ public sealed class LiveEntityRuntimeTests
const uint secondGuid = 0x70000074u;
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
foreach (uint guid in new[] { firstGuid, secondGuid })
{
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
@ -545,7 +545,7 @@ public sealed class LiveEntityRuntimeTests
const uint guid = 0x70000075u;
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
WorldEntity entity = runtime.MaterializeLiveEntity(
guid,
@ -580,7 +580,7 @@ public sealed class LiveEntityRuntimeTests
const uint guid = 0x70000072u;
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
WorldEntity oldEntity = runtime.MaterializeLiveEntity(
guid,
@ -617,7 +617,7 @@ public sealed class LiveEntityRuntimeTests
const uint guid = 0x70000073u;
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
runtime.MaterializeLiveEntity(
guid,
@ -672,7 +672,7 @@ public sealed class LiveEntityRuntimeTests
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
spatial.AddLandblock(EmptyLandblock(0x0102FFFFu));
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
WorldSession.EntitySpawn spawn = Spawn(guid, 6, 1, 0x01010001u);
LiveEntityRegistrationResult registration =
runtime.RegisterLiveEntity(spawn);
@ -702,7 +702,7 @@ public sealed class LiveEntityRuntimeTests
{
const uint parentGuid = 0x70000020u;
const uint childGuid = 0x70000021u;
var runtime = new LiveEntityRuntime(new GpuWorldState(), new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(new GpuWorldState(), new RecordingResources());
runtime.RegisterLiveEntity(Spawn(parentGuid, 9, 1, 0x01010001u));
runtime.ParentAttachments.Enqueue(new ParentEvent.Parsed(
parentGuid, childGuid, 1, 2, 9, 5));
@ -725,7 +725,7 @@ public sealed class LiveEntityRuntimeTests
{
const uint parentGuid = 0x70000022u;
const uint childGuid = 0x70000023u;
var runtime = new LiveEntityRuntime(new GpuWorldState(), new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(new GpuWorldState(), new RecordingResources());
runtime.RegisterLiveEntity(Spawn(childGuid, 3, 4, 0x01010001u));
runtime.ParentAttachments.AcceptCreateObjectRelation(new ParentAttachmentRelation(
parentGuid, childGuid, 1, 2, 9, 4));
@ -743,7 +743,7 @@ public sealed class LiveEntityRuntimeTests
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var resources = new RecordingResources();
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
WorldSession.EntitySpawn first = Spawn(0x70000002u, 4, 10, 0x01010001u);
runtime.RegisterLiveEntity(first);
WorldEntity original = runtime.MaterializeLiveEntity(
@ -771,7 +771,7 @@ public sealed class LiveEntityRuntimeTests
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var resources = new RecordingResources();
int runtimeTearDowns = 0;
var runtime = new LiveEntityRuntime(
var runtime = LiveEntityRuntimeFixture.Create(
spatial,
resources,
_ => runtimeTearDowns++);
@ -803,7 +803,7 @@ public sealed class LiveEntityRuntimeTests
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var resources = new RecordingResources();
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
WorldSession.EntitySpawn spawn = Spawn(0x70000004u, 2, 3, 0x01010001u);
runtime.RegisterLiveEntity(spawn);
WorldEntity entity = runtime.MaterializeLiveEntity(
@ -833,7 +833,7 @@ public sealed class LiveEntityRuntimeTests
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var resources = new RecordingResources();
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
const uint guid = 0x70000005u;
runtime.RegisterLiveEntity(Spawn(guid, 3, 1, 0x01010001u));
WorldEntity first = runtime.MaterializeLiveEntity(
@ -863,7 +863,7 @@ public sealed class LiveEntityRuntimeTests
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var resources = new RecordingResources();
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
WorldSession.EntitySpawn spawn = Spawn(0x70000006u, 3, 1, 0x01010001u);
runtime.RegisterLiveEntity(spawn);
@ -900,7 +900,7 @@ public sealed class LiveEntityRuntimeTests
{
var spatial = new GpuWorldState();
var resources = new RecordingResources();
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
WorldSession.EntitySpawn spawn = Spawn(0x70000007u, 1, 1, 0x01020001u);
runtime.RegisterLiveEntity(spawn);
WorldEntity entity = runtime.MaterializeLiveEntity(
@ -929,7 +929,7 @@ public sealed class LiveEntityRuntimeTests
const uint guid = 0x70000025u;
var spatial = new GpuWorldState();
var resources = new RecordingResources();
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
WorldSession.EntitySpawn spawn = Spawn(guid, 2, 1, 0x01010001u);
runtime.RegisterLiveEntity(spawn);
WorldEntity entity = runtime.MaterializeLiveEntity(
@ -983,7 +983,7 @@ public sealed class LiveEntityRuntimeTests
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var resources = new RecordingResources();
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
WorldSession.EntitySpawn spawn = Spawn(guid, 4, 10, 0x01010001u);
runtime.RegisterLiveEntity(spawn);
WorldEntity entity = runtime.MaterializeLiveEntity(
@ -1063,7 +1063,7 @@ public sealed class LiveEntityRuntimeTests
const uint guid = 0x70000027u;
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
WorldSession.EntitySpawn spawn = Spawn(guid, 1, 1, 0x01010001u);
runtime.RegisterLiveEntity(spawn);
runtime.MaterializeLiveEntity(
@ -1104,7 +1104,7 @@ public sealed class LiveEntityRuntimeTests
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
spatial.AddLandblock(EmptyLandblock(0x0102FFFFu));
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
WorldSession.EntitySpawn spawn = Spawn(guid, 1, 1, 0x01010001u);
LiveEntityRecord record = RegisterProjection(runtime, spawn);
RetailObjectQuantumClock clock = record.ObjectClock;
@ -1143,7 +1143,7 @@ public sealed class LiveEntityRuntimeTests
const uint guid = 0x70000049u;
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
WorldSession.EntitySpawn spawn = Spawn(
guid,
1,
@ -1166,7 +1166,7 @@ public sealed class LiveEntityRuntimeTests
const uint staticGuid = 0x70000051u;
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
LiveEntityRecord ordinary = RegisterProjection(
runtime,
@ -1204,7 +1204,7 @@ public sealed class LiveEntityRuntimeTests
const uint staticGuid = 0x70000054u;
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
LiveEntityRecord ordinary = RegisterProjection(
runtime,
@ -1279,7 +1279,7 @@ public sealed class LiveEntityRuntimeTests
{
const uint parentGuid = 0x50000010u;
const uint childGuid = 0x70000055u;
var runtime = new LiveEntityRuntime(new GpuWorldState(), new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(new GpuWorldState(), new RecordingResources());
runtime.RegisterLiveEntity(Spawn(parentGuid, 1, 1, 0x01010001u));
LiveEntityRecord child = RegisterProjection(
runtime,
@ -1314,7 +1314,7 @@ public sealed class LiveEntityRuntimeTests
const uint guid = 0x70000048u;
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
WorldSession.EntitySpawn firstSpawn = Spawn(guid, 1, 1, 0x01010001u);
LiveEntityRecord first = RegisterProjection(runtime, firstSpawn);
RetailObjectQuantumClock firstClock = first.ObjectClock;
@ -1341,7 +1341,7 @@ public sealed class LiveEntityRuntimeTests
{
const uint stateBeforeBindGuid = 0x70000037u;
const uint bindBeforeStateGuid = 0x70000038u;
var runtime = new LiveEntityRuntime(new GpuWorldState(), new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(new GpuWorldState(), new RecordingResources());
runtime.RegisterLiveEntity(Spawn(stateBeforeBindGuid, 1, 1, 0x01010001u));
runtime.RegisterLiveEntity(Spawn(bindBeforeStateGuid, 1, 1, 0x01010001u));
@ -1381,7 +1381,7 @@ public sealed class LiveEntityRuntimeTests
public void ParentDrivenChildNoDrawKeepsBoundBodyInCanonicalState()
{
const uint guid = 0x70000039u;
var runtime = new LiveEntityRuntime(new GpuWorldState(), new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(new GpuWorldState(), new RecordingResources());
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
runtime.MaterializeLiveEntity(
guid,
@ -1401,7 +1401,7 @@ public sealed class LiveEntityRuntimeTests
public void InitiallyVisibleCreate_DoesNotManufactureUnHideTransition()
{
const uint guid = 0x70000040u;
var runtime = new LiveEntityRuntime(new GpuWorldState(), new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(new GpuWorldState(), new RecordingResources());
LiveEntityRecord record = RegisterProjection(
runtime,
@ -1418,7 +1418,7 @@ public sealed class LiveEntityRuntimeTests
const uint guid = 0x70000041u;
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
runtime.RegisterLiveEntity(Spawn(
guid,
1,
@ -1448,7 +1448,7 @@ public sealed class LiveEntityRuntimeTests
const uint guid = 0x70000042u;
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
WorldEntity entity = runtime.MaterializeLiveEntity(
guid,
@ -1486,7 +1486,7 @@ public sealed class LiveEntityRuntimeTests
public void PositionAfterPickup_RequiresTeleportHookEvenWithEqualTeleportStamp()
{
const uint guid = 0x70000043u;
var runtime = new LiveEntityRuntime(new GpuWorldState(), new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(new GpuWorldState(), new RecordingResources());
WorldSession.EntitySpawn spawn = Spawn(guid, 1, 1, 0x01010001u);
runtime.RegisterLiveEntity(spawn);
Assert.True(runtime.TryApplyPickup(
@ -1524,7 +1524,7 @@ public sealed class LiveEntityRuntimeTests
const uint guid = 0x70000044u;
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
WorldSession.EntitySpawn spawn = Spawn(guid, 1, 1, 0x01010001u);
runtime.RegisterLiveEntity(spawn);
runtime.MaterializeLiveEntity(
@ -1563,7 +1563,7 @@ public sealed class LiveEntityRuntimeTests
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var resources = new RecordingResources();
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
WorldSession.EntitySpawn spawn = Spawn(0x70000024u, 1, 1, 0x01010001u);
runtime.RegisterLiveEntity(spawn);
WorldEntity entity = runtime.MaterializeLiveEntity(
@ -1593,7 +1593,7 @@ public sealed class LiveEntityRuntimeTests
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var resources = new RecordingResources();
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
WorldSession.EntitySpawn spawn = Spawn(0x70000009u, 1, 1, 0x01010001u);
runtime.RegisterLiveEntity(spawn);
WorldEntity entity = runtime.MaterializeLiveEntity(
@ -1620,7 +1620,7 @@ public sealed class LiveEntityRuntimeTests
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var resources = new RecordingResources();
int runtimeTearDowns = 0;
var runtime = new LiveEntityRuntime(spatial, resources, _ => runtimeTearDowns++);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources, _ => runtimeTearDowns++);
WorldSession.EntitySpawn spawn = Spawn(0x70000008u, 1, 1, 0x01010001u);
runtime.RegisterLiveEntity(spawn);
runtime.MaterializeLiveEntity(
@ -1645,7 +1645,7 @@ public sealed class LiveEntityRuntimeTests
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var resources = new FailingRegisterResources();
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
WorldSession.EntitySpawn spawn = Spawn(0x7000000Au, 1, 1, 0x01010001u);
runtime.RegisterLiveEntity(spawn);
@ -1671,7 +1671,7 @@ public sealed class LiveEntityRuntimeTests
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var resources = new FailingRegisterAndRollbackOnceResources();
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
Assert.Throws<AggregateException>(() => runtime.MaterializeLiveEntity(
@ -1709,7 +1709,7 @@ public sealed class LiveEntityRuntimeTests
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var resources = new FailingRegisterAndRollbackOnceResources();
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
Assert.Throws<AggregateException>(() => runtime.MaterializeLiveEntity(
guid,
@ -1736,7 +1736,7 @@ public sealed class LiveEntityRuntimeTests
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var resources = new FailingRegisterAndRollbackOnceResources();
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
WorldSession.EntitySpawn spawn = Spawn(guid, 1, 1, 0x01010001u);
runtime.RegisterLiveEntity(spawn);
Assert.Throws<AggregateException>(() => runtime.MaterializeLiveEntity(
@ -1764,7 +1764,7 @@ public sealed class LiveEntityRuntimeTests
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var resources = new FailingUnregisterResources(0x7000000Bu);
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
foreach (uint guid in new[] { 0x7000000Bu, 0x7000000Cu })
{
WorldSession.EntitySpawn spawn = Spawn(guid, 1, 1, 0x01010001u);
@ -1792,7 +1792,7 @@ public sealed class LiveEntityRuntimeTests
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var resources = new FailingOnceUnregisterResources(guid);
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
WorldSession.EntitySpawn spawn = Spawn(guid, 1, 1, 0x01010001u);
runtime.RegisterLiveEntity(spawn);
runtime.MaterializeLiveEntity(guid, 0x01010001u, id => Entity(id, guid));
@ -1819,7 +1819,7 @@ public sealed class LiveEntityRuntimeTests
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var resources = new FailingOnceUnregisterResources(guid);
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
WorldSession.EntitySpawn spawn = Spawn(guid, 1, 1, 0x01010001u);
runtime.RegisterLiveEntity(spawn);
runtime.MaterializeLiveEntity(guid, 0x01010001u, id => Entity(id, guid));
@ -1852,7 +1852,7 @@ public sealed class LiveEntityRuntimeTests
if (!adapter.OnRemove(entity))
throw new InvalidOperationException("presentation owner was not registered");
});
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
runtime.ProjectionVisibilityChanged += (record, visible) =>
{
if (record.WorldEntity is { } entity)
@ -1887,7 +1887,7 @@ public sealed class LiveEntityRuntimeTests
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var resources = new FailingUnregisterResources(guid);
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
WorldSession.EntitySpawn first = Spawn(guid, 1, 1, 0x01010001u);
runtime.RegisterLiveEntity(first);
runtime.MaterializeLiveEntity(
@ -1918,7 +1918,7 @@ public sealed class LiveEntityRuntimeTests
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
spatial.AddLandblock(EmptyLandblock(0x0102FFFFu));
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010022u));
runtime.MaterializeLiveEntity(guid, 0x01010022u, id => Entity(id, guid));
@ -1940,7 +1940,7 @@ public sealed class LiveEntityRuntimeTests
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
spatial.AddLandblock(EmptyLandblock(0x0102FFFFu));
var resources = new RecordingResources();
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
WorldEntity attached = runtime.MaterializeLiveEntity(
guid,
@ -1965,7 +1965,7 @@ public sealed class LiveEntityRuntimeTests
{
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var runtime = new LiveEntityRuntime(
var runtime = LiveEntityRuntimeFixture.Create(
spatial,
new RecordingResources(),
firstLocalEntityId: LiveEntityRuntime.LastLiveEntityId);
@ -1984,7 +1984,7 @@ public sealed class LiveEntityRuntimeTests
Assert.NotEqual(0u, secondEntity.Id);
Assert.True(runtime.TryGetLocalEntityId(second.Guid, out uint resolved));
Assert.Equal(secondEntity.Id, resolved);
Assert.Throws<ArgumentOutOfRangeException>(() => new LiveEntityRuntime(
Assert.Throws<ArgumentOutOfRangeException>(() => LiveEntityRuntimeFixture.Create(
new GpuWorldState(),
new RecordingResources(),
firstLocalEntityId: uint.MaxValue));
@ -1996,7 +1996,7 @@ public sealed class LiveEntityRuntimeTests
const uint guid = 0x7000002Au;
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
runtime.MaterializeLiveEntity(
guid,
@ -2022,7 +2022,7 @@ public sealed class LiveEntityRuntimeTests
public void SessionClear_ForgetsPersistentClassificationWithoutMaterializedRecord()
{
var spatial = new GpuWorldState();
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
spatial.MarkPersistent(0x7000002Bu);
runtime.Clear();
@ -2037,7 +2037,7 @@ public sealed class LiveEntityRuntimeTests
const uint guid = 0x7000002Du;
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
runtime.MaterializeLiveEntity(
guid,
@ -2067,7 +2067,7 @@ public sealed class LiveEntityRuntimeTests
const uint guid = 0x70000040u;
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
WorldEntity entity = runtime.MaterializeLiveEntity(
guid,
@ -2096,7 +2096,7 @@ public sealed class LiveEntityRuntimeTests
const uint guid = 0x70000041u;
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
runtime.MaterializeLiveEntity(
guid,
@ -2127,7 +2127,7 @@ public sealed class LiveEntityRuntimeTests
const uint guid = 0x70000044u;
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
runtime.MaterializeLiveEntity(guid, 0x01010001u, id => Entity(id, guid));
bool replaced = false;
@ -2161,7 +2161,7 @@ public sealed class LiveEntityRuntimeTests
const uint guid = 0x70000045u;
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
WorldEntity original = runtime.MaterializeLiveEntity(
guid,
@ -2200,7 +2200,7 @@ public sealed class LiveEntityRuntimeTests
const uint guid = 0x70000046u;
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
runtime.MaterializeLiveEntity(guid, 0x01010001u, id => Entity(id, guid));
bool reprojected = false;
@ -2228,7 +2228,7 @@ public sealed class LiveEntityRuntimeTests
{
const uint guid = 0x70000075u;
var spatial = new GpuWorldState();
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
WorldEntity pending = runtime.MaterializeLiveEntity(
guid,
@ -2277,7 +2277,7 @@ public sealed class LiveEntityRuntimeTests
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var resources = new FailingOnceUnregisterResources(guid);
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
WorldEntity? replacementEntity = null;
bool replaced = false;
@ -2318,7 +2318,7 @@ public sealed class LiveEntityRuntimeTests
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
spatial.AddLandblock(EmptyLandblock(0x0303FFFFu));
var runtime = new LiveEntityRuntime(spatial, new RecordingResources());
var runtime = LiveEntityRuntimeFixture.Create(spatial, new RecordingResources());
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
WorldEntity original = runtime.MaterializeLiveEntity(
guid,
@ -2352,7 +2352,7 @@ public sealed class LiveEntityRuntimeTests
const uint guid = 0x7000002Cu;
var spatial = new GpuWorldState();
var resources = new RecordingResources();
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
runtime.MaterializeLiveEntity(
guid,
@ -2394,7 +2394,7 @@ public sealed class LiveEntityRuntimeTests
const uint guid = 0x7000002Eu;
var spatial = new GpuWorldState();
var resources = new RecordingResources();
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
runtime.MaterializeLiveEntity(
guid,
@ -2434,7 +2434,7 @@ public sealed class LiveEntityRuntimeTests
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var resources = new RecordingResources();
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
WorldEntity old = runtime.MaterializeLiveEntity(
guid,
@ -2477,7 +2477,7 @@ public sealed class LiveEntityRuntimeTests
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var resources = new CallbackResources();
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
runtime.MaterializeLiveEntity(guid, 0x01010001u, id => Entity(id, guid));
resources.OnUnregister = _ =>
@ -2508,7 +2508,7 @@ public sealed class LiveEntityRuntimeTests
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var resources = new CallbackResources();
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
runtime.MaterializeLiveEntity(guid, 0x01010001u, id => Entity(id, guid));
resources.OnUnregister = _ =>
@ -2538,7 +2538,7 @@ public sealed class LiveEntityRuntimeTests
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var resources = new CallbackResources();
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
runtime.MaterializeLiveEntity(guid, 0x01010001u, id => Entity(id, guid));
resources.OnUnregister = _ =>
@ -2568,7 +2568,7 @@ public sealed class LiveEntityRuntimeTests
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var resources = new CallbackResources();
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
runtime.MaterializeLiveEntity(guid, 0x01010001u, id => Entity(id, guid));
resources.OnUnregister = _ =>
@ -2600,7 +2600,7 @@ public sealed class LiveEntityRuntimeTests
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var resources = new CallbackResources();
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
runtime.MaterializeLiveEntity(guid, 0x01010001u, id => Entity(id, guid));
resources.OnUnregister = _ =>
@ -2632,7 +2632,7 @@ public sealed class LiveEntityRuntimeTests
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var resources = new CallbackResources();
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
runtime.MaterializeLiveEntity(guid, 0x01010001u, id => Entity(id, guid));
resources.OnUnregister = _ =>
@ -2660,7 +2660,7 @@ public sealed class LiveEntityRuntimeTests
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var resources = new CallbackResources();
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
resources.OnRegister = _ =>
runtime.RegisterLiveEntity(Spawn(guid, 2, 1, 0x01010001u));
@ -2686,7 +2686,7 @@ public sealed class LiveEntityRuntimeTests
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var resources = new CallbackResources();
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
runtime.RegisterLiveEntity(Spawn(guid, 1, 1, 0x01010001u));
resources.OnRegister = _ => runtime.Clear();
@ -2711,7 +2711,7 @@ public sealed class LiveEntityRuntimeTests
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var resources = new CallbackResources();
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
runtime.RegisterLiveEntity(Spawn(firstGuid, 1, 1, 0x01010001u));
runtime.RegisterLiveEntity(Spawn(secondGuid, 1, 1, 0x01010001u));
runtime.MaterializeLiveEntity(firstGuid, 0x01010001u, id => Entity(id, firstGuid));
@ -2744,7 +2744,7 @@ public sealed class LiveEntityRuntimeTests
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var resources = new CallbackResources();
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
runtime.RegisterLiveEntity(Spawn(oldGuid, 1, 1, 0x01010001u));
runtime.MaterializeLiveEntity(oldGuid, 0x01010001u, id => Entity(id, oldGuid));
resources.OnUnregister = _ =>
@ -2785,7 +2785,7 @@ public sealed class LiveEntityRuntimeTests
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0x0101FFFFu));
var resources = new RecordingResources();
var runtime = new LiveEntityRuntime(spatial, resources);
var runtime = LiveEntityRuntimeFixture.Create(spatial, resources);
WorldSession.EntitySpawn spawn = Spawn(0x7000000Du, 4, 1, 0x01010001u);
runtime.RegisterLiveEntity(spawn);
runtime.MaterializeLiveEntity(

View file

@ -13,8 +13,19 @@ namespace AcDream.App.Tests.World;
public sealed class RuntimeEntityOwnershipTests
{
[Fact]
public void LiveEntityRuntime_ComposesCanonicalRuntimeDirectory()
public void LiveEntityRuntime_BorrowsCanonicalRuntimeDirectory()
{
var lifetime = new RuntimeEntityObjectLifetime();
var runtime = new LiveEntityRuntime(
new GpuWorldState(),
new DelegateLiveEntityResourceLifecycle(
static _ => { },
static _ => { }),
lifetime);
FieldInfo owner = typeof(LiveEntityRuntime).GetField(
"_entityObjects",
BindingFlags.Instance | BindingFlags.NonPublic)
?? throw new InvalidOperationException("Missing Runtime lifetime root.");
FieldInfo directory = typeof(LiveEntityRuntime).GetField(
"_directory",
BindingFlags.Instance | BindingFlags.NonPublic)
@ -25,9 +36,62 @@ public sealed class RuntimeEntityOwnershipTests
?? throw new InvalidOperationException("Missing App projection sidecar store.");
Assert.Equal(typeof(RuntimeEntityDirectory), directory.FieldType);
Assert.Same(lifetime, owner.GetValue(runtime));
Assert.Same(lifetime.Entities, directory.GetValue(runtime));
Assert.Equal(typeof(LiveEntityProjectionStore), sidecars.FieldType);
}
[Fact]
public void ProductionComposition_HasOneRuntimeEntityObjectConstructionRoot()
{
string root = FindRepositoryRoot();
string appRoot = Path.Combine(root, "src", "AcDream.App");
string runtimeRoot = Path.Combine(root, "src", "AcDream.Runtime");
string[] appSources = Directory.GetFiles(
appRoot,
"*.cs",
SearchOption.AllDirectories);
string[] runtimeSources = Directory.GetFiles(
runtimeRoot,
"*.cs",
SearchOption.AllDirectories);
string[] appObjectAllocators = appSources
.Where(path => !path.Contains(
$"{Path.DirectorySeparatorChar}Studio{Path.DirectorySeparatorChar}",
StringComparison.OrdinalIgnoreCase))
.Where(path => File.ReadAllText(path).Contains(
"new ClientObjectTable",
StringComparison.Ordinal))
.ToArray();
string[] appDirectoryAllocators = appSources
.Where(path => File.ReadAllText(path).Contains(
"new RuntimeEntityDirectory",
StringComparison.Ordinal))
.ToArray();
string[] runtimeObjectAllocators = runtimeSources
.Where(path => File.ReadAllText(path).Contains(
"new ClientObjectTable",
StringComparison.Ordinal))
.Select(path => Path.GetFileName(path)!)
.ToArray();
string[] runtimeDirectoryAllocators = runtimeSources
.Where(path => File.ReadAllText(path).Contains(
"new RuntimeEntityDirectory",
StringComparison.Ordinal))
.Select(path => Path.GetFileName(path)!)
.ToArray();
Assert.Empty(appObjectAllocators);
Assert.Empty(appDirectoryAllocators);
Assert.Equal(
["RuntimeEntityObjectLifetime.cs"],
runtimeObjectAllocators);
Assert.Equal(
["RuntimeEntityObjectLifetime.cs"],
runtimeDirectoryAllocators);
}
[Fact]
public void AppProjectionOwners_UseExactRuntimeKeysAndNoGuidDictionary()
{
@ -212,4 +276,18 @@ public sealed class RuntimeEntityOwnershipTests
field.FieldType.IsGenericType
&& field.FieldType.GetGenericTypeDefinition() == typeof(Dictionary<,>)
&& field.FieldType.GetGenericArguments()[0] == keyType;
private static string FindRepositoryRoot()
{
DirectoryInfo? directory = new(AppContext.BaseDirectory);
while (directory is not null)
{
if (File.Exists(Path.Combine(directory.FullName, "AcDream.slnx")))
return directory.FullName;
directory = directory.Parent;
}
throw new DirectoryNotFoundException(
$"Could not find AcDream.slnx above {AppContext.BaseDirectory}.");
}
}