Chem Master & Dispenser Power Fixes (#1622)

* -ChemDispenser & Master can now open the UI without power
-Both can also eject beaker without power

* -Disables button if not powered
-Disables clear & eject buttons if no beaker

* Fix server freeze
This commit is contained in:
Exp
2020-08-10 16:30:56 +02:00
committed by GitHub
parent 9785a8e647
commit aaffd7e198
7 changed files with 119 additions and 23 deletions

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Content.Client.UserInterface; using Content.Client.UserInterface;
@@ -273,6 +273,34 @@ namespace Content.Client.GameObjects.Components.Chemistry.ChemMaster
var castState = (ChemMasterBoundUserInterfaceState) state; var castState = (ChemMasterBoundUserInterfaceState) state;
Title = castState.DispenserName; Title = castState.DispenserName;
UpdatePanelInfo(castState); UpdatePanelInfo(castState);
if (Contents.Children != null)
{
SetButtonDisabledRecursive(Contents, !castState.HasPower);
EjectButton.Disabled = !castState.HasBeaker;
}
}
/// <summary>
/// This searches recursively through all the children of "parent"
/// and sets the Disabled value of any buttons found to "val"
/// </summary>
/// <param name="parent">The control which childrens get searched</param>
/// <param name="val">The value to which disabled gets set</param>
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);
}
}
} }
/// <summary> /// <summary>

View File

@@ -72,8 +72,8 @@ namespace Content.Client.GameObjects.Components.Chemistry
var castState = (ReagentDispenserBoundUserInterfaceState)state; var castState = (ReagentDispenserBoundUserInterfaceState)state;
_lastState = castState; _lastState = castState;
_window?.UpdateState(castState); //Update window state
UpdateReagentsList(castState.Inventory); //Update reagents list & reagent button actions UpdateReagentsList(castState.Inventory); //Update reagents list & reagent button actions
_window?.UpdateState(castState); //Update window state
} }
/// <summary> /// <summary>

View File

@@ -161,6 +161,29 @@ namespace Content.Client.GameObjects.Components.Chemistry
} }
} }
/// <summary>
/// This searches recursively through all the children of "parent"
/// and sets the Disabled value of any buttons found to "val"
/// </summary>
/// <param name="parent">The control which childrens get searched</param>
/// <param name="val">The value to which disabled gets set</param>
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);
}
}
}
/// <summary> /// <summary>
/// Update the UI state when new state data is received from the server. /// Update the UI state when new state data is received from the server.
/// </summary> /// </summary>
@@ -171,6 +194,20 @@ namespace Content.Client.GameObjects.Components.Chemistry
Title = castState.DispenserName; Title = castState.DispenserName;
UpdateContainerInfo(castState); 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()) switch (castState.SelectedDispenseAmount.Int())
{ {
case 1: case 1:

View File

@@ -83,6 +83,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
_beakerContainer = _beakerContainer =
ContainerManagerComponent.Ensure<ContainerSlot>($"{Name}-reagentContainerContainer", Owner); ContainerManagerComponent.Ensure<ContainerSlot>($"{Name}-reagentContainerContainer", Owner);
_powerReceiver = Owner.GetComponent<PowerReceiverComponent>(); _powerReceiver = Owner.GetComponent<PowerReceiverComponent>();
_powerReceiver.OnPowerStateChanged += OnPowerChanged;
//BufferSolution = Owner.BufferSolution //BufferSolution = Owner.BufferSolution
BufferSolution.Solution = new Solution(); BufferSolution.Solution = new Solution();
@@ -91,6 +92,11 @@ namespace Content.Server.GameObjects.Components.Chemistry
UpdateUserInterface(); UpdateUserInterface();
} }
private void OnPowerChanged(object sender, PowerStateEventArgs e)
{
UpdateUserInterface();
}
/// <summary> /// <summary>
/// Handles ui messages from the client. For things such as button presses /// Handles ui messages from the client. For things such as button presses
/// which interact with the world and require server action. /// which interact with the world and require server action.
@@ -98,10 +104,16 @@ namespace Content.Server.GameObjects.Components.Chemistry
/// <param name="obj">A user interface message from the client.</param> /// <param name="obj">A user interface message from the client.</param>
private void OnUiReceiveMessage(ServerBoundUserInterfaceMessage obj) 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; return;
var msg = (UiActionMessage) obj.Message;
switch (msg.action) switch (msg.action)
{ {
case UiAction.Eject: case UiAction.Eject:
@@ -134,7 +146,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
/// </summary> /// </summary>
/// <param name="playerEntity">The player entity.</param> /// <param name="playerEntity">The player entity.</param>
/// <returns>Returns true if the entity can use the chem master, and false if it cannot.</returns> /// <returns>Returns true if the entity can use the chem master, and false if it cannot.</returns>
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 //Need player entity to check if they are still able to use the chem master
if (playerEntity == null) if (playerEntity == null)
@@ -143,7 +155,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
if (!ActionBlockerSystem.CanInteract(playerEntity) || !ActionBlockerSystem.CanUse(playerEntity)) if (!ActionBlockerSystem.CanInteract(playerEntity) || !ActionBlockerSystem.CanUse(playerEntity))
return false; return false;
//Check if device is powered //Check if device is powered
if (!Powered) if (needsPower && !Powered)
return false; return false;
return true; return true;
@@ -158,12 +170,12 @@ namespace Content.Server.GameObjects.Components.Chemistry
var beaker = _beakerContainer.ContainedEntity; var beaker = _beakerContainer.ContainedEntity;
if (beaker == null) 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); "", Owner.Name, null, BufferSolution.ReagentList.ToList(), BufferModeTransfer, BufferSolution.CurrentVolume, BufferSolution.MaxVolume);
} }
var solution = beaker.GetComponent<SolutionComponent>(); var solution = beaker.GetComponent<SolutionComponent>();
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); 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<IRobustRandom>(); var random = IoCManager.Resolve<IRobustRandom>();
if (BufferSolution.CurrentVolume == 0)
return;
if (action == UiAction.CreateBottles) if (action == UiAction.CreateBottles)
{ {
var individualVolume = BufferSolution.CurrentVolume / ReagentUnit.New(bottleAmount); var individualVolume = BufferSolution.CurrentVolume / ReagentUnit.New(bottleAmount);
if (individualVolume < ReagentUnit.New(1))
return;
var actualVolume = ReagentUnit.Min(individualVolume, ReagentUnit.New(30)); var actualVolume = ReagentUnit.Min(individualVolume, ReagentUnit.New(30));
for (int i = 0; i < bottleAmount; i++) for (int i = 0; i < bottleAmount; i++)
{ {
@@ -289,6 +307,9 @@ namespace Content.Server.GameObjects.Components.Chemistry
else //Pills else //Pills
{ {
var individualVolume = BufferSolution.CurrentVolume / ReagentUnit.New(pillAmount); var individualVolume = BufferSolution.CurrentVolume / ReagentUnit.New(pillAmount);
if (individualVolume < ReagentUnit.New(1))
return;
var actualVolume = ReagentUnit.Min(individualVolume, ReagentUnit.New(50)); var actualVolume = ReagentUnit.Min(individualVolume, ReagentUnit.New(50));
for (int i = 0; i < pillAmount; i++) for (int i = 0; i < pillAmount; i++)
{ {
@@ -341,9 +362,6 @@ namespace Content.Server.GameObjects.Components.Chemistry
return; return;
} }
if (!Powered)
return;
var activeHandEntity = hands.GetActiveHand?.Owner; var activeHandEntity = hands.GetActiveHand?.Owner;
if (activeHandEntity == null) if (activeHandEntity == null)
{ {

View File

@@ -80,6 +80,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
_beakerContainer = _beakerContainer =
ContainerManagerComponent.Ensure<ContainerSlot>($"{Name}-reagentContainerContainer", Owner); ContainerManagerComponent.Ensure<ContainerSlot>($"{Name}-reagentContainerContainer", Owner);
_powerReceiver = Owner.GetComponent<PowerReceiverComponent>(); _powerReceiver = Owner.GetComponent<PowerReceiverComponent>();
_powerReceiver.OnPowerStateChanged += OnPowerChanged;
InitializeFromPrototype(); InitializeFromPrototype();
UpdateUserInterface(); UpdateUserInterface();
@@ -105,6 +106,11 @@ namespace Content.Server.GameObjects.Components.Chemistry
} }
} }
private void OnPowerChanged(object sender, PowerStateEventArgs e)
{
UpdateUserInterface();
}
/// <summary> /// <summary>
/// Handles ui messages from the client. For things such as button presses /// Handles ui messages from the client. For things such as button presses
/// which interact with the world and require server action. /// which interact with the world and require server action.
@@ -112,10 +118,16 @@ namespace Content.Server.GameObjects.Components.Chemistry
/// <param name="obj">A user interface message from the client.</param> /// <param name="obj">A user interface message from the client.</param>
private void OnUiReceiveMessage(ServerBoundUserInterfaceMessage obj) 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; return;
var msg = (UiButtonPressedMessage) obj.Message;
switch (msg.Button) switch (msg.Button)
{ {
case UiButton.Eject: case UiButton.Eject:
@@ -161,7 +173,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
/// </summary> /// </summary>
/// <param name="playerEntity">The player entity.</param> /// <param name="playerEntity">The player entity.</param>
/// <returns>Returns true if the entity can use the dispenser, and false if it cannot.</returns> /// <returns>Returns true if the entity can use the dispenser, and false if it cannot.</returns>
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 //Need player entity to check if they are still able to use the dispenser
if (playerEntity == null) if (playerEntity == null)
@@ -170,7 +182,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
if (!ActionBlockerSystem.CanInteract(playerEntity) || !ActionBlockerSystem.CanUse(playerEntity)) if (!ActionBlockerSystem.CanInteract(playerEntity) || !ActionBlockerSystem.CanUse(playerEntity))
return false; return false;
//Check if device is powered //Check if device is powered
if (!Powered) if (needsPower && !Powered)
return false; return false;
return true; return true;
@@ -185,12 +197,12 @@ namespace Content.Server.GameObjects.Components.Chemistry
var beaker = _beakerContainer.ContainedEntity; var beaker = _beakerContainer.ContainedEntity;
if (beaker == null) 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); "", Inventory, Owner.Name, null, _dispenseAmount);
} }
var solution = beaker.GetComponent<SolutionComponent>(); var solution = beaker.GetComponent<SolutionComponent>();
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); beaker.Name, Inventory, Owner.Name, solution.ReagentList.ToList(), _dispenseAmount);
} }
@@ -263,9 +275,6 @@ namespace Content.Server.GameObjects.Components.Chemistry
return; return;
} }
if (!Powered)
return;
var activeHandEntity = hands.GetActiveHand?.Owner; var activeHandEntity = hands.GetActiveHand?.Owner;
if (activeHandEntity == null) if (activeHandEntity == null)
{ {

View File

@@ -1,4 +1,4 @@
#nullable enable #nullable enable
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Content.Shared.Chemistry; using Content.Shared.Chemistry;
@@ -19,6 +19,7 @@ namespace Content.Shared.GameObjects.Components.Chemistry
[Serializable, NetSerializable] [Serializable, NetSerializable]
public class ChemMasterBoundUserInterfaceState : BoundUserInterfaceState public class ChemMasterBoundUserInterfaceState : BoundUserInterfaceState
{ {
public readonly bool HasPower;
public readonly bool HasBeaker; public readonly bool HasBeaker;
public readonly ReagentUnit BeakerCurrentVolume; public readonly ReagentUnit BeakerCurrentVolume;
public readonly ReagentUnit BeakerMaxVolume; public readonly ReagentUnit BeakerMaxVolume;
@@ -39,9 +40,10 @@ namespace Content.Shared.GameObjects.Components.Chemistry
public readonly ReagentUnit BufferCurrentVolume; public readonly ReagentUnit BufferCurrentVolume;
public readonly ReagentUnit BufferMaxVolume; 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<Solution.ReagentQuantity> containerReagents, List<Solution.ReagentQuantity> bufferReagents, bool bufferModeTransfer, ReagentUnit bufferCurrentVolume, ReagentUnit bufferMaxVolume) string dispenserName, List<Solution.ReagentQuantity> containerReagents, List<Solution.ReagentQuantity> bufferReagents, bool bufferModeTransfer, ReagentUnit bufferCurrentVolume, ReagentUnit bufferMaxVolume)
{ {
HasPower = hasPower;
HasBeaker = hasBeaker; HasBeaker = hasBeaker;
BeakerCurrentVolume = beakerCurrentVolume; BeakerCurrentVolume = beakerCurrentVolume;
BeakerMaxVolume = beakerMaxVolume; BeakerMaxVolume = beakerMaxVolume;

View File

@@ -25,6 +25,7 @@ namespace Content.Shared.GameObjects.Components.Chemistry
[Serializable, NetSerializable] [Serializable, NetSerializable]
public class ReagentDispenserBoundUserInterfaceState : BoundUserInterfaceState public class ReagentDispenserBoundUserInterfaceState : BoundUserInterfaceState
{ {
public readonly bool HasPower;
public readonly bool HasBeaker; public readonly bool HasBeaker;
public readonly ReagentUnit BeakerCurrentVolume; public readonly ReagentUnit BeakerCurrentVolume;
public readonly ReagentUnit BeakerMaxVolume; public readonly ReagentUnit BeakerMaxVolume;
@@ -40,9 +41,10 @@ namespace Content.Shared.GameObjects.Components.Chemistry
public readonly string DispenserName; public readonly string DispenserName;
public readonly ReagentUnit SelectedDispenseAmount; 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<ReagentDispenserInventoryEntry> inventory, string dispenserName, List<Solution.ReagentQuantity> containerReagents, ReagentUnit selectedDispenseAmount) List<ReagentDispenserInventoryEntry> inventory, string dispenserName, List<Solution.ReagentQuantity> containerReagents, ReagentUnit selectedDispenseAmount)
{ {
HasPower = hasPower;
HasBeaker = hasBeaker; HasBeaker = hasBeaker;
BeakerCurrentVolume = beakerCurrentVolume; BeakerCurrentVolume = beakerCurrentVolume;
BeakerMaxVolume = beakerMaxVolume; BeakerMaxVolume = beakerMaxVolume;