refactor(backend): simplify cargo kind loading

This commit is contained in:
2026-03-27 15:18:42 -04:00
parent e8fb033a01
commit 3237735b08
11 changed files with 35 additions and 82 deletions

View File

@@ -114,10 +114,8 @@ public sealed class ItemDefinition
public required string Id { get; set; }
public required string Name { get; set; }
public string Description { get; set; } = string.Empty;
public string Type { get; set; } = "material";
public string CargoKind { get; set; } = string.Empty;
[JsonIgnore]
public StorageKind? CargoStorageKind { get; set; }
public StorageKind? CargoKind { get; set; }
public float Volume { get; set; } = 1f;
public int Version { get; set; }
public string FactoryName { get; set; } = string.Empty;
@@ -130,7 +128,8 @@ public sealed class ItemDefinition
[JsonPropertyName("transport")]
public string Transport
{
set => CargoKind = value;
get => CargoKind?.ToDataValue() ?? string.Empty;
set => CargoKind = value.ToNullableStorageKind();
}
}
@@ -338,9 +337,14 @@ public sealed class ShipDefinition
public float FtlSpeed { get; set; }
public float SpoolTime { get; set; }
public float CargoCapacity { get; set; }
public string? CargoKind { get; set; }
[JsonIgnore]
public StorageKind? CargoStorageKind { get; set; }
public StorageKind? CargoKind { get; set; }
[JsonPropertyName("cargoKind")]
public string? SerializedCargoKind
{
get => CargoKind?.ToDataValue();
set => CargoKind = value.ToNullableStorageKind();
}
public required string Color { get; set; }
public required string HullColor { get; set; }
public float Size { get; set; }

View File

@@ -14,7 +14,7 @@ internal static class ProductionGraphBuilder
ItemId = item.Id,
Name = item.Name,
Group = item.Group,
CargoKind = item.CargoKind,
CargoKind = item.CargoKind?.ToDataValue() ?? string.Empty,
},
StringComparer.Ordinal);

View File

@@ -265,6 +265,9 @@ public static class SimulationEnumMappings
};
}
public static StorageKind? ToNullableStorageKind(this string? value) =>
string.IsNullOrWhiteSpace(value) ? null : value.ToStorageKind();
public static string ToContractValue(this SpatialNodeKind kind) => kind switch
{
SpatialNodeKind.Star => "star",

View File

@@ -46,7 +46,7 @@ internal static class SimulationRuntimeSupport
}
var remaining = station.Inventory
.Where(entry => world.ItemDefinitions.TryGetValue(entry.Key, out var definition) && definition.CargoStorageKind == storageKind)
.Where(entry => world.ItemDefinitions.TryGetValue(entry.Key, out var definition) && definition.CargoKind == storageKind)
.Sum(entry => entry.Value);
foreach (var (module, definition) in storageModules)
@@ -114,8 +114,8 @@ internal static class SimulationRuntimeSupport
internal static bool CanExtractNode(ShipRuntime ship, ResourceNodeRuntime node, SimulationWorld world) =>
HasShipCapabilities(ship.Definition, "mining")
&& world.ItemDefinitions.TryGetValue(node.ItemId, out var item)
&& item.CargoStorageKind is not null
&& item.CargoStorageKind == ship.Definition.CargoStorageKind;
&& item.CargoKind is not null
&& item.CargoKind == ship.Definition.CargoKind;
internal static bool CanBuildClaimBeacon(ShipRuntime ship) =>
string.Equals(ship.Definition.Kind, "military", StringComparison.Ordinal);
@@ -176,7 +176,7 @@ internal static class SimulationRuntimeSupport
return 0f;
}
var storageKind = itemDefinition.CargoStorageKind;
var storageKind = itemDefinition.CargoKind;
if (storageKind is null)
{
return 0f;
@@ -194,7 +194,7 @@ internal static class SimulationRuntimeSupport
}
var used = station.Inventory
.Where(entry => world.ItemDefinitions.TryGetValue(entry.Key, out var definition) && definition.CargoStorageKind == storageKind)
.Where(entry => world.ItemDefinitions.TryGetValue(entry.Key, out var definition) && definition.CargoKind == storageKind)
.Sum(entry => entry.Value);
var accepted = MathF.Min(amount, MathF.Max(0f, capacity - used));
if (accepted <= 0.01f)

View File

@@ -2619,7 +2619,7 @@ internal sealed class ShipAiService
{
if (world.ItemDefinitions.TryGetValue(itemId, out var itemDefinition))
{
var storageModule = GetStorageRequirement(world.ModuleDefinitions, itemDefinition.CargoStorageKind);
var storageModule = GetStorageRequirement(world.ModuleDefinitions, itemDefinition.CargoKind);
if (storageModule is not null && !modules.Contains(storageModule, StringComparer.Ordinal))
{
modules.Add(storageModule);

View File

@@ -801,7 +801,7 @@ internal sealed class SimulationProjectionService
.Select(storageKind => new StationStorageUsageSnapshot(
storageKind.ToDataValue(),
station.Inventory
.Where(entry => world.ItemDefinitions.TryGetValue(entry.Key, out var definition) && definition.CargoStorageKind == storageKind)
.Where(entry => world.ItemDefinitions.TryGetValue(entry.Key, out var definition) && definition.CargoKind == storageKind)
.Sum(entry => entry.Value),
GetStationStorageCapacity(world, station, storageKind)))
.Where(snapshot => snapshot.Capacity > 0.01f)

View File

@@ -176,7 +176,7 @@ internal sealed class InfrastructureSimulationService
}
var used = station.Inventory
.Where(entry => world.ItemDefinitions.TryGetValue(entry.Key, out var def) && def.CargoStorageKind == storageKind)
.Where(entry => world.ItemDefinitions.TryGetValue(entry.Key, out var def) && def.CargoKind == storageKind)
.Sum(entry => entry.Value);
if (used / capacity >= 0.65f)
{
@@ -195,7 +195,7 @@ internal sealed class InfrastructureSimulationService
continue;
}
if (GetStorageRequirement(world.ModuleDefinitions, itemDefinition.CargoStorageKind) is { } storageModuleId)
if (GetStorageRequirement(world.ModuleDefinitions, itemDefinition.CargoKind) is { } storageModuleId)
{
yield return storageModuleId;
}
@@ -210,7 +210,7 @@ internal sealed class InfrastructureSimulationService
continue;
}
if (GetStorageRequirement(world.ModuleDefinitions, itemDefinition.CargoStorageKind) is { } storageModuleId)
if (GetStorageRequirement(world.ModuleDefinitions, itemDefinition.CargoKind) is { } storageModuleId)
{
yield return storageModuleId;
}
@@ -325,7 +325,7 @@ internal sealed class InfrastructureSimulationService
var capacity = GetStationStorageCapacity(world, station, storageKind);
var used = station.Inventory
.Where(entry => world.ItemDefinitions.TryGetValue(entry.Key, out var def) && def.CargoStorageKind == storageKind)
.Where(entry => world.ItemDefinitions.TryGetValue(entry.Key, out var def) && def.CargoKind == storageKind)
.Sum(entry => entry.Value);
var utilization = capacity <= 0.01f ? 0f : used / capacity;
@@ -689,12 +689,12 @@ internal sealed class InfrastructureSimulationService
return recipe.Inputs.Any(input =>
world.ItemDefinitions.TryGetValue(input.ItemId, out var itemDefinition)
&& itemDefinition.CargoStorageKind == storageKind);
&& itemDefinition.CargoKind == storageKind);
}
private static bool CommodityUsesStorageClass(SimulationWorld world, string commodityId, StorageKind storageKind) =>
world.ItemDefinitions.TryGetValue(commodityId, out var itemDefinition)
&& itemDefinition.CargoStorageKind == storageKind;
&& itemDefinition.CargoKind == storageKind;
private static bool CanStationAcceptStationOutputSoon(SimulationWorld world, StationRuntime station, string itemId, float amount)
{
@@ -703,7 +703,7 @@ internal sealed class InfrastructureSimulationService
return false;
}
if (itemDefinition.CargoStorageKind is not { } storageKind)
if (itemDefinition.CargoKind is not { } storageKind)
{
return false;
}
@@ -715,7 +715,7 @@ internal sealed class InfrastructureSimulationService
}
var used = station.Inventory
.Where(entry => world.ItemDefinitions.TryGetValue(entry.Key, out var definition) && definition.CargoStorageKind == storageKind)
.Where(entry => world.ItemDefinitions.TryGetValue(entry.Key, out var definition) && definition.CargoKind == storageKind)
.Sum(entry => entry.Value);
return used + amount <= capacity * 0.95f;
}

View File

@@ -408,7 +408,7 @@ internal sealed class StationSimulationService
return false;
}
var storageKind = itemDefinition.CargoStorageKind;
var storageKind = itemDefinition.CargoKind;
if (storageKind is null)
{
return false;
@@ -426,7 +426,7 @@ internal sealed class StationSimulationService
}
var used = station.Inventory
.Where(entry => world.ItemDefinitions.TryGetValue(entry.Key, out var definition) && definition.CargoStorageKind == storageKind)
.Where(entry => world.ItemDefinitions.TryGetValue(entry.Key, out var definition) && definition.CargoKind == storageKind)
.Sum(entry => entry.Value);
return used + amount <= capacity + 0.001f;
}

View File

@@ -16,8 +16,8 @@ internal sealed class DataCatalogLoader(string dataRoot)
var authoredSystems = Read<List<SolarSystemDefinition>>("systems.json");
var scenario = Read<ScenarioDefinition>("scenario.json");
var modules = NormalizeModules(Read<List<ModuleDefinition>>("modules.json"));
var ships = NormalizeShips(Read<List<ShipDefinition>>("ships.json"));
var items = NormalizeItems(Read<List<ItemDefinition>>("items.json"));
var ships = Read<List<ShipDefinition>>("ships.json");
var items = Read<List<ItemDefinition>>("items.json");
var balance = Read<BalanceDefinition>("balance.json");
var recipes = BuildRecipes(items, ships, modules);
var moduleRecipes = BuildModuleRecipes(modules);
@@ -255,60 +255,6 @@ internal sealed class DataCatalogLoader(string dataRoot)
_ => 60,
};
private static List<ItemDefinition> NormalizeItems(List<ItemDefinition> items)
{
foreach (var item in items)
{
if (string.IsNullOrWhiteSpace(item.Type))
{
item.Type = string.IsNullOrWhiteSpace(item.Group) ? "material" : item.Group;
}
if (string.IsNullOrWhiteSpace(item.CargoKind))
{
item.CargoStorageKind = null;
}
else
{
try
{
item.CargoStorageKind = item.CargoKind.ToStorageKind();
item.CargoKind = item.CargoStorageKind.Value.ToDataValue();
}
catch (ArgumentOutOfRangeException exception)
{
throw new InvalidOperationException($"Item '{item.Id}' has unsupported cargo kind '{item.CargoKind}'.", exception);
}
}
}
return items;
}
private static List<ShipDefinition> NormalizeShips(List<ShipDefinition> ships)
{
foreach (var ship in ships)
{
if (string.IsNullOrWhiteSpace(ship.CargoKind))
{
ship.CargoStorageKind = null;
continue;
}
try
{
ship.CargoStorageKind = ship.CargoKind.ToStorageKind();
ship.CargoKind = ship.CargoStorageKind.Value.ToDataValue();
}
catch (ArgumentOutOfRangeException exception)
{
throw new InvalidOperationException($"Ship '{ship.Id}' has unsupported cargo kind '{ship.CargoKind}'.", exception);
}
}
return ships;
}
private static List<ModuleDefinition> NormalizeModules(List<ModuleDefinition> modules)
{
for (var index = 0; index < modules.Count; index += 1)

View File

@@ -218,7 +218,7 @@ internal sealed class WorldBuilder(
continue;
}
if (SpaceGame.Api.Shared.Runtime.SimulationRuntimeSupport.GetStorageRequirement(moduleDefinitions, itemDefinition.CargoStorageKind) is { } storageModuleId)
if (SpaceGame.Api.Shared.Runtime.SimulationRuntimeSupport.GetStorageRequirement(moduleDefinitions, itemDefinition.CargoKind) is { } storageModuleId)
{
yield return storageModuleId;
}

View File

@@ -241,7 +241,7 @@ internal sealed class WorldSeedingService
continue;
}
if (SpaceGame.Api.Shared.Runtime.SimulationRuntimeSupport.GetStorageRequirement(world.ModuleDefinitions, itemDefinition.CargoStorageKind) is { } storageModuleId)
if (SpaceGame.Api.Shared.Runtime.SimulationRuntimeSupport.GetStorageRequirement(world.ModuleDefinitions, itemDefinition.CargoKind) is { } storageModuleId)
{
yield return storageModuleId;
}