Make reagent dispensers gridinv-based instead of pseudo-listinv (#34205)

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.
This commit is contained in:
pathetic meowmeow
2025-05-09 23:49:05 -04:00
committed by GitHub
parent 942b2b4dcb
commit 5a0e0524ca
13 changed files with 154 additions and 216 deletions

View File

@@ -1,4 +1,5 @@
using Content.Shared.Chemistry; using Content.Shared.Chemistry;
using Content.Shared.Storage;
using Robust.Client.AutoGenerated; using Robust.Client.AutoGenerated;
using Robust.Client.Graphics; using Robust.Client.Graphics;
using Robust.Client.UserInterface; using Robust.Client.UserInterface;
@@ -9,15 +10,15 @@ namespace Content.Client.Chemistry.UI;
[GenerateTypedNameReferences] [GenerateTypedNameReferences]
public sealed partial class ReagentCardControl : Control public sealed partial class ReagentCardControl : Control
{ {
public string StorageSlotId { get; } public ItemStorageLocation StorageLocation { get; }
public Action<string>? OnPressed; public Action<ItemStorageLocation>? OnPressed;
public Action<string>? OnEjectButtonPressed; public Action<ItemStorageLocation>? OnEjectButtonPressed;
public ReagentCardControl(ReagentInventoryItem item) public ReagentCardControl(ReagentInventoryItem item)
{ {
RobustXamlLoader.Load(this); RobustXamlLoader.Load(this);
StorageSlotId = item.StorageSlotId; StorageLocation = item.StorageLocation;
ColorPanel.PanelOverride = new StyleBoxFlat { BackgroundColor = item.ReagentColor }; ColorPanel.PanelOverride = new StyleBoxFlat { BackgroundColor = item.ReagentColor };
ReagentNameLabel.Text = item.ReagentLabel; ReagentNameLabel.Text = item.ReagentLabel;
FillLabel.Text = Loc.GetString("reagent-dispenser-window-quantity-label-text", ("quantity", item.Quantity));; 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) if (item.Quantity == 0.0)
MainButton.Disabled = true; MainButton.Disabled = true;
MainButton.OnPressed += args => OnPressed?.Invoke(StorageSlotId); MainButton.OnPressed += args => OnPressed?.Invoke(StorageLocation);
EjectButton.OnPressed += args => OnEjectButtonPressed?.Invoke(StorageSlotId); EjectButton.OnPressed += args => OnEjectButtonPressed?.Invoke(StorageLocation);
} }
} }

View File

@@ -40,8 +40,8 @@ namespace Content.Client.Chemistry.UI
_window.AmountGrid.OnButtonPressed += s => SendMessage(new ReagentDispenserSetDispenseAmountMessage(s)); _window.AmountGrid.OnButtonPressed += s => SendMessage(new ReagentDispenserSetDispenseAmountMessage(s));
_window.OnDispenseReagentButtonPressed += (id) => SendMessage(new ReagentDispenserDispenseReagentMessage(id)); _window.OnDispenseReagentButtonPressed += (location) => SendMessage(new ReagentDispenserDispenseReagentMessage(location));
_window.OnEjectJugButtonPressed += (id) => SendMessage(new ItemSlotButtonPressedEvent(id)); _window.OnEjectJugButtonPressed += (location) => SendMessage(new ReagentDispenserEjectContainerMessage(location));
} }
/// <summary> /// <summary>

View File

@@ -2,6 +2,7 @@ using Content.Client.Stylesheets;
using Content.Client.UserInterface.Controls; using Content.Client.UserInterface.Controls;
using Content.Shared.Chemistry; using Content.Shared.Chemistry;
using Content.Shared.Chemistry.Reagent; using Content.Shared.Chemistry.Reagent;
using Content.Shared.Storage;
using Robust.Client.AutoGenerated; using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML; using Robust.Client.UserInterface.XAML;
@@ -18,8 +19,8 @@ namespace Content.Client.Chemistry.UI
{ {
[Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IEntityManager _entityManager = default!; [Dependency] private readonly IEntityManager _entityManager = default!;
public event Action<string>? OnDispenseReagentButtonPressed; public event Action<ItemStorageLocation>? OnDispenseReagentButtonPressed;
public event Action<string>? OnEjectJugButtonPressed; public event Action<ItemStorageLocation>? OnEjectJugButtonPressed;
/// <summary> /// <summary>
/// Create and initialize the dispenser UI client-side. Creates the basic layout, /// Create and initialize the dispenser UI client-side. Creates the basic layout,

View File

@@ -2,7 +2,6 @@ using Content.Shared.Whitelist;
using Content.Shared.Containers.ItemSlots; using Content.Shared.Containers.ItemSlots;
using Content.Server.Chemistry.EntitySystems; using Content.Server.Chemistry.EntitySystems;
using Content.Shared.Chemistry; using Content.Shared.Chemistry;
using Content.Shared.Chemistry.Dispenser;
using Robust.Shared.Audio; using Robust.Shared.Audio;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
@@ -15,47 +14,9 @@ namespace Content.Server.Chemistry.Components
[Access(typeof(ReagentDispenserSystem))] [Access(typeof(ReagentDispenserSystem))]
public sealed partial class ReagentDispenserComponent : Component 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] [DataField]
public ItemSlot BeakerSlot = new(); 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)] [DataField("clickSound"), ViewVariables(VVAccess.ReadWrite)]
public SoundSpecifier ClickSound = new SoundPathSpecifier("/Audio/Machines/machine_switch.ogg"); public SoundSpecifier ClickSound = new SoundPathSpecifier("/Audio/Machines/machine_switch.ogg");

View File

@@ -1,11 +1,12 @@
using System.Linq;
using Content.Server.Chemistry.Components; using Content.Server.Chemistry.Components;
using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Chemistry.Containers.EntitySystems;
using Content.Shared.Chemistry; using Content.Shared.Chemistry;
using Content.Shared.Chemistry.Dispenser;
using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Containers.ItemSlots; using Content.Shared.Containers.ItemSlots;
using Content.Shared.FixedPoint; using Content.Shared.FixedPoint;
using Content.Shared.Nutrition.EntitySystems; using Content.Shared.Nutrition.EntitySystems;
using Content.Shared.Storage.EntitySystems;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Server.Audio; using Robust.Server.Audio;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
@@ -13,6 +14,8 @@ using Robust.Shared.Audio;
using Robust.Shared.Containers; using Robust.Shared.Containers;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Content.Shared.Labels.Components; using Content.Shared.Labels.Components;
using Content.Shared.Storage;
using Content.Server.Hands.Systems;
namespace Content.Server.Chemistry.EntitySystems namespace Content.Server.Chemistry.EntitySystems
{ {
@@ -30,6 +33,7 @@ namespace Content.Server.Chemistry.EntitySystems
[Dependency] private readonly UserInterfaceSystem _userInterfaceSystem = default!; [Dependency] private readonly UserInterfaceSystem _userInterfaceSystem = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly OpenableSystem _openable = default!; [Dependency] private readonly OpenableSystem _openable = default!;
[Dependency] private readonly HandsSystem _handsSystem = default!;
public override void Initialize() public override void Initialize()
{ {
@@ -37,12 +41,13 @@ namespace Content.Server.Chemistry.EntitySystems
SubscribeLocalEvent<ReagentDispenserComponent, ComponentStartup>(SubscribeUpdateUiState); SubscribeLocalEvent<ReagentDispenserComponent, ComponentStartup>(SubscribeUpdateUiState);
SubscribeLocalEvent<ReagentDispenserComponent, SolutionContainerChangedEvent>(SubscribeUpdateUiState); SubscribeLocalEvent<ReagentDispenserComponent, SolutionContainerChangedEvent>(SubscribeUpdateUiState);
SubscribeLocalEvent<ReagentDispenserComponent, EntInsertedIntoContainerMessage>(SubscribeUpdateUiState); SubscribeLocalEvent<ReagentDispenserComponent, EntInsertedIntoContainerMessage>(SubscribeUpdateUiState, after: [typeof(SharedStorageSystem)]);
SubscribeLocalEvent<ReagentDispenserComponent, EntRemovedFromContainerMessage>(SubscribeUpdateUiState); SubscribeLocalEvent<ReagentDispenserComponent, EntRemovedFromContainerMessage>(SubscribeUpdateUiState, after: [typeof(SharedStorageSystem)]);
SubscribeLocalEvent<ReagentDispenserComponent, BoundUIOpenedEvent>(SubscribeUpdateUiState); SubscribeLocalEvent<ReagentDispenserComponent, BoundUIOpenedEvent>(SubscribeUpdateUiState);
SubscribeLocalEvent<ReagentDispenserComponent, ReagentDispenserSetDispenseAmountMessage>(OnSetDispenseAmountMessage); SubscribeLocalEvent<ReagentDispenserComponent, ReagentDispenserSetDispenseAmountMessage>(OnSetDispenseAmountMessage);
SubscribeLocalEvent<ReagentDispenserComponent, ReagentDispenserDispenseReagentMessage>(OnDispenseReagentMessage); SubscribeLocalEvent<ReagentDispenserComponent, ReagentDispenserDispenseReagentMessage>(OnDispenseReagentMessage);
SubscribeLocalEvent<ReagentDispenserComponent, ReagentDispenserEjectContainerMessage>(OnEjectReagentMessage);
SubscribeLocalEvent<ReagentDispenserComponent, ReagentDispenserClearContainerSolutionMessage>(OnClearContainerSolutionMessage); SubscribeLocalEvent<ReagentDispenserComponent, ReagentDispenserClearContainerSolutionMessage>(OnClearContainerSolutionMessage);
SubscribeLocalEvent<ReagentDispenserComponent, MapInitEvent>(OnMapInit, before: new []{typeof(ItemSlotsSystem)}); SubscribeLocalEvent<ReagentDispenserComponent, MapInitEvent>(OnMapInit, before: new []{typeof(ItemSlotsSystem)});
@@ -82,32 +87,31 @@ namespace Content.Server.Chemistry.EntitySystems
private List<ReagentInventoryItem> GetInventory(Entity<ReagentDispenserComponent> reagentDispenser) private List<ReagentInventoryItem> GetInventory(Entity<ReagentDispenserComponent> reagentDispenser)
{ {
if (!TryComp<StorageComponent>(reagentDispenser.Owner, out var storage))
{
return [];
}
var inventory = new List<ReagentInventoryItem>(); 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; string reagentLabel;
if (TryComp<LabelComponent>(storedContainer, out var label) && !string.IsNullOrEmpty(label.CurrentLabel)) if (TryComp<LabelComponent>(storedContainer, out var label) && !string.IsNullOrEmpty(label.CurrentLabel))
reagentLabel = label.CurrentLabel; reagentLabel = label.CurrentLabel;
else if (storedContainer != null)
reagentLabel = Name(storedContainer.Value);
else else
continue; reagentLabel = Name(storedContainer);
// Get volume remaining and color of solution // Get volume remaining and color of solution
FixedPoint2 quantity = 0f; FixedPoint2 quantity = 0f;
var reagentColor = Color.White; 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; quantity = sol.Volume;
reagentColor = sol.GetColor(_prototypeManager); reagentColor = sol.GetColor(_prototypeManager);
} }
inventory.Add(new ReagentInventoryItem(storageSlotId, reagentLabel, quantity, reagentColor)); inventory.Add(new ReagentInventoryItem(storageLocation, reagentLabel, quantity, reagentColor));
} }
return inventory; return inventory;
@@ -122,8 +126,14 @@ namespace Content.Server.Chemistry.EntitySystems
private void OnDispenseReagentMessage(Entity<ReagentDispenserComponent> reagentDispenser, ref ReagentDispenserDispenseReagentMessage message) 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. // 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) if (storedContainer == null)
return; return;
@@ -131,13 +141,13 @@ namespace Content.Server.Chemistry.EntitySystems
if (outputContainer is not { Valid: true } || !_solutionContainerSystem.TryGetFitsInDispenser(outputContainer.Value, out var solution, out _)) if (outputContainer is not { Valid: true } || !_solutionContainerSystem.TryGetFitsInDispenser(outputContainer.Value, out var solution, out _))
return; 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 _)) _solutionContainerSystem.TryGetRefillableSolution(outputContainer.Value, out var dst, out _))
{ {
// force open container, if applicable, to avoid confusing people on why it doesn't dispense // 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, _solutionTransferSystem.Transfer(reagentDispenser,
storedContainer.Value, src.Value, storedContainer, src.Value,
outputContainer.Value, dst.Value, outputContainer.Value, dst.Value,
(int)reagentDispenser.Comp.DispenseAmount); (int)reagentDispenser.Comp.DispenseAmount);
} }
@@ -146,6 +156,21 @@ namespace Content.Server.Chemistry.EntitySystems
ClickSound(reagentDispenser); 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) private void OnClearContainerSolutionMessage(Entity<ReagentDispenserComponent> reagentDispenser, ref ReagentDispenserClearContainerSolutionMessage message)
{ {
var outputContainer = _itemSlotsSystem.GetItemOrNull(reagentDispenser, SharedReagentDispenser.OutputSlotName); var outputContainer = _itemSlotsSystem.GetItemOrNull(reagentDispenser, SharedReagentDispenser.OutputSlotName);
@@ -163,39 +188,11 @@ namespace Content.Server.Chemistry.EntitySystems
} }
/// <summary> /// <summary>
/// Automatically generate storage slots for all NumSlots, and fill them with their initial chemicals. /// Initializes the beaker slot
/// The actual spawning of entities happens in ItemSlotsSystem's MapInit.
/// </summary> /// </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 _itemSlotsSystem.AddItemSlot(ent.Owner, SharedReagentDispenser.OutputSlotName, ent.Comp.BeakerSlot);
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);
} }
} }
} }

View File

@@ -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!;
}
}

View File

@@ -1,5 +1,6 @@
using Content.Shared.Chemistry.Reagent; using Content.Shared.Chemistry.Reagent;
using Content.Shared.FixedPoint; using Content.Shared.FixedPoint;
using Content.Shared.Storage;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
namespace Content.Shared.Chemistry namespace Content.Shared.Chemistry
@@ -66,11 +67,25 @@ namespace Content.Shared.Chemistry
[Serializable, NetSerializable] [Serializable, NetSerializable]
public sealed class ReagentDispenserDispenseReagentMessage : BoundUserInterfaceMessage 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] [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 string ReagentLabel = reagentLabel;
public FixedPoint2 Quantity = quantity; public FixedPoint2 Quantity = quantity;
public Color ReagentColor = reagentColor; public Color ReagentColor = reagentColor;

View File

@@ -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

View File

@@ -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

View File

@@ -32,6 +32,8 @@
interfaces: interfaces:
enum.ReagentDispenserUiKey.Key: enum.ReagentDispenserUiKey.Key:
type: ReagentDispenserBoundUserInterface type: ReagentDispenserBoundUserInterface
enum.StorageUiKey.Key:
type: StorageBoundUserInterface
- type: Anchorable - type: Anchorable
- type: Pullable - type: Pullable
- type: Damageable - type: Damageable
@@ -54,10 +56,11 @@
- !type:PlaySoundBehavior - !type:PlaySoundBehavior
sound: sound:
collection: MetalGlassBreak collection: MetalGlassBreak
- type: Storage
maxItemSize: Normal
grid:
- 0,0,19,5
- type: ReagentDispenser - type: ReagentDispenser
storageWhitelist:
tags:
- Bottle
beakerSlot: beakerSlot:
whitelistFailPopup: reagent-dispenser-component-cannot-put-entity-message whitelistFailPopup: reagent-dispenser-component-cannot-put-entity-message
whitelist: whitelist:
@@ -70,6 +73,7 @@
machine_board: !type:Container machine_board: !type:Container
machine_parts: !type:Container machine_parts: !type:Container
beakerSlot: !type:ContainerSlot beakerSlot: !type:ContainerSlot
storagebase: !type:Container
- type: StaticPrice - type: StaticPrice
price: 1000 price: 1000
- type: WiresPanel - type: WiresPanel

View File

@@ -10,11 +10,24 @@
sprite: Structures/smalldispensers.rsi sprite: Structures/smalldispensers.rsi
drawdepth: SmallObjects drawdepth: SmallObjects
state: booze state: booze
- type: ReagentDispenser - type: Storage
storageWhitelist: whitelist:
tags: tags:
- DrinkBottle - 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 - type: Transform
noRot: false noRot: false
- type: Machine - type: Machine
@@ -31,8 +44,7 @@
suffix: Empty suffix: Empty
parent: BoozeDispenser parent: BoozeDispenser
components: components:
- type: ReagentDispenser - type: Storage
storageWhitelist: whitelist:
tags: tags:
- DrinkBottle - DrinkBottle
pack: EmptyInventory

View File

@@ -1,7 +1,7 @@
- type: entity - type: entity
id: ChemDispenser id: ChemDispenserEmpty
name: chemical dispenser name: chemical dispenser
suffix: Filled suffix: Empty
parent: ReagentDispenserBase parent: ReagentDispenserBase
description: An industrial grade chemical dispenser. description: An industrial grade chemical dispenser.
components: components:
@@ -9,11 +9,10 @@
sprite: Structures/dispensers.rsi sprite: Structures/dispensers.rsi
state: industrial-working state: industrial-working
snapCardinals: true snapCardinals: true
- type: ReagentDispenser - type: Storage
storageWhitelist: whitelist:
tags: tags:
- ChemDispensable - ChemDispensable
pack: ChemDispenserStandardInventory
- type: ApcPowerReceiver - type: ApcPowerReceiver
- type: ExtensionCableReceiver - type: ExtensionCableReceiver
- type: Destructible - type: Destructible
@@ -50,10 +49,31 @@
- MachineLayer - MachineLayer
- type: entity - type: entity
id: ChemDispenserEmpty id: ChemDispenser
name: chemical dispenser name: chemical dispenser
suffix: Empty suffix: Filled
parent: ChemDispenser parent: ChemDispenserEmpty
components: components:
- type: ReagentDispenser - 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

View File

@@ -10,11 +10,31 @@
sprite: Structures/smalldispensers.rsi sprite: Structures/smalldispensers.rsi
drawdepth: SmallObjects drawdepth: SmallObjects
state: soda state: soda
- type: ReagentDispenser - type: Storage
storageWhitelist: whitelist:
tags: tags:
- DrinkBottle - 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 - type: Transform
noRot: false noRot: false
- type: Machine - type: Machine
@@ -28,9 +48,3 @@
parent: SodaDispenser parent: SodaDispenser
id: SodaDispenserEmpty id: SodaDispenserEmpty
suffix: Empty suffix: Empty
components:
- type: ReagentDispenser
storageWhitelist:
tags:
- DrinkBottle
pack: EmptyInventory