Index observed facades by daemon entity

This commit is contained in:
Meta Vens 2026-06-21 17:57:37 +01:00
commit bfa05dc2de
3 changed files with 30 additions and 21 deletions

View file

@ -1978,6 +1978,12 @@ static void RequireDaemonRenderQueryAuthority(string root)
"ZoneRenderer must reconcile rendered entities from daemon frame snapshots instead of subscribing to mirrored Unity entity collection mutations.");
}
if (zoneRenderer.Contains("foreach (var entity in legacyEntityFacadeZone.Entities)", StringComparison.Ordinal))
{
throw new InvalidOperationException(
"ZoneRenderer must use the daemon-indexed observed facade projection supplied by gameplay instead of enumerating Unity Zone.Entities.");
}
if (zoneRenderer.Contains("PerspectiveEntity.EntityInfoGathered", StringComparison.Ordinal))
{
throw new InvalidOperationException(
@ -2015,6 +2021,7 @@ static void RequireDaemonRenderQueryAuthority(string root)
"private Zone _legacyEntityFacadeZone;",
"public void LoadDaemonZoneView(",
"Zone legacyEntityFacadeZone,",
"IReadOnlyDictionary<int, Entity> observedEntityFacadesByDaemonIndex,",
"AetheriaRuntimeRunCheckpointCommit daemonRun = null",
"public void ApplyDaemonFrame(",
"AetheriaRuntimeZoneSnapshotCommit daemonZone,",
@ -2033,7 +2040,7 @@ static void RequireDaemonRenderQueryAuthority(string root)
"LoadAsteroidBelt(beltPose)",
"void LoadAsteroidBelt(AetheriaRuntimeDaemonAsteroidBeltPose beltPose)",
"foreach (var entitySnapshot in daemonZone?.Entities ?? Array.Empty<AetheriaRuntimeEntitySnapshotCommit>())",
"entitiesByDaemonIndex.TryGetValue(entitySnapshot.EntityIndex, out var entity)",
"observedEntityFacadesByDaemonIndex.TryGetValue(entitySnapshot.EntityIndex, out var entity)",
"private readonly Dictionary<int, EntityInstance> _entityInstancesByDaemonIndex",
"public IReadOnlyDictionary<int, EntityInstance> DaemonEntityInstances => _entityInstancesByDaemonIndex;",
"public bool TryGetEntityInstance(int daemonEntityIndex, out EntityInstance instance)",
@ -7755,6 +7762,9 @@ static void RequireMainMenuContinueRunState(string root)
"GetObservedInfoGathered(CurrentEntity, target)",
"IsObservedHostileContact(CurrentEntity, observedTarget)",
"_observedEntityFacadesByRecordKey",
"_observedEntityFacadesByDaemonIndex",
"RebuildObservedEntityFacadeIndex();",
"ZoneRenderer.LoadDaemonZoneView(Zone, _observedEntityFacadesByDaemonIndex, daemonZone, daemonRun)",
"entity.RestoreStatGrids(entitySnapshot.StatGrids)",
"RestoreThermalExposure((float)entitySnapshot.Heatstroke, (float)entitySnapshot.Hypothermia)",
"entity.HeatsinksEnabled = entitySnapshot.HeatsinksEnabled",
@ -8012,7 +8022,7 @@ static void RequireUnityObserverDoesNotTickLocalSimulation(string root)
"observed.IsAuthoritative",
"TryRestoreEntityGraphFromDaemonRun(observed.Run)",
"CreateDaemonZoneConstructionBlueprint(daemonZone)",
"ZoneRenderer.LoadDaemonZoneView(Zone, daemonZone, daemonRun)",
"ZoneRenderer.LoadDaemonZoneView(Zone, _observedEntityFacadesByDaemonIndex, daemonZone, daemonRun)",
"ZoneRenderer?.ApplyDaemonFrame(daemonZone, run)",
"CreateDaemonEntitySnapshots(runId, daemonZone)",
"FindCurrentDaemonZoneSnapshot()",

View file

@ -67,6 +67,7 @@ public class ActionGameManager : MonoBehaviour
private string _lastAppliedAuthoritativeDaemonRunId = "";
private int _lastAppliedAuthoritativeDaemonZoneIndex = -1;
private readonly Dictionary<string, Entity> _observedEntityFacadesByRecordKey = new Dictionary<string, Entity>(StringComparer.Ordinal);
private readonly Dictionary<int, Entity> _observedEntityFacadesByDaemonIndex = new Dictionary<int, Entity>();
private static DirectoryInfo _gameDataDirectory;
public static DirectoryInfo GameDataDirectory
{
@ -2097,7 +2098,7 @@ public class ActionGameManager : MonoBehaviour
Zone.Log = s => Debug.Log($"Zone: {s}");
ZoneRenderer.LoadDaemonZoneView(Zone, daemonZone, daemonRun);
ZoneRenderer.LoadDaemonZoneView(Zone, _observedEntityFacadesByDaemonIndex, daemonZone, daemonRun);
if (CurrentEntity != null)
{
@ -2708,6 +2709,7 @@ public class ActionGameManager : MonoBehaviour
entity.RestoreThermalExposure((float)entitySnapshot.Heatstroke, (float)entitySnapshot.Hypothermia);
RestoreRuntimeBehaviorStateFromTypedSnapshot(entity, entitySnapshot, _observedEntityFacadesByRecordKey);
}
RebuildObservedEntityFacadeIndex();
foreach (var entity in _observedEntityFacadesByRecordKey.Values)
{
@ -2795,11 +2797,22 @@ public class ActionGameManager : MonoBehaviour
_observedEntityFacadesByRecordKey.Clear();
foreach (var restoredEntity in restoredEntities)
_observedEntityFacadesByRecordKey[restoredEntity.Key] = restoredEntity.Value;
RebuildObservedEntityFacadeIndex();
if (restoredEntities.TryGetValue(currentEntityKey, out var currentEntity))
RestoreCurrentEntityBinding(currentEntity, actionBarBindings);
}
private void RebuildObservedEntityFacadeIndex()
{
_observedEntityFacadesByDaemonIndex.Clear();
foreach (var entity in _observedEntityFacadesByRecordKey.Values)
{
if (entity != null && entity.DaemonEntityIndex >= 0)
_observedEntityFacadesByDaemonIndex[entity.DaemonEntityIndex] = entity;
}
}
private void RestoreChildAndDockingRelationships(
IReadOnlyList<AetheriaRuntimeEntitySnapshot> entitySnapshots,
IReadOnlyDictionary<string, Entity> restoredEntities)
@ -3266,17 +3279,7 @@ public class ActionGameManager : MonoBehaviour
private bool TryGetObservedEntityFacade(int daemonEntityIndex, out Entity entity)
{
foreach (var observedEntity in _observedEntityFacadesByRecordKey.Values)
{
if (observedEntity != null && observedEntity.DaemonEntityIndex == daemonEntityIndex)
{
entity = observedEntity;
return true;
}
}
entity = null;
return false;
return _observedEntityFacadesByDaemonIndex.TryGetValue(daemonEntityIndex, out entity);
}
public void RequestTowToStation()

View file

@ -216,6 +216,7 @@ public class ZoneRenderer : MonoBehaviour
public void LoadDaemonZoneView(
Zone legacyEntityFacadeZone,
IReadOnlyDictionary<int, Entity> observedEntityFacadesByDaemonIndex,
AetheriaRuntimeZoneSnapshotCommit daemonZone = null,
AetheriaRuntimeRunCheckpointCommit daemonRun = null)
{
@ -245,16 +246,11 @@ public class ZoneRenderer : MonoBehaviour
_suns = _bodyViewsByBodyKey.Values.Where(p => p is SunObject).ToArray();
var entitiesByDaemonIndex = new Dictionary<int, Entity>();
foreach (var entity in legacyEntityFacadeZone.Entities)
{
if (entity != null && entity.DaemonEntityIndex >= 0)
entitiesByDaemonIndex[entity.DaemonEntityIndex] = entity;
}
foreach (var entitySnapshot in daemonZone?.Entities ?? Array.Empty<AetheriaRuntimeEntitySnapshotCommit>())
{
if (entitySnapshot != null &&
entitiesByDaemonIndex.TryGetValue(entitySnapshot.EntityIndex, out var entity))
observedEntityFacadesByDaemonIndex != null &&
observedEntityFacadesByDaemonIndex.TryGetValue(entitySnapshot.EntityIndex, out var entity))
{
Debug.Log($"Loading entity {entity.Name} from daemon entity snapshot {entitySnapshot.EntityIndex}");
LoadEntity(entity);