Files
tbd-station-14/Content.Client/GameObjects/Components/Chemistry/ReagentDispenserBoundUserInterface.cs
moneyl 963bb28f0f Reagent dispensers (#360)
* Expose more private values of Solution and SolutionComponent

Expose SolutionComponent.ContainedSolution and Solution.Contents. Both needed by ReagentDispenserComponent.

* Implement IExamine for SolutionComponent

Allows players to see the contents of a solution by examining the entity which contains it.

* Implement ReagentDispenserComponent

Adds ReagentDispenserComponent. A component which can add or remove reagents from a solution container. It's written in a general way so that it can be used for things such as the Chemical dispensers in chemistry, but also the booze and soda dispensers in the bar. 

The chemicals it may dispense are defined in yaml, similar to the way that vending machines define which entities they can dispense, by defining a reagent pack.

* Add chemical dispenser and equipment

Adds the chemical dispenser, beaker, large beaker, dropper, and a few more chemicals.

* Add booze and soda dispensers.

Adds the booze and soda dispensers, and a few chemicals for them to dispense. There's no drink mixing or drunkenness yet.

* Update engine submodule.

* Remove unneeded and commented out code

Had a few WIP notes and debug code bits I forgot to remove beforehand.

* Make SolutionComponent._containedSolution and it's values private again

- Remove `SolutionComponent.ContainedSolution` property, replace with specific access functions to maintain safety.
- Make Solution.Contents return a `ReadOnlyCollection` instead of `_contents` to prevent uncontrolled access to the Solution values.
- Add `SolutionComponent.RemoveAllSolution()`

* Update Content.Shared/Chemistry/Solution.cs

Commits a suggestion from RemieRichards to match the coding style of the rest of the codebase. Using `IReadOnlyList` instead of `IReadOnlyCollection`.

Co-Authored-By: Remie Richards <remierichards@gmail.com>

* Update Content.Shared/GameObjects/Components/Chemistry/SolutionComponent.cs

Commits a suggestion from RemieRichards to match the coding style of the rest of the codebase. Using `IReadOnlyList` instead of `IReadOnlyCollection`.

Co-Authored-By: Remie Richards <remierichards@gmail.com>

* Add import for IReadOnlyList to Shared/SolutionComponent.cs

* Add documentation

* Improve localization

Improve use of ILocalizationManager.

* Resolve ReagentDispenserWindow._localizationManager before using it

Forgot to do this in the last commit, resulting in a crash. Oops.

* Add SolutionCaps.FitsInDispenser. Use in ReagentDispenserComponent.

Used to limit large containers like buckets or mop buckets from being placed in a dispenser. Both have large capacities (500) and weren't designed to hold certain chemicals like a beaker is, so for now they can be blocked from being put in a dispenser by giving them that flag.

* Add colors to new reagents

* Update engine submodule
2019-10-05 15:10:05 +02:00

122 lines
4.8 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using Robust.Client.GameObjects.Components.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.GameObjects.Components.UserInterface;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using static Content.Shared.GameObjects.Components.Chemistry.SharedReagentDispenserComponent;
namespace Content.Client.GameObjects.Components.Chemistry
{
/// <summary>
/// Initializes a <see cref="ReagentDispenserWindow"/> and updates it when new server messages are received.
/// </summary>
public class ReagentDispenserBoundUserInterface : BoundUserInterface
{
#pragma warning disable 649
[Dependency] private readonly ILocalizationManager _localizationManager;
#pragma warning restore 649
private ReagentDispenserWindow _window;
private ReagentDispenserBoundUserInterfaceState _lastState;
public ReagentDispenserBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey)
{
}
/// <summary>
/// Called each time a dispenser UI instance is opened. Generates the dispenser window and fills it with
/// relevant info. Sets the actions for static buttons.
/// <para>Buttons which can change like reagent dispense buttons have their actions set in <see cref="UpdateReagentsList"/>.</para>
/// </summary>
protected override void Open()
{
base.Open();
//Setup window layout/elements
_window = new ReagentDispenserWindow
{
Title = _localizationManager.GetString("Reagent dispenser"),
Size = (500, 600)
};
_window.OpenCenteredMinSize();
_window.OnClose += Close;
//Setup static button actions.
_window.EjectButton.OnPressed += _ => ButtonPressed(UiButton.Eject);
_window.ClearButton.OnPressed += _ => ButtonPressed(UiButton.Clear);
_window.DispenseButton1.OnPressed += _ => ButtonPressed(UiButton.SetDispenseAmount1);
_window.DispenseButton5.OnPressed += _ => ButtonPressed(UiButton.SetDispenseAmount5);
_window.DispenseButton10.OnPressed += _ => ButtonPressed(UiButton.SetDispenseAmount10);
_window.DispenseButton25.OnPressed += _ => ButtonPressed(UiButton.SetDispenseAmount25);
_window.DispenseButton50.OnPressed += _ => ButtonPressed(UiButton.SetDispenseAmount50);
_window.DispenseButton100.OnPressed += _ => ButtonPressed(UiButton.SetDispenseAmount100);
}
/// <summary>
/// Update the ui each time new state data is sent from the server.
/// </summary>
/// <param name="state">Data of the <see cref="ReagentDispenserComponent"/> that this ui represents. Sent from the server.</param>
protected override void UpdateState(BoundUserInterfaceState state)
{
base.UpdateState(state);
var castState = (ReagentDispenserBoundUserInterfaceState)state;
_lastState = castState;
_window?.UpdateState(castState); //Update window state
UpdateReagentsList(castState.Inventory); //Update reagents list & reagent button actions
_window.ForceRunLayoutUpdate();
}
/// <summary>
/// Update the list of reagents that this dispenser can dispense on the UI.
/// </summary>
/// <param name="inventory">A list of the reagents which can be dispensed.</param>
private void UpdateReagentsList(List<ReagentDispenserInventoryEntry> inventory)
{
_window.UpdateReagentsList(inventory);
for (int i = 0; i < _window.ChemicalList.Children.Count(); i++)
{
var button = (Button)_window.ChemicalList.Children.ElementAt(i);
var i1 = i;
button.OnPressed += _ => ButtonPressed(UiButton.Dispense, i1);
button.OnMouseEntered += _ =>
{
if (_lastState != null)
{
_window.UpdateContainerInfo(_lastState, inventory[i1].ID);
}
};
button.OnMouseExited += _ =>
{
if (_lastState != null)
{
_window.UpdateContainerInfo(_lastState);
}
};
}
}
public void ButtonPressed(UiButton button, int dispenseIndex = -1)
{
SendMessage(new UiButtonPressedMessage(button, dispenseIndex));
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
_window.Dispose();
}
}
}
}