85 lines
3.6 KiB
C#
85 lines
3.6 KiB
C#
using SpaceGame.Api.Contracts;
|
|
using SpaceGame.Api.Simulation.Model;
|
|
using SpaceGame.Api.Simulation.Support;
|
|
using SpaceGame.Api.Simulation.Systems;
|
|
|
|
namespace SpaceGame.Api.Simulation.Engine;
|
|
|
|
public sealed class SimulationEngine
|
|
{
|
|
private readonly OrbitalSimulationOptions _orbitalSimulation;
|
|
private readonly OrbitalStateUpdater _orbitalStateUpdater;
|
|
private readonly InfrastructureSimulationService _infrastructureSimulation;
|
|
private readonly CommanderPlanningService _commanderPlanning;
|
|
private readonly StationSimulationService _stationSimulation;
|
|
private readonly StationLifecycleService _stationLifecycle;
|
|
private readonly ShipControlService _shipControl;
|
|
private readonly ShipTaskExecutionService _shipTaskExecution;
|
|
private readonly SimulationProjectionService _projection;
|
|
|
|
public SimulationEngine(OrbitalSimulationOptions? orbitalSimulation = null)
|
|
{
|
|
_orbitalSimulation = orbitalSimulation ?? new OrbitalSimulationOptions();
|
|
_orbitalStateUpdater = new OrbitalStateUpdater(_orbitalSimulation);
|
|
_infrastructureSimulation = new InfrastructureSimulationService();
|
|
_commanderPlanning = new CommanderPlanningService();
|
|
_stationSimulation = new StationSimulationService();
|
|
_stationLifecycle = new StationLifecycleService(_stationSimulation);
|
|
_shipControl = new ShipControlService();
|
|
_shipTaskExecution = new ShipTaskExecutionService();
|
|
_projection = new SimulationProjectionService(_orbitalSimulation);
|
|
}
|
|
|
|
public WorldDelta Tick(SimulationWorld world, float deltaSeconds, long sequence)
|
|
{
|
|
var nowUtc = DateTimeOffset.UtcNow;
|
|
var events = new List<SimulationEventRecord>();
|
|
|
|
world.OrbitalTimeSeconds += deltaSeconds * _orbitalSimulation.SimulatedSecondsPerRealSecond;
|
|
|
|
_orbitalStateUpdater.Update(world);
|
|
_infrastructureSimulation.UpdateClaims(world, events);
|
|
_infrastructureSimulation.UpdateConstructionSites(world, events);
|
|
_commanderPlanning.UpdateCommanders(this, world, deltaSeconds, events);
|
|
_stationLifecycle.UpdateStations(world, deltaSeconds, events);
|
|
|
|
foreach (var ship in world.Ships)
|
|
{
|
|
var previousPosition = ship.Position;
|
|
var previousState = ship.State;
|
|
var previousBehavior = ship.DefaultBehavior.Kind;
|
|
var previousTask = ship.ControllerTask.Kind;
|
|
|
|
_shipControl.RefreshControlLayers(ship, world);
|
|
_shipControl.PlanControllerTask(this, ship, world);
|
|
|
|
var controllerEvent = _shipTaskExecution.UpdateControllerTask(ship, world, deltaSeconds);
|
|
|
|
_shipControl.AdvanceControlState(this, ship, world, controllerEvent);
|
|
ship.Velocity = ship.Position.Subtract(previousPosition).Divide(deltaSeconds);
|
|
_shipControl.TrackHistory(ship, controllerEvent);
|
|
_shipControl.EmitShipStateEvents(ship, previousState, previousBehavior, previousTask, controllerEvent, events);
|
|
}
|
|
|
|
_orbitalStateUpdater.SyncSpatialState(world);
|
|
world.GeneratedAtUtc = nowUtc;
|
|
|
|
return _projection.BuildDelta(world, sequence, events);
|
|
}
|
|
|
|
public WorldSnapshot BuildSnapshot(SimulationWorld world, long sequence) =>
|
|
_projection.BuildSnapshot(world, sequence);
|
|
|
|
public void PrimeDeltaBaseline(SimulationWorld world) =>
|
|
_projection.PrimeDeltaBaseline(world);
|
|
|
|
internal void PlanResourceHarvest(ShipRuntime ship, SimulationWorld world, string resourceItemId, string requiredModule) =>
|
|
_shipControl.PlanResourceHarvest(ship, world, resourceItemId, requiredModule);
|
|
|
|
internal void PlanStationConstruction(ShipRuntime ship, SimulationWorld world) =>
|
|
_shipControl.PlanStationConstruction(ship, world);
|
|
|
|
internal static float GetShipCargoAmount(ShipRuntime ship) =>
|
|
SimulationRuntimeSupport.GetShipCargoAmount(ship);
|
|
}
|