diff --git a/Aetheria.State.Verify/Program.cs b/Aetheria.State.Verify/Program.cs index c6ef9ae4e..bbb670b13 100644 --- a/Aetheria.State.Verify/Program.cs +++ b/Aetheria.State.Verify/Program.cs @@ -4700,8 +4700,7 @@ static void RequireRuntimeMenuTabsUseEveSurface(string root) "AetheriaRuntimeMenuTabsSurfaceBuilder.Project(", "new AetheriaRuntimeMenuTabProjectionOption(", "ResolveVisibleTabs(", - ".DockingState", - ".Reactive()", + ".ReactiveDockingState()", ".TryCurrent(", "ResolveCurrentDocking()?.IsDocked == true", "AetheriaClient", @@ -4817,8 +4816,7 @@ static void RequireRuntimeMenuTabsUseEveSurface(string root) "AetheriaRuntimeLocalStoryCommandKind.Continue", "AetheriaRuntimeLocalStoryCommandKind.Choose", "new AetheriaRuntimeLocalStoryChoiceState(", - ".DockingState", - ".Reactive()", + ".ReactiveDockingState()", ".TryCurrent(", "unity-runtime-local-story" }; @@ -4937,8 +4935,7 @@ static void RequireInventoryShipSettingsUseEveSurface(string root) "RequestEntityShutdownPerformance(", "latestCurrentEntity.EntityKey", "(float)latestCurrentEntity.ShutdownPerformance", - ".DockingState", - ".Reactive()", + ".ReactiveDockingState()", ".TryCurrent(", "?.CurrentEntity" }; @@ -5649,8 +5646,7 @@ static void RequireTradeCargoSelectorUseEveSurface(string root) "AetheriaRuntimeTradeCargoSelectorSurfaceCommands.TryRead(request, out var command)", "AetheriaRuntimeTradeCargoSelectorCommandKind.Close", "AetheriaRuntimeTradeCargoSelectorCommandKind.Select", - ".DockingState", - ".Reactive()", + ".ReactiveDockingState()", ".TryCurrent(", "SetTargetCargo(", "selection.EntityKey", @@ -6210,8 +6206,7 @@ static void RequireInventoryDropdownUseEveSurface(string root) "_observedEntityIndex.TryResolveEntityByRecordKey", "TryResolveObservedDockingIndex(out var dockingIndex)", "dockingIndex.TryResolveCurrentDockingBay(out var resolvedDockingBay)", - ".DockingState", - ".Reactive()", + ".ReactiveDockingState()", ".TryCurrent(", "LoadoutRestoreOptions" }; @@ -6284,8 +6279,7 @@ static void RequireInventoryDropdownUseEveSurface(string root) if (!inventoryMenu.Contains("TryResolveCurrentEntity(out var currentEntity)", StringComparison.Ordinal) || !inventoryMenu.Contains("TryResolveCurrentDockingBay(out var dockingBay)", StringComparison.Ordinal) || - !inventoryMenu.Contains(".DockingState", StringComparison.Ordinal) || - !inventoryMenu.Contains(".Reactive()", StringComparison.Ordinal) || + !inventoryMenu.Contains(".ReactiveDockingState()", StringComparison.Ordinal) || !inventoryMenu.Contains(".TryCurrent(", StringComparison.Ordinal) || !inventoryMenu.Contains("TryResolveObservedDockingIndex(out var dockingIndex)", StringComparison.Ordinal) || !inventoryMenu.Contains("dockingIndex.TryResolveCurrentDockingBay(out var resolvedDockingBay)", StringComparison.Ordinal) || @@ -6946,6 +6940,8 @@ static void RequireMenuDockingUsesManagedTypedSnapshot(string root) var clientState = File.ReadAllText(clientStatePath); var requiredClientSymbols = new[] { + "public AetheriaClientDockingSnapshot LatestDockingState()", + "public AetheriaClientReactiveDockingState ReactiveDockingState(", "public AetheriaClientReactiveDockingState Reactive(", "public sealed class AetheriaClientReactiveDockingState : IDisposable", "CultMeshReactiveDocument", @@ -6995,8 +6991,9 @@ static void RequireMenuDockingUsesManagedTypedSnapshot(string root) Compact = CompactSource(entry.Source) }) .Where(entry => - !entry.Source.Contains(".DockingState.Reactive()", StringComparison.Ordinal) || + !entry.Source.Contains(".ReactiveDockingState()", StringComparison.Ordinal) || !entry.Source.Contains(".TryCurrent(", StringComparison.Ordinal) || + entry.Source.Contains(".DockingState.Reactive()", StringComparison.Ordinal) || entry.Compact.Contains(CompactSource(".DockingState.Latest()"), StringComparison.Ordinal) || entry.Compact.Contains(CompactSource(".DockingState.TryLatest("), StringComparison.Ordinal)) .Select(entry => Path.GetRelativePath(root, entry.Path)) @@ -7005,7 +7002,7 @@ static void RequireMenuDockingUsesManagedTypedSnapshot(string root) if (offenders.Length > 0) { throw new InvalidOperationException( - "Unity menu docking state must read through AetheriaClientDockingState.Reactive instead of latest wrappers: " + + "Unity menu docking state must read through AetheriaClientState.ReactiveDockingState instead of nested latest/reactive wrappers: " + string.Join(", ", offenders)); } @@ -7598,6 +7595,10 @@ static void RequireAetheriaManagedStateAccessorsCoverDomainDocuments(string root { "public AetheriaRuntimeDaemonFrameDocument LatestDaemonFrame()", "public AetheriaRuntimeDaemonSoaViewDocument LatestDaemonSoaView()", + "public AetheriaClientDockingSnapshot LatestDockingState()", + "public AetheriaClientReactiveDockingState ReactiveDockingState(", + "public AetheriaRuntimeObservedDaemonState? LatestObservedDaemon()", + "public AetheriaRuntimeReactiveObservedDaemonState ReactiveObservedDaemon(", "public AetheriaRuntimeReactiveLoadoutSnapshotProjector ReactiveLoadoutSnapshotProjector(", "public AetheriaRuntimeLoadoutTemplatesDocument LatestLoadoutTemplates()", "public AetheriaRuntimeStationRefitDocument LatestStationRefit()", @@ -7641,8 +7642,7 @@ static void RequireAetheriaManagedStateAccessorsCoverDomainDocuments(string root var observedDaemonState = File.ReadAllText(observedDaemonStatePath); var requiredObservedSymbols = new[] { - ".ReactiveObservedDaemonAsync()", - "return observed.Current;" + "return await state.LatestObservedDaemonAsync().ConfigureAwait(false);" }; var missingObservedSymbols = requiredObservedSymbols .Where(symbol => !observedDaemonState.Contains(symbol, StringComparison.Ordinal)) @@ -7650,12 +7650,13 @@ static void RequireAetheriaManagedStateAccessorsCoverDomainDocuments(string root if (missingObservedSymbols.Length > 0) { throw new InvalidOperationException( - "Observed daemon state must read managed typed daemon documents through named AetheriaClientState accessors: " + + "Observed daemon state compatibility reads must delegate to named AetheriaClientState accessors: " + string.Join(", ", missingObservedSymbols)); } if (observedDaemonState.Contains("state.LatestDaemonFrameAsync()", StringComparison.Ordinal) || observedDaemonState.Contains("state.LatestDaemonSoaViewAsync()", StringComparison.Ordinal) || + observedDaemonState.Contains("state.ReactiveObservedDaemonAsync()", StringComparison.Ordinal) || observedDaemonState.Contains("TryReadLatestSoaViewAsync", StringComparison.Ordinal)) { throw new InvalidOperationException( @@ -7677,6 +7678,9 @@ static void RequireAetheriaManagedStateAccessorsCoverDomainDocuments(string root ".Aetheria().Details.Zone(", ".Aetheria().Details.Inventory(", ".Aetheria().Starbridge.PlayerSeat(", + ".Aetheria().DockingState.Latest(", + ".Aetheria().DockingState.Reactive(", + "AetheriaRuntimeObservedDaemonState.ReadAsync(", ".State.Daemon.LatestFrame.LatestAsync()", ".State.Daemon.LatestSoaView.LatestAsync()", ".State.Daemon.AuthorityPolicy.LatestAsync()", @@ -12088,8 +12092,7 @@ static void RequireMainMenuContinueRunState(string root) { "public sealed class AetheriaUnityObservedDockingIndex", ".Aetheria()", - ".DockingState", - ".Reactive()", + ".ReactiveDockingState()", ".TryCurrent(", "public bool IsEntityUndocked(Entity entity)", "public bool TryResolveDockingBay(", @@ -14864,8 +14867,7 @@ static void RequireRuntimeStateReaderOwnsUnityStateAcquisition(string root) { "public static async Task ReadAsync(", "AetheriaClientState state", - ".ReactiveObservedDaemonAsync()", - "return observed.Current;", + "return await state.LatestObservedDaemonAsync().ConfigureAwait(false);", "AetheriaRuntimeDaemonSoaViewIndex.Build(soaView)", "public sealed class AetheriaRuntimeReactiveObservedDaemonState", "public static async Task CreateAsync(", @@ -16828,7 +16830,7 @@ static void RequireDockedCurrentShipRequestAuthority(string root) } if (!inventoryPanel.Contains("TryResolveCurrentEntityKey(out var currentEntityKey)", StringComparison.Ordinal) || - !inventoryPanel.Contains(".DockingState", StringComparison.Ordinal) || + !inventoryPanel.Contains(".ReactiveDockingState()", StringComparison.Ordinal) || !inventoryPanel.Contains("snapshot?.CurrentEntityKey", StringComparison.Ordinal) || inventoryPanel.Contains("GameManager.CurrentEntity", StringComparison.Ordinal)) { diff --git a/Assets/Scripts/Gameplay/AetheriaUnityObservedDockingIndex.cs b/Assets/Scripts/Gameplay/AetheriaUnityObservedDockingIndex.cs index c224e3c62..c3f6ded7c 100644 --- a/Assets/Scripts/Gameplay/AetheriaUnityObservedDockingIndex.cs +++ b/Assets/Scripts/Gameplay/AetheriaUnityObservedDockingIndex.cs @@ -164,7 +164,7 @@ public sealed class AetheriaUnityObservedDockingIndex : IDisposable snapshot = null; try { - _dockingState ??= _resolveClient()?.Aetheria().DockingState.Reactive(); + _dockingState ??= _resolveClient()?.Aetheria().ReactiveDockingState(); return _dockingState?.TryCurrent(out snapshot) == true; } catch diff --git a/Assets/Scripts/Tests/DaemonRuntimeDocumentTests.cs b/Assets/Scripts/Tests/DaemonRuntimeDocumentTests.cs index 4d78f35d2..8fbdd62f7 100644 --- a/Assets/Scripts/Tests/DaemonRuntimeDocumentTests.cs +++ b/Assets/Scripts/Tests/DaemonRuntimeDocumentTests.cs @@ -203,19 +203,15 @@ public class DaemonRuntimeDocumentTests .GetResult(); using var zoneRenderReactive = client.State .Reactive(); - var observed = AetheriaRuntimeObservedDaemonState - .ReadAsync(client.State) - .GetAwaiter() - .GetResult(); + var observed = client.State.LatestObservedDaemon(); var observedAuthoritativeFrame = client.State.Daemon.LatestFrameDocument(); var gameSurface = client.State.Daemon.LatestGameSurface(); var gameTuiSurface = client.State.Daemon.LatestGameTuiSurface(); var editorSurface = client.State.Daemon.LatestEditorSurface(); var editorTuiSurface = client.State.Daemon.LatestEditorTuiSurface(); var authorityStatus = client.State.Daemon.LatestAuthorityPolicy(); - var dockingState = client.Aetheria() - .DockingState - .Latest(); + var dockingState = client.State.LatestDockingState(); + using var reactiveDockingState = client.State.ReactiveDockingState(); Assert.AreEqual("aetheria.current.entity", client.State.Current.Entity.DocumentId); Assert.AreSame(client.State.Current.Entity, client.State.Document()); @@ -296,6 +292,7 @@ public class DaemonRuntimeDocumentTests Assert.AreEqual(currentEntity.EntityKey, currentEntityByType.EntityKey); Assert.AreEqual(currentEntity.EntityKey, currentEntityFromClientType.EntityKey); Assert.AreEqual(currentEntity.EntityKey, dockingState.CurrentEntityKey); + Assert.AreEqual(currentEntity.EntityKey, reactiveDockingState.Current.CurrentEntityKey); Assert.AreEqual("", dockingState.DockParentEntityKey); Assert.AreEqual(-1, dockingState.DockingBayIndex); Assert.IsTrue(client.State.Current.Entity.Sources.Any(source => @@ -2163,10 +2160,7 @@ public class DaemonRuntimeDocumentTests .OpenAsync(statePath, "unity-observer-test", pullOnOpen: true) .GetAwaiter() .GetResult(); - var observed = AetheriaRuntimeObservedDaemonState - .ReadAsync(client.State) - .GetAwaiter() - .GetResult(); + var observed = client.State.LatestObservedDaemon(); Assert.IsNotNull(observed); Assert.IsTrue(observed.IsAuthoritative); @@ -2257,10 +2251,7 @@ public class DaemonRuntimeDocumentTests .OpenAsync(statePath, "unity-frame-only-observer-test", pullOnOpen: true) .GetAwaiter() .GetResult(); - var observed = AetheriaRuntimeObservedDaemonState - .ReadAsync(client.State) - .GetAwaiter() - .GetResult(); + var observed = client.State.LatestObservedDaemon(); Assert.IsNotNull(observed); Assert.IsTrue(observed.IsAuthoritative); diff --git a/Assets/Scripts/UI/Menu/InventoryMenu.cs b/Assets/Scripts/UI/Menu/InventoryMenu.cs index 8b15cd32b..9cf6df51e 100644 --- a/Assets/Scripts/UI/Menu/InventoryMenu.cs +++ b/Assets/Scripts/UI/Menu/InventoryMenu.cs @@ -781,7 +781,7 @@ public class InventoryMenu : MonoBehaviour private AetheriaClientDockingSnapshot ResolveDockingState() { - _reactiveDockingState ??= ResolveClient().Aetheria().DockingState.Reactive(); + _reactiveDockingState ??= ResolveClient().Aetheria().ReactiveDockingState(); if (_reactiveDockingState.TryCurrent(out var docking)) return docking; diff --git a/Assets/Scripts/UI/Menu/InventoryPanel.cs b/Assets/Scripts/UI/Menu/InventoryPanel.cs index 1784eaa33..d6b5c7e80 100644 --- a/Assets/Scripts/UI/Menu/InventoryPanel.cs +++ b/Assets/Scripts/UI/Menu/InventoryPanel.cs @@ -1167,7 +1167,7 @@ private void Update() private AetheriaClientDockingSnapshot ResolveDockingState() { - _reactiveDockingState ??= ResolveClient().Aetheria().DockingState.Reactive(); + _reactiveDockingState ??= ResolveClient().Aetheria().ReactiveDockingState(); if (_reactiveDockingState.TryCurrent(out var docking)) return docking; diff --git a/Assets/Scripts/UI/Menu/LocalMenu.cs b/Assets/Scripts/UI/Menu/LocalMenu.cs index f6216fc3e..b99f331ef 100644 --- a/Assets/Scripts/UI/Menu/LocalMenu.cs +++ b/Assets/Scripts/UI/Menu/LocalMenu.cs @@ -205,7 +205,7 @@ public class LocalMenu : MonoBehaviour private bool TryResolveDockingState(out AetheriaClientDockingSnapshot dockingState) { - _dockingState ??= ResolveClient().Aetheria().DockingState.Reactive(); + _dockingState ??= ResolveClient().Aetheria().ReactiveDockingState(); var resolved = _dockingState.TryCurrent(out dockingState); if (!resolved) Debug.LogWarning("Failed to read Aetheria docking state for local story surface."); diff --git a/Assets/Scripts/UI/Menu/MenuPanel.cs b/Assets/Scripts/UI/Menu/MenuPanel.cs index 9adcd7244..f47185aa0 100644 --- a/Assets/Scripts/UI/Menu/MenuPanel.cs +++ b/Assets/Scripts/UI/Menu/MenuPanel.cs @@ -171,7 +171,7 @@ public class MenuPanel : MonoBehaviour private AetheriaClientDockingSnapshot ResolveCurrentDocking() { - _dockingState ??= ResolveClient().Aetheria().DockingState.Reactive(); + _dockingState ??= ResolveClient().Aetheria().ReactiveDockingState(); if (_dockingState.TryCurrent(out var docking)) return docking; diff --git a/Assets/Scripts/UI/Menu/TradeMenu.cs b/Assets/Scripts/UI/Menu/TradeMenu.cs index eb1a8d5ed..0f438d04b 100644 --- a/Assets/Scripts/UI/Menu/TradeMenu.cs +++ b/Assets/Scripts/UI/Menu/TradeMenu.cs @@ -541,7 +541,7 @@ public class TradeMenu : MonoBehaviour if (_dockingState != null) return _dockingState; - _reactiveDockingState ??= ResolveClient().Aetheria().DockingState.Reactive(); + _reactiveDockingState ??= ResolveClient().Aetheria().ReactiveDockingState(); if (!_reactiveDockingState.TryCurrent(out _dockingState)) { Debug.LogWarning("Failed to read Aetheria docking state for trade menu."); diff --git a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaClientState.cs b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaClientState.cs index c62fd7bed..b349409f0 100644 --- a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaClientState.cs +++ b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaClientState.cs @@ -221,6 +221,28 @@ namespace GameCult.Aetheria.State.Verse return LatestDaemonSoaViewAsync().ConfigureAwait(false).GetAwaiter().GetResult(); } + public Task LatestDockingStateAsync() + { + return DockingState.LatestAsync(); + } + + public AetheriaClientDockingSnapshot LatestDockingState() + { + return LatestDockingStateAsync().ConfigureAwait(false).GetAwaiter().GetResult(); + } + + public Task ReactiveDockingStateAsync( + CultMeshReactiveDocumentOptions? options = null) + { + return DockingState.ReactiveAsync(options); + } + + public AetheriaClientReactiveDockingState ReactiveDockingState( + CultMeshReactiveDocumentOptions? options = null) + { + return ReactiveDockingStateAsync(options).ConfigureAwait(false).GetAwaiter().GetResult(); + } + public Task ReactiveLoadoutSnapshotProjectorAsync( CultMeshReactiveDocumentOptions? options = null) { @@ -245,6 +267,17 @@ namespace GameCult.Aetheria.State.Verse return ReactiveObservedDaemonAsync(options).ConfigureAwait(false).GetAwaiter().GetResult(); } + public async Task LatestObservedDaemonAsync() + { + using var observed = await ReactiveObservedDaemonAsync().ConfigureAwait(false); + return observed.Current; + } + + public AetheriaRuntimeObservedDaemonState? LatestObservedDaemon() + { + return LatestObservedDaemonAsync().ConfigureAwait(false).GetAwaiter().GetResult(); + } + public Task LatestLoadoutTemplatesAsync() { return LoadoutTemplates.LatestAsync(); diff --git a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeObservedDaemonState.cs b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeObservedDaemonState.cs index bf68c0eeb..71182d4f9 100644 --- a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeObservedDaemonState.cs +++ b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeObservedDaemonState.cs @@ -33,10 +33,7 @@ namespace GameCult.Aetheria.State.Verse { if (state == null) throw new ArgumentNullException(nameof(state)); - using var observed = await state - .ReactiveObservedDaemonAsync() - .ConfigureAwait(false); - return observed.Current; + return await state.LatestObservedDaemonAsync().ConfigureAwait(false); } }