refactor: replace SpaceLayerKinds with strongly-typed SpaceLayerKind enum

Replaces string-based `SpaceLayerKinds` constants with a strongly-typed `SpaceLayerKind` enum. Updates backend services, runtime models, and projection logic to use the new enum. Adds `ToContractValue` method for compatibility with existing contracts.
This commit is contained in:
2026-03-24 03:03:13 -04:00
parent 766fef1c8f
commit 85a055ec91
7 changed files with 43 additions and 34 deletions

View File

@@ -86,12 +86,12 @@ public enum ShipState
Fleeing,
}
public static class SpaceLayerKinds
public enum SpaceLayerKind
{
public const string UniverseSpace = "universe-space";
public const string GalaxySpace = "galaxy-space";
public const string SystemSpace = "system-space";
public const string LocalSpace = "local-space";
UniverseSpace,
GalaxySpace,
SystemSpace,
LocalSpace,
}
public static class MovementRegimeKinds
@@ -274,4 +274,13 @@ public static class SimulationEnumMappings
ShipState.Fleeing => "fleeing",
_ => throw new ArgumentOutOfRangeException(nameof(state), state, null),
};
public static string ToContractValue(this SpaceLayerKind kind) => kind switch
{
SpaceLayerKind.UniverseSpace => "universe-space",
SpaceLayerKind.GalaxySpace => "galaxy-space",
SpaceLayerKind.SystemSpace => "system-space",
SpaceLayerKind.LocalSpace => "local-space",
_ => throw new ArgumentOutOfRangeException(nameof(kind), kind, null),
};
}

View File

@@ -1646,7 +1646,7 @@ internal sealed class ShipAiService
bool completeOnArrival)
{
var distance = ship.Position.DistanceTo(targetPosition);
ship.SpatialState.SpaceLayer = SpaceLayerKinds.LocalSpace;
ship.SpatialState.SpaceLayer = SpaceLayerKind.LocalSpace;
ship.SpatialState.MovementRegime = MovementRegimeKinds.LocalFlight;
ship.SpatialState.Transit = null;
ship.SpatialState.DestinationNodeId = targetCelestial?.Id;
@@ -1691,7 +1691,7 @@ internal sealed class ShipAiService
subTask.ElapsedSeconds = 0f;
}
ship.SpatialState.SpaceLayer = SpaceLayerKinds.SystemSpace;
ship.SpatialState.SpaceLayer = SpaceLayerKind.SystemSpace;
ship.SpatialState.MovementRegime = MovementRegimeKinds.Warp;
ship.SpatialState.CurrentCelestialId = null;
ship.SpatialState.DestinationNodeId = targetCelestial.Id;
@@ -1748,7 +1748,7 @@ internal sealed class ShipAiService
subTask.ElapsedSeconds = 0f;
}
ship.SpatialState.SpaceLayer = SpaceLayerKinds.GalaxySpace;
ship.SpatialState.SpaceLayer = SpaceLayerKind.GalaxySpace;
ship.SpatialState.MovementRegime = MovementRegimeKinds.FtlTransit;
ship.SpatialState.CurrentCelestialId = null;
ship.SpatialState.DestinationNodeId = destinationNodeId;
@@ -1779,7 +1779,7 @@ internal sealed class ShipAiService
ship.SystemId = targetSystemId;
ship.SpatialState.CurrentSystemId = targetSystemId;
ship.SpatialState.Transit = null;
ship.SpatialState.SpaceLayer = SpaceLayerKinds.LocalSpace;
ship.SpatialState.SpaceLayer = SpaceLayerKind.LocalSpace;
ship.SpatialState.MovementRegime = MovementRegimeKinds.LocalFlight;
ship.SpatialState.CurrentCelestialId = targetCelestial?.Id;
ship.SpatialState.DestinationNodeId = targetCelestial?.Id;
@@ -1794,7 +1794,7 @@ internal sealed class ShipAiService
ship.SystemId = targetSystemId;
ship.SpatialState.CurrentSystemId = targetSystemId;
ship.SpatialState.Transit = null;
ship.SpatialState.SpaceLayer = SpaceLayerKinds.LocalSpace;
ship.SpatialState.SpaceLayer = SpaceLayerKind.LocalSpace;
ship.SpatialState.MovementRegime = MovementRegimeKinds.LocalFlight;
ship.SpatialState.CurrentCelestialId = targetCelestial?.Id;
ship.SpatialState.DestinationNodeId = targetCelestial?.Id;
@@ -2095,27 +2095,27 @@ internal sealed class ShipAiService
var source = stationsById.Values
.Where(station =>
{
if (station.Id == destination.Id || GetInventoryAmount(station.Inventory, order.ItemId) <= GetStationReserveFloor(world, station, order.ItemId) + 1f)
{
return false;
}
if (station.Id == destination.Id || GetInventoryAmount(station.Inventory, order.ItemId) <= GetStationReserveFloor(world, station, order.ItemId) + 1f)
{
return false;
}
if (!TryCheckSystemAllowed(world, policy, ship.FactionId, station.SystemId, "trade", out var sourceDeniedReason))
{
deniedReason ??= sourceDeniedReason;
return false;
}
if (!TryCheckSystemAllowed(world, policy, ship.FactionId, station.SystemId, "trade", out var sourceDeniedReason))
{
deniedReason ??= sourceDeniedReason;
return false;
}
if (!IsWithinSystemRange(world, originSystemId, station.SystemId, rangeBudget))
{
return false;
}
if (!IsWithinSystemRange(world, originSystemId, station.SystemId, rangeBudget))
{
return false;
}
return !requireKnownStations
|| ship.KnownStationIds.Count == 0
|| ship.KnownStationIds.Contains(station.Id)
|| (homeStation is not null && string.Equals(station.Id, homeStation.Id, StringComparison.Ordinal));
})
return !requireKnownStations
|| ship.KnownStationIds.Count == 0
|| ship.KnownStationIds.Contains(station.Id)
|| (homeStation is not null && string.Equals(station.Id, homeStation.Id, StringComparison.Ordinal));
})
.OrderByDescending(station => GetInventoryAmount(station.Inventory, order.ItemId) - GetStationReserveFloor(world, station, order.ItemId))
.ThenByDescending(station => homeStation is not null && station.Id == homeStation.Id ? 1 : 0)
.ThenBy(station => station.Id, StringComparer.Ordinal)

View File

@@ -578,7 +578,7 @@ internal sealed class SimulationProjectionService
ship.DockedStationId ?? "none",
ship.CommanderId ?? "none",
ship.PolicySetId ?? "none",
ship.SpatialState.SpaceLayer,
ship.SpatialState.SpaceLayer.ToContractValue(),
ship.SpatialState.CurrentCelestialId ?? "none",
ship.SpatialState.MovementRegime,
ship.SpatialState.DestinationNodeId ?? "none",
@@ -1872,7 +1872,7 @@ internal sealed class SimulationProjectionService
}
private static ShipSpatialStateSnapshot ToShipSpatialStateSnapshot(ShipSpatialStateRuntime state) => new(
state.SpaceLayer,
state.SpaceLayer.ToContractValue(),
state.CurrentSystemId,
state.CurrentCelestialId,
state.LocalPosition is null ? null : ToDto(state.LocalPosition.Value),

View File

@@ -97,7 +97,7 @@ internal sealed class StationLifecycleService
private static ShipSpatialStateRuntime CreateSpawnedShipSpatialState(StationRuntime station, Vector3 position) => new()
{
CurrentSystemId = station.SystemId,
SpaceLayer = SpaceLayerKinds.LocalSpace,
SpaceLayer = SpaceLayerKind.LocalSpace,
CurrentCelestialId = station.CelestialId,
LocalPosition = position,
SystemPosition = position,

View File

@@ -50,7 +50,7 @@ public sealed class WreckRuntime
public sealed class ShipSpatialStateRuntime
{
public string SpaceLayer { get; set; } = SpaceLayerKinds.LocalSpace;
public SpaceLayerKind SpaceLayer { get; set; } = SpaceLayerKind.LocalSpace;
public required string CurrentSystemId { get; set; }
public string? CurrentCelestialId { get; set; }
public Vector3? LocalPosition { get; set; }

View File

@@ -296,7 +296,7 @@ internal sealed class SpatialBuilder
return new ShipSpatialStateRuntime
{
CurrentSystemId = systemId,
SpaceLayer = SpaceLayerKinds.LocalSpace,
SpaceLayer = SpaceLayerKind.LocalSpace,
CurrentCelestialId = nearestCelestial?.Id,
LocalPosition = position,
SystemPosition = position,

View File

@@ -268,7 +268,7 @@ internal sealed class OrbitalStateUpdater
continue;
}
ship.SpatialState.SpaceLayer = SpaceLayerKinds.LocalSpace;
ship.SpatialState.SpaceLayer = SpaceLayerKind.LocalSpace;
ship.SpatialState.MovementRegime = MovementRegimeKinds.LocalFlight;
var nearestCelestial = world.Celestials
.Where(candidate => candidate.SystemId == ship.SystemId)