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."); } } } }