Files
space-game/apps/backend/Definitions/WorldDefinitions.cs

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; }
}