refactor(backend): align api namespaces and project name

This commit is contained in:
2026-03-19 17:44:53 -04:00
parent a281d37fb4
commit 07a3142316
35 changed files with 191 additions and 169 deletions

View File

@@ -1,4 +1,4 @@
namespace SpaceGame.Simulation.Api.Contracts;
namespace SpaceGame.Api.Contracts;
public sealed record StarSnapshot(
string Kind,

View File

@@ -1,4 +1,4 @@
namespace SpaceGame.Simulation.Api.Contracts;
namespace SpaceGame.Api.Contracts;
public sealed record Vector3Dto(float X, float Y, float Z);

View File

@@ -1,4 +1,4 @@
namespace SpaceGame.Simulation.Api.Contracts;
namespace SpaceGame.Api.Contracts;
public sealed record MarketOrderSnapshot(
string Id,

View File

@@ -1,4 +1,4 @@
namespace SpaceGame.Simulation.Api.Contracts;
namespace SpaceGame.Api.Contracts;
public sealed record FactionGoapStateSnapshot(
int MilitaryShipCount,

View File

@@ -1,4 +1,4 @@
namespace SpaceGame.Simulation.Api.Contracts;
namespace SpaceGame.Api.Contracts;
public sealed record InventoryEntry(
string ItemId,

View File

@@ -1,4 +1,4 @@
namespace SpaceGame.Simulation.Api.Contracts;
namespace SpaceGame.Api.Contracts;
public sealed record ShipSnapshot(
string Id,

View File

@@ -1,4 +1,4 @@
namespace SpaceGame.Simulation.Api.Contracts;
namespace SpaceGame.Api.Contracts;
public sealed record WorldSnapshot(
string Label,

View File

@@ -1,6 +1,6 @@
using System.Text.Json.Serialization;
namespace SpaceGame.Simulation.Api.Data;
namespace SpaceGame.Api.Data;
public sealed class ConstructionDefinition
{

View File

@@ -1,7 +1,7 @@
using FastEndpoints;
using SpaceGame.Simulation.Api.Simulation;
using SpaceGame.Api.Simulation;
namespace SpaceGame.Simulation.Api.Handlers;
namespace SpaceGame.Api.Handlers;
public sealed class GetWorldHandler(WorldService worldService) : EndpointWithoutRequest
{

View File

@@ -1,7 +1,7 @@
using FastEndpoints;
using SpaceGame.Simulation.Api.Simulation;
using SpaceGame.Api.Simulation;
namespace SpaceGame.Simulation.Api.Handlers;
namespace SpaceGame.Api.Handlers;
public sealed class GetWorldHealthHandler(WorldService worldService) : EndpointWithoutRequest
{

View File

@@ -1,7 +1,7 @@
using FastEndpoints;
using SpaceGame.Simulation.Api.Simulation;
using SpaceGame.Api.Simulation;
namespace SpaceGame.Simulation.Api.Handlers;
namespace SpaceGame.Api.Handlers;
public sealed class ResetWorldHandler(WorldService worldService) : EndpointWithoutRequest
{

View File

@@ -1,6 +1,6 @@
using FastEndpoints;
namespace SpaceGame.Simulation.Api.Handlers;
namespace SpaceGame.Api.Handlers;
public sealed class RootRedirectHandler : EndpointWithoutRequest
{

View File

@@ -1,9 +1,9 @@
using System.Text.Json;
using FastEndpoints;
using SpaceGame.Simulation.Api.Contracts;
using SpaceGame.Simulation.Api.Simulation;
using SpaceGame.Api.Contracts;
using SpaceGame.Api.Simulation;
namespace SpaceGame.Simulation.Api.Handlers;
namespace SpaceGame.Api.Handlers;
public sealed class StreamWorldHandler(WorldService worldService) : EndpointWithoutRequest
{

View File

@@ -1,5 +1,5 @@
using FastEndpoints;
using SpaceGame.Simulation.Api.Simulation;
using SpaceGame.Api.Simulation;
var builder = WebApplication.CreateBuilder(args);

View File

@@ -1,4 +1,7 @@
namespace SpaceGame.Simulation.Api.Simulation;
using SpaceGame.Api.Simulation.Engine;
using SpaceGame.Api.Simulation.Model;
namespace SpaceGame.Api.Simulation.AI;
// ─── Planning State ────────────────────────────────────────────────────────────

View File

@@ -1,4 +1,7 @@
namespace SpaceGame.Simulation.Api.Simulation;
using SpaceGame.Api.Simulation.Engine;
using SpaceGame.Api.Simulation.Model;
namespace SpaceGame.Api.Simulation.AI;
public abstract class GoapAction<TState>
{

View File

@@ -1,10 +1,13 @@
namespace SpaceGame.Simulation.Api.Simulation;
using SpaceGame.Api.Simulation.Engine;
using SpaceGame.Api.Simulation.Model;
namespace SpaceGame.Api.Simulation.AI;
internal interface IShipBehaviorState
{
string Kind { get; }
string Kind { get; }
void Plan(SimulationEngine engine, ShipRuntime ship, SimulationWorld world);
void Plan(SimulationEngine engine, ShipRuntime ship, SimulationWorld world);
void ApplyEvent(SimulationEngine engine, ShipRuntime ship, SimulationWorld world, string controllerEvent);
void ApplyEvent(SimulationEngine engine, ShipRuntime ship, SimulationWorld world, string controllerEvent);
}

View File

@@ -1,38 +1,41 @@
namespace SpaceGame.Simulation.Api.Simulation;
using SpaceGame.Api.Simulation.Engine;
using SpaceGame.Api.Simulation.Model;
namespace SpaceGame.Api.Simulation.AI;
internal sealed class ShipBehaviorStateMachine
{
private readonly IReadOnlyDictionary<string, IShipBehaviorState> states;
private readonly IShipBehaviorState fallbackState;
private readonly IReadOnlyDictionary<string, IShipBehaviorState> states;
private readonly IShipBehaviorState fallbackState;
private ShipBehaviorStateMachine(IReadOnlyDictionary<string, IShipBehaviorState> states, IShipBehaviorState fallbackState)
{
this.states = states;
this.fallbackState = fallbackState;
}
private ShipBehaviorStateMachine(IReadOnlyDictionary<string, IShipBehaviorState> states, IShipBehaviorState fallbackState)
{
this.states = states;
this.fallbackState = fallbackState;
}
public static ShipBehaviorStateMachine CreateDefault()
public static ShipBehaviorStateMachine CreateDefault()
{
var idleState = new IdleShipBehaviorState();
var knownStates = new IShipBehaviorState[]
{
var idleState = new IdleShipBehaviorState();
var knownStates = new IShipBehaviorState[]
{
idleState,
new PatrolShipBehaviorState(),
new ResourceHarvestShipBehaviorState("auto-mine", "ore", "mining"),
new ConstructStationShipBehaviorState(),
};
};
return new ShipBehaviorStateMachine(
knownStates.ToDictionary(state => state.Kind, StringComparer.Ordinal),
idleState);
}
return new ShipBehaviorStateMachine(
knownStates.ToDictionary(state => state.Kind, StringComparer.Ordinal),
idleState);
}
public void Plan(SimulationEngine engine, ShipRuntime ship, SimulationWorld world) =>
Resolve(ship.DefaultBehavior.Kind).Plan(engine, ship, world);
public void Plan(SimulationEngine engine, ShipRuntime ship, SimulationWorld world) =>
Resolve(ship.DefaultBehavior.Kind).Plan(engine, ship, world);
public void ApplyEvent(SimulationEngine engine, ShipRuntime ship, SimulationWorld world, string controllerEvent) =>
Resolve(ship.DefaultBehavior.Kind).ApplyEvent(engine, ship, world, controllerEvent);
public void ApplyEvent(SimulationEngine engine, ShipRuntime ship, SimulationWorld world, string controllerEvent) =>
Resolve(ship.DefaultBehavior.Kind).ApplyEvent(engine, ship, world, controllerEvent);
private IShipBehaviorState Resolve(string kind) =>
states.TryGetValue(kind, out var state) ? state : fallbackState;
private IShipBehaviorState Resolve(string kind) =>
states.TryGetValue(kind, out var state) ? state : fallbackState;
}

View File

@@ -1,4 +1,7 @@
namespace SpaceGame.Simulation.Api.Simulation;
using SpaceGame.Api.Simulation.Engine;
using SpaceGame.Api.Simulation.Model;
namespace SpaceGame.Api.Simulation.AI;
internal sealed class IdleShipBehaviorState : IShipBehaviorState
{

View File

@@ -1,4 +1,7 @@
namespace SpaceGame.Simulation.Api.Simulation;
using SpaceGame.Api.Simulation.Engine;
using SpaceGame.Api.Simulation.Model;
namespace SpaceGame.Api.Simulation.AI;
// ─── Planning State ────────────────────────────────────────────────────────────

View File

@@ -1,30 +1,30 @@
namespace SpaceGame.Simulation.Api.Simulation;
namespace SpaceGame.Api.Simulation.Model;
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 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 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;
}

View File

@@ -1,36 +1,36 @@
namespace SpaceGame.Simulation.Api.Simulation;
namespace SpaceGame.Api.Simulation.Model;
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 CelestialId { 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 required string Id { get; init; }
public required string FactionId { get; init; }
public required string SystemId { get; init; }
public required string CelestialId { 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 CelestialId { 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<string, float> Inventory { get; } = new(StringComparer.Ordinal);
public Dictionary<string, float> RequiredItems { get; } = new(StringComparer.Ordinal);
public Dictionary<string, float> DeliveredItems { get; } = new(StringComparer.Ordinal);
public HashSet<string> AssignedConstructorShipIds { get; } = new(StringComparer.Ordinal);
public HashSet<string> 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 required string Id { get; init; }
public required string FactionId { get; init; }
public required string SystemId { get; init; }
public required string CelestialId { 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<string, float> Inventory { get; } = new(StringComparer.Ordinal);
public Dictionary<string, float> RequiredItems { get; } = new(StringComparer.Ordinal);
public Dictionary<string, float> DeliveredItems { get; } = new(StringComparer.Ordinal);
public HashSet<string> AssignedConstructorShipIds { get; } = new(StringComparer.Ordinal);
public HashSet<string> MarketOrderIds { get; } = new(StringComparer.Ordinal);
public float Progress { get; set; }
public string State { get; set; } = ConstructionSiteStateKinds.Planned;
public string LastDeltaSignature { get; set; } = string.Empty;
}

View File

@@ -1,73 +1,75 @@
namespace SpaceGame.Simulation.Api.Simulation;
using SpaceGame.Api.Simulation.AI;
namespace SpaceGame.Api.Simulation.Model;
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<string> CommanderIds { get; } = new(StringComparer.Ordinal);
public string? DefaultPolicySetId { get; set; }
public string LastDeltaSignature { get; set; } = string.Empty;
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<string> 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<string> Goals { get; } = [];
public HashSet<string> ActiveDirectives { get; } = new(StringComparer.Ordinal);
public string? ActiveGoalName { get; set; }
public string? ActiveActionName { get; set; }
public float ReplanTimer { get; set; }
public bool NeedsReplan { get; set; } = true;
public CommanderBehaviorRuntime? ActiveBehavior { get; set; }
public CommanderOrderRuntime? ActiveOrder { get; set; }
public CommanderTaskRuntime? ActiveTask { get; set; }
public HashSet<string> SubordinateCommanderIds { get; } = new(StringComparer.Ordinal);
public bool IsAlive { get; set; } = true;
public FactionPlanningState? LastPlanningState { get; set; }
public IReadOnlyList<(string Name, float Priority)>? LastGoalPriorities { get; set; }
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<string> Goals { get; } = [];
public HashSet<string> ActiveDirectives { get; } = new(StringComparer.Ordinal);
public string? ActiveGoalName { get; set; }
public string? ActiveActionName { get; set; }
public float ReplanTimer { get; set; }
public bool NeedsReplan { get; set; } = true;
public CommanderBehaviorRuntime? ActiveBehavior { get; set; }
public CommanderOrderRuntime? ActiveOrder { get; set; }
public CommanderTaskRuntime? ActiveTask { get; set; }
public HashSet<string> SubordinateCommanderIds { get; } = new(StringComparer.Ordinal);
public bool IsAlive { get; set; } = true;
public FactionPlanningState? LastPlanningState { get; set; }
public IReadOnlyList<(string Name, float Priority)>? LastGoalPriorities { get; set; }
}
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 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 OrderStatus Status { get; set; } = OrderStatus.Accepted;
public string? TargetEntityId { get; set; }
public string? DestinationNodeId { get; set; }
public required string DestinationSystemId { get; init; }
public required Vector3 DestinationPosition { get; init; }
public required string Kind { get; init; }
public OrderStatus Status { get; set; } = OrderStatus.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 WorkStatus Status { get; set; } = WorkStatus.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 required string Kind { get; set; }
public WorkStatus Status { get; set; } = WorkStatus.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; }
}

View File

@@ -1,6 +1,6 @@
using SpaceGame.Simulation.Api.Data;
using SpaceGame.Api.Data;
namespace SpaceGame.Simulation.Api.Simulation;
namespace SpaceGame.Api.Simulation.Model;
public sealed class ShipRuntime
{

View File

@@ -1,4 +1,4 @@
namespace SpaceGame.Simulation.Api.Simulation;
namespace SpaceGame.Api.Simulation.Model;
public enum SpatialNodeKind
{

View File

@@ -1,4 +1,4 @@
namespace SpaceGame.Simulation.Api.Simulation;
namespace SpaceGame.Api.Simulation.Model;
public static class SimulationUnits
{

View File

@@ -1,6 +1,6 @@
using SpaceGame.Simulation.Api.Data;
using SpaceGame.Api.Data;
namespace SpaceGame.Simulation.Api.Simulation;
namespace SpaceGame.Api.Simulation.Model;
public sealed class SimulationWorld
{

View File

@@ -1,6 +1,6 @@
using SpaceGame.Simulation.Api.Data;
using SpaceGame.Api.Data;
namespace SpaceGame.Simulation.Api.Simulation;
namespace SpaceGame.Api.Simulation.Model;
public sealed class SystemRuntime
{

View File

@@ -1,4 +1,4 @@
namespace SpaceGame.Simulation.Api.Simulation;
namespace SpaceGame.Api.Simulation.Model;
public sealed class StationRuntime
{

View File

@@ -1,4 +1,4 @@
namespace SpaceGame.Simulation.Api.Simulation;
namespace SpaceGame.Api.Simulation.Model;
public readonly record struct Vector3(float X, float Y, float Z)
{

View File

@@ -1,4 +1,4 @@
namespace SpaceGame.Simulation.Api.Simulation;
namespace SpaceGame.Api.Simulation;
public sealed class OrbitalSimulationOptions
{

View File

@@ -1,4 +1,4 @@
namespace SpaceGame.Simulation.Api.Simulation;
namespace SpaceGame.Api.Simulation;
public sealed class SimulationHostedService(WorldService worldService) : BackgroundService
{

View File

@@ -1,4 +1,4 @@
namespace SpaceGame.Simulation.Api.Simulation;
namespace SpaceGame.Api.Simulation;
public sealed class WorldGenerationOptions
{

View File

@@ -1,8 +1,10 @@
using System.Threading.Channels;
using Microsoft.Extensions.Options;
using SpaceGame.Simulation.Api.Contracts;
using SpaceGame.Api.Contracts;
using SpaceGame.Api.Simulation.Engine;
using SpaceGame.Api.Simulation.Model;
namespace SpaceGame.Simulation.Api.Simulation;
namespace SpaceGame.Api.Simulation;
public sealed class WorldService(
IWebHostEnvironment environment,
@@ -11,7 +13,7 @@ public sealed class WorldService(
{
private const int DeltaHistoryLimit = 256;
private readonly object _sync = new();
private readonly Lock _sync = new();
private readonly OrbitalSimulationSnapshot _orbitalSimulation = new(orbitalSimulationOptions.Value.SimulatedSecondsPerRealSecond);
private readonly ScenarioLoader _loader = new(environment.ContentRootPath, worldGenerationOptions.Value);
private readonly SimulationEngine _engine = new(orbitalSimulationOptions.Value);