diff --git a/Content.IntegrationTests/Tests/InventoryHelpersTest.cs b/Content.IntegrationTests/Tests/InventoryHelpersTest.cs new file mode 100644 index 0000000000..7c7bbfbac4 --- /dev/null +++ b/Content.IntegrationTests/Tests/InventoryHelpersTest.cs @@ -0,0 +1,69 @@ +using System.Threading.Tasks; +using Content.Server.GameObjects.Components.GUI; +using Content.Server.GameObjects.Components.Items.Storage; +using Content.Server.GameObjects.Components.Mobs; +using Content.Server.Utility; +using Content.Shared.GameObjects.Components.Inventory; +using NUnit.Framework; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Interfaces.Map; +using Robust.Shared.IoC; +using Robust.Shared.Map; +using static Content.Shared.GameObjects.Components.Inventory.EquipmentSlotDefines; + +namespace Content.IntegrationTests.Tests +{ + [TestFixture] + [TestOf(typeof(InventoryHelpers))] + public class InventoryHelpersTest : ContentIntegrationTest + { + [Test] + public async Task SpawnItemInSlotTest() + { + var server = StartServerDummyTicker(); + + IEntity human = null; + InventoryComponent inventory = null; + StunnableComponent stun = null; + + + server.Assert(() => + { + var mapMan = IoCManager.Resolve(); + + mapMan.CreateNewMapEntity(MapId.Nullspace); + + var entityMan = IoCManager.Resolve(); + + human = entityMan.SpawnEntity("HumanMob_Content", MapCoordinates.Nullspace); + inventory = human.GetComponent(); + stun = human.GetComponent(); + + // Can't do the test if this human doesn't have the slots for it. + Assert.That(inventory.HasSlot(Slots.INNERCLOTHING)); + Assert.That(inventory.HasSlot(Slots.IDCARD)); + + Assert.That(inventory.SpawnItemInSlot(Slots.INNERCLOTHING, "UniformJanitor", true)); + + // Do we actually have the uniform equipped? + Assert.That(inventory.TryGetSlotItem(Slots.INNERCLOTHING, out ItemComponent uniform)); + Assert.That(uniform.Owner.Prototype != null && uniform.Owner.Prototype.ID == "UniformJanitor"); + + stun.Stun(1f); + + // Since the mob is stunned, they can't equip this. + Assert.That(inventory.SpawnItemInSlot(Slots.IDCARD, "AssistantIDCard", true), Is.False); + + // Make sure we don't have the ID card equipped. + Assert.That(inventory.TryGetSlotItem(Slots.IDCARD, out ItemComponent _), Is.False); + + // Let's try skipping the interaction check and see if it equips it! + Assert.That(inventory.SpawnItemInSlot(Slots.IDCARD, "AssistantIDCard", false)); + Assert.That(inventory.TryGetSlotItem(Slots.IDCARD, out ItemComponent id)); + Assert.That(id.Owner.Prototype != null && id.Owner.Prototype.ID == "AssistantIDCard"); + }); + + await server.WaitIdleAsync(); + } + } +} diff --git a/Content.Server/Utility/InventoryHelpers.cs b/Content.Server/Utility/InventoryHelpers.cs new file mode 100644 index 0000000000..ec6bb9e851 --- /dev/null +++ b/Content.Server/Utility/InventoryHelpers.cs @@ -0,0 +1,49 @@ +using Content.Server.GameObjects.Components.GUI; +using Content.Server.GameObjects.Components.Items.Storage; +using Content.Shared.GameObjects.Components.Inventory; +using Robust.Shared.GameObjects; +using Robust.Shared.IoC; +using Robust.Shared.Map; +using Robust.Shared.Prototypes; +using static Content.Shared.GameObjects.Components.Inventory.EquipmentSlotDefines; + +namespace Content.Server.Utility +{ + public static class InventoryHelpers + { + public static bool SpawnItemInSlot(this InventoryComponent inventory, Slots slot, string prototype, bool mobCheck = false) + { + var entityManager = inventory.Owner.EntityManager; + var protoManager = IoCManager.Resolve(); + + // Let's do nothing if the owner of the inventory has been deleted. + if (inventory.Owner.Deleted) + return false; + + // If we don't have that slot or there's already an item there, we do nothing. + if (!inventory.HasSlot(slot) || inventory.TryGetSlotItem(slot, out ItemComponent _)) + return false; + + // If the prototype in question doesn't exist, we do nothing. + if (!protoManager.HasIndex(prototype)) + return false; + + // Let's spawn this in nullspace first... + var item = entityManager.SpawnEntity(prototype, MapCoordinates.Nullspace); + + // Helper method that deletes the item and returns false. + bool DeleteItem() + { + item.Delete(); + return false; + } + + // If this doesn't have an item component, then we can't do anything with it. + if (!item.TryGetComponent(out ItemComponent itemComp)) + return DeleteItem(); + + // We finally try to equip the item, otherwise we delete it. + return inventory.Equip(slot, itemComp, mobCheck) || DeleteItem(); + } + } +}