Refine ship orders and viewer controls
This commit is contained in:
153
tests/backend/ShipAiServiceExecutionTests.cs
Normal file
153
tests/backend/ShipAiServiceExecutionTests.cs
Normal file
@@ -0,0 +1,153 @@
|
||||
using FluentAssertions;
|
||||
using SpaceGame.Api.Definitions;
|
||||
using SpaceGame.Api.Industry.Planning;
|
||||
using SpaceGame.Api.Shared.Runtime;
|
||||
using SpaceGame.Api.Ships.AI;
|
||||
using SpaceGame.Api.Ships.Runtime;
|
||||
using SpaceGame.Api.Universe.Contracts;
|
||||
using SpaceGame.Api.Universe.Runtime;
|
||||
using SpaceGame.Api.Universe.Simulation;
|
||||
using Xunit;
|
||||
|
||||
namespace SpaceGame.Api.Tests;
|
||||
|
||||
public sealed class ShipAiServiceExecutionTests
|
||||
{
|
||||
[Fact]
|
||||
public void MoveOrder_CompletesAndIsRemovedAfterArrival()
|
||||
{
|
||||
var ship = new ShipRuntime
|
||||
{
|
||||
Id = "ship-1",
|
||||
SystemId = "sys-1",
|
||||
Definition = CreateShipDefinition(),
|
||||
FactionId = "player",
|
||||
Position = Vector3.Zero,
|
||||
TargetPosition = Vector3.Zero,
|
||||
SpatialState = new ShipSpatialStateRuntime
|
||||
{
|
||||
CurrentSystemId = "sys-1",
|
||||
CurrentAnchorId = null,
|
||||
LocalPosition = Vector3.Zero,
|
||||
SystemPosition = Vector3.Zero,
|
||||
},
|
||||
DefaultBehavior = new DefaultBehaviorRuntime
|
||||
{
|
||||
Kind = ShipBehaviorKinds.Idle,
|
||||
},
|
||||
Skills = new ShipSkillProfileRuntime
|
||||
{
|
||||
Navigation = 3,
|
||||
Trade = 3,
|
||||
Mining = 3,
|
||||
Combat = 3,
|
||||
Construction = 3,
|
||||
},
|
||||
Health = 100f,
|
||||
};
|
||||
|
||||
ship.OrderQueue.EnqueuePlayerOrder(new ShipOrderRuntime
|
||||
{
|
||||
Id = "move-1",
|
||||
Kind = ShipOrderKinds.Move,
|
||||
SourceKind = ShipOrderSourceKind.Player,
|
||||
SourceId = "test",
|
||||
Label = "Fly to point",
|
||||
TargetSystemId = "sys-1",
|
||||
TargetPosition = new Vector3(5f, 0f, 0f),
|
||||
});
|
||||
|
||||
var world = CreateWorld(ship);
|
||||
var service = new ShipAiService(new TestBalanceService());
|
||||
var events = new List<SimulationEventRecord>();
|
||||
|
||||
service.UpdateShip(world, ship, 1f, events);
|
||||
service.UpdateShip(world, ship, 0.01f, events);
|
||||
|
||||
ship.Position.Should().Be(new Vector3(5f, 0f, 0f));
|
||||
ship.OrderQueue.Should().BeEmpty();
|
||||
ship.ActiveOrderId.Should().BeNull();
|
||||
}
|
||||
|
||||
private static SimulationWorld CreateWorld(ShipRuntime ship)
|
||||
{
|
||||
return new SimulationWorld
|
||||
{
|
||||
Label = "test",
|
||||
Seed = 1,
|
||||
Systems =
|
||||
[
|
||||
new SystemRuntime
|
||||
{
|
||||
Definition = new SolarSystemDefinition
|
||||
{
|
||||
Id = "sys-1",
|
||||
Label = "System 1",
|
||||
Position = [0f, 0f, 0f],
|
||||
Stars = [],
|
||||
AsteroidField = new AsteroidFieldDefinition(),
|
||||
ResourceNodes = [],
|
||||
Planets = [],
|
||||
},
|
||||
Position = Vector3.Zero,
|
||||
}
|
||||
],
|
||||
Anchors = [],
|
||||
Nodes = [],
|
||||
Celestials = [],
|
||||
Wrecks = [],
|
||||
Stations = [],
|
||||
Ships = [ship],
|
||||
Factions = [],
|
||||
Commanders = [],
|
||||
Claims = [],
|
||||
ConstructionSites = [],
|
||||
MarketOrders = [],
|
||||
Policies = [],
|
||||
ShipDefinitions = new Dictionary<string, ShipDefinition>(StringComparer.Ordinal),
|
||||
ItemDefinitions = new Dictionary<string, ItemDefinition>(StringComparer.Ordinal),
|
||||
ModuleDefinitions = new Dictionary<string, ModuleDefinition>(StringComparer.Ordinal),
|
||||
ModuleRecipes = new Dictionary<string, ModuleRecipeDefinition>(StringComparer.Ordinal),
|
||||
Recipes = new Dictionary<string, RecipeDefinition>(StringComparer.Ordinal),
|
||||
ProductionGraph = new ProductionGraph
|
||||
{
|
||||
Commodities = new Dictionary<string, ProductionCommodityNode>(StringComparer.Ordinal),
|
||||
Processes = new Dictionary<string, ProductionProcessNode>(StringComparer.Ordinal),
|
||||
ProcessesByOutputId = new Dictionary<string, IReadOnlyList<ProductionProcessNode>>(StringComparer.Ordinal),
|
||||
ProcessesByInputId = new Dictionary<string, IReadOnlyList<ProductionProcessNode>>(StringComparer.Ordinal),
|
||||
OutputsByModuleId = new Dictionary<string, IReadOnlyList<string>>(StringComparer.Ordinal),
|
||||
},
|
||||
GeneratedAtUtc = DateTimeOffset.UtcNow,
|
||||
};
|
||||
}
|
||||
|
||||
private static ShipDefinition CreateShipDefinition()
|
||||
{
|
||||
return new ShipDefinition
|
||||
{
|
||||
Id = "ship-def",
|
||||
Name = "Test Ship",
|
||||
Size = "small",
|
||||
Hull = 100f,
|
||||
Purpose = ShipPurpose.Trade,
|
||||
Type = ShipType.Courier,
|
||||
};
|
||||
}
|
||||
|
||||
private sealed class TestBalanceService : IBalanceService
|
||||
{
|
||||
public float SimulationSpeedMultiplier => 1f;
|
||||
public float YPlane => 0f;
|
||||
public float ArrivalThreshold => 1f;
|
||||
public float MiningRate => 10f;
|
||||
public float MiningCycleSeconds => 1f;
|
||||
public float TransferRate => 10f;
|
||||
public float DockingDuration => 0.1f;
|
||||
public float UndockingDuration => 0.1f;
|
||||
public float UndockDistance => 10f;
|
||||
|
||||
public BalanceOptions GetCurrent() => new();
|
||||
|
||||
public BalanceOptions Update(BalanceOptions candidate) => candidate;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user