Revert "Add limited-reagent dispensers (#23907)"

This reverts commit 9394a26245.
This commit is contained in:
Aviu00
2024-01-27 08:12:04 +03:00
parent 2d2405ff93
commit 531becd592
18 changed files with 169 additions and 303 deletions

View File

@@ -57,23 +57,13 @@ namespace Content.Client.Chemistry.UI
_window.OnDispenseReagentButtonMouseEntered += (args, button) => _window.OnDispenseReagentButtonMouseEntered += (args, button) =>
{ {
if (_lastState is not null) if (_lastState is not null)
_window.UpdateContainerInfo(_lastState); _window.UpdateContainerInfo(_lastState, button.ReagentId);
}; };
_window.OnDispenseReagentButtonMouseExited += (args, button) => _window.OnDispenseReagentButtonMouseExited += (args, button) =>
{ {
if (_lastState is not null) if (_lastState is not null)
_window.UpdateContainerInfo(_lastState); _window.UpdateContainerInfo(_lastState);
}; };
_window.OnEjectJugButtonPressed += (args, button) => SendMessage(new ItemSlotButtonPressedEvent(button.ReagentId));
_window.OnEjectJugButtonMouseEntered += (args, button) => {
if (_lastState is not null)
_window.UpdateContainerInfo(_lastState);
};
_window.OnEjectJugButtonMouseExited += (args, button) => {
if (_lastState is not null)
_window.UpdateContainerInfo(_lastState);
};
} }
/// <summary> /// <summary>

View File

@@ -1,7 +1,8 @@
<DefaultWindow xmlns="https://spacestation14.io" <DefaultWindow xmlns="https://spacestation14.io"
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client" xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
Title="{Loc 'reagent-dispenser-bound-user-interface-title'}" Title="{Loc 'reagent-dispenser-bound-user-interface-title'}"
MinSize="680 450"> SetSize="620 450"
MinSize="620 450">
<BoxContainer Orientation="Vertical"> <BoxContainer Orientation="Vertical">
<BoxContainer Orientation="Horizontal"> <BoxContainer Orientation="Horizontal">
<Label Text="{Loc 'reagent-dispenser-window-amount-to-dispense-label'}"/> <Label Text="{Loc 'reagent-dispenser-window-amount-to-dispense-label'}"/>
@@ -17,8 +18,10 @@
<Button Name="DispenseButton100" Access="Public" Text="100" StyleClasses="OpenLeft"/> <Button Name="DispenseButton100" Access="Public" Text="100" StyleClasses="OpenLeft"/>
</BoxContainer> </BoxContainer>
<Control MinSize="0 10"/> <Control MinSize="0 10"/>
<GridContainer Name="ChemicalList" HorizontalExpand="True" VerticalExpand="True" Access="Public" Columns="6"> <ScrollContainer HScrollEnabled="False" HorizontalExpand="True" MinSize="0 170">
</GridContainer> <GridContainer Name="ChemicalList" Access="Public" Columns="4">
</GridContainer>
</ScrollContainer>
<Control MinSize="0 10"/> <Control MinSize="0 10"/>
<BoxContainer Orientation="Horizontal"> <BoxContainer Orientation="Horizontal">
<Label Text="{Loc 'reagent-dispenser-window-container-label'}"/> <Label Text="{Loc 'reagent-dispenser-window-container-label'}"/>

View File

@@ -23,10 +23,6 @@ namespace Content.Client.Chemistry.UI
public event Action<GUIMouseHoverEventArgs, DispenseReagentButton>? OnDispenseReagentButtonMouseEntered; public event Action<GUIMouseHoverEventArgs, DispenseReagentButton>? OnDispenseReagentButtonMouseEntered;
public event Action<GUIMouseHoverEventArgs, DispenseReagentButton>? OnDispenseReagentButtonMouseExited; public event Action<GUIMouseHoverEventArgs, DispenseReagentButton>? OnDispenseReagentButtonMouseExited;
public event Action<BaseButton.ButtonEventArgs, EjectJugButton>? OnEjectJugButtonPressed;
public event Action<GUIMouseHoverEventArgs, EjectJugButton>? OnEjectJugButtonMouseEntered;
public event Action<GUIMouseHoverEventArgs, EjectJugButton>? OnEjectJugButtonMouseExited;
/// <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,
/// actual data isn't filled in until the server sends data about the dispenser. /// actual data isn't filled in until the server sends data about the dispenser.
@@ -52,25 +48,25 @@ namespace Content.Client.Chemistry.UI
/// Update the button grid of reagents which can be dispensed. /// Update the button grid of reagents which can be dispensed.
/// </summary> /// </summary>
/// <param name="inventory">Reagents which can be dispensed by this dispenser</param> /// <param name="inventory">Reagents which can be dispensed by this dispenser</param>
public void UpdateReagentsList(List<KeyValuePair<string, KeyValuePair<string,string>>> inventory) public void UpdateReagentsList(List<ReagentId> inventory)
{ {
if (ChemicalList == null) if (ChemicalList == null)
return; return;
ChemicalList.Children.Clear(); ChemicalList.Children.Clear();
foreach (KeyValuePair<string, KeyValuePair<string, string>> entry in inventory) foreach (var entry in inventory
.OrderBy(r => {_prototypeManager.TryIndex(r.Prototype, out ReagentPrototype? p); return p?.LocalizedName;}))
{ {
var button = new DispenseReagentButton(entry.Key, entry.Value.Key, entry.Value.Value); var localizedName = _prototypeManager.TryIndex(entry.Prototype, out ReagentPrototype? p)
? p.LocalizedName
: Loc.GetString("reagent-dispenser-window-reagent-name-not-found-text");
var button = new DispenseReagentButton(entry, localizedName);
button.OnPressed += args => OnDispenseReagentButtonPressed?.Invoke(args, button); button.OnPressed += args => OnDispenseReagentButtonPressed?.Invoke(args, button);
button.OnMouseEntered += args => OnDispenseReagentButtonMouseEntered?.Invoke(args, button); button.OnMouseEntered += args => OnDispenseReagentButtonMouseEntered?.Invoke(args, button);
button.OnMouseExited += args => OnDispenseReagentButtonMouseExited?.Invoke(args, button); button.OnMouseExited += args => OnDispenseReagentButtonMouseExited?.Invoke(args, button);
ChemicalList.AddChild(button); ChemicalList.AddChild(button);
var ejectButton = new EjectJugButton(entry.Key);
ejectButton.OnPressed += args => OnEjectJugButtonPressed?.Invoke(args, ejectButton);
ejectButton.OnMouseEntered += args => OnEjectJugButtonMouseEntered?.Invoke(args, ejectButton);
ejectButton.OnMouseExited += args => OnEjectJugButtonMouseExited?.Invoke(args, ejectButton);
ChemicalList.AddChild(ejectButton);
} }
} }
@@ -125,8 +121,9 @@ namespace Content.Client.Chemistry.UI
/// <para>Also highlights a reagent if it's dispense button is being mouse hovered.</para> /// <para>Also highlights a reagent if it's dispense button is being mouse hovered.</para>
/// </summary> /// </summary>
/// <param name="state">State data for the dispenser.</param> /// <param name="state">State data for the dispenser.</param>
/// <param name="highlightedReagentId">Prototype ID of the reagent whose dispense button is currently being mouse hovered,
/// or null if no button is being hovered.</param> /// or null if no button is being hovered.</param>
public void UpdateContainerInfo(ReagentDispenserBoundUserInterfaceState state) public void UpdateContainerInfo(ReagentDispenserBoundUserInterfaceState state, ReagentId? highlightedReagentId = null)
{ {
ContainerInfo.Children.Clear(); ContainerInfo.Children.Clear();
@@ -164,6 +161,12 @@ namespace Content.Client.Chemistry.UI
StyleClasses = {StyleNano.StyleClassLabelSecondaryColor}, StyleClasses = {StyleNano.StyleClassLabelSecondaryColor},
}; };
// Check if the reagent is being moused over. If so, color it green.
if (reagent == highlightedReagentId) {
nameLabel.SetOnlyStyleClass(StyleNano.StyleClassPowerStateGood);
quantityLabel.SetOnlyStyleClass(StyleNano.StyleClassPowerStateGood);
}
ContainerInfo.Children.Add(new BoxContainer ContainerInfo.Children.Add(new BoxContainer
{ {
Orientation = LayoutOrientation.Horizontal, Orientation = LayoutOrientation.Horizontal,
@@ -177,27 +180,13 @@ namespace Content.Client.Chemistry.UI
} }
} }
public sealed class DispenseReagentButton : Button public sealed class DispenseReagentButton : Button {
{ public ReagentId ReagentId { get; }
public string ReagentId { get; }
public DispenseReagentButton(string reagentId, string text, string amount) public DispenseReagentButton(ReagentId reagentId, string text)
{ {
AddStyleClass("OpenRight");
ReagentId = reagentId; ReagentId = reagentId;
Text = text + " " + amount; Text = text;
}
}
public sealed class EjectJugButton : Button
{
public string ReagentId { get; }
public EjectJugButton(string reagentId)
{
AddStyleClass("OpenLeft");
ReagentId = reagentId;
Text = "⏏";
} }
} }
} }

View File

@@ -1,7 +1,6 @@
using Content.Client.Chemistry.UI; using Content.Client.Chemistry.UI;
using Content.IntegrationTests.Tests.Interaction; using Content.IntegrationTests.Tests.Interaction;
using Content.Shared.Chemistry; using Content.Shared.Chemistry;
using Content.Server.Chemistry.Components;
using Content.Shared.Containers.ItemSlots; using Content.Shared.Containers.ItemSlots;
namespace Content.IntegrationTests.Tests.Chemistry; namespace Content.IntegrationTests.Tests.Chemistry;
@@ -25,7 +24,7 @@ public sealed class DispenserTest : InteractionTest
await Interact(); await Interact();
// Eject beaker via BUI. // Eject beaker via BUI.
var ev = new ItemSlotButtonPressedEvent(ReagentDispenserComponent.BeakerSlotId); var ev = new ItemSlotButtonPressedEvent(SharedChemMaster.InputSlotName);
await SendBui(ReagentDispenserUiKey.Key, ev); await SendBui(ReagentDispenserUiKey.Key, ev);
// Beaker is back in the player's hands // Beaker is back in the player's hands

View File

@@ -1,5 +1,3 @@
using Content.Shared.Whitelist;
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 Content.Shared.Chemistry.Dispenser;
@@ -9,57 +7,20 @@ using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototy
namespace Content.Server.Chemistry.Components namespace Content.Server.Chemistry.Components
{ {
/// <summary> /// <summary>
/// A machine that dispenses reagents into a solution container from containers in its storage slots. /// A machine that dispenses reagents into a solution container.
/// </summary> /// </summary>
[RegisterComponent] [RegisterComponent]
[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>))] [DataField("pack", customTypeSerializer:typeof(PrototypeIdSerializer<ReagentDispenserInventoryPrototype>))]
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
public string? PackPrototypeId = default!; public string? PackPrototypeId = default!;
/// <summary> [DataField("emagPack", customTypeSerializer:typeof(PrototypeIdSerializer<ReagentDispenserInventoryPrototype>))]
/// Maximum number of internal storage slots. Dispenser can't store (or dispense) more than [ViewVariables(VVAccess.ReadWrite)]
/// this many chemicals (without unloading and reloading). public string? EmagPackPrototypeId = default!;
/// </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;
/// <summary>
/// Slot for container to dispense into.
/// </summary>
public static string BeakerSlotId = "ReagentDispenser-beakerSlot";
[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)] [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,18 +1,14 @@
using Content.Server.Administration.Logs; using Content.Server.Administration.Logs;
using Content.Server.Chemistry.Components; using Content.Server.Chemistry.Components;
using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Chemistry.Containers.EntitySystems;
using Content.Server.Nutrition.Components;
using Content.Server.Nutrition.EntitySystems;
using Content.Server.Labels.Components;
using Content.Server.Chemistry;
using Content.Shared.Chemistry; using Content.Shared.Chemistry;
using Content.Shared.Chemistry.Components.SolutionManager;
using Content.Shared.Chemistry.Dispenser; using Content.Shared.Chemistry.Dispenser;
using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Chemistry.Reagent; using Content.Shared.Chemistry.Reagent;
using Content.Shared.Containers.ItemSlots; using Content.Shared.Containers.ItemSlots;
using Content.Shared.Database; using Content.Shared.Database;
using Content.Shared.FixedPoint; using Content.Shared.Emag.Components;
using Content.Shared.Emag.Systems;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Server.Audio; using Robust.Server.Audio;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
@@ -32,13 +28,10 @@ namespace Content.Server.Chemistry.EntitySystems
{ {
[Dependency] private readonly AudioSystem _audioSystem = default!; [Dependency] private readonly AudioSystem _audioSystem = default!;
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!; [Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
[Dependency] private readonly SolutionTransferSystem _solutionTransferSystem = default!;
[Dependency] private readonly ItemSlotsSystem _itemSlotsSystem = default!; [Dependency] private readonly ItemSlotsSystem _itemSlotsSystem = default!;
[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 IAdminLogManager _adminLogger = default!; [Dependency] private readonly IAdminLogManager _adminLogger = default!;
[Dependency] private readonly OpenableSystem _openable = default!;
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
@@ -48,12 +41,11 @@ namespace Content.Server.Chemistry.EntitySystems
SubscribeLocalEvent<ReagentDispenserComponent, EntInsertedIntoContainerMessage>(SubscribeUpdateUiState); SubscribeLocalEvent<ReagentDispenserComponent, EntInsertedIntoContainerMessage>(SubscribeUpdateUiState);
SubscribeLocalEvent<ReagentDispenserComponent, EntRemovedFromContainerMessage>(SubscribeUpdateUiState); SubscribeLocalEvent<ReagentDispenserComponent, EntRemovedFromContainerMessage>(SubscribeUpdateUiState);
SubscribeLocalEvent<ReagentDispenserComponent, BoundUIOpenedEvent>(SubscribeUpdateUiState); SubscribeLocalEvent<ReagentDispenserComponent, BoundUIOpenedEvent>(SubscribeUpdateUiState);
SubscribeLocalEvent<ReagentDispenserComponent, GotEmaggedEvent>(OnEmagged);
SubscribeLocalEvent<ReagentDispenserComponent, ReagentDispenserSetDispenseAmountMessage>(OnSetDispenseAmountMessage); SubscribeLocalEvent<ReagentDispenserComponent, ReagentDispenserSetDispenseAmountMessage>(OnSetDispenseAmountMessage);
SubscribeLocalEvent<ReagentDispenserComponent, ReagentDispenserDispenseReagentMessage>(OnDispenseReagentMessage); SubscribeLocalEvent<ReagentDispenserComponent, ReagentDispenserDispenseReagentMessage>(OnDispenseReagentMessage);
SubscribeLocalEvent<ReagentDispenserComponent, ReagentDispenserClearContainerSolutionMessage>(OnClearContainerSolutionMessage); SubscribeLocalEvent<ReagentDispenserComponent, ReagentDispenserClearContainerSolutionMessage>(OnClearContainerSolutionMessage);
SubscribeLocalEvent<ReagentDispenserComponent, MapInitEvent>(OnMapInit, before: new []{typeof(ItemSlotsSystem)});
} }
private void SubscribeUpdateUiState<T>(Entity<ReagentDispenserComponent> ent, ref T ev) private void SubscribeUpdateUiState<T>(Entity<ReagentDispenserComponent> ent, ref T ev)
@@ -88,38 +80,35 @@ namespace Content.Server.Chemistry.EntitySystems
return null; return null;
} }
private List<KeyValuePair<string, KeyValuePair<string, string>>> GetInventory(ReagentDispenserComponent reagentDispenser) private List<ReagentId> GetInventory(Entity<ReagentDispenserComponent> ent)
{ {
var inventory = new List<KeyValuePair<string, KeyValuePair<string, string>>>(); var reagentDispenser = ent.Comp;
var inventory = new List<ReagentId>();
for (var i = 0; i < reagentDispenser.NumSlots; i++) if (reagentDispenser.PackPrototypeId is not null
&& _prototypeManager.TryIndex(reagentDispenser.PackPrototypeId, out ReagentDispenserInventoryPrototype? packPrototype))
{ {
var storageSlotId = ReagentDispenserComponent.BaseStorageSlotId + i; inventory.AddRange(packPrototype.Inventory.Select(x => new ReagentId(x, null)));
var storedContainer = _itemSlotsSystem.GetItemOrNull(reagentDispenser.Owner, storageSlotId); }
// Set label from manually-applied label, or metadata if unavailable if (HasComp<EmaggedComponent>(ent)
string reagentLabel; && reagentDispenser.EmagPackPrototypeId is not null
if (TryComp<LabelComponent>(storedContainer, out var label) && !string.IsNullOrEmpty(label.CurrentLabel)) && _prototypeManager.TryIndex(reagentDispenser.EmagPackPrototypeId, out ReagentDispenserInventoryPrototype? emagPackPrototype))
reagentLabel = label.CurrentLabel; {
else if (storedContainer != null) inventory.AddRange(emagPackPrototype.Inventory.Select(x => new ReagentId(x, null)));
reagentLabel = Name(storedContainer.Value);
else
continue;
// Add volume remaining label
FixedPoint2 quantity = 0f;
if (storedContainer != null && _solutionContainerSystem.TryGetDrainableSolution(storedContainer.Value, out _, out var sol))
{
quantity = sol.Volume;
}
var storedAmount = Loc.GetString("reagent-dispenser-window-quantity-label-text", ("quantity", quantity));
inventory.Add(new KeyValuePair<string, KeyValuePair<string, string>>(storageSlotId, new KeyValuePair<string, string>(reagentLabel, storedAmount)));
} }
return inventory; return inventory;
} }
private void OnEmagged(Entity<ReagentDispenserComponent> reagentDispenser, ref GotEmaggedEvent args)
{
// adding component manually to have correct state
EntityManager.AddComponent<EmaggedComponent>(reagentDispenser);
UpdateUiState(reagentDispenser);
args.Handled = true;
}
private void OnSetDispenseAmountMessage(Entity<ReagentDispenserComponent> reagentDispenser, ref ReagentDispenserSetDispenseAmountMessage message) private void OnSetDispenseAmountMessage(Entity<ReagentDispenserComponent> reagentDispenser, ref ReagentDispenserSetDispenseAmountMessage message)
{ {
reagentDispenser.Comp.DispenseAmount = message.ReagentDispenserDispenseAmount; reagentDispenser.Comp.DispenseAmount = message.ReagentDispenserDispenseAmount;
@@ -130,23 +119,18 @@ namespace Content.Server.Chemistry.EntitySystems
private void OnDispenseReagentMessage(Entity<ReagentDispenserComponent> reagentDispenser, ref ReagentDispenserDispenseReagentMessage message) private void OnDispenseReagentMessage(Entity<ReagentDispenserComponent> reagentDispenser, ref ReagentDispenserDispenseReagentMessage message)
{ {
// 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); if (!GetInventory(reagentDispenser).Contains(message.ReagentId))
if (storedContainer == null)
return; return;
var outputContainer = _itemSlotsSystem.GetItemOrNull(reagentDispenser, SharedReagentDispenser.OutputSlotName); var outputContainer = _itemSlotsSystem.GetItemOrNull(reagentDispenser, SharedReagentDispenser.OutputSlotName);
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.TryAddReagent(solution.Value, message.ReagentId, (int) reagentDispenser.Comp.DispenseAmount, out var dispensedAmount)
_solutionContainerSystem.TryGetRefillableSolution(outputContainer.Value, out var dst, out _)) && message.Session.AttachedEntity is not null)
{ {
// force open container, if applicable, to avoid confusing people on why it doesn't dispense _adminLogger.Add(LogType.ChemicalReaction, LogImpact.Medium,
_openable.SetOpen(storedContainer.Value, true); $"{ToPrettyString(message.Session.AttachedEntity.Value):player} dispensed {dispensedAmount}u of {message.ReagentId} into {ToPrettyString(outputContainer.Value):entity}");
_solutionTransferSystem.Transfer(reagentDispenser,
storedContainer.Value, src.Value,
outputContainer.Value, dst.Value,
(int)reagentDispenser.Comp.DispenseAmount);
} }
UpdateUiState(reagentDispenser); UpdateUiState(reagentDispenser);
@@ -168,41 +152,5 @@ namespace Content.Server.Chemistry.EntitySystems
{ {
_audioSystem.PlayPvs(reagentDispenser.Comp.ClickSound, reagentDispenser, AudioParams.Default.WithVolume(-2f)); _audioSystem.PlayPvs(reagentDispenser.Comp.ClickSound, reagentDispenser, AudioParams.Default.WithVolume(-2f));
} }
/// <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.
/// </summary>
private void OnMapInit(EntityUid uid, ReagentDispenserComponent component, 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, ReagentDispenserComponent.BeakerSlotId, component.BeakerSlot);
}
} }
} }

View File

@@ -1,4 +1,4 @@
using Content.Shared.Chemistry.Reagent; using Content.Shared.Chemistry.Reagent;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
@@ -14,7 +14,8 @@ namespace Content.Shared.Chemistry.Dispenser
[Serializable, NetSerializable, Prototype("reagentDispenserInventory")] [Serializable, NetSerializable, Prototype("reagentDispenserInventory")]
public sealed partial class ReagentDispenserInventoryPrototype : IPrototype public sealed partial class ReagentDispenserInventoryPrototype : IPrototype
{ {
[DataField("inventory", customTypeSerializer: typeof(PrototypeIdListSerializer<EntityPrototype>))] // TODO use ReagentId
[DataField("inventory", customTypeSerializer: typeof(PrototypeIdListSerializer<ReagentPrototype>))]
public List<string> Inventory = new(); public List<string> Inventory = new();
[ViewVariables, IdDataField] [ViewVariables, IdDataField]

View File

@@ -8,7 +8,7 @@ namespace Content.Shared.Chemistry
/// </summary> /// </summary>
public sealed class SharedReagentDispenser public sealed class SharedReagentDispenser
{ {
public const string OutputSlotName = "ReagentDispenser-beakerSlot"; public const string OutputSlotName = "beakerSlot";
} }
[Serializable, NetSerializable] [Serializable, NetSerializable]
@@ -25,11 +25,11 @@ namespace Content.Shared.Chemistry
[Serializable, NetSerializable] [Serializable, NetSerializable]
public sealed class ReagentDispenserDispenseReagentMessage : BoundUserInterfaceMessage public sealed class ReagentDispenserDispenseReagentMessage : BoundUserInterfaceMessage
{ {
public readonly string SlotId; public readonly ReagentId ReagentId;
public ReagentDispenserDispenseReagentMessage(string slotId) public ReagentDispenserDispenseReagentMessage(ReagentId reagentId)
{ {
SlotId = slotId; ReagentId = reagentId;
} }
} }
@@ -59,11 +59,11 @@ namespace Content.Shared.Chemistry
/// <summary> /// <summary>
/// A list of the reagents which this dispenser can dispense. /// A list of the reagents which this dispenser can dispense.
/// </summary> /// </summary>
public readonly List<KeyValuePair<string, KeyValuePair<string, string>>> Inventory; public readonly List<ReagentId> Inventory;
public readonly ReagentDispenserDispenseAmount SelectedDispenseAmount; public readonly ReagentDispenserDispenseAmount SelectedDispenseAmount;
public ReagentDispenserBoundUserInterfaceState(ContainerInfo? outputContainer, List<KeyValuePair<string, KeyValuePair<string, string>>> inventory, ReagentDispenserDispenseAmount selectedDispenseAmount) public ReagentDispenserBoundUserInterfaceState(ContainerInfo? outputContainer, List<ReagentId> inventory, ReagentDispenserDispenseAmount selectedDispenseAmount)
{ {
OutputContainer = outputContainer; OutputContainer = outputContainer;
Inventory = inventory; Inventory = inventory;

View File

@@ -67,8 +67,8 @@ namespace Content.Shared.Containers.ItemSlots
CopyFrom(other); CopyFrom(other);
} }
[DataField("whitelist")] [DataField("whitelist")]
[Access(typeof(ItemSlotsSystem), Other = AccessPermissions.ReadWriteExecute)]
public EntityWhitelist? Whitelist; public EntityWhitelist? Whitelist;
[DataField("blacklist")] [DataField("blacklist")]
@@ -179,7 +179,6 @@ namespace Content.Shared.Containers.ItemSlots
/// The actual deconstruction logic is handled by the server-side EmptyOnMachineDeconstructSystem. /// The actual deconstruction logic is handled by the server-side EmptyOnMachineDeconstructSystem.
/// </remarks> /// </remarks>
[DataField("ejectOnDeconstruct")] [DataField("ejectOnDeconstruct")]
[Access(typeof(ItemSlotsSystem), Other = AccessPermissions.ReadWriteExecute)]
[NonSerialized] [NonSerialized]
public bool EjectOnDeconstruct = true; public bool EjectOnDeconstruct = true;
@@ -188,7 +187,6 @@ namespace Content.Shared.Containers.ItemSlots
/// ejected when it is broken or destroyed? /// ejected when it is broken or destroyed?
/// </summary> /// </summary>
[DataField("ejectOnBreak")] [DataField("ejectOnBreak")]
[Access(typeof(ItemSlotsSystem), Other = AccessPermissions.ReadWriteExecute)]
[NonSerialized] [NonSerialized]
public bool EjectOnBreak = false; public bool EjectOnBreak = false;
@@ -207,7 +205,6 @@ namespace Content.Shared.Containers.ItemSlots
/// want to insert more than one item that matches the same whitelist. /// want to insert more than one item that matches the same whitelist.
/// </remarks> /// </remarks>
[DataField("swap")] [DataField("swap")]
[Access(typeof(ItemSlotsSystem), Other = AccessPermissions.ReadWriteExecute)]
public bool Swap = true; public bool Swap = true;
public string? ID => ContainerSlot?.ID; public string? ID => ContainerSlot?.ID;

View File

@@ -1,43 +1,61 @@
- type: reagentDispenserInventory - type: reagentDispenserInventory
id: SodaDispenserInventory id: SodaDispenserInventory
inventory: inventory:
- DrinkIceJug - Ice
- DrinkCoffeeJug - Coffee
- DrinkCreamCartonXL - Cream
- DrinkTeaJug - Tea
- DrinkGreenTeaJug - GreenTea
- DrinkIcedTeaJug - IcedTea
- DrinkColaBottleFull - IcedGreenTea
- DrinkSpaceMountainWindBottleFull - Cola
- DrinkDrGibbJug - SpaceMountainWind
- DrinkRootBeerJug - DrGibb
- DrinkSpaceUpBottleFull - RootBeer
- DrinkTonicWaterBottleFull - SpaceUp
- DrinkSodaWaterBottleFull - TonicWater
- DrinkLemonLimeJug - SodaWater
- DrinkSugarJug - LemonLime
- DrinkJuiceOrangeCartonXL - Sugar
- DrinkJuiceLimeCartonXL - JuiceOrange
- DrinkWaterMelonJuiceJug - JuiceLime
- JuiceWatermelon
###Hacked
#- Fourteen Loko
#- GrapeSoda
- type: reagentDispenserInventory - type: reagentDispenserInventory
id: BoozeDispenserInventory id: BoozeDispenserInventory
inventory: inventory:
- DrinkLemonLimeJug - Beer
- DrinkSugarJug - CoffeeLiqueur
- DrinkJuiceOrangeCartonXL - Whiskey
- DrinkJuiceLimeCartonXL - Wine
- DrinkTonicWaterBottleFull - Vodka
- DrinkSodaWaterBottleFull - Gin
- DrinkBeerGrowler - Rum
- DrinkCoffeeLiqueurBottleFull - Tequila
- DrinkWhiskeyBottleFull - Vermouth
- DrinkWineBottleFull - Cognac
- DrinkVodkaBottleFull - Ale
- DrinkGinBottleFull - Mead
- DrinkRumBottleFull ###Hacked
- DrinkTequilaBottleFull #- Goldschlager
- DrinkVermouthBottleFull #- Patron
- DrinkCognacBottleFull #- JuiceWatermelon
- DrinkAleBottleFullGrowler #- JuiceBerry
- DrinkMeadJug
- type: reagentDispenserInventory
id: SodaDispenserEmagInventory
inventory:
- FourteenLoko
- Ephedrine
- Histamine
- type: reagentDispenserInventory
id: BoozeDispenserEmagInventory
inventory:
- AtomicBomb
- Ethanol
- Iron

View File

@@ -1,26 +1,31 @@
- type: reagentDispenserInventory - type: reagentDispenserInventory
id: ChemDispenserStandardInventory id: ChemDispenserStandardInventory
inventory: inventory:
- JugAluminium - Aluminium
- JugCarbon - Carbon
- JugChlorine - Chlorine
- JugCopper - Copper
- JugEthanol - Ethanol
- JugFluorine - Fluorine
- JugSugar - Sugar
- JugHydrogen - Hydrogen
- JugIodine - Iodine
- JugIron - Iron
- JugLithium - Lithium
- JugMercury - Mercury
- JugNitrogen - Nitrogen
- JugOxygen - Oxygen
- JugPhosphorus - Phosphorus
- JugPotassium - Potassium
- JugRadium - Radium
- JugSilicon - Silicon
- JugSodium - Sodium
- JugSulfur - Sulfur
- type: reagentDispenserInventory - type: reagentDispenserInventory
id: EmptyInventory id: ChemDispenserEmaggedInventory
inventory: ##Feel free to change this to something more interesting when more chems are added
- Napalm
- Toxin
- Epinephrine
- Ultravasculine

View File

@@ -553,7 +553,7 @@
- type: Sprite - type: Sprite
state: medical state: medical
- type: MachineBoard - type: MachineBoard
prototype: ChemDispenserEmpty prototype: ChemDispenser
requirements: requirements:
Capacitor: 1 Capacitor: 1
materialRequirements: materialRequirements:
@@ -1168,7 +1168,7 @@
- type: Sprite - type: Sprite
state: service state: service
- type: MachineBoard - type: MachineBoard
prototype: BoozeDispenserEmpty prototype: BoozeDispenser
materialRequirements: materialRequirements:
Steel: 5 Steel: 5
tagRequirements: tagRequirements:
@@ -1201,7 +1201,7 @@
- type: Sprite - type: Sprite
state: service state: service
- type: MachineBoard - type: MachineBoard
prototype: SodaDispenserEmpty prototype: soda_dispenser
materialRequirements: materialRequirements:
Steel: 5 Steel: 5
tagRequirements: tagRequirements:

View File

@@ -47,9 +47,6 @@
price: 60 price: 60
- type: Label - type: Label
originalName: jug originalName: jug
- type: Tag
tags:
- ChemDispensable
- type: entity - type: entity
parent: Jug parent: Jug

View File

@@ -1,4 +1,4 @@
- type: entity - type: entity
abstract: true abstract: true
id: ReagentDispenserBase id: ReagentDispenserBase
parent: ConstructibleMachine parent: ConstructibleMachine
@@ -55,20 +55,18 @@
sound: sound:
collection: MetalGlassBreak collection: MetalGlassBreak
- type: ReagentDispenser - type: ReagentDispenser
storageWhitelist:
tags:
- Bottle
beakerSlot:
whitelistFailPopup: reagent-dispenser-component-cannot-put-entity-message
whitelist:
components:
- FitsInDispenser
- type: ItemSlots - type: ItemSlots
slots:
beakerSlot:
whitelistFailPopup: reagent-dispenser-component-cannot-put-entity-message
whitelist:
components:
- FitsInDispenser
- type: ContainerContainer - type: ContainerContainer
containers: containers:
machine_board: !type:Container machine_board: !type:Container
machine_parts: !type:Container machine_parts: !type:Container
ReagentDispenser-beakerSlot: !type:ContainerSlot beakerSlot: !type:ContainerSlot
- type: StaticPrice - type: StaticPrice
price: 1000 price: 1000
- type: Wires - type: Wires

View File

@@ -1,7 +1,6 @@
- type: entity - type: entity
id: BoozeDispenser id: BoozeDispenser
name: booze dispenser name: booze dispenser
suffix: Filled
description: A booze dispenser with a single slot for a container to be filled. description: A booze dispenser with a single slot for a container to be filled.
parent: ReagentDispenserBase parent: ReagentDispenserBase
components: components:
@@ -11,10 +10,8 @@
drawdepth: SmallObjects drawdepth: SmallObjects
state: booze state: booze
- type: ReagentDispenser - type: ReagentDispenser
storageWhitelist:
tags:
- DrinkBottle
pack: BoozeDispenserInventory pack: BoozeDispenserInventory
emagPack: BoozeDispenserEmagInventory
- type: Transform - type: Transform
noRot: false noRot: false
- type: Machine - type: Machine
@@ -27,14 +24,3 @@
- Bartender - Bartender
- type: StealTarget - type: StealTarget
stealGroup: BoozeDispenser stealGroup: BoozeDispenser
- type: entity
id: BoozeDispenserEmpty
suffix: Empty
parent: BoozeDispenser
components:
- type: ReagentDispenser
storageWhitelist:
tags:
- DrinkBottle
pack: EmptyInventory

View File

@@ -1,19 +1,16 @@
- type: entity - type: entity
id: ChemDispenser id: ChemDispenser
name: chemical dispenser name: chemical dispenser
suffix: Filled
parent: ReagentDispenserBase parent: ReagentDispenserBase
description: An industrial grade chemical dispenser. description: An industrial grade chemical dispenser with a sizeable chemical supply.
components: components:
- type: Sprite - type: Sprite
sprite: Structures/dispensers.rsi sprite: Structures/dispensers.rsi
state: industrial-working state: industrial-working
snapCardinals: true snapCardinals: true
- type: ReagentDispenser - type: ReagentDispenser
storageWhitelist:
tags:
- ChemDispensable
pack: ChemDispenserStandardInventory pack: ChemDispenserStandardInventory
emagPack: ChemDispenserEmaggedInventory
- type: ApcPowerReceiver - type: ApcPowerReceiver
- type: ExtensionCableReceiver - type: ExtensionCableReceiver
- type: Destructible - type: Destructible
@@ -40,12 +37,3 @@
- Chemist - Chemist
- type: StealTarget - type: StealTarget
stealGroup: ChemDispenser stealGroup: ChemDispenser
- type: entity
id: ChemDispenserEmpty
name: chemical dispenser
suffix: Empty
parent: ChemDispenser
components:
- type: ReagentDispenser
pack: EmptyInventory

View File

@@ -1,7 +1,6 @@
- type: entity - type: entity
id: soda_dispenser id: soda_dispenser
name: soda dispenser name: soda dispenser
suffix: Filled
parent: ReagentDispenserBase parent: ReagentDispenserBase
description: A beverage dispenser with a selection of soda and several other common beverages. Has a single fill slot for containers. description: A beverage dispenser with a selection of soda and several other common beverages. Has a single fill slot for containers.
components: components:
@@ -11,10 +10,8 @@
drawdepth: SmallObjects drawdepth: SmallObjects
state: soda state: soda
- type: ReagentDispenser - type: ReagentDispenser
storageWhitelist:
tags:
- DrinkBottle
pack: SodaDispenserInventory pack: SodaDispenserInventory
emagPack: SodaDispenserEmagInventory
- type: Transform - type: Transform
noRot: false noRot: false
- type: Machine - type: Machine
@@ -25,14 +22,3 @@
- type: GuideHelp - type: GuideHelp
guides: guides:
- Bartender - Bartender
- type: entity
id: SodaDispenserEmpty
suffix: Empty
parent: soda_dispenser
components:
- type: ReagentDispenser
storageWhitelist:
tags:
- DrinkBottle
pack: EmptyInventory