SolutionContainer refactors (#2954)
* removes unused method * Code uncluttering (Also removed the netcode, color code, and visuals, need to rewrite) * SolutionContainerVisualState * Removes caching of SolutionContainer Color * ChemicalsAdded() and ChemicalsRemoved() for updating appearance and handling reaction checks * SolutionContainerComponentState * Netcode * ChemMasterComponent no longer creates a SolutionContainerComponent with new(), uses a Solution instead * Enable nullable in SolutionContainer implementations * Some review fixes * uses IReadOnlyLists in ChemMaster * Comments * review fixes 3 * ReagentUnit documentation * Review fixes * spelling fix * spelling 2 * typo Co-authored-by: py01 <pyronetics01@gmail.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Client.UserInterface.Stylesheets;
|
using Content.Client.UserInterface.Stylesheets;
|
||||||
using Content.Shared.Chemistry;
|
using Content.Shared.Chemistry;
|
||||||
@@ -378,7 +378,7 @@ namespace Content.Client.GameObjects.Components.Chemistry.ChemMaster
|
|||||||
bufferHBox.AddChild(bufferLabel);
|
bufferHBox.AddChild(bufferLabel);
|
||||||
var bufferVol = new Label
|
var bufferVol = new Label
|
||||||
{
|
{
|
||||||
Text = $"{state.BufferCurrentVolume}/{state.BufferMaxVolume}",
|
Text = $"{state.BufferCurrentVolume}",
|
||||||
StyleClasses = {StyleNano.StyleClassLabelSecondaryColor}
|
StyleClasses = {StyleNano.StyleClassLabelSecondaryColor}
|
||||||
};
|
};
|
||||||
bufferHBox.AddChild(bufferVol);
|
bufferHBox.AddChild(bufferVol);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using Content.Shared.Chemistry;
|
#nullable enable
|
||||||
using Content.Shared.GameObjects.Components.Chemistry;
|
using Content.Shared.GameObjects.Components.Chemistry;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
|
|
||||||
@@ -8,22 +8,6 @@ namespace Content.Client.GameObjects.Components.Chemistry
|
|||||||
[ComponentReference(typeof(SharedSolutionContainerComponent))]
|
[ComponentReference(typeof(SharedSolutionContainerComponent))]
|
||||||
public class SolutionContainerComponent : SharedSolutionContainerComponent
|
public class SolutionContainerComponent : SharedSolutionContainerComponent
|
||||||
{
|
{
|
||||||
public override bool CanAddSolution(Solution solution)
|
|
||||||
{
|
|
||||||
// TODO CLIENT
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool TryAddSolution(Solution solution, bool skipReactionCheck = false, bool skipColor = false)
|
|
||||||
{
|
|
||||||
// TODO CLIENT
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool TryRemoveReagent(string reagentId, ReagentUnit quantity)
|
|
||||||
{
|
|
||||||
// TODO CLIENT
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.GameObjects.Components.Chemistry;
|
using Content.Server.GameObjects.Components.Chemistry;
|
||||||
@@ -147,7 +147,7 @@ namespace Content.Server.GameObjects.Components.Body.Behavior
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add solution to _stomachContents
|
// Add solution to _stomachContents
|
||||||
solutionComponent.TryAddSolution(solution, false, true);
|
solutionComponent.TryAddSolution(solution);
|
||||||
// Add each reagent to _reagentDeltas. Used to track how long each reagent has been in the stomach
|
// Add each reagent to _reagentDeltas. Used to track how long each reagent has been in the stomach
|
||||||
foreach (var reagent in solution.Contents)
|
foreach (var reagent in solution.Contents)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ namespace Content.Server.GameObjects.Components.Body.Circulatory
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_internalSolution.TryAddSolution(solution, false, true);
|
_internalSolution.TryAddSolution(solution);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
|||||||
|
|
||||||
[ViewVariables] private bool Powered => !Owner.TryGetComponent(out PowerReceiverComponent? receiver) || receiver.Powered;
|
[ViewVariables] private bool Powered => !Owner.TryGetComponent(out PowerReceiverComponent? receiver) || receiver.Powered;
|
||||||
|
|
||||||
[ViewVariables] private readonly SolutionContainerComponent BufferSolution = new();
|
[ViewVariables] private readonly Solution BufferSolution = new();
|
||||||
|
|
||||||
[ViewVariables] private BoundUserInterface? UserInterface => Owner.GetUIOrNull(ChemMasterUiKey.Key);
|
[ViewVariables] private BoundUserInterface? UserInterface => Owner.GetUIOrNull(ChemMasterUiKey.Key);
|
||||||
|
|
||||||
@@ -81,8 +81,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
|||||||
ContainerManagerComponent.Ensure<ContainerSlot>($"{Name}-reagentContainerContainer", Owner);
|
ContainerManagerComponent.Ensure<ContainerSlot>($"{Name}-reagentContainerContainer", Owner);
|
||||||
|
|
||||||
//BufferSolution = Owner.BufferSolution
|
//BufferSolution = Owner.BufferSolution
|
||||||
BufferSolution.Solution = new Solution();
|
BufferSolution.RemoveAllSolution();
|
||||||
BufferSolution.MaxVolume = ReagentUnit.New(1000);
|
|
||||||
|
|
||||||
UpdateUserInterface();
|
UpdateUserInterface();
|
||||||
}
|
}
|
||||||
@@ -182,12 +181,12 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
|||||||
if (beaker == null)
|
if (beaker == null)
|
||||||
{
|
{
|
||||||
return new ChemMasterBoundUserInterfaceState(Powered, false, ReagentUnit.New(0), ReagentUnit.New(0),
|
return new ChemMasterBoundUserInterfaceState(Powered, false, ReagentUnit.New(0), ReagentUnit.New(0),
|
||||||
"", Owner.Name, new List<Solution.ReagentQuantity>(), BufferSolution.ReagentList.ToList(), _bufferModeTransfer, BufferSolution.CurrentVolume, BufferSolution.MaxVolume);
|
"", Owner.Name, new List<Solution.ReagentQuantity>(), BufferSolution.Contents, _bufferModeTransfer, BufferSolution.TotalVolume);
|
||||||
}
|
}
|
||||||
|
|
||||||
var solution = beaker.GetComponent<SolutionContainerComponent>();
|
var solution = beaker.GetComponent<SolutionContainerComponent>();
|
||||||
return new ChemMasterBoundUserInterfaceState(Powered, 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, BufferSolution.Contents, _bufferModeTransfer, BufferSolution.TotalVolume);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateUserInterface()
|
private void UpdateUserInterface()
|
||||||
@@ -222,12 +221,12 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
|||||||
var beakerSolution = beaker.GetComponent<SolutionContainerComponent>();
|
var beakerSolution = beaker.GetComponent<SolutionContainerComponent>();
|
||||||
if (isBuffer)
|
if (isBuffer)
|
||||||
{
|
{
|
||||||
foreach (var reagent in BufferSolution.Solution.Contents)
|
foreach (var reagent in BufferSolution.Contents)
|
||||||
{
|
{
|
||||||
if (reagent.ReagentId == id)
|
if (reagent.ReagentId == id)
|
||||||
{
|
{
|
||||||
ReagentUnit actualAmount;
|
ReagentUnit actualAmount;
|
||||||
if (amount == ReagentUnit.New(-1))
|
if (amount == ReagentUnit.New(-1)) //amount is ReagentUnit.New(-1) when the client sends a message requesting to remove all solution from the container
|
||||||
{
|
{
|
||||||
actualAmount = ReagentUnit.Min(reagent.Quantity, beakerSolution.EmptyVolume);
|
actualAmount = ReagentUnit.Min(reagent.Quantity, beakerSolution.EmptyVolume);
|
||||||
}
|
}
|
||||||
@@ -237,7 +236,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BufferSolution.Solution.RemoveReagent(id, actualAmount);
|
BufferSolution.RemoveReagent(id, actualAmount);
|
||||||
if (_bufferModeTransfer)
|
if (_bufferModeTransfer)
|
||||||
{
|
{
|
||||||
beakerSolution.TryAddReagent(id, actualAmount, out var _);
|
beakerSolution.TryAddReagent(id, actualAmount, out var _);
|
||||||
@@ -257,14 +256,14 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
|||||||
ReagentUnit actualAmount;
|
ReagentUnit actualAmount;
|
||||||
if (amount == ReagentUnit.New(-1))
|
if (amount == ReagentUnit.New(-1))
|
||||||
{
|
{
|
||||||
actualAmount = ReagentUnit.Min(reagent.Quantity, BufferSolution.EmptyVolume);
|
actualAmount = reagent.Quantity;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
actualAmount = ReagentUnit.Min(reagent.Quantity, amount, BufferSolution.EmptyVolume);
|
actualAmount = ReagentUnit.Min(reagent.Quantity, amount);
|
||||||
}
|
}
|
||||||
beakerSolution.TryRemoveReagent(id, actualAmount);
|
beakerSolution.TryRemoveReagent(id, actualAmount);
|
||||||
BufferSolution.Solution.AddReagent(id, actualAmount);
|
BufferSolution.AddReagent(id, actualAmount);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -275,12 +274,12 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
|||||||
|
|
||||||
private void TryCreatePackage(IEntity user, UiAction action, int pillAmount, int bottleAmount)
|
private void TryCreatePackage(IEntity user, UiAction action, int pillAmount, int bottleAmount)
|
||||||
{
|
{
|
||||||
if (BufferSolution.CurrentVolume == 0)
|
if (BufferSolution.TotalVolume == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (action == UiAction.CreateBottles)
|
if (action == UiAction.CreateBottles)
|
||||||
{
|
{
|
||||||
var individualVolume = BufferSolution.CurrentVolume / ReagentUnit.New(bottleAmount);
|
var individualVolume = BufferSolution.TotalVolume / ReagentUnit.New(bottleAmount);
|
||||||
if (individualVolume < ReagentUnit.New(1))
|
if (individualVolume < ReagentUnit.New(1))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -289,7 +288,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
|||||||
{
|
{
|
||||||
var bottle = Owner.EntityManager.SpawnEntity("bottle", Owner.Transform.Coordinates);
|
var bottle = Owner.EntityManager.SpawnEntity("bottle", Owner.Transform.Coordinates);
|
||||||
|
|
||||||
var bufferSolution = BufferSolution.Solution.SplitSolution(actualVolume);
|
var bufferSolution = BufferSolution.SplitSolution(actualVolume);
|
||||||
|
|
||||||
bottle.TryGetComponent<SolutionContainerComponent>(out var bottleSolution);
|
bottle.TryGetComponent<SolutionContainerComponent>(out var bottleSolution);
|
||||||
bottleSolution?.TryAddSolution(bufferSolution);
|
bottleSolution?.TryAddSolution(bufferSolution);
|
||||||
@@ -314,7 +313,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
|||||||
}
|
}
|
||||||
else //Pills
|
else //Pills
|
||||||
{
|
{
|
||||||
var individualVolume = BufferSolution.CurrentVolume / ReagentUnit.New(pillAmount);
|
var individualVolume = BufferSolution.TotalVolume / ReagentUnit.New(pillAmount);
|
||||||
if (individualVolume < ReagentUnit.New(1))
|
if (individualVolume < ReagentUnit.New(1))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -323,7 +322,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
|||||||
{
|
{
|
||||||
var pill = Owner.EntityManager.SpawnEntity("pill", Owner.Transform.Coordinates);
|
var pill = Owner.EntityManager.SpawnEntity("pill", Owner.Transform.Coordinates);
|
||||||
|
|
||||||
var bufferSolution = BufferSolution.Solution.SplitSolution(actualVolume);
|
var bufferSolution = BufferSolution.SplitSolution(actualVolume);
|
||||||
|
|
||||||
pill.TryGetComponent<SolutionContainerComponent>(out var pillSolution);
|
pill.TryGetComponent<SolutionContainerComponent>(out var pillSolution);
|
||||||
pillSolution?.TryAddSolution(bufferSolution);
|
pillSolution?.TryAddSolution(bufferSolution);
|
||||||
|
|||||||
@@ -1,144 +1,19 @@
|
|||||||
using System.Collections.Generic;
|
#nullable enable
|
||||||
using System.Linq;
|
|
||||||
using Content.Server.Chemistry;
|
|
||||||
using Content.Server.GameObjects.Components.GUI;
|
using Content.Server.GameObjects.Components.GUI;
|
||||||
using Content.Server.GameObjects.EntitySystems;
|
|
||||||
using Content.Shared.Chemistry;
|
using Content.Shared.Chemistry;
|
||||||
using Content.Shared.GameObjects.Components.Chemistry;
|
using Content.Shared.GameObjects.Components.Chemistry;
|
||||||
using Content.Shared.GameObjects.EntitySystems;
|
|
||||||
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
|
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
|
||||||
using Content.Shared.GameObjects.Verbs;
|
using Content.Shared.GameObjects.Verbs;
|
||||||
using Content.Shared.Utility;
|
|
||||||
using Robust.Server.GameObjects;
|
|
||||||
using Robust.Server.GameObjects.EntitySystems;
|
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.GameObjects.Systems;
|
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
using Robust.Shared.IoC;
|
|
||||||
using Robust.Shared.Localization;
|
using Robust.Shared.Localization;
|
||||||
using Robust.Shared.Log;
|
|
||||||
using Robust.Shared.Maths;
|
|
||||||
using Robust.Shared.Prototypes;
|
|
||||||
using Robust.Shared.Serialization;
|
|
||||||
using Robust.Shared.Utility;
|
|
||||||
using Robust.Shared.ViewVariables;
|
|
||||||
|
|
||||||
namespace Content.Server.GameObjects.Components.Chemistry
|
namespace Content.Server.GameObjects.Components.Chemistry
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// ECS component that manages a liquid solution of reagents.
|
|
||||||
/// </summary>
|
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
[ComponentReference(typeof(SharedSolutionContainerComponent))]
|
[ComponentReference(typeof(SharedSolutionContainerComponent))]
|
||||||
public class SolutionContainerComponent : SharedSolutionContainerComponent, IExamine
|
public class SolutionContainerComponent : SharedSolutionContainerComponent
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
|
||||||
[Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;
|
|
||||||
|
|
||||||
private IEnumerable<ReactionPrototype> _reactions;
|
|
||||||
private ChemicalReactionSystem _reactionSystem;
|
|
||||||
private string _fillInitState;
|
|
||||||
private int _fillInitSteps;
|
|
||||||
private string _fillPathString = "Objects/Specific/Chemistry/fillings.rsi";
|
|
||||||
private ResourcePath _fillPath;
|
|
||||||
private SpriteSpecifier _fillSprite;
|
|
||||||
private AudioSystem _audioSystem;
|
|
||||||
private ChemistrySystem _chemistrySystem;
|
|
||||||
private SpriteComponent _spriteComponent;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The volume without reagents remaining in the container.
|
|
||||||
/// </summary>
|
|
||||||
[ViewVariables]
|
|
||||||
public ReagentUnit EmptyVolume => MaxVolume - CurrentVolume;
|
|
||||||
public IReadOnlyList<Solution.ReagentQuantity> ReagentList => Solution.Contents;
|
|
||||||
public bool CanExamineContents => Capabilities.HasCap(SolutionContainerCaps.CanExamine);
|
|
||||||
public bool CanUseWithChemDispenser => Capabilities.HasCap(SolutionContainerCaps.FitsInDispenser);
|
|
||||||
public bool CanAddSolutions => Capabilities.HasCap(SolutionContainerCaps.AddTo);
|
|
||||||
public bool CanRemoveSolutions => Capabilities.HasCap(SolutionContainerCaps.RemoveFrom);
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override void ExposeData(ObjectSerializer serializer)
|
|
||||||
{
|
|
||||||
base.ExposeData(serializer);
|
|
||||||
|
|
||||||
serializer.DataField(this, x => x.MaxVolume, "maxVol", ReagentUnit.New(0));
|
|
||||||
serializer.DataField(this, x => x.Solution, "contents", new Solution());
|
|
||||||
serializer.DataField(this, x => x.Capabilities, "caps", SolutionContainerCaps.AddTo | SolutionContainerCaps.RemoveFrom | SolutionContainerCaps.CanExamine);
|
|
||||||
serializer.DataField(ref _fillInitState, "fillingState", string.Empty);
|
|
||||||
serializer.DataField(ref _fillInitSteps, "fillingSteps", 7);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Initialize()
|
|
||||||
{
|
|
||||||
base.Initialize();
|
|
||||||
_audioSystem = EntitySystem.Get<AudioSystem>();
|
|
||||||
_chemistrySystem = _entitySystemManager.GetEntitySystem<ChemistrySystem>();
|
|
||||||
_reactions = _prototypeManager.EnumeratePrototypes<ReactionPrototype>();
|
|
||||||
_reactionSystem = _entitySystemManager.GetEntitySystem<ChemicalReactionSystem>();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Startup()
|
|
||||||
{
|
|
||||||
base.Startup();
|
|
||||||
RecalculateColor();
|
|
||||||
if (!string.IsNullOrEmpty(_fillInitState))
|
|
||||||
{
|
|
||||||
_spriteComponent = Owner.GetComponent<SpriteComponent>();
|
|
||||||
_fillPath = new ResourcePath(_fillPathString);
|
|
||||||
_fillSprite = new SpriteSpecifier.Rsi(_fillPath, _fillInitState + (_fillInitSteps - 1));
|
|
||||||
_spriteComponent.AddLayerWithSprite(_fillSprite);
|
|
||||||
UpdateFillIcon();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RemoveAllSolution()
|
|
||||||
{
|
|
||||||
Solution.RemoveAllSolution();
|
|
||||||
OnSolutionChanged(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool TryRemoveReagent(string reagentId, ReagentUnit quantity)
|
|
||||||
{
|
|
||||||
if (!Solution.ContainsReagent(reagentId, out var currentQuantity))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Solution.RemoveReagent(reagentId, quantity);
|
|
||||||
OnSolutionChanged(false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Attempt to remove the specified quantity from this solution
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="quantity">Quantity of this solution to remove</param>
|
|
||||||
/// <returns>Whether or not the solution was successfully removed</returns>
|
|
||||||
public bool TryRemoveSolution(ReagentUnit quantity)
|
|
||||||
{
|
|
||||||
if (CurrentVolume == 0)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Solution.RemoveSolution(quantity);
|
|
||||||
OnSolutionChanged(false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Solution SplitSolution(ReagentUnit quantity)
|
|
||||||
{
|
|
||||||
var solutionSplit = Solution.SplitSolution(quantity);
|
|
||||||
OnSolutionChanged(false);
|
|
||||||
return solutionSplit;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void RecalculateColor()
|
|
||||||
{
|
|
||||||
SubstanceColor = Solution.Color;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Transfers solution from the held container to the target container.
|
/// Transfers solution from the held container to the target container.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -195,43 +70,6 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IExamine.Examine(FormattedMessage message, bool inDetailsRange)
|
|
||||||
{
|
|
||||||
if (!CanExamineContents)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ReagentList.Count == 0)
|
|
||||||
{
|
|
||||||
message.AddText(Loc.GetString("It's empty."));
|
|
||||||
}
|
|
||||||
else if (ReagentList.Count == 1)
|
|
||||||
{
|
|
||||||
var reagent = ReagentList[0];
|
|
||||||
|
|
||||||
if (_prototypeManager.TryIndex(reagent.ReagentId, out ReagentPrototype proto))
|
|
||||||
{
|
|
||||||
message.AddMarkup(
|
|
||||||
Loc.GetString("It contains a [color={0}]{1}[/color] substance.",
|
|
||||||
proto.GetSubstanceTextColor().ToHexNoAlpha(),
|
|
||||||
Loc.GetString(proto.PhysicalDescription)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var reagent = ReagentList.Max();
|
|
||||||
|
|
||||||
if (_prototypeManager.TryIndex(reagent.ReagentId, out ReagentPrototype proto))
|
|
||||||
{
|
|
||||||
message.AddMarkup(
|
|
||||||
Loc.GetString("It contains a [color={0}]{1}[/color] mixture of substances.",
|
|
||||||
SubstanceColor.ToHexNoAlpha(),
|
|
||||||
Loc.GetString(proto.PhysicalDescription)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Transfers solution from a target container to the held container.
|
/// Transfers solution from a target container to the held container.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -288,86 +126,5 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
|||||||
handSolutionComp.TryAddSolution(transferSolution);
|
handSolutionComp.TryAddSolution(transferSolution);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CheckForReaction()
|
|
||||||
{
|
|
||||||
_reactionSystem.FullyReactSolution(Solution, Owner, MaxVolume);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool TryAddReagent(string reagentId, ReagentUnit quantity, out ReagentUnit acceptedQuantity, bool skipReactionCheck = false, bool skipColor = false)
|
|
||||||
{
|
|
||||||
var toAcceptQuantity = MaxVolume - Solution.TotalVolume;
|
|
||||||
if (quantity > toAcceptQuantity)
|
|
||||||
{
|
|
||||||
acceptedQuantity = toAcceptQuantity;
|
|
||||||
if (acceptedQuantity == 0) return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
acceptedQuantity = quantity;
|
|
||||||
}
|
|
||||||
|
|
||||||
Solution.AddReagent(reagentId, acceptedQuantity);
|
|
||||||
if (!skipColor) {
|
|
||||||
RecalculateColor();
|
|
||||||
}
|
|
||||||
if(!skipReactionCheck)
|
|
||||||
CheckForReaction();
|
|
||||||
OnSolutionChanged(skipColor);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool CanAddSolution(Solution solution)
|
|
||||||
{
|
|
||||||
return solution.TotalVolume <= (MaxVolume - Solution.TotalVolume);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool TryAddSolution(Solution solution, bool skipReactionCheck = false, bool skipColor = false)
|
|
||||||
{
|
|
||||||
if (!CanAddSolution(solution))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Solution.AddSolution(solution);
|
|
||||||
if (!skipColor) {
|
|
||||||
RecalculateColor();
|
|
||||||
}
|
|
||||||
if(!skipReactionCheck)
|
|
||||||
CheckForReaction();
|
|
||||||
OnSolutionChanged(skipColor);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void UpdateFillIcon()
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(_fillInitState))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var percentage = (CurrentVolume / MaxVolume).Double();
|
|
||||||
var level = ContentHelpers.RoundToLevels(percentage * 100, 100, _fillInitSteps);
|
|
||||||
|
|
||||||
//Transformed glass uses special fancy sprites so we don't bother
|
|
||||||
if (level == 0 || (Owner.TryGetComponent<TransformableContainerComponent>(out var transformComp) && transformComp.Transformed))
|
|
||||||
{
|
|
||||||
_spriteComponent.LayerSetColor(1, Color.Transparent);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_fillSprite = new SpriteSpecifier.Rsi(_fillPath, _fillInitState + level);
|
|
||||||
_spriteComponent.LayerSetSprite(1, _fillSprite);
|
|
||||||
_spriteComponent.LayerSetColor(1, SubstanceColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void OnSolutionChanged(bool skipColor)
|
|
||||||
{
|
|
||||||
if (!skipColor)
|
|
||||||
{
|
|
||||||
RecalculateColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateFillIcon();
|
|
||||||
_chemistrySystem.HandleSolutionChange(Owner);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -286,7 +286,7 @@ namespace Content.Server.GameObjects.Components.Fluids
|
|||||||
Color newColor;
|
Color newColor;
|
||||||
if (_recolor)
|
if (_recolor)
|
||||||
{
|
{
|
||||||
newColor = _contents.SubstanceColor.WithAlpha(cappedScale);
|
newColor = _contents.Color.WithAlpha(cappedScale);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ namespace Content.Server.GameObjects.Components.Fluids
|
|||||||
if (vapor.TryGetComponent(out AppearanceComponent appearance)) // Vapor sprite should face down.
|
if (vapor.TryGetComponent(out AppearanceComponent appearance)) // Vapor sprite should face down.
|
||||||
{
|
{
|
||||||
appearance.SetData(VaporVisuals.Rotation, -Angle.South + rotation);
|
appearance.SetData(VaporVisuals.Rotation, -Angle.South + rotation);
|
||||||
appearance.SetData(VaporVisuals.Color, contents.SubstanceColor.WithAlpha(1f));
|
appearance.SetData(VaporVisuals.Color, contents.Color.WithAlpha(1f));
|
||||||
appearance.SetData(VaporVisuals.State, true);
|
appearance.SetData(VaporVisuals.State, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Content.Server.Atmos;
|
using Content.Server.Atmos;
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Robust.Shared.Interfaces.Serialization;
|
using Robust.Shared.Interfaces.Serialization;
|
||||||
|
|
||||||
namespace Content.Shared.Chemistry
|
namespace Content.Shared.Chemistry
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a quantity of reagent, to a precision of 0.01.
|
||||||
|
/// To enforce this level of precision, floats are shifted by 2 decimal points, rounded, and converted to an int.
|
||||||
|
/// </summary>
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public struct ReagentUnit : ISelfSerialize, IComparable<ReagentUnit>, IEquatable<ReagentUnit>
|
public struct ReagentUnit : ISelfSerialize, IComparable<ReagentUnit>, IEquatable<ReagentUnit>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -63,6 +63,11 @@ namespace Content.Shared.Chemistry
|
|||||||
() => _contents);
|
() => _contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool ContainsReagent(string reagentId)
|
||||||
|
{
|
||||||
|
return ContainsReagent(reagentId, out _);
|
||||||
|
}
|
||||||
|
|
||||||
public bool ContainsReagent(string reagentId, out ReagentUnit quantity)
|
public bool ContainsReagent(string reagentId, out ReagentUnit quantity)
|
||||||
{
|
{
|
||||||
foreach (var reagent in Contents)
|
foreach (var reagent in Contents)
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -30,20 +30,19 @@ namespace Content.Shared.GameObjects.Components.Chemistry.ChemMaster
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A list of the reagents and their amounts within the beaker/reagent container, if applicable.
|
/// A list of the reagents and their amounts within the beaker/reagent container, if applicable.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly List<Solution.ReagentQuantity> ContainerReagents;
|
public readonly IReadOnlyList<Solution.ReagentQuantity> ContainerReagents;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A list of the reagents and their amounts within the buffer, if applicable.
|
/// A list of the reagents and their amounts within the buffer, if applicable.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly List<Solution.ReagentQuantity> BufferReagents;
|
public readonly IReadOnlyList<Solution.ReagentQuantity> BufferReagents;
|
||||||
public readonly string DispenserName;
|
public readonly string DispenserName;
|
||||||
|
|
||||||
public readonly bool BufferModeTransfer;
|
public readonly bool BufferModeTransfer;
|
||||||
|
|
||||||
public readonly ReagentUnit BufferCurrentVolume;
|
public readonly ReagentUnit BufferCurrentVolume;
|
||||||
public readonly ReagentUnit BufferMaxVolume;
|
|
||||||
|
|
||||||
public ChemMasterBoundUserInterfaceState(bool hasPower, 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, IReadOnlyList<Solution.ReagentQuantity> containerReagents, IReadOnlyList<Solution.ReagentQuantity> bufferReagents, bool bufferModeTransfer, ReagentUnit bufferCurrentVolume)
|
||||||
{
|
{
|
||||||
HasPower = hasPower;
|
HasPower = hasPower;
|
||||||
HasBeaker = hasBeaker;
|
HasBeaker = hasBeaker;
|
||||||
@@ -55,7 +54,6 @@ namespace Content.Shared.GameObjects.Components.Chemistry.ChemMaster
|
|||||||
BufferReagents = bufferReagents;
|
BufferReagents = bufferReagents;
|
||||||
BufferModeTransfer = bufferModeTransfer;
|
BufferModeTransfer = bufferModeTransfer;
|
||||||
BufferCurrentVolume = bufferCurrentVolume;
|
BufferCurrentVolume = bufferCurrentVolume;
|
||||||
BufferMaxVolume = bufferMaxVolume;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,100 +1,230 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using System;
|
|
||||||
using Content.Shared.Chemistry;
|
using Content.Shared.Chemistry;
|
||||||
|
using Content.Shared.GameObjects.EntitySystems;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.GameObjects.Components.Appearance;
|
||||||
|
using Robust.Shared.GameObjects.Systems;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Localization;
|
||||||
|
using Robust.Shared.Log;
|
||||||
using Robust.Shared.Maths;
|
using Robust.Shared.Maths;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
using Robust.Shared.ViewVariables;
|
using Robust.Shared.ViewVariables;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Content.Shared.GameObjects.Components.Chemistry
|
namespace Content.Shared.GameObjects.Components.Chemistry
|
||||||
{
|
{
|
||||||
public abstract class SharedSolutionContainerComponent : Component
|
/// <summary>
|
||||||
|
/// Holds a <see cref="Solution"/> with a limited volume.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class SharedSolutionContainerComponent : Component, IExamine
|
||||||
{
|
{
|
||||||
public override string Name => "SolutionContainer";
|
public override string Name => "SolutionContainer";
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public sealed override uint? NetID => ContentNetIDs.SOLUTION;
|
public sealed override uint? NetID => ContentNetIDs.SOLUTION;
|
||||||
|
|
||||||
private Solution _solution = new();
|
|
||||||
private ReagentUnit _maxVolume;
|
|
||||||
private Color _substanceColor;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The contained solution.
|
|
||||||
/// </summary>
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public Solution Solution
|
public Solution Solution { get; private set; } = new();
|
||||||
{
|
|
||||||
get => _solution;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (_solution == value)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_solution = value;
|
public IReadOnlyList<Solution.ReagentQuantity> ReagentList => Solution.Contents;
|
||||||
Dirty();
|
|
||||||
}
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
}
|
public ReagentUnit MaxVolume { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The total volume of all the of the reagents in the container.
|
|
||||||
/// </summary>
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public ReagentUnit CurrentVolume => Solution.TotalVolume;
|
public ReagentUnit CurrentVolume => Solution.TotalVolume;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The maximum volume of the container.
|
/// Volume needed to fill this container.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
[ViewVariables]
|
||||||
public ReagentUnit MaxVolume
|
public ReagentUnit EmptyVolume => MaxVolume - CurrentVolume;
|
||||||
{
|
|
||||||
get => _maxVolume;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (_maxVolume == value)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_maxVolume = value;
|
[ViewVariables]
|
||||||
Dirty();
|
public virtual Color Color => Solution.Color;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The current blended color of all the reagents in the container.
|
/// If reactions will be checked for when adding reagents to the container.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
public virtual Color SubstanceColor
|
public bool CanReact { get; set; }
|
||||||
{
|
|
||||||
get => _substanceColor;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (_substanceColor == value)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_substanceColor = value;
|
|
||||||
Dirty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The current capabilities of this container (is the top open to pour? can I inject it into another object?).
|
|
||||||
/// </summary>
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
public SolutionContainerCaps Capabilities { get; set; }
|
public SolutionContainerCaps Capabilities { get; set; }
|
||||||
|
|
||||||
public abstract bool CanAddSolution(Solution solution);
|
public bool CanExamineContents => Capabilities.HasCap(SolutionContainerCaps.CanExamine);
|
||||||
|
|
||||||
public abstract bool TryAddSolution(Solution solution, bool skipReactionCheck = false, bool skipColor = false);
|
public bool CanUseWithChemDispenser => Capabilities.HasCap(SolutionContainerCaps.FitsInDispenser);
|
||||||
|
|
||||||
public abstract bool TryRemoveReagent(string reagentId, ReagentUnit quantity);
|
public bool CanAddSolutions => Capabilities.HasCap(SolutionContainerCaps.AddTo);
|
||||||
|
|
||||||
|
public bool CanRemoveSolutions => Capabilities.HasCap(SolutionContainerCaps.RemoveFrom);
|
||||||
|
|
||||||
|
public override void ExposeData(ObjectSerializer serializer)
|
||||||
|
{
|
||||||
|
base.ExposeData(serializer);
|
||||||
|
|
||||||
|
serializer.DataField(this, x => x.CanReact, "canReact", true);
|
||||||
|
serializer.DataField(this, x => x.MaxVolume, "maxVol", ReagentUnit.New(0));
|
||||||
|
serializer.DataField(this, x => x.Solution, "contents", new Solution());
|
||||||
|
serializer.DataField(this, x => x.Capabilities, "caps", SolutionContainerCaps.AddTo | SolutionContainerCaps.RemoveFrom | SolutionContainerCaps.CanExamine);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAllSolution()
|
||||||
|
{
|
||||||
|
if (CurrentVolume == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Solution.RemoveAllSolution();
|
||||||
|
ChemicalsRemoved();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds reagent of an Id to the container.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="reagentId">The Id of the reagent to add.</param>
|
||||||
|
/// <param name="quantity">The amount of reagent to add.</param>
|
||||||
|
/// <param name="acceptedQuantity">The amount of reagent sucesfully added.</param>
|
||||||
|
/// <returns>If all the reagent could be added.</returns>
|
||||||
|
public bool TryAddReagent(string reagentId, ReagentUnit quantity, out ReagentUnit acceptedQuantity)
|
||||||
|
{
|
||||||
|
acceptedQuantity = EmptyVolume > quantity ? quantity : EmptyVolume;
|
||||||
|
Solution.AddReagent(reagentId, acceptedQuantity);
|
||||||
|
|
||||||
|
if (acceptedQuantity > 0)
|
||||||
|
ChemicalsAdded();
|
||||||
|
|
||||||
|
return acceptedQuantity == quantity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes reagent of an Id to the container.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="reagentId">The Id of the reagent to remove.</param>
|
||||||
|
/// <param name="quantity">The amount of reagent to remove.</param>
|
||||||
|
/// <returns>If the reagent to remove was found in the container.</returns>
|
||||||
|
public bool TryRemoveReagent(string reagentId, ReagentUnit quantity)
|
||||||
|
{
|
||||||
|
if (!Solution.ContainsReagent(reagentId))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Solution.RemoveReagent(reagentId, quantity);
|
||||||
|
ChemicalsRemoved();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes part of the solution in the container.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="quantity">the volume of solution to remove.</param>
|
||||||
|
/// <returns>The solution that was removed.</returns>
|
||||||
|
public Solution SplitSolution(ReagentUnit quantity)
|
||||||
|
{
|
||||||
|
var splitSol = Solution.SplitSolution(quantity);
|
||||||
|
ChemicalsRemoved();
|
||||||
|
return splitSol;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if a solution can fit into the container.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="solution">The solution that is trying to be added.</param>
|
||||||
|
/// <returns>If the solution can be fully added.</returns>
|
||||||
|
public bool CanAddSolution(Solution solution)
|
||||||
|
{
|
||||||
|
return solution.TotalVolume <= EmptyVolume;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a solution to the container, if it can fully fit.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="solution">The solution to try to add.</param>
|
||||||
|
/// <returns>If the solution could be added.</returns>
|
||||||
|
public bool TryAddSolution(Solution solution)
|
||||||
|
{
|
||||||
|
if (!CanAddSolution(solution))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Solution.AddSolution(solution);
|
||||||
|
ChemicalsAdded();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ChemicalsAdded()
|
||||||
|
{
|
||||||
|
ProcessReactions();
|
||||||
|
SolutionChanged();
|
||||||
|
UpdateAppearance();
|
||||||
|
Dirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ChemicalsRemoved()
|
||||||
|
{
|
||||||
|
SolutionChanged();
|
||||||
|
UpdateAppearance();
|
||||||
|
Dirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SolutionChanged()
|
||||||
|
{
|
||||||
|
EntitySystem.Get<ChemistrySystem>()
|
||||||
|
.HandleSolutionChange(Owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessReactions()
|
||||||
|
{
|
||||||
|
if (!CanReact)
|
||||||
|
return;
|
||||||
|
|
||||||
|
EntitySystem.Get<ChemicalReactionSystem>()
|
||||||
|
.FullyReactSolution(Solution, Owner, MaxVolume);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IExamine.Examine(FormattedMessage message, bool inDetailsRange)
|
||||||
|
{
|
||||||
|
if (!CanExamineContents)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
|
||||||
|
|
||||||
|
if (ReagentList.Count == 0)
|
||||||
|
{
|
||||||
|
message.AddText(Loc.GetString("Contains no chemicals."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var primaryReagent = Solution.GetPrimaryReagentId();
|
||||||
|
if (!prototypeManager.TryIndex(primaryReagent, out ReagentPrototype proto))
|
||||||
|
{
|
||||||
|
Logger.Error($"{nameof(SharedSolutionContainerComponent)} could not find the prototype associated with {primaryReagent}.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var colorHex = Color.ToHexNoAlpha(); //TODO: If the chem has a dark color, the examine text becomes black on a black background, which is unreadable.
|
||||||
|
var messageString = "It contains a [color={0}]{1}[/color] " + (ReagentList.Count == 1 ? "chemical." : "mixture of chemicals.");
|
||||||
|
|
||||||
|
message.AddMarkup(Loc.GetString(messageString, colorHex, Loc.GetString(proto.PhysicalDescription)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateAppearance()
|
||||||
|
{
|
||||||
|
if (!Owner.TryGetComponent<SharedAppearanceComponent>(out var appearance))
|
||||||
|
return;
|
||||||
|
|
||||||
|
appearance.SetData(SolutionContainerVisuals.VisualState, GetVisualState());
|
||||||
|
}
|
||||||
|
|
||||||
|
private SolutionContainerVisualState GetVisualState()
|
||||||
|
{
|
||||||
|
var filledVolumeFraction = CurrentVolume.Float() / MaxVolume.Float();
|
||||||
|
|
||||||
|
return new SolutionContainerVisualState(Color, filledVolumeFraction);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override ComponentState GetComponentState()
|
public override ComponentState GetComponentState()
|
||||||
{
|
{
|
||||||
return new SolutionContainerComponentState(Solution);
|
return new SolutionContainerComponentState(Solution);
|
||||||
@@ -102,14 +232,34 @@ namespace Content.Shared.GameObjects.Components.Chemistry
|
|||||||
|
|
||||||
public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
|
public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
|
||||||
{
|
{
|
||||||
base.HandleComponentState(curState, nextState);
|
if (curState is not SolutionContainerComponentState containerState)
|
||||||
|
|
||||||
if (curState is not SolutionContainerComponentState state)
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
_solution = state.Solution;
|
Solution = containerState.Solution;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public enum SolutionContainerVisuals : byte
|
||||||
|
{
|
||||||
|
VisualState
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public class SolutionContainerVisualState
|
||||||
|
{
|
||||||
|
public readonly Color Color;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents how full the container is, as a fraction equivalent to <see cref="FilledVolumeFraction"/>/<see cref="byte.MaxValue"/>.
|
||||||
|
/// </summary>
|
||||||
|
public readonly byte FilledVolumeFraction;
|
||||||
|
|
||||||
|
/// <param name="filledVolumeFraction">The fraction of the container's volume that is filled.</param>
|
||||||
|
public SolutionContainerVisualState(Color color, float filledVolumeFraction)
|
||||||
|
{
|
||||||
|
Color = color;
|
||||||
|
FilledVolumeFraction = (byte) (byte.MaxValue * filledVolumeFraction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using System.Collections.Generic;
|
|||||||
|
|
||||||
namespace Content.Shared.GameObjects.EntitySystems
|
namespace Content.Shared.GameObjects.EntitySystems
|
||||||
{
|
{
|
||||||
|
//TODO: Reimplement sounds for reactions
|
||||||
public class ChemicalReactionSystem : EntitySystem
|
public class ChemicalReactionSystem : EntitySystem
|
||||||
{
|
{
|
||||||
private IEnumerable<ReactionPrototype> _reactions;
|
private IEnumerable<ReactionPrototype> _reactions;
|
||||||
|
|||||||
Reference in New Issue
Block a user