diff --git a/Aetheria.State.Verify/Program.cs b/Aetheria.State.Verify/Program.cs index 8eed67244..2dd183a89 100644 --- a/Aetheria.State.Verify/Program.cs +++ b/Aetheria.State.Verify/Program.cs @@ -6951,11 +6951,12 @@ static void RequireInventoryValidationUsesManagedTypedDocuments(string root) } var clientState = File.ReadAllText(clientStatePath); - if (!clientState.Contains("public Task> ReactiveInventoryAsync(", StringComparison.Ordinal) || - !clientState.Contains("public CultMeshReactiveDocument ReactiveInventory(", StringComparison.Ordinal)) + if (!clientState.Contains("public AetheriaRuntimeCurrentEntitySession ObserveEntity(", StringComparison.Ordinal) || + !clientState.Contains("public AetheriaRuntimeStationRefitSession ObserveStationRefit(", StringComparison.Ordinal) || + !clientState.Contains("public AetheriaRuntimeInventorySession ObserveInventory(", StringComparison.Ordinal)) { throw new InvalidOperationException( - "AetheriaClientDetailState must expose managed reactive typed access for indexed inventory documents."); + "AetheriaClientState must expose managed session access for current entity, station refit, and indexed inventory documents."); } var sources = new Dictionary @@ -6969,11 +6970,11 @@ static void RequireInventoryValidationUsesManagedTypedDocuments(string root) var requiredSymbols = new[] { "ResolveCurrentEntity()", - ".ReactiveEntity()", - "ResolveReactiveStationRefit()", - ".ReactiveStationRefit()", + ".ObserveEntity()", + "ResolveStationRefitDocument()", + ".ObserveStationRefit()", "ResolveInventory(entityIndex)", - ".ReactiveInventory(entityIndex)", + ".ObserveInventory(entityIndex)", "_inventory?.Current" }; var missingSymbols = requiredSymbols @@ -6988,6 +6989,12 @@ static void RequireInventoryValidationUsesManagedTypedDocuments(string root) var forbiddenCompactedSymbols = new[] { + "CultMeshReactiveDocument", + "CultMeshReactiveDocument", + "CultMeshReactiveDocument", + ".ReactiveEntity()", + ".ReactiveStationRefit()", + ".ReactiveInventory(entityIndex)", ".Latest()", ".Latest()", ".Details.LatestInventory(entityIndex)", @@ -7028,7 +7035,8 @@ static void RequireMenuDockingUsesManagedTypedSnapshot(string root) "public CultMeshDocumentHandle StationRefit { get; }", "public CultMeshDocumentHandle Docking { get; }", "public CultMeshReactiveDocument ReactiveDocking(", - "public CultMeshReactiveDocument ReactiveStationRefit(" + "public CultMeshReactiveDocument ReactiveStationRefit(", + "public AetheriaRuntimeStationRefitSession ObserveStationRefit(" }; var missingClientSymbols = requiredClientSymbols .Where(symbol => !clientState.Contains(symbol, StringComparison.Ordinal)) @@ -7534,11 +7542,11 @@ static void RequireUnitySharedDocumentAccessorErgonomics(string root) "InventoryMenu.cs")); var requiredInventoryMenuSharedDocumentSymbols = new[] { - "CultMeshReactiveDocument _catalog", - "CultMeshReactiveDocument _playerSettings", - "ResolveClient().State.ReactiveCatalog()", + "AetheriaRuntimeCatalogSession _catalog", + "AetheriaRuntimePlayerSettingsSession _playerSettings", + "ResolveClient().State.ObserveCatalog()", ".Settings", - ".ReactivePlayer()", + ".ObservePlayer()", "_catalog?.Dispose()", "_playerSettings?.Dispose()", "_catalog?.Current", @@ -7555,6 +7563,23 @@ static void RequireUnitySharedDocumentAccessorErgonomics(string root) string.Join(", ", missingInventoryMenuSharedDocumentSymbols)); } + var forbiddenInventoryMenuSharedDocumentSymbols = new[] + { + "CultMeshReactiveDocument _catalog", + "CultMeshReactiveDocument _playerSettings", + "ResolveClient().State.ReactiveCatalog()", + ".ReactivePlayer()" + }; + var inventoryMenuRawDocumentHits = forbiddenInventoryMenuSharedDocumentSymbols + .Where(symbol => inventoryMenu.Contains(symbol, StringComparison.Ordinal)) + .ToArray(); + if (inventoryMenuRawDocumentHits.Length > 0) + { + throw new InvalidOperationException( + "InventoryMenu still owns raw catalog/settings CultMesh documents instead of managed sessions: " + + string.Join(", ", inventoryMenuRawDocumentHits)); + } + var inventoryPanel = File.ReadAllText(Path.Combine( root, "Assets", @@ -7564,11 +7589,11 @@ static void RequireUnitySharedDocumentAccessorErgonomics(string root) "InventoryPanel.cs")); var requiredInventoryPanelSharedDocumentSymbols = new[] { - "CultMeshReactiveDocument _catalog", - "CultMeshReactiveDocument _playerSettings", - "ResolveClient().State.ReactiveCatalog()", + "AetheriaRuntimeCatalogSession _catalog", + "AetheriaRuntimePlayerSettingsSession _playerSettings", + "ResolveClient().State.ObserveCatalog()", ".Settings", - ".ReactivePlayer()", + ".ObservePlayer()", "_catalog?.Dispose()", "_playerSettings?.Dispose()", "_catalog?.Current", @@ -7585,6 +7610,23 @@ static void RequireUnitySharedDocumentAccessorErgonomics(string root) string.Join(", ", missingInventoryPanelSharedDocumentSymbols)); } + var forbiddenInventoryPanelSharedDocumentSymbols = new[] + { + "CultMeshReactiveDocument _catalog", + "CultMeshReactiveDocument _playerSettings", + "ResolveClient().State.ReactiveCatalog()", + ".ReactivePlayer()" + }; + var inventoryPanelRawDocumentHits = forbiddenInventoryPanelSharedDocumentSymbols + .Where(symbol => inventoryPanel.Contains(symbol, StringComparison.Ordinal)) + .ToArray(); + if (inventoryPanelRawDocumentHits.Length > 0) + { + throw new InvalidOperationException( + "InventoryPanel still owns raw catalog/settings CultMesh documents instead of managed sessions: " + + string.Join(", ", inventoryPanelRawDocumentHits)); + } + var sectorRenderer = File.ReadAllText(Path.Combine( root, "Assets", @@ -16475,7 +16517,7 @@ static void RequireInventoryDoubleClickTransferRequestAuthority(string root) "TryValidateTypedCargoSlot(", "TryValidateTypedEquipmentSlot(", ".Details", - ".ReactiveInventory(entityIndex)", + ".ObserveInventory(entityIndex)", "origin.Cargo.TryGetValue(item, out var originPosition)", "SourceIndex == cargoIndex", "SourceIndex == equipmentIndex", @@ -17030,10 +17072,10 @@ static void RequireInventoryLoadoutSaveRequestAuthority(string root) { "RequestLoadoutTemplateSave(Entity entity)", "TryResolveEntityRecordKey(entity, out var targetEntityKey)", - "CultMeshReactiveDocument _loadoutFrame", + "AetheriaRuntimeDaemonFrameSession _loadoutFrame", "ProjectLoadoutTemplate(targetEntityKey)", "AetheriaRuntimeLoadoutSnapshotProjector.ProjectLoadoutTemplate(", - ".ReactiveDaemonFrame()", + ".ObserveDaemonFrame()", "_loadoutFrame?.Dispose()", ".Ui.SaveLoadoutTemplateAsync(loadout, \"unity-inventory\")" }; @@ -17047,6 +17089,13 @@ static void RequireInventoryLoadoutSaveRequestAuthority(string root) string.Join(", ", missingInventoryPanelSymbols)); } + if (inventoryPanel.Contains("CultMeshReactiveDocument _loadoutFrame", StringComparison.Ordinal) || + inventoryPanel.Contains(".ReactiveDaemonFrame()", StringComparison.Ordinal)) + { + throw new InvalidOperationException( + "InventoryPanel still owns a raw daemon-frame CultMesh document instead of AetheriaRuntimeDaemonFrameSession."); + } + if (inventoryPanel.Contains(".LoadoutTemplateAsync(", StringComparison.Ordinal) || inventoryPanel.Contains(".ProjectLoadoutTemplateAsync(client.State, targetEntityKey)", StringComparison.Ordinal) || inventoryPanel.Contains("AetheriaRuntimeReactiveLoadoutSnapshotProjector", StringComparison.Ordinal) || diff --git a/Assets/Scripts/Tests/DaemonRuntimeDocumentTests.cs b/Assets/Scripts/Tests/DaemonRuntimeDocumentTests.cs index 6d2613238..4337e8c39 100644 --- a/Assets/Scripts/Tests/DaemonRuntimeDocumentTests.cs +++ b/Assets/Scripts/Tests/DaemonRuntimeDocumentTests.cs @@ -206,12 +206,16 @@ public class DaemonRuntimeDocumentTests var observed = client.State.LatestObservedDaemon(); var observedAuthoritativeFrame = client.State.LatestDaemonFrame(); using var catalogSession = client.State.ObserveCatalog(); + using var daemonFrameSession = client.State.ObserveDaemonFrame(); using var sectorMapSession = client.State.ObserveSectorMap(); using var playerSettingsSession = client.State.Settings.ObservePlayer(); using var verseHostSettingsSession = client.State.Settings.ObserveVerseHost(); using var zoneContactsSession = client.State.ObserveZoneContacts(); using var currentZoneSession = client.State.Current.ObserveZone(); + using var currentEntitySession = client.State.Current.ObserveEntity(); + using var stationRefitSession = client.State.ObserveStationRefit(); using var zoneDetailsSession = client.State.Details.ObserveZone(0); + using var inventorySession = client.State.Details.ObserveInventory(0); using var objectsViewportSession = client.State.Viewports.ObserveObjects(viewport); using var renderSplatsViewportSession = client.State.Viewports.ObserveRenderSplats(viewport); using var playerHud = client.State.ObservePlayerHud(); diff --git a/Assets/Scripts/UI/Menu/InventoryMenu.cs b/Assets/Scripts/UI/Menu/InventoryMenu.cs index e80ec50a5..2432e43c1 100644 --- a/Assets/Scripts/UI/Menu/InventoryMenu.cs +++ b/Assets/Scripts/UI/Menu/InventoryMenu.cs @@ -6,7 +6,6 @@ using System; using System.Collections.Generic; using System.Globalization; using System.Linq; -using GameCult.Mesh; using GameCult.Aetheria.EveRuntime; using GameCult.Aetheria.State.Verse; using GameCult.Eve.Surface; @@ -32,12 +31,12 @@ public class InventoryMenu : MonoBehaviour private UIDocument _cargoItemDetailsSurfaceDocument; private UIDocument _equippedItemDetailsSurfaceDocument; private string _clientStatePath = ""; - private CultMeshReactiveDocument _catalog; - private CultMeshReactiveDocument _playerSettings; - private CultMeshReactiveDocument _currentEntity; - private CultMeshReactiveDocument _stationRefit; + private AetheriaRuntimeCatalogSession _catalog; + private AetheriaRuntimePlayerSettingsSession _playerSettings; + private AetheriaRuntimeCurrentEntitySession _currentEntity; + private AetheriaRuntimeStationRefitSession _stationRefit; private int _inventoryEntityIndex = -1; - private CultMeshReactiveDocument _inventory; + private AetheriaRuntimeInventorySession _inventory; private AetheriaUnityActionBarPresentation _actionBarPresentation; private AetheriaUnityObservedEntityIndex _observedEntityIndex; private AetheriaUnityObservedDockingIndex _observedDockingIndex; @@ -831,7 +830,7 @@ public class InventoryMenu : MonoBehaviour return true; } - var refit = ResolveReactiveStationRefit(); + var refit = ResolveStationRefitDocument(); var entityIndex = -1; if (refit != null) { @@ -960,7 +959,7 @@ public class InventoryMenu : MonoBehaviour _currentEntity = ResolveClient() .State .Current - .ReactiveEntity(); + .ObserveEntity(); } catch (Exception ex) { @@ -970,7 +969,7 @@ public class InventoryMenu : MonoBehaviour return _currentEntity?.Current; } - private AetheriaRuntimeStationRefitDocument ResolveReactiveStationRefit() + private AetheriaRuntimeStationRefitDocument ResolveStationRefitDocument() { if (_stationRefit != null) return _stationRefit.Current; @@ -979,7 +978,7 @@ public class InventoryMenu : MonoBehaviour { _stationRefit = ResolveClient() .State - .ReactiveStationRefit(); + .ObserveStationRefit(); } catch (Exception ex) { @@ -999,7 +998,7 @@ public class InventoryMenu : MonoBehaviour var nextInventory = ResolveClient() .State .Details - .ReactiveInventory(entityIndex); + .ObserveInventory(entityIndex); _inventory?.Dispose(); _inventoryEntityIndex = entityIndex; _inventory = nextInventory; @@ -1071,7 +1070,7 @@ public class InventoryMenu : MonoBehaviour try { - _catalog = ResolveClient().State.ReactiveCatalog(); + _catalog = ResolveClient().State.ObserveCatalog(); } catch (Exception ex) { @@ -1091,7 +1090,7 @@ public class InventoryMenu : MonoBehaviour _playerSettings = ResolveClient() .State .Settings - .ReactivePlayer(); + .ObservePlayer(); } catch (Exception ex) { diff --git a/Assets/Scripts/UI/Menu/InventoryPanel.cs b/Assets/Scripts/UI/Menu/InventoryPanel.cs index 37a3a1992..82560960b 100644 --- a/Assets/Scripts/UI/Menu/InventoryPanel.cs +++ b/Assets/Scripts/UI/Menu/InventoryPanel.cs @@ -7,7 +7,6 @@ using System.Collections; using System.Collections.Generic; using System.Globalization; using System.Linq; -using GameCult.Mesh; using GameCult.Aetheria.EveRuntime; using GameCult.Aetheria.State.Verse; using GameCult.Eve.Surface; @@ -103,13 +102,13 @@ public class InventoryPanel : MonoBehaviour, IPointerClickHandler private InventoryCell _clickCell; private float _clickTime; private string _clientStatePath = ""; - private CultMeshReactiveDocument _catalog; - private CultMeshReactiveDocument _playerSettings; - private CultMeshReactiveDocument _currentEntity; - private CultMeshReactiveDocument _stationRefit; - private CultMeshReactiveDocument _loadoutFrame; + private AetheriaRuntimeCatalogSession _catalog; + private AetheriaRuntimePlayerSettingsSession _playerSettings; + private AetheriaRuntimeCurrentEntitySession _currentEntity; + private AetheriaRuntimeStationRefitSession _stationRefit; + private AetheriaRuntimeDaemonFrameSession _loadoutFrame; private int _inventoryEntityIndex = -1; - private CultMeshReactiveDocument _inventory; + private AetheriaRuntimeInventorySession _inventory; private AetheriaRuntimeStationRefitEntityOption[] _dropdownStationRefitEntities = Array.Empty(); private AetheriaRuntimeStationLoadoutRestoreOption[] _dropdownStationRefitLoadouts = @@ -1243,7 +1242,7 @@ private void Update() return true; } - var refit = ResolveReactiveStationRefit(); + var refit = ResolveStationRefitDocument(); var entityIndex = -1; if (refit != null) { @@ -1498,7 +1497,7 @@ private void Update() _currentEntity = ResolveClient() .State .Current - .ReactiveEntity(); + .ObserveEntity(); } catch (Exception ex) { @@ -1508,7 +1507,7 @@ private void Update() return _currentEntity?.Current; } - private AetheriaRuntimeStationRefitDocument ResolveReactiveStationRefit() + private AetheriaRuntimeStationRefitDocument ResolveStationRefitDocument() { if (_stationRefit != null) return _stationRefit.Current; @@ -1517,7 +1516,7 @@ private void Update() { _stationRefit = ResolveClient() .State - .ReactiveStationRefit(); + .ObserveStationRefit(); } catch (Exception ex) { @@ -1544,7 +1543,7 @@ private void Update() { _loadoutFrame = ResolveClient() .State - .ReactiveDaemonFrame(); + .ObserveDaemonFrame(); } catch (Exception ex) { @@ -1564,7 +1563,7 @@ private void Update() var nextInventory = ResolveClient() .State .Details - .ReactiveInventory(entityIndex); + .ObserveInventory(entityIndex); _inventory?.Dispose(); _inventoryEntityIndex = entityIndex; _inventory = nextInventory; @@ -1584,7 +1583,7 @@ private void Update() try { - _catalog = ResolveClient().State.ReactiveCatalog(); + _catalog = ResolveClient().State.ObserveCatalog(); } catch (Exception ex) { @@ -1604,7 +1603,7 @@ private void Update() _playerSettings = ResolveClient() .State .Settings - .ReactivePlayer(); + .ObservePlayer(); } catch (Exception ex) { diff --git a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaClientState.cs b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaClientState.cs index 452d04dbc..523099269 100644 --- a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaClientState.cs +++ b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaClientState.cs @@ -227,6 +227,12 @@ namespace GameCult.Aetheria.State.Verse return LatestFrame.Reactive(options); } + public AetheriaRuntimeDaemonFrameSession ObserveDaemonFrame( + CultMeshReactiveDocumentOptions? options = null) + { + return new AetheriaRuntimeDaemonFrameSession(ReactiveDaemonFrame(options)); + } + public Task LatestDaemonSoaViewAsync() { return LatestSoaView.LatestAsync(); @@ -582,6 +588,12 @@ namespace GameCult.Aetheria.State.Verse return StationRefit.Reactive(options); } + public AetheriaRuntimeStationRefitSession ObserveStationRefit( + CultMeshReactiveDocumentOptions? options = null) + { + return new AetheriaRuntimeStationRefitSession(ReactiveStationRefit(options)); + } + public Task LatestZoneRenderAsync() { return ZoneRender.LatestAsync(); @@ -920,6 +932,12 @@ namespace GameCult.Aetheria.State.Verse return Entity.Reactive(options); } + public AetheriaRuntimeCurrentEntitySession ObserveEntity( + CultMeshReactiveDocumentOptions? options = null) + { + return new AetheriaRuntimeCurrentEntitySession(ReactiveEntity(options)); + } + public Task> ReactiveDockingAsync( CultMeshReactiveDocumentOptions? options = null) { @@ -1263,6 +1281,13 @@ namespace GameCult.Aetheria.State.Verse { return Inventory(entityIndex).Reactive(options); } + + public AetheriaRuntimeInventorySession ObserveInventory( + int entityIndex, + CultMeshReactiveDocumentOptions? options = null) + { + return new AetheriaRuntimeInventorySession(ReactiveInventory(entityIndex, options)); + } } public sealed class AetheriaClientStarbridgeState diff --git a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeStateSessions.cs b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeStateSessions.cs index 4cbaedb07..8cc7173a6 100644 --- a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeStateSessions.cs +++ b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeStateSessions.cs @@ -77,6 +77,24 @@ namespace GameCult.Aetheria.State.Verse } } + public sealed class AetheriaRuntimeDaemonFrameSession : IDisposable + { + private readonly CultMeshReactiveDocument _daemonFrame; + + public AetheriaRuntimeDaemonFrameSession( + CultMeshReactiveDocument daemonFrame) + { + _daemonFrame = daemonFrame ?? throw new ArgumentNullException(nameof(daemonFrame)); + } + + public AetheriaRuntimeDaemonFrameDocument? Current => _daemonFrame.Current; + + public void Dispose() + { + _daemonFrame.Dispose(); + } + } + public sealed class AetheriaRuntimeZoneContactsSession : IDisposable { private readonly CultMeshReactiveDocument _zoneContacts; @@ -95,6 +113,24 @@ namespace GameCult.Aetheria.State.Verse } } + public sealed class AetheriaRuntimeStationRefitSession : IDisposable + { + private readonly CultMeshReactiveDocument _stationRefit; + + public AetheriaRuntimeStationRefitSession( + CultMeshReactiveDocument stationRefit) + { + _stationRefit = stationRefit ?? throw new ArgumentNullException(nameof(stationRefit)); + } + + public AetheriaRuntimeStationRefitDocument? Current => _stationRefit.Current; + + public void Dispose() + { + _stationRefit.Dispose(); + } + } + public sealed class AetheriaRuntimeCurrentZoneSession : IDisposable { private readonly CultMeshReactiveDocument _currentZone; @@ -113,6 +149,24 @@ namespace GameCult.Aetheria.State.Verse } } + public sealed class AetheriaRuntimeCurrentEntitySession : IDisposable + { + private readonly CultMeshReactiveDocument _currentEntity; + + public AetheriaRuntimeCurrentEntitySession( + CultMeshReactiveDocument currentEntity) + { + _currentEntity = currentEntity ?? throw new ArgumentNullException(nameof(currentEntity)); + } + + public AetheriaRuntimeCurrentEntityDocument? Current => _currentEntity.Current; + + public void Dispose() + { + _currentEntity.Dispose(); + } + } + public sealed class AetheriaRuntimeZoneDetailsSession : IDisposable { private readonly CultMeshReactiveDocument _zoneDetails; @@ -131,6 +185,24 @@ namespace GameCult.Aetheria.State.Verse } } + public sealed class AetheriaRuntimeInventorySession : IDisposable + { + private readonly CultMeshReactiveDocument _inventory; + + public AetheriaRuntimeInventorySession( + CultMeshReactiveDocument inventory) + { + _inventory = inventory ?? throw new ArgumentNullException(nameof(inventory)); + } + + public AetheriaRuntimeInventoryDocument? Current => _inventory.Current; + + public void Dispose() + { + _inventory.Dispose(); + } + } + public sealed class AetheriaRuntimeObjectsViewportSession : IDisposable { private readonly CultMeshReactiveDocument _objectsViewport;