From ae91059c0bea7c47a0798eb330e4a10a265cc9d1 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Sat, 23 Jan 2021 16:45:20 +0100 Subject: [PATCH] Adds "Add Reagent" admin verb. --- .../UserInterface/AdminAddReagentUI.cs | 172 ++++++++++++++++++ .../Chemistry/SolutionContainerComponent.cs | 107 ++++++++++- .../Administration/AdminAddReagentEuiState.cs | 31 ++++ 3 files changed, 307 insertions(+), 3 deletions(-) create mode 100644 Content.Client/UserInterface/AdminAddReagentUI.cs create mode 100644 Content.Shared/Administration/AdminAddReagentEuiState.cs diff --git a/Content.Client/UserInterface/AdminAddReagentUI.cs b/Content.Client/UserInterface/AdminAddReagentUI.cs new file mode 100644 index 0000000000..adb9986a71 --- /dev/null +++ b/Content.Client/UserInterface/AdminAddReagentUI.cs @@ -0,0 +1,172 @@ +using Content.Client.Eui; +using Content.Shared.Administration; +using Content.Shared.Chemistry; +using Content.Shared.Eui; +using JetBrains.Annotations; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.CustomControls; +using Robust.Shared.IoC; +using Robust.Shared.Localization; +using Robust.Shared.Prototypes; + +namespace Content.Client.UserInterface +{ + [UsedImplicitly] + public sealed class AdminAddReagentEui : BaseEui + { + [Dependency] private readonly IPrototypeManager _prototypes = default!; + + private readonly Menu _window; + private bool _closed; + + public AdminAddReagentEui() + { + _window = new Menu(this); + _window.OnClose += () => SendMessage(new AdminAddReagentEuiMsg.Close()); + } + + public override void Opened() + { + _window.OpenCentered(); + } + + public override void Closed() + { + _closed = true; + + _window.Close(); + } + + public override void HandleState(EuiStateBase state) + { + _window.HandleState((AdminAddReagentEuiState) state); + } + + private void DoAdd(bool close, string reagentId, ReagentUnit amount) + { + SendMessage(new AdminAddReagentEuiMsg.DoAdd + { + Amount = amount, + ReagentId = reagentId, + CloseAfter = close + }); + } + + private sealed class Menu : SS14Window + { + private readonly AdminAddReagentEui _eui; + private readonly Label _volumeLabel; + private readonly LineEdit _reagentIdEdit; + private readonly LineEdit _amountEdit; + private readonly Label _errorLabel; + private readonly Button _addButton; + private readonly Button _addCloseButton; + + public Menu(AdminAddReagentEui eui) + { + _eui = eui; + + Title = Loc.GetString("Add reagent..."); + + Contents.AddChild(new VBoxContainer + { + Children = + { + new GridContainer + { + Columns = 2, + Children = + { + new Label {Text = Loc.GetString("Cur volume: ")}, + (_volumeLabel = new Label()), + new Label {Text = Loc.GetString("Reagent: ")}, + (_reagentIdEdit = new LineEdit {PlaceHolder = Loc.GetString("Reagent ID...")}), + new Label {Text = Loc.GetString("Amount: ")}, + (_amountEdit = new LineEdit + { + PlaceHolder = Loc.GetString("A number..."), + SizeFlagsHorizontal = SizeFlags.FillExpand + }), + }, + SizeFlagsHorizontal = SizeFlags.FillExpand, + SizeFlagsVertical = SizeFlags.FillExpand + }, + new HBoxContainer + { + Children = + { + (_errorLabel = new Label + { + SizeFlagsHorizontal = SizeFlags.FillExpand, + ClipText = true + }), + + (_addButton = new Button {Text = Loc.GetString("Add")}), + (_addCloseButton = new Button {Text = Loc.GetString("Add & Close")}) + } + } + } + }); + + _reagentIdEdit.OnTextChanged += _ => CheckErrors(); + _amountEdit.OnTextChanged += _ => CheckErrors(); + _addButton.OnPressed += _ => DoAdd(false); + _addCloseButton.OnPressed += _ => DoAdd(true); + + CheckErrors(); + } + + private void DoAdd(bool close) + { + _eui.DoAdd( + close, + _reagentIdEdit.Text, + ReagentUnit.New(float.Parse(_amountEdit.Text))); + } + + private void CheckErrors() + { + if (string.IsNullOrWhiteSpace(_reagentIdEdit.Text)) + { + DoError(Loc.GetString("Must specify reagent ID")); + return; + } + + if (!_eui._prototypes.HasIndex(_reagentIdEdit.Text)) + { + DoError(Loc.GetString("'{0}' does not exist.", _reagentIdEdit.Text)); + return; + } + + if (string.IsNullOrWhiteSpace(_amountEdit.Text)) + { + DoError(Loc.GetString("Must specify reagent amount")); + return; + } + + if (!float.TryParse(_amountEdit.Text, out _)) + { + DoError(Loc.GetString("Invalid amount")); + return; + } + + _addButton.Disabled = false; + _addCloseButton.Disabled = false; + _errorLabel.Text = ""; + + void DoError(string text) + { + _errorLabel.Text = text; + + _addButton.Disabled = true; + _addCloseButton.Disabled = true; + } + } + + public void HandleState(AdminAddReagentEuiState state) + { + _volumeLabel.Text = Loc.GetString("{0}/{1}u", state.CurVolume, state.MaxVolume); + } + } + } +} diff --git a/Content.Server/GameObjects/Components/Chemistry/SolutionContainerComponent.cs b/Content.Server/GameObjects/Components/Chemistry/SolutionContainerComponent.cs index 79a003913e..d60b1dc0fb 100644 --- a/Content.Server/GameObjects/Components/Chemistry/SolutionContainerComponent.cs +++ b/Content.Server/GameObjects/Components/Chemistry/SolutionContainerComponent.cs @@ -1,11 +1,18 @@ #nullable enable +using Content.Server.Administration; +using Content.Server.Eui; using Content.Server.GameObjects.Components.GUI; +using Content.Shared.Administration; using Content.Shared.Chemistry; +using Content.Shared.Eui; using Content.Shared.GameObjects.Components.Chemistry; using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; +using Robust.Server.Interfaces.GameObjects; +using Robust.Server.Interfaces.Player; using Robust.Shared.GameObjects; using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.IoC; using Robust.Shared.Localization; namespace Content.Server.GameObjects.Components.Chemistry @@ -58,7 +65,8 @@ namespace Content.Server.GameObjects.Components.Chemistry return; } - var transferQuantity = ReagentUnit.Min(component.MaxVolume - component.CurrentVolume, handSolutionComp.CurrentVolume, ReagentUnit.New(10)); + var transferQuantity = ReagentUnit.Min(component.MaxVolume - component.CurrentVolume, + handSolutionComp.CurrentVolume, ReagentUnit.New(10)); if (transferQuantity <= 0) { @@ -108,14 +116,15 @@ namespace Content.Server.GameObjects.Components.Chemistry return; } - if(!hands.GetActiveHand.Owner.TryGetComponent(out var handSolutionComp) || + if (!hands.GetActiveHand.Owner.TryGetComponent(out var handSolutionComp) || !handSolutionComp.CanAddSolutions || !component.CanRemoveSolutions) { return; } - var transferQuantity = ReagentUnit.Min(handSolutionComp.MaxVolume - handSolutionComp.CurrentVolume, component.CurrentVolume, ReagentUnit.New(10)); + var transferQuantity = ReagentUnit.Min(handSolutionComp.MaxVolume - handSolutionComp.CurrentVolume, + component.CurrentVolume, ReagentUnit.New(10)); if (transferQuantity <= 0) { @@ -126,5 +135,97 @@ namespace Content.Server.GameObjects.Components.Chemistry handSolutionComp.TryAddSolution(transferSolution); } } + + [Verb] + private sealed class AdminAddReagentVerb : Verb + { + private const AdminFlags ReqFlags = AdminFlags.Fun; + + protected override void GetData(IEntity user, SolutionContainerComponent component, VerbData data) + { + data.Text = Loc.GetString("Add Reagent..."); + data.CategoryData = VerbCategories.Debug; + data.Visibility = VerbVisibility.Invisible; + + var adminManager = IoCManager.Resolve(); + + if (user.TryGetComponent(out var player)) + { + if (adminManager.HasAdminFlag(player.playerSession, ReqFlags)) + { + data.Visibility = VerbVisibility.Visible; + } + } + } + + protected override void Activate(IEntity user, SolutionContainerComponent component) + { + var groupController = IoCManager.Resolve(); + if (user.TryGetComponent(out var player)) + { + if (groupController.HasAdminFlag(player.playerSession, ReqFlags)) + OpenAddReagentMenu(player.playerSession, component); + } + } + + private static void OpenAddReagentMenu(IPlayerSession player, SolutionContainerComponent comp) + { + var euiMgr = IoCManager.Resolve(); + euiMgr.OpenEui(new AdminAddReagentEui(comp), player); + } + + private sealed class AdminAddReagentEui : BaseEui + { + private readonly SolutionContainerComponent _target; + [Dependency] private readonly IAdminManager _adminManager = default!; + + public AdminAddReagentEui(SolutionContainerComponent target) + { + _target = target; + + IoCManager.InjectDependencies(this); + } + + public override void Opened() + { + StateDirty(); + } + + public override EuiStateBase GetNewState() + { + return new AdminAddReagentEuiState + { + CurVolume = _target.CurrentVolume, + MaxVolume = _target.MaxVolume + }; + } + + public override void HandleMessage(EuiMessageBase msg) + { + switch (msg) + { + case AdminAddReagentEuiMsg.Close: + Close(); + break; + case AdminAddReagentEuiMsg.DoAdd doAdd: + // Double check that user wasn't de-adminned in the mean time... + // Or the target was deleted. + if (!_adminManager.HasAdminFlag(Player, ReqFlags) || _target.Deleted) + { + Close(); + return; + } + + _target.TryAddReagent(doAdd.ReagentId, doAdd.Amount, out _); + StateDirty(); + + if (doAdd.CloseAfter) + Close(); + + break; + } + } + } + } } } diff --git a/Content.Shared/Administration/AdminAddReagentEuiState.cs b/Content.Shared/Administration/AdminAddReagentEuiState.cs new file mode 100644 index 0000000000..25bf03e17c --- /dev/null +++ b/Content.Shared/Administration/AdminAddReagentEuiState.cs @@ -0,0 +1,31 @@ +using System; +using Content.Shared.Chemistry; +using Content.Shared.Eui; +using Robust.Shared.Serialization; + +namespace Content.Shared.Administration +{ + [Serializable, NetSerializable] + public sealed class AdminAddReagentEuiState : EuiStateBase + { + public ReagentUnit MaxVolume; + public ReagentUnit CurVolume; + } + + public static class AdminAddReagentEuiMsg + { + [Serializable, NetSerializable] + public sealed class Close : EuiMessageBase + { + + } + + [Serializable, NetSerializable] + public sealed class DoAdd : EuiMessageBase + { + public bool CloseAfter; + public ReagentUnit Amount; + public string ReagentId; + } + } +}