refactor(app): key live projections by runtime identity

Move materialized live-object sidecars and presentation worksets to exact RuntimeEntityKey ownership. Runtime remains the only GUID/incarnation/local-ID authority while hydration, animation, effects, lights, equipped children, renderer resources, visibility, liveness, and teardown resolve exact projection identities. Preserve synchronous callbacks, local-ID allocation order, and current rendering behavior.
This commit is contained in:
Erik 2026-07-25 21:50:58 +02:00
parent e18df84437
commit 420e5eea70
73 changed files with 2939 additions and 1715 deletions

View file

@ -119,12 +119,12 @@ public sealed class EntityEffectControllerTests
EntityEffectProfile? profile = null)
{
WorldSession.EntitySpawn spawn = Spawn(guid, generation);
Runtime.RegisterLiveEntity(spawn);
Runtime.SetEffectProfile(guid, profile ?? LiveProfile());
WorldEntity entity = Runtime.MaterializeLiveEntity(
guid,
spawn.Position!.Value.LandblockId,
id => Entity(id, guid))!;
LiveEntityRecord record = Runtime.RegisterAndMaterializeProjection(
spawn,
id => Entity(id, guid),
initializeProjection: exact =>
exact.EffectProfile = profile ?? LiveProfile());
WorldEntity entity = Assert.IsType<WorldEntity>(record.WorldEntity);
Assert.True(Controller.OnLiveEntityReady(guid));
return entity;
}
@ -172,12 +172,11 @@ public sealed class EntityEffectControllerTests
var fixture = new Fixture();
fixture.Controller.HandleDirect(new PlayPhysicsScript(Guid, DirectDid));
WorldSession.EntitySpawn spawn = Spawn(Guid, 1);
fixture.Runtime.RegisterLiveEntity(spawn);
fixture.Runtime.SetEffectProfile(Guid, Fixture.LiveProfile());
fixture.Runtime.MaterializeLiveEntity(
Guid,
spawn.Position!.Value.LandblockId,
id => Entity(id, Guid));
fixture.Runtime.RegisterAndMaterializeProjection(
spawn,
id => Entity(id, Guid),
initializeProjection: record =>
record.EffectProfile = Fixture.LiveProfile());
Assert.True(fixture.Controller.PrepareLiveEntityOwner(Guid));
Assert.Equal(1, fixture.Controller.PendingPacketCount);
@ -279,12 +278,13 @@ public sealed class EntityEffectControllerTests
var fixture = new Fixture();
fixture.Controller.HandleDirect(new PlayPhysicsScript(Guid, DirectDid));
WorldSession.EntitySpawn spawn = Spawn(Guid, 1);
fixture.Runtime.RegisterLiveEntity(spawn);
fixture.Runtime.SetEffectProfile(Guid, Fixture.LiveProfile());
WorldEntity entity = fixture.Runtime.MaterializeLiveEntity(
Guid,
0x02020001u,
id => Entity(id, Guid))!;
LiveEntityRecord record = fixture.Runtime.RegisterAndMaterializeProjection(
spawn,
id => Entity(id, Guid),
initializeProjection: exact =>
exact.EffectProfile = Fixture.LiveProfile());
WorldEntity entity = Assert.IsType<WorldEntity>(record.WorldEntity);
fixture.Runtime.RebucketLiveEntity(Guid, 0x02020001u);
Assert.True(fixture.Controller.OnLiveEntityReady(Guid));
Assert.Equal(1, fixture.Controller.PendingPacketCount);
@ -360,6 +360,7 @@ public sealed class EntityEffectControllerTests
WorldSession.EntitySpawn first = Spawn(Guid, generation: 1);
fixture.Runtime.RegisterLiveEntity(first);
fixture.Controller.ForgetUnknownOwner(Guid);
Assert.True(fixture.Runtime.UnregisterLiveEntity(
new DeleteObject.Parsed(Guid, 1),
isLocalPlayer: false));
@ -383,11 +384,11 @@ public sealed class EntityEffectControllerTests
isLocalPlayer: false));
Assert.Equal(1, fixture.Controller.PendingPacketCount);
fixture.Runtime.SetEffectProfile(Guid, Fixture.LiveProfile());
fixture.Runtime.MaterializeLiveEntity(
Guid,
current.Position!.Value.LandblockId,
id => Entity(id, Guid));
fixture.Runtime.RegisterAndMaterializeProjection(
current,
id => Entity(id, Guid),
initializeProjection: record =>
record.EffectProfile = Fixture.LiveProfile());
Assert.True(fixture.Controller.OnLiveEntityReady(Guid));
fixture.Runner.Tick(0.0);
Assert.Equal([1u], EmitterIds(fixture.Sink));