diff --git a/Aetheria.State.Verify/Program.cs b/Aetheria.State.Verify/Program.cs index 721d424b2..4c6acdff6 100644 --- a/Aetheria.State.Verify/Program.cs +++ b/Aetheria.State.Verify/Program.cs @@ -9270,10 +9270,16 @@ static void RequireAetheriaRuntimeVerseClientContract(string root) "WatchLatestSoaViews()", "WatchRecord", "WatchRecord", + "WatchVerseAuthorityPolicies()", "CultMeshMutableStatePointer", + "CultMeshMutableStatePointer", "CultMesh.MutableStatePointer(", "CultMesh.CreateCultCacheDocumentRegistry(RuntimeDocumentTypes)", "CultMesh.CreateCultNetDocumentRegistry(RuntimeDocumentTypes, registry)", + "typeof(AetheriaRuntimeVerseAuthorityPolicyDocument)", + "AetheriaRuntimeVerseRecordKeys.VerseAuthorityPolicy", + "Document(", + "GetVerseAuthorityPolicyAsync()", "typeof(EveSurfaceState)", "GetDaemonGameTuiSurfaceAsync()", "GetDaemonEditorTuiSurfaceAsync()", @@ -9291,6 +9297,7 @@ static void RequireAetheriaRuntimeVerseClientContract(string root) "state.Daemon.LatestSoaView.LatestAsync()", "state.Daemon.Health.LatestAsync()", "state.Daemon.CommandBoundary.LatestAsync()", + "Aetheria().Daemon.AuthorityPolicy.LatestAsync()", "Aetheria().Daemon.ProviderAdvertisement.LatestAsync()", "Aetheria().Daemon.Health.LatestAsync()", "Aetheria().Daemon.CommandBoundary.LatestAsync()", @@ -9367,6 +9374,7 @@ static void RequireAetheriaRuntimeVerseClientContract(string root) "return Database.GetAsync", "return Database.GetAsync", "return Database.GetAsync", + "return Database.GetAsync", "return Database.GetAsync", "return Database.GetAsync", "return Database.GetAsync", @@ -13110,6 +13118,7 @@ static void RequireRuntimeStateReaderOwnsUnityStateAcquisition(string root) "CultMeshDocumentHandle ProviderAdvertisement", "CultMeshDocumentHandle Health", "CultMeshDocumentHandle CommandBoundary", + "CultMeshDocumentHandle AuthorityPolicy", "CultMeshDocumentHandle LatestFrame", "CultMeshDocumentHandle LatestSoaView", "CultMeshDocumentHandle GameSurface", @@ -13132,6 +13141,7 @@ static void RequireRuntimeStateReaderOwnsUnityStateAcquisition(string root) "State.Daemon.LatestFrame.LatestAsync()", "State.Daemon.LatestSoaView.LatestAsync()", "State.Daemon.Health.LatestAsync()", + "State.Daemon.AuthorityPolicy.LatestAsync()", "State.Daemon.GameSurface.LatestAsync()", "State.Daemon.GameTuiSurface.LatestAsync()", "State.Daemon.EditorSurface.LatestAsync()", @@ -13154,7 +13164,9 @@ static void RequireRuntimeStateReaderOwnsUnityStateAcquisition(string root) "return _verse.GetObservedDaemonStateAsync();", "return _verse.GetLatestAuthoritativeRunFrameAsync();", "return _verse.GetHealthAsync();", + "return _verse.GetVerseAuthorityPolicyAsync();", "return _verse.GetLatestSoaViewAsync();", + "AetheriaRuntimeDaemonPublicationStore.TryReadVerseAuthorityPolicy", "return _verse.GetDaemonGameSurfaceAsync();", "return _verse.GetDaemonGameTuiSurfaceAsync();", "return _verse.GetDaemonEditorSurfaceAsync();", diff --git a/Assets/Scripts/Tests/DaemonRuntimeDocumentTests.cs b/Assets/Scripts/Tests/DaemonRuntimeDocumentTests.cs index 644590f71..c4ce86538 100644 --- a/Assets/Scripts/Tests/DaemonRuntimeDocumentTests.cs +++ b/Assets/Scripts/Tests/DaemonRuntimeDocumentTests.cs @@ -159,7 +159,11 @@ public class DaemonRuntimeDocumentTests 7, 1.25, 0.02); + var authorityPolicy = AetheriaRuntimeVerseAuthorityPolicyDocument.TrustedCoop( + "aetheria.local", + "daemon"); PublishLatestFrameThroughVerseClient(statePath, frame); + PublishVerseAuthorityPolicyThroughVerseClient(statePath, authorityPolicy); using var client = AetheriaClient .OpenAsync(statePath, "unity-test", pullOnOpen: true) @@ -221,6 +225,7 @@ public class DaemonRuntimeDocumentTests var legacyGameTuiSurface = client.DaemonGameTuiSurfaceAsync().GetAwaiter().GetResult(); var legacyEditorSurface = client.DaemonEditorSurfaceAsync().GetAwaiter().GetResult(); var legacyEditorTuiSurface = client.DaemonEditorTuiSurfaceAsync().GetAwaiter().GetResult(); + var legacyAuthorityStatus = client.AuthorityStatusAsync().GetAwaiter().GetResult(); var dockingState = client.Aetheria() .DockingState .LatestAsync() @@ -241,6 +246,12 @@ public class DaemonRuntimeDocumentTests Assert.AreSame( client.State.Daemon.CommandBoundary, client.Document()); + Assert.AreSame( + client.State.Daemon.AuthorityPolicy, + client.Document()); + Assert.AreSame( + client.State.Daemon.AuthorityPolicy, + client.State.DocumentBySchema(AetheriaRuntimeVerseAuthoritySchemas.Policy)); Assert.AreEqual(AetheriaRuntimeDaemonGameSurfaceBuilder.SurfaceId, client.State.Daemon.GameSurface.DocumentId); Assert.AreEqual(AetheriaRuntimeDaemonGameSurfaceBuilder.TuiSurfaceId, client.State.Daemon.GameTuiSurface.DocumentId); Assert.AreEqual(AetheriaRuntimeDaemonEditorSurfaceBuilder.SurfaceId, client.State.Daemon.EditorSurface.DocumentId); @@ -272,6 +283,9 @@ public class DaemonRuntimeDocumentTests Assert.AreEqual(AetheriaRuntimeDaemonGameSurfaceBuilder.TuiSurfaceId, legacyGameTuiSurface.Surface.Id); Assert.AreEqual(AetheriaRuntimeDaemonEditorSurfaceBuilder.SurfaceId, legacyEditorSurface.Surface.Id); Assert.AreEqual(AetheriaRuntimeDaemonEditorSurfaceBuilder.TuiSurfaceId, legacyEditorTuiSurface.Surface.Id); + Assert.IsNotNull(legacyAuthorityStatus); + Assert.AreEqual(AetheriaRuntimeVerseAuthoritySchemas.Policy, legacyAuthorityStatus!.Schema); + Assert.AreEqual(authorityPolicy.HostRuntimeId, legacyAuthorityStatus.HostRuntimeId); Assert.AreEqual(AetheriaRuntimeCatalogSnapshot.SchemaId, client.State.Catalog.Sources.Last().SchemaId); Assert.GreaterOrEqual(catalog.Items.Count, 0); Assert.AreEqual(AetheriaRuntimePlayerSettingsDocument.SchemaId, playerSettings.Schema); @@ -4152,6 +4166,23 @@ public class DaemonRuntimeDocumentTests .GetResult(); } + private static void PublishVerseAuthorityPolicyThroughVerseClient( + string statePath, + AetheriaRuntimeVerseAuthorityPolicyDocument policy) + { + using var client = AetheriaRuntimeVerseClient + .OpenAsync(statePath, "daemon-authority-policy-test", startServer: false, pullOnOpen: true) + .GetAwaiter() + .GetResult(); + client.VerseAuthorityPolicy() + .ReplaceAsync(policy) + .GetAwaiter() + .GetResult(); + client.FlushAsync() + .GetAwaiter() + .GetResult(); + } + private static AetheriaRuntimeCatalogItem CatalogItem( string itemKey, IReadOnlyList behaviorPayloads) diff --git a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaClient.cs b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaClient.cs index aeea44a99..ae665e7d2 100644 --- a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaClient.cs +++ b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaClient.cs @@ -322,15 +322,10 @@ namespace GameCult.Aetheria.State.Verse return await State.Daemon.Health.LatestAsync().ConfigureAwait(false); } - public Task AuthorityStatusAsync() + public async Task AuthorityStatusAsync() { ThrowIfDisposed(); - return Task.FromResult( - AetheriaRuntimeDaemonPublicationStore.TryReadVerseAuthorityPolicy( - StatePath, - out var policy) - ? policy - : null); + return await State.Daemon.AuthorityPolicy.LatestAsync().ConfigureAwait(false); } public async Task SoaViewAsync() diff --git a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaClientState.cs b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaClientState.cs index 336bd8df2..3d5fe3b81 100644 --- a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaClientState.cs +++ b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaClientState.cs @@ -16,6 +16,7 @@ namespace GameCult.Aetheria.State.Verse CultMeshDocumentHandle providerAdvertisement, CultMeshDocumentHandle health, CultMeshDocumentHandle commandBoundary, + CultMeshDocumentHandle authorityPolicy, CultMeshDocumentHandle latestFrame, CultMeshDocumentHandle latestSoaView, CultMeshDocumentHandle gameSurface, @@ -49,6 +50,7 @@ namespace GameCult.Aetheria.State.Verse providerAdvertisement, health, commandBoundary, + authorityPolicy, latestFrame, latestSoaView, gameSurface, @@ -84,6 +86,7 @@ namespace GameCult.Aetheria.State.Verse Daemon.ProviderAdvertisement, Daemon.Health, Daemon.CommandBoundary, + Daemon.AuthorityPolicy, Daemon.GameSurface, Daemon.GameTuiSurface, Daemon.EditorSurface, @@ -214,6 +217,7 @@ namespace GameCult.Aetheria.State.Verse CultMeshDocumentHandle providerAdvertisement, CultMeshDocumentHandle health, CultMeshDocumentHandle commandBoundary, + CultMeshDocumentHandle authorityPolicy, CultMeshDocumentHandle latestFrame, CultMeshDocumentHandle latestSoaView, CultMeshDocumentHandle gameSurface, @@ -224,6 +228,7 @@ namespace GameCult.Aetheria.State.Verse ProviderAdvertisement = providerAdvertisement ?? throw new ArgumentNullException(nameof(providerAdvertisement)); Health = health ?? throw new ArgumentNullException(nameof(health)); CommandBoundary = commandBoundary ?? throw new ArgumentNullException(nameof(commandBoundary)); + AuthorityPolicy = authorityPolicy ?? throw new ArgumentNullException(nameof(authorityPolicy)); LatestFrame = latestFrame ?? throw new ArgumentNullException(nameof(latestFrame)); LatestSoaView = latestSoaView ?? throw new ArgumentNullException(nameof(latestSoaView)); GameSurface = gameSurface ?? throw new ArgumentNullException(nameof(gameSurface)); @@ -238,6 +243,8 @@ namespace GameCult.Aetheria.State.Verse public CultMeshDocumentHandle CommandBoundary { get; } + public CultMeshDocumentHandle AuthorityPolicy { get; } + public CultMeshDocumentHandle LatestFrame { get; } public CultMeshDocumentHandle LatestSoaView { get; } diff --git a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeVerseClient.cs b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeVerseClient.cs index 81d5da244..1468e31f7 100644 --- a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeVerseClient.cs +++ b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeVerseClient.cs @@ -27,6 +27,9 @@ namespace GameCult.Aetheria.State.Verse public static CultRecordKey DaemonCommandBoundary { get; } = new CultRecordKey("daemon:aetheria.command_boundary.v1"); + public static CultRecordKey VerseAuthorityPolicy { get; } = + new CultRecordKey(AetheriaRuntimeVerseAuthorityPolicyDocument.DocumentKey); + public static CultRecordKey DaemonFrameLatest { get; } = new CultRecordKey("daemon:aetheria.frame.latest.v1"); @@ -88,6 +91,7 @@ namespace GameCult.Aetheria.State.Verse typeof(AetheriaRuntimeDaemonProviderAdvertisementDocument), typeof(AetheriaRuntimeDaemonHealthDocument), typeof(AetheriaRuntimeDaemonCommandBoundaryDocument), + typeof(AetheriaRuntimeVerseAuthorityPolicyDocument), typeof(AetheriaRuntimeDaemonFrameDocument), typeof(AetheriaRuntimeDaemonSoaViewDocument), typeof(AetheriaRuntimeAssetManifestDocument), @@ -222,6 +226,12 @@ namespace GameCult.Aetheria.State.Verse return await Aetheria().Daemon.CommandBoundary.LatestAsync().ConfigureAwait(false); } + public async Task GetVerseAuthorityPolicyAsync() + { + ThrowIfDisposed(); + return await Aetheria().Daemon.AuthorityPolicy.LatestAsync().ConfigureAwait(false); + } + public async Task GetLatestFrameAsync() { ThrowIfDisposed(); @@ -391,6 +401,13 @@ namespace GameCult.Aetheria.State.Verse AetheriaRuntimeVerseRecordKeys.DaemonCommandBoundary); } + public CultMeshMutableStatePointer VerseAuthorityPolicy() + { + ThrowIfDisposed(); + return MutableDocumentPointer( + AetheriaRuntimeVerseRecordKeys.VerseAuthorityPolicy); + } + public CultMeshMutableStatePointer LatestFrame() { ThrowIfDisposed(); @@ -504,6 +521,14 @@ namespace GameCult.Aetheria.State.Verse AetheriaRuntimeVerseRecordKeys.DaemonCommandBoundary); } + public Observable> + WatchVerseAuthorityPolicies() + { + ThrowIfDisposed(); + return Database.WatchRecord( + AetheriaRuntimeVerseRecordKeys.VerseAuthorityPolicy); + } + public Observable> WatchLatestFrames() { ThrowIfDisposed(); @@ -742,6 +767,8 @@ namespace GameCult.Aetheria.State.Verse AetheriaRuntimeVerseRecordKeys.DaemonHealth), Document( AetheriaRuntimeVerseRecordKeys.DaemonCommandBoundary), + Document( + AetheriaRuntimeVerseRecordKeys.VerseAuthorityPolicy), Document( AetheriaRuntimeVerseRecordKeys.DaemonFrameLatest), Document(