Further Tests & Progress
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
using NUnit.Framework;
|
||||
using ProjectM.Server;
|
||||
using ProjectM.Simulation;
|
||||
using Unity.Core;
|
||||
using Unity.Entities;
|
||||
using Unity.Mathematics;
|
||||
using Unity.Transforms;
|
||||
|
||||
namespace ProjectM.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// Plain-Entities EditMode tests for the server-only <see cref="ExpeditionGateSystem"/> (walk-in region
|
||||
/// transit). A bare world is seeded with an <c>ExpeditionGate</c> (+ LocalTransform) and a player
|
||||
/// (RegionTag + LocalTransform + PlayerTag). A player whose region matches the gate's FromRegion and who is
|
||||
/// within the gate radius is transited (RegionTag flipped + LocalTransform teleported to ArrivalPos).
|
||||
/// Returning to base during the Expedition phase caps the cycle phase timer. Pins the proximity gate, the
|
||||
/// region/radius guards, and the early-return phase cap.
|
||||
/// </summary>
|
||||
public class ExpeditionGateSystemTests
|
||||
{
|
||||
static (World world, SimulationSystemGroup group) MakeWorld(string name)
|
||||
{
|
||||
var world = new World(name);
|
||||
var group = world.GetOrCreateSystemManaged<SimulationSystemGroup>();
|
||||
group.AddSystemToUpdateList(world.GetOrCreateSystem<ExpeditionGateSystem>());
|
||||
group.SortSystems();
|
||||
world.SetTime(new TimeData(elapsedTime: 0f, deltaTime: 1f / 60f));
|
||||
return (world, group);
|
||||
}
|
||||
|
||||
static void MakeGate(EntityManager em, float3 pos, byte from, byte to, float radius, float3 arrival)
|
||||
{
|
||||
var e = em.CreateEntity();
|
||||
em.AddComponentData(e, LocalTransform.FromPosition(pos));
|
||||
em.AddComponentData(e, new ExpeditionGate { FromRegion = from, ToRegion = to, Radius = radius, ArrivalPos = arrival });
|
||||
}
|
||||
|
||||
static Entity MakePlayer(EntityManager em, float3 pos, byte region)
|
||||
{
|
||||
var e = em.CreateEntity();
|
||||
em.AddComponentData(e, LocalTransform.FromPosition(pos));
|
||||
em.AddComponentData(e, new RegionTag { Region = region });
|
||||
em.AddComponent<PlayerTag>(e);
|
||||
return e;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Player_In_Gate_Radius_Is_Transited_And_Teleported()
|
||||
{
|
||||
var (world, group) = MakeWorld("GateTransitWorld");
|
||||
using (world)
|
||||
{
|
||||
var em = world.EntityManager;
|
||||
var arrival = new float3(1000, 1, 0);
|
||||
MakeGate(em, new float3(0, 1, 0), RegionId.Base, RegionId.Expedition, radius: 15f, arrival: arrival);
|
||||
var player = MakePlayer(em, new float3(5, 1, 0), RegionId.Base);
|
||||
|
||||
group.Update();
|
||||
|
||||
Assert.AreEqual(RegionId.Expedition, em.GetComponentData<RegionTag>(player).Region,
|
||||
"Region flips to the gate's ToRegion.");
|
||||
var p = em.GetComponentData<LocalTransform>(player).Position;
|
||||
Assert.AreEqual(1000f, p.x, 1e-3f, "Player is teleported to the gate's ArrivalPos (x).");
|
||||
Assert.AreEqual(0f, p.z, 1e-3f, "Player is teleported to the gate's ArrivalPos (z).");
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Player_Outside_Radius_Is_Not_Transited()
|
||||
{
|
||||
var (world, group) = MakeWorld("GateNoTransitWorld");
|
||||
using (world)
|
||||
{
|
||||
var em = world.EntityManager;
|
||||
MakeGate(em, new float3(0, 1, 0), RegionId.Base, RegionId.Expedition, radius: 15f, arrival: new float3(1000, 1, 0));
|
||||
var player = MakePlayer(em, new float3(50, 1, 0), RegionId.Base);
|
||||
|
||||
group.Update();
|
||||
|
||||
Assert.AreEqual(RegionId.Base, em.GetComponentData<RegionTag>(player).Region,
|
||||
"A player beyond the gate radius stays in its region.");
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Player_Wrong_Region_Is_Not_Transited()
|
||||
{
|
||||
var (world, group) = MakeWorld("GateWrongRegionWorld");
|
||||
using (world)
|
||||
{
|
||||
var em = world.EntityManager;
|
||||
// Gate only acts on players currently in the Base region.
|
||||
MakeGate(em, new float3(0, 1, 0), RegionId.Base, RegionId.Expedition, radius: 15f, arrival: new float3(1000, 1, 0));
|
||||
var player = MakePlayer(em, new float3(1, 1, 0), RegionId.Expedition);
|
||||
|
||||
group.Update();
|
||||
|
||||
Assert.AreEqual(RegionId.Expedition, em.GetComponentData<RegionTag>(player).Region,
|
||||
"A player whose region does not match FromRegion is ignored even inside the radius.");
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Return_To_Base_During_Expedition_Caps_The_Phase_Timer()
|
||||
{
|
||||
var (world, group) = MakeWorld("GateReturnCapWorld");
|
||||
using (world)
|
||||
{
|
||||
var em = world.EntityManager;
|
||||
MakeGate(em, new float3(0, 1, 0), RegionId.Expedition, RegionId.Base, radius: 15f, arrival: new float3(0, 1, 0));
|
||||
MakePlayer(em, new float3(3, 1, 0), RegionId.Expedition);
|
||||
|
||||
var cycle = em.CreateEntity(typeof(CycleState));
|
||||
em.SetComponentData(cycle, new CycleState { Phase = CyclePhase.Expedition, PhaseEndTick = 5000, CycleNumber = 1 });
|
||||
|
||||
group.Update();
|
||||
|
||||
Assert.AreEqual(1u, em.GetComponentData<CycleState>(cycle).PhaseEndTick,
|
||||
"Returning to base mid-Expedition caps PhaseEndTick to 1 so Defend starts next tick.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user