From 4a3e5ef4578eae71671bbc050550fa82266ae813 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Mon, 29 Jun 2026 00:55:14 +0100 Subject: [PATCH] Use generic Verse mutable documents --- Aetheria.State.Verify/Program.cs | 40 +++++++-- .../Tests/DaemonRuntimeDocumentTests.cs | 36 ++++++-- .../StarbridgePlayerSeatDocumentTests.cs | 4 +- .../Runtime/AetheriaRuntimeVerseClient.cs | 90 ++----------------- docs/aetheria-verse-client-contract.md | 4 +- 5 files changed, 71 insertions(+), 103 deletions(-) diff --git a/Aetheria.State.Verify/Program.cs b/Aetheria.State.Verify/Program.cs index e8d463050..68e3aa6e0 100644 --- a/Aetheria.State.Verify/Program.cs +++ b/Aetheria.State.Verify/Program.cs @@ -11596,11 +11596,7 @@ static void RequireAetheriaRuntimeVerseClientContract(string root) "AetheriaRuntimeVerseContractRegistry.CreateCultNetRegistry(registry)", "public Observable> WatchRecord(", "WatchRecord", - "CultMeshMutableStatePointer", - "CultMeshMutableStatePointer", - "CultMeshMutableStatePointer", - "CultMeshMutableStatePointer", - "CultMeshMutableStatePointer", + "public CultMeshMutableStatePointer MutableDocument(", "CultMesh.MutableStatePointer(", "CultMesh.CreateCultCacheDocumentRegistry(RuntimeDocumentTypes)", "CultMesh.CreateCultNetDocumentRegistry(RuntimeDocumentTypes, registry)", @@ -11612,7 +11608,6 @@ static void RequireAetheriaRuntimeVerseClientContract(string root) "new CultRecordKey(\"daemon:aetheria.starbridge.session.latest.v1\")", "Document(", "typeof(EveSurfaceState)", - "CultMeshMutableStatePointer", "private AetheriaClientState? _aetheriaState", "private AetheriaRuntimeManagedClientInputs? _managedClientInputs", "_managedClientInputs?.Dispose()", @@ -11676,6 +11671,37 @@ static void RequireAetheriaRuntimeVerseClientContract(string root) string.Join(", ", survivingNamedWatchHelpers)); } + var forbiddenNamedMutablePointers = new[] + { + "ProviderAdvertisement(", + "Health(", + "CommandBoundary(", + "VerseAuthorityPolicy(", + "LatestFrame(", + "LatestSoaView(", + "StarbridgeScenario(", + "StarbridgeSession(", + "StarbridgePlayerSeat(", + "DaemonGameSurface(", + "DaemonGameTuiSurface(", + "DaemonEditorSurface(", + "DaemonEditorTuiSurface(" + }; + var runtimeClientInstanceApi = client.Split( + "public AetheriaClientState Aetheria()", + StringSplitOptions.None).Last().Split( + "public CultMeshDocumentHandle Document(", + StringSplitOptions.None)[0]; + var survivingNamedMutablePointers = forbiddenNamedMutablePointers + .Where(symbol => runtimeClientInstanceApi.Contains(symbol, StringComparison.Ordinal)) + .ToArray(); + if (survivingNamedMutablePointers.Length > 0) + { + throw new InvalidOperationException( + "AetheriaRuntimeVerseClient must expose generic MutableDocument(CultRecordKey) instead of named mutable pointer wrappers: " + + string.Join(", ", survivingNamedMutablePointers)); + } + var requiredManagedInputSymbols = new[] { "internal sealed class AetheriaRuntimeManagedClientInputs : IDisposable", @@ -12016,7 +12042,7 @@ static void RequireAetheriaRuntimeVerseClientContract(string root) { "AetheriaRuntimeVerseClient", "WatchRecord(CultRecordKey)", - "CultMeshMutableStatePointer", + "MutableDocument(CultRecordKey)", "Unity", "Verse records", "EveSurfaceState", diff --git a/Assets/Scripts/Tests/DaemonRuntimeDocumentTests.cs b/Assets/Scripts/Tests/DaemonRuntimeDocumentTests.cs index 9baea3c99..e4c20ef6f 100644 --- a/Assets/Scripts/Tests/DaemonRuntimeDocumentTests.cs +++ b/Assets/Scripts/Tests/DaemonRuntimeDocumentTests.cs @@ -121,7 +121,9 @@ public class DaemonRuntimeDocumentTests .OpenAsync(statePath, "daemon-frame-read-test", startServer: false, pullOnOpen: true) .GetAwaiter() .GetResult(); - var published = client.LatestFrame() + var published = client + .MutableDocument( + AetheriaRuntimeVerseRecordKeys.DaemonFrameLatest) .ReadAsync() .GetAwaiter() .GetResult(); @@ -2041,7 +2043,9 @@ public class DaemonRuntimeDocumentTests .OpenAsync(statePath, "daemon-soa-store-read-test", startServer: false, pullOnOpen: true) .GetAwaiter() .GetResult(); - var published = client.LatestSoaView() + var published = client + .MutableDocument( + AetheriaRuntimeVerseRecordKeys.DaemonSoaViewLatest) .ReadAsync() .GetAwaiter() .GetResult(); @@ -4300,7 +4304,9 @@ public class DaemonRuntimeDocumentTests .OpenAsync(statePath, "daemon-surface-command-test", startServer: false, pullOnOpen: true) .GetAwaiter() .GetResult(); - client.LatestFrame() + client + .MutableDocument( + AetheriaRuntimeVerseRecordKeys.DaemonFrameLatest) .ReplaceAsync(frame) .GetAwaiter() .GetResult(); @@ -4317,7 +4323,9 @@ public class DaemonRuntimeDocumentTests .OpenAsync(statePath, "daemon-soa-view-test", startServer: false, pullOnOpen: true) .GetAwaiter() .GetResult(); - client.LatestSoaView() + client + .MutableDocument( + AetheriaRuntimeVerseRecordKeys.DaemonSoaViewLatest) .ReplaceAsync(soaView) .GetAwaiter() .GetResult(); @@ -4334,19 +4342,27 @@ public class DaemonRuntimeDocumentTests .OpenAsync(statePath, "daemon-surfaces-test", startServer: false, pullOnOpen: true) .GetAwaiter() .GetResult(); - client.DaemonGameSurface() + client + .MutableDocument( + AetheriaRuntimeVerseRecordKeys.DaemonGameSurface) .ReplaceAsync(ToEveSurfaceState(result.GameSurface)) .GetAwaiter() .GetResult(); - client.DaemonGameTuiSurface() + client + .MutableDocument( + AetheriaRuntimeVerseRecordKeys.DaemonGameTuiSurface) .ReplaceAsync(ToEveSurfaceState(result.GameTuiSurface)) .GetAwaiter() .GetResult(); - client.DaemonEditorSurface() + client + .MutableDocument( + AetheriaRuntimeVerseRecordKeys.DaemonEditorSurface) .ReplaceAsync(ToEveSurfaceState(result.EditorSurface)) .GetAwaiter() .GetResult(); - client.DaemonEditorTuiSurface() + client + .MutableDocument( + AetheriaRuntimeVerseRecordKeys.DaemonEditorTuiSurface) .ReplaceAsync(ToEveSurfaceState(result.EditorTuiSurface)) .GetAwaiter() .GetResult(); @@ -4438,7 +4454,9 @@ public class DaemonRuntimeDocumentTests .OpenAsync(statePath, "daemon-authority-policy-test", startServer: false, pullOnOpen: true) .GetAwaiter() .GetResult(); - client.VerseAuthorityPolicy() + client + .MutableDocument( + AetheriaRuntimeVerseRecordKeys.VerseAuthorityPolicy) .ReplaceAsync(policy) .GetAwaiter() .GetResult(); diff --git a/Assets/Scripts/Tests/StarbridgePlayerSeatDocumentTests.cs b/Assets/Scripts/Tests/StarbridgePlayerSeatDocumentTests.cs index 753cdd815..8af2d7336 100644 --- a/Assets/Scripts/Tests/StarbridgePlayerSeatDocumentTests.cs +++ b/Assets/Scripts/Tests/StarbridgePlayerSeatDocumentTests.cs @@ -72,7 +72,9 @@ public class StarbridgePlayerSeatDocumentTests .GetAwaiter() .GetResult(); - client.StarbridgePlayerSeat(seat.SeatId) + client + .MutableDocument( + AetheriaRuntimeVerseRecordKeys.StarbridgePlayerSeat(seat.SeatId)) .ReplaceAsync(seat) .GetAwaiter() .GetResult(); diff --git a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeVerseClient.cs b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeVerseClient.cs index bdd41c995..42a19b8ac 100644 --- a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeVerseClient.cs +++ b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeVerseClient.cs @@ -206,92 +206,14 @@ namespace GameCult.Aetheria.State.Verse return _aetheriaState ??= CreateAetheriaState(); } - public CultMeshMutableStatePointer ProviderAdvertisement() + public CultMeshMutableStatePointer MutableDocument( + CultRecordKey key) + where TDocument : class { ThrowIfDisposed(); - return MutableDocumentPointer( - AetheriaRuntimeVerseRecordKeys.DaemonProviderAdvertisement); - } - - public CultMeshMutableStatePointer Health() - { - ThrowIfDisposed(); - return MutableDocumentPointer( - AetheriaRuntimeVerseRecordKeys.DaemonHealth); - } - - public CultMeshMutableStatePointer CommandBoundary() - { - ThrowIfDisposed(); - return MutableDocumentPointer( - AetheriaRuntimeVerseRecordKeys.DaemonCommandBoundary); - } - - public CultMeshMutableStatePointer VerseAuthorityPolicy() - { - ThrowIfDisposed(); - return MutableDocumentPointer( - AetheriaRuntimeVerseRecordKeys.VerseAuthorityPolicy); - } - - public CultMeshMutableStatePointer LatestFrame() - { - ThrowIfDisposed(); - return MutableDocumentPointer( - AetheriaRuntimeVerseRecordKeys.DaemonFrameLatest); - } - - public CultMeshMutableStatePointer LatestSoaView() - { - ThrowIfDisposed(); - return MutableDocumentPointer( - AetheriaRuntimeVerseRecordKeys.DaemonSoaViewLatest); - } - - public CultMeshMutableStatePointer StarbridgeScenario() - { - ThrowIfDisposed(); - return MutableDocumentPointer( - AetheriaRuntimeVerseRecordKeys.StarbridgeScenarioLatest); - } - - public CultMeshMutableStatePointer StarbridgeSession() - { - ThrowIfDisposed(); - return MutableDocumentPointer( - AetheriaRuntimeVerseRecordKeys.StarbridgeSessionLatest); - } - - public CultMeshMutableStatePointer StarbridgePlayerSeat( - string seatId) - { - ThrowIfDisposed(); - return MutableDocumentPointer( - AetheriaRuntimeVerseRecordKeys.StarbridgePlayerSeat(seatId)); - } - - public CultMeshMutableStatePointer DaemonGameSurface() - { - ThrowIfDisposed(); - return MutableDocumentPointer(AetheriaRuntimeVerseRecordKeys.DaemonGameSurface); - } - - public CultMeshMutableStatePointer DaemonGameTuiSurface() - { - ThrowIfDisposed(); - return MutableDocumentPointer(AetheriaRuntimeVerseRecordKeys.DaemonGameTuiSurface); - } - - public CultMeshMutableStatePointer DaemonEditorSurface() - { - ThrowIfDisposed(); - return MutableDocumentPointer(AetheriaRuntimeVerseRecordKeys.DaemonEditorSurface); - } - - public CultMeshMutableStatePointer DaemonEditorTuiSurface() - { - ThrowIfDisposed(); - return MutableDocumentPointer(AetheriaRuntimeVerseRecordKeys.DaemonEditorTuiSurface); + if (string.IsNullOrWhiteSpace(key.Value)) + throw new ArgumentException("Value must be non-empty.", nameof(key)); + return MutableDocumentPointer(key); } public CultMeshDocumentHandle Document( diff --git a/docs/aetheria-verse-client-contract.md b/docs/aetheria-verse-client-contract.md index ef9b79fb6..c99d23cf8 100644 --- a/docs/aetheria-verse-client-contract.md +++ b/docs/aetheria-verse-client-contract.md @@ -31,9 +31,9 @@ registry and exposes: latest daemon frame, latest SoA view, and daemon game/editor Eve surfaces; - reactive watches via `WatchRecord(CultRecordKey)`, with record identity passed as data instead of one watch helper per document lane; -- `CultMeshMutableStatePointer` handles for transparent reactive POCO +- `MutableDocument(CultRecordKey)` handles for transparent reactive POCO presentation, including read, watch, and replace through shared CultMesh - Verse context semantics; + Verse context semantics, with record identity passed as data; - typed daemon and Eve command submission through the same command record keys used by the daemon.