Fix & extend add reagent verb (#4954)

* AddReagentWindow

* addReagent command

* functional UI

* fix networking

* add comments & docstrings

* Remove unecesary system

* cleanup & close-eui

* tweak default window size

* fix EUI closing error

* fix merge issues

* fix merge
This commit is contained in:
Leon Friedrich
2021-11-08 17:22:42 +13:00
committed by GitHub
parent 54f7b68503
commit 3612d25539
22 changed files with 609 additions and 339 deletions

View File

@@ -1,176 +0,0 @@
using Content.Client.Eui;
using Content.Shared.Administration;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.Eui;
using Content.Shared.FixedPoint;
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;
using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Administration.UI
{
[UsedImplicitly]
public sealed class AdminAddReagentEui : BaseEui
{
[Dependency] private readonly IPrototypeManager _prototypes = default!;
private readonly Menu _window;
public AdminAddReagentEui()
{
_window = new Menu(this);
_window.OnClose += () => SendMessage(new AdminAddReagentEuiMsg.Close());
}
public override void Opened()
{
_window.OpenCentered();
}
public override void Closed()
{
_window.Close();
}
public override void HandleState(EuiStateBase state)
{
_window.HandleState((AdminAddReagentEuiState) state);
}
private void DoAdd(bool close, string reagentId, FixedPoint2 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("admin-add-reagent-eui-title");
Contents.AddChild(new BoxContainer
{
Orientation = LayoutOrientation.Vertical,
Children =
{
new GridContainer
{
Columns = 2,
Children =
{
new Label {Text = Loc.GetString("admin-add-reagent-eui-current-volume-label") + " "},
(_volumeLabel = new Label()),
new Label {Text = Loc.GetString("admin-add-reagent-eui-reagent-label") + " "},
(_reagentIdEdit = new LineEdit {PlaceHolder = Loc.GetString("admin-add-reagent-eui-reagent-id-edit")}),
new Label {Text = Loc.GetString("admin-add-reagent-eui-amount-label") + " "},
(_amountEdit = new LineEdit
{
PlaceHolder = Loc.GetString("admin-add-reagent-eui-amount-edit"),
HorizontalExpand = true
}),
},
HorizontalExpand = true,
VerticalExpand = true
},
new BoxContainer
{
Orientation = LayoutOrientation.Horizontal,
Children =
{
(_errorLabel = new Label
{
HorizontalExpand = true,
ClipText = true
}),
(_addButton = new Button {Text = Loc.GetString("admin-add-reagent-eui-add-button")}),
(_addCloseButton = new Button {Text = Loc.GetString("admin-add-reagent-eui-add-close-button")})
}
}
}
});
_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,
FixedPoint2.New(float.Parse(_amountEdit.Text)));
}
private void CheckErrors()
{
if (string.IsNullOrWhiteSpace(_reagentIdEdit.Text))
{
DoError(Loc.GetString("admin-add-reagent-eui-no-reagent-id-error"));
return;
}
if (!_eui._prototypes.HasIndex<ReagentPrototype>(_reagentIdEdit.Text))
{
DoError(Loc.GetString("admin-add-reagent-eui-reagent-does-not-exist-error",
("reagent", _reagentIdEdit.Text)));
return;
}
if (string.IsNullOrWhiteSpace(_amountEdit.Text))
{
DoError(Loc.GetString("admin-add-reagent-eui-no-reagent-amount-specified-error"));
return;
}
if (!float.TryParse(_amountEdit.Text, out _))
{
DoError(Loc.GetString("admin-add-reagent-eui-invalid-amount-error"));
return;
}
_addButton.Disabled = false;
_addCloseButton.Disabled = false;
_errorLabel.Text = string.Empty;
void DoError(string text)
{
_errorLabel.Text = text;
_addButton.Disabled = true;
_addCloseButton.Disabled = true;
}
}
public void HandleState(AdminAddReagentEuiState state)
{
_volumeLabel.Text = Loc.GetString("admin-add-reagent-eui-current-and-max-volume-label",
("currentVolume", state.CurVolume),
("maxVolume" ,state.MaxVolume));
}
}
}
}

View File

@@ -0,0 +1,13 @@
<SS14Window
SetSize="250 300"
Margin="4 0"
xmlns="https://spacestation14.io">
<BoxContainer Orientation="Vertical">
<BoxContainer Name="QuantityBox" Orientation="Horizontal" Margin ="0 4">
<Label Text="{Loc 'admin-add-reagent-window-amount-label'}" Margin="0 0 10 0"/>
</BoxContainer>
<LineEdit Name="SearchBar" PlaceHolder="{Loc 'admin-add-reagent-window-search-placeholder'}" HorizontalExpand="True" Margin ="0 4"/>
<ItemList Name="ReagentList" SelectMode="Single" VerticalExpand="True" Margin ="0 4"/>
<Button Name="AddButton" HorizontalExpand="True" Margin ="0 4" />
</BoxContainer>
</SS14Window>

View File

@@ -0,0 +1,135 @@
using Content.Shared.Chemistry.Reagent;
using Robust.Client.AutoGenerated;
using Robust.Client.Console;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Prototypes;
namespace Content.Client.Administration.UI.ManageSolutions
{
/// <summary>
/// A debug window that allows you to add a reagent to a solution. Intended to be used with <see
/// cref="EditSolutionsWindow"/>
/// </summary>
[GenerateTypedNameReferences]
public sealed partial class AddReagentWindow : SS14Window
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IClientConsoleHost _consoleHost = default!;
private readonly EntityUid _targetEntity;
private string _targetSolution;
private ReagentPrototype? _selectedReagent;
// FloatSpinBox does not (yet?) play nice with xaml
private FloatSpinBox _quantitySpin = new(1, 2) { Value = 10, HorizontalExpand = true};
public AddReagentWindow(EntityUid targetEntity, string targetSolution)
{
IoCManager.InjectDependencies(this);
RobustXamlLoader.Load(this);
Title = Loc.GetString("admin-add-reagent-window-title", ("solution", targetSolution));
_targetEntity = targetEntity;
_targetSolution = targetSolution;
QuantityBox.AddChild(_quantitySpin);
ReagentList.OnItemSelected += ReagentListSelected;
ReagentList.OnItemDeselected += ReagentListDeselected;
SearchBar.OnTextChanged += (_) => UpdateReagentPrototypes(SearchBar.Text);
_quantitySpin.OnValueChanged += (_) => UpdateAddButton();
AddButton.OnPressed += AddReagent;
UpdateReagentPrototypes();
UpdateAddButton();
}
/// <summary>
/// Execute a console command that asks the server to add the selected reagent.
/// </summary>
private void AddReagent(BaseButton.ButtonEventArgs obj)
{
if (_selectedReagent == null)
return;
var quantity = _quantitySpin.Value.ToString("F2");
var command = $"addreagent {_targetEntity} {_targetSolution} {_selectedReagent.ID} {quantity}";
_consoleHost.ExecuteCommand(command);
}
private void ReagentListSelected(ItemList.ItemListSelectedEventArgs obj)
{
_selectedReagent = (ReagentPrototype) obj.ItemList[obj.ItemIndex].Metadata!;
UpdateAddButton();
}
private void ReagentListDeselected(ItemList.ItemListDeselectedEventArgs obj)
{
_selectedReagent = null;
UpdateAddButton();
}
public void UpdateSolution(string? selectedSolution)
{
if (selectedSolution == null)
{
Close();
Dispose();
return;
}
_targetSolution = selectedSolution;
Title = Loc.GetString("admin-add-reagent-window-title", ("solution", _targetSolution));
UpdateAddButton();
}
/// <summary>
/// Set the Text and enabled/disabled status of the button that actually adds the reagent.
/// </summary>
private void UpdateAddButton()
{
AddButton.Disabled = true;
if (_selectedReagent == null)
{
AddButton.Text = Loc.GetString("admin-add-reagent-window-add-invalid-reagent");
return;
}
AddButton.Text = Loc.GetString("admin-add-reagent-window-add",
("quantity", _quantitySpin.Value.ToString("F2")),
("reagent", _selectedReagent.ID));
AddButton.Disabled = false;
}
/// <summary>
/// Get a list of all reagent prototypes and show them in an item list.
/// </summary>
private void UpdateReagentPrototypes(string? filter = null)
{
ReagentList.Clear();
foreach (var reagent in _prototypeManager.EnumeratePrototypes<ReagentPrototype>())
{
if (!string.IsNullOrEmpty(filter) &&
!reagent.ID.ToLowerInvariant().Contains(filter.Trim().ToLowerInvariant()))
{
continue;
}
ItemList.Item regentItem = new(ReagentList)
{
Metadata = reagent,
Text = reagent.ID
};
ReagentList.Add(regentItem);
}
}
}
}

View File

@@ -0,0 +1,43 @@
using Content.Client.Eui;
using Content.Shared.Administration;
using Content.Shared.Eui;
using JetBrains.Annotations;
namespace Content.Client.Administration.UI.ManageSolutions
{
/// <summary>
/// Admin Eui for displaying and editing the reagents in a solution.
/// </summary>
[UsedImplicitly]
public sealed class EditSolutionsEui : BaseEui
{
private readonly EditSolutionsWindow _window;
public EditSolutionsEui()
{
_window = new EditSolutionsWindow();
_window.OnClose += () => SendMessage(new EditSolutionsEuiMsg.Close());
}
public override void Opened()
{
base.Opened();
_window.OpenCentered();
}
public override void Closed()
{
base.Closed();
_window.OnClose -= () => SendMessage(new EditSolutionsEuiMsg.Close());
_window.Close();
}
public override void HandleState(EuiStateBase baseState)
{
var state = (EditSolutionsEuiState) baseState;
_window.SetTargetEntity(state.Target);
_window.UpdateSolutions(state.Solutions);
_window.UpdateReagents();
}
}
}

View File

@@ -0,0 +1,16 @@
<SS14Window
SetSize="300 300"
Margin="4 0"
xmlns="https://spacestation14.io">
<BoxContainer Orientation="Vertical">
<BoxContainer Orientation="Horizontal" HorizontalExpand="True" Margin="0 4">
<Label Text ="{Loc 'admin-solutions-window-solution-label'}" Margin="0 0 10 0"/>
<OptionButton Name="SolutionOption" HorizontalExpand="True"/>
</BoxContainer>
<Label Name="TotalLabel" HorizontalExpand="True" Margin="0 4"/>
<ScrollContainer HorizontalExpand="True" VerticalExpand="True" Margin="0 4">
<BoxContainer Name="ReagentList" Orientation="Vertical"/>
</ScrollContainer>
<Button Name="AddButton" Text="{Loc 'admin-solutions-window-add-new-button'}" HorizontalExpand="True" Margin="0 4"/>
</BoxContainer>
</SS14Window>

View File

@@ -0,0 +1,179 @@
using Content.Shared.Chemistry.Components;
using Robust.Client.AutoGenerated;
using Robust.Client.Console;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using System;
using System.Collections.Generic;
namespace Content.Client.Administration.UI.ManageSolutions
{
/// <summary>
/// A simple window that displays solutions and their contained reagents. Allows you to edit the reagent quantities and add new reagents.
/// </summary>
[GenerateTypedNameReferences]
public sealed partial class EditSolutionsWindow : SS14Window
{
[Dependency] private readonly IClientConsoleHost _consoleHost = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
private EntityUid _target = EntityUid.Invalid;
private string? _selectedSolution;
private AddReagentWindow? _addReagentWindow;
private Dictionary<string, Solution>? _solutions;
public EditSolutionsWindow()
{
IoCManager.InjectDependencies(this);
RobustXamlLoader.Load(this);
SolutionOption.OnItemSelected += SolutionSelected;
AddButton.OnPressed += OpenAddReagentWindow;
}
public override void Close()
{
base.Close();
_addReagentWindow?.Close();
_addReagentWindow?.Dispose();
}
public void SetTargetEntity(EntityUid target)
{
_target = target;
var targetName = _entityManager.TryGetEntity(target, out var entity)
? entity.Name
: string.Empty;
Title = Loc.GetString("admin-solutions-window-title", ("targetName", targetName));
}
/// <summary>
/// Update the capacity label and re-create the reagent list
/// </summary>
public void UpdateReagents()
{
ReagentList.DisposeAllChildren();
if (_selectedSolution == null || _solutions == null)
return;
if (!_solutions.TryGetValue(_selectedSolution, out var solution))
return;
TotalLabel.Text = Loc.GetString("admin-solutions-window-capacity-label",
("currentVolume", solution.TotalVolume),
("maxVolume",solution.MaxVolume));
foreach (var reagent in solution)
{
AddReagentEntry(reagent);
}
}
/// <summary>
/// Add a single reagent entry to the list
/// </summary>
private void AddReagentEntry(Solution.ReagentQuantity reagent)
{
var box = new BoxContainer();
var spin = new FloatSpinBox(1, 2);
spin.Value = reagent.Quantity.Float();
spin.OnValueChanged += (args) => SetReagent(args, reagent.ReagentId);
spin.HorizontalExpand = true;
box.AddChild(new Label() { Text = reagent.ReagentId , HorizontalExpand = true});
box.AddChild(spin);
ReagentList.AddChild(box);
}
/// <summary>
/// Execute a command to modify the reagents in the solution.
/// </summary>
private void SetReagent(FloatSpinBox.FloatSpinBoxEventArgs args, string reagentId)
{
if (_solutions == null || _selectedSolution == null)
return;
var current = _solutions[_selectedSolution].GetReagentQuantity(reagentId);
var delta = args.Value - current.Float();
if (MathF.Abs(delta) < 0.01)
return;
var command = $"addreagent {_target} {_selectedSolution} {reagentId} {delta}";
_consoleHost.ExecuteCommand(command);
}
/// <summary>
/// Open a new window that has options to add new reagents to the solution.
/// </summary>
private void OpenAddReagentWindow(BaseButton.ButtonEventArgs obj)
{
if (string.IsNullOrEmpty(_selectedSolution))
return;
_addReagentWindow?.Close();
_addReagentWindow?.Dispose();
_addReagentWindow = new AddReagentWindow(_target, _selectedSolution);
_addReagentWindow.OpenCentered();
}
/// <summary>
/// When a new solution is selected, set _selectedSolution and update the reagent list.
/// </summary>
private void SolutionSelected(OptionButton.ItemSelectedEventArgs args)
{
SolutionOption.SelectId(args.Id);
_selectedSolution = (string?) SolutionOption.SelectedMetadata;
_addReagentWindow?.UpdateSolution(_selectedSolution);
UpdateReagents();
}
/// <summary>
/// Update the solution options.
/// </summary>
public void UpdateSolutions(Dictionary<string, Solution>? solutions)
{
SolutionOption.Clear();
_solutions = solutions;
if (_solutions == null)
return;
int i = 0;
foreach (var solution in _solutions.Keys)
{
SolutionOption.AddItem(solution, i);
SolutionOption.SetItemMetadata(i, solution);
if (solution == _selectedSolution)
SolutionOption.Select(i);
i++;
}
if (SolutionOption.ItemCount == 0)
{
// No applicable solutions
Close();
Dispose();
}
if (_selectedSolution == null || !_solutions.ContainsKey(_selectedSolution))
{
// the previously selected solution is no longer valid.
SolutionOption.Select(0);
_selectedSolution = (string?) SolutionOption.SelectedMetadata;
}
}
}
}

View File

@@ -1,8 +1,10 @@
using System.Collections.Generic;
using System.Threading;
using Content.Server.Administration.Commands;
using Content.Server.Administration.Managers;
using Content.Server.Administration.UI;
using Content.Server.Chemistry.Components.SolutionManager;
using Content.Server.Chemistry.EntitySystems;
using Content.Server.Configurable;
using Content.Server.Disposal.Tube.Components;
using Content.Server.EUI;
@@ -12,14 +14,15 @@ using Content.Server.Inventory.Components;
using Content.Server.Mind.Commands;
using Content.Server.Mind.Components;
using Content.Server.Players;
using Content.Server.Verbs;
using Content.Shared.Administration;
using Content.Shared.Body.Components;
using Content.Shared.GameTicking;
using Content.Shared.Interaction.Helpers;
using Content.Shared.Popups;
using Content.Shared.Verbs;
using Robust.Server.Console;
using Robust.Server.GameObjects;
using Robust.Server.Player;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
@@ -39,9 +42,13 @@ namespace Content.Server.Administration
[Dependency] private readonly EuiManager _euiManager = default!;
[Dependency] private readonly GhostRoleSystem _ghostRoleSystem = default!;
private readonly Dictionary<IPlayerSession, EditSolutionsEui> _openSolutionUis = new();
public override void Initialize()
{
SubscribeLocalEvent<GetOtherVerbsEvent>(AddDebugVerbs);
SubscribeLocalEvent<RoundRestartCleanupEvent>(Reset);
SubscribeLocalEvent<SolutionContainerManagerComponent, SolutionChangedEvent>(OnSolutionChanged);
}
private void AddDebugVerbs(GetOtherVerbsEvent args)
@@ -186,24 +193,51 @@ namespace Content.Server.Administration
args.Verbs.Add(verb);
}
// Add reagent verb
if (_adminManager.HasAdminFlag(player, AdminFlags.Fun) &&
// Add verb to open Solution Editor
if (_groupController.CanCommand(player, "addreagent") &&
args.Target.HasComponent<SolutionContainerManagerComponent>())
{
Verb verb = new();
verb.Text = Loc.GetString("admin-add-reagent-verb-get-data-text");
verb.Text = Loc.GetString("edit-solutions-verb-get-data-text");
verb.Category = VerbCategory.Debug;
verb.IconTexture = "/Textures/Interface/VerbIcons/spill.svg.192dpi.png";
verb.Act = () => _euiManager.OpenEui(new AdminAddReagentEui(args.Target), player);
// TODO CHEMISTRY
// Add reagent ui broke after solution refactor. Needs fixing
verb.Disabled = true;
verb.Message = "Currently non functional after solution refactor.";
verb.Priority = -2;
verb.Act = () => OpenEditSolutionsEui(player, args.Target.Uid);
args.Verbs.Add(verb);
}
}
#region SolutionsEui
private void OnSolutionChanged(EntityUid uid, SolutionContainerManagerComponent component, SolutionChangedEvent args)
{
foreach (var eui in _openSolutionUis.Values)
{
if (eui.Target == uid)
eui.StateDirty();
}
}
public void OpenEditSolutionsEui(IPlayerSession session, EntityUid uid)
{
if (session.AttachedEntity == null)
return;
if (_openSolutionUis.ContainsKey(session))
_openSolutionUis[session].Close();
var eui = _openSolutionUis[session] = new EditSolutionsEui(uid);
_euiManager.OpenEui(eui, session);
eui.StateDirty();
}
public void OnEditSolutionsEuiClosed(IPlayerSession session)
{
_openSolutionUis.Remove(session, out var eui);
}
private void Reset(RoundRestartCleanupEvent ev)
{
_openSolutionUis.Clear();
}
#endregion
}
}

View File

@@ -0,0 +1,71 @@
using Content.Server.Chemistry.Components.SolutionManager;
using Content.Server.Chemistry.EntitySystems;
using Content.Shared.Administration;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.FixedPoint;
using Robust.Shared.Console;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Prototypes;
using System;
namespace Content.Server.Administration.Commands
{
/// <summary>
/// Command that allows you to edit an existing solution by adding (or removing) reagents.
/// </summary>
[AdminCommand(AdminFlags.Fun)]
public class AddReagent : IConsoleCommand
{
public string Command => "addreagent";
public string Description => "Add (or remove) some amount of reagent from some solution.";
public string Help => $"Usage: {Command} <target> <solution> <reagent> <quantity>";
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
if (args.Length < 4)
{
shell.WriteLine($"Not enough arguments.\n{Help}");
return;
}
if (!EntityUid.TryParse(args[0], out var uid))
{
shell.WriteLine($"Invalid entity id.");
return;
}
if (!IoCManager.Resolve<IEntityManager>().TryGetComponent(uid, out SolutionContainerManagerComponent man))
{
shell.WriteLine($"Entity does not have any solutions.");
return;
}
if (!man.Solutions.ContainsKey(args[1]))
{
var validSolutions = string.Join(", ", man.Solutions.Keys);
shell.WriteLine($"Entity does not have a \"{args[1]}\" solution. Valid solutions are:\n{validSolutions}");
return;
}
var solution = man.Solutions[args[1]];
if (!IoCManager.Resolve<IPrototypeManager>().HasIndex<ReagentPrototype>(args[2]))
{
shell.WriteLine($"Unknown reagent prototype");
return;
}
if (!float.TryParse(args[3], out var quantityFloat))
{
shell.WriteLine($"Failed to parse quantity");
return;
}
var quantity = FixedPoint2.New(MathF.Abs(quantityFloat));
if (quantityFloat > 0)
EntitySystem.Get<SolutionContainerSystem>().TryAddReagent(uid, solution, args[2], quantity, out var _);
else
EntitySystem.Get<SolutionContainerSystem>().TryRemoveReagent(uid, solution, args[2], quantity);
}
}
}

View File

@@ -1,95 +0,0 @@
using Content.Server.Administration.Managers;
using Content.Server.Chemistry.Components.SolutionManager;
using Content.Server.Chemistry.EntitySystems;
using Content.Server.EUI;
using Content.Shared.Administration;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.Eui;
using Content.Shared.FixedPoint;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
namespace Content.Server.Administration.UI
{
public sealed class AdminAddReagentEui : BaseEui
{
private readonly IEntity _target;
[Dependency] private readonly IAdminManager _adminManager = default!;
public AdminAddReagentEui(IEntity target)
{
_target = target;
IoCManager.InjectDependencies(this);
}
public override void Opened()
{
StateDirty();
}
public override EuiStateBase GetNewState()
{
if (EntitySystem.Get<SolutionContainerSystem>()
.TryGetSolution(_target.Uid, "default", out var container))
{
return new AdminAddReagentEuiState
{
CurVolume = container.CurrentVolume,
MaxVolume = container.MaxVolume
};
}
return new AdminAddReagentEuiState
{
CurVolume = FixedPoint2.Zero,
MaxVolume = FixedPoint2.Zero
};
}
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, AdminFlags.Fun) || _target.Deleted)
{
Close();
return;
}
var id = doAdd.ReagentId;
var amount = doAdd.Amount;
var solutionsSys = EntitySystem.Get<SolutionContainerSystem>();
if (_target.TryGetComponent(out InjectableSolutionComponent? injectable)
&& solutionsSys.TryGetSolution(_target.Uid, injectable.Name, out var targetSolution))
{
var solution = new Solution(id, amount);
solutionsSys.Inject(_target.Uid, targetSolution, solution);
}
else
{
//TODO decide how to find the solution
if (solutionsSys.TryGetSolution(_target.Uid, "default", out var solution))
{
solutionsSys.TryAddReagent(_target.Uid,solution, id, amount, out _);
}
}
StateDirty();
if (doAdd.CloseAfter)
Close();
break;
}
}
}
}

View File

@@ -0,0 +1,54 @@
using Content.Server.Chemistry.Components.SolutionManager;
using Content.Server.EUI;
using Content.Shared.Administration;
using Content.Shared.Eui;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
namespace Content.Server.Administration.UI
{
/// <summary>
/// Admin Eui for displaying and editing the reagents in a solution.
/// </summary>
[UsedImplicitly]
public sealed class EditSolutionsEui : BaseEui
{
[Dependency] private readonly IEntityManager _entityManager = default!;
public readonly EntityUid Target;
public EditSolutionsEui(EntityUid entity)
{
IoCManager.InjectDependencies(this);
Target = entity;
}
public override void Opened()
{
base.Opened();
StateDirty();
}
public override void Closed()
{
base.Closed();
EntitySystem.Get<AdminVerbSystem>().OnEditSolutionsEuiClosed(Player);
}
public override EuiStateBase GetNewState()
{
var solutions = _entityManager.GetComponentOrNull<SolutionContainerManagerComponent>(Target)?.Solutions;
return new EditSolutionsEuiState(Target, solutions);
}
public override void HandleMessage(EuiMessageBase msg)
{
switch (msg)
{
case EditSolutionsEuiMsg.Close:
Close();
break;
}
}
}
}

View File

@@ -55,7 +55,6 @@ namespace Content.Server.Body.Metabolism
IReadOnlyList<Solution.ReagentQuantity> reagentList = new List<Solution.ReagentQuantity>();
Solution? solution = null;
SharedBodyComponent? body = null;
var solutionsSys = Get<SolutionContainerSystem>();
// if this field is passed we should try and take from the bloodstream over anything else
if (owner.TryGetComponent<SharedMechanismComponent>(out var mech))
@@ -64,7 +63,7 @@ namespace Content.Server.Body.Metabolism
if (body != null)
{
if (body.Owner.HasComponent<BloodstreamComponent>()
&& solutionsSys.TryGetSolution(body.Owner.Uid, comp.SolutionName, out solution)
&& _solutionContainerSystem.TryGetSolution(body.OwnerUid, comp.SolutionName, out solution)
&& solution.CurrentVolume >= FixedPoint2.Zero)
{
reagentList = solution.Contents;
@@ -79,6 +78,7 @@ namespace Content.Server.Body.Metabolism
}
List<Solution.ReagentQuantity> removeReagents = new(5);
var ent = body?.Owner ?? owner;
// Run metabolism for each reagent, remove metabolized reagents
foreach (var reagent in reagentList)
@@ -90,7 +90,6 @@ namespace Content.Server.Body.Metabolism
// Run metabolism code for each reagent
foreach (var effect in metabolism.Effects)
{
var ent = body != null ? body.Owner : owner;
var conditionsMet = true;
if (effect.Conditions != null)
{
@@ -117,7 +116,7 @@ namespace Content.Server.Body.Metabolism
removeReagents.Add(new Solution.ReagentQuantity(reagent.ReagentId, metabolism.MetabolismRate));
}
solutionsSys.TryRemoveAllReagents(solution, removeReagents);
_solutionContainerSystem.TryRemoveAllReagents(ent.Uid, solution, removeReagents);
}
}
}

View File

@@ -562,7 +562,7 @@ namespace Content.Server.Botany.Components
else
{
var one = FixedPoint2.New(1);
foreach (var reagent in solutionSystem.RemoveEachReagent(solution, one))
foreach (var reagent in solutionSystem.RemoveEachReagent(Owner.Uid, solution, one))
{
var reagentProto = _prototypeManager.Index<ReagentPrototype>(reagent);
reagentProto.ReactionPlant(Owner);

View File

@@ -249,7 +249,7 @@ namespace Content.Server.Chemistry.EntitySystems
return solutionsMgr.Solutions[name];
}
public string[] RemoveEachReagent(Solution solution, FixedPoint2 quantity)
public string[] RemoveEachReagent(EntityUid uid, Solution solution, FixedPoint2 quantity)
{
var removedReagent = new string[solution.Contents.Count];
if (quantity <= 0)
@@ -274,15 +274,21 @@ namespace Content.Server.Chemistry.EntitySystems
}
}
UpdateChemicals(uid, solution);
return removedReagent;
}
public void TryRemoveAllReagents(Solution solution, List<Solution.ReagentQuantity> removeReagents)
public void TryRemoveAllReagents(EntityUid uid, Solution solution, List<Solution.ReagentQuantity> removeReagents)
{
if (removeReagents.Count == 0)
return;
foreach (var reagent in removeReagents)
{
solution.RemoveReagent(reagent.ReagentId, reagent.Quantity);
}
UpdateChemicals(uid, solution);
}
public FixedPoint2 GetReagentQuantity(EntityUid ownerUid, string reagentId)

View File

@@ -1,33 +0,0 @@
using System;
using Content.Shared.Chemistry;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.Eui;
using Content.Shared.FixedPoint;
using Robust.Shared.Serialization;
namespace Content.Shared.Administration
{
[Serializable, NetSerializable]
public sealed class AdminAddReagentEuiState : EuiStateBase
{
public FixedPoint2 MaxVolume;
public FixedPoint2 CurVolume;
}
public static class AdminAddReagentEuiMsg
{
[Serializable, NetSerializable]
public sealed class Close : EuiMessageBase
{
}
[Serializable, NetSerializable]
public sealed class DoAdd : EuiMessageBase
{
public bool CloseAfter;
public FixedPoint2 Amount;
public string ReagentId = string.Empty;
}
}
}

View File

@@ -0,0 +1,28 @@
using Content.Shared.Eui;
using Robust.Shared.Serialization;
using System;
using Robust.Shared.GameObjects;
using System.Collections.Generic;
using Content.Shared.Chemistry.Components;
namespace Content.Shared.Administration
{
[Serializable, NetSerializable]
public class EditSolutionsEuiState : EuiStateBase
{
public readonly EntityUid Target;
public readonly Dictionary<string, Solution>? Solutions;
public EditSolutionsEuiState(EntityUid target, Dictionary<string, Solution>? solutions)
{
Target = target;
Solutions = solutions;
}
}
public static class EditSolutionsEuiMsg
{
[Serializable, NetSerializable]
public sealed class Close : EuiMessageBase { }
}
}

View File

@@ -0,0 +1,3 @@
delete-verb-get-data-text = Delete
edit-solutions-verb-get-data-text = Edit Solutions
explode-verb-get-data-text = Explode

View File

@@ -1,13 +0,0 @@
admin-add-reagent-eui-title = Add reagent...
admin-add-reagent-eui-current-volume-label = Cur volume:
admin-add-reagent-eui-reagent-label = Reagent:
admin-add-reagent-eui-reagent-id-edit = Reagent ID...
admin-add-reagent-eui-amount-label = Amount:
admin-add-reagent-eui-amount-edit = A number...
admin-add-reagent-eui-add-close-button = Add & Close
admin-add-reagent-eui-add-button = Add
admin-add-reagent-eui-no-reagent-id-error = Must specify reagent ID
admin-add-reagent-eui-reagent-does-not-exist-error = '{$reagent}' does not exist.
admin-add-reagent-eui-no-reagent-amount-specified-error = Must specify reagent amount
admin-add-reagent-eui-invalid-amount-error = Invalid amount
admin-add-reagent-eui-current-and-max-volume-label = {$currentVolume}/{$maxVolume}u

View File

@@ -0,0 +1,5 @@
admin-add-reagent-window-title = Add to {$solution}
admin-add-reagent-window-amount-label = Quantity:
admin-add-reagent-window-search-placeholder = Filter...
admin-add-reagent-window-add = Add {$quantity}u {$reagent}
admin-add-reagent-window-add-invalid-reagent = Select a Reagent

View File

@@ -0,0 +1,4 @@
admin-solutions-window-title = Solution Editor - {$targetName}
admin-solutions-window-solution-label = Target solution:
admin-solutions-window-add-new-button = Add new reagent
admin-solutions-window-capacity-label = Capacity {$currentVolume}/{$maxVolume}u

View File

@@ -1 +0,0 @@
admin-add-reagent-verb-get-data-text = Add Reagent...

View File

@@ -1 +0,0 @@
delete-verb-get-data-text = Delete

View File

@@ -1 +0,0 @@
explode-verb-get-data-text = Explode