154 lines
5.3 KiB
C#
154 lines
5.3 KiB
C#
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;
|
|
}
|
|
}
|