diff --git a/Aetheria.State.Verify/Program.cs b/Aetheria.State.Verify/Program.cs index 54e4a4a20..0acaa5d04 100644 --- a/Aetheria.State.Verify/Program.cs +++ b/Aetheria.State.Verify/Program.cs @@ -2437,7 +2437,7 @@ static void RequireDaemonRenderQueryAuthority(string root) "beltPose.InstancePoses ?? Array.Empty()", "private void RefreshDaemonContactRows()", ".Aetheria()", - ".LatestZoneContacts()", + ".ReactiveZoneContacts()", "private void RefreshDaemonCompassMarkers()", "private void RefreshDaemonVisibleEntityInstances()", "PowerPulse(", @@ -7305,9 +7305,13 @@ static void RequireUnitySharedDocumentAccessorErgonomics(string root) var requiredZoneRendererSharedDocumentSymbols = new[] { "CultMeshReactiveDocument _catalog", + "CultMeshReactiveDocument _zoneContacts", "ResolveClient().Aetheria().ReactiveCatalog()", + "ResolveClient().Aetheria().ReactiveZoneContacts()", "_catalog?.Dispose()", + "_zoneContacts?.Dispose()", "_catalog?.Current", + "_zoneContacts.Current", "private void OnDestroy()" }; var missingZoneRendererSharedDocumentSymbols = requiredZoneRendererSharedDocumentSymbols @@ -7316,7 +7320,7 @@ static void RequireUnitySharedDocumentAccessorErgonomics(string root) if (missingZoneRendererSharedDocumentSymbols.Length > 0) { throw new InvalidOperationException( - "ZoneRenderer should bind catalog state through the managed reactive Aetheria catalog document with renderer lifetime disposal: " + + "ZoneRenderer should bind catalog and contact state through managed reactive Aetheria documents with renderer lifetime disposal: " + string.Join(", ", missingZoneRendererSharedDocumentSymbols)); } @@ -11810,7 +11814,8 @@ static void RequireMainMenuContinueRunState(string root) var requiredObservedTargetQuerySymbols = new[] { - "public sealed class AetheriaUnityObservedTargetQuery", + "public sealed class AetheriaUnityObservedTargetQuery : IDisposable", + "CultMeshReactiveDocument _zoneContacts", "public Entity GetObservedTarget(Entity observer)", "public float GetObservedInfoGathered(Entity observer, Entity target)", "public bool IsObservedHostileContact(Entity observer, Entity target)", @@ -11820,7 +11825,9 @@ static void RequireMainMenuContinueRunState(string root) "AetheriaRuntimeZoneContactRow", "AetheriaRuntimeZoneTargetRow", ".Aetheria()", - ".LatestZoneContacts()", + ".ReactiveZoneContacts()", + "_zoneContacts?.Current", + "_zoneContacts?.Dispose()", "_entityIndex.TryResolveEntityByDaemonIndex(targetEntityIndex, out var targetEntity)" }; var missingObservedTargetQuerySymbols = requiredObservedTargetQuerySymbols @@ -12771,7 +12778,8 @@ static void RequireUnityObserverDoesNotTickLocalSimulation(string root) var requiredObservedTargetQuerySymbols = new[] { - "public sealed class AetheriaUnityObservedTargetQuery", + "public sealed class AetheriaUnityObservedTargetQuery : IDisposable", + "CultMeshReactiveDocument _zoneContacts", "public Entity GetObservedTarget(Entity observer)", "public float GetObservedInfoGathered(Entity observer, Entity target)", "public bool IsObservedHostileContact(Entity observer, Entity target)", @@ -12781,7 +12789,9 @@ static void RequireUnityObserverDoesNotTickLocalSimulation(string root) "AetheriaRuntimeZoneContactRow", "AetheriaRuntimeZoneTargetRow", ".Aetheria()", - ".LatestZoneContacts()", + ".ReactiveZoneContacts()", + "_zoneContacts?.Current", + "_zoneContacts?.Dispose()", "_entityIndex.TryResolveEntityByDaemonIndex(targetEntityIndex, out var targetEntity)" }; var missingObservedTargetQuerySymbols = requiredObservedTargetQuerySymbols diff --git a/Assets/Scripts/Gameplay/ActionGameManager.cs b/Assets/Scripts/Gameplay/ActionGameManager.cs index fb08ecd30..8e085b4b9 100644 --- a/Assets/Scripts/Gameplay/ActionGameManager.cs +++ b/Assets/Scripts/Gameplay/ActionGameManager.cs @@ -312,6 +312,8 @@ public class ActionGameManager : MonoBehaviour private void OnDisable() { _gameplayInputShell?.Dispose(); + _observedTargetQuery?.Dispose(); + _observedTargetQuery = null; AetheriaUnityRuntimeClientProvider.Dispose(); } diff --git a/Assets/Scripts/Gameplay/AetheriaUnityObservedTargetQuery.cs b/Assets/Scripts/Gameplay/AetheriaUnityObservedTargetQuery.cs index b35c90732..6b4309c51 100644 --- a/Assets/Scripts/Gameplay/AetheriaUnityObservedTargetQuery.cs +++ b/Assets/Scripts/Gameplay/AetheriaUnityObservedTargetQuery.cs @@ -4,12 +4,14 @@ using System; using System.Linq; +using GameCult.Mesh; using GameCult.Aetheria.State.Verse; -public sealed class AetheriaUnityObservedTargetQuery +public sealed class AetheriaUnityObservedTargetQuery : IDisposable { private readonly Func _resolveClient; private readonly AetheriaUnityObservedEntityIndex _entityIndex; + private CultMeshReactiveDocument _zoneContacts; public AetheriaUnityObservedTargetQuery( Func resolveClient, @@ -91,15 +93,25 @@ public sealed class AetheriaUnityObservedTargetQuery private AetheriaRuntimeZoneContactsDocument ReadZoneContacts() { + if (_zoneContacts != null) + return _zoneContacts.Current; + try { - return _resolveClient() + _zoneContacts = _resolveClient() ?.Aetheria() - .LatestZoneContacts(); + .ReactiveZoneContacts(); + return _zoneContacts?.Current; } catch { return null; } } + + public void Dispose() + { + _zoneContacts?.Dispose(); + _zoneContacts = null; + } } diff --git a/Assets/Scripts/Zone Display/ZoneRenderer.cs b/Assets/Scripts/Zone Display/ZoneRenderer.cs index e1043806f..a20f0e923 100644 --- a/Assets/Scripts/Zone Display/ZoneRenderer.cs +++ b/Assets/Scripts/Zone Display/ZoneRenderer.cs @@ -121,6 +121,7 @@ public class ZoneRenderer : MonoBehaviour Array.Empty(); private string _clientStatePath = ""; private CultMeshReactiveDocument _catalog; + private CultMeshReactiveDocument _zoneContacts; public Dictionary WormholeInstances = new Dictionary(); private List _loot = new List(); @@ -985,9 +986,7 @@ public class ZoneRenderer : MonoBehaviour _daemonContactRows.Clear(); try { - var contacts = ResolveClient() - .Aetheria() - .LatestZoneContacts(); + var contacts = ResolveZoneContacts(); foreach (var target in contacts?.Targets ?? Array.Empty()) { if (target != null && target.EntityIndex >= 0) @@ -1230,6 +1229,23 @@ public class ZoneRenderer : MonoBehaviour return _catalog?.Current; } + private AetheriaRuntimeZoneContactsDocument ResolveZoneContacts() + { + if (_zoneContacts != null) + return _zoneContacts.Current; + + try + { + _zoneContacts = ResolveClient().Aetheria().ReactiveZoneContacts(); + } + catch (Exception ex) + { + Debug.LogWarning($"Failed to bind Aetheria zone contacts for renderer target distances: {ex.Message}"); + } + + return _zoneContacts?.Current; + } + private AetheriaClient ResolveClient() { var stateBoot = AetheriaRuntimeStateBoot.Inspect(AetheriaUnityRuntimePaths.GameDataDirectory); @@ -1247,7 +1263,9 @@ public class ZoneRenderer : MonoBehaviour private void ClearClientCaches() { _catalog?.Dispose(); + _zoneContacts?.Dispose(); _catalog = null; + _zoneContacts = null; } }