Refactor world bootstrap and allow empty startup worlds

This commit is contained in:
2026-03-29 13:22:48 -04:00
parent 640e147ea8
commit 0bb72bee35
79 changed files with 173146 additions and 9235 deletions

View File

@@ -0,0 +1,111 @@
using SpaceGame.Api.Universe.Bootstrap;
namespace SpaceGame.Api.Universe.Scenario;
public sealed class ScenarioValidationService(IStaticDataProvider staticData)
{
public ScenarioDefinition CreateEmptyScenario(
WorldGenerationOptions worldGenerationOptions,
IReadOnlyList<SolarSystemDefinition> systems)
{
if (systems.Count == 0)
{
throw new InvalidOperationException("World generation produced no systems.");
}
return new ScenarioDefinition
{
WorldGeneration = worldGenerationOptions,
InitialStations = [],
ShipFormations = [],
PatrolRoutes = [],
};
}
public void Validate(
ScenarioDefinition scenario,
IReadOnlySet<string> availableSystemIds)
{
foreach (var station in scenario.InitialStations)
{
ValidateSystemExists(station.SystemId, $"station '{station.Label}' system", availableSystemIds);
ValidateFactionId(station.FactionId, $"station '{station.Label}'");
foreach (var moduleId in station.StartingModules)
{
ValidateModuleId(moduleId, $"station '{station.Label}' starting module");
}
}
foreach (var formation in scenario.ShipFormations)
{
ValidateSystemExists(formation.SystemId, $"ship formation '{formation.ShipId}' system", availableSystemIds);
ValidateFactionId(formation.FactionId, $"ship formation '{formation.ShipId}' in system '{formation.SystemId}'");
ValidateShipId(formation.ShipId, $"ship formation in system '{formation.SystemId}'");
foreach (var itemId in formation.StartingInventory.Keys)
{
ValidateItemId(itemId, $"ship formation '{formation.ShipId}' starting inventory");
}
}
foreach (var route in scenario.PatrolRoutes)
{
ValidateSystemExists(route.SystemId, "patrol route system", availableSystemIds);
}
}
private static string GetRequiredFactionId(string? factionId, string context)
{
if (!string.IsNullOrWhiteSpace(factionId))
{
return factionId;
}
throw new InvalidOperationException($"Scenario {context} is missing a factionId.");
}
private static void ValidateSystemExists(
string systemId,
string context,
IReadOnlySet<string> availableSystemIds)
{
if (!availableSystemIds.Contains(systemId))
{
throw new InvalidOperationException($"Scenario {context} references unknown generated system '{systemId}'.");
}
}
private void ValidateFactionId(string? factionId, string context)
{
var requiredFactionId = GetRequiredFactionId(factionId, context);
if (!staticData.FactionDefinitions.ContainsKey(requiredFactionId))
{
throw new InvalidOperationException($"Scenario {context} references unknown faction '{requiredFactionId}'.");
}
}
private void ValidateModuleId(string moduleId, string context)
{
if (!staticData.ModuleDefinitions.ContainsKey(moduleId))
{
throw new InvalidOperationException($"Scenario {context} references unknown module '{moduleId}'.");
}
}
private void ValidateShipId(string shipId, string context)
{
if (!staticData.ShipDefinitions.ContainsKey(shipId))
{
throw new InvalidOperationException($"Scenario {context} references unknown ship '{shipId}'.");
}
}
private void ValidateItemId(string itemId, string context)
{
if (!staticData.ItemDefinitions.ContainsKey(itemId))
{
throw new InvalidOperationException($"Scenario {context} references unknown item '{itemId}'.");
}
}
}