using System.Collections.Generic; using System.Linq; using NUnit.Framework; using Robust.Shared.Containers; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Map; // ReSharper disable AccessToStaticMemberViaDerivedType namespace Robust.UnitTesting.Server.GameObjects.Components { [TestFixture, Parallelizable] public sealed class ContainerTest { private static ISimulation SimulationFactory() { var sim = RobustServerSimulation .NewSimulation() .RegisterPrototypes(protoMan => protoMan.LoadString(Prototypes)) .InitializeInstance(); // Adds the map with id 1, and spawns entity 1 as the map entity. sim.AddMap(1); return sim; } const string Prototypes = @" - type: entity name: dummy id: dummy "; [Test] public void TestCreation() { var sim = SimulationFactory(); var entity = sim.SpawnEntity("dummy", new EntityCoordinates(new EntityUid(1), (0, 0))); var container = entity.CreateContainer("dummy"); Assert.That(container.ID, Is.EqualTo("dummy")); Assert.That(container.Owner, Is.EqualTo(entity)); var manager = IoCManager.Resolve().GetComponent(entity); Assert.That(container.Manager, Is.EqualTo(manager)); Assert.That(() => entity.CreateContainer("dummy"), Throws.ArgumentException); Assert.That(manager.HasContainer("dummy2"), Is.False); var container2 = entity.CreateContainer("dummy2"); Assert.That(container2.Manager, Is.EqualTo(manager)); Assert.That(container2.Owner, Is.EqualTo(entity)); Assert.That(container2.ID, Is.EqualTo("dummy2")); Assert.That(manager.HasContainer("dummy"), Is.True); Assert.That(manager.HasContainer("dummy2"), Is.True); Assert.That(manager.HasContainer("dummy3"), Is.False); Assert.That(manager.GetContainer("dummy"), Is.EqualTo(container)); Assert.That(manager.GetContainer("dummy2"), Is.EqualTo(container2)); Assert.That(() => manager.GetContainer("dummy3"), Throws.TypeOf()); IoCManager.Resolve().DeleteEntity(entity); Assert.That(manager.Deleted, Is.True); Assert.That(container.Deleted, Is.True); Assert.That(container2.Deleted, Is.True); } [Test] public void TestInsertion() { var sim = SimulationFactory(); var owner = sim.SpawnEntity("dummy", new EntityCoordinates(new EntityUid(1), (0, 0))); var inserted = sim.SpawnEntity("dummy", new EntityCoordinates(new EntityUid(1), (0, 0))); var transform = IoCManager.Resolve().GetComponent(inserted); var container = owner.CreateContainer("dummy"); Assert.That(container.Insert(inserted), Is.True); Assert.That(transform.Parent!.Owner, Is.EqualTo(owner)); var container2 = inserted.CreateContainer("dummy"); Assert.That(container2.Insert(owner), Is.False); var success = container.Remove(inserted); Assert.That(success, Is.True); success = container.Remove(inserted); Assert.That(success, Is.False); container.Insert(inserted); IoCManager.Resolve().DeleteEntity(owner); // Make sure inserted was detached. Assert.That(transform.Deleted, Is.True); } [Test] public void TestNestedRemoval() { var sim = SimulationFactory(); var owner = sim.SpawnEntity("dummy", new EntityCoordinates(new EntityUid(1), (0, 0))); var inserted = sim.SpawnEntity("dummy", new EntityCoordinates(new EntityUid(1), (0, 0))); var transform = IoCManager.Resolve().GetComponent(inserted); var entity = sim.SpawnEntity("dummy", new EntityCoordinates(new EntityUid(1), (0, 0))); var container = owner.CreateContainer("dummy"); Assert.That(container.Insert(inserted), Is.True); Assert.That(transform.Parent!.Owner, Is.EqualTo(owner)); var container2 = inserted.CreateContainer("dummy"); Assert.That(container2.Insert(entity), Is.True); Assert.That(IoCManager.Resolve().GetComponent(entity).Parent!.Owner, Is.EqualTo(inserted)); Assert.That(container2.Remove(entity), Is.True); Assert.That(container.Contains(entity), Is.True); Assert.That(IoCManager.Resolve().GetComponent(entity).Parent!.Owner, Is.EqualTo(owner)); IoCManager.Resolve().DeleteEntity(owner); Assert.That(transform.Deleted, Is.True); } [Test] public void TestNestedRemovalWithDenial() { var sim = SimulationFactory(); var coordinates = new EntityCoordinates(new EntityUid(1), (0, 0)); var entityOne = sim.SpawnEntity("dummy", coordinates); var entityTwo = sim.SpawnEntity("dummy", coordinates); var entityThree = sim.SpawnEntity("dummy", coordinates); var entityItem = sim.SpawnEntity("dummy", coordinates); var container = entityOne.CreateContainer("dummy"); var container2 = entityTwo.CreateContainer("dummy"); var container3 = entityThree.CreateContainer("dummy"); var entMan = IoCManager.Resolve(); Assert.That(container.Insert(entityTwo), Is.True); Assert.That(entMan.GetComponent(entityTwo).Parent!.Owner, Is.EqualTo(entityOne)); Assert.That(container2.Insert(entityThree), Is.True); Assert.That(entMan.GetComponent(entityThree).Parent!.Owner, Is.EqualTo(entityTwo)); Assert.That(container3.Insert(entityItem), Is.True); Assert.That(entMan.GetComponent(entityItem).Parent!.Owner, Is.EqualTo(entityThree)); Assert.That(container3.Remove(entityItem), Is.True); Assert.That(container.Contains(entityItem), Is.True); Assert.That(entMan.GetComponent(entityItem).Parent!.Owner, Is.EqualTo(entityOne)); entMan.DeleteEntity(entityOne); Assert.That(entMan.Deleted(entityOne), Is.True); } [Test] public void BaseContainer_SelfInsert_False() { var sim = SimulationFactory(); var entity = sim.SpawnEntity("dummy", new EntityCoordinates(new EntityUid(1), (0, 0))); var container = entity.CreateContainer("dummy"); Assert.That(container.Insert(entity), Is.False); Assert.That(container.CanInsert(entity), Is.False); } [Test] public void BaseContainer_InsertMap_False() { var sim = SimulationFactory(); var mapEnt = new EntityUid(1); var entity = sim.SpawnEntity("dummy", new EntityCoordinates(new EntityUid(1), (0, 0))); var container = entity.CreateContainer("dummy"); Assert.That(container.Insert(mapEnt), Is.False); Assert.That(container.CanInsert(mapEnt), Is.False); } [Test] public void BaseContainer_InsertGrid_False() { var sim = SimulationFactory(); var grid = sim.Resolve().CreateGrid(new MapId(1)).GridEntityId; var entity = sim.SpawnEntity("dummy", new EntityCoordinates(new EntityUid(1), (0, 0))); var container = entity.CreateContainer("dummy"); Assert.That(container.Insert(grid), Is.False); Assert.That(container.CanInsert(grid), Is.False); } [Test] public void BaseContainer_Insert_True() { var sim = SimulationFactory(); var containerEntity = sim.SpawnEntity("dummy", new EntityCoordinates(new EntityUid(1), (0, 0))); var container = containerEntity.CreateContainer("dummy"); var insertEntity = sim.SpawnEntity("dummy", new EntityCoordinates(new EntityUid(1), (0, 0))); var result = container.Insert(insertEntity); Assert.That(result, Is.True); Assert.That(container.ContainedEntities.Count, Is.EqualTo(1)); Assert.That(IoCManager.Resolve().GetComponent(containerEntity).ChildCount, Is.EqualTo(1)); Assert.That(IoCManager.Resolve().GetComponent(containerEntity).ChildEntities.First(), Is.EqualTo(insertEntity)); result = insertEntity.TryGetContainerMan(out var resultContainerMan); Assert.That(result, Is.True); Assert.That(resultContainerMan, Is.EqualTo(container.Manager)); } [Test] public void BaseContainer_RemoveNotAdded_False() { var sim = SimulationFactory(); var containerEntity = sim.SpawnEntity("dummy", new EntityCoordinates(new EntityUid(1), (0, 0))); var container = containerEntity.CreateContainer("dummy"); var insertEntity = sim.SpawnEntity("dummy", new EntityCoordinates(new EntityUid(1), (0, 0))); var result = container.Remove(insertEntity); Assert.That(result, Is.False); } [Test] public void BaseContainer_Transfer_True() { var sim = SimulationFactory(); var entity1 = sim.SpawnEntity("dummy", new EntityCoordinates(new EntityUid(1), (0, 0))); var container1 = entity1.CreateContainer("dummy"); var entity2 = sim.SpawnEntity("dummy", new EntityCoordinates(new EntityUid(1), (0, 0))); var container2 = entity2.CreateContainer("dummy"); var transferEntity = sim.SpawnEntity("dummy", new EntityCoordinates(new EntityUid(1), (0, 0))); container1.Insert(transferEntity); var result = container2.Insert(transferEntity); Assert.That(result, Is.True); Assert.That(container1.ContainedEntities.Count, Is.EqualTo(0)); Assert.That(container2.ContainedEntities.Count, Is.EqualTo(1)); } [Test] public void Container_Serialize() { var sim = SimulationFactory(); var entity = sim.SpawnEntity("dummy", new EntityCoordinates(new EntityUid(1), (0, 0))); var container = entity.CreateContainer("dummy"); var childEnt = sim.SpawnEntity(null, new EntityCoordinates(new EntityUid(1), (0, 0))); container.OccludesLight = true; container.ShowContents = true; container.Insert(childEnt); var containerMan = IoCManager.Resolve().GetComponent(entity); var state = (ContainerManagerComponent.ContainerManagerComponentState)containerMan.GetComponentState(); Assert.That(state.ContainerSet.Count, Is.EqualTo(1)); Assert.That(state.ContainerSet[0].Id, Is.EqualTo("dummy")); Assert.That(state.ContainerSet[0].OccludesLight, Is.True); Assert.That(state.ContainerSet[0].ShowContents, Is.True); Assert.That(state.ContainerSet[0].ContainedEntities.Length, Is.EqualTo(1)); Assert.That(state.ContainerSet[0].ContainedEntities[0], Is.EqualTo(childEnt)); } private sealed class ContainerOnlyContainer : BaseContainer { /// /// The generic container class uses a list of entities /// private readonly List _containerList = new(); private readonly List _expectedEntities = new(); public override string ContainerType => nameof(ContainerOnlyContainer); /// public override IReadOnlyList ContainedEntities => _containerList; public override List ExpectedEntities => _expectedEntities; /// protected override void InternalInsert(EntityUid toinsert, IEntityManager entMan) { _containerList.Add(toinsert); base.InternalInsert(toinsert, entMan); } /// protected override void InternalRemove(EntityUid toremove, IEntityManager entMan) { _containerList.Remove(toremove); base.InternalRemove(toremove, entMan); } /// public override bool Contains(EntityUid contained) { return _containerList.Contains(contained); } /// public override void Shutdown() { base.Shutdown(); var entMan = IoCManager.Resolve(); foreach (var entity in _containerList) { entMan.DeleteEntity(entity); } } public override bool CanInsert(EntityUid toinsert, IEntityManager? entMan = null) { IoCManager.Resolve(ref entMan); return entMan.TryGetComponent(toinsert, out IContainerManager? _); } } } }