diff --git a/Content.Client/GameObjects/Components/Chemistry/ChemMaster/ChemMasterWindow.cs b/Content.Client/GameObjects/Components/Chemistry/ChemMaster/ChemMasterWindow.cs
index a204c63124..3a2dece8e9 100644
--- a/Content.Client/GameObjects/Components/Chemistry/ChemMaster/ChemMasterWindow.cs
+++ b/Content.Client/GameObjects/Components/Chemistry/ChemMaster/ChemMasterWindow.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using Content.Client.UserInterface;
@@ -273,6 +273,34 @@ namespace Content.Client.GameObjects.Components.Chemistry.ChemMaster
var castState = (ChemMasterBoundUserInterfaceState) state;
Title = castState.DispenserName;
UpdatePanelInfo(castState);
+ if (Contents.Children != null)
+ {
+ SetButtonDisabledRecursive(Contents, !castState.HasPower);
+ EjectButton.Disabled = !castState.HasBeaker;
+ }
+ }
+
+ ///
+ /// This searches recursively through all the children of "parent"
+ /// and sets the Disabled value of any buttons found to "val"
+ ///
+ /// The control which childrens get searched
+ /// The value to which disabled gets set
+ private void SetButtonDisabledRecursive(Control parent, bool val)
+ {
+ foreach (var child in parent.Children)
+ {
+ if (child is Button but)
+ {
+ but.Disabled = val;
+ continue;
+ }
+
+ if (child.Children != null)
+ {
+ SetButtonDisabledRecursive(child, val);
+ }
+ }
}
///
diff --git a/Content.Client/GameObjects/Components/Chemistry/ReagentDispenser/ReagentDispenserBoundUserInterface.cs b/Content.Client/GameObjects/Components/Chemistry/ReagentDispenser/ReagentDispenserBoundUserInterface.cs
index 8f362cc49a..1aabef19dc 100644
--- a/Content.Client/GameObjects/Components/Chemistry/ReagentDispenser/ReagentDispenserBoundUserInterface.cs
+++ b/Content.Client/GameObjects/Components/Chemistry/ReagentDispenser/ReagentDispenserBoundUserInterface.cs
@@ -72,8 +72,8 @@ namespace Content.Client.GameObjects.Components.Chemistry
var castState = (ReagentDispenserBoundUserInterfaceState)state;
_lastState = castState;
- _window?.UpdateState(castState); //Update window state
UpdateReagentsList(castState.Inventory); //Update reagents list & reagent button actions
+ _window?.UpdateState(castState); //Update window state
}
///
diff --git a/Content.Client/GameObjects/Components/Chemistry/ReagentDispenser/ReagentDispenserWindow.cs b/Content.Client/GameObjects/Components/Chemistry/ReagentDispenser/ReagentDispenserWindow.cs
index fade17e84c..66b5fd693f 100644
--- a/Content.Client/GameObjects/Components/Chemistry/ReagentDispenser/ReagentDispenserWindow.cs
+++ b/Content.Client/GameObjects/Components/Chemistry/ReagentDispenser/ReagentDispenserWindow.cs
@@ -161,6 +161,29 @@ namespace Content.Client.GameObjects.Components.Chemistry
}
}
+ ///
+ /// This searches recursively through all the children of "parent"
+ /// and sets the Disabled value of any buttons found to "val"
+ ///
+ /// The control which childrens get searched
+ /// The value to which disabled gets set
+ private void SetButtonDisabledRecursive(Control parent, bool val)
+ {
+ foreach (var child in parent.Children)
+ {
+ if (child is Button but)
+ {
+ but.Disabled = val;
+ continue;
+ }
+
+ if (child.Children != null)
+ {
+ SetButtonDisabledRecursive(child, val);
+ }
+ }
+ }
+
///
/// Update the UI state when new state data is received from the server.
///
@@ -171,6 +194,20 @@ namespace Content.Client.GameObjects.Components.Chemistry
Title = castState.DispenserName;
UpdateContainerInfo(castState);
+ // Disable all buttons if not powered
+ if (Contents.Children != null)
+ {
+ SetButtonDisabledRecursive(Contents, !castState.HasPower);
+ EjectButton.Disabled = false;
+ }
+
+ // Disable the Clear & Eject button if no beaker
+ if (!castState.HasBeaker)
+ {
+ ClearButton.Disabled = true;
+ EjectButton.Disabled = true;
+ }
+
switch (castState.SelectedDispenseAmount.Int())
{
case 1:
diff --git a/Content.Server/GameObjects/Components/Chemistry/ChemMasterComponent.cs b/Content.Server/GameObjects/Components/Chemistry/ChemMasterComponent.cs
index 2f7caaf156..4f20a0c4e9 100644
--- a/Content.Server/GameObjects/Components/Chemistry/ChemMasterComponent.cs
+++ b/Content.Server/GameObjects/Components/Chemistry/ChemMasterComponent.cs
@@ -83,6 +83,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
_beakerContainer =
ContainerManagerComponent.Ensure($"{Name}-reagentContainerContainer", Owner);
_powerReceiver = Owner.GetComponent();
+ _powerReceiver.OnPowerStateChanged += OnPowerChanged;
//BufferSolution = Owner.BufferSolution
BufferSolution.Solution = new Solution();
@@ -91,6 +92,11 @@ namespace Content.Server.GameObjects.Components.Chemistry
UpdateUserInterface();
}
+ private void OnPowerChanged(object sender, PowerStateEventArgs e)
+ {
+ UpdateUserInterface();
+ }
+
///
/// Handles ui messages from the client. For things such as button presses
/// which interact with the world and require server action.
@@ -98,10 +104,16 @@ namespace Content.Server.GameObjects.Components.Chemistry
/// A user interface message from the client.
private void OnUiReceiveMessage(ServerBoundUserInterfaceMessage obj)
{
- if (!PlayerCanUseChemMaster(obj.Session.AttachedEntity))
+ var msg = (UiActionMessage) obj.Message;
+ var needsPower = msg.action switch
+ {
+ UiAction.Eject => false,
+ _ => true,
+ };
+
+ if (!PlayerCanUseChemMaster(obj.Session.AttachedEntity, needsPower))
return;
- var msg = (UiActionMessage) obj.Message;
switch (msg.action)
{
case UiAction.Eject:
@@ -134,7 +146,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
///
/// The player entity.
/// Returns true if the entity can use the chem master, and false if it cannot.
- private bool PlayerCanUseChemMaster(IEntity playerEntity)
+ private bool PlayerCanUseChemMaster(IEntity playerEntity, bool needsPower = true)
{
//Need player entity to check if they are still able to use the chem master
if (playerEntity == null)
@@ -143,7 +155,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
if (!ActionBlockerSystem.CanInteract(playerEntity) || !ActionBlockerSystem.CanUse(playerEntity))
return false;
//Check if device is powered
- if (!Powered)
+ if (needsPower && !Powered)
return false;
return true;
@@ -158,12 +170,12 @@ namespace Content.Server.GameObjects.Components.Chemistry
var beaker = _beakerContainer.ContainedEntity;
if (beaker == null)
{
- return new ChemMasterBoundUserInterfaceState(false, ReagentUnit.New(0), ReagentUnit.New(0),
+ return new ChemMasterBoundUserInterfaceState(Powered, false, ReagentUnit.New(0), ReagentUnit.New(0),
"", Owner.Name, null, BufferSolution.ReagentList.ToList(), BufferModeTransfer, BufferSolution.CurrentVolume, BufferSolution.MaxVolume);
}
var solution = beaker.GetComponent();
- return new ChemMasterBoundUserInterfaceState(true, solution.CurrentVolume, solution.MaxVolume,
+ return new ChemMasterBoundUserInterfaceState(Powered, true, solution.CurrentVolume, solution.MaxVolume,
beaker.Name, Owner.Name, solution.ReagentList.ToList(), BufferSolution.ReagentList.ToList(), BufferModeTransfer, BufferSolution.CurrentVolume, BufferSolution.MaxVolume);
}
@@ -252,9 +264,15 @@ namespace Content.Server.GameObjects.Components.Chemistry
{
var random = IoCManager.Resolve();
+ if (BufferSolution.CurrentVolume == 0)
+ return;
+
if (action == UiAction.CreateBottles)
{
var individualVolume = BufferSolution.CurrentVolume / ReagentUnit.New(bottleAmount);
+ if (individualVolume < ReagentUnit.New(1))
+ return;
+
var actualVolume = ReagentUnit.Min(individualVolume, ReagentUnit.New(30));
for (int i = 0; i < bottleAmount; i++)
{
@@ -289,6 +307,9 @@ namespace Content.Server.GameObjects.Components.Chemistry
else //Pills
{
var individualVolume = BufferSolution.CurrentVolume / ReagentUnit.New(pillAmount);
+ if (individualVolume < ReagentUnit.New(1))
+ return;
+
var actualVolume = ReagentUnit.Min(individualVolume, ReagentUnit.New(50));
for (int i = 0; i < pillAmount; i++)
{
@@ -341,9 +362,6 @@ namespace Content.Server.GameObjects.Components.Chemistry
return;
}
- if (!Powered)
- return;
-
var activeHandEntity = hands.GetActiveHand?.Owner;
if (activeHandEntity == null)
{
diff --git a/Content.Server/GameObjects/Components/Chemistry/ReagentDispenserComponent.cs b/Content.Server/GameObjects/Components/Chemistry/ReagentDispenserComponent.cs
index f9a698e717..a9c384dafb 100644
--- a/Content.Server/GameObjects/Components/Chemistry/ReagentDispenserComponent.cs
+++ b/Content.Server/GameObjects/Components/Chemistry/ReagentDispenserComponent.cs
@@ -80,6 +80,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
_beakerContainer =
ContainerManagerComponent.Ensure($"{Name}-reagentContainerContainer", Owner);
_powerReceiver = Owner.GetComponent();
+ _powerReceiver.OnPowerStateChanged += OnPowerChanged;
InitializeFromPrototype();
UpdateUserInterface();
@@ -105,6 +106,11 @@ namespace Content.Server.GameObjects.Components.Chemistry
}
}
+ private void OnPowerChanged(object sender, PowerStateEventArgs e)
+ {
+ UpdateUserInterface();
+ }
+
///
/// Handles ui messages from the client. For things such as button presses
/// which interact with the world and require server action.
@@ -112,10 +118,16 @@ namespace Content.Server.GameObjects.Components.Chemistry
/// A user interface message from the client.
private void OnUiReceiveMessage(ServerBoundUserInterfaceMessage obj)
{
- if(!PlayerCanUseDispenser(obj.Session.AttachedEntity))
+ var msg = (UiButtonPressedMessage) obj.Message;
+ var needsPower = msg.Button switch
+ {
+ UiButton.Eject => false,
+ _ => true,
+ };
+
+ if(!PlayerCanUseDispenser(obj.Session.AttachedEntity, needsPower))
return;
- var msg = (UiButtonPressedMessage) obj.Message;
switch (msg.Button)
{
case UiButton.Eject:
@@ -161,7 +173,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
///
/// The player entity.
/// Returns true if the entity can use the dispenser, and false if it cannot.
- private bool PlayerCanUseDispenser(IEntity playerEntity)
+ private bool PlayerCanUseDispenser(IEntity playerEntity, bool needsPower = true)
{
//Need player entity to check if they are still able to use the dispenser
if (playerEntity == null)
@@ -170,7 +182,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
if (!ActionBlockerSystem.CanInteract(playerEntity) || !ActionBlockerSystem.CanUse(playerEntity))
return false;
//Check if device is powered
- if (!Powered)
+ if (needsPower && !Powered)
return false;
return true;
@@ -185,12 +197,12 @@ namespace Content.Server.GameObjects.Components.Chemistry
var beaker = _beakerContainer.ContainedEntity;
if (beaker == null)
{
- return new ReagentDispenserBoundUserInterfaceState(false, ReagentUnit.New(0), ReagentUnit.New(0),
+ return new ReagentDispenserBoundUserInterfaceState(Powered, false, ReagentUnit.New(0), ReagentUnit.New(0),
"", Inventory, Owner.Name, null, _dispenseAmount);
}
var solution = beaker.GetComponent();
- return new ReagentDispenserBoundUserInterfaceState(true, solution.CurrentVolume, solution.MaxVolume,
+ return new ReagentDispenserBoundUserInterfaceState(Powered, true, solution.CurrentVolume, solution.MaxVolume,
beaker.Name, Inventory, Owner.Name, solution.ReagentList.ToList(), _dispenseAmount);
}
@@ -263,9 +275,6 @@ namespace Content.Server.GameObjects.Components.Chemistry
return;
}
- if (!Powered)
- return;
-
var activeHandEntity = hands.GetActiveHand?.Owner;
if (activeHandEntity == null)
{
diff --git a/Content.Shared/GameObjects/Components/Chemistry/ChemMaster/SharedChemMasterComponent.cs b/Content.Shared/GameObjects/Components/Chemistry/ChemMaster/SharedChemMasterComponent.cs
index 793e842886..8a4f630fb0 100644
--- a/Content.Shared/GameObjects/Components/Chemistry/ChemMaster/SharedChemMasterComponent.cs
+++ b/Content.Shared/GameObjects/Components/Chemistry/ChemMaster/SharedChemMasterComponent.cs
@@ -1,4 +1,4 @@
-#nullable enable
+#nullable enable
using System;
using System.Collections.Generic;
using Content.Shared.Chemistry;
@@ -19,6 +19,7 @@ namespace Content.Shared.GameObjects.Components.Chemistry
[Serializable, NetSerializable]
public class ChemMasterBoundUserInterfaceState : BoundUserInterfaceState
{
+ public readonly bool HasPower;
public readonly bool HasBeaker;
public readonly ReagentUnit BeakerCurrentVolume;
public readonly ReagentUnit BeakerMaxVolume;
@@ -39,9 +40,10 @@ namespace Content.Shared.GameObjects.Components.Chemistry
public readonly ReagentUnit BufferCurrentVolume;
public readonly ReagentUnit BufferMaxVolume;
- public ChemMasterBoundUserInterfaceState(bool hasBeaker, ReagentUnit beakerCurrentVolume, ReagentUnit beakerMaxVolume, string containerName,
+ public ChemMasterBoundUserInterfaceState(bool hasPower, bool hasBeaker, ReagentUnit beakerCurrentVolume, ReagentUnit beakerMaxVolume, string containerName,
string dispenserName, List containerReagents, List bufferReagents, bool bufferModeTransfer, ReagentUnit bufferCurrentVolume, ReagentUnit bufferMaxVolume)
{
+ HasPower = hasPower;
HasBeaker = hasBeaker;
BeakerCurrentVolume = beakerCurrentVolume;
BeakerMaxVolume = beakerMaxVolume;
diff --git a/Content.Shared/GameObjects/Components/Chemistry/ReagentDispenser/SharedReagentDispenserComponent.cs b/Content.Shared/GameObjects/Components/Chemistry/ReagentDispenser/SharedReagentDispenserComponent.cs
index d9ff0581dd..b2d094a5d0 100644
--- a/Content.Shared/GameObjects/Components/Chemistry/ReagentDispenser/SharedReagentDispenserComponent.cs
+++ b/Content.Shared/GameObjects/Components/Chemistry/ReagentDispenser/SharedReagentDispenserComponent.cs
@@ -25,6 +25,7 @@ namespace Content.Shared.GameObjects.Components.Chemistry
[Serializable, NetSerializable]
public class ReagentDispenserBoundUserInterfaceState : BoundUserInterfaceState
{
+ public readonly bool HasPower;
public readonly bool HasBeaker;
public readonly ReagentUnit BeakerCurrentVolume;
public readonly ReagentUnit BeakerMaxVolume;
@@ -40,9 +41,10 @@ namespace Content.Shared.GameObjects.Components.Chemistry
public readonly string DispenserName;
public readonly ReagentUnit SelectedDispenseAmount;
- public ReagentDispenserBoundUserInterfaceState(bool hasBeaker, ReagentUnit beakerCurrentVolume, ReagentUnit beakerMaxVolume, string containerName,
+ public ReagentDispenserBoundUserInterfaceState(bool hasPower, bool hasBeaker, ReagentUnit beakerCurrentVolume, ReagentUnit beakerMaxVolume, string containerName,
List inventory, string dispenserName, List containerReagents, ReagentUnit selectedDispenseAmount)
{
+ HasPower = hasPower;
HasBeaker = hasBeaker;
BeakerCurrentVolume = beakerCurrentVolume;
BeakerMaxVolume = beakerMaxVolume;