Collapse Eve surface projectors into typed documents

This commit is contained in:
Meta Vens 2026-06-29 04:31:20 +01:00
commit 87ac49ab89
11 changed files with 624 additions and 667 deletions

View file

@ -866,13 +866,13 @@ static async Task PublishStateSurfacesAsync(
: playerSettings.LastUpdatedAtUtc;
await node.MutableDocument<EveSurfaceState>(AetheriaStateNode.OperationsSurfaceKey)
.ReplaceAsync(AetheriaOperationsSurfaceProjector.Build(eveStatus, verseHost, runtimeSession))
.ReplaceAsync(AetheriaEveSurfaceDocuments.BuildOperationsSurface(eveStatus, verseHost, runtimeSession))
.ConfigureAwait(false);
await node.MutableDocument<EveSurfaceState>(AetheriaStateNode.PlayerSettingsSurfaceKey)
.ReplaceAsync(AetheriaPlayerSettingsSurfaceProjector.Build(playerSettings, playerSettingsUpdatedAt))
.ReplaceAsync(AetheriaEveSurfaceDocuments.BuildPlayerSettingsSurface(playerSettings, playerSettingsUpdatedAt))
.ConfigureAwait(false);
await node.MutableDocument<EveProviderAdvertisementState>(AetheriaStateNode.ProviderAdvertisementSurfaceKey)
.ReplaceAsync(AetheriaProviderAdvertisementProjector.Build(verseHost, node.StatePath, updatedAtUtc))
.ReplaceAsync(AetheriaEveSurfaceDocuments.BuildProviderAdvertisement(verseHost, node.StatePath, updatedAtUtc))
.ConfigureAwait(false);
await node.FlushAsync().ConfigureAwait(false);
}

View file

@ -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<EveSurfaceState>(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<AetheriaVerseHostSettings>(AetheriaStateNode.VerseHostSettingsKey).ReplaceAsync(verseHostSettings);
await node.MutableDocument<EveSurfaceState>(AetheriaStateNode.OperationsSurfaceKey)
.ReplaceAsync(AetheriaOperationsSurfaceProjector.Build(verseHostSettings: verseHostSettings));
.ReplaceAsync(AetheriaEveSurfaceDocuments.BuildOperationsSurface(verseHostSettings: verseHostSettings));
await node.MutableDocument<EveProviderAdvertisementState>(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<EveSurfaceState>(AetheriaStateNode.OperationsSurfaceKey).ReplaceAsync(AetheriaOperationsSurfaceProjector.Build(
await node.MutableDocument<EveSurfaceState>(AetheriaStateNode.OperationsSurfaceKey).ReplaceAsync(AetheriaEveSurfaceDocuments.BuildOperationsSurface(
verseHostSettings: verseHostSettings,
runtimeSession: await node.MutableDocument<AetheriaRuntimeSession>(AetheriaStateNode.RuntimeSessionKey("smoke-runtime")).ReadAsync()));
@ -535,7 +535,7 @@ await using (var node = await AetheriaStateNode.OpenAsync(statePath, "aetheria-s
}
});
await node.MutableDocument<EveSurfaceState>(AetheriaStateNode.PlayerSettingsSurfaceKey)
.ReplaceAsync(AetheriaPlayerSettingsSurfaceProjector.Build(
.ReplaceAsync(AetheriaEveSurfaceDocuments.BuildPlayerSettingsSurface(
await node.MutableDocument<AetheriaPlayerSettings>(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<AetheriaEveCommandAcceptanceStatus>(AetheriaStateNode.EveCommandAcceptanceStatusKey).ReplaceAsync(eveCommandStatus);
await node.MutableDocument<EveSurfaceState>(AetheriaStateNode.OperationsSurfaceKey).ReplaceAsync(AetheriaOperationsSurfaceProjector.Build(
await node.MutableDocument<EveSurfaceState>(AetheriaStateNode.OperationsSurfaceKey).ReplaceAsync(AetheriaEveSurfaceDocuments.BuildOperationsSurface(
eveCommandStatus,
verseHostSettings: await node.MutableDocument<AetheriaVerseHostSettings>(AetheriaStateNode.VerseHostSettingsKey).ReadAsync(),
runtimeSession: await node.MutableDocument<AetheriaRuntimeSession>(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"))
{

View file

@ -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.");
}

View file

@ -118,7 +118,7 @@ var items = node.Cache.GetAll<AetheriaItemDefinition>().ToArray();
var corporations = node.Cache.GetAll<AetheriaCorporation>().ToArray();
var nameFiles = node.Cache.GetAll<AetheriaNameFile>().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<AetheriaTradeValuePolicy>(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<EveSurfaceState>(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<EveSurfaceState>(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<AetheriaVerseHostSettings>(AetheriaStateNode.VerseHostSettingsKey).ReadAsync()",
"node.MutableDocument<AetheriaVerseHostSettings>(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<AetheriaVerseHostSettings>(AetheriaStateNode.VerseHostSettingsKey)",
".ReplaceAsync(normalized)",
"node.MutableDocument<EveProviderAdvertisementState>(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<EveSurfaceState>(AetheriaStateNode.OperationsSurfaceKey)",
"node.MutableDocument<EveSurfaceState>(AetheriaStateNode.PlayerSettingsSurfaceKey)",
"node.MutableDocument<EveProviderAdvertisementState>(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))

View file

@ -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());
}
}

View file

@ -52,7 +52,7 @@ public static class AetheriaEveCommandBridge
case AetheriaRuntimeEveCommandKind.CatalogRefresh:
var catalog = await node.RuntimeCatalog().LatestAsync().ConfigureAwait(false);
await node.MutableDocument<EveSurfaceState>(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<AetheriaVerseHostSettings>(AetheriaStateNode.VerseHostSettingsKey).ReadAsync().ConfigureAwait(false);
var runtimeSession = await node.MutableDocument<AetheriaRuntimeSession>(AetheriaStateNode.RuntimeSessionKey(eveStatus.RuntimeId)).ReadAsync().ConfigureAwait(false);
await node.MutableDocument<EveSurfaceState>(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<EveSurfaceState>(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<AetheriaRuntimeSession>(AetheriaStateNode.RuntimeSessionKey(eveStatus.RuntimeId)).ReadAsync().ConfigureAwait(false);
await node.MutableDocument<EveSurfaceState>(AetheriaStateNode.OperationsSurfaceKey)
.ReplaceAsync(AetheriaOperationsSurfaceProjector.Build(
.ReplaceAsync(AetheriaEveSurfaceDocuments.BuildOperationsSurface(
eveStatus,
normalized,
runtimeSession))
.ConfigureAwait(false);
await node.MutableDocument<EveProviderAdvertisementState>(AetheriaStateNode.ProviderAdvertisementSurfaceKey)
.ReplaceAsync(AetheriaProviderAdvertisementProjector.Build(normalized, node.StatePath, command.IssuedAtUtc))
.ReplaceAsync(AetheriaEveSurfaceDocuments.BuildProviderAdvertisement(normalized, node.StatePath, command.IssuedAtUtc))
.ConfigureAwait(false);
}

View file

@ -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<string, string>(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());
}
}

View file

@ -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
};
}
}

View file

@ -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<string, string>(component.Props, StringComparer.Ordinal),
Children = component.Children.Select(ConvertComponent).ToArray()
};
}
}

View file

@ -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"
}
]
};
}
}

View file

@ -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<AetheriaRuntimeDaemonFrameDocument>(
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");