]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
storage and inventory toolshed commands (#39046)
authorUpAndLeaves <92269094+Alpha-Two@users.noreply.github.com>
Thu, 11 Sep 2025 22:07:37 +0000 (23:07 +0100)
committerGitHub <noreply@github.com>
Thu, 11 Sep 2025 22:07:37 +0000 (15:07 -0700)
* First commit

* CommandImplementation on singletons is die, a la moony

* Fix duplicated thingy because yes

* Prototypes, bugfixes, refactoring oh my

* Remember to actually stage your ftl changes next time, leaf

Content.Server/Inventory/InventoryCommand.cs [new file with mode: 0644]
Content.Server/Storage/StorageCommand.cs [new file with mode: 0644]
Resources/Locale/en-US/commands/toolshed-commands.ftl

diff --git a/Content.Server/Inventory/InventoryCommand.cs b/Content.Server/Inventory/InventoryCommand.cs
new file mode 100644 (file)
index 0000000..8197889
--- /dev/null
@@ -0,0 +1,198 @@
+using System.Linq;
+using Content.Server.Administration;
+using Content.Shared.Administration;
+using Content.Shared.Inventory;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Toolshed;
+
+namespace Content.Server.Inventory;
+
+[ToolshedCommand, AdminCommand(AdminFlags.Debug)]
+public sealed class InventoryCommand : ToolshedCommand
+{
+    private InventorySystem? _inventorySystem;
+
+    [CommandImplementation("getflags")]
+    public IEnumerable<EntityUid> InventoryGetFlags([PipedArgument] IEnumerable<EntityUid> ents, SlotFlags slotFlag)
+    {
+        var items = Enumerable.Empty<EntityUid>();
+        foreach (var ent in ents)
+        {
+            items = items.Concat(InventoryGetFlags(ent, slotFlag));
+        }
+
+        return items;
+    }
+
+    public IEnumerable<EntityUid> InventoryGetFlags(EntityUid ent, SlotFlags slotFlag)
+    {
+        _inventorySystem ??= GetSys<InventorySystem>();
+
+        if (!EntityManager.TryGetComponent<InventoryComponent>(ent, out var inventory))
+            return [];
+
+        List<EntityUid> items = new();
+
+        foreach (var slot in inventory.Slots)
+        {
+            if ((slot.SlotFlags & slotFlag) == 0) // Does this seem somewhat illegal? yes. Does C# provide an alternative function for checking if an enum has ANY of a set of bit flags? no.
+                continue;
+            if (_inventorySystem.TryGetSlotEntity(ent, slot.Name, out var item, inventory))
+                items.Add(item.Value);
+        }
+
+        return items;
+    }
+
+
+    [CommandImplementation("getnamed")]
+    public IEnumerable<EntityUid> InventoryGetNamed([PipedArgument] IEnumerable<EntityUid> ents, string slotName)
+    {
+        var items = Enumerable.Empty<EntityUid>();
+        foreach (var ent in ents)
+        {
+            items = items.Concat(InventoryGetNamed(ent, slotName));
+        }
+
+        return items;
+    }
+
+    public IEnumerable<EntityUid> InventoryGetNamed(EntityUid ent, string slotName)
+    {
+        _inventorySystem ??= GetSys<InventorySystem>();
+
+        if (!EntityManager.TryGetComponent<InventoryComponent>(ent, out var inventory))
+            return [];
+
+        List<EntityUid> items = new();
+
+        foreach (var slot in inventory.Slots)
+        {
+            if (slot.Name != slotName)
+                continue;
+            if (_inventorySystem.TryGetSlotEntity(ent, slot.Name, out var item, inventory))
+                items.Add(item.Value);
+        }
+
+        return items;
+    }
+
+    [CommandImplementation("forceput")]
+    public EntityUid? InventoryForcePut([PipedArgument] IEnumerable<EntityUid> ents,
+        EntityUid itemEnt,
+        SlotFlags slotFlag) => InventoryPutEnumerableBase(ents, itemEnt, slotFlag, PutType.ForcePut);
+    [CommandImplementation("forcespawn")]
+    public EntityUid? InventoryForceSpawn([PipedArgument] IEnumerable<EntityUid> ents,
+        EntProtoId itemEnt,
+        SlotFlags slotFlag) => InventorySpawnEnumerableBase(ents, itemEnt, slotFlag, PutType.ForcePut);
+
+    [CommandImplementation("put")]
+    public EntityUid? InventoryPut([PipedArgument] IEnumerable<EntityUid> ents,
+        EntityUid itemEnt,
+        SlotFlags slotFlag) => InventoryPutEnumerableBase(ents, itemEnt, slotFlag, PutType.Put);
+    [CommandImplementation("spawn")]
+    public EntityUid? InventorySpawn([PipedArgument] IEnumerable<EntityUid> ents,
+        EntProtoId itemEnt,
+        SlotFlags slotFlag) => InventorySpawnEnumerableBase(ents, itemEnt, slotFlag, PutType.Put);
+
+    [CommandImplementation("tryput")]
+    public EntityUid? InventoryTryPut([PipedArgument] IEnumerable<EntityUid> ents,
+        EntityUid itemEnt,
+        SlotFlags slotFlag) => InventoryPutEnumerableBase(ents, itemEnt, slotFlag, PutType.Put);
+    [CommandImplementation("tryspawn")]
+    public EntityUid? InventoryTrySpawn([PipedArgument] IEnumerable<EntityUid> ents,
+        EntProtoId itemEnt,
+        SlotFlags slotFlag) => InventorySpawnEnumerableBase(ents, itemEnt, slotFlag, PutType.Put);
+
+    [CommandImplementation("ensure")]
+    public EntityUid? InventoryEnsure([PipedArgument] IEnumerable<EntityUid> ents,
+        EntityUid itemEnt,
+        SlotFlags slotFlag) => InventoryPutEnumerableBase(ents, itemEnt, slotFlag, PutType.Ensure);
+    [CommandImplementation("ensurespawn")]
+    public EntityUid? InventoryEnsureSpawn([PipedArgument] IEnumerable<EntityUid> ents,
+        EntProtoId itemEnt,
+        SlotFlags slotFlag) => InventorySpawnEnumerableBase(ents, itemEnt, slotFlag, PutType.Ensure);
+
+
+    private EntityUid? InventorySpawnEnumerableBase(IEnumerable<EntityUid> targetEnts,
+        EntProtoId itemToInsert,
+        SlotFlags slotFlags,
+        PutType putType)
+    {
+        var entityUids = targetEnts as EntityUid[] ?? targetEnts.ToArray();
+        if (!entityUids.Any())
+            return null;
+
+        var spawnedItem = Spawn(itemToInsert, Transform(entityUids.First()).Coordinates);
+
+        foreach (var entity in entityUids)
+        {
+            var result = InventoryPutBase(entity, spawnedItem, slotFlags, putType);
+            if (result == null)
+                continue;
+            if (!result.Value.Equals(spawnedItem)) Del(spawnedItem);
+            return result;
+        }
+        Del(spawnedItem);
+        return null;
+    }
+    private EntityUid? InventoryPutEnumerableBase(IEnumerable<EntityUid> targetEnts,
+        EntityUid itemToInsert,
+        SlotFlags slotFlags,
+        PutType putType)
+    {
+        foreach (var entity in targetEnts)
+        {
+            var result = InventoryPutBase(entity, itemToInsert, slotFlags, putType);
+            if (result != null)
+                return result;
+        }
+
+        return null;
+    }
+
+    private EntityUid? InventoryPutBase(EntityUid targetEnt,
+        EntityUid itemToInsert,
+        SlotFlags slotFlag,
+        PutType putType)
+    {
+        _inventorySystem ??= GetSys<InventorySystem>();
+
+        if (!EntityManager.TryGetComponent<InventoryComponent>(targetEnt, out var inventory))
+            return null;
+
+
+        foreach (var slot in inventory.Slots)
+        {
+            if ((slot.SlotFlags & slotFlag) == 0)
+                continue;
+
+
+            if (_inventorySystem.TryGetSlotEntity(targetEnt, slot.Name, out var originalItem, inventory))
+            {
+                if (putType == PutType.ForcePut)
+                    EntityManager.DeleteEntity(originalItem);
+                if (putType == PutType.Put)
+                {
+                    if (!_inventorySystem.TryUnequip(targetEnt, slot.Name, force: true, inventory: inventory))
+                        return null;
+                }
+            }
+
+            if (_inventorySystem.TryEquip(targetEnt, itemToInsert, slot.Name, force: true, inventory: inventory))
+                return itemToInsert;
+            else
+                return putType == PutType.Ensure ? originalItem : null;
+        }
+
+        return null;
+    }
+
+    private enum PutType
+    {
+        ForcePut, // Put item in slot, delete old item
+        Put, // Put item in slot, put old item on floor
+        TryPut, // Put item in slot, fail if there is already an item
+        Ensure // Try put item in slot. If there is one, return the item already there
+    }
+}
diff --git a/Content.Server/Storage/StorageCommand.cs b/Content.Server/Storage/StorageCommand.cs
new file mode 100644 (file)
index 0000000..b7aee26
--- /dev/null
@@ -0,0 +1,58 @@
+using System.Linq;
+using Content.Server.Administration;
+using Content.Shared.Administration;
+using Content.Shared.Item;
+using Content.Shared.Storage;
+using Content.Shared.Storage.EntitySystems;
+using Robust.Shared.Containers;
+using Robust.Shared.Toolshed;
+
+namespace Content.Server.Storage;
+
+[ToolshedCommand, AdminCommand(AdminFlags.Debug)]
+public sealed class StorageCommand : ToolshedCommand
+{
+    private SharedStorageSystem? _storage;
+    private SharedContainerSystem? _container;
+
+
+    [CommandImplementation("insert")]
+    public IEnumerable<EntityUid> StorageInsert([PipedArgument] IEnumerable<EntityUid> entsToInsert,
+        EntityUid targetEnt) => entsToInsert.Where(x => StorageInsert(x, targetEnt) != null);
+
+    public EntityUid? StorageInsert(EntityUid entToInsert, EntityUid targetEnt)
+    {
+        _storage ??= GetSys<SharedStorageSystem>();
+
+        if (!EntityManager.TryGetComponent<StorageComponent>(targetEnt, out var storage))
+            return null;
+
+        return _storage.Insert(targetEnt, entToInsert, out var stackedEntity, null, storage, false)
+            ? entToInsert
+            : null;
+    }
+
+
+    [CommandImplementation("fasttake")]
+    public IEnumerable<EntityUid> StorageFastTake([PipedArgument] IEnumerable<EntityUid> storageEnts) =>
+        storageEnts.Select(StorageFastTake).OfType<EntityUid>();
+
+    public EntityUid? StorageFastTake(EntityUid storageEnt)
+    {
+        _storage ??= GetSys<SharedStorageSystem>();
+        _container ??= GetSys<SharedContainerSystem>();
+
+
+        if (!EntityManager.TryGetComponent<StorageComponent>(storageEnt, out var storage))
+            return null;
+
+        var removing = storage.Container.ContainedEntities[^1];
+        if (_container.RemoveEntity(storageEnt, removing))
+            return removing;
+
+        return null;
+    }
+
+
+
+}
index 33bf53f9e3676e612fe57f807de177da5c6a6267..2e3c395198036af88e1b0a03db76c2bcab4f42b0 100644 (file)
@@ -106,6 +106,30 @@ command-description-scale-multiplyvector =
     Multiply an entity's sprite size with a certain 2d vector (without changing its fixture).
 command-description-scale-multiplywithfixture =
     Multiply an entity's sprite size with a certain factor (including its fixture).
+command-description-storage-fasttake =
+    Takes the most recently placed item from the piped storage entity.
+command-description-storage-insert =
+    Inserts the piped entity into the given storage entity.
+command-description-inventory-getflags =
+    Gets all entities in slots on the piped inventory entity matching a certain slot flag.
+command-description-inventory-getnamed =
+    Gets all entities in slots on the piped inventory entity matching a certain slot name.
+command-description-inventory-forceput =
+    Puts a given entity on the first piped entity that has a slot matching the given flag, deleting any item previously in that slot.
+command-description-inventory-forcespawn =
+    Spawns a given prototype on the first piped entity that has a slot matching the given flag, deleting any item previously in that slot.
+command-description-inventory-put =
+    Puts a given entity on the first piped entity that has a slot matching the given flag, unequiping any item previously in that slot.
+command-description-inventory-spawn =
+    Spawns a given prototype on the first piped entity that has a slot matching the given flag, unequiping any item previously in that slot.
+command-description-inventory-tryput =
+    Tries to put a given entity on the first piped entity that has a slot matching the given flag, failing if any item is in currently in that slot.
+command-description-inventory-tryspawn =
+    Tries to spawn a given prototype on the first piped entity that has a slot matching the given flag, failing if any item is in currently in that slot.
+command-description-inventory-ensure =
+    Puts a given entity on the first piped entity that has a slot matching the given flag if none exists, passing through the UID of whatever is in the slot by the end.
+command-description-inventory-ensurespawn =
+    Spawns a given prototype on the first piped entity that has a slot matching the given flag if none exists, passing through the UID of whatever is in the slot by the end.
 command-description-dynamicrule-list =
     Lists all currently active dynamic rules, usually this is just one.
 command-description-dynamicrule-get =