Fix AddReagent modifying to solution being added in some cases (#40959)
fix
This commit is contained in:
@@ -37,7 +37,6 @@ namespace Content.Shared.Chemistry.Components
|
||||
/// systems use this.
|
||||
/// </remarks>
|
||||
[DataField("maxVol")]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public FixedPoint2 MaxVolume { get; set; } = FixedPoint2.Zero;
|
||||
|
||||
public float FillFraction => MaxVolume == 0 ? 1 : Volume.Float() / MaxVolume.Float();
|
||||
@@ -45,8 +44,7 @@ namespace Content.Shared.Chemistry.Components
|
||||
/// <summary>
|
||||
/// If reactions will be checked for when adding reagents to the container.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("canReact")]
|
||||
[DataField]
|
||||
public bool CanReact { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
@@ -58,8 +56,7 @@ namespace Content.Shared.Chemistry.Components
|
||||
/// <summary>
|
||||
/// The temperature of the reagents in the solution.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("temperature")]
|
||||
[DataField]
|
||||
public float Temperature { get; set; } = 293.15f;
|
||||
|
||||
/// <summary>
|
||||
@@ -100,7 +97,7 @@ namespace Content.Shared.Chemistry.Components
|
||||
_heatCapacity = 0;
|
||||
foreach (var (reagent, quantity) in Contents)
|
||||
{
|
||||
_heatCapacity += (float) quantity *
|
||||
_heatCapacity += (float)quantity *
|
||||
protoMan.Index<ReagentPrototype>(reagent.Prototype).SpecificHeat;
|
||||
}
|
||||
|
||||
@@ -148,7 +145,7 @@ namespace Content.Shared.Chemistry.Components
|
||||
/// </summary>
|
||||
/// <param name="prototype">The prototype ID of the reagent to add.</param>
|
||||
/// <param name="quantity">The quantity in milli-units.</param>
|
||||
public Solution(string prototype, FixedPoint2 quantity, List<ReagentData>? data = null) : this()
|
||||
public Solution([ForbidLiteral] string prototype, FixedPoint2 quantity, List<ReagentData>? data = null) : this()
|
||||
{
|
||||
AddReagent(new ReagentId(prototype, data), quantity);
|
||||
}
|
||||
@@ -190,7 +187,7 @@ namespace Content.Shared.Chemistry.Components
|
||||
public void ValidateSolution()
|
||||
{
|
||||
// sandbox forbids: [Conditional("DEBUG")]
|
||||
#if DEBUG
|
||||
#if DEBUG
|
||||
// Correct volume
|
||||
DebugTools.Assert(Contents.Select(x => x.Quantity).Sum() == Volume);
|
||||
|
||||
@@ -208,7 +205,7 @@ namespace Content.Shared.Chemistry.Components
|
||||
UpdateHeatCapacity(null);
|
||||
DebugTools.Assert(MathHelper.CloseTo(_heatCapacity, cur, tolerance: 0.01));
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void ISerializationHooks.AfterDeserialization()
|
||||
@@ -223,7 +220,7 @@ namespace Content.Shared.Chemistry.Components
|
||||
MaxVolume = Volume;
|
||||
}
|
||||
|
||||
public bool ContainsPrototype(string prototype)
|
||||
public bool ContainsPrototype([ForbidLiteral] string prototype)
|
||||
{
|
||||
foreach (var (reagent, _) in Contents)
|
||||
{
|
||||
@@ -245,7 +242,7 @@ namespace Content.Shared.Chemistry.Components
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool ContainsReagent(string reagentId, List<ReagentData>? data)
|
||||
public bool ContainsReagent([ForbidLiteral] string reagentId, List<ReagentData>? data)
|
||||
=> ContainsReagent(new(reagentId, data));
|
||||
|
||||
public bool TryGetReagent(ReagentId id, out ReagentQuantity quantity)
|
||||
@@ -352,7 +349,7 @@ namespace Content.Shared.Chemistry.Components
|
||||
/// </summary>
|
||||
/// <param name="prototype">The prototype ID of the reagent to add.</param>
|
||||
/// <param name="quantity">The quantity in milli-units.</param>
|
||||
public void AddReagent(string prototype, FixedPoint2 quantity, bool dirtyHeatCap = true)
|
||||
public void AddReagent([ForbidLiteral] string prototype, FixedPoint2 quantity, bool dirtyHeatCap = true)
|
||||
=> AddReagent(new ReagentId(prototype, null), quantity, dirtyHeatCap);
|
||||
|
||||
/// <summary>
|
||||
@@ -673,6 +670,12 @@ namespace Content.Shared.Chemistry.Components
|
||||
return sol;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Splits a solution into two by moving reagents from the given solution into a new one.
|
||||
/// This modifies the original solution.
|
||||
/// </summary>
|
||||
/// <param name="toTake">The quantity of this solution to remove.</param>
|
||||
/// <returns>A new solution containing the removed reagents.</returns>
|
||||
public Solution SplitSolution(FixedPoint2 toTake)
|
||||
{
|
||||
if (toTake <= FixedPoint2.Zero)
|
||||
@@ -690,7 +693,7 @@ namespace Content.Shared.Chemistry.Components
|
||||
var origVol = Volume;
|
||||
var effVol = Volume.Value;
|
||||
newSolution = new Solution(Contents.Count) { Temperature = Temperature };
|
||||
var remaining = (long) toTake.Value;
|
||||
var remaining = (long)toTake.Value;
|
||||
|
||||
for (var i = Contents.Count - 1; i >= 0; i--) // iterate backwards because of remove swap.
|
||||
{
|
||||
@@ -706,7 +709,7 @@ namespace Content.Shared.Chemistry.Components
|
||||
continue;
|
||||
}
|
||||
|
||||
var splitQuantity = FixedPoint2.FromCents((int) split);
|
||||
var splitQuantity = FixedPoint2.FromCents((int)split);
|
||||
var newQuantity = quantity - splitQuantity;
|
||||
|
||||
DebugTools.Assert(newQuantity >= 0);
|
||||
@@ -753,7 +756,7 @@ namespace Content.Shared.Chemistry.Components
|
||||
|
||||
var effVol = Volume.Value;
|
||||
Volume -= toTake;
|
||||
var remaining = (long) toTake.Value;
|
||||
var remaining = (long)toTake.Value;
|
||||
for (var i = Contents.Count - 1; i >= 0; i--)// iterate backwards because of remove swap.
|
||||
{
|
||||
var (reagent, quantity) = Contents[i];
|
||||
@@ -768,7 +771,7 @@ namespace Content.Shared.Chemistry.Components
|
||||
continue;
|
||||
}
|
||||
|
||||
var splitQuantity = FixedPoint2.FromCents((int) split);
|
||||
var splitQuantity = FixedPoint2.FromCents((int)split);
|
||||
var newQuantity = quantity - splitQuantity;
|
||||
|
||||
if (newQuantity > FixedPoint2.Zero)
|
||||
|
||||
@@ -588,7 +588,7 @@ public abstract partial class SharedSolutionContainerSystem : EntitySystem
|
||||
/// Adds a solution to the container, if it can fully fit.
|
||||
/// </summary>
|
||||
/// <param name="targetUid">entity holding targetSolution</param>
|
||||
/// <param name="targetSolution">entity holding targetSolution</param>
|
||||
/// <param name="targetSolution">entity holding targetSolution</param>
|
||||
/// <param name="toAdd">solution being added</param>
|
||||
/// <returns>If the solution could be added.</returns>
|
||||
public bool TryAddSolution(Entity<SolutionComponent> soln, Solution toAdd)
|
||||
@@ -606,40 +606,44 @@ public abstract partial class SharedSolutionContainerSystem : EntitySystem
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds as much of a solution to a container as can fit.
|
||||
/// Adds as much of a solution to a container as can fit and updates the container.
|
||||
/// </summary>
|
||||
/// <param name="targetUid">The entity containing <paramref cref="targetSolution"/></param>
|
||||
/// <param name="targetSolution">The solution being added to.</param>
|
||||
/// <param name="toAdd">The solution being added to <paramref cref="targetSolution"/></param>
|
||||
/// <param name="toAdd">The solution being added to <paramref cref="targetSolution"/>. This solution is not modified.</param>
|
||||
/// <returns>The quantity of the solution actually added.</returns>
|
||||
public FixedPoint2 AddSolution(Entity<SolutionComponent> soln, Solution toAdd)
|
||||
{
|
||||
var (uid, comp) = soln;
|
||||
var solution = comp.Solution;
|
||||
var solution = soln.Comp.Solution;
|
||||
|
||||
if (toAdd.Volume == FixedPoint2.Zero)
|
||||
return FixedPoint2.Zero;
|
||||
|
||||
var quantity = FixedPoint2.Max(FixedPoint2.Zero, FixedPoint2.Min(toAdd.Volume, solution.AvailableVolume));
|
||||
if (quantity < toAdd.Volume)
|
||||
TryTransferSolution(soln, toAdd, quantity);
|
||||
{
|
||||
// TODO: This should be made into a function that directly transfers reagents.
|
||||
// Currently this is quite inefficient.
|
||||
solution.AddSolution(toAdd.Clone().SplitSolution(quantity), PrototypeManager);
|
||||
}
|
||||
else
|
||||
ForceAddSolution(soln, toAdd);
|
||||
solution.AddSolution(toAdd, PrototypeManager);
|
||||
|
||||
UpdateChemicals(soln);
|
||||
return quantity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a solution to a container and updates the container.
|
||||
/// This can exceed the maximum volume of the solution added to.
|
||||
/// </summary>
|
||||
/// <param name="targetUid">The entity containing <paramref cref="targetSolution"/></param>
|
||||
/// <param name="targetSolution">The solution being added to.</param>
|
||||
/// <param name="toAdd">The solution being added to <paramref cref="targetSolution"/></param>
|
||||
/// <param name="toAdd">The solution being added to <paramref cref="targetSolution"/>. This solution is not modified.</param>
|
||||
/// <returns>Whether any reagents were added to the solution.</returns>
|
||||
public bool ForceAddSolution(Entity<SolutionComponent> soln, Solution toAdd)
|
||||
{
|
||||
var (uid, comp) = soln;
|
||||
var solution = comp.Solution;
|
||||
var solution = soln.Comp.Solution;
|
||||
|
||||
if (toAdd.Volume == FixedPoint2.Zero)
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user