]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Make reagent dispensers gridinv-based instead of pseudo-listinv (#34205)
authorpathetic meowmeow <uhhadd@gmail.com>
Sat, 10 May 2025 03:49:05 +0000 (23:49 -0400)
committerGitHub <noreply@github.com>
Sat, 10 May 2025 03:49:05 +0000 (23:49 -0400)
This simplifies the code and makes the experience of examining contents
easier without the reagent dispenser UI, as well as adding the possibility
for dispensers to have items of heterogeneous sizes in them, which would
allow configuring reagent dispensers to accept smaller containers such
as beakers or vials in order to allow for more types of smaller quantities
of reagents, or other flexibilities brought by using a standard storage
component.

13 files changed:
Content.Client/Chemistry/UI/ReagentCardControl.xaml.cs
Content.Client/Chemistry/UI/ReagentDispenserBoundUserInterface.cs
Content.Client/Chemistry/UI/ReagentDispenserWindow.xaml.cs
Content.Server/Chemistry/Components/ReagentDispenserComponent.cs
Content.Server/Chemistry/EntitySystems/ReagentDispenserSystem.cs
Content.Shared/Chemistry/Dispenser/ReagentDispenserInventoryPrototype.cs [deleted file]
Content.Shared/Chemistry/SharedReagentDispenser.cs
Resources/Prototypes/Catalog/ReagentDispensers/beverage.yml [deleted file]
Resources/Prototypes/Catalog/ReagentDispensers/chemical.yml [deleted file]
Resources/Prototypes/Entities/Structures/Dispensers/base_structuredispensers.yml
Resources/Prototypes/Entities/Structures/Dispensers/booze.yml
Resources/Prototypes/Entities/Structures/Dispensers/chem.yml
Resources/Prototypes/Entities/Structures/Dispensers/soda.yml

index f7cadcc264d09c878b11b59ffe1d0f7fb5a906d4..b23b6eae06f978b78b9ef2a65ee10e63a9482eed 100644 (file)
@@ -1,4 +1,5 @@
 using Content.Shared.Chemistry;
+using Content.Shared.Storage;
 using Robust.Client.AutoGenerated;
 using Robust.Client.Graphics;
 using Robust.Client.UserInterface;
@@ -9,15 +10,15 @@ namespace Content.Client.Chemistry.UI;
 [GenerateTypedNameReferences]
 public sealed partial class ReagentCardControl : Control
 {
-    public string StorageSlotId { get; }
-    public Action<string>? OnPressed;
-    public Action<string>? OnEjectButtonPressed;
+    public ItemStorageLocation StorageLocation { get; }
+    public Action<ItemStorageLocation>? OnPressed;
+    public Action<ItemStorageLocation>? OnEjectButtonPressed;
 
     public ReagentCardControl(ReagentInventoryItem item)
     {
         RobustXamlLoader.Load(this);
 
-        StorageSlotId = item.StorageSlotId;
+        StorageLocation = item.StorageLocation;
         ColorPanel.PanelOverride = new StyleBoxFlat { BackgroundColor = item.ReagentColor };
         ReagentNameLabel.Text = item.ReagentLabel;
         FillLabel.Text = Loc.GetString("reagent-dispenser-window-quantity-label-text", ("quantity", item.Quantity));;
@@ -26,7 +27,7 @@ public sealed partial class ReagentCardControl : Control
         if (item.Quantity == 0.0)
             MainButton.Disabled = true;
 
-        MainButton.OnPressed += args => OnPressed?.Invoke(StorageSlotId);
-        EjectButton.OnPressed += args => OnEjectButtonPressed?.Invoke(StorageSlotId);
+        MainButton.OnPressed += args => OnPressed?.Invoke(StorageLocation);
+        EjectButton.OnPressed += args => OnEjectButtonPressed?.Invoke(StorageLocation);
     }
 }
index b0f2a77eed646fcd9ead17e90de4e857f00538c6..8f19a6cc04f45ca6ac56702ca69e2a51468ad31c 100644 (file)
@@ -40,8 +40,8 @@ namespace Content.Client.Chemistry.UI
 
             _window.AmountGrid.OnButtonPressed += s => SendMessage(new ReagentDispenserSetDispenseAmountMessage(s));
 
-            _window.OnDispenseReagentButtonPressed += (id) => SendMessage(new ReagentDispenserDispenseReagentMessage(id));
-            _window.OnEjectJugButtonPressed += (id) => SendMessage(new ItemSlotButtonPressedEvent(id));
+            _window.OnDispenseReagentButtonPressed += (location) => SendMessage(new ReagentDispenserDispenseReagentMessage(location));
+            _window.OnEjectJugButtonPressed += (location) => SendMessage(new ReagentDispenserEjectContainerMessage(location));
         }
 
         /// <summary>
index c462dbfc6955e4d08faf6c7a877ff6ac70c2962b..2b64eed57089394191f5502333fb84c64084ffb2 100644 (file)
@@ -2,6 +2,7 @@ using Content.Client.Stylesheets;
 using Content.Client.UserInterface.Controls;
 using Content.Shared.Chemistry;
 using Content.Shared.Chemistry.Reagent;
+using Content.Shared.Storage;
 using Robust.Client.AutoGenerated;
 using Robust.Client.UserInterface.Controls;
 using Robust.Client.UserInterface.XAML;
@@ -18,8 +19,8 @@ namespace Content.Client.Chemistry.UI
     {
         [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
         [Dependency] private readonly IEntityManager _entityManager = default!;
-        public event Action<string>? OnDispenseReagentButtonPressed;
-        public event Action<string>? OnEjectJugButtonPressed;
+        public event Action<ItemStorageLocation>? OnDispenseReagentButtonPressed;
+        public event Action<ItemStorageLocation>? OnEjectJugButtonPressed;
 
         /// <summary>
         /// Create and initialize the dispenser UI client-side. Creates the basic layout,
index eb1839ef2ec4c474375dcf9a396ddbaf7e61265f..e296f8358a1f9b41694e8d2ef90c602d9dae0888 100644 (file)
@@ -2,7 +2,6 @@ using Content.Shared.Whitelist;
 using Content.Shared.Containers.ItemSlots;
 using Content.Server.Chemistry.EntitySystems;
 using Content.Shared.Chemistry;
-using Content.Shared.Chemistry.Dispenser;
 using Robust.Shared.Audio;
 using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
 
@@ -15,47 +14,9 @@ namespace Content.Server.Chemistry.Components
     [Access(typeof(ReagentDispenserSystem))]
     public sealed partial class ReagentDispenserComponent : Component
     {
-        /// <summary>
-        /// String with the pack name that stores the initial fill of the dispenser. The initial
-        /// fill is added to the dispenser on MapInit. Note that we don't use ContainerFill because
-        /// we have to generate the storage slots at MapInit first, then fill them.
-        /// </summary>
-        [DataField("pack", customTypeSerializer:typeof(PrototypeIdSerializer<ReagentDispenserInventoryPrototype>))]
-        [ViewVariables(VVAccess.ReadWrite)]
-        public string? PackPrototypeId = default!;
-
-        /// <summary>
-        /// Maximum number of internal storage slots. Dispenser can't store (or dispense) more than
-        /// this many chemicals (without unloading and reloading).
-        /// </summary>
-        [DataField("numStorageSlots")]
-        public int NumSlots = 25;
-
-        /// <summary>
-        /// For each created storage slot for the reagent containers being dispensed, apply this
-        /// entity whitelist. Makes sure weird containers don't fit in the dispenser and that beakers
-        /// don't accidentally get slotted into the source slots.
-        /// </summary>
-        [DataField]
-        public EntityWhitelist? StorageWhitelist;
-
         [DataField]
         public ItemSlot BeakerSlot = new();
 
-        /// <summary>
-        /// Prefix for automatically-generated slot name for storage, up to NumSlots.
-        /// </summary>
-        public static string BaseStorageSlotId = "ReagentDispenser-storageSlot";
-
-        /// <summary>
-        /// List of storage slots that were created at MapInit.
-        /// </summary>
-        [DataField]
-        public List<string> StorageSlotIds = new List<string>();
-
-        [DataField]
-        public List<ItemSlot> StorageSlots = new List<ItemSlot>();
-
         [DataField("clickSound"), ViewVariables(VVAccess.ReadWrite)]
         public SoundSpecifier ClickSound = new SoundPathSpecifier("/Audio/Machines/machine_switch.ogg");
 
index f8d4a7efcd563697098b8ffbc4bf0acd91911475..3dc3cff2ec3de233c3ab51aae9273e125c4b1bdd 100644 (file)
@@ -1,11 +1,12 @@
+using System.Linq;
 using Content.Server.Chemistry.Components;
 using Content.Server.Chemistry.Containers.EntitySystems;
 using Content.Shared.Chemistry;
-using Content.Shared.Chemistry.Dispenser;
 using Content.Shared.Chemistry.EntitySystems;
 using Content.Shared.Containers.ItemSlots;
 using Content.Shared.FixedPoint;
 using Content.Shared.Nutrition.EntitySystems;
+using Content.Shared.Storage.EntitySystems;
 using JetBrains.Annotations;
 using Robust.Server.Audio;
 using Robust.Server.GameObjects;
@@ -13,6 +14,8 @@ using Robust.Shared.Audio;
 using Robust.Shared.Containers;
 using Robust.Shared.Prototypes;
 using Content.Shared.Labels.Components;
+using Content.Shared.Storage;
+using Content.Server.Hands.Systems;
 
 namespace Content.Server.Chemistry.EntitySystems
 {
@@ -30,6 +33,7 @@ namespace Content.Server.Chemistry.EntitySystems
         [Dependency] private readonly UserInterfaceSystem _userInterfaceSystem = default!;
         [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
         [Dependency] private readonly OpenableSystem _openable = default!;
+        [Dependency] private readonly HandsSystem _handsSystem = default!;
 
         public override void Initialize()
         {
@@ -37,12 +41,13 @@ namespace Content.Server.Chemistry.EntitySystems
 
             SubscribeLocalEvent<ReagentDispenserComponent, ComponentStartup>(SubscribeUpdateUiState);
             SubscribeLocalEvent<ReagentDispenserComponent, SolutionContainerChangedEvent>(SubscribeUpdateUiState);
-            SubscribeLocalEvent<ReagentDispenserComponent, EntInsertedIntoContainerMessage>(SubscribeUpdateUiState);
-            SubscribeLocalEvent<ReagentDispenserComponent, EntRemovedFromContainerMessage>(SubscribeUpdateUiState);
+            SubscribeLocalEvent<ReagentDispenserComponent, EntInsertedIntoContainerMessage>(SubscribeUpdateUiState, after: [typeof(SharedStorageSystem)]);
+            SubscribeLocalEvent<ReagentDispenserComponent, EntRemovedFromContainerMessage>(SubscribeUpdateUiState, after: [typeof(SharedStorageSystem)]);
             SubscribeLocalEvent<ReagentDispenserComponent, BoundUIOpenedEvent>(SubscribeUpdateUiState);
 
             SubscribeLocalEvent<ReagentDispenserComponent, ReagentDispenserSetDispenseAmountMessage>(OnSetDispenseAmountMessage);
             SubscribeLocalEvent<ReagentDispenserComponent, ReagentDispenserDispenseReagentMessage>(OnDispenseReagentMessage);
+            SubscribeLocalEvent<ReagentDispenserComponent, ReagentDispenserEjectContainerMessage>(OnEjectReagentMessage);
             SubscribeLocalEvent<ReagentDispenserComponent, ReagentDispenserClearContainerSolutionMessage>(OnClearContainerSolutionMessage);
 
             SubscribeLocalEvent<ReagentDispenserComponent, MapInitEvent>(OnMapInit, before: new []{typeof(ItemSlotsSystem)});
@@ -82,32 +87,31 @@ namespace Content.Server.Chemistry.EntitySystems
 
         private List<ReagentInventoryItem> GetInventory(Entity<ReagentDispenserComponent> reagentDispenser)
         {
+            if (!TryComp<StorageComponent>(reagentDispenser.Owner, out var storage))
+            {
+                return [];
+            }
+
             var inventory = new List<ReagentInventoryItem>();
 
-            for (var i = 0; i < reagentDispenser.Comp.NumSlots; i++)
+            foreach (var (storedContainer, storageLocation) in storage.StoredItems)
             {
-                var storageSlotId = ReagentDispenserComponent.BaseStorageSlotId + i;
-                var storedContainer = _itemSlotsSystem.GetItemOrNull(reagentDispenser.Owner, storageSlotId);
-
-                // Set label from manually-applied label, or metadata if unavailable
                 string reagentLabel;
                 if (TryComp<LabelComponent>(storedContainer, out var label) && !string.IsNullOrEmpty(label.CurrentLabel))
                     reagentLabel = label.CurrentLabel;
-                else if (storedContainer != null)
-                    reagentLabel = Name(storedContainer.Value);
                 else
-                    continue;
+                    reagentLabel = Name(storedContainer);
 
                 // Get volume remaining and color of solution
                 FixedPoint2 quantity = 0f;
                 var reagentColor = Color.White;
-                if (storedContainer != null && _solutionContainerSystem.TryGetDrainableSolution(storedContainer.Value, out _, out var sol))
+                if (_solutionContainerSystem.TryGetDrainableSolution(storedContainer, out _, out var sol))
                 {
                     quantity = sol.Volume;
                     reagentColor = sol.GetColor(_prototypeManager);
                 }
 
-                inventory.Add(new ReagentInventoryItem(storageSlotId, reagentLabel, quantity, reagentColor));
+                inventory.Add(new ReagentInventoryItem(storageLocation, reagentLabel, quantity, reagentColor));
             }
 
             return inventory;
@@ -122,8 +126,14 @@ namespace Content.Server.Chemistry.EntitySystems
 
         private void OnDispenseReagentMessage(Entity<ReagentDispenserComponent> reagentDispenser, ref ReagentDispenserDispenseReagentMessage message)
         {
+            if (!TryComp<StorageComponent>(reagentDispenser.Owner, out var storage))
+            {
+                return;
+            }
+
             // Ensure that the reagent is something this reagent dispenser can dispense.
-            var storedContainer = _itemSlotsSystem.GetItemOrNull(reagentDispenser, message.SlotId);
+            var storageLocation = message.StorageLocation;
+            var storedContainer = storage.StoredItems.FirstOrDefault(kvp => kvp.Value == storageLocation).Key;
             if (storedContainer == null)
                 return;
 
@@ -131,13 +141,13 @@ namespace Content.Server.Chemistry.EntitySystems
             if (outputContainer is not { Valid: true } || !_solutionContainerSystem.TryGetFitsInDispenser(outputContainer.Value, out var solution, out _))
                 return;
 
-            if (_solutionContainerSystem.TryGetDrainableSolution(storedContainer.Value, out var src, out _) &&
+            if (_solutionContainerSystem.TryGetDrainableSolution(storedContainer, out var src, out _) &&
                 _solutionContainerSystem.TryGetRefillableSolution(outputContainer.Value, out var dst, out _))
             {
                 // force open container, if applicable, to avoid confusing people on why it doesn't dispense
-                _openable.SetOpen(storedContainer.Value, true);
+                _openable.SetOpen(storedContainer, true);
                 _solutionTransferSystem.Transfer(reagentDispenser,
-                        storedContainer.Value, src.Value,
+                        storedContainer, src.Value,
                         outputContainer.Value, dst.Value,
                         (int)reagentDispenser.Comp.DispenseAmount);
             }
@@ -146,6 +156,21 @@ namespace Content.Server.Chemistry.EntitySystems
             ClickSound(reagentDispenser);
         }
 
+        private void OnEjectReagentMessage(Entity<ReagentDispenserComponent> reagentDispenser, ref ReagentDispenserEjectContainerMessage message)
+        {
+            if (!TryComp<StorageComponent>(reagentDispenser.Owner, out var storage))
+            {
+                return;
+            }
+
+            var storageLocation = message.StorageLocation;
+            var storedContainer = storage.StoredItems.FirstOrDefault(kvp => kvp.Value == storageLocation).Key;
+            if (storedContainer == null)
+                return;
+
+            _handsSystem.TryPickupAnyHand(message.Actor, storedContainer);
+        }
+
         private void OnClearContainerSolutionMessage(Entity<ReagentDispenserComponent> reagentDispenser, ref ReagentDispenserClearContainerSolutionMessage message)
         {
             var outputContainer = _itemSlotsSystem.GetItemOrNull(reagentDispenser, SharedReagentDispenser.OutputSlotName);
@@ -163,39 +188,11 @@ namespace Content.Server.Chemistry.EntitySystems
         }
 
         /// <summary>
-        /// Automatically generate storage slots for all NumSlots, and fill them with their initial chemicals.
-        /// The actual spawning of entities happens in ItemSlotsSystem's MapInit.
+        /// Initializes the beaker slot
         /// </summary>
-        private void OnMapInit(EntityUid uid, ReagentDispenserComponent component, MapInitEvent args)
+        private void OnMapInit(Entity<ReagentDispenserComponent> ent, ref MapInitEvent args)
         {
-            // Get list of pre-loaded containers
-            List<string> preLoad = new List<string>();
-            if (component.PackPrototypeId is not null
-                && _prototypeManager.TryIndex(component.PackPrototypeId, out ReagentDispenserInventoryPrototype? packPrototype))
-            {
-                preLoad.AddRange(packPrototype.Inventory);
-            }
-
-            // Populate storage slots with base storage slot whitelist
-            for (var i = 0; i < component.NumSlots; i++)
-            {
-                var storageSlotId = ReagentDispenserComponent.BaseStorageSlotId + i;
-                ItemSlot storageComponent = new();
-                storageComponent.Whitelist = component.StorageWhitelist;
-                storageComponent.Swap = false;
-                storageComponent.EjectOnBreak = true;
-
-                // Check corresponding index in pre-loaded container (if exists) and set starting item
-                if (i < preLoad.Count)
-                    storageComponent.StartingItem = preLoad[i];
-
-                component.StorageSlotIds.Add(storageSlotId);
-                component.StorageSlots.Add(storageComponent);
-                component.StorageSlots[i].Name = "Storage Slot " + (i+1);
-                _itemSlotsSystem.AddItemSlot(uid, component.StorageSlotIds[i], component.StorageSlots[i]);
-            }
-
-            _itemSlotsSystem.AddItemSlot(uid, SharedReagentDispenser.OutputSlotName, component.BeakerSlot);
+            _itemSlotsSystem.AddItemSlot(ent.Owner, SharedReagentDispenser.OutputSlotName, ent.Comp.BeakerSlot);
         }
     }
 }
diff --git a/Content.Shared/Chemistry/Dispenser/ReagentDispenserInventoryPrototype.cs b/Content.Shared/Chemistry/Dispenser/ReagentDispenserInventoryPrototype.cs
deleted file mode 100644 (file)
index 7d1399a..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-using Content.Shared.Chemistry.Reagent;
-using Robust.Shared.Prototypes;
-using Robust.Shared.Serialization;
-using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
-
-namespace Content.Shared.Chemistry.Dispenser
-{
-    /// <summary>
-    /// Is simply a list of reagents defined in yaml. This can then be set as a
-    /// <see cref="SharedReagentDispenserComponent"/>s <c>pack</c> value (also in yaml),
-    /// to define which reagents it's able to dispense. Based off of how vending
-    /// machines define their inventory.
-    /// </summary>
-    [Serializable, NetSerializable, Prototype]
-    public sealed partial class ReagentDispenserInventoryPrototype : IPrototype
-    {
-        [DataField("inventory", customTypeSerializer: typeof(PrototypeIdListSerializer<EntityPrototype>))]
-        public List<string> Inventory = new();
-
-        [ViewVariables, IdDataField]
-        public string ID { get; private set; } = default!;
-    }
-}
index c7ecd0ff439984af96eb84b31c5759056faa5bff..65b7cc41fce86c520dd78064580f3497f540d896 100644 (file)
@@ -1,5 +1,6 @@
 using Content.Shared.Chemistry.Reagent;
 using Content.Shared.FixedPoint;
+using Content.Shared.Storage;
 using Robust.Shared.Serialization;
 
 namespace Content.Shared.Chemistry
@@ -66,11 +67,25 @@ namespace Content.Shared.Chemistry
     [Serializable, NetSerializable]
     public sealed class ReagentDispenserDispenseReagentMessage : BoundUserInterfaceMessage
     {
-        public readonly string SlotId;
+        public readonly ItemStorageLocation StorageLocation;
 
-        public ReagentDispenserDispenseReagentMessage(string slotId)
+        public ReagentDispenserDispenseReagentMessage(ItemStorageLocation storageLocation)
         {
-            SlotId = slotId;
+            StorageLocation = storageLocation;
+        }
+    }
+
+    /// <summary>
+    ///     Message sent by the user interface to ask the reagent dispenser to eject a container
+    /// </summary>
+    [Serializable, NetSerializable]
+    public sealed class ReagentDispenserEjectContainerMessage : BoundUserInterfaceMessage
+    {
+        public readonly ItemStorageLocation StorageLocation;
+
+        public ReagentDispenserEjectContainerMessage(ItemStorageLocation storageLocation)
+        {
+            StorageLocation = storageLocation;
         }
     }
 
@@ -94,9 +109,9 @@ namespace Content.Shared.Chemistry
     }
 
     [Serializable, NetSerializable]
-    public sealed class ReagentInventoryItem(string storageSlotId, string reagentLabel, FixedPoint2 quantity, Color reagentColor)
+    public sealed class ReagentInventoryItem(ItemStorageLocation storageLocation, string reagentLabel, FixedPoint2 quantity, Color reagentColor)
     {
-        public string StorageSlotId = storageSlotId;
+        public ItemStorageLocation StorageLocation = storageLocation;
         public string ReagentLabel = reagentLabel;
         public FixedPoint2 Quantity = quantity;
         public Color ReagentColor = reagentColor;
diff --git a/Resources/Prototypes/Catalog/ReagentDispensers/beverage.yml b/Resources/Prototypes/Catalog/ReagentDispensers/beverage.yml
deleted file mode 100644 (file)
index 4689e26..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-- type: reagentDispenserInventory
-  id: SodaDispenserInventory
-  inventory:
-  - DrinkCoconutWaterJug
-  - DrinkCoffeeJug
-  - DrinkColaBottleFull
-  - DrinkCreamCartonXL
-  - DrinkDrGibbJug
-  - DrinkEnergyDrinkJug
-  - DrinkGreenTeaJug
-  - DrinkIceJug
-  - DrinkJuiceLimeCartonXL
-  - DrinkJuiceOrangeCartonXL
-  - DrinkLemonLimeJug
-  - DrinkRootBeerJug
-  - DrinkSodaWaterBottleFull
-  - DrinkSpaceMountainWindBottleFull
-  - DrinkSpaceUpBottleFull
-  - DrinkSugarJug
-  - DrinkTeaJug
-  - DrinkTonicWaterBottleFull
-  - DrinkWaterMelonJuiceJug
-
-- type: reagentDispenserInventory
-  id: BoozeDispenserInventory
-  inventory:
-  - DrinkAleBottleFullGrowler
-  - DrinkBeerGrowler
-  - DrinkCoffeeLiqueurBottleFull
-  - DrinkCognacBottleFull
-  - DrinkGinBottleFull
-  - DrinkMeadJug
-  - DrinkRumBottleFull
-  - DrinkTequilaBottleFull
-  - DrinkVermouthBottleFull
-  - DrinkVodkaBottleFull
-  - DrinkWhiskeyBottleFull
-  - DrinkWineBottleFull
diff --git a/Resources/Prototypes/Catalog/ReagentDispensers/chemical.yml b/Resources/Prototypes/Catalog/ReagentDispensers/chemical.yml
deleted file mode 100644 (file)
index 2b0fdfa..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-- type: reagentDispenserInventory
-  id: ChemDispenserStandardInventory
-  inventory:
-  - JugAluminium
-  - JugCarbon
-  - JugChlorine
-  - JugCopper
-  - JugEthanol
-  - JugFluorine
-  - JugSugar
-  - JugHydrogen
-  - JugIodine
-  - JugIron
-  - JugLithium
-  - JugMercury
-  - JugNitrogen
-  - JugOxygen
-  - JugPhosphorus
-  - JugPotassium
-  - JugRadium
-  - JugSilicon
-  - JugSodium
-  - JugSulfur
-
-- type: reagentDispenserInventory
-  id: EmptyInventory
index 31e233625a318221ea992af839416f463e24d059..e9797ee24ac572bef9295842d635fae236e3bf82 100644 (file)
@@ -32,6 +32,8 @@
     interfaces:
       enum.ReagentDispenserUiKey.Key:
         type: ReagentDispenserBoundUserInterface
+      enum.StorageUiKey.Key:
+        type: StorageBoundUserInterface
   - type: Anchorable
   - type: Pullable
   - type: Damageable
       - !type:PlaySoundBehavior
         sound:
           collection: MetalGlassBreak
+  - type: Storage
+    maxItemSize: Normal
+    grid:
+    - 0,0,19,5
   - type: ReagentDispenser
-    storageWhitelist:
-      tags:
-      - Bottle
     beakerSlot:
       whitelistFailPopup: reagent-dispenser-component-cannot-put-entity-message
       whitelist:
@@ -70,6 +73,7 @@
       machine_board: !type:Container
       machine_parts: !type:Container
       beakerSlot: !type:ContainerSlot
+      storagebase: !type:Container
   - type: StaticPrice
     price: 1000
   - type: WiresPanel
index b0f238c3034be0794823e1280867ebb8479c4450..232bdc7d98b703834232ce92e1cef7145b5f56f2 100644 (file)
     sprite: Structures/smalldispensers.rsi
     drawdepth: SmallObjects
     state: booze
-  - type: ReagentDispenser
-    storageWhitelist:
+  - type: Storage
+    whitelist:
       tags:
       - DrinkBottle
-    pack: BoozeDispenserInventory
+  - type: StorageFill
+    contents:
+    - id: DrinkAleBottleFullGrowler
+    - id: DrinkBeerGrowler
+    - id: DrinkCoffeeLiqueurBottleFull
+    - id: DrinkCognacBottleFull
+    - id: DrinkGinBottleFull
+    - id: DrinkMeadJug
+    - id: DrinkRumBottleFull
+    - id: DrinkTequilaBottleFull
+    - id: DrinkVermouthBottleFull
+    - id: DrinkVodkaBottleFull
+    - id: DrinkWhiskeyBottleFull
+    - id: DrinkWineBottleFull
   - type: Transform
     noRot: false
   - type: Machine
@@ -31,8 +44,7 @@
   suffix: Empty
   parent: BoozeDispenser
   components:
-  - type: ReagentDispenser
-    storageWhitelist:
+  - type: Storage
+    whitelist:
       tags:
       - DrinkBottle
-    pack: EmptyInventory
index cf51ca9b1f6d59c39d5e06442c65d8139768f46a..3ecb6f79b68ee97311fde33616eccb94bd555601 100644 (file)
@@ -1,7 +1,7 @@
 - type: entity
-  id: ChemDispenser
+  id: ChemDispenserEmpty
   name: chemical dispenser
-  suffix: Filled
+  suffix: Empty
   parent: ReagentDispenserBase
   description: An industrial grade chemical dispenser.
   components:
@@ -9,11 +9,10 @@
     sprite: Structures/dispensers.rsi
     state: industrial-working
     snapCardinals: true
-  - type: ReagentDispenser
-    storageWhitelist:
+  - type: Storage
+    whitelist:
       tags:
       - ChemDispensable
-    pack: ChemDispenserStandardInventory
   - type: ApcPowerReceiver
   - type: ExtensionCableReceiver
   - type: Destructible
         - MachineLayer
 
 - type: entity
-  id: ChemDispenserEmpty
+  id: ChemDispenser
   name: chemical dispenser
-  suffix: Empty
-  parent: ChemDispenser
+  suffix: Filled
+  parent: ChemDispenserEmpty
   components:
   - type: ReagentDispenser
-    pack: EmptyInventory
+  - type: StorageFill
+    contents:
+      - id: JugAluminium
+      - id: JugCarbon
+      - id: JugChlorine
+      - id: JugCopper
+      - id: JugEthanol
+      - id: JugFluorine
+      - id: JugSugar
+      - id: JugHydrogen
+      - id: JugIodine
+      - id: JugIron
+      - id: JugLithium
+      - id: JugMercury
+      - id: JugNitrogen
+      - id: JugOxygen
+      - id: JugPhosphorus
+      - id: JugPotassium
+      - id: JugRadium
+      - id: JugSilicon
+      - id: JugSodium
+      - id: JugSulfur
index f44745cdd202b7362da7d5aa80c6ab0888f7c9de..5db1f2484bc7de917dfa70fa5b2aa55eb82ab5d6 100644 (file)
     sprite: Structures/smalldispensers.rsi
     drawdepth: SmallObjects
     state: soda
-  - type: ReagentDispenser
-    storageWhitelist:
+  - type: Storage
+    whitelist:
       tags:
       - DrinkBottle
-    pack: SodaDispenserInventory
+  - type: StorageFill
+    contents:
+    - id: DrinkCoconutWaterJug
+    - id: DrinkCoffeeJug
+    - id: DrinkColaBottleFull
+    - id: DrinkCreamCartonXL
+    - id: DrinkDrGibbJug
+    - id: DrinkEnergyDrinkJug
+    - id: DrinkGreenTeaJug
+    - id: DrinkIceJug
+    - id: DrinkJuiceLimeCartonXL
+    - id: DrinkJuiceOrangeCartonXL
+    - id: DrinkLemonLimeJug
+    - id: DrinkRootBeerJug
+    - id: DrinkSodaWaterBottleFull
+    - id: DrinkSpaceMountainWindBottleFull
+    - id: DrinkSpaceUpBottleFull
+    - id: DrinkSugarJug
+    - id: DrinkTeaJug
+    - id: DrinkTonicWaterBottleFull
+    - id: DrinkWaterMelonJuiceJug
   - type: Transform
     noRot: false
   - type: Machine
@@ -28,9 +48,3 @@
   parent: SodaDispenser
   id: SodaDispenserEmpty
   suffix: Empty
-  components:
-  - type: ReagentDispenser
-    storageWhitelist:
-      tags:
-      - DrinkBottle
-    pack: EmptyInventory