diff --git a/Content.IntegrationTests/Tests/_Sunrise/Chemistry/CryostasisBeakerTests.cs b/Content.IntegrationTests/Tests/_Sunrise/Chemistry/CryostasisBeakerTests.cs new file mode 100644 index 0000000000..1cfe39864f --- /dev/null +++ b/Content.IntegrationTests/Tests/_Sunrise/Chemistry/CryostasisBeakerTests.cs @@ -0,0 +1,84 @@ +using Content.Shared.Chemistry.Components; +using Content.Shared.Chemistry.EntitySystems; +using Content.Shared.FixedPoint; + +namespace Content.IntegrationTests.Tests._Sunrise.Chemistry; + +[TestFixture] +[TestOf(typeof(CryostasisBeakerSystem))] +public sealed class CryostasisBeakerTests +{ + [TestPrototypes] + private const string Prototypes = @" +- type: entity + id: TestCryostasisBeaker + components: + - type: SolutionContainerManager + solutions: + beaker: + maxVol: 50 + canReact: false + - type: CryostasisBeaker + maxTemperature: 293.15 + +- type: reagent + id: TestReagent + name: reagent-name-nothing + desc: reagent-desc-nothing + physicalDesc: reagent-physical-desc-nothing +"; + + [Test] + public async Task CryostasisBeakerPreventsHeating() + { + await using var pair = await PoolManager.GetServerClient(); + var server = pair.Server; + + var testMap = await pair.CreateTestMap(); + + await server.WaitPost(() => + { + var solutionSystem = server.System(); + + var beaker = server.EntMan.SpawnEntity("TestCryostasisBeaker", testMap.GridCoords); + + Assert.That(solutionSystem.TryGetSolution(beaker, "beaker", out var solutionEntity, out var solution)); + + solutionSystem.TryAddReagent(solutionEntity.Value, "TestReagent", FixedPoint2.New(10)); + + solutionSystem.SetTemperature(solutionEntity.Value, 500.0f); + + Assert.That(solution!.Temperature, Is.LessThanOrEqualTo(293.15f)); + + solutionSystem.AddThermalEnergy(solutionEntity.Value, 10000.0f); + + Assert.That(solution.Temperature, Is.LessThanOrEqualTo(293.15f)); + }); + } + + [Test] + public async Task NormalBeakerAllowsHeating() + { + await using var pair = await PoolManager.GetServerClient(); + var server = pair.Server; + + var testMap = await pair.CreateTestMap(); + + await server.WaitPost(() => + { + var solutionSystem = server.System(); + + var beaker = server.EntMan.SpawnEntity("TestCryostasisBeaker", testMap.GridCoords); + if (server.EntMan.HasComponent(beaker)) + server.EntMan.RemoveComponent(beaker); + + Assert.That(solutionSystem.TryGetSolution(beaker, "beaker", out var solutionEntity, out var solution)); + + solutionSystem.TryAddReagent(solutionEntity.Value, "TestReagent", FixedPoint2.New(10)); + + solutionSystem.SetTemperature(solutionEntity.Value, 500.0f); + + Assert.That(solution!.Temperature, Is.EqualTo(500.0f)); + }); + } +} diff --git a/Content.Shared/Chemistry/Components/CryostasisBeakerComponent.cs b/Content.Shared/Chemistry/Components/CryostasisBeakerComponent.cs new file mode 100644 index 0000000000..cef3e0272f --- /dev/null +++ b/Content.Shared/Chemistry/Components/CryostasisBeakerComponent.cs @@ -0,0 +1,16 @@ +namespace Content.Shared.Chemistry.Components; + +/// +/// Component that marks a beaker as a cryostasis beaker, which prevents solutions inside from being heated. +/// Solutions in cryostasis beakers will remain at or below room temperature (293.15K). +/// +[RegisterComponent] +public sealed partial class CryostasisBeakerComponent : Component +{ + /// + /// Maximum temperature that solutions in this beaker can reach. + /// Default is room temperature (293.15K). + /// + [DataField("maxTemperature")] + public float MaxTemperature = 293.15f; +} \ No newline at end of file diff --git a/Content.Shared/Chemistry/EntitySystems/CryostasisBeakerSystem.cs b/Content.Shared/Chemistry/EntitySystems/CryostasisBeakerSystem.cs new file mode 100644 index 0000000000..9fe4c0af81 --- /dev/null +++ b/Content.Shared/Chemistry/EntitySystems/CryostasisBeakerSystem.cs @@ -0,0 +1,38 @@ +using Content.Shared.Chemistry.Components; +using Content.Shared.Chemistry.EntitySystems; +using Content.Shared.Chemistry.Components.SolutionManager; + +namespace Content.Shared.Chemistry.EntitySystems; + +/// +/// System that prevents solutions in cryostasis beakers from being heated above room temperature. +/// +public sealed class CryostasisBeakerSystem : EntitySystem +{ + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnSolutionChanged); + } + + private void OnSolutionChanged(EntityUid solutionEntity, SolutionComponent solutionComp, ref SolutionChangedEvent args) + { + // Get the container that holds this solution + if (!TryComp(solutionEntity, out var containedSolution)) + return; + + var containerEntity = containedSolution.Container; + + // Check if the container is a CryostasisBeaker + if (!TryComp(containerEntity, out var cryostasisBeaker)) + return; + + var solution = solutionComp.Solution; + + // If the solution temperature is above the maximum allowed, cool it down + if (solution.Temperature > cryostasisBeaker.MaxTemperature) + { + solution.Temperature = cryostasisBeaker.MaxTemperature; + } + } +} \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml b/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml index 62c533bff1..d483c715c0 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml @@ -245,6 +245,10 @@ beaker: maxVol: 60 canReact: false + # Sunrise-Start + - type: CryostasisBeaker + maxTemperature: 293.15 + # Sunrise-End - type: entity name: bluespace beaker