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

@ -37,7 +37,7 @@ public sealed class RadarSnapshotProviderTests
uint? selected = monster;
var provider = new RadarSnapshotProvider(
objects, () => entities, () => spawns,
objects, new RadarEntities(() => entities), () => spawns,
playerGuid: () => player,
playerYawRadians: () => MathF.PI / 2f, // retail heading 0 degrees
playerCellId: () => 0xA9B40001u,
@ -83,7 +83,7 @@ public sealed class RadarSnapshotProviderTests
[hidden] = Spawn(hidden),
};
var provider = new RadarSnapshotProvider(
objects, () => entities, () => spawns,
objects, new RadarEntities(() => entities), () => spawns,
playerGuid: () => player,
playerYawRadians: () => 0f,
playerCellId: () => 0xA9B40100u, // EnvCell: no landscape coordinate
@ -122,15 +122,16 @@ public sealed class RadarSnapshotProviderTests
};
var provider = new RadarSnapshotProvider(
objects,
() => interactionVisible,
new RadarEntities(
() => interactionVisible,
() => canonical),
() => spawns,
playerGuid: () => player,
playerYawRadians: () => 0f,
playerCellId: () => 0xA9B40001u,
selectedGuid: () => hiddenTarget,
coordinatesOnRadar: () => true,
uiLocked: () => false,
playerEntities: () => canonical);
uiLocked: () => false);
var snapshot = provider.BuildSnapshot();
@ -158,15 +159,14 @@ public sealed class RadarSnapshotProviderTests
new Dictionary<uint, WorldSession.EntitySpawn>();
var provider = new RadarSnapshotProvider(
objects,
() => visible,
new RadarEntities(() => visible, () => canonical),
() => spawns,
playerGuid: () => player,
playerYawRadians: () => MathF.PI / 2f,
playerCellId: () => 0xA9B40001u,
selectedGuid: () => null,
coordinatesOnRadar: () => true,
uiLocked: () => false,
playerEntities: () => canonical);
uiLocked: () => false);
Assert.Null(provider.BuildSnapshot().CoordinatesText);
@ -215,7 +215,7 @@ public sealed class RadarSnapshotProviderTests
new KeyValuePair<uint, WorldEntity>(nearby, entities[nearby]));
var provider = new RadarSnapshotProvider(
objects,
() => entities,
new RadarEntities(() => entities),
() => spawns,
playerGuid: () => player,
playerYawRadians: () => 0f,
@ -252,7 +252,7 @@ public sealed class RadarSnapshotProviderTests
ILiveEntitySpatialQuery currentSpatialQuery = new RecordingSpatialQuery();
var provider = new RadarSnapshotProvider(
objects,
() => entities,
new RadarEntities(() => entities),
() => spawns,
playerGuid: () => player,
playerYawRadians: () => 0f,
@ -287,6 +287,35 @@ public sealed class RadarSnapshotProviderTests
}
}
private sealed class RadarEntities(
Func<IReadOnlyDictionary<uint, WorldEntity>> visible,
Func<IReadOnlyDictionary<uint, WorldEntity>>? materialized = null)
: ILiveEntityRadarSource
{
private readonly Func<IReadOnlyDictionary<uint, WorldEntity>> _visible =
visible;
private readonly Func<IReadOnlyDictionary<uint, WorldEntity>> _materialized =
materialized ?? visible;
public bool TryGetMaterialized(
uint serverGuid,
out WorldEntity entity) =>
_materialized().TryGetValue(serverGuid, out entity!);
public bool TryGetVisible(
uint serverGuid,
out WorldEntity entity) =>
_visible().TryGetValue(serverGuid, out entity!);
public void CopyVisibleTo(
List<KeyValuePair<uint, WorldEntity>> destination)
{
destination.Clear();
foreach (KeyValuePair<uint, WorldEntity> pair in _visible())
destination.Add(pair);
}
}
private static WorldEntity Entity(uint guid, Vector3 position, Quaternion rotation) => new()
{
Id = guid,