Files
tbd-station-14/Content.IntegrationTests/Tests/Chemistry/SolutionSystemTests.cs
TemporalOroboros d75e743dd7 Solution Entities (#21916)
* Creates Content.Shared.Chemistry.Solutions
Copies Solution class to new namespace
Obsoletes old Solution class

* Switches over to the Solutions.Solution Solution

* Creates Content.Shared.Chemistry.Containers
Copies relevant components/systems to the new namespace
Obsoletes old versions

* Switches over to the Containers.XYZ namespace

* Creates SolutionSystem and obsoletes old SolutionContainerSystem methods

* Start using SolutionSystem for Solution manipulation

* EnumerateSolutions

* Move TryGetMixableSolution

* Move EnsureSolution to Server

* Create Solution Entities

* Stop using obsolete solution system methods

* Fix prototype component tests

* Add using ..Audio.Systems; back

* Wrap solution container slots in ContainerSlots

* Actually add the slot to the solution container map

* Dirty SolutionContainerComponent when ensuring solutions

* Revert namespace changes

* Remerge SolutionSystem and SolutionContainerSystem

* SolutionContainerManagerComponent refactor

* Avoid wrapping necessary code in DebugTools.Assert as it is removed when compiling for release

* Readd examine reagent sorting

* Fix errors

* Poke tests

* Fix solution names not being applied

* Fix WoolyComponent including statement

* Fix merge skew

* Fix compile errors

* Make reactions use solntities

* Reindent solution class namespace

* Field attribute changes

* AutoGenerateComponentState for SolutionContainerComponent

* SolutionContainerComponent -> ContainedSolutionComponent

* ref ReactionAttemptEvent

* Denetwork preinit solutions

* Misc 1

* Nullable TryGetSolution out vars

* Cache associated solutions

* Fix merge skew

* Use explicit regions in SharedSolutionContainerSystem.Capabilities

* Add debug assert

* Use explicit regions in SharedSolutionContainerSystem.Relay + ref SolutionContainerChangedEvent

* ContainedSolutionComponent.Name -> ContainedSolutionComponent.ContainerName

* SolutionComponent doc comments

* Implicit DataField names and property purge

* ReagentEffect DataField names

* Local variables for readability

* Sort using statements + Entity<T> event handlers

* Fix compile erros

* Fix compile errors

---------

Co-authored-by: ElectroJr <leonsfriedrich@gmail.com>
2023-12-28 17:58:14 -08:00

265 lines
9.8 KiB
C#

using Content.Server.Chemistry.Containers.EntitySystems;
using Content.Shared.Chemistry.Components;
using Content.Shared.FixedPoint;
using Robust.Shared.GameObjects;
using Robust.Shared.Prototypes;
namespace Content.IntegrationTests.Tests.Chemistry;
// We are adding two non-reactive solutions in these tests
// To ensure volume(A) + volume(B) = volume(A+B)
// reactions can change this assumption
[TestFixture]
[TestOf(typeof(SolutionContainerSystem))]
public sealed class SolutionSystemTests
{
[TestPrototypes]
private const string Prototypes = @"
- type: entity
id: SolutionTarget
components:
- type: SolutionContainerManager
solutions:
beaker:
maxVol: 50
- type: reagent
id: TestReagentA
name: reagent-name-nothing
desc: reagent-desc-nothing
physicalDesc: reagent-physical-desc-nothing
- type: reagent
id: TestReagentB
name: reagent-name-nothing
desc: reagent-desc-nothing
physicalDesc: reagent-physical-desc-nothing
- type: reagent
id: TestReagentC
specificHeat: 2.0
name: reagent-name-nothing
desc: reagent-desc-nothing
physicalDesc: reagent-physical-desc-nothing
";
[Test]
public async Task TryAddTwoNonReactiveReagent()
{
await using var pair = await PoolManager.GetServerClient();
var server = pair.Server;
var entityManager = server.ResolveDependency<IEntityManager>();
var protoMan = server.ResolveDependency<IPrototypeManager>();
var containerSystem = entityManager.System<SolutionContainerSystem>();
var testMap = await pair.CreateTestMap();
var coordinates = testMap.GridCoords;
EntityUid beaker;
await server.WaitAssertion(() =>
{
var oilQuantity = FixedPoint2.New(15);
var waterQuantity = FixedPoint2.New(10);
var oilAdded = new Solution("Oil", oilQuantity);
var originalWater = new Solution("Water", waterQuantity);
beaker = entityManager.SpawnEntity("SolutionTarget", coordinates);
Assert.That(containerSystem
.TryGetSolution(beaker, "beaker", out var solutionEnt, out var solution));
solution.AddSolution(originalWater, protoMan);
Assert.That(containerSystem
.TryAddSolution(solutionEnt.Value, oilAdded));
var water = solution.GetTotalPrototypeQuantity("Water");
var oil = solution.GetTotalPrototypeQuantity("Oil");
Assert.Multiple(() =>
{
Assert.That(water, Is.EqualTo(waterQuantity));
Assert.That(oil, Is.EqualTo(oilQuantity));
});
});
await pair.CleanReturnAsync();
}
// This test mimics current behavior
// i.e. if adding too much `TryAddSolution` adding will fail
[Test]
public async Task TryAddTooMuchNonReactiveReagent()
{
await using var pair = await PoolManager.GetServerClient();
var server = pair.Server;
var testMap = await pair.CreateTestMap();
var entityManager = server.ResolveDependency<IEntityManager>();
var protoMan = server.ResolveDependency<IPrototypeManager>();
var containerSystem = entityManager.System<SolutionContainerSystem>();
var coordinates = testMap.GridCoords;
EntityUid beaker;
await server.WaitAssertion(() =>
{
var oilQuantity = FixedPoint2.New(1500);
var waterQuantity = FixedPoint2.New(10);
var oilAdded = new Solution("Oil", oilQuantity);
var originalWater = new Solution("Water", waterQuantity);
beaker = entityManager.SpawnEntity("SolutionTarget", coordinates);
Assert.That(containerSystem
.TryGetSolution(beaker, "beaker", out var solutionEnt, out var solution));
solution.AddSolution(originalWater, protoMan);
Assert.That(containerSystem
.TryAddSolution(solutionEnt.Value, oilAdded), Is.False);
var water = solution.GetTotalPrototypeQuantity("Water");
var oil = solution.GetTotalPrototypeQuantity("Oil");
Assert.Multiple(() =>
{
Assert.That(water, Is.EqualTo(waterQuantity));
Assert.That(oil, Is.EqualTo(FixedPoint2.Zero));
});
});
await pair.CleanReturnAsync();
}
// Unlike TryAddSolution this adds and two solution without then splits leaving only threshold in original
[Test]
public async Task TryMixAndOverflowTooMuchReagent()
{
await using var pair = await PoolManager.GetServerClient();
var server = pair.Server;
var entityManager = server.ResolveDependency<IEntityManager>();
var protoMan = server.ResolveDependency<IPrototypeManager>();
var testMap = await pair.CreateTestMap();
var containerSystem = entityManager.System<SolutionContainerSystem>();
var coordinates = testMap.GridCoords;
EntityUid beaker;
await server.WaitAssertion(() =>
{
var ratio = 9;
var threshold = 20;
var waterQuantity = FixedPoint2.New(10);
var oilQuantity = FixedPoint2.New(ratio * waterQuantity.Int());
var oilAdded = new Solution("Oil", oilQuantity);
var originalWater = new Solution("Water", waterQuantity);
beaker = entityManager.SpawnEntity("SolutionTarget", coordinates);
Assert.That(containerSystem
.TryGetSolution(beaker, "beaker", out var solutionEnt, out var solution));
solution.AddSolution(originalWater, protoMan);
Assert.That(containerSystem
.TryMixAndOverflow(solutionEnt.Value, oilAdded, threshold, out var overflowingSolution));
Assert.Multiple(() =>
{
Assert.That(solution.Volume, Is.EqualTo(FixedPoint2.New(threshold)));
var waterMix = solution.GetTotalPrototypeQuantity("Water");
var oilMix = solution.GetTotalPrototypeQuantity("Oil");
Assert.That(waterMix, Is.EqualTo(FixedPoint2.New(threshold / (ratio + 1))));
Assert.That(oilMix, Is.EqualTo(FixedPoint2.New(threshold / (ratio + 1) * ratio)));
Assert.That(overflowingSolution.Volume, Is.EqualTo(FixedPoint2.New(80)));
var waterOverflow = overflowingSolution.GetTotalPrototypeQuantity("Water");
var oilOverFlow = overflowingSolution.GetTotalPrototypeQuantity("Oil");
Assert.That(waterOverflow, Is.EqualTo(waterQuantity - waterMix));
Assert.That(oilOverFlow, Is.EqualTo(oilQuantity - oilMix));
});
});
await pair.CleanReturnAsync();
}
// TryMixAndOverflow will fail if Threshold larger than MaxVolume
[Test]
public async Task TryMixAndOverflowTooBigOverflow()
{
await using var pair = await PoolManager.GetServerClient();
var server = pair.Server;
var entityManager = server.ResolveDependency<IEntityManager>();
var protoMan = server.ResolveDependency<IPrototypeManager>();
var containerSystem = entityManager.System<SolutionContainerSystem>();
var testMap = await pair.CreateTestMap();
var coordinates = testMap.GridCoords;
EntityUid beaker;
await server.WaitAssertion(() =>
{
var ratio = 9;
var threshold = 60;
var waterQuantity = FixedPoint2.New(10);
var oilQuantity = FixedPoint2.New(ratio * waterQuantity.Int());
var oilAdded = new Solution("Oil", oilQuantity);
var originalWater = new Solution("Water", waterQuantity);
beaker = entityManager.SpawnEntity("SolutionTarget", coordinates);
Assert.That(containerSystem
.TryGetSolution(beaker, "beaker", out var solutionEnt, out var solution));
solution.AddSolution(originalWater, protoMan);
Assert.That(containerSystem
.TryMixAndOverflow(solutionEnt.Value, oilAdded, threshold, out _),
Is.False);
});
await pair.CleanReturnAsync();
}
[Test]
public async Task TestTemperatureCalculations()
{
await using var pair = await PoolManager.GetServerClient();
var server = pair.Server;
var protoMan = server.ResolveDependency<IPrototypeManager>();
const float temp = 100.0f;
// Adding reagent with adjusts temperature
await server.WaitAssertion(() =>
{
var solution = new Solution("TestReagentA", FixedPoint2.New(100)) { Temperature = temp };
Assert.That(solution.Temperature, Is.EqualTo(temp * 1));
solution.AddSolution(new Solution("TestReagentA", FixedPoint2.New(100)) { Temperature = temp * 3 }, protoMan);
Assert.That(solution.Temperature, Is.EqualTo(temp * 2));
solution.AddSolution(new Solution("TestReagentB", FixedPoint2.New(100)) { Temperature = temp * 5 }, protoMan);
Assert.That(solution.Temperature, Is.EqualTo(temp * 3));
});
// adding solutions combines thermal energy
await server.WaitAssertion(() =>
{
var solutionOne = new Solution("TestReagentA", FixedPoint2.New(100)) { Temperature = temp };
var solutionTwo = new Solution("TestReagentB", FixedPoint2.New(100)) { Temperature = temp };
solutionTwo.AddReagent("TestReagentC", FixedPoint2.New(100));
var thermalEnergyOne = solutionOne.GetHeatCapacity(protoMan) * solutionOne.Temperature;
var thermalEnergyTwo = solutionTwo.GetHeatCapacity(protoMan) * solutionTwo.Temperature;
solutionOne.AddSolution(solutionTwo, protoMan);
Assert.That(solutionOne.GetHeatCapacity(protoMan) * solutionOne.Temperature, Is.EqualTo(thermalEnergyOne + thermalEnergyTwo));
});
await pair.CleanReturnAsync();
}
}