using SpaceGame.Simulation.Api.Data; namespace SpaceGame.Simulation.Api.Simulation; public sealed class SimulationWorld { public required string Label { get; init; } public required int Seed { get; init; } public required BalanceDefinition Balance { get; init; } public required List Systems { get; init; } public required List Nodes { get; init; } public required List SpatialNodes { get; init; } public required List LocalBubbles { get; init; } public required List Stations { get; init; } public required List Ships { get; init; } public required List Factions { get; init; } public required List Commanders { get; init; } public required List Claims { get; init; } public required List ConstructionSites { get; init; } public required List MarketOrders { get; init; } public required List Policies { get; init; } public required Dictionary ShipDefinitions { get; init; } public required Dictionary ItemDefinitions { get; init; } public required Dictionary ModuleRecipes { get; init; } public required Dictionary Recipes { get; init; } public int TickIntervalMs { get; init; } = 200; public DateTimeOffset GeneratedAtUtc { get; set; } } public sealed class SystemRuntime { public required SolarSystemDefinition Definition { get; init; } public required Vector3 Position { get; init; } } public sealed class ResourceNodeRuntime { public required string Id { get; init; } public required string SystemId { get; init; } public required Vector3 Position { get; init; } public required string SourceKind { get; init; } public required string ItemId { get; init; } public float OreRemaining { get; set; } public float MaxOre { get; init; } public string LastDeltaSignature { get; set; } = string.Empty; } public sealed class NodeRuntime { public required string Id { get; init; } public required string SystemId { get; init; } public required string Kind { get; init; } public required Vector3 Position { get; set; } public required string BubbleId { get; init; } public string? ParentNodeId { get; set; } public string? OccupyingStructureId { get; set; } public string? OrbitReferenceId { get; set; } public string LastDeltaSignature { get; set; } = string.Empty; } public sealed class LocalBubbleRuntime { public required string Id { get; init; } public required string NodeId { get; init; } public required string SystemId { get; init; } public float Radius { get; init; } public HashSet OccupantShipIds { get; } = new(StringComparer.Ordinal); public HashSet OccupantStationIds { get; } = new(StringComparer.Ordinal); public HashSet OccupantClaimIds { get; } = new(StringComparer.Ordinal); public HashSet OccupantConstructionSiteIds { get; } = new(StringComparer.Ordinal); public string LastDeltaSignature { get; set; } = string.Empty; } public sealed class StationRuntime { public required string Id { get; init; } public required string SystemId { get; init; } public required ConstructibleDefinition Definition { get; init; } public required Vector3 Position { get; set; } public required string FactionId { get; init; } public string? NodeId { get; set; } public string? BubbleId { get; set; } public string? AnchorNodeId { get; set; } public string? CommanderId { get; set; } public string? PolicySetId { get; set; } public HashSet InstalledModules { get; } = new(StringComparer.Ordinal); public Dictionary Inventory { get; } = new(StringComparer.Ordinal); public Dictionary DockingPadAssignments { get; } = new(); public HashSet MarketOrderIds { get; } = new(StringComparer.Ordinal); public float EnergyStored { get; set; } public float ProcessTimer { get; set; } public float Population { get; set; } public float PopulationCapacity { get; set; } public float WorkforceRequired { get; set; } public float WorkforceEffectiveRatio { get; set; } = 0.1f; public float PopulationGrowthProgress { get; set; } public HashSet DockedShipIds { get; } = []; public ModuleConstructionRuntime? ActiveConstruction { get; set; } public string LastDeltaSignature { get; set; } = string.Empty; } public sealed class ModuleConstructionRuntime { public required string ModuleId { get; init; } public float ProgressSeconds { get; set; } public float RequiredSeconds { get; init; } public string AssignedConstructorShipId { get; set; } = string.Empty; } public sealed class ShipRuntime { public required string Id { get; init; } public required string SystemId { get; set; } public required ShipDefinition Definition { get; init; } public required string FactionId { get; init; } public required Vector3 Position { get; set; } public required Vector3 TargetPosition { get; set; } public required ShipSpatialStateRuntime SpatialState { get; set; } public Vector3 Velocity { get; set; } = Vector3.Zero; public string State { get; set; } = "idle"; public ShipOrderRuntime? Order { get; set; } public required DefaultBehaviorRuntime DefaultBehavior { get; set; } public required ControllerTaskRuntime ControllerTask { get; set; } public float ActionTimer { get; set; } public Dictionary Inventory { get; } = new(StringComparer.Ordinal); public float WorkerPopulation { get; set; } public float EnergyStored { get; set; } public string? DockedStationId { get; set; } public int? AssignedDockingPadIndex { get; set; } public string? CommanderId { get; set; } public string? PolicySetId { get; set; } public float Health { get; set; } public List History { get; } = []; public string LastSignature { get; set; } = string.Empty; public string LastDeltaSignature { get; set; } = string.Empty; } public sealed class FactionRuntime { public required string Id { get; init; } public required string Label { get; init; } public required string Color { get; init; } public float Credits { get; set; } public float PopulationTotal { get; set; } public float OreMined { get; set; } public float GoodsProduced { get; set; } public int ShipsBuilt { get; set; } public int ShipsLost { get; set; } public HashSet CommanderIds { get; } = new(StringComparer.Ordinal); public string? DefaultPolicySetId { get; set; } public string LastDeltaSignature { get; set; } = string.Empty; } public sealed class CommanderRuntime { public required string Id { get; init; } public required string Kind { get; set; } public required string FactionId { get; init; } public string? ParentCommanderId { get; set; } public string? ControlledEntityId { get; set; } public string? PolicySetId { get; set; } public string? Doctrine { get; set; } public List Goals { get; } = []; public CommanderBehaviorRuntime? ActiveBehavior { get; set; } public CommanderOrderRuntime? ActiveOrder { get; set; } public CommanderTaskRuntime? ActiveTask { get; set; } public HashSet SubordinateCommanderIds { get; } = new(StringComparer.Ordinal); public bool IsAlive { get; set; } = true; } public sealed class CommanderBehaviorRuntime { public required string Kind { get; set; } public string? Phase { get; set; } public string? NodeId { get; set; } public string? StationId { get; set; } public string? ModuleId { get; set; } public string? AreaSystemId { get; set; } public int PatrolIndex { get; set; } } public sealed class CommanderOrderRuntime { public required string Kind { get; init; } public string Status { get; set; } = "accepted"; public string? TargetEntityId { get; set; } public string? DestinationNodeId { get; set; } public required string DestinationSystemId { get; init; } public required Vector3 DestinationPosition { get; init; } } public sealed class CommanderTaskRuntime { public required string Kind { get; set; } public string Status { get; set; } = "pending"; public string? TargetEntityId { get; set; } public string? TargetSystemId { get; set; } public string? TargetNodeId { get; set; } public Vector3? TargetPosition { get; set; } public float Threshold { get; set; } } public sealed class ClaimRuntime { public required string Id { get; init; } public required string FactionId { get; init; } public required string SystemId { get; init; } public required string NodeId { get; init; } public required string BubbleId { get; init; } public string? CommanderId { get; set; } public DateTimeOffset PlacedAtUtc { get; init; } public DateTimeOffset ActivatesAtUtc { get; set; } public string State { get; set; } = ClaimStateKinds.Placed; public float Health { get; set; } public string LastDeltaSignature { get; set; } = string.Empty; } public sealed class ConstructionSiteRuntime { public required string Id { get; init; } public required string FactionId { get; init; } public required string SystemId { get; init; } public required string NodeId { get; init; } public required string BubbleId { get; init; } public required string TargetKind { get; init; } public required string TargetDefinitionId { get; init; } public string? BlueprintId { get; set; } public string? ClaimId { get; set; } public string? StationId { get; set; } public Dictionary Inventory { get; } = new(StringComparer.Ordinal); public Dictionary RequiredItems { get; } = new(StringComparer.Ordinal); public Dictionary DeliveredItems { get; } = new(StringComparer.Ordinal); public HashSet AssignedConstructorShipIds { get; } = new(StringComparer.Ordinal); public HashSet MarketOrderIds { get; } = new(StringComparer.Ordinal); public float Progress { get; set; } public string State { get; set; } = ConstructionSiteStateKinds.Planned; public string LastDeltaSignature { get; set; } = string.Empty; } public sealed class MarketOrderRuntime { public required string Id { get; init; } public required string FactionId { get; init; } public string? StationId { get; init; } public string? ConstructionSiteId { get; init; } public required string Kind { get; init; } public required string ItemId { get; init; } public float Amount { get; init; } public float RemainingAmount { get; set; } public float Valuation { get; set; } public float? ReserveThreshold { get; set; } public string? PolicySetId { get; set; } public string State { get; set; } = MarketOrderStateKinds.Open; public string LastDeltaSignature { get; set; } = string.Empty; } public sealed class PolicySetRuntime { public required string Id { get; init; } public required string OwnerKind { get; init; } public required string OwnerId { get; init; } public string TradeAccessPolicy { get; set; } = "owner-and-allies"; public string DockingAccessPolicy { get; set; } = "owner-and-allies"; public string ConstructionAccessPolicy { get; set; } = "owner-only"; public string OperationalRangePolicy { get; set; } = "unrestricted"; public string LastDeltaSignature { get; set; } = string.Empty; } public sealed class ShipOrderRuntime { public required string Kind { get; init; } public string Status { get; set; } = "accepted"; public required string DestinationSystemId { get; init; } public required Vector3 DestinationPosition { get; init; } } public sealed class DefaultBehaviorRuntime { public required string Kind { get; set; } public string? AreaSystemId { get; set; } public string? StationId { get; set; } public string? RefineryId { get; set; } public string? NodeId { get; set; } public string? ModuleId { get; set; } public string? Phase { get; set; } public List PatrolPoints { get; set; } = []; public int PatrolIndex { get; set; } } public sealed class ControllerTaskRuntime { public required string Kind { get; set; } public string Status { get; set; } = "pending"; public string? CommanderId { get; set; } public string? TargetEntityId { get; set; } public string? TargetSystemId { get; set; } public string? TargetNodeId { get; set; } public Vector3? TargetPosition { get; set; } public float Threshold { get; set; } } public sealed class ShipSpatialStateRuntime { public string SpaceLayer { get; set; } = SpaceLayerKinds.LocalSpace; public required string CurrentSystemId { get; set; } public string? CurrentNodeId { get; set; } public string? CurrentBubbleId { get; set; } public Vector3? LocalPosition { get; set; } public Vector3? SystemPosition { get; set; } public string MovementRegime { get; set; } = MovementRegimeKinds.LocalFlight; public string? DestinationNodeId { get; set; } public ShipTransitRuntime? Transit { get; set; } } public sealed class ShipTransitRuntime { public required string Regime { get; init; } public string? OriginNodeId { get; init; } public string? DestinationNodeId { get; init; } public DateTimeOffset? StartedAtUtc { get; set; } public DateTimeOffset? ArrivalDueAtUtc { get; set; } public float Progress { get; set; } } public static class SpaceLayerKinds { public const string UniverseSpace = "universe-space"; public const string GalaxySpace = "galaxy-space"; public const string SystemSpace = "system-space"; public const string LocalSpace = "local-space"; } public static class MovementRegimeKinds { public const string LocalFlight = "local-flight"; public const string Warp = "warp"; public const string StargateTransit = "stargate-transit"; public const string FtlTransit = "ftl-transit"; } public static class CommanderKind { public const string Faction = "faction"; public const string Station = "station"; public const string Ship = "ship"; public const string Fleet = "fleet"; public const string Sector = "sector"; public const string TaskGroup = "task-group"; } public static class ShipTaskKinds { public const string Idle = "idle"; public const string LocalMove = "local-move"; public const string WarpToNode = "warp-to-node"; public const string UseStargate = "use-stargate"; public const string UseFtl = "use-ftl"; public const string Dock = "dock"; public const string Undock = "undock"; public const string LoadCargo = "load-cargo"; public const string UnloadCargo = "unload-cargo"; public const string LoadWorkers = "load-workers"; public const string UnloadWorkers = "unload-workers"; public const string MineNode = "mine-node"; public const string HarvestGas = "harvest-gas"; public const string DeliverToStation = "deliver-to-station"; public const string ClaimLagrangePoint = "claim-lagrange-point"; public const string BuildConstructionSite = "build-construction-site"; public const string EscortTarget = "escort-target"; public const string AttackTarget = "attack-target"; public const string DefendBubble = "defend-bubble"; public const string Retreat = "retreat"; public const string HoldPosition = "hold-position"; } public static class ShipOrderKinds { public const string DirectMove = "direct-move"; public const string TravelToNode = "travel-to-node"; public const string DockAtStation = "dock-at-station"; public const string DeliverCargo = "deliver-cargo"; public const string BuildAtSite = "build-at-site"; public const string AttackTarget = "attack-target"; public const string HoldPosition = "hold-position"; } public static class ClaimStateKinds { public const string Placed = "placed"; public const string Activating = "activating"; public const string Active = "active"; public const string Destroyed = "destroyed"; } public static class ConstructionSiteStateKinds { public const string Planned = "planned"; public const string Active = "active"; public const string Paused = "paused"; public const string Completed = "completed"; public const string Destroyed = "destroyed"; } public static class MarketOrderKinds { public const string Buy = "buy"; public const string Sell = "sell"; } public static class MarketOrderStateKinds { public const string Open = "open"; public const string PartiallyFilled = "partially-filled"; public const string Filled = "filled"; public const string Cancelled = "cancelled"; } public readonly record struct Vector3(float X, float Y, float Z) { public static Vector3 Zero => new(0f, 0f, 0f); public float LengthSquared() => (X * X) + (Y * Y) + (Z * Z); public float DistanceTo(Vector3 other) { var dx = X - other.X; var dy = Y - other.Y; var dz = Z - other.Z; return MathF.Sqrt((dx * dx) + (dy * dy) + (dz * dz)); } public Vector3 MoveToward(Vector3 target, float maxDistance) { var distance = DistanceTo(target); if (distance <= maxDistance || distance <= 0.0001f) { return target; } var t = maxDistance / distance; return new Vector3( X + ((target.X - X) * t), Y + ((target.Y - Y) * t), Z + ((target.Z - Z) * t)); } public Vector3 Subtract(Vector3 other) => new(X - other.X, Y - other.Y, Z - other.Z); public Vector3 Divide(float value) { if (value == 0f) { return Zero; } return new(X / value, Y / value, Z / value); } }