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 Stations { get; init; } public required List Ships { get; init; } public required List Factions { get; init; } public required Dictionary ShipDefinitions { 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 StationRuntime { public required string Id { get; init; } public required string SystemId { get; init; } public required ConstructibleDefinition Definition { get; init; } public required Vector3 Position { get; init; } public required string FactionId { get; init; } public float OreStored { get; set; } public float RefinedStock { get; set; } public float ProcessTimer { get; set; } public HashSet DockedShipIds { get; } = []; public string LastDeltaSignature { 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 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 float Cargo { get; set; } public string? DockedStationId { 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 OreMined { get; set; } public float GoodsProduced { get; set; } public int ShipsBuilt { get; set; } public int ShipsLost { get; set; } 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? RefineryId { get; set; } public string? NodeId { 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? TargetEntityId { get; set; } public string? TargetSystemId { get; set; } public Vector3? TargetPosition { get; set; } public float Threshold { get; set; } } public readonly record struct Vector3(float X, float Y, float Z) { public static Vector3 Zero => new(0f, 0f, 0f); 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); } }