using System; using System.Collections.Generic; using System.Linq; using GameCult.Caching; using GameCult.Mesh; using MessagePack; #nullable enable namespace GameCult.Aetheria.State.Verse { public sealed class AetheriaRuntimeDaemonCommandEnvelope { public AetheriaRuntimeDaemonCommandEnvelope( string schema, string commandId, string clientId, string issuedAtUtc, string sessionId, long observedFrameId, AetheriaRuntimeDaemonCommandKinds kind, string actorEntityKey, string path, CultMeshOperationReceipt? receipt = null) { Schema = schema; CommandId = commandId; ClientId = clientId; IssuedAtUtc = issuedAtUtc; SessionId = sessionId; ObservedFrameId = observedFrameId; Kind = kind; ActorEntityKey = actorEntityKey; Path = path; Receipt = receipt ?? AetheriaRuntimeDaemonOperationIds.CreateReceipt(kind); } public string Schema { get; } public string CommandId { get; } public string ClientId { get; } public string IssuedAtUtc { get; } public string SessionId { get; } public long ObservedFrameId { get; } public AetheriaRuntimeDaemonCommandKinds Kind { get; } public string ActorEntityKey { get; } public string Path { get; } public CultMeshOperationReceipt Receipt { get; } public string OperationId => Receipt.OperationId; public bool Accepted => Receipt.Accepted; public CultMeshRouteHint Route => Receipt.Route; public string? Diagnostic => Receipt.Diagnostic; public static implicit operator CultMeshOperationReceipt(AetheriaRuntimeDaemonCommandEnvelope envelope) { if (envelope == null) throw new ArgumentNullException(nameof(envelope)); return envelope.Receipt; } } public static class AetheriaRuntimeDaemonSchemas { public const string Frame = "gamecult.aetheria.daemon_frame.v1"; public const string Command = "gamecult.aetheria.daemon_command.v1"; public const string CommittedCommandFact = "gamecult.aetheria.committed_command_fact.v1"; public const string GameViewport = "gamecult.aetheria.game_viewport.v1"; public const string ObjectsViewport = "gamecult.aetheria.objects_viewport.v1"; public const string GravityViewport = "gamecult.aetheria.gravity_viewport.v1"; public const string RenderSplatsViewport = "gamecult.aetheria.render_splats_viewport.v1"; public const string AssetManifest = "gamecult.aetheria.asset_manifest.v1"; public const string CultMeshCdnAssetBlob = "gamecult.cultmesh.cdn.asset_blob.v1"; public const string CurrentZone = "gamecult.aetheria.current_zone.v1"; public const string CurrentEntity = "gamecult.aetheria.current_entity.v1"; public const string CurrentDocking = "gamecult.aetheria.current_docking.v1"; public const string ZoneContacts = "gamecult.aetheria.zone_contacts.v1"; public const string StationRefit = "gamecult.aetheria.station_refit.v1"; public const string SectorMap = "gamecult.aetheria.sector_map.v1"; public const string ZoneDetails = "gamecult.aetheria.zone_details.v1"; public const string ZoneRender = "gamecult.aetheria.zone_render.v1"; public const string SelectedObject = "gamecult.aetheria.selected_object.v1"; public const string Inventory = "gamecult.aetheria.inventory.v1"; public const string StarbridgeScenario = "gamecult.aetheria.starbridge_scenario.v1"; public const string StarbridgeSession = "gamecult.aetheria.starbridge_session.v1"; public const string StarbridgeSessionSummary = "gamecult.aetheria.starbridge_session_summary.v1"; public const string StarbridgePlayerSeat = "gamecult.aetheria.starbridge_player_seat.v1"; public const string VerseAuthorityPolicy = AetheriaRuntimeVerseAuthoritySchemas.Policy; public const string AuthorityLease = AetheriaRuntimeVerseAuthoritySchemas.Lease; public const string SoaView = "gamecult.aetheria.daemon_soa_view.v1"; public const string ProviderAdvertisement = "gamecult.aetheria.daemon_provider_advertisement.v1"; public const string Health = "gamecult.aetheria.daemon_health.v1"; public const string CommandBoundary = "gamecult.aetheria.daemon_command_boundary.v1"; public const string EveCommandAcceptanceStatus = "aetheria.eve_command_acceptance_status.v1"; public const string GameSurface = "gamecult.aetheria.daemon_game_surface.v1"; public const string EditorSurface = "gamecult.aetheria.daemon_editor_surface.v1"; } public static class AetheriaRuntimeDaemonOperationIds { public static string SetMoveVector => ForKind(AetheriaRuntimeDaemonCommandKinds.SetMoveVector); public static string SetTarget => ForKind(AetheriaRuntimeDaemonCommandKinds.SetTarget); public static string ForKind(AetheriaRuntimeDaemonCommandKinds kind) { switch (kind) { case AetheriaRuntimeDaemonCommandKinds.SetMoveVector: return "gamecult.aetheria.pilot.set_move_vector.v1"; case AetheriaRuntimeDaemonCommandKinds.SetTarget: return "gamecult.aetheria.pilot.set_target.v1"; case AetheriaRuntimeDaemonCommandKinds.None: return "gamecult.aetheria.daemon.none.v1"; default: return "gamecult.aetheria.daemon." + ToSnakeCase(kind.ToString()) + ".v1"; } } public static CultMeshOperationReceipt CreateReceipt( AetheriaRuntimeDaemonCommandKinds kind, bool accepted = true, CultMeshRouteHint? route = null, string? diagnostic = null) { return new CultMeshOperationReceipt( ForKind(kind), accepted, route ?? new CultMeshRouteHint(CultMeshLocalityKind.Network, "aetheria-daemon-command"), diagnostic); } private static string ToSnakeCase(string value) { if (string.IsNullOrWhiteSpace(value)) return "unknown"; var chars = new List(value.Length + 8); for (var i = 0; i < value.Length; i++) { var c = value[i]; if (char.IsUpper(c)) { if (i > 0) chars.Add('_'); chars.Add(char.ToLowerInvariant(c)); } else { chars.Add(c); } } return new string(chars.ToArray()); } } public enum AetheriaRuntimeDaemonCommandKinds { None = 0, Ping, SetTarget, ClearTarget, TargetNearest, TargetNext, TargetPrevious, TargetReticle, SetMoveVector, SetLookDirection, SetTractorPower, FireWeaponGroup, SetWeaponGroupActive, SetWeaponGroupMembership, SetBehaviorActive, ActivateConsumable, SensorPing, SetItemEnabled, SetItemOverrideShutdown, SetThermotoggleTargetTemperature, PickUpLoot, RestoreLoadout, Dock, DockNearest, Undock, Interact, SetDockedCurrentShip, TowToStation, EnterWormhole, TradePurchase, TransferCargoItem, EquipItem, StoreItem, ToggleHullConductivity, SetEntityName, DestroyEntity, SetOverrideShutdown, SetHeatsinksEnabled, SetShutdownPerformance, ToggleShieldEnabled } [CultDocument("gamecult.aetheria.daemon_provider_advertisement", "gamecult.aetheria.daemon_provider_advertisement.v1")] [MessagePackObject] public sealed class AetheriaRuntimeDaemonProviderAdvertisementDocument { [Key(0)] public string Schema { get; set; } = AetheriaRuntimeDaemonSchemas.ProviderAdvertisement; [Key(1)] public string VerseId { get; set; } = "aetheria.local"; [Key(2)] public string ProviderId { get; set; } = "aetheria.daemon"; [Key(3)] public string DaemonId { get; set; } = "aetheria-daemon"; [Key(4)] public string PublishedAtUtc { get; set; } = ""; [Key(5)] public string StateRecordRef { get; set; } = ""; [Key(6)] public string FrameRecordRef { get; set; } = ""; [Key(7)] public string SoaViewRecordRef { get; set; } = ""; [Key(8)] public string HealthRecordRef { get; set; } = ""; [Key(9)] public string CommandBoundaryRecordRef { get; set; } = ""; [Key(10)] public string EveGuiSurfaceRecordRef { get; set; } = ""; [Key(11)] public string EveTuiSurfaceRecordRef { get; set; } = ""; [Key(12)] public string EveGuiSurfaceId { get; set; } = "aetheria.game"; [Key(13)] public string EveTuiSurfaceId { get; set; } = "aetheria.game.tui"; [Key(14)] public string EditorGuiSurfaceRecordRef { get; set; } = ""; [Key(15)] public string EditorTuiSurfaceRecordRef { get; set; } = ""; [Key(16)] public string EditorGuiSurfaceId { get; set; } = "aetheria.daemon.editor"; [Key(17)] public string EditorTuiSurfaceId { get; set; } = "aetheria.daemon.editor.tui"; [Key(18)] public IReadOnlyList PublishedSchemas { get; set; } = Array.Empty(); [Key(19)] public IReadOnlyList CommandBoundaryIds { get; set; } = Array.Empty(); [Key(20)] public string CultMeshAddress { get; set; } = "cultmesh://aetheria.local/eve/providers/aetheria.daemon"; [Key(21)] public string AssetManifestRecordRef { get; set; } = ""; [Key(22)] public IReadOnlyList EveSurfaces { get; set; } = Array.Empty(); public static AetheriaRuntimeDaemonProviderAdvertisementDocument Create( string stateFilePath, string daemonId, string verseId, string cultMeshAddress) { return new AetheriaRuntimeDaemonProviderAdvertisementDocument { VerseId = string.IsNullOrWhiteSpace(verseId) ? "aetheria.local" : verseId, DaemonId = string.IsNullOrWhiteSpace(daemonId) ? "aetheria-daemon" : daemonId, PublishedAtUtc = DateTime.UtcNow.ToString("O"), StateRecordRef = stateFilePath ?? "", FrameRecordRef = AetheriaRuntimeVerseRecordKeys.DaemonFrameLatest.ToString(), SoaViewRecordRef = AetheriaRuntimeVerseRecordKeys.DaemonSoaViewLatest.ToString(), HealthRecordRef = AetheriaRuntimeVerseRecordKeys.DaemonHealth.ToString(), AssetManifestRecordRef = AetheriaRuntimeVerseRecordKeys.DaemonAssetManifest.ToString(), CommandBoundaryRecordRef = AetheriaRuntimeVerseRecordKeys.DaemonCommandBoundary.ToString(), EveGuiSurfaceRecordRef = AetheriaRuntimeVerseRecordKeys.DaemonGameSurface.ToString(), EveTuiSurfaceRecordRef = AetheriaRuntimeVerseRecordKeys.DaemonGameTuiSurface.ToString(), EveGuiSurfaceId = AetheriaRuntimeDaemonGameSurfaceBuilder.SurfaceId, EveTuiSurfaceId = AetheriaRuntimeDaemonGameSurfaceBuilder.TuiSurfaceId, EditorGuiSurfaceRecordRef = AetheriaRuntimeVerseRecordKeys.DaemonEditorSurface.ToString(), EditorTuiSurfaceRecordRef = AetheriaRuntimeVerseRecordKeys.DaemonEditorTuiSurface.ToString(), EditorGuiSurfaceId = AetheriaRuntimeDaemonEditorSurfaceBuilder.SurfaceId, EditorTuiSurfaceId = AetheriaRuntimeDaemonEditorSurfaceBuilder.TuiSurfaceId, CultMeshAddress = string.IsNullOrWhiteSpace(cultMeshAddress) ? "cultmesh://aetheria.local/eve/providers/aetheria.daemon" : cultMeshAddress, EveSurfaces = AetheriaRuntimeEveSurfaceCatalog.All, PublishedSchemas = new[] { AetheriaRuntimeDaemonSchemas.Frame, AetheriaRuntimeDaemonSchemas.SoaView, AetheriaRuntimeDaemonSchemas.Health, AetheriaRuntimeDaemonSchemas.CommandBoundary, AetheriaRuntimeDaemonSchemas.ObjectsViewport, AetheriaRuntimeDaemonSchemas.GravityViewport, AetheriaRuntimeDaemonSchemas.RenderSplatsViewport, AetheriaRuntimeDaemonSchemas.AssetManifest, AetheriaRuntimeDaemonSchemas.CurrentZone, AetheriaRuntimeDaemonSchemas.CurrentEntity, AetheriaRuntimeDaemonSchemas.CurrentDocking, AetheriaRuntimeDaemonSchemas.ZoneContacts, AetheriaRuntimeDaemonSchemas.StationRefit, AetheriaRuntimeDaemonSchemas.SectorMap, AetheriaRuntimeDaemonSchemas.ZoneDetails, AetheriaRuntimeDaemonSchemas.ZoneRender, AetheriaRuntimeDaemonSchemas.SelectedObject, AetheriaRuntimeDaemonSchemas.Inventory, AetheriaRuntimeDaemonSchemas.GameSurface, AetheriaRuntimeDaemonSchemas.EditorSurface, "gamecult.eve.surface.v1", AetheriaRuntimeDaemonSchemas.Command, AetheriaRuntimeDaemonSchemas.StarbridgeScenario, AetheriaRuntimeDaemonSchemas.StarbridgeSession, AetheriaRuntimeDaemonSchemas.StarbridgeSessionSummary, AetheriaRuntimeDaemonSchemas.StarbridgePlayerSeat, AetheriaRuntimeDaemonSchemas.VerseAuthorityPolicy, AetheriaRuntimeDaemonSchemas.AuthorityLease }, CommandBoundaryIds = new[] { "aetheria.daemon.commands" } }; } } [CultDocument("gamecult.aetheria.daemon_health", "gamecult.aetheria.daemon_health.v1")] [MessagePackObject] public sealed class AetheriaRuntimeDaemonHealthDocument { [Key(0)] public string Schema { get; set; } = AetheriaRuntimeDaemonSchemas.Health; [Key(1)] public string DaemonId { get; set; } = "aetheria-daemon"; [Key(2)] public string VerseId { get; set; } = "aetheria.local"; [Key(3)] public string PublishedAtUtc { get; set; } = ""; [Key(4)] public string StatePath { get; set; } = ""; [Key(5)] public long FrameId { get; set; } [Key(6)] public int ObservedCommandCount { get; set; } [Key(7)] public int AppliedCommandCount { get; set; } [Key(8)] public int RejectedCommandCount { get; set; } [Key(9)] public string Status { get; set; } = "healthy"; [Key(10)] public string PublicationSource { get; set; } = "daemon-published"; [Key(11)] public string Transport { get; set; } = "cultcache-witness"; [Key(12)] public string CommandBoundaryPath { get; set; } = ""; } [CultDocument("gamecult.aetheria.daemon_command_boundary", "gamecult.aetheria.daemon_command_boundary.v1")] [MessagePackObject] public sealed class AetheriaRuntimeDaemonCommandBoundaryDocument { [Key(0)] public string Schema { get; set; } = AetheriaRuntimeDaemonSchemas.CommandBoundary; [Key(1)] public string BoundaryId { get; set; } = "aetheria.daemon.commands"; [Key(2)] public string DaemonId { get; set; } = "aetheria-daemon"; [Key(3)] public string PublishedAtUtc { get; set; } = ""; [Key(4)] public string CommandSchema { get; set; } = AetheriaRuntimeDaemonSchemas.Command; [Key(5)] public string ReceiptSchema { get; set; } = AetheriaRuntimeDaemonSchemas.Frame; [Key(6)] public string Delivery { get; set; } = "cultnet-document-put"; [Key(7)] public IReadOnlyList Commands { get; set; } = Array.Empty(); public static AetheriaRuntimeDaemonCommandBoundaryDocument Create(string daemonId) { return new AetheriaRuntimeDaemonCommandBoundaryDocument { DaemonId = string.IsNullOrWhiteSpace(daemonId) ? "aetheria-daemon" : daemonId, PublishedAtUtc = DateTime.UtcNow.ToString("O"), Commands = Enum .GetValues(typeof(AetheriaRuntimeDaemonCommandKinds)) .Cast() .Where(kind => kind != AetheriaRuntimeDaemonCommandKinds.None) .Select(kind => new AetheriaRuntimeDaemonCommandBoundaryEntry { Kind = kind, CommandBody = CommandBodyFor(kind), Authority = "local-player-input", Receipt = "applied-or-rejected-command-id-in-frame" }) .ToArray() }; } private static string CommandBodyFor(AetheriaRuntimeDaemonCommandKinds kind) { switch (kind) { case AetheriaRuntimeDaemonCommandKinds.TransferCargoItem: return nameof(AetheriaRuntimeCargoTransferCommand); case AetheriaRuntimeDaemonCommandKinds.TradePurchase: return nameof(AetheriaRuntimeTradePurchaseCommand); case AetheriaRuntimeDaemonCommandKinds.PickUpLoot: return nameof(AetheriaRuntimeLootPickupCommand); case AetheriaRuntimeDaemonCommandKinds.RestoreLoadout: return nameof(AetheriaRuntimeLoadoutRestoreCommand); case AetheriaRuntimeDaemonCommandKinds.EquipItem: return nameof(AetheriaRuntimeEquipmentTransferCommand); case AetheriaRuntimeDaemonCommandKinds.StoreItem: return nameof(AetheriaRuntimeStoreItemCommand); default: return nameof(AetheriaRuntimeDaemonCommandDocument); } } } [MessagePackObject] public sealed class AetheriaRuntimeDaemonCommandBoundaryEntry { [Key(0)] public AetheriaRuntimeDaemonCommandKinds Kind { get; set; } [Key(1)] public string CommandBody { get; set; } = ""; [Key(2)] public string Authority { get; set; } = ""; [Key(3)] public string Receipt { get; set; } = ""; } [CultDocument("gamecult.aetheria.daemon_frame", "gamecult.aetheria.daemon_frame.v1")] [MessagePackObject] public sealed class AetheriaRuntimeDaemonFrameDocument { [Key(0)] public string Schema { get; set; } = AetheriaRuntimeDaemonSchemas.Frame; [Key(1)] public string DaemonId { get; set; } = "local"; [Key(2)] public string SessionId { get; set; } = "local"; [Key(3)] public long FrameId { get; set; } [Key(4)] public string PublishedAtUtc { get; set; } = ""; [Key(5)] public double SimulationTimeSeconds { get; set; } [Key(6)] public double FixedDeltaSeconds { get; set; } [Key(7)] public bool IsAuthoritative { get; set; } = true; [Key(8)] public string StateSource { get; set; } = "daemon"; [Key(9)] public AetheriaRuntimeRunCheckpointCommit Run { get; set; } = new AetheriaRuntimeRunCheckpointCommit(); [Key(10)] public IReadOnlyList Capabilities { get; set; } = Array.Empty(); [Key(11)] public IReadOnlyList AppliedCommandIds { get; set; } = Array.Empty(); [Key(12)] public IReadOnlyList RejectedCommandIds { get; set; } = Array.Empty(); [Key(13)] public IReadOnlyList AccountedCommandIds { get; set; } = Array.Empty(); [Key(14)] public IReadOnlyList CumulativeAppliedCommandIds { get; set; } = Array.Empty(); [Key(15)] public IReadOnlyList CumulativeRejectedCommandIds { get; set; } = Array.Empty(); [Key(16)] public IReadOnlyList ImportedFactIds { get; set; } = Array.Empty(); [Key(17)] public IReadOnlyList RejectedImportedFactIds { get; set; } = Array.Empty(); [Key(18)] public IReadOnlyList DuplicateImportedFactIds { get; set; } = Array.Empty(); [Key(19)] public IReadOnlyList CumulativeImportedFactIds { get; set; } = Array.Empty(); [Key(20)] public IReadOnlyList CumulativeRejectedImportedFactIds { get; set; } = Array.Empty(); [Key(21)] public AetheriaRuntimeDaemonRenderSettings RenderSettings { get; set; } = AetheriaRuntimeDaemonRenderSettings.AetheriaDefault; [Key(22)] public AetheriaRuntimeDaemonSimulationSettings SimulationSettings { get; set; } = AetheriaRuntimeDaemonSimulationSettings.AetheriaDefault; public static AetheriaRuntimeDaemonFrameDocument Create( AetheriaRuntimeRunCheckpointCommit run, string daemonId, string sessionId, long frameId, double simulationTimeSeconds, double fixedDeltaSeconds, bool isAuthoritative = true, string stateSource = "daemon", AetheriaRuntimeDaemonRenderSettings? renderSettings = null, AetheriaRuntimeDaemonSimulationSettings? simulationSettings = null) { return new AetheriaRuntimeDaemonFrameDocument { DaemonId = string.IsNullOrWhiteSpace(daemonId) ? "local" : daemonId, SessionId = string.IsNullOrWhiteSpace(sessionId) ? "local" : sessionId, FrameId = frameId, PublishedAtUtc = DateTime.UtcNow.ToString("O"), SimulationTimeSeconds = simulationTimeSeconds, FixedDeltaSeconds = fixedDeltaSeconds, IsAuthoritative = isAuthoritative, StateSource = string.IsNullOrWhiteSpace(stateSource) ? "daemon" : stateSource, Run = run ?? new AetheriaRuntimeRunCheckpointCommit(), RenderSettings = renderSettings ?? AetheriaRuntimeDaemonRenderSettings.AetheriaDefault, SimulationSettings = simulationSettings ?? AetheriaRuntimeDaemonSimulationSettings.AetheriaDefault }; } } [CultDocument("gamecult.aetheria.daemon_command", "gamecult.aetheria.daemon_command.v1")] [MessagePackObject] public sealed class AetheriaRuntimeDaemonCommandDocument { [Key(0)] public string Schema { get; set; } = AetheriaRuntimeDaemonSchemas.Command; [Key(1)] public string CommandId { get; set; } = ""; [Key(2)] public string ClientId { get; set; } = ""; [Key(3)] public string IssuedAtUtc { get; set; } = ""; [Key(4)] public string SessionId { get; set; } = ""; [Key(5)] public long ObservedFrameId { get; set; } = -1; [Key(6)] public AetheriaRuntimeDaemonCommandKinds Kind { get; set; } = AetheriaRuntimeDaemonCommandKinds.None; [Key(7)] public string ActorEntityKey { get; set; } = ""; [Key(8)] public string TargetEntityKey { get; set; } = ""; [Key(9)] public int TargetZoneIndex { get; set; } = -1; [Key(10)] public int EquipmentIndex { get; set; } = -1; [Key(11)] public int BehaviorIndex { get; set; } = -1; [Key(12)] public int WeaponGroup { get; set; } = -1; [Key(13)] public double PositionX { get; set; } [Key(14)] public double PositionY { get; set; } [Key(15)] public double PositionZ { get; set; } [Key(16)] public double DirectionX { get; set; } [Key(17)] public double DirectionY { get; set; } [Key(18)] public double ScalarValue { get; set; } [Key(19)] public string TextValue { get; set; } = ""; [Key(21)] public AetheriaRuntimeCargoTransferCommand CargoTransfer { get; set; } = new AetheriaRuntimeCargoTransferCommand(); [Key(22)] public AetheriaRuntimeTradePurchaseCommand TradePurchase { get; set; } = new AetheriaRuntimeTradePurchaseCommand(); [Key(23)] public AetheriaRuntimeLootPickupCommand LootPickup { get; set; } = new AetheriaRuntimeLootPickupCommand(); [Key(24)] public AetheriaRuntimeLoadoutRestoreCommand LoadoutRestore { get; set; } = new AetheriaRuntimeLoadoutRestoreCommand(); [Key(25)] public AetheriaRuntimeEquipmentTransferCommand EquipmentTransfer { get; set; } = new AetheriaRuntimeEquipmentTransferCommand(); [Key(26)] public AetheriaRuntimeStoreItemCommand StoreItem { get; set; } = new AetheriaRuntimeStoreItemCommand(); [Key(27)] public string AuthorRuntimeId { get; set; } = ""; [Key(28)] public string SubjectKey { get; set; } = ""; [Key(29)] public string ClaimKind { get; set; } = ""; public static AetheriaRuntimeDaemonCommandDocument Create( AetheriaRuntimeDaemonCommandKinds kind, string clientId, string sessionId, long observedFrameId, string actorEntityKey) { return new AetheriaRuntimeDaemonCommandDocument { CommandId = Guid.NewGuid().ToString("N"), ClientId = clientId ?? "", IssuedAtUtc = DateTime.UtcNow.ToString("O"), SessionId = sessionId ?? "", ObservedFrameId = observedFrameId, Kind = kind, ActorEntityKey = actorEntityKey ?? "", AuthorRuntimeId = clientId ?? "", SubjectKey = actorEntityKey ?? "", ClaimKind = AetheriaRuntimeAuthorityRouter.ResolveClaimKind(kind) }; } } public static class AetheriaRuntimeCommandFactOutcomes { public const string Applied = "applied"; public const string Rejected = "rejected"; } [CultDocument("gamecult.aetheria.committed_command_fact", "gamecult.aetheria.committed_command_fact.v1")] [MessagePackObject] public sealed class AetheriaRuntimeCommittedCommandFactDocument { [Key(0)] public string Schema { get; set; } = AetheriaRuntimeDaemonSchemas.CommittedCommandFact; [Key(1)] public string FactId { get; set; } = ""; [Key(2)] public string VerseId { get; set; } = "aetheria.local"; [Key(3)] public string SourceRuntimeId { get; set; } = ""; [Key(4)] public string SourceDaemonId { get; set; } = ""; [Key(5)] public string SessionId { get; set; } = ""; [Key(6)] public long SourceFrameId { get; set; } = -1; [Key(7)] public string CommandId { get; set; } = ""; [Key(8)] public string SubjectKey { get; set; } = ""; [Key(9)] public string ClaimKind { get; set; } = ""; [Key(10)] public AetheriaRuntimeDaemonCommandKinds CommandKind { get; set; } = AetheriaRuntimeDaemonCommandKinds.None; [Key(11)] public string Outcome { get; set; } = AetheriaRuntimeCommandFactOutcomes.Applied; [Key(12)] public string CommittedAtUtc { get; set; } = ""; [Key(13)] public AetheriaRuntimeDaemonCommandDocument Command { get; set; } = new AetheriaRuntimeDaemonCommandDocument(); public static AetheriaRuntimeCommittedCommandFactDocument FromAppliedCommand( AetheriaRuntimeDaemonFrameDocument frame, AetheriaRuntimeDaemonCommandDocument command, string verseId) { return FromCommand(frame, command, verseId, AetheriaRuntimeCommandFactOutcomes.Applied); } public static AetheriaRuntimeCommittedCommandFactDocument FromRejectedCommand( AetheriaRuntimeDaemonFrameDocument frame, AetheriaRuntimeDaemonCommandDocument command, string verseId) { return FromCommand(frame, command, verseId, AetheriaRuntimeCommandFactOutcomes.Rejected); } public static string CreateRecordKey(string factId) { return $"daemon:facts:{StableToken(factId)}:{AetheriaRuntimeDaemonSchemas.CommittedCommandFact}"; } private static AetheriaRuntimeCommittedCommandFactDocument FromCommand( AetheriaRuntimeDaemonFrameDocument frame, AetheriaRuntimeDaemonCommandDocument command, string verseId, string outcome) { frame ??= new AetheriaRuntimeDaemonFrameDocument(); command ??= new AetheriaRuntimeDaemonCommandDocument(); var sourceRuntimeId = string.IsNullOrWhiteSpace(command.AuthorRuntimeId) ? command.ClientId ?? "" : command.AuthorRuntimeId; var subjectKey = AetheriaRuntimeAuthorityRouter.ResolveSubjectKey(command); var claimKind = AetheriaRuntimeAuthorityRouter.ResolveClaimKind(command.Kind); return new AetheriaRuntimeCommittedCommandFactDocument { FactId = string.Join( ":", "fact", string.IsNullOrWhiteSpace(frame.DaemonId) ? "daemon" : frame.DaemonId, Math.Max(frame.FrameId, 0).ToString(System.Globalization.CultureInfo.InvariantCulture), string.IsNullOrWhiteSpace(command.CommandId) ? Guid.NewGuid().ToString("N") : command.CommandId, string.IsNullOrWhiteSpace(outcome) ? AetheriaRuntimeCommandFactOutcomes.Applied : outcome), VerseId = string.IsNullOrWhiteSpace(verseId) ? "aetheria.local" : verseId, SourceRuntimeId = sourceRuntimeId, SourceDaemonId = frame.DaemonId ?? "", SessionId = frame.SessionId ?? command.SessionId ?? "", SourceFrameId = frame.FrameId, CommandId = command.CommandId ?? "", SubjectKey = subjectKey, ClaimKind = claimKind, CommandKind = command.Kind, Outcome = string.IsNullOrWhiteSpace(outcome) ? AetheriaRuntimeCommandFactOutcomes.Applied : outcome, CommittedAtUtc = DateTime.UtcNow.ToString("O"), Command = command }; } private static string StableToken(string value) { if (string.IsNullOrWhiteSpace(value)) return "empty"; var chars = value .Select(character => char.IsLetterOrDigit(character) ? character : '-') .ToArray(); var token = new string(chars).Trim('-').ToLowerInvariant(); while (token.Contains("--", StringComparison.Ordinal)) token = token.Replace("--", "-", StringComparison.Ordinal); return string.IsNullOrWhiteSpace(token) ? "empty" : token; } } [MessagePackObject] public sealed class AetheriaRuntimeCargoTransferCommand { [Key(0)] public string OriginEntityKey { get; set; } = ""; [Key(1)] public int OriginCargoIndex { get; set; } = -1; [Key(2)] public string DestinationEntityKey { get; set; } = ""; [Key(3)] public int DestinationCargoIndex { get; set; } = -1; [Key(4)] public int SourceX { get; set; } = int.MinValue; [Key(5)] public int SourceY { get; set; } = int.MinValue; [Key(6)] public int DestinationX { get; set; } [Key(7)] public int DestinationY { get; set; } [Key(8)] public bool HasDestinationPosition { get; set; } } [MessagePackObject] public sealed class AetheriaRuntimeTradePurchaseCommand { [Key(0)] public string PurchaseKind { get; set; } = ""; [Key(1)] public string ItemKey { get; set; } = ""; [Key(2)] public int Quantity { get; set; } = 1; [Key(3)] public int UnitPrice { get; set; } [Key(4)] public int TotalPrice { get; set; } [Key(5)] public string StationEntityKey { get; set; } = ""; [Key(6)] public int StationCargoIndex { get; set; } = -1; [Key(7)] public string TargetEntityKey { get; set; } = ""; [Key(8)] public int TargetCargoIndex { get; set; } = -1; [Key(9)] public int SourceX { get; set; } = int.MinValue; [Key(10)] public int SourceY { get; set; } = int.MinValue; [Key(11)] public bool CreatesDockedShip { get; set; } } [MessagePackObject] public sealed class AetheriaRuntimeLootPickupCommand { [Key(0)] public string ItemKey { get; set; } = ""; [Key(1)] public int Quantity { get; set; } = 1; [Key(2)] public double PositionX { get; set; } [Key(3)] public double PositionY { get; set; } [Key(4)] public double PositionZ { get; set; } } [MessagePackObject] public sealed class AetheriaRuntimeLoadoutRestoreCommand { [Key(0)] public string DockedEntityKey { get; set; } = ""; [Key(1)] public string TemplateName { get; set; } = ""; [Key(2)] public int Price { get; set; } } [MessagePackObject] public sealed class AetheriaRuntimeEquipmentTransferCommand { [Key(0)] public string SourceKind { get; set; } = ""; [Key(1)] public string OriginEntityKey { get; set; } = ""; [Key(2)] public int OriginIndex { get; set; } = -1; [Key(3)] public string DestinationEntityKey { get; set; } = ""; [Key(4)] public int SourceX { get; set; } = int.MinValue; [Key(5)] public int SourceY { get; set; } = int.MinValue; [Key(6)] public int DestinationX { get; set; } [Key(7)] public int DestinationY { get; set; } [Key(8)] public bool HasDestinationPosition { get; set; } } [MessagePackObject] public sealed class AetheriaRuntimeStoreItemCommand { [Key(0)] public string OriginEntityKey { get; set; } = ""; [Key(1)] public int SourceEquipmentIndex { get; set; } = -1; [Key(2)] public string DestinationEntityKey { get; set; } = ""; [Key(3)] public int DestinationCargoIndex { get; set; } = -1; [Key(4)] public int DestinationX { get; set; } [Key(5)] public int DestinationY { get; set; } [Key(6)] public bool HasDestinationPosition { get; set; } } }