595 lines
18 KiB
C#
595 lines
18 KiB
C#
using System.Diagnostics.CodeAnalysis;
|
|
using System.Text.Json.Serialization;
|
|
using SpaceGame.Api.Shared.Runtime;
|
|
using SpaceGame.Api.Shared.Runtime;
|
|
using SpaceGame.Api.Universe.Simulation;
|
|
|
|
namespace SpaceGame.Api.Definitions;
|
|
|
|
public sealed class ConstructionDefinition
|
|
{
|
|
public string? RecipeId { get; set; }
|
|
public string FacilityCategory { get; set; } = "station";
|
|
public List<string> RequiredModules { get; set; } = [];
|
|
public List<RecipeInputDefinition> Requirements { get; set; } = [];
|
|
public float CycleTime { get; set; }
|
|
public float BatchSize { get; set; } = 1f;
|
|
public float ProductsPerHour { get; set; }
|
|
public float MaxEfficiency { get; set; } = 1f;
|
|
public int Priority { get; set; }
|
|
}
|
|
|
|
public sealed class ItemPriceDefinition
|
|
{
|
|
public float Min { get; set; }
|
|
public float Max { get; set; }
|
|
public float Avg { get; set; }
|
|
}
|
|
|
|
public sealed class ItemEffectDefinition
|
|
{
|
|
public required string Type { get; set; }
|
|
public float Product { get; set; }
|
|
}
|
|
|
|
public sealed class ItemProductionDefinition
|
|
{
|
|
public float Time { get; set; }
|
|
public float Amount { get; set; }
|
|
public string Method { get; set; } = "default";
|
|
public string Name { get; set; } = "Universal";
|
|
public List<RecipeInputDefinition> Wares { get; set; } = [];
|
|
public List<ItemEffectDefinition> Effects { get; set; } = [];
|
|
}
|
|
|
|
public sealed class StarDefinition
|
|
{
|
|
public string Kind { get; set; } = "main-sequence";
|
|
public required string Color { get; set; }
|
|
public required string Glow { get; set; }
|
|
public float Size { get; set; }
|
|
public float OrbitRadius { get; set; }
|
|
public float OrbitSpeed { get; set; }
|
|
public float OrbitPhaseAtEpoch { get; set; }
|
|
}
|
|
|
|
public sealed class MoonDefinition
|
|
{
|
|
public required string Label { get; set; }
|
|
public float Size { get; set; }
|
|
public required string Color { get; set; }
|
|
public float OrbitRadius { get; set; }
|
|
public float OrbitSpeed { get; set; }
|
|
public float OrbitPhaseAtEpoch { get; set; }
|
|
public float OrbitInclination { get; set; }
|
|
public float OrbitLongitudeOfAscendingNode { get; set; }
|
|
}
|
|
|
|
public sealed class SolarSystemDefinition
|
|
{
|
|
public required string Id { get; set; }
|
|
public required string Label { get; set; }
|
|
public required float[] Position { get; set; }
|
|
public required List<StarDefinition> Stars { get; set; }
|
|
public required AsteroidFieldDefinition AsteroidField { get; set; }
|
|
public required List<ResourceNodeDefinition> ResourceNodes { get; set; }
|
|
public required List<PlanetDefinition> Planets { get; set; }
|
|
}
|
|
|
|
public sealed class RaceDefinition
|
|
{
|
|
public required string Id { get; set; }
|
|
public required string Name { get; set; }
|
|
public string Description { get; set; } = string.Empty;
|
|
public string Icon { get; set; } = string.Empty;
|
|
[JsonIgnore]
|
|
public string Label => Name;
|
|
}
|
|
|
|
public sealed class FactionDefinition
|
|
{
|
|
public required string Id { get; set; }
|
|
public int Version { get; set; }
|
|
public required string Name { get; set; }
|
|
public string Description { get; set; } = string.Empty;
|
|
public string Icon { get; set; } = string.Empty;
|
|
public string? Race { get; set; }
|
|
public List<FactionLicenseDefinition> Licenses { get; set; } = [];
|
|
[JsonIgnore]
|
|
public string Label => Name;
|
|
[JsonIgnore]
|
|
public string? RaceId => Race;
|
|
}
|
|
|
|
public sealed class FactionLicenseDefinition
|
|
{
|
|
public required string Type { get; set; }
|
|
public string Name { get; set; } = string.Empty;
|
|
public string Icon { get; set; } = string.Empty;
|
|
public float Price { get; set; }
|
|
}
|
|
|
|
public sealed class AsteroidFieldDefinition
|
|
{
|
|
public int DecorationCount { get; set; }
|
|
public float RadiusOffset { get; set; }
|
|
public float RadiusVariance { get; set; }
|
|
public float HeightVariance { get; set; }
|
|
}
|
|
|
|
public sealed class ResourceNodeDefinition
|
|
{
|
|
public string SourceKind { get; set; } = "local-space";
|
|
public string? AnchorReference { get; set; }
|
|
public float Angle { get; set; }
|
|
public float RadiusOffset { get; set; }
|
|
public float InclinationDegrees { get; set; }
|
|
public int? AnchorPlanetIndex { get; set; }
|
|
public int? AnchorMoonIndex { get; set; }
|
|
public float OreAmount { get; set; }
|
|
public required string ItemId { get; set; }
|
|
public int ShardCount { get; set; }
|
|
}
|
|
|
|
public sealed class ItemDefinition
|
|
{
|
|
public required string Id { get; set; }
|
|
public required string Name { get; set; }
|
|
public string Description { get; set; } = string.Empty;
|
|
[JsonIgnore]
|
|
public StorageKind? CargoKind { get; set; }
|
|
public float Volume { get; set; } = 1f;
|
|
public int Version { get; set; }
|
|
public string FactoryName { get; set; } = string.Empty;
|
|
public string Icon { get; set; } = string.Empty;
|
|
public string Group { get; set; } = string.Empty;
|
|
public ItemPriceDefinition? Price { get; set; }
|
|
public List<string> Illegal { get; set; } = [];
|
|
public List<ItemProductionDefinition> Production { get; set; } = [];
|
|
public ConstructionDefinition? Construction { get; set; }
|
|
[JsonPropertyName("transport")]
|
|
public string Transport
|
|
{
|
|
get => CargoKind?.ToDataValue() ?? string.Empty;
|
|
set => CargoKind = value.ToNullableStorageKind();
|
|
}
|
|
}
|
|
|
|
public sealed class RecipeOutputDefinition
|
|
{
|
|
public required string ItemId { get; set; }
|
|
public float Amount { get; set; }
|
|
}
|
|
|
|
public sealed class RecipeInputDefinition
|
|
{
|
|
public string ItemId { get; set; } = string.Empty;
|
|
public float Amount { get; set; }
|
|
[JsonPropertyName("ware")]
|
|
public string Ware
|
|
{
|
|
set => ItemId = value;
|
|
}
|
|
}
|
|
|
|
public sealed class ModuleDockDefinition
|
|
{
|
|
public int Capacity { get; set; }
|
|
public required string Size { get; set; }
|
|
}
|
|
|
|
public sealed class ModuleCargoDefinition
|
|
{
|
|
public float Max { get; set; }
|
|
public required string Type { get; set; }
|
|
}
|
|
|
|
public sealed class ModuleWorkforceDefinition
|
|
{
|
|
[JsonPropertyName("capacity")]
|
|
public float SupportedPopulation { get; set; }
|
|
|
|
[JsonPropertyName("max")]
|
|
public float RequiredWorkforce { get; set; }
|
|
|
|
public string Race { get; set; } = string.Empty;
|
|
}
|
|
|
|
public sealed class ModuleMountDefinition
|
|
{
|
|
public required string Group { get; set; }
|
|
public required string Size { get; set; }
|
|
public bool Hittable { get; set; }
|
|
public List<string> Types { get; set; } = [];
|
|
}
|
|
|
|
public sealed class ModuleBuildRecipeDefinition
|
|
{
|
|
public float Time { get; set; }
|
|
public float Amount { get; set; }
|
|
public string Method { get; set; } = "default";
|
|
public string Name { get; set; } = "Universal";
|
|
public List<RecipeInputDefinition> Wares { get; set; } = [];
|
|
}
|
|
|
|
public class ModuleDefinition
|
|
{
|
|
public ModuleDefinition()
|
|
{
|
|
}
|
|
|
|
[SetsRequiredMembers]
|
|
protected ModuleDefinition(ModuleDefinition source)
|
|
{
|
|
Id = source.Id;
|
|
Name = source.Name;
|
|
Description = source.Description;
|
|
Type = source.Type;
|
|
ModuleType = source.ModuleType;
|
|
ProductIds = [.. source.ProductIds];
|
|
Radius = source.Radius;
|
|
Hull = source.Hull;
|
|
Version = source.Version;
|
|
Macro = source.Macro;
|
|
MakerRace = source.MakerRace;
|
|
ExplosionDamage = source.ExplosionDamage;
|
|
Price = source.Price;
|
|
Owners = [.. source.Owners];
|
|
Cargo = source.Cargo;
|
|
SerializedWorkforce = source.SerializedWorkforce;
|
|
Docks = [.. source.Docks];
|
|
Shields = [.. source.Shields];
|
|
Turrets = [.. source.Turrets];
|
|
BuildRecipes = [.. source.BuildRecipes];
|
|
}
|
|
|
|
public required string Id { get; set; }
|
|
public required string Name { get; set; }
|
|
public string Description { get; set; } = string.Empty;
|
|
public required string Type { get; set; }
|
|
[JsonIgnore]
|
|
public ModuleType ModuleType { get; set; }
|
|
[JsonPropertyName("product")]
|
|
public List<string> ProductIds { get; set; } = [];
|
|
[JsonIgnore]
|
|
public virtual IReadOnlyList<string> ProductItemIds => [];
|
|
public float Radius { get; set; } = 12f;
|
|
public float Hull { get; set; } = 100f;
|
|
public int Version { get; set; }
|
|
public string Macro { get; set; } = string.Empty;
|
|
public string MakerRace { get; set; } = string.Empty;
|
|
public int ExplosionDamage { get; set; }
|
|
public ItemPriceDefinition? Price { get; set; }
|
|
public List<string> Owners { get; set; } = [];
|
|
public ModuleCargoDefinition? Cargo { get; set; }
|
|
[JsonPropertyName("workForce")]
|
|
public ModuleWorkforceDefinition? SerializedWorkforce { get; set; }
|
|
public List<ModuleDockDefinition> Docks { get; set; } = [];
|
|
public List<ModuleMountDefinition> Shields { get; set; } = [];
|
|
public List<ModuleMountDefinition> Turrets { get; set; } = [];
|
|
[JsonPropertyName("production")]
|
|
public List<ModuleBuildRecipeDefinition> BuildRecipes { get; set; } = [];
|
|
}
|
|
|
|
public abstract class ProductionLaneModuleDefinition : ModuleDefinition
|
|
{
|
|
[SetsRequiredMembers]
|
|
protected ProductionLaneModuleDefinition(ModuleDefinition source, float requiredWorkforce)
|
|
: base(source)
|
|
{
|
|
RequiredWorkforce = requiredWorkforce;
|
|
}
|
|
|
|
public float RequiredWorkforce { get; init; }
|
|
}
|
|
|
|
public sealed class ProductionModuleDefinition : ProductionLaneModuleDefinition
|
|
{
|
|
[SetsRequiredMembers]
|
|
internal ProductionModuleDefinition(ModuleDefinition source, float requiredWorkforce)
|
|
: base(source, requiredWorkforce)
|
|
{
|
|
ProductItemIds = [.. source.ProductIds];
|
|
}
|
|
|
|
public override IReadOnlyList<string> ProductItemIds { get; } = [];
|
|
}
|
|
|
|
public sealed class BuildModuleDefinition : ProductionLaneModuleDefinition
|
|
{
|
|
[SetsRequiredMembers]
|
|
internal BuildModuleDefinition(ModuleDefinition source, float requiredWorkforce)
|
|
: base(source, requiredWorkforce)
|
|
{
|
|
}
|
|
}
|
|
|
|
public sealed class HabitationModuleDefinition : ModuleDefinition
|
|
{
|
|
[SetsRequiredMembers]
|
|
internal HabitationModuleDefinition(ModuleDefinition source, float supportedPopulation)
|
|
: base(source)
|
|
{
|
|
SupportedPopulation = supportedPopulation;
|
|
}
|
|
|
|
public float SupportedPopulation { get; init; }
|
|
}
|
|
|
|
public sealed class StorageModuleDefinition : ModuleDefinition
|
|
{
|
|
[SetsRequiredMembers]
|
|
internal StorageModuleDefinition(ModuleDefinition source, StorageKind storageKind, float storageCapacity)
|
|
: base(source)
|
|
{
|
|
StorageKind = storageKind;
|
|
StorageCapacity = storageCapacity;
|
|
}
|
|
|
|
public StorageKind StorageKind { get; init; }
|
|
public float StorageCapacity { get; init; }
|
|
}
|
|
|
|
public sealed class ModuleRecipeDefinition
|
|
{
|
|
public required string ModuleId { get; set; }
|
|
public float Duration { get; set; }
|
|
public required List<RecipeInputDefinition> Inputs { get; set; }
|
|
}
|
|
|
|
public sealed class RecipeDefinition
|
|
{
|
|
public required string Id { get; set; }
|
|
public required string Label { get; set; }
|
|
public required string FacilityCategory { get; set; }
|
|
public float Duration { get; set; }
|
|
public int Priority { get; set; }
|
|
public List<string> RequiredModules { get; set; } = [];
|
|
public List<RecipeInputDefinition> Inputs { get; set; } = [];
|
|
public List<RecipeOutputDefinition> Outputs { get; set; } = [];
|
|
public string? ShipOutputId { get; set; }
|
|
}
|
|
|
|
public sealed class PlanetDefinition
|
|
{
|
|
public required string Label { get; set; }
|
|
public string PlanetType { get; set; } = "terrestrial";
|
|
public string Shape { get; set; } = "sphere";
|
|
public List<MoonDefinition> Moons { get; set; } = [];
|
|
public float OrbitRadius { get; set; }
|
|
public float OrbitSpeed { get; set; }
|
|
public float OrbitEccentricity { get; set; }
|
|
public float OrbitInclination { get; set; }
|
|
public float OrbitLongitudeOfAscendingNode { get; set; }
|
|
public float OrbitArgumentOfPeriapsis { get; set; }
|
|
public float OrbitPhaseAtEpoch { get; set; }
|
|
public float Size { get; set; }
|
|
public required string Color { get; set; }
|
|
public float Tilt { get; set; }
|
|
public bool HasRing { get; set; }
|
|
}
|
|
|
|
public enum ShipPurpose
|
|
{
|
|
[JsonStringEnumMemberName("auxiliary")]
|
|
Auxiliary,
|
|
[JsonStringEnumMemberName("mine")]
|
|
Mine,
|
|
[JsonStringEnumMemberName("build")]
|
|
Build,
|
|
[JsonStringEnumMemberName("fight")]
|
|
Fight,
|
|
[JsonStringEnumMemberName("trade")]
|
|
Trade,
|
|
[JsonStringEnumMemberName("salvage")]
|
|
Salvage,
|
|
[JsonStringEnumMemberName("dismantling")]
|
|
Dismantling,
|
|
}
|
|
|
|
public enum ShipType
|
|
{
|
|
[JsonStringEnumMemberName("resupplier")]
|
|
Resupplier,
|
|
[JsonStringEnumMemberName("miner")]
|
|
Miner,
|
|
[JsonStringEnumMemberName("carrier")]
|
|
Carrier,
|
|
[JsonStringEnumMemberName("fighter")]
|
|
Fighter,
|
|
[JsonStringEnumMemberName("heavyfighter")]
|
|
HeavyFighter,
|
|
[JsonStringEnumMemberName("destroyer")]
|
|
Destroyer,
|
|
[JsonStringEnumMemberName("largeminer")]
|
|
LargeMiner,
|
|
[JsonStringEnumMemberName("freighter")]
|
|
Freighter,
|
|
[JsonStringEnumMemberName("bomber")]
|
|
Bomber,
|
|
[JsonStringEnumMemberName("scavenger")]
|
|
Scavenger,
|
|
[JsonStringEnumMemberName("frigate")]
|
|
Frigate,
|
|
[JsonStringEnumMemberName("transporter")]
|
|
Transporter,
|
|
[JsonStringEnumMemberName("interceptor")]
|
|
Interceptor,
|
|
[JsonStringEnumMemberName("scout")]
|
|
Scout,
|
|
[JsonStringEnumMemberName("courier")]
|
|
Courier,
|
|
[JsonStringEnumMemberName("builder")]
|
|
Builder,
|
|
[JsonStringEnumMemberName("corvette")]
|
|
Corvette,
|
|
[JsonStringEnumMemberName("police")]
|
|
Police,
|
|
[JsonStringEnumMemberName("battleship")]
|
|
Battleship,
|
|
[JsonStringEnumMemberName("gunboat")]
|
|
Gunboat,
|
|
[JsonStringEnumMemberName("tug")]
|
|
Tug,
|
|
[JsonStringEnumMemberName("compactor")]
|
|
Compactor,
|
|
}
|
|
|
|
public sealed class ShipDefinition
|
|
{
|
|
public required string Id { get; set; }
|
|
public int Version { get; set; }
|
|
public required string Name { get; set; }
|
|
public string Description { get; set; } = string.Empty;
|
|
public string Size { get; set; } = string.Empty;
|
|
public float ExplosionDamage { get; set; }
|
|
public float Hull { get; set; }
|
|
public Dictionary<string, float> Storage { get; set; } = new(StringComparer.Ordinal);
|
|
public int People { get; set; }
|
|
public ShipPurpose Purpose { get; set; }
|
|
public string Thruster { get; set; } = string.Empty;
|
|
public ShipType Type { get; set; }
|
|
public float Mass { get; set; }
|
|
public ShipInertiaDefinition? Inertia { get; set; }
|
|
public ShipDragDefinition? Drag { get; set; }
|
|
public List<ShipMountDefinition> Engines { get; set; } = [];
|
|
public List<ShipMountDefinition> Shields { get; set; } = [];
|
|
public List<ShipMountDefinition> Weapons { get; set; } = [];
|
|
public List<ShipMountDefinition> Turrets { get; set; } = [];
|
|
public List<ShipCargoDefinition> Cargo { get; set; } = [];
|
|
public List<ModuleDockDefinition> Docks { get; set; } = [];
|
|
public List<string> Owners { get; set; } = [];
|
|
public ItemPriceDefinition? Price { get; set; }
|
|
public List<ItemProductionDefinition> Production { get; set; } = [];
|
|
[JsonIgnore]
|
|
public float Speed => InferLocalSpeed(Size);
|
|
[JsonIgnore]
|
|
public float WarpSpeed => InferWarpSpeed(Size);
|
|
[JsonIgnore]
|
|
public float FtlSpeed => InferFtlSpeed(Size);
|
|
[JsonIgnore]
|
|
public float SpoolTime => InferSpoolTime(Size);
|
|
public float GetTotalCargoCapacity() => Cargo.Sum(entry => entry.Max);
|
|
|
|
public float GetCargoCapacity(StorageKind kind) =>
|
|
Cargo
|
|
.Where(entry => entry.Types.Any(type => type.ToNullableStorageKind() == kind))
|
|
.Sum(entry => entry.Max);
|
|
|
|
public bool SupportsCargoKind(StorageKind kind) =>
|
|
GetCargoCapacity(kind) > 0f;
|
|
|
|
private static float InferWarpSpeed(string size) =>
|
|
size switch
|
|
{
|
|
"extrasmall" => 4.8f,
|
|
"small" => 4.2f,
|
|
"medium" => 3.4f,
|
|
"large" => 2.4f,
|
|
"extralarge" => 1.8f,
|
|
_ => 3f,
|
|
};
|
|
|
|
private static float InferLocalSpeed(string size) =>
|
|
size switch
|
|
{
|
|
"extrasmall" => 420f,
|
|
"small" => 320f,
|
|
"medium" => 230f,
|
|
"large" => 150f,
|
|
"extralarge" => 110f,
|
|
_ => 200f,
|
|
};
|
|
|
|
private static float InferFtlSpeed(string size) =>
|
|
size switch
|
|
{
|
|
"extrasmall" => 1f,
|
|
"small" => 0.85f,
|
|
"medium" => 0.7f,
|
|
"large" => 0.55f,
|
|
"extralarge" => 0.45f,
|
|
_ => 0.6f,
|
|
};
|
|
|
|
private static float InferSpoolTime(string size) =>
|
|
size switch
|
|
{
|
|
"extrasmall" => 0.8f,
|
|
"small" => 1f,
|
|
"medium" => 1.4f,
|
|
"large" => 2f,
|
|
"extralarge" => 2.6f,
|
|
_ => 1.5f,
|
|
};
|
|
}
|
|
|
|
public sealed class ShipInertiaDefinition
|
|
{
|
|
public float Pitch { get; set; }
|
|
public float Yaw { get; set; }
|
|
public float Roll { get; set; }
|
|
}
|
|
|
|
public sealed class ShipDragDefinition
|
|
{
|
|
public float Forward { get; set; }
|
|
public float Reverse { get; set; }
|
|
public float Horizontal { get; set; }
|
|
public float Vertical { get; set; }
|
|
public float Pitch { get; set; }
|
|
public float Yaw { get; set; }
|
|
public float Roll { get; set; }
|
|
}
|
|
|
|
public sealed class ShipMountDefinition
|
|
{
|
|
public string? Group { get; set; }
|
|
public required string Size { get; set; }
|
|
public bool Hittable { get; set; }
|
|
public List<string> Types { get; set; } = [];
|
|
}
|
|
|
|
public sealed class ShipCargoDefinition
|
|
{
|
|
public float Max { get; set; }
|
|
public List<string> Types { get; set; } = [];
|
|
}
|
|
|
|
public sealed class ScenarioDefinition
|
|
{
|
|
public required WorldGenerationOptions WorldGeneration { get; set; }
|
|
public required List<InitialStationDefinition> InitialStations { get; set; }
|
|
public required List<ShipFormationDefinition> ShipFormations { get; set; }
|
|
public required List<PatrolRouteDefinition> PatrolRoutes { get; set; }
|
|
}
|
|
|
|
public sealed class InitialStationDefinition
|
|
{
|
|
public required string SystemId { get; set; }
|
|
public string Label { get; set; } = "Orbital Station";
|
|
public string Color { get; set; } = "#8df0d2";
|
|
public string Objective { get; set; } = "general";
|
|
public List<string> StartingModules { get; set; } = [];
|
|
public string? FactionId { get; set; }
|
|
public int? PlanetIndex { get; set; }
|
|
public int? LagrangeSide { get; set; }
|
|
public float[]? Position { get; set; }
|
|
}
|
|
|
|
public sealed class ShipFormationDefinition
|
|
{
|
|
public required string ShipId { get; set; }
|
|
public int Count { get; set; }
|
|
public required float[] Center { get; set; }
|
|
public required string SystemId { get; set; }
|
|
public string? FactionId { get; set; }
|
|
public Dictionary<string, float> StartingInventory { get; set; } = new(StringComparer.Ordinal);
|
|
}
|
|
|
|
public sealed class PatrolRouteDefinition
|
|
{
|
|
public required string SystemId { get; set; }
|
|
public required List<float[]> Points { get; set; }
|
|
}
|