From f47b0f2d7d1e5170ebf1048ff1134d4ae338293d Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Mon, 29 Jun 2026 10:31:54 +0100 Subject: [PATCH] Sample inventory menu through current typed access --- Aetheria.State.Verify/Program.cs | 160 ++++++++++++++++-------- Assets/Scripts/UI/Menu/InventoryMenu.cs | 85 ++++--------- 2 files changed, 132 insertions(+), 113 deletions(-) diff --git a/Aetheria.State.Verify/Program.cs b/Aetheria.State.Verify/Program.cs index fe16d2dbe..64be06010 100644 --- a/Aetheria.State.Verify/Program.cs +++ b/Aetheria.State.Verify/Program.cs @@ -5077,7 +5077,8 @@ static void RequireInventoryShipSettingsUseEveSurface(string root) "RequestEntityShutdownPerformance(", "latestCurrentEntity.EntityKey", "(float)latestCurrentEntity.ShutdownPerformance", - "CultMeshReactiveDocument _currentEntity", + ".RuntimeState(\"unity-inventory-menu\")", + ".CurrentEntityState()", "CurrentEntitySnapshot()", "currentEntity = CurrentEntitySnapshot();" }; @@ -6620,7 +6621,7 @@ static void RequireInventoryDropdownUseEveSurface(string root) inventoryMenu.Contains("GameManager.DockingBay", StringComparison.Ordinal)) { throw new InvalidOperationException( - "InventoryMenu must resolve typed current entity/refit state through managed sessions before adapting docking state to Unity objects."); + "InventoryMenu must resolve typed current entity/refit state through managed current documents before adapting docking state to Unity objects."); } var requiredBuilderSymbols = new[] @@ -7254,28 +7255,36 @@ static void RequireInventoryValidationUsesManagedTypedDocuments(string root) foreach (var (name, source) in sources) { var compact = CompactSource(source); + var currentEntityAccess = name == "InventoryMenu.cs" + ? ".RuntimeState(\"unity-inventory-menu\").CurrentEntityState()" + : ".ReactiveCurrentEntity(\"unity-inventory\")"; + var stationRefitAccess = name == "InventoryMenu.cs" + ? ".RuntimeState(\"unity-inventory-menu\").CurrentStationRefit()" + : ".ReactiveStationRefit(\"unity-inventory\")"; + var inventoryAccess = name == "InventoryMenu.cs" + ? ".RuntimeState(\"unity-inventory-menu\").CurrentInventory(entityIndex)" + : ".ReactiveInventory(entityIndex)"; var requiredSymbols = new[] { "CurrentEntitySnapshot()", "StationRefitSnapshot", - "InventorySnapshot(entityIndex)", - "_inventory?.Current" + "InventorySnapshot(entityIndex)" }; var missingSymbols = requiredSymbols .Where(symbol => !source.Contains(symbol, StringComparison.Ordinal)) .ToArray(); - var currentEntityAccess = name == "InventoryMenu.cs" - ? ".ReactiveCurrentEntity(\"unity-inventory-menu\")" - : ".ReactiveCurrentEntity(\"unity-inventory\")"; - var stationRefitAccess = name == "InventoryMenu.cs" - ? ".ReactiveStationRefit(\"unity-inventory-menu\")" - : ".ReactiveStationRefit(\"unity-inventory\")"; var requiredCompactedSymbols = new[] { currentEntityAccess, stationRefitAccess, - ".ReactiveInventory(entityIndex)" + inventoryAccess }; + if (name == "InventoryPanel.cs") + { + missingSymbols = missingSymbols + .Concat(new[] { "_inventory?.Current" }.Where(symbol => !source.Contains(symbol, StringComparison.Ordinal))) + .ToArray(); + } missingSymbols = missingSymbols .Concat(requiredCompactedSymbols.Where(symbol => !compact.Contains(symbol, StringComparison.Ordinal))) .ToArray(); @@ -7312,30 +7321,54 @@ static void RequireInventoryValidationUsesManagedTypedDocuments(string root) $"{name} still routes inventory validation through session wrappers instead of direct managed reactive typed documents."); } - RequireReactiveTypedDocumentAccess( - source, - name, - "AetheriaRuntimeCurrentEntityDocument", - "_currentEntity", - currentEntityAccess, - "AetheriaRuntimeCurrentEntitySession", - ".ObserveEntity()"); - RequireReactiveTypedDocumentAccess( - source, - name, - "AetheriaRuntimeStationRefitDocument", - "_stationRefit", - stationRefitAccess, - "AetheriaRuntimeStationRefitSession", - ".ObserveStationRefit()"); - RequireReactiveTypedDocumentAccess( - source, - name, - "AetheriaRuntimeInventoryDocument", - "_inventory", - ".ReactiveInventory(entityIndex)", - "AetheriaRuntimeInventorySession", - ".ObserveInventory(entityIndex)"); + if (name == "InventoryMenu.cs") + { + var forbiddenMenuSymbols = new[] + { + "CultMeshReactiveDocument<", + ".ReactiveCurrentEntity(\"unity-inventory-menu\")", + ".ReactiveStationRefit(\"unity-inventory-menu\")", + ".ReactiveInventory(entityIndex)", + "_currentEntity?.Dispose()", + "_stationRefit?.Dispose()", + "_inventory?.Dispose()" + } + .Where(symbol => source.Contains(symbol, StringComparison.Ordinal)) + .ToArray(); + if (forbiddenMenuSymbols.Length > 0) + { + throw new InvalidOperationException( + "InventoryMenu should sample inventory validation state through current typed documents instead of owning reactive handles: " + + string.Join(", ", forbiddenMenuSymbols)); + } + } + else + { + RequireReactiveTypedDocumentAccess( + source, + name, + "AetheriaRuntimeCurrentEntityDocument", + "_currentEntity", + currentEntityAccess, + "AetheriaRuntimeCurrentEntitySession", + ".ObserveEntity()"); + RequireReactiveTypedDocumentAccess( + source, + name, + "AetheriaRuntimeStationRefitDocument", + "_stationRefit", + stationRefitAccess, + "AetheriaRuntimeStationRefitSession", + ".ObserveStationRefit()"); + RequireReactiveTypedDocumentAccess( + source, + name, + "AetheriaRuntimeInventoryDocument", + "_inventory", + ".ReactiveInventory(entityIndex)", + "AetheriaRuntimeInventorySession", + ".ObserveInventory(entityIndex)"); + } } Console.WriteLine("Inventory validation: cargo/equipment checks read managed typed client documents instead of manual handle walks"); @@ -7967,33 +8000,44 @@ static void RequireUnitySharedDocumentAccessorErgonomics(string root) "UI", "Menu", "InventoryMenu.cs")); - var requiredInventoryMenuSharedDocumentSymbols = new[] { "private void OnDestroy()" }; + var compactInventoryMenu = CompactSource(inventoryMenu); + var requiredInventoryMenuSharedDocumentSymbols = new[] + { + ".RuntimeState(\"unity-inventory-menu\").CurrentCatalog()", + ".RuntimeState(\"unity-inventory-menu\").CurrentPlayerSettings()", + "private void OnDestroy()" + }; var missingInventoryMenuSharedDocumentSymbols = requiredInventoryMenuSharedDocumentSymbols - .Where(symbol => !inventoryMenu.Contains(symbol, StringComparison.Ordinal)) + .Where(symbol => !compactInventoryMenu.Contains(symbol, StringComparison.Ordinal) && + !inventoryMenu.Contains(symbol, StringComparison.Ordinal)) .ToArray(); if (missingInventoryMenuSharedDocumentSymbols.Length > 0) { throw new InvalidOperationException( - "InventoryMenu should bind shared catalog/settings through managed reactive Aetheria documents with menu lifetime disposal: " + + "InventoryMenu should sample shared catalog/settings through named current typed Aetheria documents: " + string.Join(", ", missingInventoryMenuSharedDocumentSymbols)); } - RequireReactiveTypedDocumentAccess( - inventoryMenu, - "InventoryMenu", - "AetheriaRuntimeCatalogSnapshot", - "_catalog", + var forbiddenInventoryMenuSharedDocumentSymbols = new[] + { + "CultMeshReactiveDocument<", ".ReactiveCatalogSnapshot(\"unity-inventory-menu\")", - "AetheriaRuntimeCatalogSession", - "ResolveClient().State.ObserveCatalog()"); - RequireReactiveTypedDocumentAccess( - inventoryMenu, - "InventoryMenu", - "AetheriaRuntimePlayerSettingsDocument", - "_playerSettings", ".ReactivePlayerSettingsDocument(\"unity-inventory-menu\")", + "AetheriaRuntimeCatalogSession", "AetheriaRuntimePlayerSettingsSession", - ".ObservePlayer()"); + "ResolveClient().State.ObserveCatalog()", + ".ObservePlayer()", + "_catalog?.Dispose()", + "_playerSettings?.Dispose()" + } + .Where(symbol => inventoryMenu.Contains(symbol, StringComparison.Ordinal)) + .ToArray(); + if (forbiddenInventoryMenuSharedDocumentSymbols.Length > 0) + { + throw new InvalidOperationException( + "InventoryMenu still routes catalog/settings through wrapper/session/reactive handles instead of current typed documents: " + + string.Join(", ", forbiddenInventoryMenuSharedDocumentSymbols)); + } var inventoryPanel = File.ReadAllText(Path.Combine( root, @@ -17925,7 +17969,6 @@ static void RequireInventoryDoubleClickTransferRequestAuthority(string root) "TryResolveTypedInventoryRows(", "TryValidateTypedCargoSlot(", "TryValidateTypedEquipmentSlot(", - ".ReactiveInventory(entityIndex)", "origin.Cargo.TryGetValue(item, out var originPosition)", "SourceIndex == cargoIndex", "SourceIndex == equipmentIndex", @@ -17945,6 +17988,19 @@ static void RequireInventoryDoubleClickTransferRequestAuthority(string root) "Inventory cargo/equipment submissions must validate Unity inventory items against typed inventory document slot identity: " + string.Join(", ", missingTypedSlotValidationSymbols)); } + var requiredMenuInventoryAccess = ".CurrentInventory(entityIndex)"; + var requiredPanelInventoryAccess = ".ReactiveInventory(entityIndex)"; + if (!inventoryMenu.Contains(requiredMenuInventoryAccess, StringComparison.Ordinal) || + !inventoryPanel.Contains(requiredPanelInventoryAccess, StringComparison.Ordinal)) + { + throw new InvalidOperationException( + "Inventory cargo/equipment submissions must read typed inventory slot identity through the appropriate managed document access: " + + string.Join(", ", new[] + { + inventoryMenu.Contains(requiredMenuInventoryAccess, StringComparison.Ordinal) ? null : requiredMenuInventoryAccess, + inventoryPanel.Contains(requiredPanelInventoryAccess, StringComparison.Ordinal) ? null : requiredPanelInventoryAccess + }.Where(symbol => symbol != null))); + } var forbiddenUnknownOriginSymbols = new[] { "int.MinValue" }; var unknownOriginHits = new[] { inventoryMenuPath, inventoryPanelPath } diff --git a/Assets/Scripts/UI/Menu/InventoryMenu.cs b/Assets/Scripts/UI/Menu/InventoryMenu.cs index 4ba0238e3..64a9e5b28 100644 --- a/Assets/Scripts/UI/Menu/InventoryMenu.cs +++ b/Assets/Scripts/UI/Menu/InventoryMenu.cs @@ -9,7 +9,6 @@ using System.Linq; using GameCult.Aetheria.EveRuntime; using GameCult.Aetheria.State.Verse; using GameCult.Eve.Surface; -using GameCult.Mesh; using UnityEngine; using UniRx; using UniRx.Triggers; @@ -31,12 +30,6 @@ public class InventoryMenu : MonoBehaviour private UIDocument _shipSettingsSurfaceDocument; private UIDocument _cargoItemDetailsSurfaceDocument; private UIDocument _equippedItemDetailsSurfaceDocument; - private CultMeshReactiveDocument _catalog; - private CultMeshReactiveDocument _playerSettings; - private CultMeshReactiveDocument _currentEntity; - private CultMeshReactiveDocument _stationRefit; - private int _inventoryEntityIndex = -1; - private CultMeshReactiveDocument _inventory; private AetheriaUnityActionBarPresentation _actionBarPresentation; private AetheriaUnityObservedEntityIndex _observedEntityIndex; private AetheriaUnityObservedDockingIndex _observedDockingIndex; @@ -903,76 +896,52 @@ public class InventoryMenu : MonoBehaviour private void ClearClientCaches() { - _catalog?.Dispose(); - _playerSettings?.Dispose(); - _currentEntity?.Dispose(); - _stationRefit?.Dispose(); - _inventory?.Dispose(); - _catalog = null; - _playerSettings = null; - _currentEntity = null; - _stationRefit = null; _observedDockingIndex = null; - _inventory = null; - _inventoryEntityIndex = -1; } private AetheriaRuntimeCurrentEntityDocument CurrentEntitySnapshot() { - if (_currentEntity != null) - return _currentEntity.Current; - try { - _currentEntity = AetheriaUnityRuntimeClientProvider - .ReactiveCurrentEntity("unity-inventory-menu"); + return AetheriaUnityRuntimeClientProvider + .RuntimeState("unity-inventory-menu") + .CurrentEntityState(); } catch (Exception ex) { - Debug.LogWarning($"Failed to bind Aetheria current entity for inventory menu: {ex.Message}"); + Debug.LogWarning($"Failed to read Aetheria current entity for inventory menu: {ex.Message}"); + return null; } - - return _currentEntity?.Current; } private AetheriaRuntimeStationRefitDocument StationRefitSnapshot() { - if (_stationRefit != null) - return _stationRefit.Current; - try { - _stationRefit = AetheriaUnityRuntimeClientProvider - .ReactiveStationRefit("unity-inventory-menu"); + return AetheriaUnityRuntimeClientProvider + .RuntimeState("unity-inventory-menu") + .CurrentStationRefit(); } catch (Exception ex) { - Debug.LogWarning($"Failed to bind Aetheria station refit for inventory menu: {ex.Message}"); + Debug.LogWarning($"Failed to read Aetheria station refit for inventory menu: {ex.Message}"); + return null; } - - return _stationRefit?.Current; } private AetheriaRuntimeInventoryDocument InventorySnapshot(int entityIndex) { - if (_inventory != null && _inventoryEntityIndex == entityIndex) - return _inventory.Current; - try { - var nextInventory = AetheriaUnityRuntimeClientProvider + return AetheriaUnityRuntimeClientProvider .RuntimeState("unity-inventory-menu") - .ReactiveInventory(entityIndex); - _inventory?.Dispose(); - _inventoryEntityIndex = entityIndex; - _inventory = nextInventory; + .CurrentInventory(entityIndex); } catch (Exception ex) { - Debug.LogWarning($"Failed to bind Aetheria typed inventory document for entity {entityIndex}: {ex.Message}"); + Debug.LogWarning($"Failed to read Aetheria typed inventory document for entity {entityIndex}: {ex.Message}"); + return null; } - - return _inventory?.Current; } void Update() @@ -1029,38 +998,32 @@ public class InventoryMenu : MonoBehaviour private AetheriaRuntimeCatalogSnapshot CatalogSnapshot() { - if (_catalog != null) - return _catalog.Current; - try { - _catalog = AetheriaUnityRuntimeClientProvider - .ReactiveCatalogSnapshot("unity-inventory-menu"); + return AetheriaUnityRuntimeClientProvider + .RuntimeState("unity-inventory-menu") + .CurrentCatalog(); } catch (Exception ex) { - Debug.LogWarning($"Failed to bind Aetheria runtime catalog for inventory menu: {ex.Message}"); + Debug.LogWarning($"Failed to read Aetheria runtime catalog for inventory menu: {ex.Message}"); + return null; } - - return _catalog?.Current; } private AetheriaRuntimePlayerSettingsDocument PlayerSettingsSnapshot() { - if (_playerSettings != null) - return _playerSettings.Current; - try { - _playerSettings = AetheriaUnityRuntimeClientProvider - .ReactivePlayerSettingsDocument("unity-inventory-menu"); + return AetheriaUnityRuntimeClientProvider + .RuntimeState("unity-inventory-menu") + .CurrentPlayerSettings(); } catch (Exception ex) { - Debug.LogWarning($"Failed to bind Aetheria player settings for inventory menu: {ex.Message}"); + Debug.LogWarning($"Failed to read Aetheria player settings for inventory menu: {ex.Message}"); + return null; } - - return _playerSettings?.Current; } private float ResolveDefaultShutdownPerformance()