Complete universe model migration
This commit is contained in:
@@ -18,13 +18,13 @@ public sealed class ScenarioContentBuilder(
|
||||
scenario,
|
||||
topology.SystemsById,
|
||||
topology.SpatialLayout.SystemGraphs,
|
||||
topology.SpatialLayout.Celestials);
|
||||
topology.SpatialLayout.Anchors);
|
||||
|
||||
var patrolRoutes = BuildPatrolRoutes(scenario, topology.SystemsById);
|
||||
var ships = CreateShips(
|
||||
scenario,
|
||||
topology.SystemsById,
|
||||
topology.SpatialLayout.Celestials,
|
||||
topology.SpatialLayout.Anchors,
|
||||
patrolRoutes,
|
||||
stations);
|
||||
|
||||
@@ -35,7 +35,7 @@ public sealed class ScenarioContentBuilder(
|
||||
ScenarioDefinition scenario,
|
||||
IReadOnlyDictionary<string, SystemRuntime> systemsById,
|
||||
IReadOnlyDictionary<string, SystemSpatialGraph> systemGraphs,
|
||||
IReadOnlyCollection<CelestialRuntime> celestials)
|
||||
IReadOnlyCollection<AnchorRuntime> anchors)
|
||||
{
|
||||
var stations = new List<StationRuntime>();
|
||||
var stationIdCounter = 0;
|
||||
@@ -47,23 +47,27 @@ public sealed class ScenarioContentBuilder(
|
||||
throw new InvalidOperationException($"Scenario station '{plan.Label}' references unknown system '{plan.SystemId}'.");
|
||||
}
|
||||
|
||||
var placement = SpatialBuilder.ResolveStationPlacement(plan, system, systemGraphs[system.Definition.Id], celestials);
|
||||
var placement = SpatialBuilder.ResolveStationPlacement(plan, system, systemGraphs[system.Definition.Id], anchors);
|
||||
var station = new StationRuntime
|
||||
{
|
||||
Id = $"station-{++stationIdCounter}",
|
||||
SystemId = system.Definition.Id,
|
||||
AnchorId = placement.Anchor.Id,
|
||||
Label = plan.Label,
|
||||
Color = plan.Color,
|
||||
Objective = StationSimulationService.NormalizeStationObjective(plan.Objective),
|
||||
Position = placement.Position,
|
||||
Position = Vector3.Zero,
|
||||
FactionId = GetRequiredFactionId(plan.FactionId, $"station '{plan.Label}'"),
|
||||
CelestialId = placement.AnchorCelestial.Id,
|
||||
Health = 600f,
|
||||
MaxHealth = 600f,
|
||||
};
|
||||
|
||||
stations.Add(station);
|
||||
placement.AnchorCelestial.OccupyingStructureId = station.Id;
|
||||
placement.Anchor.OccupyingStructureId = station.Id;
|
||||
if (placement.Celestial is not null)
|
||||
{
|
||||
placement.Celestial.OccupyingStructureId = station.Id;
|
||||
}
|
||||
|
||||
var startingModules = BuildStartingModules(plan);
|
||||
foreach (var moduleId in startingModules)
|
||||
@@ -162,7 +166,7 @@ public sealed class ScenarioContentBuilder(
|
||||
private List<ShipRuntime> CreateShips(
|
||||
ScenarioDefinition scenario,
|
||||
IReadOnlyDictionary<string, SystemRuntime> systemsById,
|
||||
IReadOnlyCollection<CelestialRuntime> celestials,
|
||||
IReadOnlyCollection<AnchorRuntime> anchors,
|
||||
IReadOnlyDictionary<string, List<Vector3>> patrolRoutes,
|
||||
IReadOnlyCollection<StationRuntime> stations)
|
||||
{
|
||||
@@ -181,6 +185,8 @@ public sealed class ScenarioContentBuilder(
|
||||
var offset = new Vector3((index % 3) * 18f, balance.YPlane, (index / 3) * 18f);
|
||||
var position = Add(NormalizeScenarioPoint(systemsById[formation.SystemId], formation.Center), offset);
|
||||
var factionId = GetRequiredFactionId(formation.FactionId, $"ship formation '{formation.ShipId}' in system '{formation.SystemId}'");
|
||||
var spatialState = SpatialBuilder.CreateInitialShipSpatialState(formation.SystemId, position, anchors);
|
||||
var localPosition = spatialState.LocalPosition ?? Vector3.Zero;
|
||||
|
||||
ships.Add(new ShipRuntime
|
||||
{
|
||||
@@ -188,9 +194,9 @@ public sealed class ScenarioContentBuilder(
|
||||
SystemId = formation.SystemId,
|
||||
Definition = definition,
|
||||
FactionId = factionId,
|
||||
Position = position,
|
||||
TargetPosition = position,
|
||||
SpatialState = SpatialBuilder.CreateInitialShipSpatialState(formation.SystemId, position, celestials),
|
||||
Position = localPosition,
|
||||
TargetPosition = localPosition,
|
||||
SpatialState = spatialState,
|
||||
DefaultBehavior = CreateBehavior(
|
||||
definition,
|
||||
formation.SystemId,
|
||||
|
||||
@@ -2,8 +2,15 @@ using static SpaceGame.Api.Universe.Scenario.LoaderSupport;
|
||||
|
||||
namespace SpaceGame.Api.Universe.Scenario;
|
||||
|
||||
public sealed class SpatialBuilder(IBalanceService balance)
|
||||
public sealed class SpatialBuilder
|
||||
{
|
||||
internal static bool IsConstructibleAnchorKind(SpatialNodeKind kind) => kind is SpatialNodeKind.Planet or SpatialNodeKind.Moon or SpatialNodeKind.LagrangePoint;
|
||||
|
||||
internal static string? ResolveCompatibleCelestialId(AnchorRuntime? anchor) =>
|
||||
anchor is not null && string.Equals(anchor.SourceEntityKind, "celestial", StringComparison.Ordinal)
|
||||
? anchor.SourceEntityId
|
||||
: null;
|
||||
|
||||
internal ScenarioSpatialLayout BuildLayout(IReadOnlyList<SystemRuntime> systems)
|
||||
{
|
||||
var systemGraphs = systems.ToDictionary(
|
||||
@@ -11,6 +18,19 @@ public sealed class SpatialBuilder(IBalanceService balance)
|
||||
BuildSystemSpatialGraph,
|
||||
StringComparer.Ordinal);
|
||||
var celestials = systemGraphs.Values.SelectMany(graph => graph.Celestials).ToList();
|
||||
var anchors = celestials.Select(celestial => new AnchorRuntime
|
||||
{
|
||||
Id = celestial.Id,
|
||||
SystemId = celestial.SystemId,
|
||||
Kind = celestial.Kind,
|
||||
Position = celestial.Position,
|
||||
LocalSpaceRadius = celestial.LocalSpaceRadius,
|
||||
ParentAnchorId = celestial.ParentAnchorId,
|
||||
OrbitReferenceId = celestial.OrbitReferenceId,
|
||||
OccupyingStructureId = celestial.OccupyingStructureId,
|
||||
SourceEntityKind = "celestial",
|
||||
SourceEntityId = celestial.Id,
|
||||
}).ToList();
|
||||
var nodes = new List<ResourceNodeRuntime>();
|
||||
var nodeIdCounter = 0;
|
||||
|
||||
@@ -20,24 +40,43 @@ public sealed class SpatialBuilder(IBalanceService balance)
|
||||
foreach (var node in system.Definition.ResourceNodes)
|
||||
{
|
||||
var anchorCelestial = ResolveResourceNodeAnchor(systemGraph, node);
|
||||
var nodeId = $"node-{++nodeIdCounter}";
|
||||
var localPosition = ComputeResourceNodeLocalPosition(node);
|
||||
var anchorPosition = anchorCelestial is null
|
||||
? localPosition
|
||||
: Add(anchorCelestial.Position, localPosition);
|
||||
nodes.Add(new ResourceNodeRuntime
|
||||
{
|
||||
Id = $"node-{++nodeIdCounter}",
|
||||
Id = nodeId,
|
||||
AnchorId = nodeId,
|
||||
SystemId = system.Definition.Id,
|
||||
Position = ComputeResourceNodePosition(anchorCelestial, node, balance.YPlane),
|
||||
Position = localPosition,
|
||||
SourceKind = node.SourceKind,
|
||||
ItemId = node.ItemId,
|
||||
CelestialId = anchorCelestial?.Id,
|
||||
LocalSpaceRadius = LocalSpaceRadius,
|
||||
OrbitRadius = node.RadiusOffset,
|
||||
OrbitPhase = node.Angle,
|
||||
OrbitInclination = DegreesToRadians(node.InclinationDegrees),
|
||||
OreRemaining = node.OreAmount,
|
||||
MaxOre = node.OreAmount,
|
||||
});
|
||||
nodes[^1].Deposits.AddRange(BuildResourceDeposits(system.Definition.Id, nodeId, node, node.OreAmount));
|
||||
|
||||
anchors.Add(new AnchorRuntime
|
||||
{
|
||||
Id = nodeId,
|
||||
SystemId = system.Definition.Id,
|
||||
Kind = SpatialNodeKind.ResourceNode,
|
||||
Position = anchorPosition,
|
||||
LocalSpaceRadius = LocalSpaceRadius,
|
||||
ParentAnchorId = anchorCelestial?.Id,
|
||||
SourceEntityKind = "resource-node",
|
||||
SourceEntityId = nodeId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return new ScenarioSpatialLayout(systemGraphs, celestials, nodes);
|
||||
return new ScenarioSpatialLayout(systemGraphs, anchors, celestials, nodes);
|
||||
}
|
||||
|
||||
private static SystemSpatialGraph BuildSystemSpatialGraph(SystemRuntime system)
|
||||
@@ -70,7 +109,7 @@ public sealed class SpatialBuilder(IBalanceService balance)
|
||||
kind: SpatialNodeKind.Planet,
|
||||
position: planetPosition,
|
||||
localSpaceRadius: LocalSpaceRadius,
|
||||
parentNodeId: primaryStarNodeId);
|
||||
parentAnchorId: primaryStarNodeId);
|
||||
|
||||
var lagrangeNodes = new Dictionary<string, CelestialRuntime>(StringComparer.Ordinal);
|
||||
foreach (var point in EnumeratePlanetLagrangePoints(planetPosition, planet))
|
||||
@@ -82,7 +121,7 @@ public sealed class SpatialBuilder(IBalanceService balance)
|
||||
kind: SpatialNodeKind.LagrangePoint,
|
||||
position: point.Position,
|
||||
localSpaceRadius: LocalSpaceRadius,
|
||||
parentNodeId: planetCelestial.Id,
|
||||
parentAnchorId: planetCelestial.Id,
|
||||
orbitReferenceId: point.Designation);
|
||||
lagrangeNodes[point.Designation] = lagrangeCelestial;
|
||||
}
|
||||
@@ -100,7 +139,7 @@ public sealed class SpatialBuilder(IBalanceService balance)
|
||||
kind: SpatialNodeKind.Moon,
|
||||
position: moonPosition,
|
||||
localSpaceRadius: LocalSpaceRadius,
|
||||
parentNodeId: planetCelestial.Id);
|
||||
parentAnchorId: planetCelestial.Id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,7 +153,7 @@ public sealed class SpatialBuilder(IBalanceService balance)
|
||||
SpatialNodeKind kind,
|
||||
Vector3 position,
|
||||
float localSpaceRadius,
|
||||
string? parentNodeId = null,
|
||||
string? parentAnchorId = null,
|
||||
string? orbitReferenceId = null)
|
||||
{
|
||||
var celestial = new CelestialRuntime
|
||||
@@ -124,7 +163,7 @@ public sealed class SpatialBuilder(IBalanceService balance)
|
||||
Kind = kind,
|
||||
Position = position,
|
||||
LocalSpaceRadius = localSpaceRadius,
|
||||
ParentNodeId = parentNodeId,
|
||||
ParentAnchorId = parentAnchorId,
|
||||
OrbitReferenceId = orbitReferenceId,
|
||||
};
|
||||
|
||||
@@ -183,7 +222,7 @@ public sealed class SpatialBuilder(IBalanceService balance)
|
||||
InitialStationDefinition plan,
|
||||
SystemRuntime system,
|
||||
SystemSpatialGraph graph,
|
||||
IReadOnlyCollection<CelestialRuntime> existingCelestials)
|
||||
IReadOnlyCollection<AnchorRuntime> existingAnchors)
|
||||
{
|
||||
if (plan.PlanetIndex is int planetIndex &&
|
||||
graph.LagrangeNodesByPlanetIndex.TryGetValue(planetIndex, out var lagrangeNodes))
|
||||
@@ -191,28 +230,32 @@ public sealed class SpatialBuilder(IBalanceService balance)
|
||||
var designation = ResolveLagrangeDesignation(plan.LagrangeSide);
|
||||
if (lagrangeNodes.TryGetValue(designation, out var lagrangeCelestial))
|
||||
{
|
||||
return new StationPlacement(lagrangeCelestial, lagrangeCelestial.Position);
|
||||
var lagrangeAnchor = existingAnchors.First(anchor => string.Equals(anchor.Id, lagrangeCelestial.Id, StringComparison.Ordinal));
|
||||
return new StationPlacement(lagrangeAnchor, lagrangeCelestial, lagrangeAnchor.Position);
|
||||
}
|
||||
}
|
||||
|
||||
if (plan.Position is { Length: 3 })
|
||||
{
|
||||
var targetPosition = NormalizeScenarioPoint(system, plan.Position);
|
||||
var preferredCelestial = existingCelestials
|
||||
.Where(c => c.SystemId == system.Definition.Id && c.Kind == SpatialNodeKind.LagrangePoint)
|
||||
.OrderBy(c => c.Position.DistanceTo(targetPosition))
|
||||
var preferredAnchor = existingAnchors
|
||||
.Where(anchor => anchor.SystemId == system.Definition.Id && anchor.Kind == SpatialNodeKind.LagrangePoint)
|
||||
.OrderBy(anchor => anchor.Position.DistanceTo(targetPosition))
|
||||
.FirstOrDefault()
|
||||
?? existingCelestials
|
||||
.Where(c => c.SystemId == system.Definition.Id)
|
||||
.OrderBy(c => c.Position.DistanceTo(targetPosition))
|
||||
?? existingAnchors
|
||||
.Where(anchor => anchor.SystemId == system.Definition.Id && IsConstructibleAnchorKind(anchor.Kind))
|
||||
.OrderBy(anchor => anchor.Position.DistanceTo(targetPosition))
|
||||
.First();
|
||||
return new StationPlacement(preferredCelestial, preferredCelestial.Position);
|
||||
var preferredCelestial = graph.Celestials.FirstOrDefault(c => string.Equals(c.Id, ResolveCompatibleCelestialId(preferredAnchor), StringComparison.Ordinal));
|
||||
return new StationPlacement(preferredAnchor, preferredCelestial, preferredAnchor.Position);
|
||||
}
|
||||
|
||||
var fallbackCelestial = graph.Celestials
|
||||
.FirstOrDefault(c => c.Kind == SpatialNodeKind.LagrangePoint && string.IsNullOrEmpty(c.OccupyingStructureId))
|
||||
?? graph.Celestials.First(c => c.Kind == SpatialNodeKind.Planet);
|
||||
return new StationPlacement(fallbackCelestial, fallbackCelestial.Position);
|
||||
var fallbackAnchor = existingAnchors
|
||||
.Where(anchor => anchor.SystemId == system.Definition.Id)
|
||||
.FirstOrDefault(anchor => anchor.Kind == SpatialNodeKind.LagrangePoint && string.IsNullOrEmpty(anchor.OccupyingStructureId))
|
||||
?? existingAnchors.First(anchor => anchor.SystemId == system.Definition.Id && anchor.Kind == SpatialNodeKind.Planet);
|
||||
var fallbackCelestial = graph.Celestials.FirstOrDefault(c => string.Equals(c.Id, ResolveCompatibleCelestialId(fallbackAnchor), StringComparison.Ordinal));
|
||||
return new StationPlacement(fallbackAnchor, fallbackCelestial, fallbackAnchor.Position);
|
||||
}
|
||||
|
||||
private static string ResolveLagrangeDesignation(int? lagrangeSide) => lagrangeSide switch
|
||||
@@ -256,20 +299,80 @@ public sealed class SpatialBuilder(IBalanceService balance)
|
||||
return graph.Celestials.FirstOrDefault(c => c.Id == planetNodeId);
|
||||
}
|
||||
|
||||
private static Vector3 ComputeResourceNodePosition(CelestialRuntime? anchorCelestial, ResourceNodeDefinition definition, float yPlane)
|
||||
private static Vector3 ComputeResourceNodeLocalPosition(ResourceNodeDefinition definition)
|
||||
{
|
||||
var verticalOffset = MathF.Sin(DegreesToRadians(definition.InclinationDegrees)) * MathF.Min(definition.RadiusOffset * 0.04f, 25000f);
|
||||
var offset = new Vector3(
|
||||
return new Vector3(
|
||||
MathF.Cos(definition.Angle) * definition.RadiusOffset,
|
||||
verticalOffset,
|
||||
MathF.Sin(definition.Angle) * definition.RadiusOffset);
|
||||
}
|
||||
|
||||
if (anchorCelestial is null)
|
||||
private static IReadOnlyList<ResourceDepositRuntime> BuildResourceDeposits(
|
||||
string systemId,
|
||||
string nodeId,
|
||||
ResourceNodeDefinition definition,
|
||||
float oreAmount)
|
||||
{
|
||||
var depositCount = Math.Clamp((int)MathF.Round(MathF.Sqrt(MathF.Max(oreAmount, 1f)) / 18f), 4, 12);
|
||||
var deposits = new List<ResourceDepositRuntime>(depositCount);
|
||||
var weightTotal = 0f;
|
||||
var weights = new float[depositCount];
|
||||
for (var index = 0; index < depositCount; index += 1)
|
||||
{
|
||||
return new Vector3(offset.X, yPlane + offset.Y, offset.Z);
|
||||
var weight = 0.8f + (Hash01(systemId, nodeId, $"weight-{index}") * 1.6f);
|
||||
weights[index] = weight;
|
||||
weightTotal += weight;
|
||||
}
|
||||
|
||||
return Add(anchorCelestial.Position, offset);
|
||||
var scatterRadius = MathF.Max(140f, LocalSpaceRadius * 0.58f);
|
||||
for (var index = 0; index < depositCount; index += 1)
|
||||
{
|
||||
var angle = Hash01(systemId, nodeId, $"angle-{index}") * MathF.PI * 2f;
|
||||
var radiusFactor = 0.22f + (Hash01(systemId, nodeId, $"radius-{index}") * 0.74f);
|
||||
var radius = scatterRadius * MathF.Sqrt(radiusFactor);
|
||||
var vertical = (Hash01(systemId, nodeId, $"vertical-{index}") - 0.5f) * MathF.Max(60f, scatterRadius * 0.14f);
|
||||
var localPosition = new Vector3(
|
||||
MathF.Cos(angle) * radius,
|
||||
vertical,
|
||||
MathF.Sin(angle) * radius);
|
||||
var maxOre = oreAmount * (weights[index] / MathF.Max(weightTotal, 0.001f));
|
||||
deposits.Add(new ResourceDepositRuntime
|
||||
{
|
||||
Id = $"{nodeId}-deposit-{index + 1}",
|
||||
NodeId = nodeId,
|
||||
AnchorId = nodeId,
|
||||
Position = localPosition,
|
||||
OreRemaining = maxOre,
|
||||
MaxOre = maxOre,
|
||||
});
|
||||
}
|
||||
|
||||
return deposits;
|
||||
}
|
||||
|
||||
private static float Hash01(string systemId, string nodeId, string salt)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
var hash = 17;
|
||||
foreach (var character in systemId)
|
||||
{
|
||||
hash = (hash * 31) + character;
|
||||
}
|
||||
|
||||
foreach (var character in nodeId)
|
||||
{
|
||||
hash = (hash * 31) + character;
|
||||
}
|
||||
|
||||
foreach (var character in salt)
|
||||
{
|
||||
hash = (hash * 31) + character;
|
||||
}
|
||||
|
||||
return (hash & 0x7fffffff) / (float)int.MaxValue;
|
||||
}
|
||||
}
|
||||
|
||||
private static Vector3 ComputePlanetPosition(PlanetDefinition planet)
|
||||
@@ -286,19 +389,22 @@ public sealed class SpatialBuilder(IBalanceService balance)
|
||||
return Add(planetPosition, local);
|
||||
}
|
||||
|
||||
internal static ShipSpatialStateRuntime CreateInitialShipSpatialState(string systemId, Vector3 position, IReadOnlyCollection<CelestialRuntime> celestials)
|
||||
internal static ShipSpatialStateRuntime CreateInitialShipSpatialState(string systemId, Vector3 position, IReadOnlyCollection<AnchorRuntime> anchors)
|
||||
{
|
||||
var nearestCelestial = celestials
|
||||
.Where(c => c.SystemId == systemId)
|
||||
.OrderBy(c => c.Position.DistanceTo(position))
|
||||
var nearestAnchor = anchors
|
||||
.Where(anchor => anchor.SystemId == systemId)
|
||||
.OrderBy(anchor => anchor.Position.DistanceTo(position))
|
||||
.FirstOrDefault();
|
||||
var localPosition = nearestAnchor is null
|
||||
? position
|
||||
: position.Subtract(nearestAnchor.Position);
|
||||
|
||||
return new ShipSpatialStateRuntime
|
||||
{
|
||||
CurrentSystemId = systemId,
|
||||
SpaceLayer = SpaceLayerKind.LocalSpace,
|
||||
CurrentCelestialId = nearestCelestial?.Id,
|
||||
LocalPosition = position,
|
||||
CurrentAnchorId = nearestAnchor?.Id,
|
||||
LocalPosition = localPosition,
|
||||
SystemPosition = position,
|
||||
MovementRegime = MovementRegimeKind.LocalFlight,
|
||||
};
|
||||
@@ -307,6 +413,7 @@ public sealed class SpatialBuilder(IBalanceService balance)
|
||||
|
||||
public sealed record ScenarioSpatialLayout(
|
||||
IReadOnlyDictionary<string, SystemSpatialGraph> SystemGraphs,
|
||||
List<AnchorRuntime> Anchors,
|
||||
List<CelestialRuntime> Celestials,
|
||||
List<ResourceNodeRuntime> Nodes);
|
||||
|
||||
@@ -317,4 +424,4 @@ public sealed record SystemSpatialGraph(
|
||||
|
||||
internal sealed record LagrangePointPlacement(string Designation, Vector3 Position);
|
||||
|
||||
internal sealed record StationPlacement(CelestialRuntime AnchorCelestial, Vector3 Position);
|
||||
internal sealed record StationPlacement(AnchorRuntime Anchor, CelestialRuntime? Celestial, Vector3 Position);
|
||||
|
||||
@@ -18,13 +18,14 @@ public sealed class WorldRuntimeAssembler(
|
||||
var policies = seedingService.CreatePolicies(factions);
|
||||
var commanders = seedingService.CreateCommanders(factions, content.Stations, content.Ships);
|
||||
var nowUtc = DateTimeOffset.UtcNow;
|
||||
var claims = seedingService.CreateClaims(content.Stations, topology.SpatialLayout.Celestials, nowUtc);
|
||||
var claims = seedingService.CreateClaims(content.Stations, topology.SpatialLayout.Anchors, nowUtc);
|
||||
|
||||
var world = new SimulationWorld
|
||||
{
|
||||
Label = "Split Viewer / Simulation World",
|
||||
Seed = worldGenerationOptions.Seed,
|
||||
Systems = topology.SystemRuntimes.ToList(),
|
||||
Anchors = topology.SpatialLayout.Anchors,
|
||||
Celestials = topology.SpatialLayout.Celestials,
|
||||
Nodes = topology.SpatialLayout.Nodes,
|
||||
Wrecks = [],
|
||||
|
||||
@@ -74,27 +74,27 @@ public sealed class WorldSeedingService(IStaticDataProvider staticData)
|
||||
|
||||
internal List<ClaimRuntime> CreateClaims(
|
||||
IReadOnlyCollection<StationRuntime> stations,
|
||||
IReadOnlyCollection<CelestialRuntime> celestials,
|
||||
IReadOnlyCollection<AnchorRuntime> anchors,
|
||||
DateTimeOffset nowUtc)
|
||||
{
|
||||
var stationsByCelestialId = stations
|
||||
.Where(station => station.CelestialId is not null)
|
||||
.ToDictionary(station => station.CelestialId!, StringComparer.Ordinal);
|
||||
var stationsByAnchorId = stations
|
||||
.Where(station => !string.IsNullOrWhiteSpace(station.AnchorId))
|
||||
.ToDictionary(station => station.AnchorId!, StringComparer.Ordinal);
|
||||
var claims = new List<ClaimRuntime>();
|
||||
|
||||
foreach (var celestial in celestials.Where(c => c.Kind == SpatialNodeKind.LagrangePoint))
|
||||
foreach (var anchor in anchors.Where(candidate => candidate.Kind == SpatialNodeKind.LagrangePoint))
|
||||
{
|
||||
if (!stationsByCelestialId.TryGetValue(celestial.Id, out var station))
|
||||
if (!stationsByAnchorId.TryGetValue(anchor.Id, out var station))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
claims.Add(new ClaimRuntime
|
||||
{
|
||||
Id = $"claim-{celestial.Id}",
|
||||
Id = $"claim-{anchor.Id}",
|
||||
FactionId = station.FactionId,
|
||||
SystemId = celestial.SystemId,
|
||||
CelestialId = celestial.Id,
|
||||
SystemId = anchor.SystemId,
|
||||
AnchorId = anchor.Id,
|
||||
PlacedAtUtc = nowUtc,
|
||||
ActivatesAtUtc = nowUtc.AddSeconds(8),
|
||||
State = ClaimStateKinds.Activating,
|
||||
@@ -119,12 +119,12 @@ public sealed class WorldSeedingService(IStaticDataProvider staticData)
|
||||
}
|
||||
|
||||
var moduleId = InfrastructureSimulationService.GetNextStationModuleToBuild(station, world);
|
||||
if (moduleId is null || station.CelestialId is null)
|
||||
if (moduleId is null || station.AnchorId is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var claim = world.Claims.FirstOrDefault(candidate => candidate.CelestialId == station.CelestialId);
|
||||
var claim = world.Claims.FirstOrDefault(candidate => string.Equals(candidate.AnchorId, station.AnchorId, StringComparison.Ordinal));
|
||||
if (claim is null || !world.ModuleRecipes.TryGetValue(moduleId, out var recipe))
|
||||
{
|
||||
continue;
|
||||
@@ -135,7 +135,7 @@ public sealed class WorldSeedingService(IStaticDataProvider staticData)
|
||||
Id = $"site-{station.Id}",
|
||||
FactionId = station.FactionId,
|
||||
SystemId = station.SystemId,
|
||||
CelestialId = station.CelestialId,
|
||||
AnchorId = station.AnchorId,
|
||||
TargetKind = "station-module",
|
||||
TargetDefinitionId = "station",
|
||||
BlueprintId = moduleId,
|
||||
|
||||
Reference in New Issue
Block a user