namespace SpaceGame.Simulation.Api.Simulation; internal sealed class IdleShipBehaviorState : IShipBehaviorState { public string Kind => "idle"; public void Plan(SimulationEngine engine, ShipRuntime ship, SimulationWorld world) { ship.ControllerTask = new ControllerTaskRuntime { Kind = ControllerTaskKind.Idle, Threshold = world.Balance.ArrivalThreshold, Status = WorkStatus.Pending, }; } public void ApplyEvent(SimulationEngine engine, ShipRuntime ship, SimulationWorld world, string controllerEvent) { } } internal sealed class PatrolShipBehaviorState : IShipBehaviorState { public string Kind => "patrol"; public void Plan(SimulationEngine engine, ShipRuntime ship, SimulationWorld world) { if (ship.DefaultBehavior.PatrolPoints.Count == 0) { ship.DefaultBehavior.Kind = "idle"; ship.ControllerTask = new ControllerTaskRuntime { Kind = ControllerTaskKind.Idle, Threshold = world.Balance.ArrivalThreshold, Status = WorkStatus.Pending, }; return; } ship.ControllerTask = new ControllerTaskRuntime { Kind = ControllerTaskKind.Travel, TargetPosition = ship.DefaultBehavior.PatrolPoints[ship.DefaultBehavior.PatrolIndex], TargetSystemId = ship.SystemId, Threshold = 18f, }; } public void ApplyEvent(SimulationEngine engine, ShipRuntime ship, SimulationWorld world, string controllerEvent) { if (controllerEvent == "arrived" && ship.DefaultBehavior.PatrolPoints.Count > 0) { ship.DefaultBehavior.PatrolIndex = (ship.DefaultBehavior.PatrolIndex + 1) % ship.DefaultBehavior.PatrolPoints.Count; } } } internal sealed class ResourceHarvestShipBehaviorState : IShipBehaviorState { private readonly string resourceItemId; private readonly string requiredModule; public ResourceHarvestShipBehaviorState(string kind, string resourceItemId, string requiredModule) { Kind = kind; this.resourceItemId = resourceItemId; this.requiredModule = requiredModule; } public string Kind { get; } public void Plan(SimulationEngine engine, ShipRuntime ship, SimulationWorld world) => engine.PlanResourceHarvest(ship, world, resourceItemId, requiredModule); public void ApplyEvent(SimulationEngine engine, ShipRuntime ship, SimulationWorld world, string controllerEvent) { switch (ship.DefaultBehavior.Phase, controllerEvent) { case ("travel-to-node", "arrived"): ship.DefaultBehavior.Phase = SimulationEngine.GetShipCargoAmount(ship) >= ship.Definition.CargoCapacity ? "travel-to-station" : "extract"; break; case ("extract", "cargo-full"): ship.DefaultBehavior.Phase = "travel-to-station"; break; case ("extract", "node-depleted"): ship.DefaultBehavior.Phase = "travel-to-node"; ship.DefaultBehavior.NodeId = null; break; case ("travel-to-station", "arrived"): ship.DefaultBehavior.Phase = "dock"; break; case ("dock", "docked"): ship.DefaultBehavior.Phase = SimulationEngine.GetShipCargoAmount(ship) > 0.01f ? "unload" : "refuel"; break; case ("unload", "unloaded"): ship.DefaultBehavior.Phase = "refuel"; break; case ("refuel", "refueled"): ship.DefaultBehavior.Phase = "undock"; break; case ("undock", "undocked"): ship.DefaultBehavior.Phase = "travel-to-node"; ship.DefaultBehavior.NodeId = null; break; } } } internal sealed class ConstructStationShipBehaviorState : IShipBehaviorState { public string Kind => "construct-station"; public void Plan(SimulationEngine engine, ShipRuntime ship, SimulationWorld world) => engine.PlanStationConstruction(ship, world); public void ApplyEvent(SimulationEngine engine, ShipRuntime ship, SimulationWorld world, string controllerEvent) { switch (ship.DefaultBehavior.Phase, controllerEvent) { case ("travel-to-station", "arrived"): ship.DefaultBehavior.Phase = SimulationEngine.NeedsRefuel(ship, world) ? "refuel" : "deliver-to-site"; break; case ("refuel", "refueled"): ship.DefaultBehavior.Phase = "deliver-to-site"; break; case ("deliver-to-site", "construction-delivered"): ship.DefaultBehavior.Phase = "build-site"; break; case ("construct-module", "module-constructed"): case ("build-site", "site-constructed"): ship.DefaultBehavior.Phase = "travel-to-station"; ship.DefaultBehavior.ModuleId = null; break; } } } internal sealed class EnergySupplyShipBehaviorState : IShipBehaviorState { public string Kind => "auto-supply-energy"; public void Plan(SimulationEngine engine, ShipRuntime ship, SimulationWorld world) => engine.PlanEnergySupply(ship, world); public void ApplyEvent(SimulationEngine engine, ShipRuntime ship, SimulationWorld world, string controllerEvent) { switch (ship.DefaultBehavior.Phase, controllerEvent) { case ("travel-to-source", "arrived"): case ("travel-to-destination", "arrived"): ship.DefaultBehavior.Phase = "dock"; break; case ("dock", "docked"): ship.DefaultBehavior.Phase = SimulationEngine.GetShipCargoAmount(ship) > 0.01f ? "unload" : "load"; break; case ("load", "loaded"): ship.DefaultBehavior.Phase = SimulationEngine.NeedsRefuel(ship, world) ? "refuel" : "undock"; break; case ("unload", "unloaded"): ship.DefaultBehavior.Phase = SimulationEngine.NeedsRefuel(ship, world) ? "refuel" : "undock"; break; case ("refuel", "refueled"): ship.DefaultBehavior.Phase = "undock"; break; case ("undock", "undocked"): ship.DefaultBehavior.Phase = SimulationEngine.GetShipCargoAmount(ship) > 0.01f ? "travel-to-destination" : "travel-to-source"; break; } } }