From 188188cec856b3def698f5b0e07bd24ad7443a41 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Wed, 1 Jul 2026 14:33:46 +0100 Subject: [PATCH] Simplify CultMesh menu surface access --- Aetheria.State.Smoke/Program.cs | 13 +- Aetheria.State.Verify/Program.cs | 469 ++++++------ Assets/Scripts/UI/MainMenu.cs | 90 +-- GameData/aetheria-world.cc | Bin 74536 -> 32620 bytes .../Runtime/AetheriaRuntimeCatalogSnapshot.cs | 707 ++++++++++-------- .../AetheriaRuntimeDaemonTradeItemQueries.cs | 9 +- .../AetheriaRuntimeMainMenuSurfaceBuilder.cs | 39 +- ...eriaRuntimePlayerSettingsSurfaceBuilder.cs | 131 ---- .../AetheriaRuntimeSurfaceDocuments.cs | 131 ++++ 9 files changed, 823 insertions(+), 766 deletions(-) diff --git a/Aetheria.State.Smoke/Program.cs b/Aetheria.State.Smoke/Program.cs index 8eb34eed1..c04050401 100644 --- a/Aetheria.State.Smoke/Program.cs +++ b/Aetheria.State.Smoke/Program.cs @@ -731,14 +731,17 @@ await using (var reopened = await AetheriaStateNode.OpenAsync(statePath, "aether !advertisement.Schemas.Contains(AetheriaRuntimeDaemonSchemas.GameSurface) || !advertisement.Schemas.Contains(AetheriaRuntimeDaemonSchemas.EditorSurface) || !advertisement.Witnesses.Any(witness => - witness.Kind == "cultcache-witness" && - witness.Ref == AetheriaRuntimeStateBoundary.GetDaemonProviderPath(statePath)) || + witness.Kind == "cultcache" && + witness.Ref == statePath) || !advertisement.Witnesses.Any(witness => - witness.Kind == "cultcache-witness" && - witness.Ref == AetheriaRuntimeStateBoundary.GetDaemonCommandBoundaryPath(statePath)) || + witness.Kind == "cultmesh-record" && + witness.Ref == AetheriaRuntimeVerseRecordKeys.DaemonProviderAdvertisement.ToString()) || + !advertisement.Witnesses.Any(witness => + witness.Kind == "cultmesh-record" && + witness.Ref == AetheriaRuntimeVerseRecordKeys.DaemonCommandBoundary.ToString()) || !advertisement.Commands.Any(command => command.Command == "aetheria.daemon.commands" && - command.Transport == "cultcache-witness") || + command.Transport == "cultmesh") || !advertisement.Commands.Any(command => command.Command == "aetheria.player_settings.graphics.show_asteroids.toggle") || !advertisement.Schemas.Contains(AetheriaEveCommandBridge.CommandSchema)) { diff --git a/Aetheria.State.Verify/Program.cs b/Aetheria.State.Verify/Program.cs index 3f348e154..949bc7a15 100644 --- a/Aetheria.State.Verify/Program.cs +++ b/Aetheria.State.Verify/Program.cs @@ -571,7 +571,7 @@ Console.WriteLine($"Described/geoname-linked corporations: {describedCorporation Console.WriteLine($"Corporation allegiance edges: {corporationAllegianceEdges}"); Console.WriteLine($"Name files: {nameFiles.Length}"); Console.WriteLine("Live gameplay source purity: no serializer or legacy database symbols in Assets/Scripts"); -Console.WriteLine("Package serializer boundary: MessagePack symbols remain in named CultCache transport files only"); +Console.WriteLine("Package serializer boundary: MessagePack execution remains in named CultCache transport files; document DTOs may carry schema annotations"); Console.WriteLine("Shared Eve package ownership: generic Unity Eve packages import from the neighboring Eve repo instead of local staged copies"); Console.WriteLine("Typed runtime behavior coverage: live behavior kinds have typed factory plus progress/state restore coverage"); Console.WriteLine("Zone construction/runtime key authority: body/orbit wrappers and task shells retain typed keys instead of GUID sidecars"); @@ -873,7 +873,7 @@ static void RequireSharedEvePackagesImportedFromEveRepo(string root) !runtimeSurfaceDocuments.Contains("public IReadOnlyList StateBindings", StringComparison.Ordinal) || !runtimeSurfaceDocuments.Contains("public IReadOnlyList EmbeddedDocuments", StringComparison.Ordinal) || !runtimeSurfaceDocuments.Contains("public sealed class AetheriaRuntimeEmbeddedDocumentSlot", StringComparison.Ordinal) || - !runtimeSurfaceBuilder.Contains("public static CultMeshStateBindingDescriptor ForDaemonStateRef(", StringComparison.Ordinal) || + !runtimeSurfaceDocuments.Contains("public static CultMeshStateBindingDescriptor ForDaemonStateRef(", StringComparison.Ordinal) || !runtimeSurfaceDocuments.Contains("public CultMeshOperationBindingDescriptor Operation", StringComparison.Ordinal)) { throw new InvalidOperationException( @@ -888,10 +888,10 @@ static void RequireSharedEvePackagesImportedFromEveRepo(string root) "Aetheria runtime surfaces no longer hand CultMesh state bindings and embedded document slots to the shared Eve component model."); } - if (!runtimeSurfaceBuilder.Contains("CultMesh.StateBindingRecord(binding)", StringComparison.Ordinal) || + if (!runtimeSurfaceDocuments.Contains("CultMesh.StateBindingRecord(binding)", StringComparison.Ordinal) || !runtimeSurfaceDocuments.Contains("CultMesh.StateBindingRecord(", StringComparison.Ordinal) || !runtimeSurfaceDocuments.Contains(".ToBinding()", StringComparison.Ordinal) || - runtimeSurfaceBuilder.Contains("CultMesh.RouteRecord(binding.RouteHint)", StringComparison.Ordinal) || + runtimeSurfaceDocuments.Contains("CultMesh.RouteRecord(binding.RouteHint)", StringComparison.Ordinal) || runtimeSurfaceDocuments.Contains("CultMesh.RouteRecord(binding.RouteKind, binding.RouteDescription)", StringComparison.Ordinal) || runtimeSurfaceBuilder.Contains("ParseRouteKind(", StringComparison.Ordinal) || runtimeSurfaceDocuments.Contains("ParseRouteKind(", StringComparison.Ordinal)) @@ -916,20 +916,11 @@ static void RequireSharedEvePackagesImportedFromEveRepo(string root) "AetheriaRuntimeEveSurfaceAdapter is dead conversion chaff; runtime surface lowering belongs on AetheriaRuntimeSurfaceDocuments."); } - var surfaceCommandDocuments = string.Join( - "\n", - runtimeSurfaceDocuments, - playerSettingsSurfaceDocuments, - catalogSurfaceDocuments, - operationsSurfaceDocuments); if (!runtimeCultCacheDocumentStore.Contains("CultMesh.OperationBindingRecord(command.Operation)", StringComparison.Ordinal) || !runtimeCultCacheDocumentStore.Contains("CultMesh.OperationBindingRecord(", StringComparison.Ordinal) || !runtimeCultCacheDocumentStore.Contains("routeDescription).ToBinding()", StringComparison.Ordinal) || - !runtimeSurfaceDocuments.Contains("CultMesh.OperationBindingRecord(", StringComparison.Ordinal) || - !runtimeSurfaceDocuments.Contains("command.SchemaId", StringComparison.Ordinal) || !runtimeSurfaceDocuments.Contains("public static GameCult.Mesh.EveSurfaceDocument ToPortableSurface(AetheriaRuntimeSurfaceDocument document)", StringComparison.Ordinal) || !runtimeSurfaceDocuments.Contains("new GameCult.Mesh.EveSurfaceCommandTemplate(command.Operation)", StringComparison.Ordinal) || - !surfaceCommandDocuments.Contains("CultMesh.OperationBindingRecord(", StringComparison.Ordinal) || runtimeCultCacheDocumentStore.Contains("new CultMeshOperationBindingDescriptor(", StringComparison.Ordinal) || runtimeSurfaceDocuments.Contains("new CultMeshOperationBindingDescriptor(", StringComparison.Ordinal)) { @@ -1015,45 +1006,31 @@ static void RequirePackageSerializerBoundary(string root) throw new InvalidOperationException($"Cannot verify package serializer boundary; missing path: {packageRuntimeRoot}"); } - var allowedFiles = new HashSet(StringComparer.Ordinal) + var allowedSerializerExecutionFiles = new HashSet(StringComparer.Ordinal) { "AetheriaRuntimeCatalogStore.cs", "AetheriaRuntimeClientTargetStore.cs", "AetheriaRuntimeCultCacheDocumentStore.cs", "AetheriaRuntimeVerseClient.cs", - "AetheriaRuntimeSnapshotDocuments.cs", - "AetheriaRuntimeEveCommandDocument.cs", - "AetheriaRuntimeEveSurfaceState.cs", - "AetheriaRuntimeDaemonDocuments.cs", - "AetheriaRuntimeDaemonSoaDocuments.cs", - "AetheriaRuntimeRtsViewportDocuments.cs", - "AetheriaRuntimeAssetDocuments.cs", - "AetheriaRuntimeRenderSplatDocuments.cs", - "AetheriaRuntimeSettingsDocuments.cs", - "AetheriaRuntimeSurfaceDocuments.cs", - "AetheriaRuntimeInventoryDropdownSurfaceDocuments.cs", - "AetheriaRuntimeStarbridgeDocuments.cs", - "AetheriaRuntimeStarbridgePlayerSeatDocuments.cs", - "AetheriaRuntimeVerseAuthorityPolicy.cs" + "AetheriaRuntimeSnapshotDocuments.cs" }; - var serializerSymbols = new[] + var serializerExecutionSymbols = new[] { - "MessagePack", "MessagePackObject", "MessagePackSerializer", "MessagePackReader", "MessagePackWriter", - "IMessagePackFormatter", - "[Union(", - "[Key(" + "IMessagePackFormatter" }; var hits = Directory.EnumerateFiles(packageRuntimeRoot, "*.cs", SearchOption.AllDirectories) - .Where(path => !allowedFiles.Contains(Path.GetFileName(path))) + .Where(path => !allowedSerializerExecutionFiles.Contains(Path.GetFileName(path))) .SelectMany(path => File.ReadLines(path) .Select((line, index) => new { Path = path, LineNumber = index + 1, Line = line })) - .Where(line => serializerSymbols.Any(symbol => line.Line.Contains(symbol, StringComparison.Ordinal))) + .Where(line => serializerExecutionSymbols + .Where(symbol => symbol != "MessagePackObject") + .Any(symbol => line.Line.Contains(symbol, StringComparison.Ordinal))) .Select(line => $"{Path.GetRelativePath(root, line.Path)}:{line.LineNumber}: {line.Line.Trim()}") .Take(10) .ToArray(); @@ -1061,7 +1038,7 @@ static void RequirePackageSerializerBoundary(string root) if (hits.Length > 0) { throw new InvalidOperationException( - "Package serializer symbols escaped the named CultCache transport boundary: " + + "Package serializer execution escaped the named CultCache transport boundary: " + string.Join("; ", hits)); } } @@ -3367,11 +3344,10 @@ static void RequireEveRuntimeBootstrap(string root) { "private string surfaceId = AetheriaRuntimeDaemonGameSurfaceBuilder.SurfaceId", "ReadDaemonSurface(stateBoot)", - ".RuntimeState(stateBoot, \"unity-eve-surface-presenter\")", ".EveSurfaceDocument(surfaceId)", "?.Reactive()", - "AetheriaUnityRuntimeClientProvider.EveSurfaceCultMeshStateRefResolver(", - "CultMeshReactiveDocument", + "AetheriaEveRuntimeUnityHooks.TryCreateStateRefResolver(", + "CultMeshReactiveDocument", "ResolveReactiveDaemonSurfaceState(", "DisposeReactiveSurfaceState()", "AetheriaRuntimeSurfaceDocuments.ToEveSurfaceDocument(", @@ -3781,8 +3757,9 @@ static void RequireMainMenuSettingsCommands(string root) var requiredMainMenuSymbols = new[] { - "AetheriaRuntimeMainMenuSurfaceBuilder.BuildPlayerSettingsShell(", - "ResolvePlayerSettings(CurrentStateBoot())", + "ResolveMainMenuSurface(AetheriaRuntimeMainMenuCommands.PlayerSettingsShellSurfaceId)", + ".RuntimeState(stateBoot, \"unity-main-menu\")", + ".MainMenuSurface(surfaceId, CanOpenRuntimeInputScreen(), InGame)", "AetheriaEveUnitySurfaceHost.RenderRuntime(", "AetheriaRuntimeMainMenuCommandKind.PlayerSettingsCommand", "SendKnownAetheriaEveCommand(request, \"player-settings\")" @@ -3873,11 +3850,11 @@ static void RequireMainMenuSettingsShellUsesEveSurface(string root) var requiredSymbols = new[] { "RenderMenuSurface(", - "AetheriaRuntimeMainMenuSurfaceBuilder.BuildSettings(", - "AetheriaRuntimeMainMenuSurfaceBuilder.BuildPlayerSettingsShell(", - "AetheriaRuntimeMainMenuSurfaceBuilder.BuildVerseSettingsShell(", - "AetheriaRuntimeClientTargetSurfaceBuilder.Build(", - "AetheriaRuntimeMainMenuSurfaceBuilder.BuildInputSettings(", + "ResolveMainMenuSurface(AetheriaRuntimeMainMenuCommands.SettingsSurfaceId)", + "ResolveMainMenuSurface(AetheriaRuntimeMainMenuCommands.InputSettingsSurfaceId)", + "ResolveMainMenuSurface(AetheriaRuntimeMainMenuCommands.PlayerSettingsShellSurfaceId)", + "ResolveMainMenuSurface(AetheriaRuntimeMainMenuCommands.VerseSettingsShellSurfaceId)", + ".MainMenuSurface(surfaceId, CanOpenRuntimeInputScreen(), InGame)", "HandleSettingsSurfaceCommand(", "HandleVerseSettingsSurfaceCommand(", "HandleInputSettingsSurfaceCommand(", @@ -3888,7 +3865,6 @@ static void RequireMainMenuSettingsShellUsesEveSurface(string root) "AetheriaRuntimeMainMenuCommandKind.BackToMain", "AetheriaRuntimeMainMenuCommandKind.BackToSettings", "AetheriaRuntimeMainMenuCommandKind.OpenRuntimeInputScreen", - "ResolvePlayerSettings(", "AetheriaEveUnitySurfaceHost.RenderRuntime(", "AetheriaEveUnitySurfaceHost.Hide(_menuSurfaceDocument)" }; @@ -4017,7 +3993,8 @@ static void RequireMainMenuRootUsesEveSurface(string root) var mainMenuSurfaceBuilder = File.ReadAllText(mainMenuSurfaceBuilderPath); var requiredSymbols = new[] { - "AetheriaRuntimeMainMenuSurfaceBuilder.BuildRoot(", + "ResolveMainMenuSurface(AetheriaRuntimeMainMenuCommands.RootSurfaceId)", + ".MainMenuSurface(surfaceId, CanOpenRuntimeInputScreen(), InGame)", "AetheriaRuntimeMainMenuSurfaceCommands.TryRead(request, out var command)", "AetheriaRuntimeMainMenuCommandKind.ContinueRun", "AetheriaRuntimeMainMenuCommandKind.NewGame", @@ -4025,8 +4002,6 @@ static void RequireMainMenuRootUsesEveSurface(string root) "AetheriaRuntimeMainMenuCommandKind.Quit", "HandleMainSurfaceCommand(", "ResolveSectorMap(stateBoot)", - "ResolveVerseHostSettings(stateBoot)", - "ResolvePlayerSettings(stateBoot)", "HideMenuSurface();" }; @@ -4041,6 +4016,13 @@ static void RequireMainMenuRootUsesEveSurface(string root) string.Join(", ", missingSymbols)); } + if (!mainMenuSurfaceBuilder.Contains("AetheriaRuntimeMainMenuSurfaceBuilder", StringComparison.Ordinal) || + !mainMenuSurfaceBuilder.Contains("public static AetheriaRuntimeSurfaceDocument BuildRoot(", StringComparison.Ordinal)) + { + throw new InvalidOperationException( + "Shared runtime main-menu surface builder no longer owns the root shell composition."); + } + var forbiddenSymbols = new[] { "PanelPrototype", @@ -4299,8 +4281,8 @@ static void RequireMainMenuInputSettingsDelegateToRuntimeScreen(string root) "SetRuntimeInputScreenShell(Func canOpenRuntimeInputScreen, Action openRuntimeInputScreen)", "CanOpenRuntimeInputScreen()", "TryOpenRuntimeInputScreen()", - "AetheriaRuntimeMainMenuSurfaceBuilder.BuildInputSettings(", - "ResolvePlayerSettings(stateBoot)", + "ResolveMainMenuSurface(AetheriaRuntimeMainMenuCommands.InputSettingsSurfaceId)", + ".MainMenuSurface(surfaceId, CanOpenRuntimeInputScreen(), InGame)", "_canOpenRuntimeInputScreen?.Invoke() == true", "_openRuntimeInputScreen?.Invoke();" }; @@ -5055,7 +5037,9 @@ static void RequireRuntimeMenuTabsUseEveSurface(string root) "public static class AetheriaEveUnitySurfaceHost", "public static UIDocument Render(", "new EveUiToolkitSurfaceLowerer(new EveUiToolkitSurfaceOptions(embeddedDocumentResolver))", - "shell.Add(lowerer.Lower(surface, commandHandler))" + "lowerer.Lower(surface, commandHandler)", + "shell.Add(lowered)", + "root.Add(lowered)" }; var missingHostSymbols = requiredHostSymbols @@ -5375,7 +5359,7 @@ static void RequireInventoryCargoItemDetailsUseEveSurface(string root) "Packages", "org.gamecult.aetheria.state", "Runtime", - "AetheriaRuntimePlayerSettingsSurfaceBuilder.cs"); + "AetheriaRuntimeSurfaceDocuments.cs"); var daemonItemStatQueriesPath = Path.Combine( root, "Packages", @@ -5501,32 +5485,41 @@ static void RequireInventoryCargoItemDetailsUseEveSurface(string root) "InventoryMenu must project current item stats through shared daemon item-stat queries instead of direct Unity ItemManager stat authority."); } - if (!surfaceDocument.Contains("public static class AetheriaRuntimeSurfaceStateRefs", StringComparison.Ordinal) || - !surfaceDocument.Contains("public const string Source = \"stateRef\"", StringComparison.Ordinal) || - !surfaceDocument.Contains("public const string Value = \"valueRef\"", StringComparison.Ordinal) || - !daemonItemStatQueries.Contains("public const string StateRefPrefix = \"aetheria.state/items\"", StringComparison.Ordinal) || - !daemonItemStatQueries.Contains("public static string ItemStatRef(", StringComparison.Ordinal) || - !daemonItemStatQueries.Contains("public static bool TryReadItemStatRef(", StringComparison.Ordinal) || - !daemonItemStatQueries.Contains("public string ValueRef =>", StringComparison.Ordinal) || - !unityProject.Contains("AetheriaRuntimeDaemonItemStatQueries.cs", StringComparison.Ordinal) || - !eveUnitySurfaceHost.Contains("CultMeshStateRefResolver stateRefResolver", StringComparison.Ordinal) || - !eveUnitySurfaceHost.Contains("ContainsStateRefs(surface)", StringComparison.Ordinal) || - !eveUnitySurfaceHost.Contains("prop.Key.EndsWith(\"Ref\", StringComparison.Ordinal)", StringComparison.Ordinal) || - !eveUnitySurfaceHost.Contains("CreateDefaultStateRefResolver()", StringComparison.Ordinal) || - !eveUnitySurfaceHost.Contains("AetheriaUnityRuntimeClientProvider", StringComparison.Ordinal) || - !eveUnitySurfaceHost.Contains("AetheriaUnityRuntimeClientProvider.EveSurfaceCultMeshStateRefResolver(", StringComparison.Ordinal) || - !runtimeSurfaceDocuments.Contains("public static EveSurfaceDocument ResolveStateRefs(", StringComparison.Ordinal) || - !runtimeSurfaceDocuments.Contains("ResolvePropRefs(props, resolveStateRef)", StringComparison.Ordinal) || - !runtimeSurfaceDocuments.Contains("ResolvePropRef(props, AetheriaRuntimeSurfaceStateRefs.Source, \"value\", resolveStateRef)", StringComparison.Ordinal) || - !runtimeSurfaceDocuments.Contains("IsStatePointerProp(prop.Key)", StringComparison.Ordinal) || - !runtimeSurfaceDocuments.Contains("ResolvePointerValueKey(refProp.Key)", StringComparison.Ordinal) || - !cargoItemSurfaceBuilder.Contains("public string ValueRef { get; }", StringComparison.Ordinal) || - !cargoItemSurfaceBuilder.Contains("props.Add(AetheriaRuntimeSurfaceStateRefs.ValueRef(valueRef))", StringComparison.Ordinal) || - !equippedItemSurfaceBuilder.Contains("public string ValueRef { get; }", StringComparison.Ordinal) || - !equippedItemSurfaceBuilder.Contains("props.Add(AetheriaRuntimeSurfaceStateRefs.ValueRef(valueRef))", StringComparison.Ordinal)) + var stateRefRequiredSymbols = new[] + { + ("AetheriaRuntimeSurfaceDocuments.cs", surfaceDocument, "public static class AetheriaRuntimeSurfaceStateRefs"), + ("AetheriaRuntimeSurfaceDocuments.cs", surfaceDocument, "public const string Source = \"stateRef\""), + ("AetheriaRuntimeSurfaceDocuments.cs", surfaceDocument, "public const string Value = \"valueRef\""), + ("AetheriaRuntimeDaemonItemStatQueries.cs", daemonItemStatQueries, "public const string StateRefPrefix = \"aetheria.state/items\""), + ("AetheriaRuntimeDaemonItemStatQueries.cs", daemonItemStatQueries, "public static string ItemStatRef("), + ("AetheriaRuntimeDaemonItemStatQueries.cs", daemonItemStatQueries, "public static bool TryReadItemStatRef("), + ("AetheriaRuntimeDaemonItemStatQueries.cs", daemonItemStatQueries, "public string ValueRef =>"), + ("GameCult.Aetheria.State.Unity.csproj", unityProject, "AetheriaRuntimeDaemonItemStatQueries.cs"), + ("AetheriaEveUnitySurfaceHost.cs", eveUnitySurfaceHost, "CultMeshStateRefResolver stateRefResolver"), + ("AetheriaEveUnitySurfaceHost.cs", eveUnitySurfaceHost, "ContainsStateRefs(surface)"), + ("AetheriaEveUnitySurfaceHost.cs", eveUnitySurfaceHost, "prop.Key.EndsWith(\"Ref\", StringComparison.Ordinal)"), + ("AetheriaEveUnitySurfaceHost.cs", eveUnitySurfaceHost, "CreateDefaultStateRefResolver()"), + ("AetheriaEveUnitySurfaceHost.cs", eveUnitySurfaceHost, "AetheriaEveRuntimeUnityHooks"), + ("AetheriaEveUnitySurfaceHost.cs", eveUnitySurfaceHost, "TryCreateDefaultStateRefResolver()"), + ("AetheriaRuntimeSurfaceDocuments.cs", runtimeSurfaceDocuments, "public static EveUiSurfaceDocument ResolveStateRefs("), + ("AetheriaRuntimeSurfaceDocuments.cs", runtimeSurfaceDocuments, "ResolvePropRefs(props, resolveStateRef)"), + ("AetheriaRuntimeSurfaceDocuments.cs", runtimeSurfaceDocuments, "ResolvePropRef(props, AetheriaRuntimeSurfaceStateRefs.Source, \"value\", resolveStateRef)"), + ("AetheriaRuntimeSurfaceDocuments.cs", runtimeSurfaceDocuments, "IsStatePointerProp(prop.Key)"), + ("AetheriaRuntimeSurfaceDocuments.cs", runtimeSurfaceDocuments, "ResolvePointerValueKey(refProp.Key)"), + ("AetheriaRuntimeCargoItemDetailsSurfaceBuilder.cs", cargoItemSurfaceBuilder, "public string ValueRef { get; }"), + ("AetheriaRuntimeCargoItemDetailsSurfaceBuilder.cs", cargoItemSurfaceBuilder, "props.Add(AetheriaRuntimeSurfaceStateRefs.ValueRef(valueRef))"), + ("AetheriaRuntimeEquippedItemDetailsSurfaceBuilder.cs", equippedItemSurfaceBuilder, "public string ValueRef { get; }"), + ("AetheriaRuntimeEquippedItemDetailsSurfaceBuilder.cs", equippedItemSurfaceBuilder, "props.Add(AetheriaRuntimeSurfaceStateRefs.ValueRef(valueRef))") + }; + var missingStateRefSymbols = stateRefRequiredSymbols + .Where(symbol => !symbol.Item2.Contains(symbol.Item3, StringComparison.Ordinal)) + .Select(symbol => $"{symbol.Item1}: {symbol.Item3}") + .ToArray(); + if (missingStateRefSymbols.Length > 0) { throw new InvalidOperationException( - "Eve/CultUI item stat surfaces must expose typed daemon state refs that the UI runtime can resolve."); + "Eve/CultUI item stat surfaces must expose typed daemon state refs that the UI runtime can resolve: " + + string.Join(", ", missingStateRefSymbols)); } var forbiddenSymbols = new[] @@ -6719,7 +6712,7 @@ static void RequireInventoryDropdownUseEveSurface(string root) "AetheriaRuntimeInventoryDropdownCommandKind.Close", "AetheriaRuntimeInventoryDropdownCommandKind.Select", "TryResolveDropdownSelection(request, command.Command, out var selection)", - "AetheriaRuntimeInventoryDropdownSurfaceCommands.TryReadSelection(command, selectionKey, out selection)", + "PayloadValue(request, \"selectionKind\")", "AetheriaRuntimeInventoryDropdownSelectionKind.EntityBay", "AetheriaRuntimeInventoryDropdownSelectionKind.Loadout", "selection.EntityKey", @@ -7191,15 +7184,33 @@ static void RequirePlayerSettingsEveSurface(string root) "Player settings Eve surface document should pass typed settings directly into the shared builder, not repack them into a shadow surface state."); } - var bridge = File.Exists(bridgePath) - ? File.ReadAllText(bridgePath) - : throw new InvalidOperationException("Player settings Eve command bridge is missing."); - var provider = File.Exists(providerPath) - ? File.ReadAllText(providerPath) - : throw new InvalidOperationException("Player settings provider advertisement projector is missing."); - var daemonHost = File.Exists(daemonHostPath) - ? File.ReadAllText(daemonHostPath) - : throw new InvalidOperationException("Aetheria.State.Daemon program is missing."); + var runtimeVerseClientPath = Path.Combine( + root, + "Packages", + "org.gamecult.aetheria.state", + "Runtime", + "AetheriaRuntimeVerseClient.cs"); + var runtimeEveCommandClientPath = Path.Combine( + root, + "Packages", + "org.gamecult.aetheria.state", + "Runtime", + "AetheriaRuntimeEveCommandClient.cs"); + var runtimeUiPath = Path.Combine( + root, + "Packages", + "org.gamecult.aetheria.state", + "Runtime", + "AetheriaUi.cs"); + var runtimeVerseClient = File.Exists(runtimeVerseClientPath) + ? File.ReadAllText(runtimeVerseClientPath) + : throw new InvalidOperationException("Managed runtime Verse client is missing."); + var runtimeEveCommandClient = File.Exists(runtimeEveCommandClientPath) + ? File.ReadAllText(runtimeEveCommandClientPath) + : throw new InvalidOperationException("Managed runtime Eve command client is missing."); + var runtimeUi = File.Exists(runtimeUiPath) + ? File.ReadAllText(runtimeUiPath) + : throw new InvalidOperationException("Managed runtime UI command facade is missing."); var sharedCommands = File.Exists(sharedCommandsPath) ? File.ReadAllText(sharedCommandsPath) : throw new InvalidOperationException("Shared player-settings Eve command contract is missing."); @@ -7207,38 +7218,28 @@ static void RequirePlayerSettingsEveSurface(string root) ? File.ReadAllText(surfaceBuilderPath) : throw new InvalidOperationException("Shared player-settings Eve surface builder is missing."); - if (!bridge.Contains("AcceptedPlayerSettingsCommands", StringComparison.Ordinal) || - !bridge.Contains("ExecutePlayerSettingsCommandAsync", StringComparison.Ordinal) || - !bridge.Contains("MutableDocument(AetheriaStateNode.PlayerSettingsSurfaceKey)", StringComparison.Ordinal) || - !bridge.Contains(".ReplaceAsync(AetheriaEveSurfaceDocuments.BuildPlayerSettingsSurface", StringComparison.Ordinal) || - !bridge.Contains("SetPlayerName", StringComparison.Ordinal) || - !bridge.Contains("command.PlayerSettings.PlayerName", StringComparison.Ordinal)) + if (!runtimeUi.Contains("public async Task SurfaceCommandAsync(", StringComparison.Ordinal) || + !runtimeUi.Contains(".SubmitKnownSurfaceCommandAsync(request, clientId, flush)", StringComparison.Ordinal) || + !runtimeVerseClient.Contains("SubmitKnownSurfaceCommandAsync(", StringComparison.Ordinal) || + !runtimeVerseClient.Contains("AetheriaRuntimeEveCommandClient.TryCreateKnownSurfaceCommand(request, out var envelope)", StringComparison.Ordinal) || + !runtimeVerseClient.Contains("Database.PutAsync(AetheriaRuntimeVerseRecordKeys.EveCommand(command.CommandId), command)", StringComparison.Ordinal) || + !runtimeEveCommandClient.Contains("AetheriaRuntimePlayerSettingsCommands.SurfaceId", StringComparison.Ordinal) || + !runtimeEveCommandClient.Contains("AetheriaRuntimePlayerSettingsCommands.IsKnown(command)", StringComparison.Ordinal) || + !runtimeEveCommandClient.Contains("CreatePlayerSettingsCommand(CommandKindForSurface(request), request, clientId)", StringComparison.Ordinal) || + !runtimeEveCommandClient.Contains("playerSettings: ReadPlayerSettingsBody(request)", StringComparison.Ordinal) || + !runtimeEveCommandClient.Contains("invocation: request.Operation", StringComparison.Ordinal) || + !runtimeEveCommandClient.Contains("payload: request.Payload", StringComparison.Ordinal)) { throw new InvalidOperationException( - "Eve command bridge no longer owns the typed player-settings surface mutation path."); + "Managed Eve command path no longer submits typed player-settings surface commands through CultMesh."); } - if (!provider.Contains("SurfaceId = PlayerSettingsSurfaceId", StringComparison.Ordinal) || - !provider.Contains("Key = PlayerSettingsSurfaceKey", StringComparison.Ordinal) || - !provider.Contains("AetheriaRuntimePlayerSettingsCommands.Refresh", StringComparison.Ordinal)) + if ((File.Exists(bridgePath) && File.ReadAllText(bridgePath).Contains("MutableDocument", StringComparison.Ordinal)) || + (File.Exists(daemonHostPath) && File.ReadAllText(daemonHostPath).Contains("MutableDocument", StringComparison.Ordinal)) || + runtimeVerseClient.Contains("EveSurfaceState", StringComparison.Ordinal)) { throw new InvalidOperationException( - "Provider advertisement no longer publishes the player-settings Eve surface and commands."); - } - - if (!daemonHost.Contains("MutableDocument(AetheriaStateNode.PlayerSettingsSurfaceKey)", 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."); - } - - if (bridge.Contains("PlayerSettingsSurface()", StringComparison.Ordinal) || - daemonHost.Contains("PlayerSettingsSurface()", StringComparison.Ordinal)) - { - throw new InvalidOperationException( - "Player-settings Eve publication still uses named AetheriaStateNode surface helpers instead of generic mutable typed documents."); + "Player-settings Eve command path still depends on local EveSurfaceState publication instead of managed CultMesh command documents."); } if (!sharedCommands.Contains("SurfaceId = \"aetheria.player_settings\"", StringComparison.Ordinal) || @@ -8072,9 +8073,8 @@ static void RequireUnitySharedDocumentAccessorErgonomics(string root) { "AetheriaUnityRuntimeClientProvider", ".RuntimeState(stateBoot, \"unity-main-menu\")", - ".SectorMap", - ".PlayerSettings", - ".VerseHostSettings", + "ResolveMainMenuSurface(string surfaceId)", + ".MainMenuSurface(surfaceId, CanOpenRuntimeInputScreen(), InGame)", ".Latest()", "private void OnDestroy()" }; @@ -8084,7 +8084,7 @@ static void RequireUnitySharedDocumentAccessorErgonomics(string root) if (missingMainMenuSharedDocumentSymbols.Length > 0) { throw new InvalidOperationException( - "MainMenu should sample sector, player, and Verse host state through a managed typed Aetheria runtime state handle: " + + "MainMenu should sample daemon-published menu surfaces through a managed typed Aetheria runtime state handle: " + string.Join(", ", missingMainMenuSharedDocumentSymbols)); } @@ -8717,7 +8717,7 @@ static void RequireAetheriaManagedStateAccessorsCoverDomainDocuments(string root "public CultMeshDocumentHandle Catalog { get; }", "public CultMeshDocumentHandle PlayerSettings { get; }", "public static bool TryResolveEveSurface(", - "public CultMeshDocumentHandle? EveSurfaceDocument(", + "public CultMeshDocumentHandle? EveSurfaceDocument(", "public CultMeshDocumentHandle RtsViewport(", "public CultMeshDocumentHandle ObjectsViewport(", "public CultMeshDocumentHandle GravityViewport(", @@ -9444,6 +9444,7 @@ static void RequireClientTargetBootAuthority(string root) var mainMenuSurfaceBuilderPath = Path.Combine(root, "Packages", "org.gamecult.aetheria.state", "Runtime", "AetheriaRuntimeMainMenuSurfaceBuilder.cs"); var bootstrapPath = Path.Combine(root, "Packages", "org.gamecult.aetheria.eve-runtime", "Runtime", "AetheriaEveRuntimeBootstrap.cs"); var presenterPath = Path.Combine(root, "Packages", "org.gamecult.aetheria.eve-runtime", "Runtime", "AetheriaEveSurfacePresenter.cs"); + var unityEveRuntimeHooksPath = Path.Combine(root, "Assets", "Scripts", "Gameplay", "AetheriaUnityEveRuntimeHooks.cs"); var actionGameManagerPath = Path.Combine(root, "Assets", "Scripts", "Gameplay", "ActionGameManager.cs"); var gameplayBootShellPath = Path.Combine(root, "Assets", "Scripts", "Gameplay", "AetheriaUnityGameplayBootShell.cs"); var mainMenuPath = Path.Combine(root, "Assets", "Scripts", "UI", "MainMenu.cs"); @@ -9461,6 +9462,7 @@ static void RequireClientTargetBootAuthority(string root) mainMenuSurfaceBuilderPath, bootstrapPath, presenterPath, + unityEveRuntimeHooksPath, actionGameManagerPath, gameplayBootShellPath, mainMenuPath @@ -9488,6 +9490,7 @@ static void RequireClientTargetBootAuthority(string root) var mainMenuSurfaceBuilder = File.ReadAllText(mainMenuSurfaceBuilderPath); var bootstrap = File.ReadAllText(bootstrapPath); var presenter = File.ReadAllText(presenterPath); + var unityEveRuntimeHooks = File.ReadAllText(unityEveRuntimeHooksPath); var actionGameManager = File.ReadAllText(actionGameManagerPath); var gameplayBootShell = File.ReadAllText(gameplayBootShellPath); var mainMenu = File.ReadAllText(mainMenuPath); @@ -9821,8 +9824,8 @@ static void RequireClientTargetBootAuthority(string root) var requiredPresenterSymbols = new[] { - "AetheriaRuntimeStateBoot.Inspect(", - "AetheriaUnityRuntimePaths.GameDataDirectory", + "ResolveStateBoot()", + "AetheriaEveRuntimeUnityHooks.RequireStateBoot(", "!stateBoot.SupportsLocalStateFileRead", "stateBoot.StateFileExists" }; @@ -9836,6 +9839,13 @@ static void RequireClientTargetBootAuthority(string root) string.Join(", ", missingPresenterSymbols)); } + if (!unityEveRuntimeHooks.Contains("AetheriaRuntimeStateBoot.Inspect(", StringComparison.Ordinal) || + !unityEveRuntimeHooks.Contains("AetheriaUnityRuntimePaths.GameDataDirectory", StringComparison.Ordinal)) + { + throw new InvalidOperationException( + "Aetheria Eve runtime hooks no longer own Unity client-target boot resolution."); + } + if (bootstrap.Contains("StatePathEnvironmentVariable", StringComparison.Ordinal) || bootstrap.Contains("presenter.StateFilePathOverride =", StringComparison.Ordinal)) { @@ -9851,26 +9861,21 @@ static void RequireClientTargetBootAuthority(string root) ".RuntimeState(stateBoot, \"unity-main-menu\")", ".SectorMap", ".Latest()", - "ResolveVerseHostSettings(AetheriaRuntimeStateBootReport stateBoot)", - ".VerseHostSettings", + "ResolveMainMenuSurface(", + ".MainMenuSurface(surfaceId, CanOpenRuntimeInputScreen(), InGame)", "AetheriaState.At(AetheriaUnityRuntimePaths.GameDataDirectory)", ".ClientTarget", "RequestClientTargetCommand(request)", - "AetheriaRuntimeClientTargetSurfaceCommands.TryRequest(", - "ResolvePlayerSettings(AetheriaRuntimeStateBootReport stateBoot)", - ".PlayerSettings", - "AetheriaRuntimeClientTargetSurfaceBuilder.Build(", - "AetheriaRuntimeMainMenuSurfaceBuilder.BuildRoot(", - "AetheriaRuntimeMainMenuSurfaceBuilder.BuildSettings(", - "AetheriaRuntimeMainMenuSurfaceBuilder.BuildInputSettings(" + "AetheriaRuntimeClientTargetSurfaceCommands.TryRequest(" }; var requiredMainMenuBuilderSymbols = new[] { "private static AetheriaRuntimeSurfaceDocument BuildRoot(", "var verseLabel = VerseLabel(verseTitle, verseId)", - "\"Client Target\"", - "\"Transport\"", - "\"Target Source\"" + "\"Verse\"", + "\"Target\"", + "\"Daemon\"", + "\"Transport\"" }; var missingMainMenuSymbols = requiredMainMenuSymbols .Where(symbol => !mainMenu.Contains(symbol, StringComparison.Ordinal)) @@ -10351,10 +10356,10 @@ static void RequireVerseSettingsShellAndBridge(string root) var requiredMainMenuSymbols = new[] { "AetheriaRuntimeMainMenuCommandKind.ShowVerseSettings", - "ShowVerseSettingsSurface()", + "ShowVerseSettingsSurface(", "HandleVerseSettingsSurfaceCommand(EveSurfaceCommandRequest request)", - "AetheriaRuntimeMainMenuSurfaceBuilder.BuildVerseSettingsShell(", - "AetheriaRuntimeClientTargetSurfaceBuilder.Build(", + "ResolveMainMenuSurface(AetheriaRuntimeMainMenuCommands.VerseSettingsShellSurfaceId)", + ".MainMenuSurface(surfaceId, CanOpenRuntimeInputScreen(), InGame)", "AetheriaRuntimeMainMenuSurfaceCommands.TryRead(request, out var command)", "AetheriaRuntimeMainMenuCommandKind.ClientTargetCommand", "AetheriaRuntimeMainMenuCommandKind.VerseHostCommand", @@ -11737,10 +11742,10 @@ static void RequireDaemonVersePublication(string root) "node.MutableDocument(AetheriaRuntimeVerseRecordKeys.DaemonProviderAdvertisement)", "node.MutableDocument(AetheriaRuntimeVerseRecordKeys.DaemonHealth)", "node.MutableDocument(AetheriaRuntimeVerseRecordKeys.DaemonCommandBoundary)", - "node.MutableDocument(AetheriaRuntimeVerseRecordKeys.DaemonGameSurface)", - "node.MutableDocument(AetheriaRuntimeVerseRecordKeys.DaemonGameTuiSurface)", - "node.MutableDocument(AetheriaRuntimeVerseRecordKeys.DaemonEditorSurface)", - "node.MutableDocument(AetheriaRuntimeVerseRecordKeys.DaemonEditorTuiSurface)", + "node.MutableDocument(AetheriaRuntimeVerseRecordKeys.DaemonGameSurface)", + "node.MutableDocument(AetheriaRuntimeVerseRecordKeys.DaemonGameTuiSurface)", + "node.MutableDocument(AetheriaRuntimeVerseRecordKeys.DaemonEditorSurface)", + "node.MutableDocument(AetheriaRuntimeVerseRecordKeys.DaemonEditorTuiSurface)", "node.MutableDocument(AetheriaRuntimeVerseRecordKeys.StarbridgeSessionSummary)", ".ReplaceAsync(result.Frame)", ".ReplaceAsync(result.SoaView)", @@ -11760,8 +11765,8 @@ static void RequireDaemonVersePublication(string root) "node.MutableDocument(AetheriaStateNode.EveCommandAcceptanceStatusKey)", "node.MutableDocument(AetheriaStateNode.RuntimeSessionKey(options.DaemonId))", "node.MutableDocument(AetheriaStateNode.PlayerSettingsKey).ReadAsync()", - "node.MutableDocument(AetheriaStateNode.OperationsSurfaceKey)", - "node.MutableDocument(AetheriaStateNode.PlayerSettingsSurfaceKey)", + "node.MutableDocument(AetheriaStateNode.OperationsSurfaceKey)", + "node.MutableDocument(AetheriaStateNode.PlayerSettingsSurfaceKey)", "node.MutableDocument(AetheriaStateNode.ProviderAdvertisementSurfaceKey)", "AetheriaEveSurfaceDocuments.BuildProviderAdvertisement(verseHost, node.StatePath, updatedAtUtc)", "AetheriaEveSurfaceDocuments.BuildOperationsSurface(eveStatus, verseHost, runtimeSession)", @@ -12196,13 +12201,13 @@ static void RequireDaemonVersePublication(string root) "AetheriaClient control submission did not appear as a typed daemon state record.", "AetheriaClient UI submission did not appear as a typed Eve state record.", "node.MutableDocument(AetheriaRuntimeVerseRecordKeys.DaemonFrameLatest)", - "node.MutableDocument(AetheriaRuntimeVerseRecordKeys.DaemonGameSurface)", - ".ReplaceAsync(AetheriaRuntimeSurfaceDocuments.ToEveSurfaceState(daemonGameSurface))", + "node.MutableDocument(AetheriaRuntimeVerseRecordKeys.DaemonGameSurface)", + ".ReplaceAsync(AetheriaRuntimeSurfaceDocuments.ToPortableSurface(daemonGameSurface))", "reopened.MutableDocument(AetheriaRuntimeVerseRecordKeys.DaemonProviderAdvertisement)", "reopened.MutableDocument(AetheriaRuntimeVerseRecordKeys.DaemonHealth)", "reopened.MutableDocument(AetheriaRuntimeVerseRecordKeys.DaemonCommandBoundary)", "reopened.MutableDocument(AetheriaRuntimeVerseRecordKeys.DaemonFrameLatest)", - "reopened.MutableDocument(AetheriaRuntimeVerseRecordKeys.DaemonGameSurface)", + "reopened.MutableDocument(AetheriaRuntimeVerseRecordKeys.DaemonGameSurface)", "DaemonGameSurfaceKey", "DaemonGameTuiSurfaceKey", "DaemonEditorSurfaceKey", @@ -12323,20 +12328,34 @@ static void RequireDaemonVersePublication(string root) static void RequireUnityRuntimeCatalogClientUsesManagedDocument(string root) { - var clientPath = Path.Combine(root, "Aetheria.State.Unity", "AetheriaRuntimeCatalogClient.cs"); + var clientPath = Path.Combine( + root, + "Packages", + "org.gamecult.aetheria.state", + "Runtime", + "AetheriaClientState.cs"); + var verseClientPath = Path.Combine( + root, + "Packages", + "org.gamecult.aetheria.state", + "Runtime", + "AetheriaRuntimeVerseClient.cs"); var mapperPath = Path.Combine(root, "Aetheria.State.Unity", "AetheriaRuntimeCatalogSnapshotMapper.cs"); var client = File.Exists(clientPath) ? File.ReadAllText(clientPath) - : throw new InvalidOperationException("Cannot verify Unity runtime catalog client; AetheriaRuntimeCatalogClient.cs is missing."); + : throw new InvalidOperationException("Cannot verify managed Unity runtime catalog client; AetheriaClientState.cs is missing."); + var verseClient = File.Exists(verseClientPath) + ? File.ReadAllText(verseClientPath) + : throw new InvalidOperationException("Cannot verify managed Unity runtime catalog client; AetheriaRuntimeVerseClient.cs is missing."); var requiredSymbols = new[] { - "\"aetheria-unity-runtime-catalog\",", - "enableDurableShardLogs: false", - "public AetheriaRuntimeCatalogSnapshot ReadCatalog()", - "return _node.RuntimeCatalog().Latest();", - "public EveSurfaceState? ReadCatalogSurface()", - "return _node.CatalogSurface().Latest();" + "using MeshEveSurfaceDocument = GameCult.Mesh.EveSurfaceDocument;", + "CultMeshDocumentHandle catalog", + "public CultMeshDocumentHandle Catalog", + "public CultMeshDocumentHandle? EveSurfaceDocument(", + "AetheriaClientEveSurface.Game => GameSurface", + "AetheriaClientEveSurface.Editor => EditorSurface" }; var missingSymbols = requiredSymbols .Where(symbol => !client.Contains(symbol, StringComparison.Ordinal)) @@ -12348,8 +12367,26 @@ static void RequireUnityRuntimeCatalogClientUsesManagedDocument(string root) string.Join(", ", missingSymbols)); } + var requiredVerseClientSymbols = new[] + { + "BootstrapCatalogDocument(", + "Document(", + "AetheriaRuntimeVerseRecordKeys.DaemonGameSurface", + "AetheriaRuntimeVerseRecordKeys.DaemonEditorSurface" + }; + var missingVerseClientSymbols = requiredVerseClientSymbols + .Where(symbol => !verseClient.Contains(symbol, StringComparison.Ordinal)) + .ToArray(); + if (missingVerseClientSymbols.Length > 0) + { + throw new InvalidOperationException( + "Runtime Verse client no longer exposes managed catalog/Eve surface document handles: " + + string.Join(", ", missingVerseClientSymbols)); + } + var forbiddenSymbols = new[] { + "EveSurfaceState", "_node.ReadCatalog", "_node.GetCatalogSurfaceAsync()", "ReadCatalogSurfaceAsync(", @@ -12564,18 +12601,18 @@ static void RequireAetheriaRuntimeVerseClientContract(string root) "AetheriaRuntimeLoadoutTemplatesDocument", "StarbridgeSummaryAsync", "CultMeshReactiveDocument? managedDaemonFrame = null;", - "managedDaemonFrame = state.DaemonFrame.Reactive();", - "managedCatalog = state.Catalog.Reactive();", - "managedLoadoutTemplates = state.LoadoutTemplates.Reactive();", + "managedDaemonFrame ??= latestFrameDocument.Reactive();", + "managedCatalog ??= catalogDocument.Reactive();", + "managedLoadoutTemplates ??= loadoutTemplatesDocument.Reactive();", "managedPlayerSettings = state.PlayerSettings.Reactive();", - "managedStarbridgeScenario = state.StarbridgeScenario.Reactive();", - "managedStarbridgeSession = state.StarbridgeSession.Reactive();", + "managedStarbridgeScenario ??= starbridgeScenarioDocument.Reactive();", + "managedStarbridgeSession ??= starbridgeSessionDocument.Reactive();", "AetheriaRuntimeDaemonFrameDocument RequireManagedFrame()", "RequireManagedFrame()", "RequireManagedCatalog()", "RequireManagedLoadoutTemplates().Templates", - "managedStarbridgeScenario?.Current", - "managedStarbridgeSession?.Current", + "return managedStarbridgeScenario.Current;", + "return managedStarbridgeSession.Current;", "BootstrapCatalogDocument(", "CatalogBootstrapSource(", "BootstrapRuntimeCatalog", @@ -12673,12 +12710,7 @@ static void RequireAetheriaRuntimeVerseClientContract(string root) client.Contains("state.ObserveCatalog()", StringComparison.Ordinal) || client.Contains("state.ObserveLoadoutTemplates()", StringComparison.Ordinal) || client.Contains("state.Starbridge.ObserveScenario()", StringComparison.Ordinal) || - client.Contains("state.Starbridge.ObserveSession()", StringComparison.Ordinal) || - client.Contains("catalogDocument.Reactive()", StringComparison.Ordinal) || - client.Contains("loadoutTemplatesDocument.Reactive()", StringComparison.Ordinal) || - client.Contains("starbridgeScenarioDocument.Reactive()", StringComparison.Ordinal) || - client.Contains("starbridgeSessionDocument.Reactive()", StringComparison.Ordinal) || - client.Contains("latestFrameDocument.Reactive()", StringComparison.Ordinal)) + client.Contains("state.Starbridge.ObserveSession()", StringComparison.Ordinal)) { throw new InvalidOperationException( "Aetheria Verse client derived documents must sample directly owned named reactive typed documents instead of an input/session wrapper."); @@ -12735,14 +12767,13 @@ static void RequireAetheriaRuntimeVerseClientContract(string root) "CultMeshReactiveDocument? _eveStateRefHealth", "CultMeshReactiveDocument? _eveStateRefCommandBoundary", "CultMeshReactiveDocument? _eveStateRefCatalog", - "_eveStateRefFrame ??= DaemonFrame.Reactive()", - "_eveStateRefHealth ??= Health.Reactive()", - "_eveStateRefCommandBoundary ??= CommandBoundary.Reactive()", - "_eveStateRefCatalog ??= Catalog.Reactive()", - "() => _eveStateRefFrame.Current", - "() => _eveStateRefHealth.Current", - "() => _eveStateRefCommandBoundary.Current", - "() => _eveStateRefCatalog.Current", + "() => ReadOptionalReactive(ref _eveStateRefFrame, DaemonFrame)", + "() => ReadOptionalReactive(ref _eveStateRefHealth, Health)", + "() => ReadOptionalReactive(ref _eveStateRefCommandBoundary, CommandBoundary)", + "() => ReadOptionalReactive(ref _eveStateRefCatalog, Catalog)", + "private static TDocument? ReadOptionalReactive(", + "reactive ??= handle.Reactive()", + "return reactive.Current", "public void Dispose()", "_eveStateRefFrame?.Dispose()", "_eveStateRefHealth?.Dispose()", @@ -13500,41 +13531,41 @@ static void RequireMainMenuVerseHostDocumentAccess(string root) var requiredMainMenuSymbols = new[] { - "ResolveVerseHostSettings(AetheriaRuntimeStateBootReport stateBoot)", "AetheriaUnityRuntimeClientProvider", ".RuntimeState(stateBoot, \"unity-main-menu\")", - ".VerseHostSettings", + ".MainMenuSurface(surfaceId, CanOpenRuntimeInputScreen(), InGame)", ".Latest()", - "AetheriaRuntimeClientTargetSurfaceBuilder.Build(", - "AetheriaRuntimeMainMenuSurfaceBuilder.BuildRoot(" + "ResolveMainMenuSurface(" }; var requiredBuilderSymbols = new[] { - "\"Client Target\"", - "\"Transport\"", - "\"Target Source\"", - "\"Verse\"", - "\"Visibility\"", - "\"CultMesh\"", - "The client target chooses which Verse it follows; game truth belongs to the daemon serving" + "public static AetheriaRuntimeSurfaceDocument BuildRoot(", + "AetheriaRuntimeStateBootReport stateBoot", + "AetheriaRuntimeVerseHostSettingsDocument verseHost", + "verseHost?.Title ?? stateBoot.Title", + "verseHost?.VerseId ?? stateBoot.VerseId", + "verseHost?.Visibility ?? \"unknown\"", + "verseHost?.CultMeshAddress ?? stateBoot.CultMeshAddress", + ".TitleSubtitle(\"AETHERIA\", \"TERMINUS\")", + ".Metric(\"Verse\", verseLabel)", + ".Metric(\"Target\", targetLine)", + ".Metric(\"Daemon\", daemonLine)", + ".Metric(\"Transport\", transportLine)", + "private static string VerseLabel(", + "private static string TargetLine(", + "\"No daemon frame\"", + "\"Run {daemonRunId} / frame {daemonFrameId}\"" }; var requiredClientTargetBuilderSymbols = new[] { "Build(", "AetheriaRuntimeStateBootReport stateBoot", - "AetheriaRuntimeVerseHostSettingsDocument verseHost", - "stateBoot.FailureMessage", - "stateBoot.DiscoveryEndpoints", - "stateBoot.DiscoveredVerses", - "stateBoot.LastDiscoveryAtUtc", - "stateBoot.LastDiscoveryError", - "stateBoot.ReplicaStateFilePath", - "stateBoot.LastReplicaSyncAtUtc", - "stateBoot.LastReplicaSyncError", - "var hostTitle = verseHost?.Title ?? targetTitle", - "var hostVerseId = verseHost?.VerseId ?? targetVerseId", - "var hostVisibility = verseHost?.Visibility ?? \"unknown\"", - "var hostCultMeshAddress = verseHost?.CultMeshAddress ?? targetCultMeshAddress" + "\"Transport\"", + "\"Target Source\"", + "\"Verse\"", + "\"Visibility\"", + "\"CultMesh\"", + "Client target edits are local. Visibility changes append provider-owned Eve requests" }; var missingMainMenuSymbols = requiredMainMenuSymbols .Where(symbol => !mainMenu.Contains(symbol, StringComparison.Ordinal)) @@ -13570,13 +13601,15 @@ static void RequireMainMenuVerseHostDocumentAccess(string root) string.Join(", ", missingClientTargetBuilderSymbols)); } - if (mainMenu.Contains("AetheriaRuntimeMainMenuSurfaceBuilder.ProjectVerseSettings(", StringComparison.Ordinal) || + if (mainMenu.Contains("AetheriaRuntimeMainMenuSurfaceBuilder.BuildRoot(", StringComparison.Ordinal) || + mainMenu.Contains("AetheriaRuntimeClientTargetSurfaceBuilder.Build(", StringComparison.Ordinal) || + mainMenu.Contains("AetheriaRuntimeMainMenuSurfaceBuilder.ProjectVerseSettings(", StringComparison.Ordinal) || mainMenuSurfaceBuilder.Contains("ProjectVerseSettings(", StringComparison.Ordinal) || mainMenu.Contains("new AetheriaRuntimeClientTargetSurfaceState(", StringComparison.Ordinal) || mainMenuSurfaceBuilder.Contains("new AetheriaRuntimeClientTargetSurfaceState(", StringComparison.Ordinal)) { throw new InvalidOperationException( - "Main-menu Verse state must come from typed documents through AetheriaRuntimeClientTargetSurfaceBuilder; do not reintroduce menu-local client-target state shaping."); + "Unity MainMenu must consume daemon-published main-menu surfaces instead of reintroducing menu-local client-target state shaping."); } } @@ -16682,16 +16715,18 @@ static void RequireRuntimeStateReaderOwnsUnityStateAcquisition(string root) var requiredSurfaceDocumentSymbols = new[] { "public static class AetheriaRuntimeSurfaceDocuments", - "public static EveSurfaceDocument ToEveSurfaceDocument(AetheriaRuntimeSurfaceDocument document)", - "public static EveSurfaceDocument ResolveStateRefs(", + "public static GameCult.Mesh.EveSurfaceDocument ToPortableSurface(AetheriaRuntimeSurfaceDocument document)", + "public static EveUiSurfaceDocument ToEveSurfaceDocument(AetheriaRuntimeSurfaceDocument document)", + "public static EveUiSurfaceDocument ToEveSurfaceDocument(GameCult.Mesh.EveSurfaceDocument document)", + "public static EveUiSurfaceDocument ResolveStateRefs(", "CultMeshStateRefResolver? stateRefResolver", "ResolvePropRefs(props, resolveStateRef)", "ResolvePropRef(props, AetheriaRuntimeSurfaceStateRefs.Source, \"value\", resolveStateRef)", "IsStatePointerProp(prop.Key)", "ResolvePointerValueKey(refProp.Key)", - "public static EveSurfaceDocument EmptySurface(string surfaceId)", - "new EveSurfaceDocument(", - "new EveSurfaceComponent(" + "public static EveUiSurfaceDocument EmptySurface(string surfaceId)", + "new EveUiSurfaceDocument(", + "new EveUiSurfaceComponent(" }; var missingSurfaceDocumentSymbols = requiredSurfaceDocumentSymbols .Where(symbol => !runtimeSurfaceDocuments.Contains(symbol, StringComparison.Ordinal)) @@ -16977,7 +17012,8 @@ static void RequireRuntimeStateReaderOwnsUnityStateAcquisition(string root) var missingProviderClientAccess = providerOwnedClientAccessSources .Where(pair => - !pair.Value.Contains("AetheriaUnityRuntimeClientProvider", StringComparison.Ordinal)) + !pair.Value.Contains("AetheriaUnityRuntimeClientProvider", StringComparison.Ordinal) && + !pair.Value.Contains("AetheriaEveRuntimeUnityHooks", StringComparison.Ordinal)) .Select(pair => pair.Key) .ToArray(); if (missingProviderClientAccess.Length > 0) @@ -17023,10 +17059,11 @@ static void RequireRuntimeStateReaderOwnsUnityStateAcquisition(string root) "public CultMeshDocumentHandle AuthorityPolicy { get; }", "public CultMeshDocumentHandle DaemonFrame { get; }", "public CultMeshDocumentHandle DaemonSoaView { get; }", - "public CultMeshDocumentHandle GameSurface { get; }", - "public CultMeshDocumentHandle GameTuiSurface { get; }", - "public CultMeshDocumentHandle EditorSurface { get; }", - "public CultMeshDocumentHandle EditorTuiSurface { get; }", + "using MeshEveSurfaceDocument = GameCult.Mesh.EveSurfaceDocument;", + "public CultMeshDocumentHandle GameSurface { get; }", + "public CultMeshDocumentHandle GameTuiSurface { get; }", + "public CultMeshDocumentHandle EditorSurface { get; }", + "public CultMeshDocumentHandle EditorTuiSurface { get; }", "public CultMeshDocumentHandle Catalog { get; }", "public CultMeshDocumentHandle LoadoutTemplates { get; }", "public CultMeshDocumentHandle PlayerSettings { get; }", @@ -17420,11 +17457,9 @@ static void RequireRuntimeStateReaderOwnsUnityStateAcquisition(string root) } if (!mainMenu.Contains("AetheriaUnityRuntimeClientProvider", StringComparison.Ordinal) || - !mainMenu.Contains("ResolveSectorMap(AetheriaRuntimeStateBootReport stateBoot)", StringComparison.Ordinal) || + !mainMenu.Contains("ResolveMainMenuSurface(string surfaceId)", StringComparison.Ordinal) || !mainMenu.Contains(".RuntimeState(stateBoot, \"unity-main-menu\")", StringComparison.Ordinal) || - !mainMenu.Contains(".SectorMap", StringComparison.Ordinal) || - !mainMenu.Contains(".PlayerSettings", StringComparison.Ordinal) || - !mainMenu.Contains(".VerseHostSettings", StringComparison.Ordinal) || + !mainMenu.Contains(".MainMenuSurface(surfaceId, CanOpenRuntimeInputScreen(), InGame)", StringComparison.Ordinal) || !mainMenu.Contains(".Latest()", StringComparison.Ordinal)) { throw new InvalidOperationException( @@ -17513,7 +17548,7 @@ static void RequireRuntimeStateReaderOwnsUnityStateAcquisition(string root) string.Join(", ", mainMenuReaderHits)); } - if (!eveSurfacePresenter.Contains(".RuntimeState(stateBoot, \"unity-eve-surface-presenter\")", StringComparison.Ordinal) || + if (!eveSurfacePresenter.Contains(".RequireRuntimeState(stateBoot, \"unity-eve-surface-presenter\")", StringComparison.Ordinal) || !eveSurfacePresenter.Contains(".EveSurfaceDocument(surfaceId)", StringComparison.Ordinal) || !eveSurfacePresenter.Contains("?.Reactive()", StringComparison.Ordinal) || !eveSurfacePresenter.Contains("ReadDaemonSurface(stateBoot)", StringComparison.Ordinal)) @@ -17522,8 +17557,8 @@ static void RequireRuntimeStateReaderOwnsUnityStateAcquisition(string root) "Aetheria Eve surface presenter must grab the provider RuntimeState and read the daemon surface through AetheriaClientState reactive typed documents."); } - if (!eveSurfacePresenter.Contains("AetheriaUnityRuntimeClientProvider.EveSurfaceCultMeshStateRefResolver(", StringComparison.Ordinal) || - !eveUnitySurfaceHost.Contains("AetheriaUnityRuntimeClientProvider.EveSurfaceCultMeshStateRefResolver(", StringComparison.Ordinal)) + if (!eveSurfacePresenter.Contains("AetheriaEveRuntimeUnityHooks.TryCreateStateRefResolver(", StringComparison.Ordinal) || + !eveUnitySurfaceHost.Contains("AetheriaEveRuntimeUnityHooks.TryCreateDefaultStateRefResolver()", StringComparison.Ordinal)) { throw new InvalidOperationException( "Unity Eve surface lowering must resolve provider state refs through provider-native managed AetheriaClientState documents."); diff --git a/Assets/Scripts/UI/MainMenu.cs b/Assets/Scripts/UI/MainMenu.cs index 7bf687329..867de8251 100644 --- a/Assets/Scripts/UI/MainMenu.cs +++ b/Assets/Scripts/UI/MainMenu.cs @@ -16,20 +16,12 @@ public class MainMenu : MonoBehaviour public GameSettings Settings; public ConfirmationDialog Dialog; public bool InGame; - public float FadeTime = 0.5f; - public float FadeDistance = 512f; - public float FadeAlphaExponent = 2f; - public float FadePositionExponent = 2f; public float HoverSpacing = 8f; public float HoverAnimationDuration = 0.16f; - private UIDocument _currentMenuSurfaceDocument; - private UIDocument _nextMenuSurfaceDocument; + private UIDocument _menuSurfaceDocument; private Func _canOpenRuntimeInputScreen; private Action _openRuntimeInputScreen; - private bool _fadeFromRight; - private bool _fading; - private float _fadeLerp; private readonly List _hoverButtons = new List(); private readonly AetheriaEveUnitySurfaceChrome _menuSurfaceChrome = new AetheriaEveUnitySurfaceChrome { @@ -51,7 +43,6 @@ public class MainMenu : MonoBehaviour void Update() { - UpdateMenuFade(); UpdateHoverButtons(); } @@ -219,30 +210,16 @@ public class MainMenu : MonoBehaviour Action commandHandler, bool animateFromRight) { - var initialRender = _currentMenuSurfaceDocument == null; - var targetDocument = initialRender ? _currentMenuSurfaceDocument : _nextMenuSurfaceDocument; - targetDocument = AetheriaEveUnitySurfaceHost.RenderRuntime( + _menuSurfaceDocument = AetheriaEveUnitySurfaceHost.RenderRuntime( transform, - targetDocument, - initialRender ? "Aetheria Menu Surface" : "Aetheria Menu Surface Transition", + _menuSurfaceDocument, + "Aetheria Menu Surface", document, commandHandler, _menuSurfaceChrome, - sortingOrder: initialRender ? 1000 : 1001); + sortingOrder: 1000); - ApplyMenuStyles(targetDocument.rootVisualElement, IsRootMainMenu(document)); - SetDocumentTransition(targetDocument, initialRender ? 0f : (animateFromRight ? FadeDistance : -FadeDistance), initialRender ? 1f : 0f); - - if (initialRender) - { - _currentMenuSurfaceDocument = targetDocument; - return; - } - - _nextMenuSurfaceDocument = targetDocument; - _fadeFromRight = animateFromRight; - _fadeLerp = 0f; - _fading = true; + ApplyMenuStyles(_menuSurfaceDocument.rootVisualElement, IsRootMainMenu(document)); } private static bool IsRootMainMenu(AetheriaRuntimeSurfaceDocument document) @@ -253,46 +230,6 @@ public class MainMenu : MonoBehaviour StringComparison.Ordinal); } - private void UpdateMenuFade() - { - if (!_fading) - return; - - _fadeLerp += Time.unscaledDeltaTime / Mathf.Max(0.01f, FadeTime); - var t = Mathf.Clamp01(_fadeLerp); - var outgoing = Mathf.Pow(t, FadePositionExponent); - var incoming = Mathf.Pow(1f - t, FadePositionExponent); - var direction = _fadeFromRight ? 1f : -1f; - - SetDocumentTransition( - _currentMenuSurfaceDocument, - -direction * FadeDistance * outgoing, - Mathf.Pow(1f - t, FadeAlphaExponent)); - SetDocumentTransition( - _nextMenuSurfaceDocument, - direction * FadeDistance * incoming, - Mathf.Pow(t, FadeAlphaExponent)); - - if (_fadeLerp <= 1f) - return; - - _fading = false; - AetheriaEveUnitySurfaceHost.Hide(_currentMenuSurfaceDocument); - var previous = _currentMenuSurfaceDocument; - _currentMenuSurfaceDocument = _nextMenuSurfaceDocument; - _nextMenuSurfaceDocument = previous; - SetDocumentTransition(_currentMenuSurfaceDocument, 0f, 1f); - } - - private static void SetDocumentTransition(UIDocument document, float x, float opacity) - { - if (document?.rootVisualElement == null) - return; - - document.rootVisualElement.style.translate = new Translate(new Length(x, LengthUnit.Pixel), 0f, 0f); - document.rootVisualElement.style.opacity = opacity; - } - private void UpdateHoverButtons() { for (var i = _hoverButtons.Count - 1; i >= 0; i--) @@ -689,8 +626,7 @@ public class MainMenu : MonoBehaviour private void HideMenuSurface() { - AetheriaEveUnitySurfaceHost.Hide(_currentMenuSurfaceDocument); - AetheriaEveUnitySurfaceHost.Hide(_nextMenuSurfaceDocument); + AetheriaEveUnitySurfaceHost.Hide(_menuSurfaceDocument); } public void SetRuntimeInputScreenShell(Func canOpenRuntimeInputScreen, Action openRuntimeInputScreen) @@ -777,16 +713,10 @@ public class MainMenu : MonoBehaviour private void OnDestroy() { - if (_currentMenuSurfaceDocument != null) + if (_menuSurfaceDocument != null) { - Destroy(_currentMenuSurfaceDocument.gameObject); - _currentMenuSurfaceDocument = null; - } - - if (_nextMenuSurfaceDocument != null) - { - Destroy(_nextMenuSurfaceDocument.gameObject); - _nextMenuSurfaceDocument = null; + Destroy(_menuSurfaceDocument.gameObject); + _menuSurfaceDocument = null; } } diff --git a/GameData/aetheria-world.cc b/GameData/aetheria-world.cc index dc4173233278dce15d4efd23de9e435af5f9e5de..1785936ed3c8c5b7af87909a16524a2e9267e366 100644 GIT binary patch delta 32 ocmZ2+jOEQg#tCwavo|WXb8VJW^A6eU(0M^n+a literal 74536 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 _itemsByKey; - private readonly Dictionary _corporationsByKey; - private readonly Dictionary _nameFilesByKey; + public AetheriaRuntimeCatalogSnapshot() + { + } public AetheriaRuntimeCatalogSnapshot( AetheriaRuntimeCatalogItem[] items, @@ -22,39 +24,39 @@ namespace GameCult.Aetheria.State.Verse AetheriaRuntimeNameFile[] nameFiles, AetheriaRuntimeTradeValueSettings? tradeValueSettings = null) { - Items = items; - Corporations = corporations; - NameFiles = nameFiles; + Items = items ?? Array.Empty(); + Corporations = corporations ?? Array.Empty(); + NameFiles = nameFiles ?? Array.Empty(); TradeValueSettings = tradeValueSettings ?? AetheriaRuntimeTradeValueSettings.Default; - TradeItems = items.Where(item => item.Price > 0).ToArray(); - EquipmentItems = items.Where(item => !string.IsNullOrWhiteSpace(item.HardpointType)).ToArray(); - - _itemsByKey = items - .Where(item => !string.IsNullOrWhiteSpace(item.ItemKey)) - .ToDictionary(item => item.ItemKey, StringComparer.OrdinalIgnoreCase); - _corporationsByKey = corporations - .Where(corporation => !string.IsNullOrWhiteSpace(corporation.CorporationKey)) - .ToDictionary(corporation => corporation.CorporationKey, StringComparer.OrdinalIgnoreCase); - _nameFilesByKey = nameFiles - .Where(nameFile => !string.IsNullOrWhiteSpace(nameFile.NameFileKey)) - .ToDictionary(nameFile => nameFile.NameFileKey, StringComparer.OrdinalIgnoreCase); } - public IReadOnlyList Items { get; } + [Key(0)] + [CultName] + public string CatalogId { get; set; } = DocumentName; - public IReadOnlyList TradeItems { get; } + [Key(1)] + public IReadOnlyList Items { get; set; } = Array.Empty(); - public IReadOnlyList EquipmentItems { get; } + [IgnoreMember] + public IReadOnlyList TradeItems => + Items.Where(item => item.Price > 0).ToArray(); - public IReadOnlyList Corporations { get; } + [IgnoreMember] + public IReadOnlyList EquipmentItems => + Items.Where(item => !string.IsNullOrWhiteSpace(item.HardpointType)).ToArray(); - public IReadOnlyList NameFiles { get; } + [Key(2)] + public IReadOnlyList Corporations { get; set; } = Array.Empty(); - public AetheriaRuntimeTradeValueSettings TradeValueSettings { get; } + [Key(3)] + public IReadOnlyList NameFiles { get; set; } = Array.Empty(); + + [Key(4)] + public AetheriaRuntimeTradeValueSettings TradeValueSettings { get; set; } = AetheriaRuntimeTradeValueSettings.Default; public AetheriaRuntimeCatalogItem? FindItem(string itemKey) { - return TryGet(_itemsByKey, itemKey); + return TryGet(Items, itemKey, item => item.ItemKey); } public AetheriaRuntimeCatalogItem? FindItem(T? item, Func itemKey) where T : class @@ -67,12 +69,12 @@ namespace GameCult.Aetheria.State.Verse public AetheriaRuntimeCorporation? FindCorporation(string corporationKey) { - return TryGet(_corporationsByKey, corporationKey); + return TryGet(Corporations, corporationKey, corporation => corporation.CorporationKey); } public AetheriaRuntimeNameFile? FindNameFile(string nameFileKey) { - return TryGet(_nameFilesByKey, nameFileKey); + return TryGet(NameFiles, nameFileKey, nameFile => nameFile.NameFileKey); } public IEnumerable FindItemsByBehavior(string behaviorKind) @@ -99,9 +101,11 @@ namespace GameCult.Aetheria.State.Verse return FindNameFile(corporation.GeonameFileKey); } - private static T? TryGet(IReadOnlyDictionary dictionary, string key) where T : class + private static T? TryGet(IEnumerable values, string key, Func getKey) where T : class { - return string.IsNullOrWhiteSpace(key) ? null : dictionary.TryGetValue(key, out var value) ? value : null; + return string.IsNullOrWhiteSpace(key) + ? null + : values.FirstOrDefault(value => string.Equals(getKey(value), key, StringComparison.OrdinalIgnoreCase)); } } @@ -109,6 +113,11 @@ namespace GameCult.Aetheria.State.Verse public sealed class AetheriaRuntimeLoadoutTemplatesDocument { public const string SchemaId = "gamecult.aetheria.loadout_templates.v1"; + public const string DocumentName = "aetheria.loadout_templates"; + + public AetheriaRuntimeLoadoutTemplatesDocument() + { + } public AetheriaRuntimeLoadoutTemplatesDocument( IReadOnlyList? templates = null) @@ -116,9 +125,16 @@ namespace GameCult.Aetheria.State.Verse Templates = templates ?? Array.Empty(); } - public IReadOnlyList Templates { get; } + [Key(0)] + [CultName] + public string CatalogId { get; set; } = DocumentName; + + [Key(1)] + public IReadOnlyList Templates { get; set; } = + Array.Empty(); } + [MessagePackObject(true)] public sealed class AetheriaRuntimeCatalogItem { public AetheriaRuntimeCatalogItem( @@ -221,54 +237,54 @@ namespace GameCult.Aetheria.State.Verse CompoundCommodityCategory = compoundCommodityCategory; } - public string ItemKey { get; } - public string Name { get; } - public string Category { get; } - public string Description { get; } - public string ManufacturerKey { get; } - public int Price { get; } - public double Mass { get; } - public double SpecificHeat { get; } - public double Conductivity { get; } - public double Volume { get; } - public int ShapeWidth { get; } - public int ShapeHeight { get; } - public int OccupiedCells { get; } - public IReadOnlyList ShapeCells { get; } - public int InteriorShapeWidth { get; } - public int InteriorShapeHeight { get; } - public int InteriorOccupiedCells { get; } - public IReadOnlyList InteriorShapeCells { get; } - public IReadOnlyList Hardpoints { get; } - public IReadOnlyList BehaviorPayloads { get; } - public string HardpointType { get; } - public string HullType { get; } - public IReadOnlyList BehaviorKinds { get; } - public int MaxStack { get; } - public bool Stackable { get; } - public double Duration { get; } - public double Durability { get; } - public string WeaponRange { get; } - public string WeaponCaliber { get; } - public string WeaponType { get; } - public string WeaponFireTypes { get; } - public string WeaponModifiers { get; } - public double MinimumTemperature { get; } - public double MaximumTemperature { get; } - public IReadOnlyList ThermalPerformanceCurveKeys { get; } - public string HullPrefab { get; } - public double ThermalResilience { get; } - public double HullGridOffset { get; } - public double HullArmor { get; } - public double HullDrag { get; } - public bool HullCanTow { get; } - public int DockingMaxSizeX { get; } - public int DockingMaxSizeY { get; } - public string ActionBarIcon { get; } - public IReadOnlyList AudioStats { get; } - public IReadOnlyList EffectivenessCurveKeys { get; } - public string SimpleCommodityCategory { get; } - public string CompoundCommodityCategory { get; } + public string ItemKey { get; set; } + public string Name { get; set; } + public string Category { get; set; } + public string Description { get; set; } + public string ManufacturerKey { get; set; } + public int Price { get; set; } + public double Mass { get; set; } + public double SpecificHeat { get; set; } + public double Conductivity { get; set; } + public double Volume { get; set; } + public int ShapeWidth { get; set; } + public int ShapeHeight { get; set; } + public int OccupiedCells { get; set; } + public IReadOnlyList ShapeCells { get; set; } + public int InteriorShapeWidth { get; set; } + public int InteriorShapeHeight { get; set; } + public int InteriorOccupiedCells { get; set; } + public IReadOnlyList InteriorShapeCells { get; set; } + public IReadOnlyList Hardpoints { get; set; } + public IReadOnlyList BehaviorPayloads { get; set; } + public string HardpointType { get; set; } + public string HullType { get; set; } + public IReadOnlyList BehaviorKinds { get; set; } + public int MaxStack { get; set; } + public bool Stackable { get; set; } + public double Duration { get; set; } + public double Durability { get; set; } + public string WeaponRange { get; set; } + public string WeaponCaliber { get; set; } + public string WeaponType { get; set; } + public string WeaponFireTypes { get; set; } + public string WeaponModifiers { get; set; } + public double MinimumTemperature { get; set; } + public double MaximumTemperature { get; set; } + public IReadOnlyList ThermalPerformanceCurveKeys { get; set; } + public string HullPrefab { get; set; } + public double ThermalResilience { get; set; } + public double HullGridOffset { get; set; } + public double HullArmor { get; set; } + public double HullDrag { get; set; } + public bool HullCanTow { get; set; } + public int DockingMaxSizeX { get; set; } + public int DockingMaxSizeY { get; set; } + public string ActionBarIcon { get; set; } + public IReadOnlyList AudioStats { get; set; } + public IReadOnlyList EffectivenessCurveKeys { get; set; } + public string SimpleCommodityCategory { get; set; } + public string CompoundCommodityCategory { get; set; } public bool TryGetHardpointType(out TEnum hardpointType) where TEnum : struct { @@ -292,6 +308,7 @@ namespace GameCult.Aetheria.State.Verse } } + [MessagePackObject(true)] public sealed class AetheriaRuntimeAudioStat { public AetheriaRuntimeAudioStat(uint parameter, AetheriaRuntimePerformanceStat stat) @@ -300,10 +317,11 @@ namespace GameCult.Aetheria.State.Verse Stat = stat; } - public uint Parameter { get; } - public AetheriaRuntimePerformanceStat Stat { get; } + public uint Parameter { get; set; } + public AetheriaRuntimePerformanceStat Stat { get; set; } } + [MessagePackObject(true)] public sealed class AetheriaRuntimePerformanceStat { public AetheriaRuntimePerformanceStat( @@ -322,14 +340,15 @@ namespace GameCult.Aetheria.State.Verse Recipe = recipe; } - public double Min { get; } - public double Max { get; } - public double HeatExponentMultiplier { get; } - public double DurabilityExponentMultiplier { get; } - public double QualityExponent { get; } - public AetheriaRuntimeStatRecipe? Recipe { get; } + public double Min { get; set; } + public double Max { get; set; } + public double HeatExponentMultiplier { get; set; } + public double DurabilityExponentMultiplier { get; set; } + public double QualityExponent { get; set; } + public AetheriaRuntimeStatRecipe? Recipe { get; set; } } + [MessagePackObject(true)] public sealed class AetheriaRuntimeStatRecipe { public AetheriaRuntimeStatRecipe(double baseValue, IReadOnlyList modifiers) @@ -338,10 +357,11 @@ namespace GameCult.Aetheria.State.Verse Modifiers = modifiers ?? Array.Empty(); } - public double BaseValue { get; } - public IReadOnlyList Modifiers { get; } + public double BaseValue { get; set; } + public IReadOnlyList Modifiers { get; set; } } + [MessagePackObject(true)] public sealed class AetheriaRuntimeStatRecipeModifier { public AetheriaRuntimeStatRecipeModifier( @@ -358,13 +378,14 @@ namespace GameCult.Aetheria.State.Verse Enabled = enabled; } - public string Condition { get; } - public string Operation { get; } - public double Amount { get; } - public IReadOnlyList CurveKeys { get; } - public bool Enabled { get; } + public string Condition { get; set; } + public string Operation { get; set; } + public double Amount { get; set; } + public IReadOnlyList CurveKeys { get; set; } + public bool Enabled { get; set; } } + [MessagePackObject(true)] public sealed class AetheriaRuntimeCurveKey { public AetheriaRuntimeCurveKey(double time, double value, double inTangent, double outTangent) @@ -375,12 +396,13 @@ namespace GameCult.Aetheria.State.Verse OutTangent = outTangent; } - public double Time { get; } - public double Value { get; } - public double InTangent { get; } - public double OutTangent { get; } + public double Time { get; set; } + public double Value { get; set; } + public double InTangent { get; set; } + public double OutTangent { get; set; } } + [MessagePackObject(true)] public sealed class AetheriaRuntimeShapeCell { public AetheriaRuntimeShapeCell(int x, int y) @@ -389,11 +411,12 @@ namespace GameCult.Aetheria.State.Verse Y = y; } - public int X { get; } + public int X { get; set; } - public int Y { get; } + public int Y { get; set; } } + [MessagePackObject(true)] public sealed class AetheriaRuntimeBehaviorPayload { public AetheriaRuntimeBehaviorPayload( @@ -408,15 +431,16 @@ namespace GameCult.Aetheria.State.Verse Fields = fields; } - public int UnionKey { get; } + public int UnionKey { get; set; } - public string Kind { get; } + public string Kind { get; set; } - public int Group { get; } + public int Group { get; set; } - public IReadOnlyList Fields { get; } + public IReadOnlyList Fields { get; set; } } + [MessagePackObject(true)] public sealed class AetheriaRuntimeBehaviorField { public AetheriaRuntimeBehaviorField(int key, AetheriaRuntimeBehaviorValue value) @@ -425,11 +449,12 @@ namespace GameCult.Aetheria.State.Verse Value = value; } - public int Key { get; } + public int Key { get; set; } - public AetheriaRuntimeBehaviorValue Value { get; } + public AetheriaRuntimeBehaviorValue Value { get; set; } } + [MessagePackObject(true)] public sealed class AetheriaRuntimeBehaviorMapEntry { public AetheriaRuntimeBehaviorMapEntry(string key, AetheriaRuntimeBehaviorValue value) @@ -438,11 +463,12 @@ namespace GameCult.Aetheria.State.Verse Value = value; } - public string Key { get; } + public string Key { get; set; } - public AetheriaRuntimeBehaviorValue Value { get; } + public AetheriaRuntimeBehaviorValue Value { get; set; } } + [MessagePackObject(true)] public sealed class AetheriaRuntimeBehaviorValue { public AetheriaRuntimeBehaviorValue( @@ -465,23 +491,24 @@ namespace GameCult.Aetheria.State.Verse MapEntries = mapEntries; } - public string Kind { get; } + public string Kind { get; set; } - public string StringValue { get; } + public string StringValue { get; set; } - public double NumberValue { get; } + public double NumberValue { get; set; } - public bool BoolValue { get; } + public bool BoolValue { get; set; } - public string LegacyIdValue { get; } + public string LegacyIdValue { get; set; } - public string ItemKeyValue { get; } + public string ItemKeyValue { get; set; } - public IReadOnlyList Children { get; } + public IReadOnlyList Children { get; set; } - public IReadOnlyList MapEntries { get; } + public IReadOnlyList MapEntries { get; set; } } + [MessagePackObject(true)] public sealed class AetheriaRuntimeHardpoint { public AetheriaRuntimeHardpoint( @@ -508,27 +535,28 @@ namespace GameCult.Aetheria.State.Verse Armor = armor; } - public string Type { get; } + public string Type { get; set; } - public int PositionX { get; } + public int PositionX { get; set; } - public int PositionY { get; } + public int PositionY { get; set; } - public int ShapeWidth { get; } + public int ShapeWidth { get; set; } - public int ShapeHeight { get; } + public int ShapeHeight { get; set; } - public int OccupiedCells { get; } + public int OccupiedCells { get; set; } - public IReadOnlyList ShapeCells { get; } + public IReadOnlyList ShapeCells { get; set; } - public string Transform { get; } + public string Transform { get; set; } - public string Rotation { get; } + public string Rotation { get; set; } - public double Armor { get; } + public double Armor { get; set; } } + [MessagePackObject(true)] public sealed class AetheriaRuntimeCorporation { public AetheriaRuntimeCorporation( @@ -553,17 +581,18 @@ namespace GameCult.Aetheria.State.Verse Allegiances = allegiances; } - public string CorporationKey { get; } - public string Name { get; } - public string ShortName { get; } - public string Description { get; } - public string GeonameFileKey { get; } - public string BossHullItemKey { get; } - public int InfluenceDistance { get; } - public int AllegianceCount { get; } - public IReadOnlyList Allegiances { get; } + public string CorporationKey { get; set; } + public string Name { get; set; } + public string ShortName { get; set; } + public string Description { get; set; } + public string GeonameFileKey { get; set; } + public string BossHullItemKey { get; set; } + public int InfluenceDistance { get; set; } + public int AllegianceCount { get; set; } + public IReadOnlyList Allegiances { get; set; } } + [MessagePackObject(true)] public sealed class AetheriaRuntimeCorporationAllegiance { public AetheriaRuntimeCorporationAllegiance(string corporationKey, double weight) @@ -572,10 +601,11 @@ namespace GameCult.Aetheria.State.Verse Weight = weight; } - public string CorporationKey { get; } - public double Weight { get; } + public string CorporationKey { get; set; } + public double Weight { get; set; } } + [MessagePackObject(true)] public sealed class AetheriaRuntimeNameFile { public AetheriaRuntimeNameFile( @@ -592,13 +622,14 @@ namespace GameCult.Aetheria.State.Verse Names = names; } - public string NameFileKey { get; } - public string Name { get; } - public int NameCount { get; } - public IReadOnlyList SampleNames { get; } - public IReadOnlyList Names { get; } + public string NameFileKey { get; set; } + public string Name { get; set; } + public int NameCount { get; set; } + public IReadOnlyList SampleNames { get; set; } + public IReadOnlyList Names { get; set; } } + [MessagePackObject(true)] public sealed class AetheriaRuntimePlayerSettingsSnapshot { public AetheriaRuntimePlayerSettingsSnapshot( @@ -625,18 +656,19 @@ namespace GameCult.Aetheria.State.Verse ActionBarInputs = actionBarInputs; } - public string PlayerName { get; } - public bool TutorialPassed { get; } - public IReadOnlyList StoryFileHashes { get; } - public string TemperatureUnit { get; } - public int SignificantDigits { get; } - public double DefaultShutdownPerformance { get; } - public string NebulaQuality { get; } - public bool ShowAsteroidsInMinimap { get; } - public IReadOnlyList BindingOverrides { get; } - public IReadOnlyList ActionBarInputs { get; } + public string PlayerName { get; set; } + public bool TutorialPassed { get; set; } + public IReadOnlyList StoryFileHashes { get; set; } + public string TemperatureUnit { get; set; } + public int SignificantDigits { get; set; } + public double DefaultShutdownPerformance { get; set; } + public string NebulaQuality { get; set; } + public bool ShowAsteroidsInMinimap { get; set; } + public IReadOnlyList BindingOverrides { get; set; } + public IReadOnlyList ActionBarInputs { get; set; } } + [MessagePackObject(true)] public sealed class AetheriaRuntimeVerseHostSettingsSnapshot { public AetheriaRuntimeVerseHostSettingsSnapshot( @@ -661,17 +693,18 @@ namespace GameCult.Aetheria.State.Verse LastUpdatedAtUtc = lastUpdatedAtUtc; } - public string ServiceId { get; } - public string VerseId { get; } - public string RootVerse { get; } - public string CanonicalService { get; } - public string LocatedService { get; } - public string CultMeshAddress { get; } - public string Title { get; } - public string Visibility { get; } - public string LastUpdatedAtUtc { get; } + public string ServiceId { get; set; } + public string VerseId { get; set; } + public string RootVerse { get; set; } + public string CanonicalService { get; set; } + public string LocatedService { get; set; } + public string CultMeshAddress { get; set; } + public string Title { get; set; } + public string Visibility { get; set; } + public string LastUpdatedAtUtc { get; set; } } + [MessagePackObject(true)] public sealed class AetheriaRuntimeStoryFileHash { public AetheriaRuntimeStoryFileHash(string storyPath, string hash) @@ -680,10 +713,11 @@ namespace GameCult.Aetheria.State.Verse Hash = hash; } - public string StoryPath { get; } - public string Hash { get; } + public string StoryPath { get; set; } + public string Hash { get; set; } } + [MessagePackObject(true)] public sealed class AetheriaRuntimeInputBindingOverride { public AetheriaRuntimeInputBindingOverride(string actionName, int bindingIndex, string bindingPath) @@ -693,11 +727,12 @@ namespace GameCult.Aetheria.State.Verse BindingPath = bindingPath; } - public string ActionName { get; } - public int BindingIndex { get; } - public string BindingPath { get; } + public string ActionName { get; set; } + public int BindingIndex { get; set; } + public string BindingPath { get; set; } } + [MessagePackObject(true)] public sealed class AetheriaRuntimeLoadoutTemplateSnapshot { public AetheriaRuntimeLoadoutTemplateSnapshot( @@ -714,13 +749,14 @@ namespace GameCult.Aetheria.State.Verse UpdatedAtUtc = updatedAtUtc; } - public string Name { get; } - public string OwnerPlayerKey { get; } - public AetheriaRuntimeEntityLoadoutSnapshot RootEntity { get; } - public string CreatedAtUtc { get; } - public string UpdatedAtUtc { get; } + public string Name { get; set; } + public string OwnerPlayerKey { get; set; } + public AetheriaRuntimeEntityLoadoutSnapshot RootEntity { get; set; } + public string CreatedAtUtc { get; set; } + public string UpdatedAtUtc { get; set; } } + [MessagePackObject(true)] public sealed class AetheriaRuntimeEntityLoadoutSnapshot { public AetheriaRuntimeEntityLoadoutSnapshot( @@ -751,20 +787,21 @@ namespace GameCult.Aetheria.State.Verse Children = children; } - public string Name { get; } - public string Kind { get; } - public string FactionKey { get; } - public AetheriaRuntimeLoadoutItemSnapshot Hull { get; } - public IReadOnlyList Equipment { get; } - public IReadOnlyList CargoBays { get; } - public IReadOnlyList DockingBays { get; } - public IReadOnlyList CargoContents { get; } - public IReadOnlyList DockingBayContents { get; } - public IReadOnlyList DockingBayAssignments { get; } - public IReadOnlyList> WeaponGroups { get; } - public IReadOnlyList Children { get; } + public string Name { get; set; } + public string Kind { get; set; } + public string FactionKey { get; set; } + public AetheriaRuntimeLoadoutItemSnapshot Hull { get; set; } + public IReadOnlyList Equipment { get; set; } + public IReadOnlyList CargoBays { get; set; } + public IReadOnlyList DockingBays { get; set; } + public IReadOnlyList CargoContents { get; set; } + public IReadOnlyList DockingBayContents { get; set; } + public IReadOnlyList DockingBayAssignments { get; set; } + public IReadOnlyList> WeaponGroups { get; set; } + public IReadOnlyList Children { get; set; } } + [MessagePackObject(true)] public sealed class AetheriaRuntimeLoadoutItemSnapshot { public AetheriaRuntimeLoadoutItemSnapshot( @@ -785,15 +822,16 @@ namespace GameCult.Aetheria.State.Verse Temperature = temperature; } - public string ItemKey { get; } - public double Quality { get; } - public double Durability { get; } - public int Quantity { get; } - public bool Enabled { get; } - public bool OverrideShutdown { get; } - public double Temperature { get; } + public string ItemKey { get; set; } + public double Quality { get; set; } + public double Durability { get; set; } + public int Quantity { get; set; } + public bool Enabled { get; set; } + public bool OverrideShutdown { get; set; } + public double Temperature { get; set; } } + [MessagePackObject(true)] public sealed class AetheriaRuntimeLoadoutItemSlotSnapshot { public AetheriaRuntimeLoadoutItemSlotSnapshot(int x, int y, AetheriaRuntimeLoadoutItemSnapshot item) @@ -803,11 +841,12 @@ namespace GameCult.Aetheria.State.Verse Item = item; } - public int X { get; } - public int Y { get; } - public AetheriaRuntimeLoadoutItemSnapshot Item { get; } + public int X { get; set; } + public int Y { get; set; } + public AetheriaRuntimeLoadoutItemSnapshot Item { get; set; } } + [MessagePackObject(true)] public sealed class AetheriaRuntimeCargoBayLoadoutSnapshot { public AetheriaRuntimeCargoBayLoadoutSnapshot(IReadOnlyList items) @@ -815,9 +854,10 @@ namespace GameCult.Aetheria.State.Verse Items = items; } - public IReadOnlyList Items { get; } + public IReadOnlyList Items { get; set; } } + [MessagePackObject(true)] public sealed class AetheriaRuntimeEntitySnapshot { public AetheriaRuntimeEntitySnapshot( @@ -898,45 +938,46 @@ namespace GameCult.Aetheria.State.Verse ShutdownPerformance = shutdownPerformance; } - public string RecordKey { get; } - public int EntityIndex { get; } - public string Name { get; } - public string Kind { get; } - public double PositionX { get; } - public double PositionY { get; } - public double PositionZ { get; } - public double DirectionX { get; } - public double DirectionY { get; } - public string FactionKey { get; } - public string HullItemKey { get; } - public IReadOnlyList Equipment { get; } - public IReadOnlyList CargoBays { get; } - public IReadOnlyList DockingBays { get; } - public IReadOnlyList ChildEntityKeys { get; } - public IReadOnlyList> WeaponGroups { get; } - public IReadOnlyList StatGrids { get; } - public double VelocityX { get; } - public double VelocityY { get; } - public string TargetEntityKey { get; } - public bool IsActive { get; } - public bool HeatsinksEnabled { get; } - public bool OverrideShutdown { get; } - public double TractorPower { get; } - public double Heatstroke { get; } - public double Hypothermia { get; } - public IReadOnlyList ActiveConsumables { get; } - public IReadOnlyList BehaviorProgress { get; } - public IReadOnlyList WeaponStates { get; } - public IReadOnlyList BehaviorStates { get; } - public IReadOnlyList CargoContents { get; } - public IReadOnlyList DockingBayContents { get; } - public IReadOnlyList DockingBayAssignments { get; } - public double Visibility { get; } - public int VisibilitySourceCount { get; } - public IReadOnlyList Contacts { get; } - public double ShutdownPerformance { get; } + public string RecordKey { get; set; } + public int EntityIndex { get; set; } + public string Name { get; set; } + public string Kind { get; set; } + public double PositionX { get; set; } + public double PositionY { get; set; } + public double PositionZ { get; set; } + public double DirectionX { get; set; } + public double DirectionY { get; set; } + public string FactionKey { get; set; } + public string HullItemKey { get; set; } + public IReadOnlyList Equipment { get; set; } + public IReadOnlyList CargoBays { get; set; } + public IReadOnlyList DockingBays { get; set; } + public IReadOnlyList ChildEntityKeys { get; set; } + public IReadOnlyList> WeaponGroups { get; set; } + public IReadOnlyList StatGrids { get; set; } + public double VelocityX { get; set; } + public double VelocityY { get; set; } + public string TargetEntityKey { get; set; } + public bool IsActive { get; set; } + public bool HeatsinksEnabled { get; set; } + public bool OverrideShutdown { get; set; } + public double TractorPower { get; set; } + public double Heatstroke { get; set; } + public double Hypothermia { get; set; } + public IReadOnlyList ActiveConsumables { get; set; } + public IReadOnlyList BehaviorProgress { get; set; } + public IReadOnlyList WeaponStates { get; set; } + public IReadOnlyList BehaviorStates { get; set; } + public IReadOnlyList CargoContents { get; set; } + public IReadOnlyList DockingBayContents { get; set; } + public IReadOnlyList DockingBayAssignments { get; set; } + public double Visibility { get; set; } + public int VisibilitySourceCount { get; set; } + public IReadOnlyList Contacts { get; set; } + public double ShutdownPerformance { get; set; } } + [MessagePackObject(true)] public sealed class AetheriaRuntimeEntityContactSnapshot { public AetheriaRuntimeEntityContactSnapshot(string targetEntityKey, double infoGathered, bool hostile, bool visible) @@ -947,12 +988,13 @@ namespace GameCult.Aetheria.State.Verse Visible = visible; } - public string TargetEntityKey { get; } - public double InfoGathered { get; } - public bool Hostile { get; } - public bool Visible { get; } + public string TargetEntityKey { get; set; } + public double InfoGathered { get; set; } + public bool Hostile { get; set; } + public bool Visible { get; set; } } + [MessagePackObject(true)] public sealed class AetheriaRuntimeEntityItemSlotSnapshot { public AetheriaRuntimeEntityItemSlotSnapshot( @@ -977,17 +1019,18 @@ namespace GameCult.Aetheria.State.Verse Temperature = temperature; } - public int X { get; } - public int Y { get; } - public string ItemKey { get; } - public double Quality { get; } - public double Durability { get; } - public int Quantity { get; } - public bool Enabled { get; } - public bool OverrideShutdown { get; } - public double Temperature { get; } + public int X { get; set; } + public int Y { get; set; } + public string ItemKey { get; set; } + public double Quality { get; set; } + public double Durability { get; set; } + public int Quantity { get; set; } + public bool Enabled { get; set; } + public bool OverrideShutdown { get; set; } + public double Temperature { get; set; } } + [MessagePackObject(true)] public sealed class AetheriaRuntimeEntityStatGridSnapshot { public AetheriaRuntimeEntityStatGridSnapshot(string name, int width, int height, IReadOnlyList values) @@ -998,12 +1041,13 @@ namespace GameCult.Aetheria.State.Verse Values = values; } - public string Name { get; } - public int Width { get; } - public int Height { get; } - public IReadOnlyList Values { get; } + public string Name { get; set; } + public int Width { get; set; } + public int Height { get; set; } + public IReadOnlyList Values { get; set; } } + [MessagePackObject(true)] public sealed class AetheriaRuntimeActiveConsumableSnapshot { public AetheriaRuntimeActiveConsumableSnapshot(string itemKey, double quality, double remainingDuration, double duration) @@ -1014,12 +1058,13 @@ namespace GameCult.Aetheria.State.Verse Duration = duration; } - public string ItemKey { get; } - public double Quality { get; } - public double RemainingDuration { get; } - public double Duration { get; } + public string ItemKey { get; set; } + public double Quality { get; set; } + public double RemainingDuration { get; set; } + public double Duration { get; set; } } + [MessagePackObject(true)] public sealed class AetheriaRuntimeBehaviorProgressSnapshot { public AetheriaRuntimeBehaviorProgressSnapshot(string ownerKind, int ownerIndex, int behaviorIndex, string behaviorKind, double progress) @@ -1031,13 +1076,14 @@ namespace GameCult.Aetheria.State.Verse Progress = progress; } - public string OwnerKind { get; } - public int OwnerIndex { get; } - public int BehaviorIndex { get; } - public string BehaviorKind { get; } - public double Progress { get; } + public string OwnerKind { get; set; } + public int OwnerIndex { get; set; } + public int BehaviorIndex { get; set; } + public string BehaviorKind { get; set; } + public double Progress { get; set; } } + [MessagePackObject(true)] public sealed class AetheriaRuntimeWeaponStateSnapshot { public AetheriaRuntimeWeaponStateSnapshot( @@ -1082,27 +1128,28 @@ namespace GameCult.Aetheria.State.Verse LockTargetEntityKey = lockTargetEntityKey; } - public string OwnerKind { get; } - public int OwnerIndex { get; } - public int BehaviorIndex { get; } - public string BehaviorKind { get; } - public bool Firing { get; } - public int Ammo { get; } - public int BurstRemaining { get; } - public double BurstTimer { get; } - public double BurstInterval { get; } - public double CooldownProgress { get; } - public bool CoolingDown { get; } - public bool Charging { get; } - public bool Charged { get; } - public double Charge { get; } - public bool Reloading { get; } - public double ReloadProgress { get; } - public double AmmoIntervalProgress { get; } - public double LockProgress { get; } - public string LockTargetEntityKey { get; } + public string OwnerKind { get; set; } + public int OwnerIndex { get; set; } + public int BehaviorIndex { get; set; } + public string BehaviorKind { get; set; } + public bool Firing { get; set; } + public int Ammo { get; set; } + public int BurstRemaining { get; set; } + public double BurstTimer { get; set; } + public double BurstInterval { get; set; } + public double CooldownProgress { get; set; } + public bool CoolingDown { get; set; } + public bool Charging { get; set; } + public bool Charged { get; set; } + public double Charge { get; set; } + public bool Reloading { get; set; } + public double ReloadProgress { get; set; } + public double AmmoIntervalProgress { get; set; } + public double LockProgress { get; set; } + public string LockTargetEntityKey { get; set; } } + [MessagePackObject(true)] public sealed class AetheriaRuntimeBehaviorStateSnapshot { public AetheriaRuntimeBehaviorStateSnapshot( @@ -1219,60 +1266,60 @@ namespace GameCult.Aetheria.State.Verse TurretControllerPredictShots = turretControllerPredictShots; } - public string OwnerKind { get; } - public int OwnerIndex { get; } - public int BehaviorIndex { get; } - public string BehaviorKind { get; } - public bool Pinging { get; } - public double PingCooldown { get; } - public double PingLerp { get; } - public double PingRadius { get; } - public int PingedEntityCount { get; } - public double RadiatorTemperature { get; } - public double Emissivity { get; } - public double PumpedHeat { get; } - public double WasteHeat { get; } - public double EnergyUsage { get; } - public double ReactorDraw { get; } - public double ReactorLoadRatio { get; } - public double CapacitorCharge { get; } - public double CapacitorCapacity { get; } - public double CapacitorEfficiency { get; } - public double AetherDriveAxisX { get; } - public double AetherDriveAxisY { get; } - public double AetherDriveAxisZ { get; } - public double AetherDriveThrustX { get; } - public double AetherDriveThrustY { get; } - public double AetherDriveThrustZ { get; } - public double AetherDriveRpmX { get; } - public double AetherDriveRpmY { get; } - public double AetherDriveRpmZ { get; } - public double AetherDriveMaximumRpm { get; } - public double AetherDriveThrustDirectionX { get; } - public double AetherDriveThrustDirectionY { get; } - public string ResourceScannerTargetBodyKey { get; } - public int ResourceScannerAsteroidIndex { get; } - public double ResourceScannerScanTime { get; } - public double ResourceScannerRange { get; } - public double ResourceScannerMinimumDensity { get; } - public double ResourceScannerScanDuration { get; } - public string MiningToolAsteroidBeltKey { get; } - public int MiningToolAsteroidIndex { get; } - public double MiningToolRange { get; } - public double ThrusterAxis { get; } - public double ThrusterThrust { get; } - public double ThrusterTorque { get; } - public double ShieldEfficiency { get; } - public double ShieldEnergyUsage { get; } - public double VelocityLimit { get; } - public double ThermotoggleTargetTemperature { get; } - public bool SwitchActivated { get; } - public bool TriggerPulled { get; } - public bool StatModifierApplied { get; } - public bool StatModifierExecuted { get; } - public int StatModifierTargetStatCount { get; } - public int TurretControllerWeaponCount { get; } - public double TurretControllerShotSpeed { get; } - public bool TurretControllerPredictShots { get; } + public string OwnerKind { get; set; } + public int OwnerIndex { get; set; } + public int BehaviorIndex { get; set; } + public string BehaviorKind { get; set; } + public bool Pinging { get; set; } + public double PingCooldown { get; set; } + public double PingLerp { get; set; } + public double PingRadius { get; set; } + public int PingedEntityCount { get; set; } + public double RadiatorTemperature { get; set; } + public double Emissivity { get; set; } + public double PumpedHeat { get; set; } + public double WasteHeat { get; set; } + public double EnergyUsage { get; set; } + public double ReactorDraw { get; set; } + public double ReactorLoadRatio { get; set; } + public double CapacitorCharge { get; set; } + public double CapacitorCapacity { get; set; } + public double CapacitorEfficiency { get; set; } + public double AetherDriveAxisX { get; set; } + public double AetherDriveAxisY { get; set; } + public double AetherDriveAxisZ { get; set; } + public double AetherDriveThrustX { get; set; } + public double AetherDriveThrustY { get; set; } + public double AetherDriveThrustZ { get; set; } + public double AetherDriveRpmX { get; set; } + public double AetherDriveRpmY { get; set; } + public double AetherDriveRpmZ { get; set; } + public double AetherDriveMaximumRpm { get; set; } + public double AetherDriveThrustDirectionX { get; set; } + public double AetherDriveThrustDirectionY { get; set; } + public string ResourceScannerTargetBodyKey { get; set; } + public int ResourceScannerAsteroidIndex { get; set; } + public double ResourceScannerScanTime { get; set; } + public double ResourceScannerRange { get; set; } + public double ResourceScannerMinimumDensity { get; set; } + public double ResourceScannerScanDuration { get; set; } + public string MiningToolAsteroidBeltKey { get; set; } + public int MiningToolAsteroidIndex { get; set; } + public double MiningToolRange { get; set; } + public double ThrusterAxis { get; set; } + public double ThrusterThrust { get; set; } + public double ThrusterTorque { get; set; } + public double ShieldEfficiency { get; set; } + public double ShieldEnergyUsage { get; set; } + public double VelocityLimit { get; set; } + public double ThermotoggleTargetTemperature { get; set; } + public bool SwitchActivated { get; set; } + public bool TriggerPulled { get; set; } + public bool StatModifierApplied { get; set; } + public bool StatModifierExecuted { get; set; } + public int StatModifierTargetStatCount { get; set; } + public int TurretControllerWeaponCount { get; set; } + public double TurretControllerShotSpeed { get; set; } + public bool TurretControllerPredictShots { get; set; } } } diff --git a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeDaemonTradeItemQueries.cs b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeDaemonTradeItemQueries.cs index 566d11cf1..24b2ffb71 100644 --- a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeDaemonTradeItemQueries.cs +++ b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeDaemonTradeItemQueries.cs @@ -1,11 +1,13 @@ using System; using System.Collections.Generic; using System.Globalization; +using MessagePack; #nullable enable namespace GameCult.Aetheria.State.Verse { + [MessagePackObject(true)] public readonly struct AetheriaRuntimeExponentialLerp { public AetheriaRuntimeExponentialLerp(double exponent, double minimum, double maximum) @@ -26,6 +28,7 @@ namespace GameCult.Aetheria.State.Verse } } + [MessagePackObject(true)] public readonly struct AetheriaRuntimeItemRarityTier { public AetheriaRuntimeItemRarityTier(string name, double quality, double red, double green, double blue) @@ -44,6 +47,7 @@ namespace GameCult.Aetheria.State.Verse public double Blue { get; } } + [MessagePackObject(true)] public sealed class AetheriaRuntimeTradeValueSettings { public static AetheriaRuntimeTradeValueSettings Default { get; } = new AetheriaRuntimeTradeValueSettings( @@ -65,8 +69,9 @@ namespace GameCult.Aetheria.State.Verse Tiers = tiers ?? Array.Empty(); } - public AetheriaRuntimeExponentialLerp QualityPriceModifier { get; } - public IReadOnlyList Tiers { get; } + public AetheriaRuntimeExponentialLerp QualityPriceModifier { get; set; } + public IReadOnlyList Tiers { get; set; } = + Array.Empty(); } public readonly struct AetheriaRuntimeTradeItemValue diff --git a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeMainMenuSurfaceBuilder.cs b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeMainMenuSurfaceBuilder.cs index c798f2c80..d0bf0c34b 100644 --- a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeMainMenuSurfaceBuilder.cs +++ b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeMainMenuSurfaceBuilder.cs @@ -151,6 +151,15 @@ namespace GameCult.Aetheria.State.Verse string updatedAtUtc, long version) { + var verseLabel = VerseLabel(verseTitle, verseId); + var targetLine = TargetLine(targetLabel, targetKind, targetSource); + var daemonLine = hasAuthoritativeDaemonFrame + ? $"Run {daemonRunId} / frame {daemonFrameId}" + : "No daemon frame"; + var transportLine = string.IsNullOrWhiteSpace(verseCultMeshAddress) + ? verseVisibility + : $"{verseVisibility} / {verseCultMeshAddress}"; + var builder = MainMenuSurface( AetheriaRuntimeMainMenuCommands.RootSurfaceId, "Aetheria Terminus", @@ -171,11 +180,39 @@ namespace GameCult.Aetheria.State.Verse actions.Button("New Game", Operation(AetheriaRuntimeMainMenuCommands.NewGame, "New Game")); actions.Button("Settings", Operation(AetheriaRuntimeMainMenuCommands.ShowSettings, "Settings")); actions.Button("Quit", Operation(AetheriaRuntimeMainMenuCommands.Quit, "Quit")); - }); + }) + .Form( + $"{AetheriaRuntimeMainMenuCommands.RootSurfaceId}.verse", + form => form + .Metric("Verse", verseLabel) + .Metric("Target", targetLine) + .Metric("Daemon", daemonLine) + .Metric("Transport", transportLine)); return AetheriaRuntimeSurfaceDocuments.FromPortableSurface(builder.Build()); } + private static string VerseLabel(string verseTitle, string verseId) + { + if (string.IsNullOrWhiteSpace(verseTitle)) + return string.IsNullOrWhiteSpace(verseId) ? "Unknown Verse" : verseId; + + if (string.IsNullOrWhiteSpace(verseId) || string.Equals(verseTitle, verseId, StringComparison.Ordinal)) + return verseTitle; + + return $"{verseTitle} / {verseId}"; + } + + private static string TargetLine(string targetLabel, string targetKind, string targetSource) + { + var label = string.IsNullOrWhiteSpace(targetLabel) ? "Unknown target" : targetLabel; + var kind = string.IsNullOrWhiteSpace(targetKind) ? "unknown" : targetKind; + if (string.IsNullOrWhiteSpace(targetSource)) + return $"{label} ({kind})"; + + return $"{label} ({kind}) / {targetSource}"; + } + public static AetheriaRuntimeSurfaceDocument BuildSettings( string updatedAtUtc, long version = 1) diff --git a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimePlayerSettingsSurfaceBuilder.cs b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimePlayerSettingsSurfaceBuilder.cs index c52815919..f732facde 100644 --- a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimePlayerSettingsSurfaceBuilder.cs +++ b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimePlayerSettingsSurfaceBuilder.cs @@ -5,137 +5,6 @@ using GameCult.Mesh; namespace GameCult.Aetheria.State.Verse { - public static class AetheriaRuntimeSurfaceStateRefs - { - public const string Source = "stateRef"; - public const string Value = "valueRef"; - public const string Label = "labelRef"; - public const string Format = "stateFormat"; - - public static (string Key, string Value) SourceRef(string reference) - { - return (Source, reference ?? ""); - } - - public static (string Key, string Value) ValueRef(string reference) - { - return (Value, reference ?? ""); - } - - public static (string Key, string Value) LabelRef(string reference) - { - return (Label, reference ?? ""); - } - - public static (string Key, string Value) FormatRef(string format) - { - return (Format, format ?? ""); - } - } - - public static class AetheriaRuntimeSurfaceStateBindings - { - public const string PropPrefix = "cultmesh.statePointer."; - public const string PointerIdSuffix = ".pointerId"; - public const string SourceIdSuffix = ".sourceId"; - public const string SchemaIdSuffix = ".schemaId"; - public const string RouteKindSuffix = ".routeKind"; - public const string RouteDescriptionSuffix = ".routeDescription"; - - public static CultMeshStateBindingDescriptor ForDaemonStateRef( - string targetProp, - string stateRef, - string schemaId = AetheriaRuntimeDaemonSchemas.Frame) - { - return new CultMeshStateBindingDescriptor( - targetProp, - ToPointerId(stateRef), - stateRef, - schemaId, - new CultMeshRouteHint( - CultMeshLocalityKind.SharedMemory, - "daemon-published CultCache state")); - } - - public static IReadOnlyList FromProps( - IReadOnlyDictionary props) - { - if (props == null || props.Count == 0) - return Array.Empty(); - - var bindings = new List(); - AddPropBinding(bindings, "value", Get(props, AetheriaRuntimeSurfaceStateRefs.Source)); - foreach (var prop in props) - { - if (string.IsNullOrWhiteSpace(prop.Value) || - string.Equals(prop.Key, AetheriaRuntimeSurfaceStateRefs.Source, StringComparison.Ordinal) || - !prop.Key.EndsWith("Ref", StringComparison.Ordinal)) - { - continue; - } - - AddPropBinding(bindings, prop.Key.Substring(0, prop.Key.Length - "Ref".Length), prop.Value); - } - - return bindings; - } - - public static void AddPointerProps( - IDictionary props, - IReadOnlyList bindings) - { - if (props == null || bindings == null) - return; - - foreach (var binding in bindings) - { - if (binding == null || string.IsNullOrWhiteSpace(binding.PointerId)) - continue; - - var record = CultMesh.StateBindingRecord(binding); - var prefix = PropPrefix + record.TargetProp; - props[prefix + PointerIdSuffix] = record.PointerId; - props[prefix + SourceIdSuffix] = record.SourceId; - props[prefix + SchemaIdSuffix] = record.SchemaId; - props[prefix + RouteKindSuffix] = record.RouteKind; - props[prefix + RouteDescriptionSuffix] = record.RouteDescription; - } - } - - private static void AddPropBinding( - List bindings, - string targetProp, - string stateRef) - { - if (string.IsNullOrWhiteSpace(stateRef)) - return; - - var schemaId = stateRef.StartsWith(AetheriaRuntimeDaemonItemStatQueries.StateRefPrefix + "/", StringComparison.Ordinal) - ? AetheriaRuntimeDaemonSchemas.CurrentEntity - : AetheriaRuntimeDaemonSchemas.Frame; - bindings.Add(ForDaemonStateRef(targetProp, stateRef, schemaId)); - } - - private static string Get(IReadOnlyDictionary props, string key) - { - return props.TryGetValue(key, out var value) ? value : ""; - } - - private static string ToPointerId(string stateRef) - { - if (string.IsNullOrWhiteSpace(stateRef)) - return ""; - - var chars = stateRef - .Select(character => char.IsLetterOrDigit(character) ? char.ToLowerInvariant(character) : '.') - .ToArray(); - var pointerId = new string(chars).Trim('.'); - while (pointerId.Contains("..", StringComparison.Ordinal)) - pointerId = pointerId.Replace("..", ".", StringComparison.Ordinal); - return string.IsNullOrWhiteSpace(pointerId) ? "aetheria.state.unknown" : pointerId; - } - } - public static class AetheriaRuntimePlayerSettingsSurfaceBuilder { public static AetheriaRuntimeSurfaceDocument Build( diff --git a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeSurfaceDocuments.cs b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeSurfaceDocuments.cs index 8b9b5d473..e58fc7876 100644 --- a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeSurfaceDocuments.cs +++ b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeSurfaceDocuments.cs @@ -15,6 +15,137 @@ using EveUiSurfaceTree = GameCult.Eve.Surface.EveSurfaceTree; namespace GameCult.Aetheria.State.Verse { + public static class AetheriaRuntimeSurfaceStateRefs + { + public const string Source = "stateRef"; + public const string Value = "valueRef"; + public const string Label = "labelRef"; + public const string Format = "stateFormat"; + + public static (string Key, string Value) SourceRef(string reference) + { + return (Source, reference ?? ""); + } + + public static (string Key, string Value) ValueRef(string reference) + { + return (Value, reference ?? ""); + } + + public static (string Key, string Value) LabelRef(string reference) + { + return (Label, reference ?? ""); + } + + public static (string Key, string Value) FormatRef(string format) + { + return (Format, format ?? ""); + } + } + + public static class AetheriaRuntimeSurfaceStateBindings + { + public const string PropPrefix = "cultmesh.statePointer."; + public const string PointerIdSuffix = ".pointerId"; + public const string SourceIdSuffix = ".sourceId"; + public const string SchemaIdSuffix = ".schemaId"; + public const string RouteKindSuffix = ".routeKind"; + public const string RouteDescriptionSuffix = ".routeDescription"; + + public static CultMeshStateBindingDescriptor ForDaemonStateRef( + string targetProp, + string stateRef, + string schemaId = AetheriaRuntimeDaemonSchemas.Frame) + { + return new CultMeshStateBindingDescriptor( + targetProp, + ToPointerId(stateRef), + stateRef, + schemaId, + new CultMeshRouteHint( + CultMeshLocalityKind.SharedMemory, + "daemon-published CultCache state")); + } + + public static IReadOnlyList FromProps( + IReadOnlyDictionary props) + { + if (props == null || props.Count == 0) + return Array.Empty(); + + var bindings = new List(); + AddPropBinding(bindings, "value", Get(props, AetheriaRuntimeSurfaceStateRefs.Source)); + foreach (var prop in props) + { + if (string.IsNullOrWhiteSpace(prop.Value) || + string.Equals(prop.Key, AetheriaRuntimeSurfaceStateRefs.Source, StringComparison.Ordinal) || + !prop.Key.EndsWith("Ref", StringComparison.Ordinal)) + { + continue; + } + + AddPropBinding(bindings, prop.Key.Substring(0, prop.Key.Length - "Ref".Length), prop.Value); + } + + return bindings; + } + + public static void AddPointerProps( + IDictionary props, + IReadOnlyList bindings) + { + if (props == null || bindings == null) + return; + + foreach (var binding in bindings) + { + if (binding == null || string.IsNullOrWhiteSpace(binding.PointerId)) + continue; + + var record = CultMesh.StateBindingRecord(binding); + var prefix = PropPrefix + record.TargetProp; + props[prefix + PointerIdSuffix] = record.PointerId; + props[prefix + SourceIdSuffix] = record.SourceId; + props[prefix + SchemaIdSuffix] = record.SchemaId; + props[prefix + RouteKindSuffix] = record.RouteKind; + props[prefix + RouteDescriptionSuffix] = record.RouteDescription; + } + } + + private static void AddPropBinding( + List bindings, + string targetProp, + string stateRef) + { + if (string.IsNullOrWhiteSpace(stateRef)) + return; + + var schemaId = stateRef.StartsWith(AetheriaRuntimeDaemonItemStatQueries.StateRefPrefix + "/", StringComparison.Ordinal) + ? AetheriaRuntimeDaemonSchemas.CurrentEntity + : AetheriaRuntimeDaemonSchemas.Frame; + bindings.Add(ForDaemonStateRef(targetProp, stateRef, schemaId)); + } + + private static string Get(IReadOnlyDictionary props, string key) + { + return props.TryGetValue(key, out var value) ? value : ""; + } + + private static string ToPointerId(string stateRef) + { + if (string.IsNullOrWhiteSpace(stateRef)) + return ""; + + var chars = stateRef + .Select(character => char.IsLetterOrDigit(character) ? char.ToLowerInvariant(character) : '.') + .ToArray(); + var pointerId = new string(chars).Trim('.'); + while (pointerId.Contains("..", StringComparison.Ordinal)) + pointerId = pointerId.Replace("..", ".", StringComparison.Ordinal); + return string.IsNullOrWhiteSpace(pointerId) ? "aetheria.state.unknown" : pointerId; + } + } + [CultDocument("gamecult.aetheria.runtime_surface", "gamecult.aetheria.runtime_surface.v1")] [MessagePackObject] public sealed class AetheriaRuntimeSurfaceDocument