using NUnit.Framework;
using ProjectM.Server;
using ProjectM.Simulation;
using Unity.Core;
using Unity.Entities;
using Unity.NetCode;
namespace ProjectM.Tests
{
///
/// Plain-Entities EditMode tests for the server-only — the RPC that
/// moves a player's PERSONAL inventory into the shared ledger. Mirrors RegionTransitSystemTests' seeding:
/// a ResourceLedger singleton, a mock connection (NetworkId), a player (GhostOwner + InventorySlot +
/// PlayerTag), and an InventoryDepositRequest + ReceiveRpcCommandRequest. Pins: a specific-item deposit
/// moves the clamped amount; ItemId 0 deposits everything and empties the bag; an unresolvable connection
/// moves nothing; the request is consumed either way.
///
public class InventoryDepositSystemTests
{
static (World world, SimulationSystemGroup group, Entity ledger) MakeWorld(string name)
{
var world = new World(name);
var group = world.GetOrCreateSystemManaged();
group.AddSystemToUpdateList(world.GetOrCreateSystem());
group.SortSystems();
world.SetTime(new TimeData(elapsedTime: 0f, deltaTime: 1f / 60f));
var em = world.EntityManager;
var ledger = em.CreateEntity(typeof(ResourceLedger));
em.AddBuffer(ledger);
return (world, group, ledger);
}
static Entity MakeConnection(EntityManager em, int networkId)
{
var e = em.CreateEntity();
em.AddComponentData(e, new NetworkId { Value = networkId });
return e;
}
static Entity MakePlayer(EntityManager em, int networkId, params (ushort id, int count)[] items)
{
var e = em.CreateEntity();
em.AddComponentData(e, new GhostOwner { NetworkId = networkId });
em.AddComponent(e);
var bag = em.AddBuffer(e);
foreach (var it in items)
bag.Add(new InventorySlot { ItemId = it.id, Count = it.count });
return e;
}
static void MakeRequest(EntityManager em, ushort itemId, int count, Entity conn)
{
var e = em.CreateEntity();
em.AddComponentData(e, new InventoryDepositRequest { ItemId = itemId, Count = count });
em.AddComponentData(e, new ReceiveRpcCommandRequest { SourceConnection = conn });
}
static int LedgerCount(EntityManager em, Entity ledger, ushort itemId)
{
var buf = em.GetBuffer(ledger);
for (int i = 0; i < buf.Length; i++)
if (buf[i].ItemId == itemId) return buf[i].Count;
return 0;
}
static int InvCount(EntityManager em, Entity player, ushort itemId)
{
var buf = em.GetBuffer(player);
return InventoryMath.CountOf(buf, itemId);
}
[Test]
public void Deposit_Specific_Item_Moves_Clamped_Amount_To_Ledger()
{
var (world, group, ledger) = MakeWorld("DepositSpecific");
using (world)
{
var em = world.EntityManager;
var conn = MakeConnection(em, 1);
var player = MakePlayer(em, 1, (ResourceId.Ore, 30));
MakeRequest(em, ResourceId.Ore, 20, conn);
group.Update();
Assert.AreEqual(10, InvCount(em, player, ResourceId.Ore), "20 of 30 Ore moved out of the bag.");
Assert.AreEqual(20, LedgerCount(em, ledger, ResourceId.Ore), "20 Ore landed in the shared ledger.");
using var q = em.CreateEntityQuery(typeof(InventoryDepositRequest));
Assert.AreEqual(0, q.CalculateEntityCount(), "The request is consumed.");
}
}
[Test]
public void Deposit_All_Empties_Bag_Into_Ledger()
{
var (world, group, ledger) = MakeWorld("DepositAll");
using (world)
{
var em = world.EntityManager;
var conn = MakeConnection(em, 1);
var player = MakePlayer(em, 1, (ResourceId.Ore, 30), (ResourceId.Aether, 5));
MakeRequest(em, itemId: 0, count: 0, conn); // 0 = deposit all
group.Update();
Assert.AreEqual(0, InvCount(em, player, ResourceId.Ore), "Deposit-all empties the bag.");
Assert.AreEqual(0, InvCount(em, player, ResourceId.Aether));
Assert.AreEqual(30, LedgerCount(em, ledger, ResourceId.Ore));
Assert.AreEqual(5, LedgerCount(em, ledger, ResourceId.Aether));
}
}
[Test]
public void Deposit_From_Unresolvable_Connection_Moves_Nothing()
{
var (world, group, ledger) = MakeWorld("DepositUnknown");
using (world)
{
var em = world.EntityManager;
var player = MakePlayer(em, 1, (ResourceId.Ore, 30));
MakeRequest(em, ResourceId.Ore, 20, Entity.Null); // no NetworkId on Entity.Null
group.Update();
Assert.AreEqual(30, InvCount(em, player, ResourceId.Ore), "An unresolvable sender moves nothing.");
Assert.AreEqual(0, LedgerCount(em, ledger, ResourceId.Ore));
using var q = em.CreateEntityQuery(typeof(InventoryDepositRequest));
Assert.AreEqual(0, q.CalculateEntityCount(), "The request is still consumed.");
}
}
}
}