Add SolutionContainerSystem tests (#6726)
This commit is contained in:
195
Content.IntegrationTests/Tests/Chemistry/SolutionSystemTests.cs
Normal file
195
Content.IntegrationTests/Tests/Chemistry/SolutionSystemTests.cs
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using Content.Server.Chemistry.EntitySystems;
|
||||||
|
using Content.Shared.Chemistry.Components;
|
||||||
|
using Content.Shared.FixedPoint;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Map;
|
||||||
|
|
||||||
|
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 : ContentIntegrationTest
|
||||||
|
{
|
||||||
|
private const string Prototypes = @"
|
||||||
|
- type: entity
|
||||||
|
id: SolutionTarget
|
||||||
|
components:
|
||||||
|
- type: SolutionContainerManager
|
||||||
|
solutions:
|
||||||
|
beaker:
|
||||||
|
maxVol: 50
|
||||||
|
";
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task TryAddTwoNonReactiveReagent()
|
||||||
|
{
|
||||||
|
var options = new ServerContentIntegrationOption { ExtraPrototypes = Prototypes };
|
||||||
|
var server = StartServer(options);
|
||||||
|
|
||||||
|
await server.WaitIdleAsync();
|
||||||
|
|
||||||
|
var entityManager = server.ResolveDependency<IEntityManager>();
|
||||||
|
var mapManager = server.ResolveDependency<IMapManager>();
|
||||||
|
var coordinates = GetMainEntityCoordinates(mapManager);
|
||||||
|
|
||||||
|
EntityUid beaker;
|
||||||
|
|
||||||
|
server.Assert(() =>
|
||||||
|
{
|
||||||
|
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(EntitySystem.Get<SolutionContainerSystem>()
|
||||||
|
.TryGetSolution(beaker, "beaker", out var solution));
|
||||||
|
|
||||||
|
solution.AddSolution(originalWater);
|
||||||
|
Assert.That(EntitySystem.Get<SolutionContainerSystem>()
|
||||||
|
.TryAddSolution(beaker, solution, oilAdded));
|
||||||
|
|
||||||
|
solution.ContainsReagent("Water", out var water);
|
||||||
|
solution.ContainsReagent("Oil", out var oil);
|
||||||
|
Assert.That(water, Is.EqualTo(waterQuantity));
|
||||||
|
Assert.That(oil, Is.EqualTo(oilQuantity));
|
||||||
|
});
|
||||||
|
|
||||||
|
await server.WaitIdleAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This test mimics current behavior
|
||||||
|
// i.e. if adding too much `TryAddSolution` adding will fail
|
||||||
|
[Test]
|
||||||
|
public async Task TryAddTooMuchNonReactiveReagent()
|
||||||
|
{
|
||||||
|
var options = new ServerContentIntegrationOption { ExtraPrototypes = Prototypes };
|
||||||
|
var server = StartServer(options);
|
||||||
|
|
||||||
|
await server.WaitIdleAsync();
|
||||||
|
|
||||||
|
var entityManager = server.ResolveDependency<IEntityManager>();
|
||||||
|
var mapManager = server.ResolveDependency<IMapManager>();
|
||||||
|
var coordinates = GetMainEntityCoordinates(mapManager);
|
||||||
|
|
||||||
|
EntityUid beaker;
|
||||||
|
|
||||||
|
server.Assert(() =>
|
||||||
|
{
|
||||||
|
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(EntitySystem.Get<SolutionContainerSystem>()
|
||||||
|
.TryGetSolution(beaker, "beaker", out var solution));
|
||||||
|
|
||||||
|
solution.AddSolution(originalWater);
|
||||||
|
Assert.That(EntitySystem.Get<SolutionContainerSystem>()
|
||||||
|
.TryAddSolution(beaker, solution, oilAdded), Is.False);
|
||||||
|
|
||||||
|
solution.ContainsReagent("Water", out var water);
|
||||||
|
solution.ContainsReagent("Oil", out var oil);
|
||||||
|
Assert.That(water, Is.EqualTo(waterQuantity));
|
||||||
|
Assert.That(oil, Is.EqualTo(FixedPoint2.Zero));
|
||||||
|
});
|
||||||
|
|
||||||
|
await server.WaitIdleAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unlike TryAddSolution this adds and two solution without then splits leaving only threshold in original
|
||||||
|
[Test]
|
||||||
|
public async Task TryMixAndOverflowTooMuchReagent()
|
||||||
|
{
|
||||||
|
var options = new ServerContentIntegrationOption { ExtraPrototypes = Prototypes };
|
||||||
|
var server = StartServer(options);
|
||||||
|
|
||||||
|
await server.WaitIdleAsync();
|
||||||
|
|
||||||
|
var entityManager = server.ResolveDependency<IEntityManager>();
|
||||||
|
var mapManager = server.ResolveDependency<IMapManager>();
|
||||||
|
var coordinates = GetMainEntityCoordinates(mapManager);
|
||||||
|
|
||||||
|
EntityUid beaker;
|
||||||
|
|
||||||
|
server.Assert(() =>
|
||||||
|
{
|
||||||
|
int ratio = 9;
|
||||||
|
int 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(EntitySystem.Get<SolutionContainerSystem>()
|
||||||
|
.TryGetSolution(beaker, "beaker", out var solution));
|
||||||
|
|
||||||
|
solution.AddSolution(originalWater);
|
||||||
|
Assert.That(EntitySystem.Get<SolutionContainerSystem>()
|
||||||
|
.TryMixAndOverflow(beaker, solution, oilAdded, threshold, out var overflowingSolution));
|
||||||
|
|
||||||
|
Assert.That(solution.CurrentVolume, Is.EqualTo(FixedPoint2.New(threshold)));
|
||||||
|
solution.ContainsReagent("Water", out var waterMix);
|
||||||
|
solution.ContainsReagent("Oil", out var oilMix);
|
||||||
|
Assert.That(waterMix, Is.EqualTo(FixedPoint2.New(threshold / (ratio + 1))));
|
||||||
|
Assert.That(oilMix, Is.EqualTo(FixedPoint2.New(threshold / (ratio + 1) * ratio)));
|
||||||
|
|
||||||
|
Assert.That(overflowingSolution.CurrentVolume, Is.EqualTo(FixedPoint2.New(80)));
|
||||||
|
overflowingSolution.ContainsReagent("Water", out var waterOverflow);
|
||||||
|
overflowingSolution.ContainsReagent("Oil", out var oilOverFlow);
|
||||||
|
Assert.That(waterOverflow, Is.EqualTo(waterQuantity - waterMix));
|
||||||
|
Assert.That(oilOverFlow, Is.EqualTo(oilQuantity - oilMix));
|
||||||
|
});
|
||||||
|
|
||||||
|
await server.WaitIdleAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TryMixAndOverflow will fail if Threshold larger than MaxVolume
|
||||||
|
[Test]
|
||||||
|
public async Task TryMixAndOverflowTooBigOverflow()
|
||||||
|
{
|
||||||
|
var options = new ServerContentIntegrationOption { ExtraPrototypes = Prototypes };
|
||||||
|
var server = StartServer(options);
|
||||||
|
|
||||||
|
await server.WaitIdleAsync();
|
||||||
|
|
||||||
|
var entityManager = server.ResolveDependency<IEntityManager>();
|
||||||
|
var mapManager = server.ResolveDependency<IMapManager>();
|
||||||
|
var coordinates = GetMainEntityCoordinates(mapManager);
|
||||||
|
|
||||||
|
EntityUid beaker;
|
||||||
|
|
||||||
|
server.Assert(() =>
|
||||||
|
{
|
||||||
|
int ratio = 9;
|
||||||
|
int 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(EntitySystem.Get<SolutionContainerSystem>()
|
||||||
|
.TryGetSolution(beaker, "beaker", out var solution));
|
||||||
|
|
||||||
|
solution.AddSolution(originalWater);
|
||||||
|
Assert.That(EntitySystem.Get<SolutionContainerSystem>()
|
||||||
|
.TryMixAndOverflow(beaker, solution, oilAdded, threshold, out _),
|
||||||
|
Is.False);
|
||||||
|
});
|
||||||
|
|
||||||
|
await server.WaitIdleAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,16 +1,13 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Content.Server.Chemistry.Components.SolutionManager;
|
using Content.Server.Chemistry.Components.SolutionManager;
|
||||||
using Content.Server.Database;
|
|
||||||
using Content.Shared.Chemistry.Components;
|
using Content.Shared.Chemistry.Components;
|
||||||
using Content.Shared.Chemistry.Reagent;
|
|
||||||
using Content.Shared.FixedPoint;
|
using Content.Shared.FixedPoint;
|
||||||
using Robust.Shared.GameObjects;
|
|
||||||
|
|
||||||
namespace Content.Server.Chemistry.EntitySystems
|
namespace Content.Server.Chemistry.EntitySystems;
|
||||||
|
|
||||||
|
public sealed partial class SolutionContainerSystem
|
||||||
{
|
{
|
||||||
public sealed partial class SolutionContainerSystem
|
|
||||||
{
|
|
||||||
public void Refill(EntityUid targetUid, Solution targetSolution, Solution addedSolution,
|
public void Refill(EntityUid targetUid, Solution targetSolution, Solution addedSolution,
|
||||||
RefillableSolutionComponent? refillableSolution = null)
|
RefillableSolutionComponent? refillableSolution = null)
|
||||||
{
|
{
|
||||||
@@ -146,11 +143,11 @@ namespace Content.Server.Chemistry.EntitySystems
|
|||||||
{
|
{
|
||||||
sb.Append(", ");
|
sb.Append(", ");
|
||||||
}
|
}
|
||||||
sb.AppendFormat("{0}: {1}u", id, quantity);
|
|
||||||
|
|
||||||
|
sb.AppendFormat("{0}: {1}u", id, quantity);
|
||||||
}
|
}
|
||||||
|
|
||||||
sb.Append(']');
|
sb.Append(']');
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using Content.Server.Chemistry.Components.SolutionManager;
|
using Content.Server.Chemistry.Components.SolutionManager;
|
||||||
using Content.Server.Fluids.Components;
|
|
||||||
using Content.Shared.Chemistry;
|
using Content.Shared.Chemistry;
|
||||||
using Content.Shared.Chemistry.Components;
|
using Content.Shared.Chemistry.Components;
|
||||||
using Content.Shared.Chemistry.Reaction;
|
using Content.Shared.Chemistry.Reaction;
|
||||||
@@ -10,28 +7,24 @@ using Content.Shared.Chemistry.Reagent;
|
|||||||
using Content.Shared.Examine;
|
using Content.Shared.Examine;
|
||||||
using Content.Shared.FixedPoint;
|
using Content.Shared.FixedPoint;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Shared.GameObjects;
|
|
||||||
using Robust.Shared.IoC;
|
|
||||||
using Robust.Shared.Localization;
|
|
||||||
using Robust.Shared.Log;
|
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.Server.Chemistry.EntitySystems
|
namespace Content.Server.Chemistry.EntitySystems;
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This event alerts system that the solution was changed
|
|
||||||
/// </summary>
|
|
||||||
public sealed class SolutionChangedEvent : EntityEventArgs
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Part of Chemistry system deal with SolutionContainers
|
/// This event alerts system that the solution was changed
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[UsedImplicitly]
|
public sealed class SolutionChangedEvent : EntityEventArgs
|
||||||
public sealed partial class SolutionContainerSystem : EntitySystem
|
{
|
||||||
{
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Part of Chemistry system deal with SolutionContainers
|
||||||
|
/// </summary>
|
||||||
|
[UsedImplicitly]
|
||||||
|
public sealed partial class SolutionContainerSystem : EntitySystem
|
||||||
|
{
|
||||||
[Dependency]
|
[Dependency]
|
||||||
private readonly SharedChemicalReactionSystem _chemistrySystem = default!;
|
private readonly SharedChemicalReactionSystem _chemistrySystem = default!;
|
||||||
|
|
||||||
@@ -105,7 +98,8 @@ namespace Content.Server.Chemistry.EntitySystems
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
var filledVolumePercent = solution.CurrentVolume.Float() / solution.MaxVolume.Float();
|
var filledVolumePercent = solution.CurrentVolume.Float() / solution.MaxVolume.Float();
|
||||||
appearanceComponent.SetData(SolutionContainerVisuals.VisualState, new SolutionContainerVisualState(solution.Color, filledVolumePercent));
|
appearanceComponent.SetData(SolutionContainerVisuals.VisualState,
|
||||||
|
new SolutionContainerVisualState(solution.Color, filledVolumePercent));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -231,12 +225,14 @@ namespace Content.Server.Chemistry.EntitySystems
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a solution to the container, overflowing the rest.
|
/// Adds a solution to the container, overflowing the rest.
|
||||||
/// Unlike TryAddSolution it will ignore size limits.
|
/// It will
|
||||||
|
/// Unlike <see cref="TryAddSolution"/> it will ignore size limits.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="targetUid">entity holding targetSolution</param>
|
/// <param name="targetUid">entity holding targetSolution</param>
|
||||||
/// <param name="targetSolution">The container to which we try to add.</param>
|
/// <param name="targetSolution">The container to which we try to add.</param>
|
||||||
/// <param name="addedSolution">solution being added</param>
|
/// <param name="addedSolution">solution being added</param>
|
||||||
/// <param name="overflowThreshold">After addition this much will be left in targetSolution</param>
|
/// <param name="overflowThreshold">After addition this much will be left in targetSolution. Should be less
|
||||||
|
/// than targetSolution.TotalVolume</param>
|
||||||
/// <param name="overflowingSolution">Solution that exceeded overflowThreshold</param>
|
/// <param name="overflowingSolution">Solution that exceeded overflowThreshold</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public bool TryMixAndOverflow(EntityUid targetUid, Solution targetSolution,
|
public bool TryMixAndOverflow(EntityUid targetUid, Solution targetSolution,
|
||||||
@@ -244,7 +240,7 @@ namespace Content.Server.Chemistry.EntitySystems
|
|||||||
FixedPoint2 overflowThreshold,
|
FixedPoint2 overflowThreshold,
|
||||||
[NotNullWhen(true)] out Solution? overflowingSolution)
|
[NotNullWhen(true)] out Solution? overflowingSolution)
|
||||||
{
|
{
|
||||||
if (addedSolution.TotalVolume == 0)
|
if (addedSolution.TotalVolume == 0 || overflowThreshold > targetSolution.MaxVolume)
|
||||||
{
|
{
|
||||||
overflowingSolution = null;
|
overflowingSolution = null;
|
||||||
return false;
|
return false;
|
||||||
@@ -342,6 +338,7 @@ namespace Content.Server.Chemistry.EntitySystems
|
|||||||
|
|
||||||
|
|
||||||
// Thermal energy and temperature management.
|
// Thermal energy and temperature management.
|
||||||
|
|
||||||
#region Thermal Energy and Temperature
|
#region Thermal Energy and Temperature
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -390,5 +387,4 @@ namespace Content.Server.Chemistry.EntitySystems
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion Thermal Energy and Temperature
|
#endregion Thermal Energy and Temperature
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
using Content.Shared.Chemistry.Components;
|
using Content.Shared.Chemistry.Components;
|
||||||
using Content.Shared.Chemistry.Reagent;
|
|
||||||
using Content.Shared.FixedPoint;
|
using Content.Shared.FixedPoint;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace Content.Tests.Shared.Chemistry
|
namespace Content.Tests.Shared.Chemistry;
|
||||||
|
|
||||||
|
[TestFixture, Parallelizable, TestOf(typeof(Solution))]
|
||||||
|
public sealed class Solution_Tests : ContentUnitTest
|
||||||
{
|
{
|
||||||
[TestFixture, Parallelizable, TestOf(typeof(Solution))]
|
|
||||||
public sealed class Solution_Tests : ContentUnitTest
|
|
||||||
{
|
|
||||||
[OneTimeSetUp]
|
[OneTimeSetUp]
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
@@ -353,6 +352,7 @@ namespace Content.Tests.Shared.Chemistry
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Tests concerning thermal energy and temperature.
|
// Tests concerning thermal energy and temperature.
|
||||||
|
|
||||||
#region Thermal Energy and Temperature
|
#region Thermal Energy and Temperature
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -480,5 +480,4 @@ namespace Content.Tests.Shared.Chemistry
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion Thermal Energy and Temperature
|
#endregion Thermal Energy and Temperature
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user