From bd439240cd7743d057d9f2163beede2ad8131cfc Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Sun, 28 Jun 2026 12:34:47 +0100 Subject: [PATCH] Route runtime menu docking reads through observed index --- Aetheria.State.Verify/Program.cs | 22 ++++-- .../AetheriaUnityGameplaySceneWiring.cs | 2 + Assets/Scripts/UI/Menu/MenuPanel.cs | 47 +++++++++--- Assets/Scripts/UI/Menu/TradeMenu.cs | 71 ++++++++++++------- 4 files changed, 98 insertions(+), 44 deletions(-) diff --git a/Aetheria.State.Verify/Program.cs b/Aetheria.State.Verify/Program.cs index 9a4137047..5e3d0caf0 100644 --- a/Aetheria.State.Verify/Program.cs +++ b/Aetheria.State.Verify/Program.cs @@ -4717,9 +4717,10 @@ static void RequireRuntimeMenuTabsUseEveSurface(string root) "AetheriaRuntimeMenuTabsSurfaceBuilder.Project(", "new AetheriaRuntimeMenuTabProjectionOption(", "ResolveVisibleTabs(", - ".ReactiveDockingState()", - ".TryCurrent(", - "ResolveCurrentDocking()?.IsDocked == true", + "SetObservedEntityIndex(AetheriaUnityObservedEntityIndex observedEntityIndex)", + "TryResolveObservedDockingIndex(out var dockingIndex)", + "dockingIndex.TryResolveCurrentDocking(out docking)", + "docking.IsDocked", "AetheriaClient", "AetheriaUnityRuntimeClientProvider.ResolveClient(", "GetTabLabel(", @@ -4791,10 +4792,12 @@ static void RequireRuntimeMenuTabsUseEveSurface(string root) } if (source.Contains("GameManager.IsObservedDocked", StringComparison.Ordinal) || - source.Contains("GameManager.TryGetObservedDockedLocalStory", StringComparison.Ordinal)) + source.Contains("GameManager.TryGetObservedDockedLocalStory", StringComparison.Ordinal) || + source.Contains("AetheriaClientReactiveDockingState _dockingState", StringComparison.Ordinal) || + source.Contains("private AetheriaClientDockingSnapshot ResolveCurrentDocking()", StringComparison.Ordinal)) { throw new InvalidOperationException( - "MenuPanel tab visibility must read typed current-docking state through AetheriaClient instead of ActionGameManager observed adapters."); + "MenuPanel tab visibility must read typed current-docking state through AetheriaUnityObservedDockingIndex instead of direct docking caches or ActionGameManager observed adapters."); } var requiredProjectionBuilderSymbols = new[] @@ -5660,8 +5663,10 @@ static void RequireTradeCargoSelectorUseEveSurface(string root) "AetheriaRuntimeTradeCargoSelectorSurfaceCommands.TryRead(request, out var command)", "AetheriaRuntimeTradeCargoSelectorCommandKind.Close", "AetheriaRuntimeTradeCargoSelectorCommandKind.Select", - ".ReactiveDockingState()", - ".TryCurrent(", + "SetObservedEntityIndex(AetheriaUnityObservedEntityIndex observedEntityIndex)", + "TryResolveObservedDockingIndex(out var dockingIndex)", + "dockingIndex.TryResolveCurrentDocking(out docking)", + "dockingIndex.ResolveStationRefit()", "SetTargetCargo(", "selection.EntityKey", "OwnedQuantity", @@ -5702,6 +5707,9 @@ static void RequireTradeCargoSelectorUseEveSurface(string root) "GameManager.CurrentEntity.Parent.Children", "GameManager.DockingBay", "GameManager.AvailableEntities()", + "AetheriaClientReactiveDockingState _reactiveDockingState", + "AetheriaClientDockingSnapshot _dockingState", + "private AetheriaClientDockingSnapshot ResolveDockingState()", "_cargoSelectorStationRefitEntities", "stationRefit.AvailableEntities ?? Array.Empty()", "stationRefit.StationStock ?? Array.Empty()" diff --git a/Assets/Scripts/Gameplay/AetheriaUnityGameplaySceneWiring.cs b/Assets/Scripts/Gameplay/AetheriaUnityGameplaySceneWiring.cs index 8f76f2af9..10d2b8e4d 100644 --- a/Assets/Scripts/Gameplay/AetheriaUnityGameplaySceneWiring.cs +++ b/Assets/Scripts/Gameplay/AetheriaUnityGameplaySceneWiring.cs @@ -138,6 +138,8 @@ public sealed class AetheriaUnityGameplaySceneWiring public void ConfigureObservedEntityIndex(AetheriaUnityObservedEntityIndex observedEntityIndex) { + Menu?.SetObservedEntityIndex(observedEntityIndex); + TradeMenu?.SetObservedEntityIndex(observedEntityIndex); Inventory?.SetObservedEntityIndex(observedEntityIndex); ShipPanel?.SetObservedEntityIndex(observedEntityIndex); TargetShipPanel?.SetObservedEntityIndex(observedEntityIndex); diff --git a/Assets/Scripts/UI/Menu/MenuPanel.cs b/Assets/Scripts/UI/Menu/MenuPanel.cs index f47185aa0..c071baa8e 100644 --- a/Assets/Scripts/UI/Menu/MenuPanel.cs +++ b/Assets/Scripts/UI/Menu/MenuPanel.cs @@ -31,11 +31,23 @@ public class MenuPanel : MonoBehaviour private MenuTabBinding _current; private UIDocument _tabSurfaceDocument; private readonly AetheriaEveUnitySurfaceChrome _tabSurfaceChrome = new AetheriaEveUnitySurfaceChrome(); + private AetheriaUnityObservedEntityIndex _observedEntityIndex; + private AetheriaUnityObservedDockingIndex _observedDockingIndex; private string _clientStatePath = ""; - private AetheriaClientReactiveDockingState _dockingState; public MenuTab CurrentTab { get; private set; } + public void SetObservedEntityIndex(AetheriaUnityObservedEntityIndex observedEntityIndex) + { + if (!ReferenceEquals(_observedEntityIndex, observedEntityIndex)) + { + _observedDockingIndex?.Dispose(); + _observedDockingIndex = null; + } + + _observedEntityIndex = observedEntityIndex; + } + public void ShowTab(MenuTab tab) { gameObject.SetActive(true); @@ -95,8 +107,8 @@ public class MenuPanel : MonoBehaviour AetheriaEveUnitySurfaceHost.DestroyDocument(_tabSurfaceDocument); _tabSurfaceDocument = null; } - _dockingState?.Dispose(); - _dockingState = null; + _observedDockingIndex?.Dispose(); + _observedDockingIndex = null; } private void RenderTabSurface() @@ -161,7 +173,7 @@ public class MenuPanel : MonoBehaviour private MenuTabBinding[] ResolveVisibleTabs() { - var isDocked = ResolveCurrentDocking()?.IsDocked == true; + var isDocked = TryResolveCurrentDocking(out var docking) && docking.IsDocked; return _tabs.Values .Where(tabBinding => !tabBinding.RequireDock || isDocked) .Where(tabBinding => tabBinding.Tab != MenuTab.Local || isDocked) @@ -169,14 +181,27 @@ public class MenuPanel : MonoBehaviour .ToArray(); } - private AetheriaClientDockingSnapshot ResolveCurrentDocking() + private bool TryResolveCurrentDocking(out AetheriaRuntimeCurrentDockingDocument docking) { - _dockingState ??= ResolveClient().Aetheria().ReactiveDockingState(); - if (_dockingState.TryCurrent(out var docking)) - return docking; + docking = null; + if (TryResolveObservedDockingIndex(out var dockingIndex) && + dockingIndex.TryResolveCurrentDocking(out docking)) + { + return true; + } Debug.LogWarning("Failed to read Aetheria current docking for runtime menu tabs."); - return null; + return false; + } + + private bool TryResolveObservedDockingIndex(out AetheriaUnityObservedDockingIndex dockingIndex) + { + dockingIndex = null; + if (_observedEntityIndex == null) + return false; + + dockingIndex = _observedDockingIndex ??= new AetheriaUnityObservedDockingIndex(ResolveClient, _observedEntityIndex); + return true; } private AetheriaClient ResolveClient() @@ -185,8 +210,8 @@ public class MenuPanel : MonoBehaviour if (!string.Equals(_clientStatePath, stateBoot.StateFilePath, StringComparison.Ordinal)) { _clientStatePath = stateBoot.StateFilePath; - _dockingState?.Dispose(); - _dockingState = null; + _observedDockingIndex?.Dispose(); + _observedDockingIndex = null; } return AetheriaUnityRuntimeClientProvider.ResolveClient(stateBoot, "unity-runtime-menu-tabs"); diff --git a/Assets/Scripts/UI/Menu/TradeMenu.cs b/Assets/Scripts/UI/Menu/TradeMenu.cs index 7f7c0e293..26beccd8c 100644 --- a/Assets/Scripts/UI/Menu/TradeMenu.cs +++ b/Assets/Scripts/UI/Menu/TradeMenu.cs @@ -40,6 +40,8 @@ public class TradeMenu : MonoBehaviour private string _clientStatePath = ""; private CultMeshReactiveDocument _catalog; private CultMeshReactiveDocument _playerSettings; + private AetheriaUnityObservedEntityIndex _observedEntityIndex; + private AetheriaUnityObservedDockingIndex _observedDockingIndex; private readonly AetheriaEveUnitySurfaceChrome _cargoSelectorSurfaceChrome = PanelChrome(360f, 420f, Align.FlexEnd); private readonly AetheriaEveUnitySurfaceChrome _filterSurfaceChrome = PanelChrome(420f, 520f, Align.FlexStart); private readonly AetheriaEveUnitySurfaceChrome _rowActionSurfaceChrome = PanelChrome(320f, 360f, Align.FlexStart); @@ -47,26 +49,36 @@ public class TradeMenu : MonoBehaviour private AetheriaRuntimeTradeCargoSelectorSurfaceProjection _cargoSelectorSurfaceProjection; private AetheriaRuntimeStationCargoTargetRow[] _cargoSelectorStationRefitTargets = Array.Empty(); - private AetheriaClientReactiveDockingState _reactiveDockingState; - private AetheriaClientDockingSnapshot _dockingState; private AetheriaRuntimeStationRefitDocument _stationRefit; private AetheriaRuntimeTradeFilterSurfaceProjection _filterSurfaceProjection; private Action[] _rowActionCallbacks = Array.Empty(); private AetheriaRuntimeTradeRowActionSurfaceProjection _rowActionSurfaceProjection; public EquippedCargoBay Inventory { get; set; } + + public void SetObservedEntityIndex(AetheriaUnityObservedEntityIndex observedEntityIndex) + { + if (!ReferenceEquals(_observedEntityIndex, observedEntityIndex)) + { + _observedDockingIndex?.Dispose(); + _observedDockingIndex = null; + InvalidateStationRefit(); + } + + _observedEntityIndex = observedEntityIndex; + } private void OnEnable() { - var dockingState = ResolveDockingState(); - if (dockingState?.IsDocked != true || - string.IsNullOrWhiteSpace(dockingState.DockParentEntityKey) || - dockingState.DockingBayIndex < 0) + if (!TryResolveCurrentDocking(out var docking) || + docking.IsDocked != true || + string.IsNullOrWhiteSpace(docking.DockParentEntityKey) || + docking.DockingBayIndex < 0) { return; } - SetTargetCargo(dockingState.DockParentEntityKey, dockingState.DockingBayIndex, "Docking Bay"); + SetTargetCargo(docking.DockParentEntityKey, docking.DockingBayIndex, "Docking Bay"); HideCargoSelectorSurface(); HideFilterSurface(); HideRowActionSurface(); @@ -496,14 +508,14 @@ public class TradeMenu : MonoBehaviour private bool TryResolveCurrentDockingTargetEntityKey(out string targetEntityKey) { targetEntityKey = ""; - var dockingState = ResolveDockingState(); - if (dockingState?.IsDocked != true || - string.IsNullOrWhiteSpace(dockingState.DockParentEntityKey)) + if (!TryResolveCurrentDocking(out var docking) || + docking.IsDocked != true || + string.IsNullOrWhiteSpace(docking.DockParentEntityKey)) { return false; } - targetEntityKey = dockingState.DockParentEntityKey; + targetEntityKey = docking.DockParentEntityKey; return true; } @@ -512,29 +524,37 @@ public class TradeMenu : MonoBehaviour if (_stationRefit != null) return _stationRefit; - _stationRefit = ResolveDockingState()?.StationRefit; + _stationRefit = TryResolveObservedDockingIndex(out var dockingIndex) + ? dockingIndex.ResolveStationRefit() + : null; return _stationRefit; } - private AetheriaClientDockingSnapshot ResolveDockingState() + private bool TryResolveCurrentDocking(out AetheriaRuntimeCurrentDockingDocument docking) { - if (_dockingState != null) - return _dockingState; - - _reactiveDockingState ??= ResolveClient().Aetheria().ReactiveDockingState(); - if (!_reactiveDockingState.TryCurrent(out _dockingState)) + docking = null; + if (TryResolveObservedDockingIndex(out var dockingIndex) && + dockingIndex.TryResolveCurrentDocking(out docking)) { - Debug.LogWarning("Failed to read Aetheria docking state for trade menu."); - return null; + return true; } - _stationRefit = _dockingState?.StationRefit; - return _dockingState; + Debug.LogWarning("Failed to read Aetheria docking state for trade menu."); + return false; + } + + private bool TryResolveObservedDockingIndex(out AetheriaUnityObservedDockingIndex dockingIndex) + { + dockingIndex = null; + if (_observedEntityIndex == null) + return false; + + dockingIndex = _observedDockingIndex ??= new AetheriaUnityObservedDockingIndex(ResolveClient, _observedEntityIndex); + return true; } private void InvalidateStationRefit() { - _dockingState = null; _stationRefit = null; } @@ -600,11 +620,10 @@ public class TradeMenu : MonoBehaviour { _catalog?.Dispose(); _playerSettings?.Dispose(); - _reactiveDockingState?.Dispose(); + _observedDockingIndex?.Dispose(); _catalog = null; _playerSettings = null; - _reactiveDockingState = null; - _dockingState = null; + _observedDockingIndex = null; _stationRefit = null; }