From bafcfa4ead33344c46f09f4ac596d5d1204afa63 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Sun, 21 Jun 2026 10:21:00 +0100 Subject: [PATCH] Type Eve command operations --- Aetheria.State.Smoke/Program.cs | 24 ++- Aetheria.State.Unity.Smoke/Program.cs | 4 +- Aetheria.State.Verify/Program.cs | 44 +++- Aetheria.State/AetheriaEveCommandBridge.cs | 78 +++---- Aetheria.State/AetheriaStateNode.cs | 2 + Assets/Scripts/Gameplay/ActionGameManager.cs | 6 +- Assets/Scripts/UI/MainMenu.cs | 6 +- .../Runtime/AetheriaRuntimeCommandPort.cs | 1 + .../AetheriaRuntimeEveCommandClient.cs | 199 +++++++++++++++--- .../AetheriaRuntimeEveCommandDocument.cs | 29 +++ 10 files changed, 300 insertions(+), 93 deletions(-) diff --git a/Aetheria.State.Smoke/Program.cs b/Aetheria.State.Smoke/Program.cs index 39cdce1c3..051a775bd 100644 --- a/Aetheria.State.Smoke/Program.cs +++ b/Aetheria.State.Smoke/Program.cs @@ -539,7 +539,7 @@ await using (var node = await AetheriaStateNode.OpenAsync(statePath, "aetheria-s AetheriaRuntimeEveCommandClient.ToDocument( AetheriaRuntimeEveCommands.SubmitCatalogCommand( statePath, - AetheriaRuntimeCatalogCommands.Refresh, + AetheriaRuntimeEveCommandKind.CatalogRefresh, "aetheria-state-smoke"))); await using (var commandVerifyNode = await AetheriaStateNode.OpenAsync( statePath, @@ -551,25 +551,31 @@ await using (var node = await AetheriaStateNode.OpenAsync(statePath, "aetheria-s await node.SubmitEveCommandAsync(AetheriaRuntimeEveCommandClient.ToDocument( AetheriaRuntimeEveCommands.SubmitCatalogCommand( statePath, - AetheriaRuntimeCatalogCommands.Refresh, + AetheriaRuntimeEveCommandKind.CatalogRefresh, "aetheria-state-smoke"))); await node.SubmitEveCommandAsync(AetheriaRuntimeEveCommandClient.ToDocument( AetheriaRuntimeEveCommands.SubmitPlayerSettingsCommand( statePath, - AetheriaRuntimePlayerSettingsCommands.IncrementSignificantDigits, + AetheriaRuntimeEveCommandKind.IncrementSignificantDigits, new AetheriaRuntimePlayerSettingsCommandBody(), "aetheria-state-smoke"))); await node.SubmitEveCommandAsync(AetheriaRuntimeEveCommandClient.ToDocument( AetheriaRuntimeEveCommands.SubmitPlayerSettingsCommand( statePath, - AetheriaRuntimePlayerSettingsCommands.ToggleShowAsteroidsInMinimap, + AetheriaRuntimeEveCommandKind.ToggleShowAsteroidsInMinimap, new AetheriaRuntimePlayerSettingsCommandBody(), "aetheria-state-smoke"))); - await node.SubmitEveCommandAsync(AetheriaRuntimeEveCommandClient.ToDocument( - AetheriaRuntimeEveCommands.SubmitCatalogCommand( - statePath, - "aetheria.catalog.unknown", - "aetheria-state-smoke"))); + await node.SubmitEveCommandAsync(new AetheriaRuntimeEveCommandDocument + { + Schema = AetheriaRuntimeEveCommandDocument.SchemaId, + CommandId = Guid.NewGuid().ToString("N"), + ProviderId = "aetheria", + SurfaceId = AetheriaRuntimeCatalogCommands.SurfaceId, + Command = "aetheria.catalog.unknown", + Kind = AetheriaRuntimeEveCommandKind.Unknown, + IssuedAtUtc = DateTime.UtcNow.ToString("O"), + ClientId = "aetheria-state-smoke" + }); var eveCommandReport = await AetheriaEveCommandBridge.AcceptObservedAsync(node); var eveCommandStatus = new AetheriaEveCommandAcceptanceStatus { diff --git a/Aetheria.State.Unity.Smoke/Program.cs b/Aetheria.State.Unity.Smoke/Program.cs index 4d0bc5a1d..6b70614ba 100644 --- a/Aetheria.State.Unity.Smoke/Program.cs +++ b/Aetheria.State.Unity.Smoke/Program.cs @@ -173,7 +173,7 @@ try { var eveCommand = AetheriaRuntimeEveCommands.SubmitCatalogCommand( commitSmokeStatePath, - AetheriaRuntimeCatalogCommands.Refresh, + AetheriaRuntimeEveCommandKind.CatalogRefresh, "aetheria-state-unity-smoke"); await using var eveCommandNode = await AetheriaStateNode.OpenAsync( commitSmokeStatePath, @@ -185,6 +185,7 @@ try ProviderId = eveCommand.ProviderId, SurfaceId = eveCommand.SurfaceId, Command = eveCommand.Command, + Kind = (GameCult.Aetheria.State.Verse.AetheriaRuntimeEveCommandKind)(int)eveCommand.Kind, IssuedAtUtc = eveCommand.IssuedAtUtc, ClientId = eveCommand.ClientId, PlayerSettings = new GameCult.Aetheria.State.Verse.AetheriaRuntimePlayerSettingsCommandBody @@ -206,6 +207,7 @@ try eveSubmitted[0].ProviderId != "aetheria" || eveSubmitted[0].SurfaceId != AetheriaRuntimeCatalogCommands.SurfaceId || eveSubmitted[0].Command != AetheriaRuntimeCatalogCommands.Refresh || + (int)eveSubmitted[0].Kind != (int)AetheriaRuntimeEveCommandKind.CatalogRefresh || eveSubmitted[0].PlayerSettings == null || eveSubmitted[0].InputSettings == null) { diff --git a/Aetheria.State.Verify/Program.cs b/Aetheria.State.Verify/Program.cs index 09ab51b29..13207a552 100644 --- a/Aetheria.State.Verify/Program.cs +++ b/Aetheria.State.Verify/Program.cs @@ -3153,8 +3153,8 @@ static void RequireRuntimeInputScreenUsesEveSurface(string root) var requiredActionGameManagerSymbols = new[] { "AetheriaRuntimeEveCommands.TrySendInputSettingsCommand", - "AetheriaRuntimeInputSettingsCommands.SetBindingOverride", - "AetheriaRuntimeInputSettingsCommands.SetActionBarEnabled" + "AetheriaRuntimeEveCommandKind.SetBindingOverride", + "AetheriaRuntimeEveCommandKind.SetActionBarEnabled" }; var missingActionGameManagerSymbols = requiredActionGameManagerSymbols @@ -5546,7 +5546,8 @@ static void RequireVerseSettingsShellAndBridge(string root) "AetheriaRuntimeMainMenuCommandKind.ClientTargetCommand", "AetheriaRuntimeMainMenuCommandKind.VerseHostCommand", "TryRequestClientTargetCommand(request)", - "TrySendVerseHostCommand(command.Command)", + "TrySendVerseHostCommand(AetheriaRuntimeEveCommandClient.CommandKindForSurface(request))", + "TrySendVerseHostCommand(AetheriaRuntimeEveCommandKind command)", "AetheriaRuntimeEveCommands.TrySendVerseHostCommand(", "AetheriaState.At(ActionGameManager.GameDataDirectory)", ".ClientTarget", @@ -5603,13 +5604,13 @@ static void RequireVerseSettingsShellAndBridge(string root) var requiredBridgeSymbols = new[] { "AcceptedVerseHostCommands", - "AetheriaRuntimeVerseHostCommands.Refresh", - "AetheriaRuntimeVerseHostCommands.CycleVisibility", + "AetheriaRuntimeEveCommandKind.VerseHostRefresh", + "AetheriaRuntimeEveCommandKind.CycleVerseHostVisibility", "ExecuteVerseHostCommandAsync", "PutVerseHostSettingsAsync", "PutProviderAdvertisementAsync", "AetheriaOperationsSurfaceProjector.Build(", - "AetheriaRuntimeVerseHostCommands.IsKnown(command)" + "switch (command.Kind)" }; var missingBridgeSymbols = requiredBridgeSymbols .Where(symbol => !commandBridge.Contains(symbol, StringComparison.Ordinal)) @@ -6598,6 +6599,7 @@ static void RequireTypedEveCommandBodies(string root) var eveCommandDocument = File.ReadAllText(eveCommandDocumentPath); var eveCommandClient = File.ReadAllText(eveCommandClientPath); + var normalizedEveCommandClient = eveCommandClient.Replace("\r\n", "\n", StringComparison.Ordinal); var runtimeCommandPort = File.ReadAllText(runtimeCommandPortPath); var eveCommandBridge = File.ReadAllText(eveCommandBridgePath); var stateNode = File.ReadAllText(stateNodePath); @@ -6607,8 +6609,10 @@ static void RequireTypedEveCommandBodies(string root) var requiredDocumentSymbols = new[] { + "public enum AetheriaRuntimeEveCommandKind", "public sealed class AetheriaRuntimePlayerSettingsCommandBody", "public sealed class AetheriaRuntimeInputSettingsCommandBody", + "public AetheriaRuntimeEveCommandKind Kind", "public AetheriaRuntimePlayerSettingsCommandBody PlayerSettings", "public AetheriaRuntimeInputSettingsCommandBody InputSettings", "public AetheriaRuntimeLoadoutTemplateCommit? LoadoutTemplate", @@ -6665,8 +6669,11 @@ static void RequireTypedEveCommandBodies(string root) "TrySendLoadoutTemplateCommand(", "TrySendKnownSurfaceCommand(", "TryCreateKnownSurfaceCommand(", + "CommandKindForSurface(", + "CommandText(", "ToDocument(", "AcceptObservedAsync(", + "switch (command.Kind)", "node.ReadObservedEveCommands()", "AccountedCommandIds", "SubmitEveCommandAsync(", @@ -6775,6 +6782,29 @@ static void RequireTypedEveCommandBodies(string root) string.Join(", ", genericSurfaceCommandHits)); } + var forbiddenStringCommandOverloads = new[] + { + "SubmitPlayerSettingsCommand(\n string stateFilePath,\n string command", + "SubmitInputSettingsCommand(\n string stateFilePath,\n string command", + "SubmitCatalogCommand(\n string stateFilePath,\n string command", + "SubmitOperationsCommand(\n string stateFilePath,\n string command", + "SubmitVerseHostCommand(\n string stateFilePath,\n string command", + "TrySendInputSettingsCommand(\n string stateFilePath,\n string command", + "TrySendVerseHostCommand(\n string stateFilePath,\n string command", + "CreateCatalogCommand(\n string command", + "CreateOperationsCommand(\n string command", + "CreateVerseHostCommand(\n string command" + }; + var survivingStringCommandOverloads = forbiddenStringCommandOverloads + .Where(symbol => normalizedEveCommandClient.Contains(symbol, StringComparison.Ordinal)) + .ToArray(); + if (survivingStringCommandOverloads.Length > 0) + { + throw new InvalidOperationException( + "Aetheria Eve command client still exposes public string command overloads instead of typed command kinds: " + + string.Join(", ", survivingStringCommandOverloads)); + } + var forbiddenQueueSymbols = new[] { "public static class AetheriaRuntimeEveCommandLog", @@ -8931,7 +8961,7 @@ static void RequireInventoryLoadoutSaveRequestAuthority(string root) var requiredBridgeSymbols = new[] { - "AetheriaRuntimeLoadoutTemplateCommands.Save", + "AetheriaRuntimeEveCommandKind.SaveLoadoutTemplate", "ExecuteLoadoutTemplateCommandAsync", "command.LoadoutTemplate", "AetheriaRuntimeStateMapper.ToLoadoutTemplate", diff --git a/Aetheria.State/AetheriaEveCommandBridge.cs b/Aetheria.State/AetheriaEveCommandBridge.cs index e9b3df028..b48a7c567 100644 --- a/Aetheria.State/AetheriaEveCommandBridge.cs +++ b/Aetheria.State/AetheriaEveCommandBridge.cs @@ -44,14 +44,14 @@ public static class AetheriaEveCommandBridge continue; } - switch (command.Command) + switch (command.Kind) { - case AetheriaRuntimeCatalogCommands.Refresh: + case AetheriaRuntimeEveCommandKind.CatalogRefresh: await node.PutCatalogSurfaceAsync( AetheriaCatalogSurfaceProjector.Build(node.ReadCatalogSnapshot(), command.IssuedAtUtc)).ConfigureAwait(false); report.AcceptedCatalogRefreshes++; break; - case AetheriaRuntimeOperationsCommands.Refresh: + case AetheriaRuntimeEveCommandKind.OperationsRefresh: var eveStatus = await node.GetEveCommandAcceptanceStatusAsync().ConfigureAwait(false) ?? EmptyEveCommandAcceptanceStatus(node.StatePath, command.IssuedAtUtc); var verseHostSettings = await node.GetVerseHostSettingsAsync().ConfigureAwait(false); @@ -63,28 +63,28 @@ public static class AetheriaEveCommandBridge runtimeSession)).ConfigureAwait(false); report.AcceptedOperationsRefreshes++; break; - case GameCult.Aetheria.State.Verse.AetheriaRuntimePlayerSettingsCommands.Refresh: - case GameCult.Aetheria.State.Verse.AetheriaRuntimePlayerSettingsCommands.SetPlayerName: - case GameCult.Aetheria.State.Verse.AetheriaRuntimePlayerSettingsCommands.CycleTemperatureUnit: - case GameCult.Aetheria.State.Verse.AetheriaRuntimePlayerSettingsCommands.DecrementSignificantDigits: - case GameCult.Aetheria.State.Verse.AetheriaRuntimePlayerSettingsCommands.IncrementSignificantDigits: - case GameCult.Aetheria.State.Verse.AetheriaRuntimePlayerSettingsCommands.CycleNebulaQuality: - case GameCult.Aetheria.State.Verse.AetheriaRuntimePlayerSettingsCommands.ToggleShowAsteroidsInMinimap: + case AetheriaRuntimeEveCommandKind.PlayerSettingsRefresh: + case AetheriaRuntimeEveCommandKind.SetPlayerName: + case AetheriaRuntimeEveCommandKind.CycleTemperatureUnit: + case AetheriaRuntimeEveCommandKind.DecrementSignificantDigits: + case AetheriaRuntimeEveCommandKind.IncrementSignificantDigits: + case AetheriaRuntimeEveCommandKind.CycleNebulaQuality: + case AetheriaRuntimeEveCommandKind.ToggleShowAsteroidsInMinimap: await ExecutePlayerSettingsCommandAsync(node, command).ConfigureAwait(false); report.AcceptedPlayerSettingsCommands++; break; - case GameCult.Aetheria.State.Verse.AetheriaRuntimeInputSettingsCommands.Refresh: - case GameCult.Aetheria.State.Verse.AetheriaRuntimeInputSettingsCommands.SetBindingOverride: - case GameCult.Aetheria.State.Verse.AetheriaRuntimeInputSettingsCommands.SetActionBarEnabled: + case AetheriaRuntimeEveCommandKind.InputSettingsRefresh: + case AetheriaRuntimeEveCommandKind.SetBindingOverride: + case AetheriaRuntimeEveCommandKind.SetActionBarEnabled: await ExecuteInputSettingsCommandAsync(node, command).ConfigureAwait(false); report.AcceptedInputSettingsCommands++; break; - case GameCult.Aetheria.State.Verse.AetheriaRuntimeLoadoutTemplateCommands.Save: + case AetheriaRuntimeEveCommandKind.SaveLoadoutTemplate: await ExecuteLoadoutTemplateCommandAsync(node, command).ConfigureAwait(false); report.AcceptedLoadoutTemplateCommands++; break; - case GameCult.Aetheria.State.Verse.AetheriaRuntimeVerseHostCommands.Refresh: - case GameCult.Aetheria.State.Verse.AetheriaRuntimeVerseHostCommands.CycleVisibility: + case AetheriaRuntimeEveCommandKind.VerseHostRefresh: + case AetheriaRuntimeEveCommandKind.CycleVerseHostVisibility: await ExecuteVerseHostCommandAsync(node, command).ConfigureAwait(false); report.AcceptedVerseHostCommands++; break; @@ -111,28 +111,14 @@ public static class AetheriaEveCommandBridge return $"Unexpected Eve command schema '{command.Schema}'."; if (!string.Equals(command.ProviderId, AetheriaProviderAdvertisementProjector.ProviderId, StringComparison.Ordinal)) return $"Unexpected Eve provider '{command.ProviderId}'."; - if (!KnownCommand(command.SurfaceId, command.Command)) - return $"Command '{command.Command}' is not advertised for surface '{command.SurfaceId}'."; + if (command.Kind == AetheriaRuntimeEveCommandKind.Unknown) + return $"Unknown typed Eve command kind for surface '{command.SurfaceId}' command '{command.Command}'."; + if (AetheriaRuntimeEveCommandClient.CommandKindForSurface(command.SurfaceId, command.Command) != command.Kind) + return $"Eve command '{command.Command}' does not match typed command kind '{command.Kind}'."; return ""; } - private static bool KnownCommand(string surfaceId, string command) - { - return (string.Equals(surfaceId, AetheriaRuntimeCatalogCommands.SurfaceId, StringComparison.Ordinal) && - AetheriaRuntimeCatalogCommands.IsKnown(command)) || - (string.Equals(surfaceId, AetheriaRuntimeOperationsCommands.SurfaceId, StringComparison.Ordinal) && - AetheriaRuntimeOperationsCommands.IsKnown(command)) || - (string.Equals(surfaceId, AetheriaPlayerSettingsSurfaceProjector.SurfaceId, StringComparison.Ordinal) && - GameCult.Aetheria.State.Verse.AetheriaRuntimePlayerSettingsCommands.IsKnown(command)) || - (string.Equals(surfaceId, GameCult.Aetheria.State.Verse.AetheriaRuntimeInputSettingsCommands.SurfaceId, StringComparison.Ordinal) && - GameCult.Aetheria.State.Verse.AetheriaRuntimeInputSettingsCommands.IsKnown(command)) || - (string.Equals(surfaceId, GameCult.Aetheria.State.Verse.AetheriaRuntimeLoadoutTemplateCommands.SurfaceId, StringComparison.Ordinal) && - GameCult.Aetheria.State.Verse.AetheriaRuntimeLoadoutTemplateCommands.IsKnown(command)) || - (string.Equals(surfaceId, GameCult.Aetheria.State.Verse.AetheriaRuntimeVerseHostCommands.SurfaceId, StringComparison.Ordinal) && - GameCult.Aetheria.State.Verse.AetheriaRuntimeVerseHostCommands.IsKnown(command)); - } - private static async Task ExecutePlayerSettingsCommandAsync( AetheriaStateNode node, AetheriaRuntimeEveCommandDocument command) @@ -142,13 +128,13 @@ public static class AetheriaEveCommandBridge settings.Graphics ??= new AetheriaPlayerGraphicsSettings(); var persistSettings = false; - switch (command.Command) + switch (command.Kind) { - case GameCult.Aetheria.State.Verse.AetheriaRuntimePlayerSettingsCommands.SetPlayerName: + case AetheriaRuntimeEveCommandKind.SetPlayerName: settings.PlayerName = command.PlayerSettings.PlayerName ?? ""; persistSettings = true; break; - case GameCult.Aetheria.State.Verse.AetheriaRuntimePlayerSettingsCommands.CycleTemperatureUnit: + case AetheriaRuntimeEveCommandKind.CycleTemperatureUnit: settings.Gameplay.TemperatureUnit = Cycle( settings.Gameplay.TemperatureUnit, "Kelvin", @@ -156,16 +142,16 @@ public static class AetheriaEveCommandBridge "Fahrenheit"); persistSettings = true; break; - case GameCult.Aetheria.State.Verse.AetheriaRuntimePlayerSettingsCommands.DecrementSignificantDigits: + case AetheriaRuntimeEveCommandKind.DecrementSignificantDigits: settings.Gameplay.SignificantDigits = Math.Max(0, settings.Gameplay.SignificantDigits - 1); persistSettings = true; break; - case GameCult.Aetheria.State.Verse.AetheriaRuntimePlayerSettingsCommands.IncrementSignificantDigits: + case AetheriaRuntimeEveCommandKind.IncrementSignificantDigits: if (settings.Gameplay.SignificantDigits < int.MaxValue) settings.Gameplay.SignificantDigits++; persistSettings = true; break; - case GameCult.Aetheria.State.Verse.AetheriaRuntimePlayerSettingsCommands.CycleNebulaQuality: + case AetheriaRuntimeEveCommandKind.CycleNebulaQuality: settings.Graphics.NebulaQuality = Cycle( settings.Graphics.NebulaQuality, "Low", @@ -174,7 +160,7 @@ public static class AetheriaEveCommandBridge "Ultra"); persistSettings = true; break; - case GameCult.Aetheria.State.Verse.AetheriaRuntimePlayerSettingsCommands.ToggleShowAsteroidsInMinimap: + case AetheriaRuntimeEveCommandKind.ToggleShowAsteroidsInMinimap: settings.Graphics.ShowAsteroidsInMinimap = !settings.Graphics.ShowAsteroidsInMinimap; persistSettings = true; break; @@ -199,9 +185,9 @@ public static class AetheriaEveCommandBridge settings.Input ??= new AetheriaPlayerInputSettings(); var persistSettings = false; - switch (command.Command) + switch (command.Kind) { - case GameCult.Aetheria.State.Verse.AetheriaRuntimeInputSettingsCommands.SetBindingOverride: + case AetheriaRuntimeEveCommandKind.SetBindingOverride: var actionName = command.InputSettings.ActionName ?? ""; var inputSystemPath = command.InputSettings.InputSystemPath ?? ""; var bindingIndex = command.InputSettings.BindingIndex; @@ -225,7 +211,7 @@ public static class AetheriaEveCommandBridge persistSettings = true; } break; - case GameCult.Aetheria.State.Verse.AetheriaRuntimeInputSettingsCommands.SetActionBarEnabled: + case AetheriaRuntimeEveCommandKind.SetActionBarEnabled: var inputPath = command.InputSettings.InputSystemPath ?? ""; var enabled = command.InputSettings.Enabled; if (!string.IsNullOrWhiteSpace(inputPath)) @@ -258,9 +244,9 @@ public static class AetheriaEveCommandBridge var normalized = AetheriaVerseHostSettingsNormalizer.Normalize(settings); var persistSettings = false; - switch (command.Command) + switch (command.Kind) { - case GameCult.Aetheria.State.Verse.AetheriaRuntimeVerseHostCommands.CycleVisibility: + case AetheriaRuntimeEveCommandKind.CycleVerseHostVisibility: normalized.Visibility = Cycle(normalized.Visibility, "private", "public"); persistSettings = true; break; diff --git a/Aetheria.State/AetheriaStateNode.cs b/Aetheria.State/AetheriaStateNode.cs index 4f7870627..6e8e30ccf 100644 --- a/Aetheria.State/AetheriaStateNode.cs +++ b/Aetheria.State/AetheriaStateNode.cs @@ -275,6 +275,7 @@ public sealed class AetheriaStateNode : IAsyncDisposable, IDisposable AetheriaRuntimeEveCommandDocument command) { if (command == null) throw new ArgumentNullException(nameof(command)); + AetheriaRuntimeEveCommandClient.NormalizeDocument(command); command.Schema = AetheriaRuntimeEveCommandDocument.SchemaId; if (string.IsNullOrWhiteSpace(command.CommandId)) command.CommandId = Guid.NewGuid().ToString("N"); @@ -288,6 +289,7 @@ public sealed class AetheriaStateNode : IAsyncDisposable, IDisposable { return Cache .GetAll() + .Select(AetheriaRuntimeEveCommandClient.NormalizeDocument) .OrderBy(command => command.IssuedAtUtc ?? "", StringComparer.Ordinal) .ThenBy(command => command.CommandId ?? "", StringComparer.Ordinal) .ToArray(); diff --git a/Assets/Scripts/Gameplay/ActionGameManager.cs b/Assets/Scripts/Gameplay/ActionGameManager.cs index 77c10dff9..d8c8d80ae 100644 --- a/Assets/Scripts/Gameplay/ActionGameManager.cs +++ b/Assets/Scripts/Gameplay/ActionGameManager.cs @@ -89,7 +89,7 @@ public class ActionGameManager : MonoBehaviour public static void RequestRuntimeInputBindingOverride(string actionName, int bindingIndex, string inputSystemPath) { TrySendRuntimeInputSettingsCommand( - AetheriaRuntimeInputSettingsCommands.SetBindingOverride, + AetheriaRuntimeEveCommandKind.SetBindingOverride, new AetheriaRuntimeInputSettingsCommandBody { ActionName = actionName ?? "", @@ -103,7 +103,7 @@ public class ActionGameManager : MonoBehaviour public static void RequestRuntimeActionBarInput(string inputSystemPath, bool enabled) { TrySendRuntimeInputSettingsCommand( - AetheriaRuntimeInputSettingsCommands.SetActionBarEnabled, + AetheriaRuntimeEveCommandKind.SetActionBarEnabled, new AetheriaRuntimeInputSettingsCommandBody { InputSystemPath = inputSystemPath ?? "", @@ -114,7 +114,7 @@ public class ActionGameManager : MonoBehaviour } private static bool TrySendRuntimeInputSettingsCommand( - string command, + AetheriaRuntimeEveCommandKind command, AetheriaRuntimeInputSettingsCommandBody body, string clientId, string label) diff --git a/Assets/Scripts/UI/MainMenu.cs b/Assets/Scripts/UI/MainMenu.cs index 3e58a0f3a..19fad2c40 100644 --- a/Assets/Scripts/UI/MainMenu.cs +++ b/Assets/Scripts/UI/MainMenu.cs @@ -341,7 +341,7 @@ public class MainMenu : MonoBehaviour return; case AetheriaRuntimeMainMenuCommandKind.VerseHostCommand: - if (TrySendVerseHostCommand(command.Command)) + if (TrySendVerseHostCommand(AetheriaRuntimeEveCommandClient.CommandKindForSurface(request))) { ShowVerseSettingsSurface(); } @@ -468,10 +468,10 @@ public class MainMenu : MonoBehaviour } } - private static bool TrySendVerseHostCommand(string command) + private static bool TrySendVerseHostCommand(AetheriaRuntimeEveCommandKind command) { var stateBoot = CurrentStateBoot(); - if (!CanSendLocalEveCommand(stateBoot, "Verse-host", command)) + if (!CanSendLocalEveCommand(stateBoot, "Verse-host", command.ToString())) return true; try diff --git a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeCommandPort.cs b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeCommandPort.cs index 84ac7cb28..09102a4e0 100644 --- a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeCommandPort.cs +++ b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeCommandPort.cs @@ -79,6 +79,7 @@ namespace Aetheria.State { if (command == null) throw new ArgumentNullException(nameof(command)); + AetheriaRuntimeEveCommandClient.NormalizeDocument(command); command.Schema = AetheriaRuntimeEveCommandDocument.SchemaId; if (string.IsNullOrWhiteSpace(command.CommandId)) command.CommandId = Guid.NewGuid().ToString("N"); diff --git a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeEveCommandClient.cs b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeEveCommandClient.cs index 7c61b2041..7e71d95ae 100644 --- a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeEveCommandClient.cs +++ b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeEveCommandClient.cs @@ -17,7 +17,7 @@ namespace GameCult.Aetheria.State.Verse public static AetheriaRuntimeEveCommandEnvelope SubmitPlayerSettingsCommand( string stateFilePath, - string command, + AetheriaRuntimeEveCommandKind command, AetheriaRuntimePlayerSettingsCommandBody body, string clientId) { @@ -57,7 +57,7 @@ namespace GameCult.Aetheria.State.Verse public static AetheriaRuntimeEveCommandEnvelope SubmitInputSettingsCommand( string stateFilePath, - string command, + AetheriaRuntimeEveCommandKind command, AetheriaRuntimeInputSettingsCommandBody body, string clientId) { @@ -66,7 +66,7 @@ namespace GameCult.Aetheria.State.Verse public static bool TrySendInputSettingsCommand( string stateFilePath, - string command, + AetheriaRuntimeEveCommandKind command, AetheriaRuntimeInputSettingsCommandBody body, string clientId, out AetheriaRuntimeEveCommandEnvelope? envelope, @@ -82,7 +82,7 @@ namespace GameCult.Aetheria.State.Verse public static AetheriaRuntimeEveCommandEnvelope SubmitCatalogCommand( string stateFilePath, - string command, + AetheriaRuntimeEveCommandKind command, string clientId) { return AetheriaRuntimeEveCommandClient.CreateCatalogCommand(command, clientId); @@ -90,7 +90,7 @@ namespace GameCult.Aetheria.State.Verse public static AetheriaRuntimeEveCommandEnvelope SubmitOperationsCommand( string stateFilePath, - string command, + AetheriaRuntimeEveCommandKind command, string clientId) { return AetheriaRuntimeEveCommandClient.CreateOperationsCommand(command, clientId); @@ -98,7 +98,7 @@ namespace GameCult.Aetheria.State.Verse public static AetheriaRuntimeEveCommandEnvelope SubmitVerseHostCommand( string stateFilePath, - string command, + AetheriaRuntimeEveCommandKind command, string clientId) { return AetheriaRuntimeEveCommandClient.CreateVerseHostCommand(command, clientId); @@ -106,7 +106,7 @@ namespace GameCult.Aetheria.State.Verse public static bool TrySendVerseHostCommand( string stateFilePath, - string command, + AetheriaRuntimeEveCommandKind command, string clientId, out AetheriaRuntimeEveCommandEnvelope? envelope, out string error) @@ -196,23 +196,23 @@ namespace GameCult.Aetheria.State.Verse { case AetheriaRuntimePlayerSettingsCommands.SurfaceId when AetheriaRuntimePlayerSettingsCommands.IsKnown(command): - envelope = CreatePlayerSettingsCommand(request, clientId); + envelope = CreatePlayerSettingsCommand(CommandKindForSurface(request), request, clientId); return true; case AetheriaRuntimeInputSettingsCommands.SurfaceId when AetheriaRuntimeInputSettingsCommands.IsKnown(command): - envelope = CreateInputSettingsCommand(request, clientId); + envelope = CreateInputSettingsCommand(CommandKindForSurface(request), request, clientId); return true; case AetheriaRuntimeCatalogCommands.SurfaceId when AetheriaRuntimeCatalogCommands.IsKnown(command): - envelope = CreateCatalogCommand(command, clientId); + envelope = CreateCatalogCommand(CommandKindForSurface(request), clientId); return true; case AetheriaRuntimeOperationsCommands.SurfaceId when AetheriaRuntimeOperationsCommands.IsKnown(command): - envelope = CreateOperationsCommand(command, clientId); + envelope = CreateOperationsCommand(CommandKindForSurface(request), clientId); return true; case AetheriaRuntimeVerseHostCommands.SurfaceId when AetheriaRuntimeVerseHostCommands.IsKnown(command): - envelope = CreateVerseHostCommand(command, clientId); + envelope = CreateVerseHostCommand(CommandKindForSurface(request), clientId); return true; } @@ -221,7 +221,7 @@ namespace GameCult.Aetheria.State.Verse } public static AetheriaRuntimeEveCommandEnvelope CreatePlayerSettingsCommand( - string command, + AetheriaRuntimeEveCommandKind command, AetheriaRuntimePlayerSettingsCommandBody body, string clientId) { @@ -245,14 +245,22 @@ namespace GameCult.Aetheria.State.Verse string clientId) { if (request == null) throw new ArgumentNullException(nameof(request)); + return CreatePlayerSettingsCommand(CommandKindForSurface(request), request, clientId); + } + + private static AetheriaRuntimeEveCommandEnvelope CreatePlayerSettingsCommand( + AetheriaRuntimeEveCommandKind command, + EveSurfaceCommandRequest request, + string clientId) + { return CreatePlayerSettingsCommand( - request.Command ?? "", + command, ReadPlayerSettingsBody(request), string.IsNullOrWhiteSpace(clientId) ? request.ClientId ?? "" : clientId); } public static AetheriaRuntimeEveCommandEnvelope CreateInputSettingsCommand( - string command, + AetheriaRuntimeEveCommandKind command, AetheriaRuntimeInputSettingsCommandBody body, string clientId) { @@ -270,14 +278,22 @@ namespace GameCult.Aetheria.State.Verse string clientId) { if (request == null) throw new ArgumentNullException(nameof(request)); + return CreateInputSettingsCommand(CommandKindForSurface(request), request, clientId); + } + + private static AetheriaRuntimeEveCommandEnvelope CreateInputSettingsCommand( + AetheriaRuntimeEveCommandKind command, + EveSurfaceCommandRequest request, + string clientId) + { return CreateInputSettingsCommand( - request.Command ?? "", + command, ReadInputSettingsBody(request), string.IsNullOrWhiteSpace(clientId) ? request.ClientId ?? "" : clientId); } public static AetheriaRuntimeEveCommandEnvelope CreateCatalogCommand( - string command, + AetheriaRuntimeEveCommandKind command, string clientId) { return CreateTypedCommand( @@ -290,7 +306,7 @@ namespace GameCult.Aetheria.State.Verse } public static AetheriaRuntimeEveCommandEnvelope CreateOperationsCommand( - string command, + AetheriaRuntimeEveCommandKind command, string clientId) { return CreateTypedCommand( @@ -303,7 +319,7 @@ namespace GameCult.Aetheria.State.Verse } public static AetheriaRuntimeEveCommandEnvelope CreateVerseHostCommand( - string command, + AetheriaRuntimeEveCommandKind command, string clientId) { return CreateTypedCommand( @@ -321,7 +337,7 @@ namespace GameCult.Aetheria.State.Verse { return CreateTypedCommand( AetheriaRuntimeLoadoutTemplateCommands.SurfaceId, - AetheriaRuntimeLoadoutTemplateCommands.Save, + AetheriaRuntimeEveCommandKind.SaveLoadoutTemplate, clientId, playerSettings: new AetheriaRuntimePlayerSettingsCommandBody(), inputSettings: new AetheriaRuntimeInputSettingsCommandBody(), @@ -332,29 +348,31 @@ namespace GameCult.Aetheria.State.Verse { if (envelope == null) throw new ArgumentNullException(nameof(envelope)); - return new AetheriaRuntimeEveCommandDocument + return NormalizeDocument(new AetheriaRuntimeEveCommandDocument { Schema = string.IsNullOrWhiteSpace(envelope.Schema) ? CommandSchema : envelope.Schema, CommandId = envelope.CommandId ?? "", ProviderId = envelope.ProviderId ?? "", SurfaceId = envelope.SurfaceId ?? "", Command = envelope.Command ?? "", + Kind = envelope.Kind, IssuedAtUtc = envelope.IssuedAtUtc ?? "", ClientId = envelope.ClientId ?? "", PlayerSettings = envelope.PlayerSettings ?? new AetheriaRuntimePlayerSettingsCommandBody(), InputSettings = envelope.InputSettings ?? new AetheriaRuntimeInputSettingsCommandBody(), LoadoutTemplate = envelope.LoadoutTemplate - }; + }); } private static AetheriaRuntimeEveCommandEnvelope CreateTypedCommand( string surfaceId, - string command, + AetheriaRuntimeEveCommandKind kind, string clientId, AetheriaRuntimePlayerSettingsCommandBody playerSettings, AetheriaRuntimeInputSettingsCommandBody inputSettings, AetheriaRuntimeLoadoutTemplateCommit? loadoutTemplate) { + var command = CommandText(kind); var commandId = Guid.NewGuid().ToString("N"); var issuedAtUtc = DateTime.UtcNow.ToString("O"); var document = new AetheriaRuntimeEveCommandDocument @@ -363,7 +381,8 @@ namespace GameCult.Aetheria.State.Verse CommandId = commandId, ProviderId = "aetheria", SurfaceId = surfaceId ?? "", - Command = command ?? "", + Command = command, + Kind = kind, IssuedAtUtc = issuedAtUtc, ClientId = clientId ?? "", PlayerSettings = playerSettings, @@ -376,12 +395,14 @@ namespace GameCult.Aetheria.State.Verse public static AetheriaRuntimeEveCommandEnvelope ToEnvelope(AetheriaRuntimeEveCommandDocument document) { + NormalizeDocument(document); return new AetheriaRuntimeEveCommandEnvelope( document.Schema ?? "", document.CommandId ?? "", document.ProviderId ?? "", document.SurfaceId ?? "", document.Command ?? "", + document.Kind, document.IssuedAtUtc ?? "", document.ClientId ?? "", document.PlayerSettings ?? new AetheriaRuntimePlayerSettingsCommandBody(), @@ -390,6 +411,136 @@ namespace GameCult.Aetheria.State.Verse document.LoadoutTemplate); } + public static AetheriaRuntimeEveCommandDocument NormalizeDocument(AetheriaRuntimeEveCommandDocument document) + { + if (document == null) throw new ArgumentNullException(nameof(document)); + + document.Schema = string.IsNullOrWhiteSpace(document.Schema) ? CommandSchema : document.Schema; + if (document.Kind == AetheriaRuntimeEveCommandKind.Unknown) + document.Kind = CommandKindForSurface(document.SurfaceId ?? "", document.Command ?? ""); + if (string.IsNullOrWhiteSpace(document.Command) && document.Kind != AetheriaRuntimeEveCommandKind.Unknown) + document.Command = CommandText(document.Kind); + return document; + } + + public static AetheriaRuntimeEveCommandKind CommandKindForSurface(EveSurfaceCommandRequest request) + { + if (request == null) throw new ArgumentNullException(nameof(request)); + return CommandKindForSurface(request.SurfaceId ?? "", request.Command ?? ""); + } + + public static AetheriaRuntimeEveCommandKind CommandKindForSurface(string surfaceId, string command) + { + switch (surfaceId ?? "") + { + case AetheriaRuntimeCatalogCommands.SurfaceId: + return command == AetheriaRuntimeCatalogCommands.Refresh + ? AetheriaRuntimeEveCommandKind.CatalogRefresh + : AetheriaRuntimeEveCommandKind.Unknown; + case AetheriaRuntimeOperationsCommands.SurfaceId: + return command == AetheriaRuntimeOperationsCommands.Refresh + ? AetheriaRuntimeEveCommandKind.OperationsRefresh + : AetheriaRuntimeEveCommandKind.Unknown; + case AetheriaRuntimePlayerSettingsCommands.SurfaceId: + return PlayerSettingsKind(command); + case AetheriaRuntimeInputSettingsCommands.SurfaceId: + return InputSettingsKind(command); + case AetheriaRuntimeLoadoutTemplateCommands.SurfaceId: + return command == AetheriaRuntimeLoadoutTemplateCommands.Save + ? AetheriaRuntimeEveCommandKind.SaveLoadoutTemplate + : AetheriaRuntimeEveCommandKind.Unknown; + case AetheriaRuntimeVerseHostCommands.SurfaceId: + return command == AetheriaRuntimeVerseHostCommands.Refresh + ? AetheriaRuntimeEveCommandKind.VerseHostRefresh + : command == AetheriaRuntimeVerseHostCommands.CycleVisibility + ? AetheriaRuntimeEveCommandKind.CycleVerseHostVisibility + : AetheriaRuntimeEveCommandKind.Unknown; + default: + return AetheriaRuntimeEveCommandKind.Unknown; + } + } + + public static string CommandText(AetheriaRuntimeEveCommandKind kind) + { + switch (kind) + { + case AetheriaRuntimeEveCommandKind.CatalogRefresh: + return AetheriaRuntimeCatalogCommands.Refresh; + case AetheriaRuntimeEveCommandKind.OperationsRefresh: + return AetheriaRuntimeOperationsCommands.Refresh; + case AetheriaRuntimeEveCommandKind.PlayerSettingsRefresh: + return AetheriaRuntimePlayerSettingsCommands.Refresh; + case AetheriaRuntimeEveCommandKind.SetPlayerName: + return AetheriaRuntimePlayerSettingsCommands.SetPlayerName; + case AetheriaRuntimeEveCommandKind.CycleTemperatureUnit: + return AetheriaRuntimePlayerSettingsCommands.CycleTemperatureUnit; + case AetheriaRuntimeEveCommandKind.DecrementSignificantDigits: + return AetheriaRuntimePlayerSettingsCommands.DecrementSignificantDigits; + case AetheriaRuntimeEveCommandKind.IncrementSignificantDigits: + return AetheriaRuntimePlayerSettingsCommands.IncrementSignificantDigits; + case AetheriaRuntimeEveCommandKind.CycleNebulaQuality: + return AetheriaRuntimePlayerSettingsCommands.CycleNebulaQuality; + case AetheriaRuntimeEveCommandKind.ToggleShowAsteroidsInMinimap: + return AetheriaRuntimePlayerSettingsCommands.ToggleShowAsteroidsInMinimap; + case AetheriaRuntimeEveCommandKind.InputSettingsRefresh: + return AetheriaRuntimeInputSettingsCommands.Refresh; + case AetheriaRuntimeEveCommandKind.BeginInputCapture: + return AetheriaRuntimeInputSettingsCommands.BeginCapture; + case AetheriaRuntimeEveCommandKind.CancelInputCapture: + return AetheriaRuntimeInputSettingsCommands.CancelCapture; + case AetheriaRuntimeEveCommandKind.SetBindingOverride: + return AetheriaRuntimeInputSettingsCommands.SetBindingOverride; + case AetheriaRuntimeEveCommandKind.ToggleActionBar: + return AetheriaRuntimeInputSettingsCommands.ToggleActionBar; + case AetheriaRuntimeEveCommandKind.SetActionBarEnabled: + return AetheriaRuntimeInputSettingsCommands.SetActionBarEnabled; + case AetheriaRuntimeEveCommandKind.SaveLoadoutTemplate: + return AetheriaRuntimeLoadoutTemplateCommands.Save; + case AetheriaRuntimeEveCommandKind.VerseHostRefresh: + return AetheriaRuntimeVerseHostCommands.Refresh; + case AetheriaRuntimeEveCommandKind.CycleVerseHostVisibility: + return AetheriaRuntimeVerseHostCommands.CycleVisibility; + default: + return ""; + } + } + + private static AetheriaRuntimeEveCommandKind PlayerSettingsKind(string command) + { + if (command == AetheriaRuntimePlayerSettingsCommands.Refresh) + return AetheriaRuntimeEveCommandKind.PlayerSettingsRefresh; + if (command == AetheriaRuntimePlayerSettingsCommands.SetPlayerName) + return AetheriaRuntimeEveCommandKind.SetPlayerName; + if (command == AetheriaRuntimePlayerSettingsCommands.CycleTemperatureUnit) + return AetheriaRuntimeEveCommandKind.CycleTemperatureUnit; + if (command == AetheriaRuntimePlayerSettingsCommands.DecrementSignificantDigits) + return AetheriaRuntimeEveCommandKind.DecrementSignificantDigits; + if (command == AetheriaRuntimePlayerSettingsCommands.IncrementSignificantDigits) + return AetheriaRuntimeEveCommandKind.IncrementSignificantDigits; + if (command == AetheriaRuntimePlayerSettingsCommands.CycleNebulaQuality) + return AetheriaRuntimeEveCommandKind.CycleNebulaQuality; + if (command == AetheriaRuntimePlayerSettingsCommands.ToggleShowAsteroidsInMinimap) + return AetheriaRuntimeEveCommandKind.ToggleShowAsteroidsInMinimap; + return AetheriaRuntimeEveCommandKind.Unknown; + } + + private static AetheriaRuntimeEveCommandKind InputSettingsKind(string command) + { + if (command == AetheriaRuntimeInputSettingsCommands.Refresh) + return AetheriaRuntimeEveCommandKind.InputSettingsRefresh; + if (command == AetheriaRuntimeInputSettingsCommands.BeginCapture) + return AetheriaRuntimeEveCommandKind.BeginInputCapture; + if (command == AetheriaRuntimeInputSettingsCommands.CancelCapture) + return AetheriaRuntimeEveCommandKind.CancelInputCapture; + if (command == AetheriaRuntimeInputSettingsCommands.SetBindingOverride) + return AetheriaRuntimeEveCommandKind.SetBindingOverride; + if (command == AetheriaRuntimeInputSettingsCommands.ToggleActionBar) + return AetheriaRuntimeEveCommandKind.ToggleActionBar; + if (command == AetheriaRuntimeInputSettingsCommands.SetActionBarEnabled) + return AetheriaRuntimeEveCommandKind.SetActionBarEnabled; + return AetheriaRuntimeEveCommandKind.Unknown; + } + private static AetheriaRuntimePlayerSettingsCommandBody ReadPlayerSettingsBody(EveSurfaceCommandRequest request) { if (!string.Equals(request.SurfaceId, AetheriaRuntimePlayerSettingsCommands.SurfaceId, StringComparison.Ordinal)) diff --git a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeEveCommandDocument.cs b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeEveCommandDocument.cs index 35d4c40b5..c9f2036d0 100644 --- a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeEveCommandDocument.cs +++ b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeEveCommandDocument.cs @@ -6,6 +6,29 @@ using MessagePack; namespace GameCult.Aetheria.State.Verse { + public enum AetheriaRuntimeEveCommandKind + { + Unknown = 0, + CatalogRefresh = 1, + OperationsRefresh = 2, + PlayerSettingsRefresh = 3, + SetPlayerName = 4, + CycleTemperatureUnit = 5, + DecrementSignificantDigits = 6, + IncrementSignificantDigits = 7, + CycleNebulaQuality = 8, + ToggleShowAsteroidsInMinimap = 9, + InputSettingsRefresh = 10, + BeginInputCapture = 11, + CancelInputCapture = 12, + SetBindingOverride = 13, + ToggleActionBar = 14, + SetActionBarEnabled = 15, + SaveLoadoutTemplate = 16, + VerseHostRefresh = 17, + CycleVerseHostVisibility = 18 + } + public sealed class AetheriaRuntimeEveCommandEnvelope { public AetheriaRuntimeEveCommandEnvelope( @@ -14,6 +37,7 @@ namespace GameCult.Aetheria.State.Verse string providerId, string surfaceId, string command, + AetheriaRuntimeEveCommandKind kind, string issuedAtUtc, string clientId, AetheriaRuntimePlayerSettingsCommandBody playerSettings, @@ -26,6 +50,7 @@ namespace GameCult.Aetheria.State.Verse ProviderId = providerId; SurfaceId = surfaceId; Command = command; + Kind = kind; IssuedAtUtc = issuedAtUtc; ClientId = clientId; PlayerSettings = playerSettings ?? new AetheriaRuntimePlayerSettingsCommandBody(); @@ -39,6 +64,7 @@ namespace GameCult.Aetheria.State.Verse public string ProviderId { get; } public string SurfaceId { get; } public string Command { get; } + public AetheriaRuntimeEveCommandKind Kind { get; } public string IssuedAtUtc { get; } public string ClientId { get; } public AetheriaRuntimePlayerSettingsCommandBody PlayerSettings { get; } @@ -82,6 +108,9 @@ namespace GameCult.Aetheria.State.Verse [Key(9)] public AetheriaRuntimeInputSettingsCommandBody InputSettings { get; set; } = new AetheriaRuntimeInputSettingsCommandBody(); + + [IgnoreMember] + public AetheriaRuntimeEveCommandKind Kind { get; set; } } [MessagePackObject]