Merge branch 'master' into round_end_screen
This commit is contained in:
@@ -6,7 +6,7 @@ namespace Content.Shared.Chat
|
||||
/// Represents chat channels that the player can filter chat tabs by.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum ChatChannel : byte
|
||||
public enum ChatChannel : short
|
||||
{
|
||||
None = 0,
|
||||
|
||||
@@ -46,9 +46,14 @@ namespace Content.Shared.Chat
|
||||
/// </summary>
|
||||
Emotes = 64,
|
||||
|
||||
/// <summary>
|
||||
/// Deadchat
|
||||
/// </summary>
|
||||
Dead = 128,
|
||||
|
||||
/// <summary>
|
||||
/// Unspecified.
|
||||
/// </summary>
|
||||
Unspecified = 128,
|
||||
Unspecified = 256,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace Content.Shared.Chat
|
||||
|
||||
/// <summary>
|
||||
/// The sending entity.
|
||||
/// Only applies to <see cref="ChatChannel.Local"/> and <see cref="ChatChannel.Emotes"/>.
|
||||
/// Only applies to <see cref="ChatChannel.Local"/>, <see cref="ChatChannel.Dead"/> and <see cref="ChatChannel.Emotes"/>.
|
||||
/// </summary>
|
||||
public EntityUid SenderEntity { get; set; }
|
||||
|
||||
@@ -48,6 +48,7 @@ namespace Content.Shared.Chat
|
||||
switch (Channel)
|
||||
{
|
||||
case ChatChannel.Local:
|
||||
case ChatChannel.Dead:
|
||||
case ChatChannel.Emotes:
|
||||
SenderEntity = buffer.ReadEntityUid();
|
||||
break;
|
||||
@@ -63,6 +64,7 @@ namespace Content.Shared.Chat
|
||||
switch (Channel)
|
||||
{
|
||||
case ChatChannel.Local:
|
||||
case ChatChannel.Dead:
|
||||
case ChatChannel.Emotes:
|
||||
buffer.Write(SenderEntity);
|
||||
break;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using Content.Shared.Interfaces.Chemistry;
|
||||
using Content.Shared.Interfaces.Chemistry;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Interfaces.Serialization;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.Chemistry
|
||||
@@ -10,18 +10,17 @@ namespace Content.Shared.Chemistry
|
||||
class DefaultMetabolizable : IMetabolizable
|
||||
{
|
||||
//Rate of metabolism in units / second
|
||||
private int _metabolismRate = 1;
|
||||
public int MetabolismRate => _metabolismRate;
|
||||
private decimal _metabolismRate = 1;
|
||||
public decimal MetabolismRate => _metabolismRate;
|
||||
|
||||
void IExposeData.ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
serializer.DataField(ref _metabolismRate, "rate", 1);
|
||||
}
|
||||
|
||||
int IMetabolizable.Metabolize(IEntity solutionEntity, string reagentId, float tickTime)
|
||||
ReagentUnit IMetabolizable.Metabolize(IEntity solutionEntity, string reagentId, float tickTime)
|
||||
{
|
||||
int metabolismAmount = (int)Math.Round(MetabolismRate * tickTime);
|
||||
return metabolismAmount;
|
||||
return ReagentUnit.New(MetabolismRate * (decimal)tickTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ namespace Content.Shared.Chemistry
|
||||
private string _description;
|
||||
private Color _substanceColor;
|
||||
private List<IMetabolizable> _metabolism;
|
||||
private string _spritePath;
|
||||
|
||||
public string ID => _id;
|
||||
public string Name => _name;
|
||||
@@ -29,6 +30,8 @@ namespace Content.Shared.Chemistry
|
||||
//List of metabolism effects this reagent has, should really only be used server-side.
|
||||
public List<IMetabolizable> Metabolism => _metabolism;
|
||||
|
||||
public string SpriteReplacementPath => _spritePath;
|
||||
|
||||
public ReagentPrototype()
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
@@ -42,6 +45,7 @@ namespace Content.Shared.Chemistry
|
||||
serializer.DataField(ref _name, "name", string.Empty);
|
||||
serializer.DataField(ref _description, "desc", string.Empty);
|
||||
serializer.DataField(ref _substanceColor, "color", Color.White);
|
||||
serializer.DataField(ref _spritePath, "spritePath", string.Empty);
|
||||
|
||||
if (_moduleManager.IsServerModule)
|
||||
serializer.DataField(ref _metabolism, "metabolism", new List<IMetabolizable> {new DefaultMetabolizable()});
|
||||
|
||||
225
Content.Shared/Chemistry/ReagentUnit.cs
Normal file
225
Content.Shared/Chemistry/ReagentUnit.cs
Normal file
@@ -0,0 +1,225 @@
|
||||
using Robust.Shared.Interfaces.Serialization;
|
||||
using Robust.Shared.Serialization;
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
|
||||
namespace Content.Shared.Chemistry
|
||||
{
|
||||
[Serializable]
|
||||
public struct ReagentUnit : ISelfSerialize, IComparable<ReagentUnit>, IEquatable<ReagentUnit>
|
||||
{
|
||||
private int _value;
|
||||
private static readonly int Shift = 2;
|
||||
|
||||
public static ReagentUnit MaxValue => new ReagentUnit(int.MaxValue);
|
||||
|
||||
private double ShiftDown()
|
||||
{
|
||||
return _value / Math.Pow(10, Shift);
|
||||
}
|
||||
|
||||
private ReagentUnit(int value)
|
||||
{
|
||||
_value = value;
|
||||
}
|
||||
|
||||
public static ReagentUnit New(int value)
|
||||
{
|
||||
return new ReagentUnit(value * (int) Math.Pow(10, Shift));
|
||||
}
|
||||
|
||||
public static ReagentUnit New(decimal value)
|
||||
{
|
||||
return new ReagentUnit((int) Math.Round(value * (decimal) Math.Pow(10, Shift), MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
public static ReagentUnit New(float value)
|
||||
{
|
||||
return new ReagentUnit(FromFloat(value));
|
||||
}
|
||||
|
||||
private static int FromFloat(float value)
|
||||
{
|
||||
return (int) Math.Round(value * (float) Math.Pow(10, Shift), MidpointRounding.AwayFromZero);
|
||||
}
|
||||
|
||||
public static ReagentUnit New(double value)
|
||||
{
|
||||
return new ReagentUnit((int) Math.Round(value * Math.Pow(10, Shift), MidpointRounding.AwayFromZero));
|
||||
}
|
||||
|
||||
public static ReagentUnit New(string value)
|
||||
{
|
||||
return New(FloatFromString(value));
|
||||
}
|
||||
|
||||
private static float FloatFromString(string value)
|
||||
{
|
||||
return float.Parse(value, CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
public static ReagentUnit operator +(ReagentUnit a) => a;
|
||||
|
||||
public static ReagentUnit operator -(ReagentUnit a) => new ReagentUnit(-a._value);
|
||||
|
||||
public static ReagentUnit operator +(ReagentUnit a, ReagentUnit b)
|
||||
=> new ReagentUnit(a._value + b._value);
|
||||
|
||||
public static ReagentUnit operator -(ReagentUnit a, ReagentUnit b)
|
||||
=> a + -b;
|
||||
|
||||
public static ReagentUnit operator *(ReagentUnit a, ReagentUnit b)
|
||||
{
|
||||
var aD = a.ShiftDown();
|
||||
var bD = b.ShiftDown();
|
||||
return New(aD * bD);
|
||||
}
|
||||
|
||||
public static ReagentUnit operator *(ReagentUnit a, float b)
|
||||
{
|
||||
var aD = (float) a.ShiftDown();
|
||||
return New(aD * b);
|
||||
}
|
||||
|
||||
public static ReagentUnit operator *(ReagentUnit a, decimal b)
|
||||
{
|
||||
var aD = (decimal) a.ShiftDown();
|
||||
return New(aD * b);
|
||||
}
|
||||
|
||||
public static ReagentUnit operator *(ReagentUnit a, double b)
|
||||
{
|
||||
var aD = a.ShiftDown();
|
||||
return New(aD * b);
|
||||
}
|
||||
|
||||
public static ReagentUnit operator *(ReagentUnit a, int b)
|
||||
{
|
||||
return new ReagentUnit(a._value * b);
|
||||
}
|
||||
|
||||
public static ReagentUnit operator /(ReagentUnit a, ReagentUnit b)
|
||||
{
|
||||
if (b._value == 0)
|
||||
{
|
||||
throw new DivideByZeroException();
|
||||
}
|
||||
var aD = a.ShiftDown();
|
||||
var bD = b.ShiftDown();
|
||||
return New(aD / bD);
|
||||
}
|
||||
|
||||
public static bool operator <=(ReagentUnit a, int b)
|
||||
{
|
||||
return a.ShiftDown() <= b;
|
||||
}
|
||||
|
||||
public static bool operator >=(ReagentUnit a, int b)
|
||||
{
|
||||
return a.ShiftDown() >= b;
|
||||
}
|
||||
|
||||
public static bool operator ==(ReagentUnit a, int b)
|
||||
{
|
||||
return a.ShiftDown() == b;
|
||||
}
|
||||
|
||||
public static bool operator !=(ReagentUnit a, int b)
|
||||
{
|
||||
return a.ShiftDown() != b;
|
||||
}
|
||||
|
||||
public static bool operator <=(ReagentUnit a, ReagentUnit b)
|
||||
{
|
||||
return a._value <= b._value;
|
||||
}
|
||||
|
||||
public static bool operator >=(ReagentUnit a, ReagentUnit b)
|
||||
{
|
||||
return a._value >= b._value;
|
||||
}
|
||||
|
||||
public static bool operator <(ReagentUnit a, ReagentUnit b)
|
||||
{
|
||||
return a._value < b._value;
|
||||
}
|
||||
|
||||
public static bool operator >(ReagentUnit a, ReagentUnit b)
|
||||
{
|
||||
return a._value > b._value;
|
||||
}
|
||||
|
||||
public float Float()
|
||||
{
|
||||
return (float) ShiftDown();
|
||||
}
|
||||
|
||||
public decimal Decimal()
|
||||
{
|
||||
return (decimal) ShiftDown();
|
||||
}
|
||||
|
||||
public double Double()
|
||||
{
|
||||
return ShiftDown();
|
||||
}
|
||||
|
||||
public int Int()
|
||||
{
|
||||
return (int) ShiftDown();
|
||||
}
|
||||
|
||||
public static ReagentUnit Min(params ReagentUnit[] reagentUnits)
|
||||
{
|
||||
return reagentUnits.Min();
|
||||
}
|
||||
|
||||
public static ReagentUnit Min(ReagentUnit a, ReagentUnit b)
|
||||
{
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is ReagentUnit unit &&
|
||||
_value == unit._value;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(_value);
|
||||
}
|
||||
|
||||
public void Deserialize(string value)
|
||||
{
|
||||
_value = FromFloat(FloatFromString(value));
|
||||
}
|
||||
|
||||
public override string ToString() => $"{ShiftDown().ToString(CultureInfo.InvariantCulture)}";
|
||||
|
||||
public string Serialize()
|
||||
{
|
||||
return ToString();
|
||||
}
|
||||
|
||||
public bool Equals([AllowNull] ReagentUnit other)
|
||||
{
|
||||
return _value == other._value;
|
||||
}
|
||||
|
||||
public int CompareTo([AllowNull] ReagentUnit other)
|
||||
{
|
||||
if(other._value > _value)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if(other._value < _value)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Content.Shared.Interfaces.Chemistry;
|
||||
using Robust.Shared.Interfaces.Serialization;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Utility;
|
||||
using Robust.Shared.ViewVariables;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Content.Shared.Chemistry
|
||||
{
|
||||
@@ -23,7 +25,7 @@ namespace Content.Shared.Chemistry
|
||||
/// The calculated total volume of all reagents in the solution (ex. Total volume of liquid in beaker).
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public int TotalVolume { get; private set; }
|
||||
public ReagentUnit TotalVolume { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructs an empty solution (ex. an empty beaker).
|
||||
@@ -35,7 +37,7 @@ namespace Content.Shared.Chemistry
|
||||
/// </summary>
|
||||
/// <param name="reagentId">The prototype ID of the reagent to add.</param>
|
||||
/// <param name="quantity">The quantity in milli-units.</param>
|
||||
public Solution(string reagentId, int quantity)
|
||||
public Solution(string reagentId, ReagentUnit quantity)
|
||||
{
|
||||
AddReagent(reagentId, quantity);
|
||||
}
|
||||
@@ -47,7 +49,7 @@ namespace Content.Shared.Chemistry
|
||||
|
||||
if (serializer.Reading)
|
||||
{
|
||||
TotalVolume = 0;
|
||||
TotalVolume = ReagentUnit.New(0);
|
||||
foreach (var reagent in _contents)
|
||||
{
|
||||
TotalVolume += reagent.Quantity;
|
||||
@@ -60,9 +62,9 @@ namespace Content.Shared.Chemistry
|
||||
/// </summary>
|
||||
/// <param name="reagentId">The prototype ID of the reagent to add.</param>
|
||||
/// <param name="quantity">The quantity in milli-units.</param>
|
||||
public void AddReagent(string reagentId, int quantity)
|
||||
public void AddReagent(string reagentId, ReagentUnit quantity)
|
||||
{
|
||||
if(quantity <= 0)
|
||||
if (quantity <= 0)
|
||||
return;
|
||||
|
||||
for (var i = 0; i < _contents.Count; i++)
|
||||
@@ -85,7 +87,7 @@ namespace Content.Shared.Chemistry
|
||||
/// </summary>
|
||||
/// <param name="reagentId">The prototype ID of the reagent to add.</param>
|
||||
/// <returns>The quantity in milli-units.</returns>
|
||||
public int GetReagentQuantity(string reagentId)
|
||||
public ReagentUnit GetReagentQuantity(string reagentId)
|
||||
{
|
||||
for (var i = 0; i < _contents.Count; i++)
|
||||
{
|
||||
@@ -93,10 +95,10 @@ namespace Content.Shared.Chemistry
|
||||
return _contents[i].Quantity;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ReagentUnit.New(0);
|
||||
}
|
||||
|
||||
public void RemoveReagent(string reagentId, int quantity)
|
||||
public void RemoveReagent(string reagentId, ReagentUnit quantity)
|
||||
{
|
||||
if(quantity <= 0)
|
||||
return;
|
||||
@@ -129,12 +131,12 @@ namespace Content.Shared.Chemistry
|
||||
/// Remove the specified quantity from this solution.
|
||||
/// </summary>
|
||||
/// <param name="quantity">The quantity of this solution to remove</param>
|
||||
public void RemoveSolution(int quantity)
|
||||
public void RemoveSolution(ReagentUnit quantity)
|
||||
{
|
||||
if(quantity <= 0)
|
||||
return;
|
||||
|
||||
var ratio = (float)(TotalVolume - quantity) / TotalVolume;
|
||||
var ratio = (TotalVolume - quantity).Decimal() / TotalVolume.Decimal();
|
||||
|
||||
if (ratio <= 0)
|
||||
{
|
||||
@@ -149,21 +151,21 @@ namespace Content.Shared.Chemistry
|
||||
|
||||
// quantity taken is always a little greedy, so fractional quantities get rounded up to the nearest
|
||||
// whole unit. This should prevent little bits of chemical remaining because of float rounding errors.
|
||||
var newQuantity = (int)Math.Floor(oldQuantity * ratio);
|
||||
var newQuantity = oldQuantity * ratio;
|
||||
|
||||
_contents[i] = new ReagentQuantity(reagent.ReagentId, newQuantity);
|
||||
}
|
||||
|
||||
TotalVolume = (int)Math.Floor(TotalVolume * ratio);
|
||||
TotalVolume = TotalVolume * ratio;
|
||||
}
|
||||
|
||||
public void RemoveAllSolution()
|
||||
{
|
||||
_contents.Clear();
|
||||
TotalVolume = 0;
|
||||
TotalVolume = ReagentUnit.New(0);
|
||||
}
|
||||
|
||||
public Solution SplitSolution(int quantity)
|
||||
public Solution SplitSolution(ReagentUnit quantity)
|
||||
{
|
||||
if (quantity <= 0)
|
||||
return new Solution();
|
||||
@@ -178,14 +180,14 @@ namespace Content.Shared.Chemistry
|
||||
}
|
||||
|
||||
newSolution = new Solution();
|
||||
var newTotalVolume = 0;
|
||||
var ratio = (float)(TotalVolume - quantity) / TotalVolume;
|
||||
var newTotalVolume = ReagentUnit.New(0M);
|
||||
var ratio = (TotalVolume - quantity).Decimal() / TotalVolume.Decimal();
|
||||
|
||||
for (var i = 0; i < _contents.Count; i++)
|
||||
{
|
||||
var reagent = _contents[i];
|
||||
|
||||
var newQuantity = (int)Math.Floor(reagent.Quantity * ratio);
|
||||
var newQuantity = reagent.Quantity * ratio;
|
||||
var splitQuantity = reagent.Quantity - newQuantity;
|
||||
|
||||
_contents[i] = new ReagentQuantity(reagent.ReagentId, newQuantity);
|
||||
@@ -193,7 +195,7 @@ namespace Content.Shared.Chemistry
|
||||
newTotalVolume += splitQuantity;
|
||||
}
|
||||
|
||||
TotalVolume = (int)Math.Floor(TotalVolume * ratio);
|
||||
TotalVolume = TotalVolume * ratio;
|
||||
newSolution.TotalVolume = newTotalVolume;
|
||||
|
||||
return newSolution;
|
||||
@@ -228,7 +230,7 @@ namespace Content.Shared.Chemistry
|
||||
|
||||
public Solution Clone()
|
||||
{
|
||||
var volume = 0;
|
||||
var volume = ReagentUnit.New(0);
|
||||
var newSolution = new Solution();
|
||||
|
||||
for (var i = 0; i < _contents.Count; i++)
|
||||
@@ -246,9 +248,9 @@ namespace Content.Shared.Chemistry
|
||||
public readonly struct ReagentQuantity
|
||||
{
|
||||
public readonly string ReagentId;
|
||||
public readonly int Quantity;
|
||||
public readonly ReagentUnit Quantity;
|
||||
|
||||
public ReagentQuantity(string reagentId, int quantity)
|
||||
public ReagentQuantity(string reagentId, ReagentUnit quantity)
|
||||
{
|
||||
ReagentId = reagentId;
|
||||
Quantity = quantity;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Content.Shared.Chemistry;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
@@ -18,11 +19,11 @@ namespace Content.Shared.GameObjects.Components.Chemistry
|
||||
[Serializable, NetSerializable]
|
||||
protected sealed class InjectorComponentState : ComponentState
|
||||
{
|
||||
public int CurrentVolume { get; }
|
||||
public int TotalVolume { get; }
|
||||
public ReagentUnit CurrentVolume { get; }
|
||||
public ReagentUnit TotalVolume { get; }
|
||||
public InjectorToggleMode CurrentMode { get; }
|
||||
|
||||
public InjectorComponentState(int currentVolume, int totalVolume, InjectorToggleMode currentMode) : base(ContentNetIDs.REAGENT_INJECTOR)
|
||||
public InjectorComponentState(ReagentUnit currentVolume, ReagentUnit totalVolume, InjectorToggleMode currentMode) : base(ContentNetIDs.REAGENT_INJECTOR)
|
||||
{
|
||||
CurrentVolume = currentVolume;
|
||||
TotalVolume = totalVolume;
|
||||
|
||||
@@ -26,8 +26,8 @@ namespace Content.Shared.GameObjects.Components.Chemistry
|
||||
public class ReagentDispenserBoundUserInterfaceState : BoundUserInterfaceState
|
||||
{
|
||||
public readonly bool HasBeaker;
|
||||
public readonly int BeakerCurrentVolume;
|
||||
public readonly int BeakerMaxVolume;
|
||||
public readonly ReagentUnit BeakerCurrentVolume;
|
||||
public readonly ReagentUnit BeakerMaxVolume;
|
||||
public readonly string ContainerName;
|
||||
/// <summary>
|
||||
/// A list of the reagents which this dispenser can dispense.
|
||||
@@ -38,10 +38,10 @@ namespace Content.Shared.GameObjects.Components.Chemistry
|
||||
/// </summary>
|
||||
public readonly List<Solution.ReagentQuantity> ContainerReagents;
|
||||
public readonly string DispenserName;
|
||||
public readonly int SelectedDispenseAmount;
|
||||
public readonly ReagentUnit SelectedDispenseAmount;
|
||||
|
||||
public ReagentDispenserBoundUserInterfaceState(bool hasBeaker, int beakerCurrentVolume, int beakerMaxVolume, string containerName,
|
||||
List<ReagentDispenserInventoryEntry> inventory, string dispenserName, List<Solution.ReagentQuantity> containerReagents, int selectedDispenseAmount)
|
||||
public ReagentDispenserBoundUserInterfaceState(bool hasBeaker, ReagentUnit beakerCurrentVolume, ReagentUnit beakerMaxVolume, string containerName,
|
||||
List<ReagentDispenserInventoryEntry> inventory, string dispenserName, List<Solution.ReagentQuantity> containerReagents, ReagentUnit selectedDispenseAmount)
|
||||
{
|
||||
HasBeaker = hasBeaker;
|
||||
BeakerCurrentVolume = beakerCurrentVolume;
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Content.Shared.Chemistry;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Shared.GameObjects.Components.Chemistry
|
||||
{
|
||||
public class SharedSolutionComponent : Component
|
||||
{
|
||||
public override string Name => "Solution";
|
||||
|
||||
/// <inheritdoc />
|
||||
public sealed override uint? NetID => ContentNetIDs.SOLUTION;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public class SolutionComponentState : ComponentState
|
||||
{
|
||||
public SolutionComponentState() : base(ContentNetIDs.SOLUTION) { }
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override ComponentState GetComponentState()
|
||||
{
|
||||
return new SolutionComponentState();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void HandleComponentState(ComponentState curState, ComponentState nextState)
|
||||
{
|
||||
base.HandleComponentState(curState, nextState);
|
||||
|
||||
if(curState == null)
|
||||
return;
|
||||
|
||||
var compState = (SolutionComponentState)curState;
|
||||
|
||||
//TODO: Make me work!
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,238 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Content.Shared.Chemistry;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Shared.GameObjects.Components.Chemistry
|
||||
{
|
||||
public class SolutionComponent : Component
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager;
|
||||
#pragma warning restore 649
|
||||
|
||||
[ViewVariables]
|
||||
protected Solution _containedSolution = new Solution();
|
||||
protected int _maxVolume;
|
||||
private SolutionCaps _capabilities;
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when the solution contents change.
|
||||
/// </summary>
|
||||
public event Action SolutionChanged;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum volume of the container.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public int MaxVolume
|
||||
{
|
||||
get => _maxVolume;
|
||||
set => _maxVolume = value; // Note that the contents won't spill out if the capacity is reduced.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The total volume of all the of the reagents in the container.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public int CurrentVolume => _containedSolution.TotalVolume;
|
||||
|
||||
/// <summary>
|
||||
/// The volume without reagents remaining in the container.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public int EmptyVolume => MaxVolume - CurrentVolume;
|
||||
|
||||
/// <summary>
|
||||
/// The current blended color of all the reagents in the container.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public Color SubstanceColor { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The current capabilities of this container (is the top open to pour? can I inject it into another object?).
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public SolutionCaps Capabilities
|
||||
{
|
||||
get => _capabilities;
|
||||
set => _capabilities = value;
|
||||
}
|
||||
|
||||
public IReadOnlyList<Solution.ReagentQuantity> ReagentList => _containedSolution.Contents;
|
||||
|
||||
/// <summary>
|
||||
/// Shortcut for Capabilities PourIn flag to avoid binary operators.
|
||||
/// </summary>
|
||||
public bool CanPourIn => (Capabilities & SolutionCaps.PourIn) != 0;
|
||||
/// <summary>
|
||||
/// Shortcut for Capabilities PourOut flag to avoid binary operators.
|
||||
/// </summary>
|
||||
public bool CanPourOut => (Capabilities & SolutionCaps.PourOut) != 0;
|
||||
/// <summary>
|
||||
/// Shortcut for Capabilities Injectable flag
|
||||
/// </summary>
|
||||
public bool Injectable => (Capabilities & SolutionCaps.Injectable) != 0;
|
||||
/// <summary>
|
||||
/// Shortcut for Capabilities Injector flag
|
||||
/// </summary>
|
||||
public bool Injector => (Capabilities & SolutionCaps.Injector) != 0;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Name => "Solution";
|
||||
|
||||
/// <inheritdoc />
|
||||
public sealed override uint? NetID => ContentNetIDs.SOLUTION;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
base.ExposeData(serializer);
|
||||
|
||||
serializer.DataField(ref _maxVolume, "maxVol", 0);
|
||||
serializer.DataField(ref _containedSolution, "contents", _containedSolution);
|
||||
serializer.DataField(ref _capabilities, "caps", SolutionCaps.None);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Startup()
|
||||
{
|
||||
base.Startup();
|
||||
|
||||
RecalculateColor();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Shutdown()
|
||||
{
|
||||
base.Shutdown();
|
||||
|
||||
_containedSolution.RemoveAllSolution();
|
||||
_containedSolution = new Solution();
|
||||
}
|
||||
|
||||
public void RemoveAllSolution()
|
||||
{
|
||||
_containedSolution.RemoveAllSolution();
|
||||
OnSolutionChanged();
|
||||
}
|
||||
|
||||
public bool TryRemoveReagent(string reagentId, int quantity)
|
||||
{
|
||||
if (!ContainsReagent(reagentId, out var currentQuantity)) return false;
|
||||
|
||||
_containedSolution.RemoveReagent(reagentId, quantity);
|
||||
OnSolutionChanged();
|
||||
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(int quantity)
|
||||
{
|
||||
if (CurrentVolume == 0)
|
||||
return false;
|
||||
|
||||
_containedSolution.RemoveSolution(quantity);
|
||||
OnSolutionChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
public Solution SplitSolution(int quantity)
|
||||
{
|
||||
var solutionSplit = _containedSolution.SplitSolution(quantity);
|
||||
OnSolutionChanged();
|
||||
return solutionSplit;
|
||||
}
|
||||
|
||||
protected void RecalculateColor()
|
||||
{
|
||||
if(_containedSolution.TotalVolume == 0)
|
||||
SubstanceColor = Color.White;
|
||||
|
||||
Color mixColor = default;
|
||||
float runningTotalQuantity = 0;
|
||||
|
||||
foreach (var reagent in _containedSolution)
|
||||
{
|
||||
runningTotalQuantity += reagent.Quantity;
|
||||
|
||||
if(!_prototypeManager.TryIndex(reagent.ReagentId, out ReagentPrototype proto))
|
||||
continue;
|
||||
|
||||
if (mixColor == default)
|
||||
mixColor = proto.SubstanceColor;
|
||||
|
||||
mixColor = BlendRGB(mixColor, proto.SubstanceColor, reagent.Quantity / runningTotalQuantity);
|
||||
}
|
||||
}
|
||||
|
||||
private Color BlendRGB(Color rgb1, Color rgb2, float amount)
|
||||
{
|
||||
var r = (float)Math.Round(rgb1.R + (rgb2.R - rgb1.R) * amount, 1);
|
||||
var g = (float)Math.Round(rgb1.G + (rgb2.G - rgb1.G) * amount, 1);
|
||||
var b = (float)Math.Round(rgb1.B + (rgb2.B - rgb1.B) * amount, 1);
|
||||
var alpha = (float)Math.Round(rgb1.A + (rgb2.A - rgb1.A) * amount, 1);
|
||||
|
||||
return new Color(r, g, b, alpha);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override ComponentState GetComponentState()
|
||||
{
|
||||
return new SolutionComponentState();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void HandleComponentState(ComponentState curState, ComponentState nextState)
|
||||
{
|
||||
base.HandleComponentState(curState, nextState);
|
||||
|
||||
if(curState == null)
|
||||
return;
|
||||
|
||||
var compState = (SolutionComponentState)curState;
|
||||
|
||||
//TODO: Make me work!
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public class SolutionComponentState : ComponentState
|
||||
{
|
||||
public SolutionComponentState() : base(ContentNetIDs.SOLUTION) { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the solution contains the specified reagent.
|
||||
/// </summary>
|
||||
/// <param name="reagentId">The reagent to check for.</param>
|
||||
/// <param name="quantity">Output the quantity of the reagent if it is contained, 0 if it isn't.</param>
|
||||
/// <returns>Return true if the solution contains the reagent.</returns>
|
||||
public bool ContainsReagent(string reagentId, out int quantity)
|
||||
{
|
||||
foreach (var reagent in _containedSolution.Contents)
|
||||
{
|
||||
if (reagent.ReagentId == reagentId)
|
||||
{
|
||||
quantity = reagent.Quantity;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
quantity = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
protected virtual void OnSolutionChanged()
|
||||
{
|
||||
SolutionChanged?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Components.UserInterface;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.GameObjects.Components.Command
|
||||
{
|
||||
public class SharedCommunicationsConsoleComponent : Component
|
||||
{
|
||||
public override string Name => "CommunicationsConsole";
|
||||
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public class CommunicationsConsoleInterfaceState : BoundUserInterfaceState
|
||||
{
|
||||
public readonly TimeSpan? ExpectedCountdownEnd;
|
||||
public readonly bool CountdownStarted;
|
||||
|
||||
public CommunicationsConsoleInterfaceState(TimeSpan? expectedCountdownEnd = null)
|
||||
{
|
||||
ExpectedCountdownEnd = expectedCountdownEnd;
|
||||
CountdownStarted = expectedCountdownEnd != null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public class CommunicationsConsoleCallEmergencyShuttleMessage : BoundUserInterfaceMessage
|
||||
{
|
||||
public CommunicationsConsoleCallEmergencyShuttleMessage()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public class CommunicationsConsoleRecallEmergencyShuttleMessage : BoundUserInterfaceMessage
|
||||
{
|
||||
public CommunicationsConsoleRecallEmergencyShuttleMessage()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum CommunicationsConsoleUiKey
|
||||
{
|
||||
Key
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.GameObjects.Components.Observer
|
||||
{
|
||||
public class SharedGhostComponent : Component
|
||||
{
|
||||
public override string Name => "Ghost";
|
||||
public override uint? NetID => ContentNetIDs.GHOST;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public class GhostComponentState : ComponentState
|
||||
{
|
||||
public bool CanReturnToBody { get; }
|
||||
|
||||
public GhostComponentState(bool canReturnToBody) : base(ContentNetIDs.GHOST)
|
||||
{
|
||||
CanReturnToBody = canReturnToBody;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public class ReturnToBodyComponentMessage : ComponentMessage
|
||||
{
|
||||
public ReturnToBodyComponentMessage() => Directed = true;
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,109 @@
|
||||
using System;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Interfaces.Reflection;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Shared.GameObjects.Components
|
||||
{
|
||||
public abstract class SharedStackComponent : Component
|
||||
{
|
||||
private const string SerializationCache = "stack";
|
||||
|
||||
public sealed override string Name => "Stack";
|
||||
public sealed override uint? NetID => ContentNetIDs.STACK;
|
||||
|
||||
private int _count;
|
||||
private int _maxCount;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public virtual int Count
|
||||
{
|
||||
get => _count;
|
||||
set
|
||||
{
|
||||
_count = value;
|
||||
if (_count <= 0)
|
||||
{
|
||||
Owner.Delete();
|
||||
}
|
||||
|
||||
Dirty();
|
||||
}
|
||||
}
|
||||
|
||||
[ViewVariables]
|
||||
public int MaxCount
|
||||
{
|
||||
get => _maxCount;
|
||||
private set
|
||||
{
|
||||
_maxCount = value;
|
||||
Dirty();
|
||||
}
|
||||
}
|
||||
|
||||
[ViewVariables] public int AvailableSpace => MaxCount - Count;
|
||||
|
||||
[ViewVariables] public object StackType { get; private set; }
|
||||
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
serializer.DataFieldCached(ref _maxCount, "max", 50);
|
||||
serializer.DataFieldCached(ref _count, "count", MaxCount);
|
||||
|
||||
if (!serializer.Reading)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (serializer.TryGetCacheData(SerializationCache, out object stackType))
|
||||
{
|
||||
StackType = stackType;
|
||||
return;
|
||||
}
|
||||
|
||||
if (serializer.TryReadDataFieldCached("stacktype", out string raw))
|
||||
{
|
||||
var refl = IoCManager.Resolve<IReflectionManager>();
|
||||
if (refl.TryParseEnumReference(raw, out var @enum))
|
||||
{
|
||||
stackType = @enum;
|
||||
}
|
||||
else
|
||||
{
|
||||
stackType = raw;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stackType = Owner.Prototype.ID;
|
||||
}
|
||||
|
||||
serializer.SetCacheData(SerializationCache, stackType);
|
||||
StackType = stackType;
|
||||
}
|
||||
|
||||
public override ComponentState GetComponentState()
|
||||
{
|
||||
return new StackComponentState(Count, MaxCount);
|
||||
}
|
||||
|
||||
public override void HandleComponentState(ComponentState curState, ComponentState nextState)
|
||||
{
|
||||
if (!(curState is StackComponentState cast))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Count = cast.Count;
|
||||
MaxCount = cast.MaxCount;
|
||||
}
|
||||
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
protected sealed class StackComponentState : ComponentState
|
||||
private sealed class StackComponentState : ComponentState
|
||||
{
|
||||
public int Count { get; }
|
||||
public int MaxCount { get; }
|
||||
@@ -22,4 +115,14 @@ namespace Content.Shared.GameObjects.Components
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum StackType
|
||||
{
|
||||
Metal,
|
||||
Glass,
|
||||
Cable,
|
||||
Ointment,
|
||||
Brutepack,
|
||||
FloorTileSteel
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,5 +41,6 @@
|
||||
public const uint HANDHELD_LIGHT = 1036;
|
||||
public const uint PAPER = 1037;
|
||||
public const uint REAGENT_INJECTOR = 1038;
|
||||
public const uint GHOST = 1039;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,6 @@ namespace Content.Shared.Interfaces.Chemistry
|
||||
/// <param name="reagentId">The reagent id</param>
|
||||
/// <param name="tickTime">The time since the last metabolism tick in seconds.</param>
|
||||
/// <returns>The amount of reagent to be removed. The metabolizing organ should handle removing the reagent.</returns>
|
||||
int Metabolize(IEntity solutionEntity, string reagentId, float tickTime);
|
||||
ReagentUnit Metabolize(IEntity solutionEntity, string reagentId, float tickTime);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user