diff --git a/Aetheria.State.Daemon/Program.cs b/Aetheria.State.Daemon/Program.cs index d2d8cb722..4f4cf0c24 100644 --- a/Aetheria.State.Daemon/Program.cs +++ b/Aetheria.State.Daemon/Program.cs @@ -866,13 +866,13 @@ static async Task PublishStateSurfacesAsync( : playerSettings.LastUpdatedAtUtc; await node.MutableDocument(AetheriaStateNode.OperationsSurfaceKey) - .ReplaceAsync(AetheriaOperationsSurfaceProjector.Build(eveStatus, verseHost, runtimeSession)) + .ReplaceAsync(AetheriaEveSurfaceDocuments.BuildOperationsSurface(eveStatus, verseHost, runtimeSession)) .ConfigureAwait(false); await node.MutableDocument(AetheriaStateNode.PlayerSettingsSurfaceKey) - .ReplaceAsync(AetheriaPlayerSettingsSurfaceProjector.Build(playerSettings, playerSettingsUpdatedAt)) + .ReplaceAsync(AetheriaEveSurfaceDocuments.BuildPlayerSettingsSurface(playerSettings, playerSettingsUpdatedAt)) .ConfigureAwait(false); await node.MutableDocument(AetheriaStateNode.ProviderAdvertisementSurfaceKey) - .ReplaceAsync(AetheriaProviderAdvertisementProjector.Build(verseHost, node.StatePath, updatedAtUtc)) + .ReplaceAsync(AetheriaEveSurfaceDocuments.BuildProviderAdvertisement(verseHost, node.StatePath, updatedAtUtc)) .ConfigureAwait(false); await node.FlushAsync().ConfigureAwait(false); } diff --git a/Aetheria.State.Smoke/Program.cs b/Aetheria.State.Smoke/Program.cs index 0a1f11207..770b37a19 100644 --- a/Aetheria.State.Smoke/Program.cs +++ b/Aetheria.State.Smoke/Program.cs @@ -95,7 +95,7 @@ await using (var node = await AetheriaStateNode.OpenAsync(statePath, "aetheria-s await node.FlushAsync(); var runtimeCatalog = await node.RuntimeCatalog().LatestAsync().ConfigureAwait(false); await node.MutableDocument(AetheriaStateNode.CatalogSurfaceKey) - .ReplaceAsync(AetheriaCatalogSurfaceProjector.Build(runtimeCatalog, now)); + .ReplaceAsync(AetheriaEveSurfaceDocuments.BuildCatalogSurface(runtimeCatalog, now)); var verseHostSettings = AetheriaVerseHostSettingsNormalizer.Normalize(new AetheriaVerseHostSettings { @@ -103,9 +103,9 @@ await using (var node = await AetheriaStateNode.OpenAsync(statePath, "aetheria-s }); await node.MutableDocument(AetheriaStateNode.VerseHostSettingsKey).ReplaceAsync(verseHostSettings); await node.MutableDocument(AetheriaStateNode.OperationsSurfaceKey) - .ReplaceAsync(AetheriaOperationsSurfaceProjector.Build(verseHostSettings: verseHostSettings)); + .ReplaceAsync(AetheriaEveSurfaceDocuments.BuildOperationsSurface(verseHostSettings: verseHostSettings)); await node.MutableDocument(AetheriaStateNode.ProviderAdvertisementSurfaceKey) - .ReplaceAsync(AetheriaProviderAdvertisementProjector.Build(verseHostSettings, statePath, now)); + .ReplaceAsync(AetheriaEveSurfaceDocuments.BuildProviderAdvertisement(verseHostSettings, statePath, now)); var daemonProvider = AetheriaRuntimeDaemonProviderAdvertisementDocument.Create( statePath, "smoke-daemon", @@ -182,7 +182,7 @@ await using (var node = await AetheriaStateNode.OpenAsync(statePath, "aetheria-s LastSeenAtUtc = now, Status = "running" }); - await node.MutableDocument(AetheriaStateNode.OperationsSurfaceKey).ReplaceAsync(AetheriaOperationsSurfaceProjector.Build( + await node.MutableDocument(AetheriaStateNode.OperationsSurfaceKey).ReplaceAsync(AetheriaEveSurfaceDocuments.BuildOperationsSurface( verseHostSettings: verseHostSettings, runtimeSession: await node.MutableDocument(AetheriaStateNode.RuntimeSessionKey("smoke-runtime")).ReadAsync())); @@ -535,7 +535,7 @@ await using (var node = await AetheriaStateNode.OpenAsync(statePath, "aetheria-s } }); await node.MutableDocument(AetheriaStateNode.PlayerSettingsSurfaceKey) - .ReplaceAsync(AetheriaPlayerSettingsSurfaceProjector.Build( + .ReplaceAsync(AetheriaEveSurfaceDocuments.BuildPlayerSettingsSurface( await node.MutableDocument(AetheriaStateNode.PlayerSettingsKey).ReadAsync(), now)); @@ -616,7 +616,7 @@ await using (var node = await AetheriaStateNode.OpenAsync(statePath, "aetheria-s Status = eveCommandReport.RejectedCommands > 0 ? "rejected" : "ok" }; await node.MutableDocument(AetheriaStateNode.EveCommandAcceptanceStatusKey).ReplaceAsync(eveCommandStatus); - await node.MutableDocument(AetheriaStateNode.OperationsSurfaceKey).ReplaceAsync(AetheriaOperationsSurfaceProjector.Build( + await node.MutableDocument(AetheriaStateNode.OperationsSurfaceKey).ReplaceAsync(AetheriaEveSurfaceDocuments.BuildOperationsSurface( eveCommandStatus, verseHostSettings: await node.MutableDocument(AetheriaStateNode.VerseHostSettingsKey).ReadAsync(), runtimeSession: await node.MutableDocument(AetheriaStateNode.RuntimeSessionKey("smoke-runtime")).ReadAsync())); @@ -678,7 +678,7 @@ await using (var reopened = await AetheriaStateNode.OpenAsync(statePath, "aether } if (catalogSurface?.Schema != "gamecult.eve.surface.v1" || - catalogSurface.Surface.Id != AetheriaCatalogSurfaceProjector.SurfaceId) + catalogSurface.Surface.Id != AetheriaEveSurfaceDocuments.CatalogSurfaceId) { throw new InvalidOperationException("Eve catalog surface did not survive flush/reopen."); } @@ -688,7 +688,7 @@ await using (var reopened = await AetheriaStateNode.OpenAsync(statePath, "aether eveCommandStatus.AppliedCatalogRefreshes != 1 || eveCommandStatus.AppliedPlayerSettingsCommands != 2 || !eveCommandStatus.LastRejectedReason.Contains("Unknown typed Eve command kind", StringComparison.Ordinal) || - operationsSurface?.Surface.Id != AetheriaOperationsSurfaceProjector.SurfaceId || + operationsSurface?.Surface.Id != AetheriaEveSurfaceDocuments.OperationsSurfaceId || !operationsSurface.Surface.Root.Children.Any(child => child.Id == "aetheria.operations.eveCommandAcceptance") || operationsSurface.Surface.Root.Children.Any(child => child.Id == "aetheria.operations.commitDrain") || !operationsSurface.Surface.Root.Children.Any(child => child.Id == "aetheria.operations.runtimeSession")) @@ -704,23 +704,23 @@ await using (var reopened = await AetheriaStateNode.OpenAsync(statePath, "aether $"children=[{string.Join(", ", operationsSurface?.Surface.Root.Children.Select(child => child.Id) ?? [])}]."); } - if (advertisement?.ProviderId != AetheriaProviderAdvertisementProjector.ProviderId || + if (advertisement?.ProviderId != AetheriaEveSurfaceDocuments.ProviderId || advertisement.Surfaces.Length < 7 || - !advertisement.Surfaces.Any(surface => surface.SurfaceId == AetheriaCatalogSurfaceProjector.SurfaceId) || - !advertisement.Surfaces.Any(surface => surface.SurfaceId == AetheriaOperationsSurfaceProjector.SurfaceId) || - !advertisement.Surfaces.Any(surface => surface.SurfaceId == AetheriaPlayerSettingsSurfaceProjector.SurfaceId) || + !advertisement.Surfaces.Any(surface => surface.SurfaceId == AetheriaEveSurfaceDocuments.CatalogSurfaceId) || + !advertisement.Surfaces.Any(surface => surface.SurfaceId == AetheriaEveSurfaceDocuments.OperationsSurfaceId) || + !advertisement.Surfaces.Any(surface => surface.SurfaceId == AetheriaEveSurfaceDocuments.PlayerSettingsSurfaceId) || !advertisement.Surfaces.Any(surface => surface.SurfaceId == AetheriaRuntimeDaemonGameSurfaceBuilder.SurfaceId && - surface.Key == AetheriaProviderAdvertisementProjector.DaemonGameSurfaceKey) || + surface.Key == AetheriaEveSurfaceDocuments.DaemonGameSurfaceKey) || !advertisement.Surfaces.Any(surface => surface.SurfaceId == AetheriaRuntimeDaemonGameSurfaceBuilder.TuiSurfaceId && - surface.Key == AetheriaProviderAdvertisementProjector.DaemonGameTuiSurfaceKey) || + surface.Key == AetheriaEveSurfaceDocuments.DaemonGameTuiSurfaceKey) || !advertisement.Surfaces.Any(surface => surface.SurfaceId == AetheriaRuntimeDaemonEditorSurfaceBuilder.SurfaceId && - surface.Key == AetheriaProviderAdvertisementProjector.DaemonEditorSurfaceKey) || + surface.Key == AetheriaEveSurfaceDocuments.DaemonEditorSurfaceKey) || !advertisement.Surfaces.Any(surface => surface.SurfaceId == AetheriaRuntimeDaemonEditorSurfaceBuilder.TuiSurfaceId && - surface.Key == AetheriaProviderAdvertisementProjector.DaemonEditorTuiSurfaceKey) || + surface.Key == AetheriaEveSurfaceDocuments.DaemonEditorTuiSurfaceKey) || !advertisement.Schemas.Contains("aetheria.runtime_session.v1") || !advertisement.Schemas.Contains(AetheriaRuntimeDaemonSchemas.ProviderAdvertisement) || !advertisement.Schemas.Contains(AetheriaRuntimeDaemonSchemas.Frame) || @@ -776,7 +776,7 @@ await using (var reopened = await AetheriaStateNode.OpenAsync(statePath, "aether throw new InvalidOperationException("Player settings did not survive flush/reopen."); } - if (playerSettingsSurface?.Surface.Id != AetheriaPlayerSettingsSurfaceProjector.SurfaceId || + if (playerSettingsSurface?.Surface.Id != AetheriaEveSurfaceDocuments.PlayerSettingsSurfaceId || !playerSettingsSurface.Surface.Root.Children.Any(child => child.Id == "aetheria.playerSettings.gameplay") || !playerSettingsSurface.Surface.Root.Children.Any(child => child.Id == "aetheria.playerSettings.graphics")) { diff --git a/Aetheria.State.Unity.Smoke/Program.cs b/Aetheria.State.Unity.Smoke/Program.cs index 75ad5d08d..7e71243c2 100644 --- a/Aetheria.State.Unity.Smoke/Program.cs +++ b/Aetheria.State.Unity.Smoke/Program.cs @@ -152,7 +152,7 @@ if (packageCorporation.Allegiances.Count == 0 || packageCorporation.Allegiances. } if (surface?.Schema != "gamecult.eve.surface.v1" || - surface.Surface.Id != AetheriaCatalogSurfaceProjector.SurfaceId) + surface.Surface.Id != AetheriaEveSurfaceDocuments.CatalogSurfaceId) { throw new InvalidOperationException("Runtime catalog client did not read the typed Eve surface."); } diff --git a/Aetheria.State.Verify/Program.cs b/Aetheria.State.Verify/Program.cs index 7dd59db93..6518c5783 100644 --- a/Aetheria.State.Verify/Program.cs +++ b/Aetheria.State.Verify/Program.cs @@ -118,7 +118,7 @@ var items = node.Cache.GetAll().ToArray(); var corporations = node.Cache.GetAll().ToArray(); var nameFiles = node.Cache.GetAll().ToArray(); var catalog = await node.RuntimeCatalog().LatestAsync().ConfigureAwait(false); -var surface = AetheriaCatalogSurfaceProjector.Build(catalog, DateTimeOffset.UtcNow.ToString("O")); +var surface = AetheriaEveSurfaceDocuments.BuildCatalogSurface(catalog, DateTimeOffset.UtcNow.ToString("O")); var tradeValuePolicy = await node.MutableDocument(AetheriaStateNode.TradeValuePolicyKey).ReadAsync() ?? throw new InvalidOperationException("Missing authored trade value policy document."); await RequireTradeValuePolicyEveCommandPersistsAsync(); @@ -522,7 +522,7 @@ if (surface.Schema != "gamecult.eve.surface.v1" || } if (publishedSurface.Schema != surface.Schema || - publishedSurface.Surface.Id != AetheriaCatalogSurfaceProjector.SurfaceId || + publishedSurface.Surface.Id != AetheriaEveSurfaceDocuments.CatalogSurfaceId || publishedSurface.Surface.Root.Kind != "surface") { throw new InvalidOperationException("Published Aetheria catalog Eve surface is not the expected typed surface."); @@ -725,18 +725,18 @@ static void RequireSharedEvePackagesImportedFromEveRepo(string root) "org.gamecult.aetheria.state", "Runtime", "AetheriaRuntimeCultCacheDocumentStore.cs"); - var playerSettingsSurfaceProjectorPath = Path.Combine( + var playerSettingsSurfaceDocumentsPath = Path.Combine( root, "Aetheria.State", - "AetheriaPlayerSettingsSurfaceProjector.cs"); - var catalogSurfaceProjectorPath = Path.Combine( + "AetheriaEveSurfaceDocuments.cs"); + var catalogSurfaceDocumentsPath = Path.Combine( root, "Aetheria.State", - "AetheriaCatalogSurfaceProjector.cs"); - var operationsSurfaceProjectorPath = Path.Combine( + "AetheriaEveSurfaceDocuments.cs"); + var operationsSurfaceDocumentsPath = Path.Combine( root, "Aetheria.State", - "AetheriaOperationsSurfaceProjector.cs"); + "AetheriaEveSurfaceDocuments.cs"); var manifest = File.Exists(manifestPath) ? File.ReadAllText(manifestPath) @@ -768,15 +768,15 @@ static void RequireSharedEvePackagesImportedFromEveRepo(string root) var runtimeCultCacheDocumentStore = File.Exists(runtimeCultCacheDocumentStorePath) ? File.ReadAllText(runtimeCultCacheDocumentStorePath) : throw new InvalidOperationException("Cannot verify shared Eve package ownership; AetheriaRuntimeCultCacheDocumentStore.cs is missing."); - var playerSettingsSurfaceProjector = File.Exists(playerSettingsSurfaceProjectorPath) - ? File.ReadAllText(playerSettingsSurfaceProjectorPath) - : throw new InvalidOperationException("Cannot verify shared Eve package ownership; AetheriaPlayerSettingsSurfaceProjector.cs is missing."); - var catalogSurfaceProjector = File.Exists(catalogSurfaceProjectorPath) - ? File.ReadAllText(catalogSurfaceProjectorPath) - : throw new InvalidOperationException("Cannot verify shared Eve package ownership; AetheriaCatalogSurfaceProjector.cs is missing."); - var operationsSurfaceProjector = File.Exists(operationsSurfaceProjectorPath) - ? File.ReadAllText(operationsSurfaceProjectorPath) - : throw new InvalidOperationException("Cannot verify shared Eve package ownership; AetheriaOperationsSurfaceProjector.cs is missing."); + var playerSettingsSurfaceDocuments = File.Exists(playerSettingsSurfaceDocumentsPath) + ? File.ReadAllText(playerSettingsSurfaceDocumentsPath) + : throw new InvalidOperationException("Cannot verify shared Eve package ownership; AetheriaEveSurfaceDocuments.cs is missing."); + var catalogSurfaceDocuments = File.Exists(catalogSurfaceDocumentsPath) + ? File.ReadAllText(catalogSurfaceDocumentsPath) + : throw new InvalidOperationException("Cannot verify shared Eve package ownership; AetheriaEveSurfaceDocuments.cs is missing."); + var operationsSurfaceDocuments = File.Exists(operationsSurfaceDocumentsPath) + ? File.ReadAllText(operationsSurfaceDocumentsPath) + : throw new InvalidOperationException("Cannot verify shared Eve package ownership; AetheriaEveSurfaceDocuments.cs is missing."); var requiredManifestSymbols = new[] { @@ -899,12 +899,12 @@ static void RequireSharedEvePackagesImportedFromEveRepo(string root) "AetheriaRuntimeEveSurfaceStateProjector is dead conversion chaff; AetheriaRuntimeEveSurfaceAdapter owns runtime surface to Eve state lowering."); } - var surfaceCommandProjectors = string.Join( + var surfaceCommandDocuments = string.Join( "\n", runtimeAdapter, - playerSettingsSurfaceProjector, - catalogSurfaceProjector, - operationsSurfaceProjector); + playerSettingsSurfaceDocuments, + catalogSurfaceDocuments, + operationsSurfaceDocuments); if (!runtimeCultCacheDocumentStore.Contains("CultMesh.OperationBindingRecord(command.Operation)", StringComparison.Ordinal) || !runtimeCultCacheDocumentStore.Contains("CultMesh.OperationBindingRecord(", StringComparison.Ordinal) || !runtimeCultCacheDocumentStore.Contains("routeDescription).ToBinding()", StringComparison.Ordinal) || @@ -912,7 +912,7 @@ static void RequireSharedEvePackagesImportedFromEveRepo(string root) !runtimeAdapter.Contains("command.SchemaId", StringComparison.Ordinal) || !runtimeAdapter.Contains("public static EveSurfaceState ToEveSurfaceState(AetheriaRuntimeSurfaceDocument document)", StringComparison.Ordinal) || !runtimeAdapter.Contains("global::Aetheria.State.Documents.EveSurfaceComponent ToEveSurfaceState(", StringComparison.Ordinal) || - !surfaceCommandProjectors.Contains("CultMesh.OperationBindingRecord(", StringComparison.Ordinal) || + !surfaceCommandDocuments.Contains("CultMesh.OperationBindingRecord(", StringComparison.Ordinal) || runtimeCultCacheDocumentStore.Contains("new CultMeshOperationBindingDescriptor(", StringComparison.Ordinal) || runtimeAdapter.Contains("new CultMeshOperationBindingDescriptor(", StringComparison.Ordinal)) { @@ -6767,9 +6767,9 @@ static void RequireNoDeadPopupShells(string root) static void RequirePlayerSettingsEveSurface(string root) { - var projectorPath = Path.Combine(root, "Aetheria.State", "AetheriaPlayerSettingsSurfaceProjector.cs"); + var surfaceDocumentsPath = Path.Combine(root, "Aetheria.State", "AetheriaEveSurfaceDocuments.cs"); var bridgePath = Path.Combine(root, "Aetheria.State", "AetheriaEveCommandBridge.cs"); - var providerPath = Path.Combine(root, "Aetheria.State", "AetheriaProviderAdvertisementProjector.cs"); + var providerPath = Path.Combine(root, "Aetheria.State", "AetheriaEveSurfaceDocuments.cs"); var daemonHostPath = Path.Combine(root, "Aetheria.State.Daemon", "Program.cs"); var sharedCommandsPath = Path.Combine( root, @@ -6784,13 +6784,13 @@ static void RequirePlayerSettingsEveSurface(string root) "Runtime", "AetheriaRuntimePlayerSettingsSurfaceBuilder.cs"); - if (!File.Exists(projectorPath)) + if (!File.Exists(surfaceDocumentsPath)) { - throw new InvalidOperationException("Player settings Eve surface projector is missing."); + throw new InvalidOperationException("Player settings Eve surface document is missing."); } - var projector = File.ReadAllText(projectorPath); - var requiredProjectorSymbols = new[] + var surfaceDocuments = File.ReadAllText(surfaceDocumentsPath); + var requiredSurfaceDocumentSymbols = new[] { "AetheriaRuntimePlayerSettingsCommands.SurfaceId", "AetheriaRuntimePlayerSettingsSurfaceBuilder.Build", @@ -6798,15 +6798,15 @@ static void RequirePlayerSettingsEveSurface(string root) "settings.ActiveRunKey" }; - var missingProjectorSymbols = requiredProjectorSymbols - .Where(symbol => !projector.Contains(symbol, StringComparison.Ordinal)) + var missingSurfaceDocumentSymbols = requiredSurfaceDocumentSymbols + .Where(symbol => !surfaceDocuments.Contains(symbol, StringComparison.Ordinal)) .ToArray(); - if (missingProjectorSymbols.Length > 0) + if (missingSurfaceDocumentSymbols.Length > 0) { throw new InvalidOperationException( - "Player settings Eve surface projector is missing required typed controls: " + - string.Join(", ", missingProjectorSymbols)); + "Player settings Eve surface document is missing required typed controls: " + + string.Join(", ", missingSurfaceDocumentSymbols)); } var bridge = File.Exists(bridgePath) @@ -6828,7 +6828,7 @@ static void RequirePlayerSettingsEveSurface(string root) if (!bridge.Contains("AcceptedPlayerSettingsCommands", StringComparison.Ordinal) || !bridge.Contains("ExecutePlayerSettingsCommandAsync", StringComparison.Ordinal) || !bridge.Contains("MutableDocument(AetheriaStateNode.PlayerSettingsSurfaceKey)", StringComparison.Ordinal) || - !bridge.Contains(".ReplaceAsync(AetheriaPlayerSettingsSurfaceProjector.Build", StringComparison.Ordinal) || + !bridge.Contains(".ReplaceAsync(AetheriaEveSurfaceDocuments.BuildPlayerSettingsSurface", StringComparison.Ordinal) || !bridge.Contains("SetPlayerName", StringComparison.Ordinal) || !bridge.Contains("command.PlayerSettings.PlayerName", StringComparison.Ordinal)) { @@ -6836,7 +6836,8 @@ static void RequirePlayerSettingsEveSurface(string root) "Eve command bridge no longer owns the typed player-settings surface mutation path."); } - if (!provider.Contains("AetheriaPlayerSettingsSurfaceProjector.SurfaceId", StringComparison.Ordinal) || + if (!provider.Contains("SurfaceId = PlayerSettingsSurfaceId", StringComparison.Ordinal) || + !provider.Contains("Key = PlayerSettingsSurfaceKey", StringComparison.Ordinal) || !provider.Contains("AetheriaRuntimePlayerSettingsCommands.Refresh", StringComparison.Ordinal)) { throw new InvalidOperationException( @@ -6844,8 +6845,8 @@ static void RequirePlayerSettingsEveSurface(string root) } if (!daemonHost.Contains("MutableDocument(AetheriaStateNode.PlayerSettingsSurfaceKey)", StringComparison.Ordinal) || - !daemonHost.Contains(".ReplaceAsync(AetheriaPlayerSettingsSurfaceProjector.Build", StringComparison.Ordinal) || - !daemonHost.Contains("AetheriaPlayerSettingsSurfaceProjector.Build", StringComparison.Ordinal)) + !daemonHost.Contains(".ReplaceAsync(AetheriaEveSurfaceDocuments.BuildPlayerSettingsSurface", StringComparison.Ordinal) || + !daemonHost.Contains("AetheriaEveSurfaceDocuments.BuildPlayerSettingsSurface", StringComparison.Ordinal)) { throw new InvalidOperationException( "Aetheria.State.Daemon no longer republishes the provider-owned player-settings Eve surface."); @@ -8600,8 +8601,8 @@ static void RequireVerseHostSettingsAuthority(string root) var verseDiscoveryHostPath = Path.Combine(root, "Aetheria.State", "AetheriaVerseDiscoveryHost.cs"); var registryPath = Path.Combine(root, "Aetheria.State", "AetheriaDocumentRegistry.cs"); var nodePath = Path.Combine(root, "Aetheria.State", "AetheriaStateNode.cs"); - var providerPath = Path.Combine(root, "Aetheria.State", "AetheriaProviderAdvertisementProjector.cs"); - var operationsPath = Path.Combine(root, "Aetheria.State", "AetheriaOperationsSurfaceProjector.cs"); + var providerPath = Path.Combine(root, "Aetheria.State", "AetheriaEveSurfaceDocuments.cs"); + var operationsPath = Path.Combine(root, "Aetheria.State", "AetheriaEveSurfaceDocuments.cs"); var daemonHostPath = Path.Combine(root, "Aetheria.State.Daemon", "Program.cs"); var requiredFiles = new[] @@ -8774,7 +8775,7 @@ static void RequireVerseHostSettingsAuthority(string root) "node.MutableDocument(AetheriaStateNode.VerseHostSettingsKey).ReadAsync()", "node.MutableDocument(AetheriaStateNode.VerseHostSettingsKey)", ".ReplaceAsync(normalized)", - "AetheriaProviderAdvertisementProjector.Build(verseHost, node.StatePath, updatedAtUtc)" + "AetheriaEveSurfaceDocuments.BuildProviderAdvertisement(verseHost, node.StatePath, updatedAtUtc)" }; var missingDaemonHostSymbols = requiredDaemonHostSymbols .Where(symbol => !daemonHost.Contains(symbol, StringComparison.Ordinal)) @@ -9407,7 +9408,7 @@ static void RequireVerseSettingsShellAndBridge(string root) var mainMenuPath = Path.Combine(root, "Assets", "Scripts", "UI", "MainMenu.cs"); var commandBridgePath = Path.Combine(root, "Aetheria.State", "AetheriaEveCommandBridge.cs"); var acceptanceStatusPath = Path.Combine(root, "Aetheria.State", "Documents", "AetheriaEveCommandAcceptanceStatus.cs"); - var operationsProjectorPath = Path.Combine(root, "Aetheria.State", "AetheriaOperationsSurfaceProjector.cs"); + var operationsSurfaceDocumentsPath = Path.Combine(root, "Aetheria.State", "AetheriaEveSurfaceDocuments.cs"); var daemonHostPath = Path.Combine(root, "Aetheria.State.Daemon", "Program.cs"); var requiredFiles = new[] @@ -9424,7 +9425,7 @@ static void RequireVerseSettingsShellAndBridge(string root) mainMenuPath, commandBridgePath, acceptanceStatusPath, - operationsProjectorPath, + operationsSurfaceDocumentsPath, daemonHostPath }; @@ -9451,7 +9452,7 @@ static void RequireVerseSettingsShellAndBridge(string root) var mainMenu = File.ReadAllText(mainMenuPath); var commandBridge = File.ReadAllText(commandBridgePath); var acceptanceStatus = File.ReadAllText(acceptanceStatusPath); - var operationsProjector = File.ReadAllText(operationsProjectorPath); + var operationsSurfaceDocuments = File.ReadAllText(operationsSurfaceDocumentsPath); var daemonHost = File.ReadAllText(daemonHostPath); var requiredUnityPackageProjectSymbols = new[] @@ -9772,7 +9773,7 @@ static void RequireVerseSettingsShellAndBridge(string root) "node.MutableDocument(AetheriaStateNode.VerseHostSettingsKey)", ".ReplaceAsync(normalized)", "node.MutableDocument(AetheriaStateNode.ProviderAdvertisementSurfaceKey)", - "AetheriaOperationsSurfaceProjector.Build(", + "AetheriaEveSurfaceDocuments.BuildOperationsSurface(", "switch (command.Kind)" }; var missingBridgeSymbols = requiredBridgeSymbols @@ -9824,7 +9825,7 @@ static void RequireVerseSettingsShellAndBridge(string root) { ["Aetheria daemon host"] = daemonHost, ["Aetheria Eve command bridge"] = commandBridge, - ["operations projector"] = operationsProjector + ["operations surface document"] = operationsSurfaceDocuments }; var pendingBeforeApplyUses = pendingBeforeApplyUseSources .Where(source => source.Value.Contains("PendingBeforeApply", StringComparison.Ordinal)) @@ -9837,8 +9838,8 @@ static void RequireVerseSettingsShellAndBridge(string root) string.Join(", ", pendingBeforeApplyUses)); } - if (!operationsProjector.Contains("Verse Host Commands", StringComparison.Ordinal) || - !operationsProjector.Contains("AppliedVerseHostCommands", StringComparison.Ordinal)) + if (!operationsSurfaceDocuments.Contains("Verse Host Commands", StringComparison.Ordinal) || + !operationsSurfaceDocuments.Contains("AppliedVerseHostCommands", StringComparison.Ordinal)) { throw new InvalidOperationException( "Operations surface no longer projects Verse-host Eve command counts."); @@ -10538,7 +10539,7 @@ static void RequireDaemonVersePublication(string root) var documentRegistryPath = Path.Combine(root, "Aetheria.State", "AetheriaDocumentRegistry.cs"); var stateNodePath = Path.Combine(root, "Aetheria.State", "AetheriaStateNode.cs"); var runtimeEveSurfaceAdapterPath = Path.Combine(root, "Packages", "org.gamecult.aetheria.state", "Runtime", "AetheriaRuntimeEveSurfaceAdapter.cs"); - var providerAdvertisementPath = Path.Combine(root, "Aetheria.State", "AetheriaProviderAdvertisementProjector.cs"); + var providerAdvertisementPath = Path.Combine(root, "Aetheria.State", "AetheriaEveSurfaceDocuments.cs"); var documentStorePath = Path.Combine(root, "Packages", "org.gamecult.aetheria.state", "Runtime", "AetheriaRuntimeCultCacheDocumentStore.cs"); var boundaryPath = Path.Combine(root, "Packages", "org.gamecult.aetheria.state", "Runtime", "AetheriaRuntimeStateBoundary.cs"); var testsPath = Path.Combine(root, "Assets", "Scripts", "Tests", "DaemonRuntimeDocumentTests.cs"); @@ -11095,9 +11096,9 @@ static void RequireDaemonVersePublication(string root) "node.MutableDocument(AetheriaStateNode.OperationsSurfaceKey)", "node.MutableDocument(AetheriaStateNode.PlayerSettingsSurfaceKey)", "node.MutableDocument(AetheriaStateNode.ProviderAdvertisementSurfaceKey)", - "AetheriaProviderAdvertisementProjector.Build(verseHost, node.StatePath, updatedAtUtc)", - "AetheriaOperationsSurfaceProjector.Build(eveStatus, verseHost, runtimeSession)", - "AetheriaPlayerSettingsSurfaceProjector.Build(playerSettings, playerSettingsUpdatedAt)", + "AetheriaEveSurfaceDocuments.BuildProviderAdvertisement(verseHost, node.StatePath, updatedAtUtc)", + "AetheriaEveSurfaceDocuments.BuildOperationsSurface(eveStatus, verseHost, runtimeSession)", + "AetheriaEveSurfaceDocuments.BuildPlayerSettingsSurface(playerSettings, playerSettingsUpdatedAt)", "Role = \"verse-daemon\"", "Console.CancelKeyPress", "Aetheria Verse daemon is running" @@ -11701,13 +11702,13 @@ static void RequireUnityRuntimeCatalogClientUsesManagedDocument(string root) static void RequireCatalogSurfaceUsesManagedRuntimeCatalog(string root) { - var projectorPath = Path.Combine(root, "Aetheria.State", "AetheriaCatalogSurfaceProjector.cs"); + var surfaceDocumentsPath = Path.Combine(root, "Aetheria.State", "AetheriaEveSurfaceDocuments.cs"); var bridgePath = Path.Combine(root, "Aetheria.State", "AetheriaEveCommandBridge.cs"); var importPath = Path.Combine(root, "Aetheria.State.Import", "Program.cs"); var legacySnapshotPath = Path.Combine(root, "Aetheria.State", "AetheriaCatalogSnapshot.cs"); - var projector = File.Exists(projectorPath) - ? File.ReadAllText(projectorPath) - : throw new InvalidOperationException("Cannot verify catalog surface projector; AetheriaCatalogSurfaceProjector.cs is missing."); + var surfaceDocuments = File.Exists(surfaceDocumentsPath) + ? File.ReadAllText(surfaceDocumentsPath) + : throw new InvalidOperationException("Cannot verify catalog surface document; AetheriaEveSurfaceDocuments.cs is missing."); var bridge = File.Exists(bridgePath) ? File.ReadAllText(bridgePath) : throw new InvalidOperationException("Cannot verify Eve command bridge catalog refresh; AetheriaEveCommandBridge.cs is missing."); @@ -11715,25 +11716,26 @@ static void RequireCatalogSurfaceUsesManagedRuntimeCatalog(string root) ? File.ReadAllText(importPath) : throw new InvalidOperationException("Cannot verify legacy catalog import; Aetheria.State.Import/Program.cs is missing."); - var requiredProjectorSymbols = new[] + var requiredSurfaceDocumentSymbols = new[] { - "Build(AetheriaRuntimeCatalogSnapshot catalog", + "BuildCatalogSurface(", + "AetheriaRuntimeCatalogSnapshot catalog", "item.ItemKey", "corporation.CorporationKey", "catalog.GetManufacturer(item)", "catalog.GetNameFile(corporation)" }; - var missingProjectorSymbols = requiredProjectorSymbols - .Where(symbol => !projector.Contains(symbol, StringComparison.Ordinal)) + var missingSurfaceDocumentSymbols = requiredSurfaceDocumentSymbols + .Where(symbol => !surfaceDocuments.Contains(symbol, StringComparison.Ordinal)) .ToArray(); - if (missingProjectorSymbols.Length > 0) + if (missingSurfaceDocumentSymbols.Length > 0) { throw new InvalidOperationException( - "Catalog Eve surface must project from the managed runtime catalog document: " + - string.Join(", ", missingProjectorSymbols)); + "Catalog Eve surface must build from the managed runtime catalog document: " + + string.Join(", ", missingSurfaceDocumentSymbols)); } - if (projector.Contains("Build(AetheriaCatalogSnapshot catalog", StringComparison.Ordinal)) + if (surfaceDocuments.Contains("Build(AetheriaCatalogSnapshot catalog", StringComparison.Ordinal)) { throw new InvalidOperationException( "Catalog Eve surface still depends on the legacy authored catalog snapshot instead of the managed runtime catalog document."); @@ -11748,7 +11750,7 @@ static void RequireCatalogSurfaceUsesManagedRuntimeCatalog(string root) var requiredBridgeSymbols = new[] { "var catalog = await node.RuntimeCatalog().LatestAsync().ConfigureAwait(false);", - "AetheriaCatalogSurfaceProjector.Build(catalog, command.IssuedAtUtc)" + "AetheriaEveSurfaceDocuments.BuildCatalogSurface(catalog, command.IssuedAtUtc)" }; var missingBridgeSymbols = requiredBridgeSymbols .Where(symbol => !bridge.Contains(symbol, StringComparison.Ordinal)) diff --git a/Aetheria.State/AetheriaCatalogSurfaceProjector.cs b/Aetheria.State/AetheriaCatalogSurfaceProjector.cs deleted file mode 100644 index 1b11f4616..000000000 --- a/Aetheria.State/AetheriaCatalogSurfaceProjector.cs +++ /dev/null @@ -1,121 +0,0 @@ -using System; -using System.Linq; -using Aetheria.State.Documents; -using GameCult.Aetheria.State.Verse; - -namespace Aetheria.State; - -public static class AetheriaCatalogSurfaceProjector -{ - public const string SurfaceKey = "eve:surface:aetheria.catalog.operator"; - public const string SurfaceId = AetheriaRuntimeCatalogCommands.SurfaceId; - - public static EveSurfaceState Build(AetheriaRuntimeCatalogSnapshot catalog, string updatedAtUtc, long version = 1) - { - var tradeItems = catalog.TradeItems.Take(12).Select(item => - Row( - $"item.{SafeId(item.ItemKey)}", - ("name", item.Name), - ("manufacturer", catalog.GetManufacturer(item)?.Name ?? "GameCult"), - ("price", item.Price.ToString("N0")), - ("size", item.ShapeWidth > 0 && item.ShapeHeight > 0 ? $"{item.ShapeWidth}x{item.ShapeHeight}" : ""))) - .ToArray(); - - var corporations = catalog.Corporations.Take(12).Select(corporation => - Row( - $"corporation.{SafeId(corporation.CorporationKey)}", - ("name", corporation.Name), - ("short", corporation.ShortName), - ("names", catalog.GetNameFile(corporation)?.Name ?? ""), - ("influence", corporation.InfluenceDistance.ToString()))) - .ToArray(); - var refreshCommand = GameCult.Mesh.CultMesh.OperationBindingRecord( - GameCult.Mesh.CultMesh.OperationBinding( - AetheriaRuntimeCatalogCommands.Refresh, - label: "Refresh", - routeHint: new GameCult.Mesh.CultMeshRouteHint( - GameCult.Mesh.CultMeshLocalityKind.Automatic, - "cultmesh"))); - - return new EveSurfaceState - { - ProviderId = "aetheria", - ProviderKind = "game.runtime", - Title = "Aetheria Catalog", - Version = version, - UpdatedAtUtc = updatedAtUtc, - Surface = new EveSurface - { - Id = SurfaceId, - Root = Node( - "aetheria.catalog.root", - "surface", - [], - Node( - "aetheria.catalog.summary", - "grid", - [("columns", "6")], - Metric("summary.items", "Items", catalog.Items.Count.ToString()), - Metric("summary.trade", "Trade Items", catalog.TradeItems.Count().ToString()), - Metric("summary.equipment", "Equipment", catalog.EquipmentItems.Count().ToString()), - Metric("summary.behaviors", "Behavior Kinds", catalog.Items.SelectMany(item => item.BehaviorKinds).Distinct().Count().ToString()), - Metric("summary.corporations", "Corporations", catalog.Corporations.Count.ToString()), - Metric("summary.nameFiles", "Name Files", catalog.NameFiles.Count.ToString())), - Node( - "aetheria.catalog.trade", - "card", - [("title", "Trade Catalog")], - Node("aetheria.catalog.trade.rows", "inspector.kv", [], tradeItems)), - Node( - "aetheria.catalog.corporations", - "card", - [("title", "Corporations")], - Node("aetheria.catalog.corporation.rows", "inspector.kv", [], corporations))) - }, - Commands = - [ - new EveCommandTemplate - { - Command = refreshCommand.OperationId, - Label = refreshCommand.Label, - Transport = refreshCommand.RouteDescription, - SchemaId = refreshCommand.SchemaId, - RouteKind = refreshCommand.RouteKind, - RouteDescription = refreshCommand.RouteDescription - } - ] - }; - } - - private static EveSurfaceComponent Metric(string id, string label, string value) - { - return Node(id, "metric", [("label", label), ("value", value)]); - } - - private static EveSurfaceComponent Row(string id, params (string Key, string Value)[] props) - { - return Node(id, "row", props); - } - - private static EveSurfaceComponent Node( - string id, - string kind, - (string Key, string Value)[] props, - params EveSurfaceComponent[] children) - { - return new EveSurfaceComponent - { - Id = id, - Kind = kind, - Props = props.ToDictionary(prop => prop.Key, prop => prop.Value), - Children = children - }; - } - - private static string SafeId(string value) - { - return string.IsNullOrWhiteSpace(value) - ? "empty" - : new string(value.Select(character => char.IsLetterOrDigit(character) ? character : '.').ToArray()); - } -} diff --git a/Aetheria.State/AetheriaEveCommandBridge.cs b/Aetheria.State/AetheriaEveCommandBridge.cs index 639e6a1de..1032b47d0 100644 --- a/Aetheria.State/AetheriaEveCommandBridge.cs +++ b/Aetheria.State/AetheriaEveCommandBridge.cs @@ -52,7 +52,7 @@ public static class AetheriaEveCommandBridge case AetheriaRuntimeEveCommandKind.CatalogRefresh: var catalog = await node.RuntimeCatalog().LatestAsync().ConfigureAwait(false); await node.MutableDocument(AetheriaStateNode.CatalogSurfaceKey) - .ReplaceAsync(AetheriaCatalogSurfaceProjector.Build(catalog, command.IssuedAtUtc)) + .ReplaceAsync(AetheriaEveSurfaceDocuments.BuildCatalogSurface(catalog, command.IssuedAtUtc)) .ConfigureAwait(false); report.AcceptedCatalogRefreshes++; break; @@ -62,7 +62,7 @@ public static class AetheriaEveCommandBridge var verseHostSettings = await node.MutableDocument(AetheriaStateNode.VerseHostSettingsKey).ReadAsync().ConfigureAwait(false); var runtimeSession = await node.MutableDocument(AetheriaStateNode.RuntimeSessionKey(eveStatus.RuntimeId)).ReadAsync().ConfigureAwait(false); await node.MutableDocument(AetheriaStateNode.OperationsSurfaceKey) - .ReplaceAsync(AetheriaOperationsSurfaceProjector.Build( + .ReplaceAsync(AetheriaEveSurfaceDocuments.BuildOperationsSurface( eveStatus, verseHostSettings, runtimeSession)) @@ -123,7 +123,7 @@ public static class AetheriaEveCommandBridge { if (!string.Equals(command.Schema, CommandSchema, StringComparison.Ordinal)) return $"Unexpected Eve command schema '{command.Schema}'."; - if (!string.Equals(command.ProviderId, AetheriaProviderAdvertisementProjector.ProviderId, StringComparison.Ordinal)) + if (!string.Equals(command.ProviderId, AetheriaEveSurfaceDocuments.ProviderId, StringComparison.Ordinal)) return $"Unexpected Eve provider '{command.ProviderId}'."; if (command.Kind == AetheriaRuntimeEveCommandKind.Unknown) return $"Unknown typed Eve command kind for surface '{command.SurfaceId}' command '{command.Command}'."; @@ -189,7 +189,7 @@ public static class AetheriaEveCommandBridge } await node.MutableDocument(AetheriaStateNode.PlayerSettingsSurfaceKey) - .ReplaceAsync(AetheriaPlayerSettingsSurfaceProjector.Build(settings, command.IssuedAtUtc)) + .ReplaceAsync(AetheriaEveSurfaceDocuments.BuildPlayerSettingsSurface(settings, command.IssuedAtUtc)) .ConfigureAwait(false); } @@ -283,13 +283,13 @@ public static class AetheriaEveCommandBridge var runtimeSession = await node.MutableDocument(AetheriaStateNode.RuntimeSessionKey(eveStatus.RuntimeId)).ReadAsync().ConfigureAwait(false); await node.MutableDocument(AetheriaStateNode.OperationsSurfaceKey) - .ReplaceAsync(AetheriaOperationsSurfaceProjector.Build( + .ReplaceAsync(AetheriaEveSurfaceDocuments.BuildOperationsSurface( eveStatus, normalized, runtimeSession)) .ConfigureAwait(false); await node.MutableDocument(AetheriaStateNode.ProviderAdvertisementSurfaceKey) - .ReplaceAsync(AetheriaProviderAdvertisementProjector.Build(normalized, node.StatePath, command.IssuedAtUtc)) + .ReplaceAsync(AetheriaEveSurfaceDocuments.BuildProviderAdvertisement(normalized, node.StatePath, command.IssuedAtUtc)) .ConfigureAwait(false); } diff --git a/Aetheria.State/AetheriaEveSurfaceDocuments.cs b/Aetheria.State/AetheriaEveSurfaceDocuments.cs new file mode 100644 index 000000000..accbe1b80 --- /dev/null +++ b/Aetheria.State/AetheriaEveSurfaceDocuments.cs @@ -0,0 +1,525 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Aetheria.State.Documents; +using GameCult.Aetheria.State.Verse; +using GameCult.Mesh; + +namespace Aetheria.State; + +public static class AetheriaEveSurfaceDocuments +{ + public const string ProviderId = "aetheria"; + public const string ProviderAdvertisementKey = "eve:provider:aetheria"; + public const string CatalogSurfaceKey = "eve:surface:aetheria.catalog.operator"; + public const string OperationsSurfaceKey = "eve:surface:aetheria.operations"; + public const string PlayerSettingsSurfaceKey = "eve:surface:aetheria.player_settings"; + public const string DaemonGameSurfaceKey = "eve:surface:aetheria.daemon.game"; + public const string DaemonGameTuiSurfaceKey = "eve:surface:aetheria.daemon.game.tui"; + public const string DaemonEditorSurfaceKey = "eve:surface:aetheria.daemon.editor"; + public const string DaemonEditorTuiSurfaceKey = "eve:surface:aetheria.daemon.editor.tui"; + + public const string CatalogSurfaceId = AetheriaRuntimeCatalogCommands.SurfaceId; + public const string OperationsSurfaceId = AetheriaRuntimeOperationsCommands.SurfaceId; + public const string PlayerSettingsSurfaceId = AetheriaRuntimePlayerSettingsCommands.SurfaceId; + + private const string DaemonCommandBoundaryId = "aetheria.daemon.commands"; + private const string DaemonRecordTransport = "cultmesh-record"; + + public static EveSurfaceState BuildCatalogSurface( + AetheriaRuntimeCatalogSnapshot catalog, + string updatedAtUtc, + long version = 1) + { + var tradeItems = catalog.TradeItems.Take(12).Select(item => + Row( + $"item.{SafeId(item.ItemKey)}", + ("name", item.Name), + ("manufacturer", catalog.GetManufacturer(item)?.Name ?? "GameCult"), + ("price", item.Price.ToString("N0")), + ("size", item.ShapeWidth > 0 && item.ShapeHeight > 0 ? $"{item.ShapeWidth}x{item.ShapeHeight}" : ""))) + .ToArray(); + + var corporations = catalog.Corporations.Take(12).Select(corporation => + Row( + $"corporation.{SafeId(corporation.CorporationKey)}", + ("name", corporation.Name), + ("short", corporation.ShortName), + ("names", catalog.GetNameFile(corporation)?.Name ?? ""), + ("influence", corporation.InfluenceDistance.ToString()))) + .ToArray(); + var refreshCommand = CultMesh.OperationBindingRecord( + CultMesh.OperationBinding( + AetheriaRuntimeCatalogCommands.Refresh, + label: "Refresh", + routeHint: new CultMeshRouteHint( + CultMeshLocalityKind.Automatic, + "cultmesh"))); + + return new EveSurfaceState + { + ProviderId = ProviderId, + ProviderKind = "game.runtime", + Title = "Aetheria Catalog", + Version = version, + UpdatedAtUtc = updatedAtUtc, + Surface = new EveSurface + { + Id = CatalogSurfaceId, + Root = Node( + "aetheria.catalog.root", + "surface", + [], + Node( + "aetheria.catalog.summary", + "grid", + [("columns", "6")], + Metric("summary.items", "Items", catalog.Items.Count.ToString()), + Metric("summary.trade", "Trade Items", catalog.TradeItems.Count().ToString()), + Metric("summary.equipment", "Equipment", catalog.EquipmentItems.Count().ToString()), + Metric("summary.behaviors", "Behavior Kinds", catalog.Items.SelectMany(item => item.BehaviorKinds).Distinct().Count().ToString()), + Metric("summary.corporations", "Corporations", catalog.Corporations.Count.ToString()), + Metric("summary.nameFiles", "Name Files", catalog.NameFiles.Count.ToString())), + Node( + "aetheria.catalog.trade", + "card", + [("title", "Trade Catalog")], + Node("aetheria.catalog.trade.rows", "inspector.kv", [], tradeItems)), + Node( + "aetheria.catalog.corporations", + "card", + [("title", "Corporations")], + Node("aetheria.catalog.corporation.rows", "inspector.kv", [], corporations))) + }, + Commands = + [ + new EveCommandTemplate + { + Command = refreshCommand.OperationId, + Label = refreshCommand.Label, + Transport = refreshCommand.RouteDescription, + SchemaId = refreshCommand.SchemaId, + RouteKind = refreshCommand.RouteKind, + RouteDescription = refreshCommand.RouteDescription + } + ] + }; + } + + public static EveSurfaceState BuildOperationsSurface( + AetheriaEveCommandAcceptanceStatus? eveCommandStatus = null, + AetheriaVerseHostSettings? verseHostSettings = null, + AetheriaRuntimeSession? runtimeSession = null, + long version = 1) + { + var normalizedVerseHost = AetheriaVerseHostSettingsNormalizer.Normalize(verseHostSettings); + var updatedAtUtc = LatestTimestamp( + eveCommandStatus?.LastPollAtUtc, + normalizedVerseHost.LastUpdatedAtUtc, + runtimeSession?.LastSeenAtUtc); + var refreshCommand = CultMesh.OperationBindingRecord( + CultMesh.OperationBinding( + AetheriaRuntimeOperationsCommands.Refresh, + label: "Refresh", + routeHint: new CultMeshRouteHint( + CultMeshLocalityKind.Automatic, + "cultmesh"))); + return new EveSurfaceState + { + ProviderId = ProviderId, + ProviderKind = "game.runtime", + Title = "Aetheria Operations", + Version = version, + UpdatedAtUtc = updatedAtUtc, + Surface = new EveSurface + { + Id = OperationsSurfaceId, + Root = Node( + "aetheria.operations.root", + "surface", + [], + Node( + "aetheria.operations.eveCommandAcceptance", + "card", + [("title", "Eve Request Acceptance")], + Metric("eveCommandAcceptance.status", "Status", eveCommandStatus?.Status ?? "missing"), + Metric("eveCommandAcceptance.observed", "Observed Before Accept", (eveCommandStatus?.ObservedBeforeAccept ?? 0).ToString()), + Metric("eveCommandAcceptance.accepted", "Commands Accepted", (eveCommandStatus?.CommandsAccepted ?? 0).ToString()), + Metric("eveCommandAcceptance.rejected", "Commands Rejected", (eveCommandStatus?.CommandsRejected ?? 0).ToString()), + Metric("eveCommandAcceptance.catalogRefreshes", "Catalog Refreshes", (eveCommandStatus?.AppliedCatalogRefreshes ?? 0).ToString()), + Metric("eveCommandAcceptance.operationsRefreshes", "Operations Refreshes", (eveCommandStatus?.AppliedOperationsRefreshes ?? 0).ToString()), + Metric("eveCommandAcceptance.playerSettings", "Player Settings Commands", (eveCommandStatus?.AppliedPlayerSettingsCommands ?? 0).ToString()), + Metric("eveCommandAcceptance.inputSettings", "Input Settings Commands", (eveCommandStatus?.AppliedInputSettingsCommands ?? 0).ToString()), + Metric("eveCommandAcceptance.loadoutTemplates", "Loadout Template Commands", (eveCommandStatus?.AppliedLoadoutTemplateCommands ?? 0).ToString()), + Metric("eveCommandAcceptance.verseHost", "Verse Host Commands", (eveCommandStatus?.AppliedVerseHostCommands ?? 0).ToString()), + Metric("eveCommandAcceptance.failures", "Consecutive Failures", (eveCommandStatus?.ConsecutiveFailures ?? 0).ToString()), + Row( + "eveCommandAcceptance.last", + ("runtime", eveCommandStatus?.RuntimeId ?? ""), + ("lastPoll", eveCommandStatus?.LastPollAtUtc ?? ""), + ("lastAccepted", eveCommandStatus?.LastAcceptedAtUtc ?? ""), + ("lastRejected", eveCommandStatus?.LastRejectedCommand ?? ""), + ("rejectedReason", eveCommandStatus?.LastRejectedReason ?? ""), + ("error", eveCommandStatus?.LastError ?? ""))), + Node( + "aetheria.operations.verseHost", + "card", + [("title", "Verse Host")], + Metric("verseHost.visibility", "Visibility", normalizedVerseHost.Visibility), + Metric("verseHost.service", "Service", normalizedVerseHost.ServiceId), + Metric("verseHost.verse", "Verse", normalizedVerseHost.VerseId), + Row( + "verseHost.identity", + ("rootVerse", normalizedVerseHost.RootVerse), + ("canonicalService", normalizedVerseHost.CanonicalService), + ("locatedService", normalizedVerseHost.LocatedService), + ("cultMeshAddress", normalizedVerseHost.CultMeshAddress))), + Node( + "aetheria.operations.runtimeSession", + "card", + [("title", "Runtime Session")], + Metric("runtimeSession.status", "Status", runtimeSession?.Status ?? "missing"), + Metric("runtimeSession.role", "Role", runtimeSession?.Role ?? ""), + Row( + "runtimeSession.last", + ("runtime", runtimeSession?.RuntimeId ?? ""), + ("started", runtimeSession?.StartedAtUtc ?? ""), + ("lastSeen", runtimeSession?.LastSeenAtUtc ?? "")))) + }, + Commands = + [ + new EveCommandTemplate + { + Command = refreshCommand.OperationId, + Label = refreshCommand.Label, + Transport = refreshCommand.RouteDescription, + SchemaId = refreshCommand.SchemaId, + RouteKind = refreshCommand.RouteKind, + RouteDescription = refreshCommand.RouteDescription + } + ] + }; + } + + public static EveSurfaceState BuildPlayerSettingsSurface( + AetheriaPlayerSettings? settings, + string updatedAtUtc, + long version = 1) + { + settings ??= new AetheriaPlayerSettings(); + var gameplay = settings.Gameplay ?? new AetheriaPlayerGameplaySettings(); + var graphics = settings.Graphics ?? new AetheriaPlayerGraphicsSettings(); + var publishedAtUtc = !string.IsNullOrWhiteSpace(settings.LastUpdatedAtUtc) + ? settings.LastUpdatedAtUtc + : updatedAtUtc; + + var surface = AetheriaRuntimePlayerSettingsSurfaceBuilder.Build( + new AetheriaRuntimePlayerSettingsSurfaceState( + settings.PlayerName, + settings.TutorialPassed, + settings.ActiveRunKey, + gameplay.TemperatureUnit, + gameplay.SignificantDigits, + graphics.NebulaQuality, + graphics.ShowAsteroidsInMinimap, + publishedAtUtc), + version); + + return new EveSurfaceState + { + ProviderId = surface.ProviderId, + ProviderKind = surface.ProviderKind, + Title = surface.Title, + Version = surface.Version, + UpdatedAtUtc = surface.UpdatedAtUtc, + Surface = new EveSurface + { + Id = surface.Surface.Id, + Root = ConvertComponent(surface.Surface.Root), + Styles = surface.Surface.Styles + .Select(style => new EveStyleToken + { + Name = style.Name, + Value = style.Value + }) + .ToArray() + }, + Commands = surface.Commands + .Select(command => + { + var record = CultMesh.OperationBindingRecord(command.Operation); + return new EveCommandTemplate + { + Command = record.OperationId, + Label = record.Label, + Transport = record.RouteDescription, + SchemaId = record.SchemaId, + RouteKind = record.RouteKind, + RouteDescription = record.RouteDescription + }; + }) + .ToArray() + }; + } + + public static EveProviderAdvertisementState BuildProviderAdvertisement( + AetheriaVerseHostSettings settings, + string statePath, + string updatedAtUtc) + { + var normalized = AetheriaVerseHostSettingsNormalizer.Normalize(settings); + return new EveProviderAdvertisementState + { + ProviderId = ProviderId, + ServiceId = normalized.ServiceId, + VerseId = normalized.VerseId, + RootVerse = normalized.RootVerse, + CanonicalService = normalized.CanonicalService, + LocatedService = normalized.LocatedService, + CultMeshAddress = normalized.CultMeshAddress, + Title = normalized.Title, + Kind = "game.runtime", + UpdatedAtUtc = updatedAtUtc, + Freshness = new EveProviderFreshness + { + State = "fresh", + LastSeenAtUtc = updatedAtUtc, + MaxAgeMs = 15000 + }, + Schemas = + [ + "aetheria.world_state.v1", + "aetheria.item_definition.v1", + "aetheria.corporation.v2", + "aetheria.name_file.v2", + "aetheria.trade_value_policy.v1", + "aetheria.player_settings.v1", + "aetheria.loadout_template.v1", + "aetheria.run_state.v1", + "aetheria.zone_state.v1", + "aetheria.entity_snapshot.v1", + "aetheria.verse_host_settings.v1", + "aetheria.runtime_session.v1", + "aetheria.eve_command_acceptance_status.v1", + "gamecult.eve.surface.v1", + "gamecult.eve.command.v1", + AetheriaRuntimeDaemonSchemas.ProviderAdvertisement, + AetheriaRuntimeDaemonSchemas.Frame, + AetheriaRuntimeDaemonSchemas.SoaView, + AetheriaRuntimeDaemonSchemas.Health, + AetheriaRuntimeDaemonSchemas.CommandBoundary, + AetheriaRuntimeDaemonSchemas.GameSurface, + AetheriaRuntimeDaemonSchemas.EditorSurface, + AetheriaRuntimeDaemonSchemas.Command + ], + Witnesses = + [ + new EveProviderWitness + { + Kind = "cultcache", + Ref = statePath, + Summary = "Aetheria typed CultCache state file" + }, + new EveProviderWitness + { + Kind = DaemonRecordTransport, + Ref = AetheriaRuntimeVerseRecordKeys.DaemonProviderAdvertisement.ToString(), + Summary = "Aetheria daemon-owned provider advertisement record" + }, + new EveProviderWitness + { + Kind = DaemonRecordTransport, + Ref = AetheriaRuntimeVerseRecordKeys.DaemonFrameLatest.ToString(), + Summary = "Aetheria daemon latest simulation frame record" + }, + new EveProviderWitness + { + Kind = DaemonRecordTransport, + Ref = AetheriaRuntimeVerseRecordKeys.DaemonSoaViewLatest.ToString(), + Summary = "Aetheria daemon latest SoA view record for thin clients" + }, + new EveProviderWitness + { + Kind = DaemonRecordTransport, + Ref = AetheriaRuntimeVerseRecordKeys.DaemonHealth.ToString(), + Summary = "Aetheria daemon health record" + }, + new EveProviderWitness + { + Kind = DaemonRecordTransport, + Ref = AetheriaRuntimeVerseRecordKeys.DaemonCommandBoundary.ToString(), + Summary = "Aetheria daemon typed command boundary record" + }, + new EveProviderWitness + { + Kind = DaemonRecordTransport, + Ref = AetheriaRuntimeVerseRecordKeys.DaemonGameSurface.ToString(), + Summary = "Aetheria daemon game Eve GUI surface record" + }, + new EveProviderWitness + { + Kind = DaemonRecordTransport, + Ref = AetheriaRuntimeVerseRecordKeys.DaemonGameTuiSurface.ToString(), + Summary = "Aetheria daemon game Eve TUI surface record" + }, + new EveProviderWitness + { + Kind = DaemonRecordTransport, + Ref = AetheriaRuntimeVerseRecordKeys.DaemonEditorSurface.ToString(), + Summary = "Aetheria daemon editor Eve GUI surface record" + }, + new EveProviderWitness + { + Kind = DaemonRecordTransport, + Ref = AetheriaRuntimeVerseRecordKeys.DaemonEditorTuiSurface.ToString(), + Summary = "Aetheria daemon editor Eve TUI surface record" + } + ], + Surfaces = + [ + new EveProviderSurfaceRef + { + SurfaceId = CatalogSurfaceId, + Key = CatalogSurfaceKey + }, + new EveProviderSurfaceRef + { + SurfaceId = OperationsSurfaceId, + Key = OperationsSurfaceKey + }, + new EveProviderSurfaceRef + { + SurfaceId = PlayerSettingsSurfaceId, + Key = PlayerSettingsSurfaceKey + }, + new EveProviderSurfaceRef + { + SurfaceId = AetheriaRuntimeDaemonGameSurfaceBuilder.SurfaceId, + Key = DaemonGameSurfaceKey + }, + new EveProviderSurfaceRef + { + SurfaceId = AetheriaRuntimeDaemonGameSurfaceBuilder.TuiSurfaceId, + Key = DaemonGameTuiSurfaceKey + }, + new EveProviderSurfaceRef + { + SurfaceId = AetheriaRuntimeDaemonEditorSurfaceBuilder.SurfaceId, + Key = DaemonEditorSurfaceKey + }, + new EveProviderSurfaceRef + { + SurfaceId = AetheriaRuntimeDaemonEditorSurfaceBuilder.TuiSurfaceId, + Key = DaemonEditorTuiSurfaceKey + } + ], + Commands = + [ + new EveProviderCommandRef + { + Command = DaemonCommandBoundaryId, + Transport = "cultmesh", + Summary = "Aetheria daemon typed command boundary" + }, + new EveProviderCommandRef + { + Command = AetheriaRuntimeCatalogCommands.Refresh, + Summary = "Refresh catalog state" + }, + new EveProviderCommandRef + { + Command = AetheriaRuntimeOperationsCommands.Refresh, + Summary = "Refresh operations state" + }, + new EveProviderCommandRef + { + Command = AetheriaRuntimePlayerSettingsCommands.Refresh, + Summary = "Refresh player settings state" + }, + new EveProviderCommandRef + { + Command = AetheriaRuntimePlayerSettingsCommands.CycleTemperatureUnit, + Summary = "Cycle the typed player temperature unit" + }, + new EveProviderCommandRef + { + Command = AetheriaRuntimePlayerSettingsCommands.DecrementSignificantDigits, + Summary = "Decrease typed player significant digits" + }, + new EveProviderCommandRef + { + Command = AetheriaRuntimePlayerSettingsCommands.IncrementSignificantDigits, + Summary = "Increase typed player significant digits" + }, + new EveProviderCommandRef + { + Command = AetheriaRuntimePlayerSettingsCommands.CycleNebulaQuality, + Summary = "Cycle typed player nebula quality" + }, + new EveProviderCommandRef + { + Command = AetheriaRuntimePlayerSettingsCommands.ToggleShowAsteroidsInMinimap, + Summary = "Toggle typed player minimap asteroid visibility" + } + ] + }; + } + + private static string LatestTimestamp(params string?[] timestamps) + { + var latest = ""; + foreach (var timestamp in timestamps) + { + if (!string.IsNullOrWhiteSpace(timestamp) && + (string.IsNullOrWhiteSpace(latest) || string.CompareOrdinal(timestamp, latest) > 0)) + { + latest = timestamp; + } + } + + return latest; + } + + private static EveSurfaceComponent Metric(string id, string label, string value) + { + return Node(id, "metric", [("label", label), ("value", value)]); + } + + private static EveSurfaceComponent Row(string id, params (string Key, string Value)[] props) + { + return Node(id, "row", props); + } + + private static EveSurfaceComponent Node( + string id, + string kind, + (string Key, string Value)[] props, + params EveSurfaceComponent[] children) + { + return new EveSurfaceComponent + { + Id = id, + Kind = kind, + Props = props.ToDictionary(prop => prop.Key, prop => prop.Value), + Children = children + }; + } + + private static EveSurfaceComponent ConvertComponent(AetheriaRuntimeSurfaceComponent component) + { + return new EveSurfaceComponent + { + Id = component.Id, + Kind = component.Kind, + Props = new Dictionary(component.Props, StringComparer.Ordinal), + Children = component.Children.Select(ConvertComponent).ToArray() + }; + } + + private static string SafeId(string value) + { + return string.IsNullOrWhiteSpace(value) + ? "empty" + : new string(value.Select(character => char.IsLetterOrDigit(character) ? character : '.').ToArray()); + } +} diff --git a/Aetheria.State/AetheriaOperationsSurfaceProjector.cs b/Aetheria.State/AetheriaOperationsSurfaceProjector.cs deleted file mode 100644 index 15e1bb03b..000000000 --- a/Aetheria.State/AetheriaOperationsSurfaceProjector.cs +++ /dev/null @@ -1,145 +0,0 @@ -using Aetheria.State.Documents; -using GameCult.Aetheria.State.Verse; - -namespace Aetheria.State; - -public static class AetheriaOperationsSurfaceProjector -{ - public const string SurfaceKey = "eve:surface:aetheria.operations"; - public const string SurfaceId = AetheriaRuntimeOperationsCommands.SurfaceId; - - public static EveSurfaceState Build( - AetheriaEveCommandAcceptanceStatus? eveCommandStatus = null, - AetheriaVerseHostSettings? verseHostSettings = null, - AetheriaRuntimeSession? runtimeSession = null, - long version = 1) - { - var normalizedVerseHost = AetheriaVerseHostSettingsNormalizer.Normalize(verseHostSettings); - var updatedAtUtc = LatestTimestamp( - eveCommandStatus?.LastPollAtUtc, - normalizedVerseHost.LastUpdatedAtUtc, - runtimeSession?.LastSeenAtUtc); - var refreshCommand = GameCult.Mesh.CultMesh.OperationBindingRecord( - GameCult.Mesh.CultMesh.OperationBinding( - AetheriaRuntimeOperationsCommands.Refresh, - label: "Refresh", - routeHint: new GameCult.Mesh.CultMeshRouteHint( - GameCult.Mesh.CultMeshLocalityKind.Automatic, - "cultmesh"))); - return new EveSurfaceState - { - ProviderId = "aetheria", - ProviderKind = "game.runtime", - Title = "Aetheria Operations", - Version = version, - UpdatedAtUtc = updatedAtUtc, - Surface = new EveSurface - { - Id = SurfaceId, - Root = Node( - "aetheria.operations.root", - "surface", - [], - Node( - "aetheria.operations.eveCommandAcceptance", - "card", - [("title", "Eve Request Acceptance")], - Metric("eveCommandAcceptance.status", "Status", eveCommandStatus?.Status ?? "missing"), - Metric("eveCommandAcceptance.observed", "Observed Before Accept", (eveCommandStatus?.ObservedBeforeAccept ?? 0).ToString()), - Metric("eveCommandAcceptance.accepted", "Commands Accepted", (eveCommandStatus?.CommandsAccepted ?? 0).ToString()), - Metric("eveCommandAcceptance.rejected", "Commands Rejected", (eveCommandStatus?.CommandsRejected ?? 0).ToString()), - Metric("eveCommandAcceptance.catalogRefreshes", "Catalog Refreshes", (eveCommandStatus?.AppliedCatalogRefreshes ?? 0).ToString()), - Metric("eveCommandAcceptance.operationsRefreshes", "Operations Refreshes", (eveCommandStatus?.AppliedOperationsRefreshes ?? 0).ToString()), - Metric("eveCommandAcceptance.playerSettings", "Player Settings Commands", (eveCommandStatus?.AppliedPlayerSettingsCommands ?? 0).ToString()), - Metric("eveCommandAcceptance.inputSettings", "Input Settings Commands", (eveCommandStatus?.AppliedInputSettingsCommands ?? 0).ToString()), - Metric("eveCommandAcceptance.loadoutTemplates", "Loadout Template Commands", (eveCommandStatus?.AppliedLoadoutTemplateCommands ?? 0).ToString()), - Metric("eveCommandAcceptance.verseHost", "Verse Host Commands", (eveCommandStatus?.AppliedVerseHostCommands ?? 0).ToString()), - Metric("eveCommandAcceptance.failures", "Consecutive Failures", (eveCommandStatus?.ConsecutiveFailures ?? 0).ToString()), - Row( - "eveCommandAcceptance.last", - ("runtime", eveCommandStatus?.RuntimeId ?? ""), - ("lastPoll", eveCommandStatus?.LastPollAtUtc ?? ""), - ("lastAccepted", eveCommandStatus?.LastAcceptedAtUtc ?? ""), - ("lastRejected", eveCommandStatus?.LastRejectedCommand ?? ""), - ("rejectedReason", eveCommandStatus?.LastRejectedReason ?? ""), - ("error", eveCommandStatus?.LastError ?? ""))), - Node( - "aetheria.operations.verseHost", - "card", - [("title", "Verse Host")], - Metric("verseHost.visibility", "Visibility", normalizedVerseHost.Visibility), - Metric("verseHost.service", "Service", normalizedVerseHost.ServiceId), - Metric("verseHost.verse", "Verse", normalizedVerseHost.VerseId), - Row( - "verseHost.identity", - ("rootVerse", normalizedVerseHost.RootVerse), - ("canonicalService", normalizedVerseHost.CanonicalService), - ("locatedService", normalizedVerseHost.LocatedService), - ("cultMeshAddress", normalizedVerseHost.CultMeshAddress))), - Node( - "aetheria.operations.runtimeSession", - "card", - [("title", "Runtime Session")], - Metric("runtimeSession.status", "Status", runtimeSession?.Status ?? "missing"), - Metric("runtimeSession.role", "Role", runtimeSession?.Role ?? ""), - Row( - "runtimeSession.last", - ("runtime", runtimeSession?.RuntimeId ?? ""), - ("started", runtimeSession?.StartedAtUtc ?? ""), - ("lastSeen", runtimeSession?.LastSeenAtUtc ?? "")))) - }, - Commands = - [ - new EveCommandTemplate - { - Command = refreshCommand.OperationId, - Label = refreshCommand.Label, - Transport = refreshCommand.RouteDescription, - SchemaId = refreshCommand.SchemaId, - RouteKind = refreshCommand.RouteKind, - RouteDescription = refreshCommand.RouteDescription - } - ] - }; - } - - private static string LatestTimestamp(params string?[] timestamps) - { - var latest = ""; - foreach (var timestamp in timestamps) - { - if (!string.IsNullOrWhiteSpace(timestamp) && - (string.IsNullOrWhiteSpace(latest) || string.CompareOrdinal(timestamp, latest) > 0)) - { - latest = timestamp; - } - } - - return latest; - } - - private static EveSurfaceComponent Metric(string id, string label, string value) - { - return Node(id, "metric", [("label", label), ("value", value)]); - } - - private static EveSurfaceComponent Row(string id, params (string Key, string Value)[] props) - { - return Node(id, "row", props); - } - - private static EveSurfaceComponent Node( - string id, - string kind, - (string Key, string Value)[] props, - params EveSurfaceComponent[] children) - { - return new EveSurfaceComponent - { - Id = id, - Kind = kind, - Props = props.ToDictionary(prop => prop.Key, prop => prop.Value), - Children = children - }; - } -} diff --git a/Aetheria.State/AetheriaPlayerSettingsSurfaceProjector.cs b/Aetheria.State/AetheriaPlayerSettingsSurfaceProjector.cs deleted file mode 100644 index 19cdb0127..000000000 --- a/Aetheria.State/AetheriaPlayerSettingsSurfaceProjector.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Aetheria.State.Documents; -using GameCult.Aetheria.State.Verse; - -namespace Aetheria.State; - -public static class AetheriaPlayerSettingsSurfaceProjector -{ - public const string SurfaceKey = "eve:surface:aetheria.player_settings"; - public const string SurfaceId = AetheriaRuntimePlayerSettingsCommands.SurfaceId; - - public static EveSurfaceState Build( - AetheriaPlayerSettings? settings, - string updatedAtUtc, - long version = 1) - { - settings ??= new AetheriaPlayerSettings(); - var gameplay = settings.Gameplay ?? new AetheriaPlayerGameplaySettings(); - var graphics = settings.Graphics ?? new AetheriaPlayerGraphicsSettings(); - var publishedAtUtc = !string.IsNullOrWhiteSpace(settings.LastUpdatedAtUtc) - ? settings.LastUpdatedAtUtc - : updatedAtUtc; - - var surface = AetheriaRuntimePlayerSettingsSurfaceBuilder.Build( - new AetheriaRuntimePlayerSettingsSurfaceState( - settings.PlayerName, - settings.TutorialPassed, - settings.ActiveRunKey, - gameplay.TemperatureUnit, - gameplay.SignificantDigits, - graphics.NebulaQuality, - graphics.ShowAsteroidsInMinimap, - publishedAtUtc), - version); - - return new EveSurfaceState - { - ProviderId = surface.ProviderId, - ProviderKind = surface.ProviderKind, - Title = surface.Title, - Version = surface.Version, - UpdatedAtUtc = surface.UpdatedAtUtc, - Surface = new EveSurface - { - Id = surface.Surface.Id, - Root = ConvertComponent(surface.Surface.Root), - Styles = surface.Surface.Styles - .Select(style => new EveStyleToken - { - Name = style.Name, - Value = style.Value - }) - .ToArray() - }, - Commands = surface.Commands - .Select(command => - { - var record = GameCult.Mesh.CultMesh.OperationBindingRecord(command.Operation); - return new EveCommandTemplate - { - Command = record.OperationId, - Label = record.Label, - Transport = record.RouteDescription, - SchemaId = record.SchemaId, - RouteKind = record.RouteKind, - RouteDescription = record.RouteDescription - }; - }) - .ToArray() - }; - } - - private static EveSurfaceComponent ConvertComponent(AetheriaRuntimeSurfaceComponent component) - { - return new EveSurfaceComponent - { - Id = component.Id, - Kind = component.Kind, - Props = new Dictionary(component.Props, StringComparer.Ordinal), - Children = component.Children.Select(ConvertComponent).ToArray() - }; - } -} diff --git a/Aetheria.State/AetheriaProviderAdvertisementProjector.cs b/Aetheria.State/AetheriaProviderAdvertisementProjector.cs deleted file mode 100644 index ad4c3cd14..000000000 --- a/Aetheria.State/AetheriaProviderAdvertisementProjector.cs +++ /dev/null @@ -1,219 +0,0 @@ -using Aetheria.State.Documents; -using GameCult.Aetheria.State.Verse; - -namespace Aetheria.State; - -public static class AetheriaProviderAdvertisementProjector -{ - public const string AdvertisementKey = "eve:provider:aetheria"; - public const string DaemonGameSurfaceKey = "eve:surface:aetheria.daemon.game"; - public const string DaemonGameTuiSurfaceKey = "eve:surface:aetheria.daemon.game.tui"; - public const string DaemonEditorSurfaceKey = "eve:surface:aetheria.daemon.editor"; - public const string DaemonEditorTuiSurfaceKey = "eve:surface:aetheria.daemon.editor.tui"; - public const string ProviderId = "aetheria"; - private const string DaemonCommandBoundaryId = "aetheria.daemon.commands"; - private const string DaemonRecordTransport = "cultmesh-record"; - - public static EveProviderAdvertisementState Build( - AetheriaVerseHostSettings settings, - string statePath, - string updatedAtUtc) - { - var normalized = AetheriaVerseHostSettingsNormalizer.Normalize(settings); - return new EveProviderAdvertisementState - { - ProviderId = ProviderId, - ServiceId = normalized.ServiceId, - VerseId = normalized.VerseId, - RootVerse = normalized.RootVerse, - CanonicalService = normalized.CanonicalService, - LocatedService = normalized.LocatedService, - CultMeshAddress = normalized.CultMeshAddress, - Title = normalized.Title, - Kind = "game.runtime", - UpdatedAtUtc = updatedAtUtc, - Freshness = new EveProviderFreshness - { - State = "fresh", - LastSeenAtUtc = updatedAtUtc, - MaxAgeMs = 15000 - }, - Schemas = - [ - "aetheria.world_state.v1", - "aetheria.item_definition.v1", - "aetheria.corporation.v2", - "aetheria.name_file.v2", - "aetheria.trade_value_policy.v1", - "aetheria.player_settings.v1", - "aetheria.loadout_template.v1", - "aetheria.run_state.v1", - "aetheria.zone_state.v1", - "aetheria.entity_snapshot.v1", - "aetheria.verse_host_settings.v1", - "aetheria.runtime_session.v1", - "aetheria.eve_command_acceptance_status.v1", - "gamecult.eve.surface.v1", - "gamecult.eve.command.v1", - AetheriaRuntimeDaemonSchemas.ProviderAdvertisement, - AetheriaRuntimeDaemonSchemas.Frame, - AetheriaRuntimeDaemonSchemas.SoaView, - AetheriaRuntimeDaemonSchemas.Health, - AetheriaRuntimeDaemonSchemas.CommandBoundary, - AetheriaRuntimeDaemonSchemas.GameSurface, - AetheriaRuntimeDaemonSchemas.EditorSurface, - AetheriaRuntimeDaemonSchemas.Command - ], - Witnesses = - [ - new EveProviderWitness - { - Kind = "cultcache", - Ref = statePath, - Summary = "Aetheria typed CultCache state file" - }, - new EveProviderWitness - { - Kind = DaemonRecordTransport, - Ref = AetheriaRuntimeVerseRecordKeys.DaemonProviderAdvertisement.ToString(), - Summary = "Aetheria daemon-owned provider advertisement record" - }, - new EveProviderWitness - { - Kind = DaemonRecordTransport, - Ref = AetheriaRuntimeVerseRecordKeys.DaemonFrameLatest.ToString(), - Summary = "Aetheria daemon latest simulation frame record" - }, - new EveProviderWitness - { - Kind = DaemonRecordTransport, - Ref = AetheriaRuntimeVerseRecordKeys.DaemonSoaViewLatest.ToString(), - Summary = "Aetheria daemon latest SoA view record for thin clients" - }, - new EveProviderWitness - { - Kind = DaemonRecordTransport, - Ref = AetheriaRuntimeVerseRecordKeys.DaemonHealth.ToString(), - Summary = "Aetheria daemon health record" - }, - new EveProviderWitness - { - Kind = DaemonRecordTransport, - Ref = AetheriaRuntimeVerseRecordKeys.DaemonCommandBoundary.ToString(), - Summary = "Aetheria daemon typed command boundary record" - }, - new EveProviderWitness - { - Kind = DaemonRecordTransport, - Ref = AetheriaRuntimeVerseRecordKeys.DaemonGameSurface.ToString(), - Summary = "Aetheria daemon game Eve GUI surface record" - }, - new EveProviderWitness - { - Kind = DaemonRecordTransport, - Ref = AetheriaRuntimeVerseRecordKeys.DaemonGameTuiSurface.ToString(), - Summary = "Aetheria daemon game Eve TUI surface record" - }, - new EveProviderWitness - { - Kind = DaemonRecordTransport, - Ref = AetheriaRuntimeVerseRecordKeys.DaemonEditorSurface.ToString(), - Summary = "Aetheria daemon editor Eve GUI surface record" - }, - new EveProviderWitness - { - Kind = DaemonRecordTransport, - Ref = AetheriaRuntimeVerseRecordKeys.DaemonEditorTuiSurface.ToString(), - Summary = "Aetheria daemon editor Eve TUI surface record" - } - ], - Surfaces = - [ - new EveProviderSurfaceRef - { - SurfaceId = AetheriaCatalogSurfaceProjector.SurfaceId, - Key = AetheriaCatalogSurfaceProjector.SurfaceKey - }, - new EveProviderSurfaceRef - { - SurfaceId = AetheriaOperationsSurfaceProjector.SurfaceId, - Key = AetheriaOperationsSurfaceProjector.SurfaceKey - }, - new EveProviderSurfaceRef - { - SurfaceId = AetheriaPlayerSettingsSurfaceProjector.SurfaceId, - Key = AetheriaPlayerSettingsSurfaceProjector.SurfaceKey - }, - new EveProviderSurfaceRef - { - SurfaceId = AetheriaRuntimeDaemonGameSurfaceBuilder.SurfaceId, - Key = DaemonGameSurfaceKey - }, - new EveProviderSurfaceRef - { - SurfaceId = AetheriaRuntimeDaemonGameSurfaceBuilder.TuiSurfaceId, - Key = DaemonGameTuiSurfaceKey - }, - new EveProviderSurfaceRef - { - SurfaceId = AetheriaRuntimeDaemonEditorSurfaceBuilder.SurfaceId, - Key = DaemonEditorSurfaceKey - }, - new EveProviderSurfaceRef - { - SurfaceId = AetheriaRuntimeDaemonEditorSurfaceBuilder.TuiSurfaceId, - Key = DaemonEditorTuiSurfaceKey - } - ], - Commands = - [ - new EveProviderCommandRef - { - Command = DaemonCommandBoundaryId, - Transport = "cultmesh", - Summary = "Aetheria daemon typed command boundary" - }, - new EveProviderCommandRef - { - Command = AetheriaRuntimeCatalogCommands.Refresh, - Summary = "Refresh catalog projection" - }, - new EveProviderCommandRef - { - Command = AetheriaRuntimeOperationsCommands.Refresh, - Summary = "Refresh operations projection" - }, - new EveProviderCommandRef - { - Command = AetheriaRuntimePlayerSettingsCommands.Refresh, - Summary = "Refresh player settings projection" - }, - new EveProviderCommandRef - { - Command = AetheriaRuntimePlayerSettingsCommands.CycleTemperatureUnit, - Summary = "Cycle the typed player temperature unit" - }, - new EveProviderCommandRef - { - Command = AetheriaRuntimePlayerSettingsCommands.DecrementSignificantDigits, - Summary = "Decrease typed player significant digits" - }, - new EveProviderCommandRef - { - Command = AetheriaRuntimePlayerSettingsCommands.IncrementSignificantDigits, - Summary = "Increase typed player significant digits" - }, - new EveProviderCommandRef - { - Command = AetheriaRuntimePlayerSettingsCommands.CycleNebulaQuality, - Summary = "Cycle typed player nebula quality" - }, - new EveProviderCommandRef - { - Command = AetheriaRuntimePlayerSettingsCommands.ToggleShowAsteroidsInMinimap, - Summary = "Toggle typed player minimap asteroid visibility" - } - ] - }; - } -} diff --git a/Aetheria.State/AetheriaStateNode.cs b/Aetheria.State/AetheriaStateNode.cs index 63885c056..6a56152fa 100644 --- a/Aetheria.State/AetheriaStateNode.cs +++ b/Aetheria.State/AetheriaStateNode.cs @@ -129,13 +129,13 @@ public sealed class AetheriaStateNode : IAsyncDisposable, IDisposable return _catalogSurface ??= CultMesh.Document( "aetheria.catalog.surface", CultMesh.Verse("aetheria.local", RuntimeId), - _ => Task.FromResult(AetheriaCatalogSurfaceProjector.Build( + _ => Task.FromResult(AetheriaEveSurfaceDocuments.BuildCatalogSurface( catalog.Latest(), DateTimeOffset.UtcNow.ToString("O"))), _ => Database.WatchRecord( AetheriaRuntimeVerseRecordKeys.DaemonFrameLatest) .Where(change => change.Document != null) - .Select(_ => AetheriaCatalogSurfaceProjector.Build( + .Select(_ => AetheriaEveSurfaceDocuments.BuildCatalogSurface( catalog.Latest(), DateTimeOffset.UtcNow.ToString("O"))), sources: new[] @@ -238,16 +238,16 @@ public sealed class AetheriaStateNode : IAsyncDisposable, IDisposable new("global:aetheria.legacy_catalog_quarantine.v1"); public static CultRecordKey CatalogSurfaceKey { get; } = - new(AetheriaCatalogSurfaceProjector.SurfaceKey); + new(AetheriaEveSurfaceDocuments.CatalogSurfaceKey); public static CultRecordKey OperationsSurfaceKey { get; } = - new(AetheriaOperationsSurfaceProjector.SurfaceKey); + new(AetheriaEveSurfaceDocuments.OperationsSurfaceKey); public static CultRecordKey PlayerSettingsSurfaceKey { get; } = - new(AetheriaPlayerSettingsSurfaceProjector.SurfaceKey); + new(AetheriaEveSurfaceDocuments.PlayerSettingsSurfaceKey); public static CultRecordKey ProviderAdvertisementSurfaceKey { get; } = - new(AetheriaProviderAdvertisementProjector.AdvertisementKey); + new(AetheriaEveSurfaceDocuments.ProviderAdvertisementKey); public static CultRecordKey PlayerSettingsKey { get; } = new("global:aetheria.player_settings.v1");