146 lines
5.0 KiB
C#
146 lines
5.0 KiB
C#
using SpaceGame.Api.Shared.Runtime;
|
|
|
|
namespace SpaceGame.Api.Universe.Scenario;
|
|
|
|
internal static class StarterStationLayoutResolver
|
|
{
|
|
internal static string ResolveDockModuleId(
|
|
string? factionId,
|
|
IReadOnlyDictionary<string, ModuleDefinition> moduleDefinitions) =>
|
|
SelectPreferredModule(
|
|
moduleDefinitions.Values.Where(definition => definition.ModuleType == ModuleType.DockArea),
|
|
factionId,
|
|
"starter dock module").Id;
|
|
|
|
internal static string ResolvePowerModuleId(
|
|
string? factionId,
|
|
IReadOnlyDictionary<string, ModuleDefinition> moduleDefinitions) =>
|
|
ResolveProducerModuleId("energycells", factionId, moduleDefinitions);
|
|
|
|
internal static string? ResolveObjectiveModuleId(
|
|
string? objective,
|
|
string? factionId,
|
|
IReadOnlyDictionary<string, ModuleDefinition> moduleDefinitions)
|
|
{
|
|
var targetWareId = ResolveObjectiveWareId(objective);
|
|
return targetWareId is null ? null : ResolveProducerModuleId(targetWareId, factionId, moduleDefinitions);
|
|
}
|
|
|
|
internal static IEnumerable<string> ResolveRequiredStorageModuleIds(
|
|
string moduleId,
|
|
string? factionId,
|
|
IReadOnlyDictionary<string, ModuleDefinition> moduleDefinitions,
|
|
IReadOnlyDictionary<string, ItemDefinition> itemDefinitions)
|
|
{
|
|
if (!moduleDefinitions.TryGetValue(moduleId, out var moduleDefinition))
|
|
{
|
|
throw new InvalidOperationException($"Module '{moduleId}' is not defined in static data.");
|
|
}
|
|
|
|
foreach (var wareId in moduleDefinition.BuildRecipes
|
|
.SelectMany(production => production.Wares.Select(ware => ware.ItemId))
|
|
.Concat(moduleDefinition.ProductItemIds)
|
|
.Distinct(StringComparer.Ordinal))
|
|
{
|
|
if (!itemDefinitions.TryGetValue(wareId, out var itemDefinition))
|
|
{
|
|
throw new InvalidOperationException($"Module '{moduleId}' references unknown ware '{wareId}'.");
|
|
}
|
|
|
|
if (itemDefinition.CargoKind is not { } storageKind)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
yield return ResolveStorageModuleId(storageKind, factionId, moduleDefinitions);
|
|
}
|
|
}
|
|
|
|
private static string? ResolveObjectiveWareId(string? objective) =>
|
|
StationSimulationService.NormalizeStationObjective(objective) switch
|
|
{
|
|
"power" => "energycells",
|
|
"refinery" => "refinedmetals",
|
|
"graphene" => "graphene",
|
|
"siliconwafers" => "siliconwafers",
|
|
"hullparts" => "hullparts",
|
|
"claytronics" => "claytronics",
|
|
"quantumtubes" => "quantumtubes",
|
|
"antimattercells" => "antimattercells",
|
|
"superfluidcoolant" => "superfluidcoolant",
|
|
"water" => "water",
|
|
_ => null,
|
|
};
|
|
|
|
private static string ResolveProducerModuleId(
|
|
string wareId,
|
|
string? factionId,
|
|
IReadOnlyDictionary<string, ModuleDefinition> moduleDefinitions) =>
|
|
SelectPreferredModule(
|
|
moduleDefinitions.Values
|
|
.OfType<ProductionModuleDefinition>()
|
|
.Where(definition => definition.ProductItemIds.Contains(wareId, StringComparer.Ordinal)),
|
|
factionId,
|
|
$"producer module for ware '{wareId}'").Id;
|
|
|
|
private static string ResolveStorageModuleId(
|
|
StorageKind storageKind,
|
|
string? factionId,
|
|
IReadOnlyDictionary<string, ModuleDefinition> moduleDefinitions) =>
|
|
SelectPreferredModule(
|
|
moduleDefinitions.Values
|
|
.OfType<StorageModuleDefinition>()
|
|
.Where(definition => definition.StorageKind == storageKind),
|
|
factionId,
|
|
$"storage module for cargo kind '{storageKind.ToDataValue()}'").Id;
|
|
|
|
private static T SelectPreferredModule<T>(
|
|
IEnumerable<T> candidates,
|
|
string? factionId,
|
|
string context)
|
|
where T : ModuleDefinition
|
|
{
|
|
var ordered = candidates
|
|
.OrderBy(definition => ComputeOwnerRank(definition, factionId))
|
|
.ThenBy(definition => ComputeModuleRank(definition))
|
|
.ThenBy(definition => definition.Id, StringComparer.Ordinal)
|
|
.ToList();
|
|
|
|
return ordered.FirstOrDefault()
|
|
?? throw new InvalidOperationException($"Unable to resolve {context}.");
|
|
}
|
|
|
|
private static int ComputeOwnerRank(ModuleDefinition definition, string? factionId)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(factionId))
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
return definition.Owners.Contains(factionId, StringComparer.Ordinal) ? 0 : 1;
|
|
}
|
|
|
|
private static int ComputeModuleRank(ModuleDefinition definition)
|
|
{
|
|
if (definition.ModuleType is ModuleType.DockArea or ModuleType.Storage)
|
|
{
|
|
if (definition.Id.Contains("_m_", StringComparison.Ordinal))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (definition.Id.Contains("_s_", StringComparison.Ordinal))
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
if (definition.Id.Contains("_l_", StringComparison.Ordinal))
|
|
{
|
|
return 2;
|
|
}
|
|
}
|
|
|
|
return 3;
|
|
}
|
|
}
|