From c7050c17f8566a75f4c250286d2f6c29689b968a Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Sun, 28 Jun 2026 12:39:17 +0100 Subject: [PATCH] Read observed docking from typed reactive documents --- Aetheria.State.Verify/Program.cs | 30 ++++-- .../AetheriaUnityObservedDockingIndex.cs | 96 ++++++++++++------- 2 files changed, 82 insertions(+), 44 deletions(-) diff --git a/Aetheria.State.Verify/Program.cs b/Aetheria.State.Verify/Program.cs index 5e3d0caf0..b0468bcca 100644 --- a/Aetheria.State.Verify/Program.cs +++ b/Aetheria.State.Verify/Program.cs @@ -7079,7 +7079,7 @@ static void RequireMenuDockingUsesManagedTypedSnapshot(string root) if (offenders.Length > 0) { throw new InvalidOperationException( - "Unity menu docking state must read through AetheriaClientState.ReactiveDockingState instead of nested latest/reactive wrappers: " + + "Unity menu docking state must read managed typed docking documents instead of nested latest/reactive wrappers: " + string.Join(", ", offenders)); } @@ -7088,16 +7088,23 @@ static void RequireMenuDockingUsesManagedTypedSnapshot(string root) static bool HasManagedDockingSnapshotAccess(string source) { - if (source.Contains(".ReactiveDockingState()", StringComparison.Ordinal) && - source.Contains(".TryCurrent(", StringComparison.Ordinal)) + if (source.Contains("AetheriaUnityObservedDockingIndex", StringComparison.Ordinal) && + source.Contains("TryResolveObservedDockingIndex(out var dockingIndex)", StringComparison.Ordinal) && + source.Contains("dockingIndex.TryResolveCurrent", StringComparison.Ordinal) && + !source.Contains("AetheriaClientReactiveDockingState _reactiveDockingState", StringComparison.Ordinal)) { return true; } - return source.Contains("AetheriaUnityObservedDockingIndex", StringComparison.Ordinal) && - source.Contains("TryResolveObservedDockingIndex(out var dockingIndex)", StringComparison.Ordinal) && - source.Contains("dockingIndex.TryResolveCurrent", StringComparison.Ordinal) && - !source.Contains("AetheriaClientReactiveDockingState _reactiveDockingState", StringComparison.Ordinal); + return source.Contains("public sealed class AetheriaUnityObservedDockingIndex", StringComparison.Ordinal) && + source.Contains("CultMeshReactiveDocument _currentEntity", StringComparison.Ordinal) && + source.Contains("CultMeshReactiveDocument _currentDocking", StringComparison.Ordinal) && + source.Contains("CultMeshReactiveDocument _stationRefit", StringComparison.Ordinal) && + source.Contains("state.ReactiveEntity()", StringComparison.Ordinal) && + source.Contains("state.ReactiveDocking()", StringComparison.Ordinal) && + source.Contains("state.ReactiveStationRefit()", StringComparison.Ordinal) && + !source.Contains("AetheriaClientReactiveDockingState _dockingState", StringComparison.Ordinal) && + !source.Contains(".ReactiveDockingState()", StringComparison.Ordinal); } static void RequireUnitySharedDocumentAccessorErgonomics(string root) @@ -12314,9 +12321,12 @@ static void RequireMainMenuContinueRunState(string root) var requiredObservedDockingSymbols = new[] { "public sealed class AetheriaUnityObservedDockingIndex", - ".Aetheria()", - ".ReactiveDockingState()", - ".TryCurrent(", + "CultMeshReactiveDocument _currentEntity", + "CultMeshReactiveDocument _currentDocking", + "CultMeshReactiveDocument _stationRefit", + "state.ReactiveEntity()", + "state.ReactiveDocking()", + "state.ReactiveStationRefit()", "public bool IsEntityUndocked(Entity entity)", "public bool TryResolveDockingBay(", "out AetheriaRuntimeCurrentDockingDocument docking", diff --git a/Assets/Scripts/Gameplay/AetheriaUnityObservedDockingIndex.cs b/Assets/Scripts/Gameplay/AetheriaUnityObservedDockingIndex.cs index c3f6ded7c..ff34fbd4f 100644 --- a/Assets/Scripts/Gameplay/AetheriaUnityObservedDockingIndex.cs +++ b/Assets/Scripts/Gameplay/AetheriaUnityObservedDockingIndex.cs @@ -3,13 +3,17 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ using System; +using System.Linq; +using GameCult.Mesh; using GameCult.Aetheria.State.Verse; public sealed class AetheriaUnityObservedDockingIndex : IDisposable { private readonly Func _resolveClient; private readonly AetheriaUnityObservedEntityIndex _observedEntityIndex; - private AetheriaClientReactiveDockingState _dockingState; + private CultMeshReactiveDocument _currentEntity; + private CultMeshReactiveDocument _currentDocking; + private CultMeshReactiveDocument _stationRefit; public AetheriaUnityObservedDockingIndex( Func resolveClient, @@ -35,52 +39,67 @@ public sealed class AetheriaUnityObservedDockingIndex : IDisposable public bool TryResolveCurrentEntity(out Entity entity) { entity = null; - return TryResolveCurrentDockingSnapshot(out var snapshot) && - !string.IsNullOrWhiteSpace(snapshot.CurrentEntityKey) && - _observedEntityIndex.TryResolveEntityByRecordKey(snapshot.CurrentEntityKey, out entity); + return TryResolveCurrentEntityKey(out var currentEntityKey) && + _observedEntityIndex.TryResolveEntityByRecordKey(currentEntityKey, out entity); } public bool TryResolveCurrentEntityKey(out string currentEntityKey) { - currentEntityKey = TryResolveCurrentDockingSnapshot(out var snapshot) - ? snapshot.CurrentEntityKey - : ""; + currentEntityKey = ""; + if (TryResolveCurrentEntityDocument(out var currentEntity)) + currentEntityKey = currentEntity.EntityKey ?? ""; + if (string.IsNullOrWhiteSpace(currentEntityKey) && + TryResolveCurrentDocking(out var docking)) + { + currentEntityKey = docking.CurrentEntityKey ?? ""; + } + return !string.IsNullOrWhiteSpace(currentEntityKey); } public bool TryResolveCurrentEntityDocument(out AetheriaRuntimeCurrentEntityDocument currentEntity) { - currentEntity = TryResolveCurrentDockingSnapshot(out var snapshot) - ? snapshot.CurrentEntity - : null; + currentEntity = null; + if (!TryResolveReactiveDocuments()) + return false; + + currentEntity = _currentEntity?.Current; return currentEntity != null; } public AetheriaRuntimeStationRefitDocument ResolveStationRefit() { - return TryResolveCurrentDockingSnapshot(out var snapshot) - ? snapshot.StationRefit - : null; + if (!TryResolveReactiveDocuments()) + return null; + + return _stationRefit?.Current; } public bool TryResolveCurrentDockingBayRow(out AetheriaRuntimeStationDockingBayRow dockingBay) { - dockingBay = TryResolveCurrentDockingSnapshot(out var snapshot) - ? snapshot.CurrentDockingBay - : null; + dockingBay = null; + var refit = ResolveStationRefit(); + if (refit?.IsDocked != true || + refit.DockingBayIndex < 0) + { + return false; + } + + dockingBay = (refit.DockingBays ?? Array.Empty()) + .FirstOrDefault(row => row != null && row.DockingBayIndex == refit.DockingBayIndex); return dockingBay != null; } public bool TryResolveCurrentDockingBay(out EquippedDockingBay dockingBay) { dockingBay = null; - if (!TryResolveCurrentDockingSnapshot(out var snapshot) || - snapshot.CurrentDockingBay == null || - string.IsNullOrWhiteSpace(snapshot.DockParentEntityKey) || - snapshot.DockingBayIndex < 0 || + var refit = ResolveStationRefit(); + if (!TryResolveCurrentDockingBayRow(out _) || + string.IsNullOrWhiteSpace(refit?.DockParentEntityKey) || + refit.DockingBayIndex < 0 || !_observedEntityIndex.TryResolveDockingBayByRecordKey( - snapshot.DockParentEntityKey, - snapshot.DockingBayIndex, + refit.DockParentEntityKey, + refit.DockingBayIndex, out dockingBay)) { return false; @@ -91,9 +110,11 @@ public sealed class AetheriaUnityObservedDockingIndex : IDisposable public bool TryResolveCurrentDocking(out AetheriaRuntimeCurrentDockingDocument docking) { - docking = TryResolveCurrentDockingSnapshot(out var snapshot) - ? snapshot.CurrentDocking - : null; + docking = null; + if (!TryResolveReactiveDocuments()) + return false; + + docking = _currentDocking?.Current; return docking != null; } @@ -139,9 +160,7 @@ public sealed class AetheriaUnityObservedDockingIndex : IDisposable Entity entity, out AetheriaRuntimeCurrentDockingDocument docking) { - docking = TryResolveCurrentDockingSnapshot(out var snapshot) - ? snapshot.CurrentDocking - : null; + TryResolveCurrentDocking(out docking); if (entity == null || docking == null || docking.CurrentEntityIndex != entity.DaemonEntityIndex) @@ -159,13 +178,18 @@ public sealed class AetheriaUnityObservedDockingIndex : IDisposable return true; } - private bool TryResolveCurrentDockingSnapshot(out AetheriaClientDockingSnapshot snapshot) + private bool TryResolveReactiveDocuments() { - snapshot = null; try { - _dockingState ??= _resolveClient()?.Aetheria().ReactiveDockingState(); - return _dockingState?.TryCurrent(out snapshot) == true; + var state = _resolveClient()?.Aetheria(); + if (state == null) + return false; + + _currentEntity ??= state.ReactiveEntity(); + _currentDocking ??= state.ReactiveDocking(); + _stationRefit ??= state.ReactiveStationRefit(); + return _currentEntity != null && _currentDocking != null && _stationRefit != null; } catch { @@ -175,7 +199,11 @@ public sealed class AetheriaUnityObservedDockingIndex : IDisposable public void Dispose() { - _dockingState?.Dispose(); - _dockingState = null; + _currentEntity?.Dispose(); + _currentDocking?.Dispose(); + _stationRefit?.Dispose(); + _currentEntity = null; + _currentDocking = null; + _stationRefit = null; } }