Further Tests & Progress
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
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="ResourceHarvestSystem"/> — the swept-segment
|
||||
/// harvest sweep that deposits a hit node's yield into the GLOBAL resource ledger. A bare world is seeded with
|
||||
/// a ResourceLedger singleton (+ StorageEntry buffer), resource nodes (LocalTransform + HitRadius +
|
||||
/// ResourceNode) and projectiles (LocalTransform + Projectile with a baked LastStep, since ProjectileMoveSystem
|
||||
/// is not in this world). Pins: a hit deposits + decrements Remaining + consumes the projectile; two same-tick
|
||||
/// hits over-harvest but destroy the node at most once (a double DestroyEntity would throw at playback); a miss
|
||||
/// leaves everything untouched and the projectile alive.
|
||||
/// </summary>
|
||||
public class ResourceHarvestSystemTests
|
||||
{
|
||||
static (World world, SimulationSystemGroup group, Entity ledger) MakeWorld(string name)
|
||||
{
|
||||
var world = new World(name);
|
||||
var group = world.GetOrCreateSystemManaged<SimulationSystemGroup>();
|
||||
group.AddSystemToUpdateList(world.GetOrCreateSystem<ResourceHarvestSystem>());
|
||||
group.SortSystems();
|
||||
world.SetTime(new TimeData(elapsedTime: 0f, deltaTime: 1f / 60f));
|
||||
var em = world.EntityManager;
|
||||
var ledger = em.CreateEntity(typeof(ResourceLedger));
|
||||
em.AddBuffer<StorageEntry>(ledger);
|
||||
return (world, group, ledger);
|
||||
}
|
||||
|
||||
static Entity MakeNode(EntityManager em, float3 pos, float hitRadius, byte resourceId, int remaining, float perHit)
|
||||
{
|
||||
var e = em.CreateEntity();
|
||||
em.AddComponentData(e, LocalTransform.FromPosition(pos));
|
||||
em.AddComponentData(e, new HitRadius { Value = hitRadius });
|
||||
em.AddComponentData(e, new ResourceNode { ResourceId = resourceId, Remaining = remaining, HarvestPerHit = perHit });
|
||||
return e;
|
||||
}
|
||||
|
||||
static Entity MakeProjectile(EntityManager em, float3 pos, float2 dir, float lastStep)
|
||||
{
|
||||
var e = em.CreateEntity();
|
||||
em.AddComponentData(e, LocalTransform.FromPosition(pos));
|
||||
em.AddComponentData(e, new Projectile { Direction = dir, LastStep = lastStep });
|
||||
return e;
|
||||
}
|
||||
|
||||
static int LedgerCount(EntityManager em, Entity ledger, ushort itemId)
|
||||
{
|
||||
var buf = em.GetBuffer<StorageEntry>(ledger);
|
||||
for (int i = 0; i < buf.Length; i++)
|
||||
if (buf[i].ItemId == itemId) return buf[i].Count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Hit_Deposits_To_Ledger_Decrements_Node_And_Consumes_Projectile()
|
||||
{
|
||||
var (world, group, ledger) = MakeWorld("HarvestHit");
|
||||
using (world)
|
||||
{
|
||||
var em = world.EntityManager;
|
||||
var node = MakeNode(em, new float3(10, 1, 10), hitRadius: 1f, resourceId: ResourceId.Aether, remaining: 100, perHit: 25f);
|
||||
var proj = MakeProjectile(em, new float3(10, 1, 10), new float2(1, 0), lastStep: 5f);
|
||||
|
||||
group.Update();
|
||||
|
||||
Assert.AreEqual(25, LedgerCount(em, ledger, ResourceId.Aether), "One hit deposits HarvestPerHit into the ledger.");
|
||||
Assert.AreEqual(75, em.GetComponentData<ResourceNode>(node).Remaining, "Node Remaining decrements by the harvested amount.");
|
||||
Assert.IsTrue(em.Exists(node), "A node with resource left survives.");
|
||||
Assert.IsFalse(em.Exists(proj), "The harvesting projectile is consumed.");
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Two_Projectiles_Deplete_Node_But_Destroy_It_At_Most_Once()
|
||||
{
|
||||
var (world, group, ledger) = MakeWorld("HarvestDeplete");
|
||||
using (world)
|
||||
{
|
||||
var em = world.EntityManager;
|
||||
var node = MakeNode(em, new float3(10, 1, 10), hitRadius: 1f, resourceId: ResourceId.Aether, remaining: 40, perHit: 25f);
|
||||
var p1 = MakeProjectile(em, new float3(10, 1, 10), new float2(1, 0), lastStep: 5f);
|
||||
var p2 = MakeProjectile(em, new float3(10, 1, 10), new float2(0, 1), lastStep: 5f);
|
||||
|
||||
group.Update();
|
||||
|
||||
Assert.AreEqual(50, LedgerCount(em, ledger, ResourceId.Aether), "Both hits deposit, even though the second over-harvests.");
|
||||
Assert.IsFalse(em.Exists(node), "A depleted node is destroyed exactly once (a double destroy would throw at playback).");
|
||||
Assert.IsFalse(em.Exists(p1), "Both projectiles are consumed.");
|
||||
Assert.IsFalse(em.Exists(p2));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Missing_Projectile_Leaves_Node_And_Ledger_Untouched()
|
||||
{
|
||||
var (world, group, ledger) = MakeWorld("HarvestMiss");
|
||||
using (world)
|
||||
{
|
||||
var em = world.EntityManager;
|
||||
var node = MakeNode(em, new float3(10, 1, 10), hitRadius: 1f, resourceId: ResourceId.Aether, remaining: 100, perHit: 25f);
|
||||
var proj = MakeProjectile(em, new float3(50, 1, 50), new float2(1, 0), lastStep: 5f);
|
||||
|
||||
group.Update();
|
||||
|
||||
Assert.AreEqual(0, LedgerCount(em, ledger, ResourceId.Aether), "A miss deposits nothing.");
|
||||
Assert.AreEqual(100, em.GetComponentData<ResourceNode>(node).Remaining, "A miss leaves Remaining untouched.");
|
||||
Assert.IsTrue(em.Exists(proj), "A projectile that hits no node survives (no destroy-on-miss).");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user