using Content.Server.Atmos.Reactions;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Reactions;
+using JetBrains.Annotations;
using Robust.Shared.Prototypes;
using DependencyAttribute = Robust.Shared.IoC.DependencyAttribute;
return reaction;
}
+ /// <summary>
+ /// Adds an array of moles to a <see cref="GasMixture"/>.
+ /// Guards against negative moles by clamping to zero.
+ /// </summary>
+ /// <param name="mixture">The <see cref="GasMixture"/> to add moles to.</param>
+ /// <param name="molsToAdd">The <see cref="ReadOnlySpan{T}"/> of moles to add.</param>
+ /// <exception cref="ArgumentOutOfRangeException">Thrown when the length of the <see cref="ReadOnlySpan{T}"/>
+ /// is not the same as the length of the <see cref="GasMixture"/> gas array.</exception>
+ [PublicAPI]
+ public static void AddMolsToMixture(GasMixture mixture, ReadOnlySpan<float> molsToAdd)
+ {
+ // Span length should be as long as the length of the gas array.
+ // Technically this is a redundant check because NumericsHelpers will do the same thing,
+ // but eh.
+ ArgumentOutOfRangeException.ThrowIfNotEqual(mixture.Moles.Length, molsToAdd.Length, nameof(mixture.Moles.Length));
+
+ NumericsHelpers.Add(mixture.Moles, molsToAdd);
+ NumericsHelpers.Max(mixture.Moles, 0f);
+ }
+
public enum GasCompareResult
{
NoExchange = -2,
--- /dev/null
+using System;
+using Content.Server.Atmos.EntitySystems;
+using Content.Shared.Atmos;
+using NUnit.Framework;
+
+namespace Content.Tests.Server.Atmos;
+
+[TestFixture, TestOf(typeof(AtmosphereSystem))]
+[Parallelizable(ParallelScope.All)]
+public sealed class AddMolsToMixtureTest
+{
+ /// <summary>
+ /// Assert that an exception is thrown if the length of the array passed in
+ /// does not match the number of gases.
+ /// </summary>
+ [Test]
+ [TestCase(-1)]
+ [TestCase(1)]
+ public void AddMolsToMixture_Throws_OnLengthMismatch(int num)
+ {
+ var mixture = new GasMixture();
+ var wrongLength = new float[Atmospherics.AdjustedNumberOfGases + num];
+
+ var ex = Assert.Throws<ArgumentOutOfRangeException>(() =>
+ AtmosphereSystem.AddMolsToMixture(mixture, wrongLength));
+
+ Assert.That(ex!.ParamName, Is.EqualTo("Length"));
+ }
+
+ /// <summary>
+ /// Assert that the added mols are correctly added.
+ /// </summary>
+ [Test]
+ public void AddMolsToMixture_Adds_CheckElementwise()
+ {
+ var mixture = new GasMixture();
+ mixture.SetMoles(Gas.Oxygen, 1f);
+ mixture.SetMoles(Gas.Nitrogen, 2f);
+
+ var add = new float[Atmospherics.AdjustedNumberOfGases];
+ add[(int)Gas.Oxygen] = 3f;
+ add[(int)Gas.Nitrogen] = 4f;
+
+ AtmosphereSystem.AddMolsToMixture(mixture, add);
+
+ using (Assert.EnterMultipleScope())
+ {
+ Assert.That(mixture.GetMoles(Gas.Oxygen), Is.EqualTo(4f));
+ Assert.That(mixture.GetMoles(Gas.Nitrogen), Is.EqualTo(6f));
+ }
+ }
+
+ /// <summary>
+ /// Assert that the added mols are correctly clamped at zero.
+ /// </summary>
+ [Test]
+ public void AddMolsToMixture_EnsureClamp()
+ {
+ var mixture = new GasMixture();
+ mixture.SetMoles(Gas.Oxygen, 1f);
+ mixture.SetMoles(Gas.Nitrogen, 2f);
+
+ var add = new float[Atmospherics.AdjustedNumberOfGases];
+ add[(int)Gas.Oxygen] = -2f; // would go to -1 without clamping
+ add[(int)Gas.Nitrogen] = -1f; // should become 1
+
+ AtmosphereSystem.AddMolsToMixture(mixture, add);
+
+ using (Assert.EnterMultipleScope())
+ {
+ Assert.That(mixture.GetMoles(Gas.Oxygen), Is.Zero);
+ Assert.That(mixture.GetMoles(Gas.Nitrogen), Is.EqualTo(1f));
+ }
+ }
+}