diff --git a/Content.Client/Administration/UI/ManageSolutions/AddReagentWindow.xaml.cs b/Content.Client/Administration/UI/ManageSolutions/AddReagentWindow.xaml.cs index 1ded5cebb3..cf7c8c5058 100644 --- a/Content.Client/Administration/UI/ManageSolutions/AddReagentWindow.xaml.cs +++ b/Content.Client/Administration/UI/ManageSolutions/AddReagentWindow.xaml.cs @@ -4,6 +4,9 @@ using Robust.Client.Console; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.CustomControls; using Robust.Client.UserInterface.XAML; +using Robust.Shared.GameObjects; +using Robust.Shared.IoC; +using Robust.Shared.Localization; using Robust.Shared.Prototypes; namespace Content.Client.Administration.UI.ManageSolutions diff --git a/Content.Client/Administration/UI/ManageSolutions/EditSolutionsWindow.xaml.cs b/Content.Client/Administration/UI/ManageSolutions/EditSolutionsWindow.xaml.cs index ecc26d6026..d2dda0ccbd 100644 --- a/Content.Client/Administration/UI/ManageSolutions/EditSolutionsWindow.xaml.cs +++ b/Content.Client/Administration/UI/ManageSolutions/EditSolutionsWindow.xaml.cs @@ -20,7 +20,7 @@ namespace Content.Client.Administration.UI.ManageSolutions private NetEntity _target = NetEntity.Invalid; private string? _selectedSolution; private AddReagentWindow? _addReagentWindow; - private Dictionary? _solutions; + private Dictionary? _solutions; public EditSolutionsWindow() { @@ -60,11 +60,9 @@ namespace Content.Client.Administration.UI.ManageSolutions if (_selectedSolution == null || _solutions == null) return; - if (!_solutions.TryGetValue(_selectedSolution, out var solutionId) || - !_entityManager.TryGetComponent(solutionId, out SolutionComponent? solutionComp)) + if (!_solutions.TryGetValue(_selectedSolution, out var solution)) return; - var solution = solutionComp.Solution; UpdateVolumeBox(solution); UpdateThermalBox(solution); @@ -200,13 +198,10 @@ namespace Content.Client.Administration.UI.ManageSolutions /// private void SetReagent(FloatSpinBox.FloatSpinBoxEventArgs args, string prototype) { - if (_solutions == null || _selectedSolution == null || - !_solutions.TryGetValue(_selectedSolution, out var solutionId) || - !_entityManager.TryGetComponent(solutionId, out SolutionComponent? solutionComp)) + if (_solutions == null || _selectedSolution == null) return; - var solution = solutionComp.Solution; - var current = solution.GetTotalPrototypeQuantity(prototype); + var current = _solutions[_selectedSolution].GetTotalPrototypeQuantity(prototype); var delta = args.Value - current.Float(); if (MathF.Abs(delta) < 0.01) @@ -280,38 +275,22 @@ namespace Content.Client.Administration.UI.ManageSolutions /// /// Update the solution options. /// - public void UpdateSolutions(List<(string, NetEntity)>? solutions) + public void UpdateSolutions(Dictionary? solutions) { SolutionOption.Clear(); - - if (solutions is { Count: > 0 }) - { - if (_solutions is { Count: > 0 }) - _solutions.Clear(); - else - _solutions = new(solutions.Count); - - foreach (var (name, netSolution) in solutions) - { - if (_entityManager.TryGetEntity(netSolution, out var solution)) - _solutions.Add(name, solution.Value); - } - } - else - _solutions = null; + _solutions = solutions; if (_solutions == null) return; int i = 0; - int selectedIndex = 0; // Default to the first solution if none are found. - foreach (var (name, _) in _solutions) + foreach (var solution in _solutions.Keys) { - SolutionOption.AddItem(name, i); - SolutionOption.SetItemMetadata(i, name); + SolutionOption.AddItem(solution, i); + SolutionOption.SetItemMetadata(i, solution); - if (name == _selectedSolution) - selectedIndex = i; + if (solution == _selectedSolution) + SolutionOption.Select(i); i++; } @@ -321,11 +300,14 @@ namespace Content.Client.Administration.UI.ManageSolutions // No applicable solutions Close(); Dispose(); - return; } - SolutionOption.Select(selectedIndex); - _selectedSolution = (string?) SolutionOption.SelectedMetadata; + if (_selectedSolution == null || !_solutions.ContainsKey(_selectedSolution)) + { + // the previously selected solution is no longer valid. + SolutionOption.Select(0); + _selectedSolution = (string?) SolutionOption.SelectedMetadata; + } } } } diff --git a/Content.Client/Chemistry/Containers/EntitySystems/SolutionContainerSystem.cs b/Content.Client/Chemistry/Containers/EntitySystems/SolutionContainerSystem.cs deleted file mode 100644 index 0c38d605d2..0000000000 --- a/Content.Client/Chemistry/Containers/EntitySystems/SolutionContainerSystem.cs +++ /dev/null @@ -1,7 +0,0 @@ -using Content.Shared.Chemistry.EntitySystems; - -namespace Content.Client.Chemistry.Containers.EntitySystems; - -public sealed partial class SolutionContainerSystem : SharedSolutionContainerSystem -{ -} diff --git a/Content.Client/Kitchen/UI/GrinderMenu.xaml.cs b/Content.Client/Kitchen/UI/GrinderMenu.xaml.cs index 6e4b7a7618..1822dd7fff 100644 --- a/Content.Client/Kitchen/UI/GrinderMenu.xaml.cs +++ b/Content.Client/Kitchen/UI/GrinderMenu.xaml.cs @@ -1,9 +1,11 @@ using Content.Client.UserInterface.Controls; +using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Reagent; using Content.Shared.Kitchen; using Robust.Client.AutoGenerated; using Robust.Client.GameObjects; using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.CustomControls; using Robust.Client.UserInterface.XAML; using Robust.Shared.Prototypes; @@ -13,7 +15,7 @@ namespace Content.Client.Kitchen.UI public sealed partial class GrinderMenu : FancyWindow { private readonly IEntityManager _entityManager; - private readonly IPrototypeManager _prototypeManager; + private readonly IPrototypeManager _prototypeManager ; private readonly ReagentGrinderBoundUserInterface _owner; private readonly Dictionary _chamberVisualContents = new(); @@ -120,8 +122,8 @@ namespace Content.Client.Kitchen.UI { foreach (var (reagent, quantity) in reagents) { - var reagentName = _prototypeManager.TryIndex(reagent.Prototype, out ReagentPrototype? proto) - ? Loc.GetString($"{quantity} {proto.LocalizedName}") + var reagentName = _prototypeManager.TryIndex(reagent.Prototype, out ReagentPrototype? proto) + ? Loc.GetString($"{quantity} {proto.LocalizedName}") : "???"; BeakerContentBox.BoxContents.AddItem(reagentName); } diff --git a/Content.Client/Kitchen/UI/MicrowaveBoundUserInterface.cs b/Content.Client/Kitchen/UI/MicrowaveBoundUserInterface.cs index 74579b2699..518fbe095e 100644 --- a/Content.Client/Kitchen/UI/MicrowaveBoundUserInterface.cs +++ b/Content.Client/Kitchen/UI/MicrowaveBoundUserInterface.cs @@ -1,9 +1,11 @@ +using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Reagent; using Content.Shared.Kitchen.Components; using JetBrains.Annotations; using Robust.Client.GameObjects; using Robust.Client.Graphics; using Robust.Client.UserInterface.Controls; +using Robust.Shared.Graphics; namespace Content.Client.Kitchen.UI { diff --git a/Content.IntegrationTests/Tests/Chemistry/SolutionSystemTests.cs b/Content.IntegrationTests/Tests/Chemistry/SolutionSystemTests.cs index d96a035b2d..064ce46934 100644 --- a/Content.IntegrationTests/Tests/Chemistry/SolutionSystemTests.cs +++ b/Content.IntegrationTests/Tests/Chemistry/SolutionSystemTests.cs @@ -1,5 +1,5 @@ -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Shared.Chemistry.Components; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.FixedPoint; using Robust.Shared.GameObjects; using Robust.Shared.Prototypes; @@ -51,7 +51,7 @@ public sealed class SolutionSystemTests var entityManager = server.ResolveDependency(); var protoMan = server.ResolveDependency(); - var containerSystem = entityManager.System(); + var containerSystem = entityManager.EntitySysManager.GetEntitySystem(); var testMap = await pair.CreateTestMap(); var coordinates = testMap.GridCoords; @@ -67,11 +67,11 @@ public sealed class SolutionSystemTests beaker = entityManager.SpawnEntity("SolutionTarget", coordinates); Assert.That(containerSystem - .TryGetSolution(beaker, "beaker", out var solutionEnt, out var solution)); + .TryGetSolution(beaker, "beaker", out var solution)); solution.AddSolution(originalWater, protoMan); Assert.That(containerSystem - .TryAddSolution(solutionEnt.Value, oilAdded)); + .TryAddSolution(beaker, solution, oilAdded)); var water = solution.GetTotalPrototypeQuantity("Water"); var oil = solution.GetTotalPrototypeQuantity("Oil"); @@ -97,7 +97,7 @@ public sealed class SolutionSystemTests var entityManager = server.ResolveDependency(); var protoMan = server.ResolveDependency(); - var containerSystem = entityManager.System(); + var containerSystem = entityManager.EntitySysManager.GetEntitySystem(); var coordinates = testMap.GridCoords; EntityUid beaker; @@ -112,11 +112,11 @@ public sealed class SolutionSystemTests beaker = entityManager.SpawnEntity("SolutionTarget", coordinates); Assert.That(containerSystem - .TryGetSolution(beaker, "beaker", out var solutionEnt, out var solution)); + .TryGetSolution(beaker, "beaker", out var solution)); solution.AddSolution(originalWater, protoMan); Assert.That(containerSystem - .TryAddSolution(solutionEnt.Value, oilAdded), Is.False); + .TryAddSolution(beaker, solution, oilAdded), Is.False); var water = solution.GetTotalPrototypeQuantity("Water"); var oil = solution.GetTotalPrototypeQuantity("Oil"); @@ -141,7 +141,7 @@ public sealed class SolutionSystemTests var entityManager = server.ResolveDependency(); var protoMan = server.ResolveDependency(); var testMap = await pair.CreateTestMap(); - var containerSystem = entityManager.System(); + var containerSystem = entityManager.EntitySysManager.GetEntitySystem(); var coordinates = testMap.GridCoords; EntityUid beaker; @@ -158,11 +158,11 @@ public sealed class SolutionSystemTests beaker = entityManager.SpawnEntity("SolutionTarget", coordinates); Assert.That(containerSystem - .TryGetSolution(beaker, "beaker", out var solutionEnt, out var solution)); + .TryGetSolution(beaker, "beaker", out var solution)); solution.AddSolution(originalWater, protoMan); Assert.That(containerSystem - .TryMixAndOverflow(solutionEnt.Value, oilAdded, threshold, out var overflowingSolution)); + .TryMixAndOverflow(beaker, solution, oilAdded, threshold, out var overflowingSolution)); Assert.Multiple(() => { @@ -194,7 +194,7 @@ public sealed class SolutionSystemTests var entityManager = server.ResolveDependency(); var protoMan = server.ResolveDependency(); - var containerSystem = entityManager.System(); + var containerSystem = entityManager.EntitySysManager.GetEntitySystem(); var testMap = await pair.CreateTestMap(); var coordinates = testMap.GridCoords; @@ -212,11 +212,11 @@ public sealed class SolutionSystemTests beaker = entityManager.SpawnEntity("SolutionTarget", coordinates); Assert.That(containerSystem - .TryGetSolution(beaker, "beaker", out var solutionEnt, out var solution)); + .TryGetSolution(beaker, "beaker", out var solution)); solution.AddSolution(originalWater, protoMan); Assert.That(containerSystem - .TryMixAndOverflow(solutionEnt.Value, oilAdded, threshold, out _), + .TryMixAndOverflow(beaker, solution, oilAdded, threshold, out _), Is.False); }); diff --git a/Content.IntegrationTests/Tests/Chemistry/TryAllReactionsTest.cs b/Content.IntegrationTests/Tests/Chemistry/TryAllReactionsTest.cs index ddfe7b3481..5213747588 100644 --- a/Content.IntegrationTests/Tests/Chemistry/TryAllReactionsTest.cs +++ b/Content.IntegrationTests/Tests/Chemistry/TryAllReactionsTest.cs @@ -1,11 +1,11 @@ -using Content.Server.Chemistry.Containers.EntitySystems; -using Content.Shared.Chemistry.Reaction; +using System.Linq; using Content.Shared.Chemistry.Components; +using Content.Shared.Chemistry.EntitySystems; +using Content.Shared.Chemistry.Reaction; using Robust.Shared.GameObjects; using Robust.Shared.Map; using Robust.Shared.Prototypes; using Robust.Shared.Utility; -using System.Linq; namespace Content.IntegrationTests.Tests.Chemistry { @@ -34,7 +34,8 @@ namespace Content.IntegrationTests.Tests.Chemistry var prototypeManager = server.ResolveDependency(); var testMap = await pair.CreateTestMap(); var coordinates = testMap.GridCoords; - var solutionContainerSystem = entityManager.System(); + var solutionSystem = server.ResolveDependency() + .GetEntitySystem(); foreach (var reactionPrototype in prototypeManager.EnumeratePrototypes()) { @@ -42,31 +43,30 @@ namespace Content.IntegrationTests.Tests.Chemistry Console.WriteLine($"Testing {reactionPrototype.ID}"); EntityUid beaker = default; - Entity? solutionEnt = default!; - Solution solution = null; + Solution component = null; await server.WaitAssertion(() => { beaker = entityManager.SpawnEntity("TestSolutionContainer", coordinates); - Assert.That(solutionContainerSystem - .TryGetSolution(beaker, "beaker", out solutionEnt, out solution)); + Assert.That(solutionSystem + .TryGetSolution(beaker, "beaker", out component)); foreach (var (id, reactant) in reactionPrototype.Reactants) { #pragma warning disable NUnit2045 - Assert.That(solutionContainerSystem - .TryAddReagent(solutionEnt.Value, id, reactant.Amount, out var quantity)); + Assert.That(solutionSystem + .TryAddReagent(beaker, component, id, reactant.Amount, out var quantity)); Assert.That(reactant.Amount, Is.EqualTo(quantity)); #pragma warning restore NUnit2045 } - solutionContainerSystem.SetTemperature(solutionEnt.Value, reactionPrototype.MinimumTemperature); + solutionSystem.SetTemperature(beaker, component, reactionPrototype.MinimumTemperature); if (reactionPrototype.MixingCategories != null) { var dummyEntity = entityManager.SpawnEntity(null, MapCoordinates.Nullspace); var mixerComponent = entityManager.AddComponent(dummyEntity); mixerComponent.ReactionTypes = reactionPrototype.MixingCategories; - solutionContainerSystem.UpdateChemicals(solutionEnt.Value, true, mixerComponent); + solutionSystem.UpdateChemicals(beaker, component, true, mixerComponent); } }); @@ -79,7 +79,7 @@ namespace Content.IntegrationTests.Tests.Chemistry var foundProductsMap = reactionPrototype.Products .Concat(reactionPrototype.Reactants.Where(x => x.Value.Catalyst).ToDictionary(x => x.Key, x => x.Value.Amount)) .ToDictionary(x => x, _ => false); - foreach (var (reagent, quantity) in solution.Contents) + foreach (var (reagent, quantity) in component.Contents) { Assert.That(foundProductsMap.TryFirstOrNull(x => x.Key.Key == reagent.Prototype && x.Key.Value == quantity, out var foundProduct)); foundProductsMap[foundProduct.Value.Key] = true; diff --git a/Content.IntegrationTests/Tests/Fluids/AbsorbentTest.cs b/Content.IntegrationTests/Tests/Fluids/AbsorbentTest.cs index 87ef41fe96..de5226202c 100644 --- a/Content.IntegrationTests/Tests/Fluids/AbsorbentTest.cs +++ b/Content.IntegrationTests/Tests/Fluids/AbsorbentTest.cs @@ -80,7 +80,7 @@ public sealed class AbsorbentTest var entityManager = server.ResolveDependency(); var absorbentSystem = entityManager.System(); - var solutionContainerSystem = entityManager.System(); + var solutionContainerSystem = entityManager.System(); var prototypeManager = server.ResolveDependency(); EntityUid user = default; @@ -94,19 +94,19 @@ public sealed class AbsorbentTest refillable = entityManager.SpawnEntity(RefillableDummyId, coordinates); entityManager.TryGetComponent(absorbent, out component); - solutionContainerSystem.TryGetSolution(absorbent, AbsorbentComponent.SolutionName, out var absorbentSoln, out var absorbentSolution); - solutionContainerSystem.TryGetRefillableSolution(refillable, out var refillableSoln, out var refillableSolution); + solutionContainerSystem.TryGetSolution(absorbent, AbsorbentComponent.SolutionName, out var absorbentSolution); + solutionContainerSystem.TryGetRefillableSolution(refillable, out var refillableSolution); // Arrange if (testCase.InitialAbsorbentSolution.VolumeOfEvaporable > FixedPoint2.Zero) - solutionContainerSystem.AddSolution(absorbentSoln.Value, new Solution(EvaporablePrototypeId, testCase.InitialAbsorbentSolution.VolumeOfEvaporable)); + solutionContainerSystem.AddSolution(absorbent, absorbentSolution, new Solution(EvaporablePrototypeId, testCase.InitialAbsorbentSolution.VolumeOfEvaporable)); if (testCase.InitialAbsorbentSolution.VolumeOfNonEvaporable > FixedPoint2.Zero) - solutionContainerSystem.AddSolution(absorbentSoln.Value, new Solution(NonEvaporablePrototypeId, testCase.InitialAbsorbentSolution.VolumeOfNonEvaporable)); + solutionContainerSystem.AddSolution(absorbent, absorbentSolution, new Solution(NonEvaporablePrototypeId, testCase.InitialAbsorbentSolution.VolumeOfNonEvaporable)); if (testCase.InitialRefillableSolution.VolumeOfEvaporable > FixedPoint2.Zero) - solutionContainerSystem.AddSolution(refillableSoln.Value, new Solution(EvaporablePrototypeId, testCase.InitialRefillableSolution.VolumeOfEvaporable)); + solutionContainerSystem.AddSolution(refillable, refillableSolution, new Solution(EvaporablePrototypeId, testCase.InitialRefillableSolution.VolumeOfEvaporable)); if (testCase.InitialRefillableSolution.VolumeOfNonEvaporable > FixedPoint2.Zero) - solutionContainerSystem.AddSolution(refillableSoln.Value, new Solution(NonEvaporablePrototypeId, testCase.InitialRefillableSolution.VolumeOfNonEvaporable)); + solutionContainerSystem.AddSolution(refillable, refillableSolution, new Solution(NonEvaporablePrototypeId, testCase.InitialRefillableSolution.VolumeOfNonEvaporable)); // Act absorbentSystem.Mop(user, refillable, absorbent, component); @@ -138,7 +138,7 @@ public sealed class AbsorbentTest var entityManager = server.ResolveDependency(); var absorbentSystem = entityManager.System(); - var solutionContainerSystem = entityManager.System(); + var solutionContainerSystem = entityManager.System(); var prototypeManager = server.ResolveDependency(); EntityUid user = default; @@ -152,18 +152,18 @@ public sealed class AbsorbentTest refillable = entityManager.SpawnEntity(SmallRefillableDummyId, coordinates); entityManager.TryGetComponent(absorbent, out component); - solutionContainerSystem.TryGetSolution(absorbent, AbsorbentComponent.SolutionName, out var absorbentSoln, out var absorbentSolution); - solutionContainerSystem.TryGetRefillableSolution(refillable, out var refillableSoln, out var refillableSolution); + solutionContainerSystem.TryGetSolution(absorbent, AbsorbentComponent.SolutionName, out var absorbentSolution); + solutionContainerSystem.TryGetRefillableSolution(refillable, out var refillableSolution); // Arrange - solutionContainerSystem.AddSolution(absorbentSoln.Value, new Solution(EvaporablePrototypeId, testCase.InitialAbsorbentSolution.VolumeOfEvaporable)); + solutionContainerSystem.AddSolution(absorbent, absorbentSolution, new Solution(EvaporablePrototypeId, testCase.InitialAbsorbentSolution.VolumeOfEvaporable)); if (testCase.InitialAbsorbentSolution.VolumeOfNonEvaporable > FixedPoint2.Zero) - solutionContainerSystem.AddSolution(absorbentSoln.Value, new Solution(NonEvaporablePrototypeId, testCase.InitialAbsorbentSolution.VolumeOfNonEvaporable)); + solutionContainerSystem.AddSolution(absorbent, absorbentSolution, new Solution(NonEvaporablePrototypeId, testCase.InitialAbsorbentSolution.VolumeOfNonEvaporable)); if (testCase.InitialRefillableSolution.VolumeOfEvaporable > FixedPoint2.Zero) - solutionContainerSystem.AddSolution(refillableSoln.Value, new Solution(EvaporablePrototypeId, testCase.InitialRefillableSolution.VolumeOfEvaporable)); + solutionContainerSystem.AddSolution(refillable, refillableSolution, new Solution(EvaporablePrototypeId, testCase.InitialRefillableSolution.VolumeOfEvaporable)); if (testCase.InitialRefillableSolution.VolumeOfNonEvaporable > FixedPoint2.Zero) - solutionContainerSystem.AddSolution(refillableSoln.Value, new Solution(NonEvaporablePrototypeId, testCase.InitialRefillableSolution.VolumeOfNonEvaporable)); + solutionContainerSystem.AddSolution(refillable, refillableSolution, new Solution(NonEvaporablePrototypeId, testCase.InitialRefillableSolution.VolumeOfNonEvaporable)); // Act absorbentSystem.Mop(user, refillable, absorbent, component); diff --git a/Content.Server/Administration/Commands/AddReagent.cs b/Content.Server/Administration/Commands/AddReagent.cs index 46e8e8c35e..b75e46ad90 100644 --- a/Content.Server/Administration/Commands/AddReagent.cs +++ b/Content.Server/Administration/Commands/AddReagent.cs @@ -1,11 +1,10 @@ -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Shared.Administration; using Content.Shared.Chemistry.Components.SolutionManager; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Chemistry.Reagent; using Content.Shared.FixedPoint; using Robust.Shared.Console; using Robust.Shared.Prototypes; -using System.Linq; namespace Content.Server.Administration.Commands { @@ -42,13 +41,13 @@ namespace Content.Server.Administration.Commands return; } - var solutionContainerSystem = _entManager.System(); - if (!solutionContainerSystem.TryGetSolution((uid.Value, man), args[1], out var solution)) + if (!man.Solutions.ContainsKey(args[1])) { - var validSolutions = string.Join(", ", solutionContainerSystem.EnumerateSolutions((uid.Value, man)).Select(s => s.Name)); + var validSolutions = string.Join(", ", man.Solutions.Keys); shell.WriteLine($"Entity does not have a \"{args[1]}\" solution. Valid solutions are:\n{validSolutions}"); return; } + var solution = man.Solutions[args[1]]; if (!_protomanager.HasIndex(args[2])) { @@ -64,9 +63,9 @@ namespace Content.Server.Administration.Commands var quantity = FixedPoint2.New(MathF.Abs(quantityFloat)); if (quantityFloat > 0) - solutionContainerSystem.TryAddReagent(solution.Value, args[2], quantity, out _); + _entManager.System().TryAddReagent(uid.Value, solution, args[2], quantity, out _); else - solutionContainerSystem.RemoveReagent(solution.Value, args[2], quantity); + _entManager.System().RemoveReagent(uid.Value, solution, args[2], quantity); } } } diff --git a/Content.Server/Administration/Commands/SetSolutionCapacity.cs b/Content.Server/Administration/Commands/SetSolutionCapacity.cs index 19900d488b..e1e644f84f 100644 --- a/Content.Server/Administration/Commands/SetSolutionCapacity.cs +++ b/Content.Server/Administration/Commands/SetSolutionCapacity.cs @@ -1,9 +1,8 @@ -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Shared.Administration; using Content.Shared.Chemistry.Components.SolutionManager; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.FixedPoint; using Robust.Shared.Console; -using System.Linq; namespace Content.Server.Administration.Commands { @@ -36,13 +35,13 @@ namespace Content.Server.Administration.Commands return; } - var solutionContainerSystem = _entManager.System(); - if (!solutionContainerSystem.TryGetSolution((uid.Value, man), args[1], out var solution)) + if (!man.Solutions.ContainsKey(args[1])) { - var validSolutions = string.Join(", ", solutionContainerSystem.EnumerateSolutions((uid.Value, man)).Select(s => s.Name)); + var validSolutions = string.Join(", ", man.Solutions.Keys); shell.WriteLine($"Entity does not have a \"{args[1]}\" solution. Valid solutions are:\n{validSolutions}"); return; } + var solution = man.Solutions[args[1]]; if (!float.TryParse(args[2], out var quantityFloat)) { @@ -50,14 +49,14 @@ namespace Content.Server.Administration.Commands return; } - if (quantityFloat < 0.0f) + if(quantityFloat < 0.0f) { shell.WriteLine($"Cannot set the maximum volume of a solution to a negative number."); return; } var quantity = FixedPoint2.New(quantityFloat); - solutionContainerSystem.SetCapacity(solution.Value, quantity); + _entManager.System().SetCapacity(uid.Value, solution, quantity); } } } diff --git a/Content.Server/Administration/Commands/SetSolutionTemperature.cs b/Content.Server/Administration/Commands/SetSolutionTemperature.cs index 5ebd39880b..e8f58a50cf 100644 --- a/Content.Server/Administration/Commands/SetSolutionTemperature.cs +++ b/Content.Server/Administration/Commands/SetSolutionTemperature.cs @@ -1,8 +1,7 @@ -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Shared.Administration; using Content.Shared.Chemistry.Components.SolutionManager; +using Content.Shared.Chemistry.EntitySystems; using Robust.Shared.Console; -using System.Linq; namespace Content.Server.Administration.Commands { @@ -35,13 +34,13 @@ namespace Content.Server.Administration.Commands return; } - var solutionContainerSystem = _entManager.System(); - if (!solutionContainerSystem.TryGetSolution((uid.Value, man), args[1], out var solution)) + if (!man.Solutions.ContainsKey(args[1])) { - var validSolutions = string.Join(", ", solutionContainerSystem.EnumerateSolutions((uid.Value, man)).Select(s => s.Name)); + var validSolutions = string.Join(", ", man.Solutions.Keys); shell.WriteLine($"Entity does not have a \"{args[1]}\" solution. Valid solutions are:\n{validSolutions}"); return; } + var solution = man.Solutions[args[1]]; if (!float.TryParse(args[2], out var quantity)) { @@ -55,7 +54,7 @@ namespace Content.Server.Administration.Commands return; } - solutionContainerSystem.SetTemperature(solution.Value, quantity); + _entManager.System().SetTemperature(uid.Value, solution, quantity); } } } diff --git a/Content.Server/Administration/Commands/SetSolutionThermalEnergy.cs b/Content.Server/Administration/Commands/SetSolutionThermalEnergy.cs index 6442f1141a..c2b7f9d25c 100644 --- a/Content.Server/Administration/Commands/SetSolutionThermalEnergy.cs +++ b/Content.Server/Administration/Commands/SetSolutionThermalEnergy.cs @@ -1,8 +1,7 @@ -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Shared.Administration; using Content.Shared.Chemistry.Components.SolutionManager; +using Content.Shared.Chemistry.EntitySystems; using Robust.Shared.Console; -using System.Linq; namespace Content.Server.Administration.Commands { @@ -35,13 +34,13 @@ namespace Content.Server.Administration.Commands return; } - var solutionContainerSystem = _entManager.System(); - if (!solutionContainerSystem.TryGetSolution((uid.Value, man), args[1], out var solutionEnt, out var solution)) + if (!man.Solutions.ContainsKey(args[1])) { - var validSolutions = string.Join(", ", solutionContainerSystem.EnumerateSolutions((uid.Value, man)).Select(s => s.Name)); + var validSolutions = string.Join(", ", man.Solutions.Keys); shell.WriteLine($"Entity does not have a \"{args[1]}\" solution. Valid solutions are:\n{validSolutions}"); return; } + var solution = man.Solutions[args[1]]; if (!float.TryParse(args[2], out var quantity)) { @@ -51,19 +50,19 @@ namespace Content.Server.Administration.Commands if (solution.GetHeatCapacity(null) <= 0.0f) { - if (quantity != 0.0f) + if(quantity != 0.0f) { shell.WriteLine($"Cannot set the thermal energy of a solution with 0 heat capacity to a non-zero number."); return; } } - else if (quantity <= 0.0f) + else if(quantity <= 0.0f) { shell.WriteLine($"Cannot set the thermal energy of a solution with heat capacity to a non-positive number."); return; } - solutionContainerSystem.SetThermalEnergy(solutionEnt.Value, quantity); + _entManager.System().SetThermalEnergy(uid.Value, solution, quantity); } } } diff --git a/Content.Server/Administration/Systems/AdminVerbSystem.cs b/Content.Server/Administration/Systems/AdminVerbSystem.cs index cfd8311d8e..2637004565 100644 --- a/Content.Server/Administration/Systems/AdminVerbSystem.cs +++ b/Content.Server/Administration/Systems/AdminVerbSystem.cs @@ -1,3 +1,4 @@ +using System.Linq; using Content.Server.Administration.Logs; using Content.Server.Administration.Managers; using Content.Server.Administration.UI; @@ -33,7 +34,6 @@ using Robust.Shared.Prototypes; using Robust.Shared.Timing; using Robust.Shared.Toolshed; using Robust.Shared.Utility; -using System.Linq; using static Content.Shared.Configurable.ConfigurationComponent; namespace Content.Server.Administration.Systems @@ -71,7 +71,7 @@ namespace Content.Server.Administration.Systems { SubscribeLocalEvent>(GetVerbs); SubscribeLocalEvent(Reset); - SubscribeLocalEvent(OnSolutionChanged); + SubscribeLocalEvent(OnSolutionChanged); } private void GetVerbs(GetVerbsEvent ev) @@ -470,11 +470,11 @@ namespace Content.Server.Administration.Systems } #region SolutionsEui - private void OnSolutionChanged(Entity entity, ref SolutionContainerChangedEvent args) + private void OnSolutionChanged(EntityUid uid, SolutionContainerManagerComponent component, SolutionChangedEvent args) { foreach (var eui in _openSolutionUis.Values) { - if (eui.Target == entity.Owner) + if (eui.Target == uid) eui.StateDirty(); } } diff --git a/Content.Server/Administration/Toolshed/SolutionCommand.cs b/Content.Server/Administration/Toolshed/SolutionCommand.cs index e81e9aa323..1edf958c95 100644 --- a/Content.Server/Administration/Toolshed/SolutionCommand.cs +++ b/Content.Server/Administration/Toolshed/SolutionCommand.cs @@ -1,12 +1,12 @@ -using Content.Server.Chemistry.Containers.EntitySystems; +using System.Linq; using Content.Shared.Administration; using Content.Shared.Chemistry.Components; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Chemistry.Reagent; using Content.Shared.FixedPoint; using Robust.Shared.Toolshed; using Robust.Shared.Toolshed.Syntax; using Robust.Shared.Toolshed.TypeParsers; -using System.Linq; namespace Content.Server.Administration.Toolshed; @@ -24,8 +24,10 @@ public sealed class SolutionCommand : ToolshedCommand { _solutionContainer ??= GetSys(); - if (_solutionContainer.TryGetSolution(input, name.Evaluate(ctx)!, out var solution)) - return new SolutionRef(solution.Value); + _solutionContainer.TryGetSolution(input, name.Evaluate(ctx)!, out var solution); + + if (solution is not null) + return new SolutionRef(input, solution); return null; } @@ -53,11 +55,11 @@ public sealed class SolutionCommand : ToolshedCommand var amount = amountRef.Evaluate(ctx); if (amount > 0) { - _solutionContainer.TryAddReagent(input.Solution, name.Value.ID, amount, out _); + _solutionContainer.TryAddReagent(input.Owner, input.Solution, name.Value.ID, amount, out _); } else if (amount < 0) { - _solutionContainer.RemoveReagent(input.Solution, name.Value.ID, -amount); + _solutionContainer.RemoveReagent(input.Owner, input.Solution, name.Value.ID, -amount); } return input; @@ -73,10 +75,10 @@ public sealed class SolutionCommand : ToolshedCommand => input.Select(x => AdjReagent(ctx, x, name, amountRef)); } -public readonly record struct SolutionRef(Entity Solution) +public readonly record struct SolutionRef(EntityUid Owner, Solution Solution) { public override string ToString() { - return $"{Solution.Owner} {Solution.Comp.Solution}"; + return $"{Owner} {Solution}"; } } diff --git a/Content.Server/Administration/UI/EditSolutionsEui.cs b/Content.Server/Administration/UI/EditSolutionsEui.cs index 228463d5ce..5136b347a2 100644 --- a/Content.Server/Administration/UI/EditSolutionsEui.cs +++ b/Content.Server/Administration/UI/EditSolutionsEui.cs @@ -1,5 +1,4 @@ using Content.Server.Administration.Systems; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.EUI; using Content.Shared.Administration; using Content.Shared.Chemistry.Components.SolutionManager; @@ -15,13 +14,11 @@ namespace Content.Server.Administration.UI public sealed class EditSolutionsEui : BaseEui { [Dependency] private readonly IEntityManager _entityManager = default!; - private readonly SolutionContainerSystem _solutionContainerSystem = default!; public readonly EntityUid Target; public EditSolutionsEui(EntityUid entity) { IoCManager.InjectDependencies(this); - _solutionContainerSystem = _entityManager.System(); Target = entity; } @@ -39,23 +36,8 @@ namespace Content.Server.Administration.UI public override EuiStateBase GetNewState() { - List<(string Name, NetEntity Solution)>? netSolutions; - - if (_entityManager.TryGetComponent(Target, out SolutionContainerManagerComponent? container) && container.Containers.Count > 0) - { - netSolutions = new(); - foreach (var (name, solution) in _solutionContainerSystem.EnumerateSolutions((Target, container))) - { - if (name is null || !_entityManager.TryGetNetEntity(solution, out var netSolution)) - continue; - - netSolutions.Add((name, netSolution.Value)); - } - } - else - netSolutions = null; - - return new EditSolutionsEuiState(_entityManager.GetNetEntity(Target), netSolutions); + var solutions = _entityManager.GetComponentOrNull(Target)?.Solutions; + return new EditSolutionsEuiState(_entityManager.GetNetEntity(Target), solutions); } } } diff --git a/Content.Server/Animals/Components/UdderComponent.cs b/Content.Server/Animals/Components/UdderComponent.cs index 620f4572a7..3895a8ba24 100644 --- a/Content.Server/Animals/Components/UdderComponent.cs +++ b/Content.Server/Animals/Components/UdderComponent.cs @@ -1,10 +1,10 @@ using Content.Server.Animals.Systems; -using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Reagent; using Content.Shared.FixedPoint; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; + namespace Content.Server.Animals.Components /// @@ -20,17 +20,11 @@ namespace Content.Server.Animals.Components [DataField, ViewVariables(VVAccess.ReadOnly)] public ProtoId ReagentId = "Milk"; - /// - /// The name of . - /// - [DataField, ViewVariables(VVAccess.ReadOnly)] - public string SolutionName = "udder"; - /// /// The solution to add reagent to. /// - [DataField] - public Entity? Solution = null; + [DataField, ViewVariables(VVAccess.ReadOnly)] + public string Solution = "udder"; /// /// The amount of reagent to be generated on update. diff --git a/Content.Server/Animals/Components/WoolyComponent.cs b/Content.Server/Animals/Components/WoolyComponent.cs index c09c6f5e08..e700fd76f6 100644 --- a/Content.Server/Animals/Components/WoolyComponent.cs +++ b/Content.Server/Animals/Components/WoolyComponent.cs @@ -1,5 +1,4 @@ using Content.Server.Animals.Systems; -using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Reagent; using Content.Shared.FixedPoint; using Robust.Shared.Prototypes; @@ -20,17 +19,11 @@ public sealed partial class WoolyComponent : Component [DataField, ViewVariables(VVAccess.ReadOnly)] public ProtoId ReagentId = "Fiber"; - /// - /// The name of . - /// - [DataField, ViewVariables(VVAccess.ReadOnly)] - public string SolutionName = "wool"; - /// /// The solution to add reagent to. /// - [DataField] - public Entity? Solution; + [DataField, ViewVariables(VVAccess.ReadOnly)] + public string Solution = "wool"; /// /// The amount of reagent to be generated on update. diff --git a/Content.Server/Animals/Systems/UdderSystem.cs b/Content.Server/Animals/Systems/UdderSystem.cs index ef43c2c89d..c07ba12dd5 100644 --- a/Content.Server/Animals/Systems/UdderSystem.cs +++ b/Content.Server/Animals/Systems/UdderSystem.cs @@ -1,7 +1,7 @@ using Content.Server.Animals.Components; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Popups; using Content.Shared.Chemistry.Components; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.DoAfter; using Content.Shared.IdentityManagement; using Content.Shared.Mobs.Systems; @@ -61,11 +61,11 @@ internal sealed class UdderSystem : EntitySystem _hunger.ModifyHunger(uid, -udder.HungerUsage, hunger); } - if (!_solutionContainerSystem.ResolveSolution(uid, udder.SolutionName, ref udder.Solution)) + if (!_solutionContainerSystem.TryGetSolution(uid, udder.Solution, out var solution)) continue; //TODO: toxins from bloodstream !? - _solutionContainerSystem.TryAddReagent(udder.Solution.Value, udder.ReagentId, udder.QuantityPerUpdate, out _); + _solutionContainerSystem.TryAddReagent(uid, solution, udder.ReagentId, udder.QuantityPerUpdate, out _); } } @@ -85,50 +85,47 @@ internal sealed class UdderSystem : EntitySystem _doAfterSystem.TryStartDoAfter(doargs); } - private void OnDoAfter(Entity entity, ref MilkingDoAfterEvent args) + private void OnDoAfter(EntityUid uid, UdderComponent component, MilkingDoAfterEvent args) { if (args.Cancelled || args.Handled || args.Args.Used == null) return; - if (!_solutionContainerSystem.ResolveSolution(entity.Owner, entity.Comp.SolutionName, ref entity.Comp.Solution, out var solution)) + if (!_solutionContainerSystem.TryGetSolution(uid, component.Solution, out var solution)) return; - if (!_solutionContainerSystem.TryGetRefillableSolution(args.Args.Used.Value, out var targetSoln, out var targetSolution)) + if (!_solutionContainerSystem.TryGetRefillableSolution(args.Args.Used.Value, out var targetSolution)) return; args.Handled = true; var quantity = solution.Volume; if (quantity == 0) { - _popupSystem.PopupEntity(Loc.GetString("udder-system-dry"), entity.Owner, args.Args.User); + _popupSystem.PopupEntity(Loc.GetString("udder-system-dry"), uid, args.Args.User); return; } if (quantity > targetSolution.AvailableVolume) quantity = targetSolution.AvailableVolume; - var split = _solutionContainerSystem.SplitSolution(entity.Comp.Solution.Value, quantity); - _solutionContainerSystem.TryAddSolution(targetSoln.Value, split); + var split = _solutionContainerSystem.SplitSolution(uid, solution, quantity); + _solutionContainerSystem.TryAddSolution(args.Args.Used.Value, targetSolution, split); - _popupSystem.PopupEntity(Loc.GetString("udder-system-success", ("amount", quantity), ("target", Identity.Entity(args.Args.Used.Value, EntityManager))), entity.Owner, + _popupSystem.PopupEntity(Loc.GetString("udder-system-success", ("amount", quantity), ("target", Identity.Entity(args.Args.Used.Value, EntityManager))), uid, args.Args.User, PopupType.Medium); } - private void AddMilkVerb(Entity entity, ref GetVerbsEvent args) + private void AddMilkVerb(EntityUid uid, UdderComponent component, GetVerbsEvent args) { if (args.Using == null || !args.CanInteract || !EntityManager.HasComponent(args.Using.Value)) return; - var uid = entity.Owner; - var user = args.User; - var used = args.Using.Value; AlternativeVerb verb = new() { Act = () => { - AttemptMilk(uid, user, used); + AttemptMilk(uid, args.User, args.Using.Value); }, Text = Loc.GetString("udder-system-verb-milk"), Priority = 2 diff --git a/Content.Server/Animals/Systems/WoolySystem.cs b/Content.Server/Animals/Systems/WoolySystem.cs index cbe959fb56..6cf8d8c88f 100644 --- a/Content.Server/Animals/Systems/WoolySystem.cs +++ b/Content.Server/Animals/Systems/WoolySystem.cs @@ -1,6 +1,6 @@ using Content.Server.Animals.Components; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Nutrition; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Mobs.Systems; using Content.Shared.Nutrition.Components; using Content.Shared.Nutrition.EntitySystems; @@ -52,10 +52,10 @@ public sealed class WoolySystem : EntitySystem _hunger.ModifyHunger(uid, -wooly.HungerUsage, hunger); } - if (!_solutionContainer.ResolveSolution(uid, wooly.SolutionName, ref wooly.Solution)) + if (!_solutionContainer.TryGetSolution(uid, wooly.Solution, out var solution)) continue; - _solutionContainer.TryAddReagent(wooly.Solution.Value, wooly.ReagentId, wooly.Quantity, out _); + _solutionContainer.TryAddReagent(uid, solution, wooly.ReagentId, wooly.Quantity, out _); } } diff --git a/Content.Server/Anomaly/Components/ReagentProducerAnomalyComponent.cs b/Content.Server/Anomaly/Components/ReagentProducerAnomalyComponent.cs index 49c62aec81..aa860c1713 100644 --- a/Content.Server/Anomaly/Components/ReagentProducerAnomalyComponent.cs +++ b/Content.Server/Anomaly/Components/ReagentProducerAnomalyComponent.cs @@ -1,5 +1,4 @@ using Content.Server.Anomaly.Effects; -using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Reagent; using Robust.Shared.Audio; using Robust.Shared.Prototypes; @@ -86,17 +85,10 @@ public sealed partial class ReagentProducerAnomalyComponent : Component /// [DataField, ViewVariables(VVAccess.ReadWrite)] public ProtoId ProducingReagent = "Water"; - /// /// Solution name where the substance is generated /// [ViewVariables(VVAccess.ReadWrite)] [DataField("solution")] - public string SolutionName = "default"; - - /// - /// Solution where the substance is generated - /// - [DataField("solutionRef")] - public Entity? Solution = null; + public string Solution = "default"; } diff --git a/Content.Server/Anomaly/Effects/InjectionAnomalySystem.cs b/Content.Server/Anomaly/Effects/InjectionAnomalySystem.cs index 2bef32e322..05f1c5c61c 100644 --- a/Content.Server/Anomaly/Effects/InjectionAnomalySystem.cs +++ b/Content.Server/Anomaly/Effects/InjectionAnomalySystem.cs @@ -1,8 +1,8 @@ +using System.Linq; using Content.Server.Anomaly.Components; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Shared.Anomaly.Components; using Content.Shared.Chemistry.Components.SolutionManager; -using System.Linq; +using Content.Shared.Chemistry.EntitySystems; namespace Content.Server.Anomaly.Effects; /// @@ -27,40 +27,41 @@ public sealed class InjectionAnomalySystem : EntitySystem _injectableQuery = GetEntityQuery(); } - private void OnPulse(Entity entity, ref AnomalyPulseEvent args) + private void OnPulse(EntityUid uid, InjectionAnomalyComponent component, ref AnomalyPulseEvent args) { - PulseScalableEffect(entity, entity.Comp.InjectRadius, entity.Comp.MaxSolutionInjection * args.Severity); + PulseScalableEffect(uid, component, component.InjectRadius, component.MaxSolutionInjection * args.Severity); } - private void OnSupercritical(Entity entity, ref AnomalySupercriticalEvent args) + private void OnSupercritical(EntityUid uid, InjectionAnomalyComponent component, ref AnomalySupercriticalEvent args) { - PulseScalableEffect(entity, entity.Comp.SuperCriticalInjectRadius, entity.Comp.SuperCriticalSolutionInjection); + PulseScalableEffect(uid, component, component.SuperCriticalInjectRadius, component.SuperCriticalSolutionInjection); } - private void PulseScalableEffect(Entity entity, float injectRadius, float maxInject) + private void PulseScalableEffect(EntityUid uid, InjectionAnomalyComponent component, float injectRadius, float maxInject) { - if (!_solutionContainer.TryGetSolution(entity.Owner, entity.Comp.Solution, out _, out var sol)) + if (!_solutionContainer.TryGetSolution(uid, component.Solution, out var sol)) return; - //We get all the entity in the radius into which the reagent will be injected. var xformQuery = GetEntityQuery(); - var xform = xformQuery.GetComponent(entity); + var xform = xformQuery.GetComponent(uid); var allEnts = _lookup.GetEntitiesInRange(xform.MapPosition, injectRadius) .Select(x => x.Owner).ToList(); //for each matching entity found foreach (var ent in allEnts) { - if (!_solutionContainer.TryGetInjectableSolution(ent, out var injectable, out _)) + if (!_solutionContainer.TryGetInjectableSolution(ent, out var injectable)) continue; if (_injectableQuery.TryGetComponent(ent, out var injEnt)) { - _solutionContainer.TryTransferSolution(injectable.Value, sol, maxInject); + var buffer = sol; + _solutionContainer.TryTransferSolution(ent, injectable, buffer, maxInject); //Spawn Effect var uidXform = Transform(ent); - Spawn(entity.Comp.VisualEffectPrototype, uidXform.Coordinates); + Spawn(component.VisualEffectPrototype, uidXform.Coordinates); } } } + } diff --git a/Content.Server/Anomaly/Effects/PuddleCreateAnomalySystem.cs b/Content.Server/Anomaly/Effects/PuddleCreateAnomalySystem.cs index 90177bae8e..9855e66cfe 100644 --- a/Content.Server/Anomaly/Effects/PuddleCreateAnomalySystem.cs +++ b/Content.Server/Anomaly/Effects/PuddleCreateAnomalySystem.cs @@ -1,7 +1,7 @@ using Content.Server.Anomaly.Components; -using Content.Server.Chemistry.Containers.EntitySystems; -using Content.Server.Fluids.EntitySystems; using Content.Shared.Anomaly.Components; +using Content.Shared.Chemistry.EntitySystems; +using Content.Server.Fluids.EntitySystems; namespace Content.Server.Anomaly.Effects; @@ -19,21 +19,21 @@ public sealed class PuddleCreateAnomalySystem : EntitySystem SubscribeLocalEvent(OnSupercritical, before: new[] { typeof(InjectionAnomalySystem) }); } - private void OnPulse(Entity entity, ref AnomalyPulseEvent args) + private void OnPulse(EntityUid uid, PuddleCreateAnomalyComponent component, ref AnomalyPulseEvent args) { - if (!_solutionContainer.TryGetSolution(entity.Owner, entity.Comp.Solution, out var sol, out _)) + if (!_solutionContainer.TryGetSolution(uid, component.Solution, out var sol)) return; - var xform = Transform(entity.Owner); - var puddleSol = _solutionContainer.SplitSolution(sol.Value, entity.Comp.MaxPuddleSize * args.Severity); - _puddle.TrySplashSpillAt(entity.Owner, xform.Coordinates, puddleSol, out _); + var xform = Transform(uid); + var puddleSol = _solutionContainer.SplitSolution(uid, sol, component.MaxPuddleSize * args.Severity); + _puddle.TrySplashSpillAt(uid, xform.Coordinates, puddleSol, out _); } - private void OnSupercritical(Entity entity, ref AnomalySupercriticalEvent args) + private void OnSupercritical(EntityUid uid, PuddleCreateAnomalyComponent component, ref AnomalySupercriticalEvent args) { - if (!_solutionContainer.TryGetSolution(entity.Owner, entity.Comp.Solution, out _, out var sol)) + if (!_solutionContainer.TryGetSolution(uid, component.Solution, out var sol)) return; - - var xform = Transform(entity.Owner); - _puddle.TrySpillAt(xform.Coordinates, sol, out _); + var buffer = sol; + var xform = Transform(uid); + _puddle.TrySpillAt(xform.Coordinates, buffer, out _); } } diff --git a/Content.Server/Anomaly/Effects/ReagentProducerAnomalySystem.cs b/Content.Server/Anomaly/Effects/ReagentProducerAnomalySystem.cs index 0e49c5ee56..487d20f43f 100644 --- a/Content.Server/Anomaly/Effects/ReagentProducerAnomalySystem.cs +++ b/Content.Server/Anomaly/Effects/ReagentProducerAnomalySystem.cs @@ -1,12 +1,12 @@ using Content.Server.Anomaly.Components; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Shared.Anomaly.Components; +using Robust.Shared.Random; using Content.Shared.Chemistry.Components; +using Content.Shared.Chemistry.EntitySystems; +using Robust.Shared.Prototypes; using Content.Shared.Sprite; using Robust.Server.GameObjects; using Robust.Shared.Audio.Systems; -using Robust.Shared.Prototypes; -using Robust.Shared.Random; namespace Content.Server.Anomaly.Effects; @@ -42,17 +42,17 @@ public sealed class ReagentProducerAnomalySystem : EntitySystem SubscribeLocalEvent(OnMapInit); } - private void OnPulse(Entity entity, ref AnomalyPulseEvent args) + private void OnPulse(EntityUid uid, ReagentProducerAnomalyComponent component, ref AnomalyPulseEvent args) { if (_random.NextFloat(0.0f, 1.0f) > args.Stability) - ChangeReagent(entity, args.Severity); + ChangeReagent(uid, component, args.Severity); } - private void ChangeReagent(Entity entity, float severity) + private void ChangeReagent(EntityUid uid, ReagentProducerAnomalyComponent component, float severity) { - var reagent = GetRandomReagentType(entity, severity); - entity.Comp.ProducingReagent = reagent; - _audio.PlayPvs(entity.Comp.ChangeSound, entity); + var reagent = GetRandomReagentType(uid, component, severity); + component.ProducingReagent = reagent; + _audio.PlayPvs(component.ChangeSound, uid); } //reagent realtime generation @@ -68,7 +68,7 @@ public sealed class ReagentProducerAnomalySystem : EntitySystem if (component.AccumulatedFrametime < component.UpdateInterval) continue; - if (!_solutionContainer.ResolveSolution(uid, component.SolutionName, ref component.Solution, out var producerSolution)) + if (!_solutionContainer.TryGetSolution(uid, component.Solution, out var producerSol)) continue; Solution newSol = new(); @@ -76,7 +76,7 @@ public sealed class ReagentProducerAnomalySystem : EntitySystem if (anomaly.Severity >= 0.97) reagentProducingAmount *= component.SupercriticalReagentProducingModifier; newSol.AddReagent(component.ProducingReagent, reagentProducingAmount); - _solutionContainer.TryAddSolution(component.Solution.Value, newSol); //TO DO - the container is not fully filled. + _solutionContainer.TryAddSolution(uid, producerSol, newSol); //TO DO - the container is not fully filled. component.AccumulatedFrametime = 0; @@ -87,7 +87,7 @@ public sealed class ReagentProducerAnomalySystem : EntitySystem // and nothing worked out for me. So for now it will be like this. if (component.NeedRecolor) { - var color = producerSolution.GetColor(_prototypeManager); + var color = producerSol.GetColor(_prototypeManager); _light.SetColor(uid, color); if (TryComp(uid, out var randomSprite)) { @@ -103,9 +103,9 @@ public sealed class ReagentProducerAnomalySystem : EntitySystem } } - private void OnMapInit(Entity entity, ref MapInitEvent args) + private void OnMapInit(EntityUid uid, ReagentProducerAnomalyComponent component, MapInitEvent args) { - ChangeReagent(entity, 0.1f); //MapInit Reagent 100% change + ChangeReagent(uid, component, 0.1f); //MapInit Reagent 100% change } // returns a random reagent based on a system of random weights. @@ -117,33 +117,33 @@ public sealed class ReagentProducerAnomalySystem : EntitySystem // After that, a random reagent in the selected category is selected. // // Such a system is made to control the danger and interest of the anomaly more. - private string GetRandomReagentType(Entity entity, float severity) + private string GetRandomReagentType(EntityUid uid, ReagentProducerAnomalyComponent component, float severity) { //Category Weight Randomization - var currentWeightDangerous = MathHelper.Lerp(entity.Comp.WeightSpreadDangerous.X, entity.Comp.WeightSpreadDangerous.Y, severity); - var currentWeightFun = MathHelper.Lerp(entity.Comp.WeightSpreadFun.X, entity.Comp.WeightSpreadFun.Y, severity); - var currentWeightUseful = MathHelper.Lerp(entity.Comp.WeightSpreadUseful.X, entity.Comp.WeightSpreadUseful.Y, severity); + var currentWeightDangerous = MathHelper.Lerp(component.WeightSpreadDangerous.X, component.WeightSpreadDangerous.Y, severity); + var currentWeightFun = MathHelper.Lerp(component.WeightSpreadFun.X, component.WeightSpreadFun.Y, severity); + var currentWeightUseful = MathHelper.Lerp(component.WeightSpreadUseful.X, component.WeightSpreadUseful.Y, severity); var sumWeight = currentWeightDangerous + currentWeightFun + currentWeightUseful; var rnd = _random.NextFloat(0f, sumWeight); //Dangerous - if (rnd <= currentWeightDangerous && entity.Comp.DangerousChemicals.Count > 0) + if (rnd <= currentWeightDangerous && component.DangerousChemicals.Count > 0) { - var reagent = _random.Pick(entity.Comp.DangerousChemicals); + var reagent = _random.Pick(component.DangerousChemicals); return reagent; } else rnd -= currentWeightDangerous; //Fun - if (rnd <= currentWeightFun && entity.Comp.FunChemicals.Count > 0) + if (rnd <= currentWeightFun && component.FunChemicals.Count > 0) { - var reagent = _random.Pick(entity.Comp.FunChemicals); + var reagent = _random.Pick(component.FunChemicals); return reagent; } else rnd -= currentWeightFun; //Useful - if (rnd <= currentWeightUseful && entity.Comp.UsefulChemicals.Count > 0) + if (rnd <= currentWeightUseful && component.UsefulChemicals.Count > 0) { - var reagent = _random.Pick(entity.Comp.UsefulChemicals); + var reagent = _random.Pick(component.UsefulChemicals); return reagent; } //We should never end up here. diff --git a/Content.Server/Atmos/Piping/Unary/Components/GasCondenserComponent.cs b/Content.Server/Atmos/Piping/Unary/Components/GasCondenserComponent.cs index c25c010708..1db0b524bb 100644 --- a/Content.Server/Atmos/Piping/Unary/Components/GasCondenserComponent.cs +++ b/Content.Server/Atmos/Piping/Unary/Components/GasCondenserComponent.cs @@ -1,5 +1,4 @@ using Content.Server.Atmos.Piping.Unary.EntitySystems; -using Content.Shared.Chemistry.Components; namespace Content.Server.Atmos.Piping.Unary.Components; @@ -22,12 +21,6 @@ public sealed partial class GasCondenserComponent : Component [DataField] public string SolutionId = "tank"; - /// - /// The solution that gases are condensed into. - /// - [DataField] - public Entity? Solution = null; - /// /// For a condenser, how many U of reagents are given per each mole of gas. /// diff --git a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCondenserSystem.cs b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCondenserSystem.cs index 491bf60062..f9ed614d9c 100644 --- a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCondenserSystem.cs +++ b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCondenserSystem.cs @@ -5,11 +5,10 @@ using Content.Server.NodeContainer; using Content.Server.NodeContainer.EntitySystems; using Content.Server.NodeContainer.Nodes; using Content.Server.Power.Components; -using Content.Server.Power.EntitySystems; using Content.Shared.Atmos; -using Content.Shared.Chemistry.EntitySystems; -using Content.Shared.FixedPoint; using JetBrains.Annotations; +using Content.Server.Power.EntitySystems; +using Content.Shared.Chemistry.EntitySystems; namespace Content.Server.Atmos.Piping.Unary.EntitySystems; @@ -19,7 +18,7 @@ public sealed class GasCondenserSystem : EntitySystem [Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!; [Dependency] private readonly PowerReceiverSystem _power = default!; [Dependency] private readonly NodeContainerSystem _nodeContainer = default!; - [Dependency] private readonly SharedSolutionContainerSystem _solution = default!; + [Dependency] private readonly SolutionContainerSystem _solution = default!; public override void Initialize() { @@ -28,12 +27,12 @@ public sealed class GasCondenserSystem : EntitySystem SubscribeLocalEvent(OnCondenserUpdated); } - private void OnCondenserUpdated(Entity entity, ref AtmosDeviceUpdateEvent args) + private void OnCondenserUpdated(EntityUid uid, GasCondenserComponent component, ref AtmosDeviceUpdateEvent args) { - if (!(_power.IsPowered(entity) && TryComp(entity, out var receiver)) - || !TryComp(entity, out var nodeContainer) - || !_nodeContainer.TryGetNode(nodeContainer, entity.Comp.Inlet, out PipeNode? inlet) - || !_solution.ResolveSolution(entity.Owner, entity.Comp.SolutionId, ref entity.Comp.Solution, out var solution)) + if (!(_power.IsPowered(uid) && TryComp(uid, out var receiver)) + || !TryComp(uid, out var nodeContainer) + || !_nodeContainer.TryGetNode(nodeContainer, component.Inlet, out PipeNode? inlet) + || !_solution.TryGetSolution(uid, component.SolutionId, out var solution)) { return; } @@ -49,21 +48,18 @@ public sealed class GasCondenserSystem : EntitySystem if (moles <= 0) continue; - if (_atmosphereSystem.GetGas(i).Reagent is not { } gasReagent) + if (_atmosphereSystem.GetGas(i).Reagent is not {} gasReagent) continue; - var moleToReagentMultiplier = entity.Comp.MolesToReagentMultiplier; - var amount = FixedPoint2.Min(FixedPoint2.New(moles * moleToReagentMultiplier), solution.AvailableVolume); - if (amount <= 0) - continue; + var moleToReagentMultiplier = component.MolesToReagentMultiplier; + var amount = moles * moleToReagentMultiplier; - solution.AddReagent(gasReagent, amount); + if (_solution.TryAddReagent(uid, solution, gasReagent, amount, out var remaining)) + continue; // if we have leftover reagent, then convert it back to moles and put it back in the mixture. - inlet.Air.AdjustMoles(i, moles - (amount.Float() / moleToReagentMultiplier)); + inlet.Air.AdjustMoles(i, remaining.Float() / moleToReagentMultiplier); } - - _solution.UpdateChemicals(entity.Comp.Solution.Value); } public float NumberOfMolesToConvert(ApcPowerReceiverComponent comp, GasMixture mix, float dt) diff --git a/Content.Server/Body/Components/BloodstreamComponent.cs b/Content.Server/Body/Components/BloodstreamComponent.cs index 3ee8fe4d17..33db12157e 100644 --- a/Content.Server/Body/Components/BloodstreamComponent.cs +++ b/Content.Server/Body/Components/BloodstreamComponent.cs @@ -34,52 +34,52 @@ namespace Content.Server.Body.Components /// /// How much should bleeding should be reduced every update interval? /// - [DataField] + [DataField("bleedReductionAmount")] public float BleedReductionAmount = 1.0f; /// /// How high can go? /// - [DataField] + [DataField("maxBleedAmount")] public float MaxBleedAmount = 10.0f; /// /// What percentage of current blood is necessary to avoid dealing blood loss damage? /// - [DataField] + [DataField("bloodlossThreshold")] public float BloodlossThreshold = 0.9f; /// /// The base bloodloss damage to be incurred if below /// The default values are defined per mob/species in YML. /// - [DataField(required: true)] + [DataField("bloodlossDamage", required: true)] public DamageSpecifier BloodlossDamage = new(); /// /// The base bloodloss damage to be healed if above /// The default values are defined per mob/species in YML. /// - [DataField(required: true)] + [DataField("bloodlossHealDamage", required: true)] public DamageSpecifier BloodlossHealDamage = new(); /// /// How frequently should this bloodstream update, in seconds? /// - [DataField] + [DataField("updateInterval")] public float UpdateInterval = 3.0f; // TODO shouldn't be hardcoded, should just use some organ simulation like bone marrow or smth. /// /// How much reagent of blood should be restored each update interval? /// - [DataField] + [DataField("bloodRefreshAmount")] public float BloodRefreshAmount = 1.0f; /// /// How much blood needs to be in the temporary solution in order to create a puddle? /// - [DataField] + [DataField("bleedPuddleThreshold")] public FixedPoint2 BleedPuddleThreshold = 1.0f; /// @@ -89,19 +89,19 @@ namespace Content.Server.Body.Components /// /// For example, piercing damage is increased while poison damage is nullified entirely. /// - [DataField(customTypeSerializer:typeof(PrototypeIdSerializer))] + [DataField("damageBleedModifiers", customTypeSerializer:typeof(PrototypeIdSerializer))] public string DamageBleedModifiers = "BloodlossHuman"; /// /// The sound to be played when a weapon instantly deals blood loss damage. /// - [DataField] + [DataField("instantBloodSound")] public SoundSpecifier InstantBloodSound = new SoundCollectionSpecifier("blood"); /// /// The sound to be played when some damage actually heals bleeding rather than starting it. /// - [DataField] + [DataField("bloodHealedSound")] public SoundSpecifier BloodHealedSound = new SoundPathSpecifier("/Audio/Effects/lightburn.ogg"); // TODO probably damage bleed thresholds. @@ -109,14 +109,14 @@ namespace Content.Server.Body.Components /// /// Max volume of internal chemical solution storage /// - [DataField] + [DataField("chemicalMaxVolume")] public FixedPoint2 ChemicalMaxVolume = FixedPoint2.New(250); /// /// Max volume of internal blood storage, /// and starting level of blood. /// - [DataField] + [DataField("bloodMaxVolume")] public FixedPoint2 BloodMaxVolume = FixedPoint2.New(300); /// @@ -125,40 +125,29 @@ namespace Content.Server.Body.Components /// /// Slime-people might use slime as their blood or something like that. /// - [DataField] + [DataField("bloodReagent")] public string BloodReagent = "Blood"; - /// Name/Key that is indexed by. - [DataField] - public string BloodSolutionName = DefaultBloodSolutionName; - - /// Name/Key that is indexed by. - [DataField] - public string ChemicalSolutionName = DefaultChemicalsSolutionName; - - /// Name/Key that is indexed by. - [DataField] - public string BloodTemporarySolutionName = DefaultBloodTemporarySolutionName; - - /// - /// Internal solution for blood storage - /// - [DataField] - public Entity? BloodSolution = null; - /// /// Internal solution for reagent storage /// - [DataField] - public Entity? ChemicalSolution = null; + [ViewVariables(VVAccess.ReadWrite)] + [Access(typeof(BloodstreamSystem), Other = AccessPermissions.ReadExecute)] // FIXME Friends + public Solution ChemicalSolution = default!; + + /// + /// Internal solution for blood storage + /// + [ViewVariables(VVAccess.ReadWrite)] + public Solution BloodSolution = default!; /// /// Temporary blood solution. /// When blood is lost, it goes to this solution, and when this /// solution hits a certain cap, the blood is actually spilled as a puddle. /// - [DataField] - public Entity? TemporarySolution = null; + [ViewVariables(VVAccess.ReadWrite)] + public Solution BloodTemporarySolution = default!; /// /// Variable that stores the amount of status time added by having a low blood level. diff --git a/Content.Server/Body/Components/LungComponent.cs b/Content.Server/Body/Components/LungComponent.cs index 1d997a9950..434286a5c6 100644 --- a/Content.Server/Body/Components/LungComponent.cs +++ b/Content.Server/Body/Components/LungComponent.cs @@ -8,7 +8,7 @@ namespace Content.Server.Body.Components; [RegisterComponent, Access(typeof(LungSystem))] public sealed partial class LungComponent : Component { - [DataField] + [DataField("air")] [Access(typeof(LungSystem), Other = AccessPermissions.ReadExecute)] // FIXME Friends public GasMixture Air { get; set; } = new() { @@ -16,15 +16,7 @@ public sealed partial class LungComponent : Component Temperature = Atmospherics.NormalBodyTemperature }; - /// - /// The name/key of the solution on this entity which these lungs act on. - /// - [DataField] - public string SolutionName = LungSystem.LungSolutionName; - - /// - /// The solution on this entity that these lungs act on. - /// - [DataField] - public Entity? Solution = null; + [ViewVariables] + [Access(typeof(LungSystem), Other = AccessPermissions.ReadExecute)] // FIXME Friends + public Solution LungSolution = default!; } diff --git a/Content.Server/Body/Components/MetabolizerComponent.cs b/Content.Server/Body/Components/MetabolizerComponent.cs index a8c82f3d36..21a0be25d2 100644 --- a/Content.Server/Body/Components/MetabolizerComponent.cs +++ b/Content.Server/Body/Components/MetabolizerComponent.cs @@ -18,7 +18,7 @@ namespace Content.Server.Body.Components /// How often to metabolize reagents, in seconds. /// /// - [DataField] + [DataField("updateFrequency")] public float UpdateFrequency = 1.0f; /// @@ -33,13 +33,13 @@ namespace Content.Server.Body.Components /// /// Most things will use the parent entity (bloodstream). /// - [DataField] + [DataField("solutionOnBody")] public bool SolutionOnBody = true; /// /// List of metabolizer types that this organ is. ex. Human, Slime, Felinid, w/e. /// - [DataField(customTypeSerializer:typeof(PrototypeIdHashSetSerializer))] + [DataField("metabolizerTypes", customTypeSerializer:typeof(PrototypeIdHashSetSerializer))] [Access(typeof(MetabolizerSystem), Other = AccessPermissions.ReadExecute)] // FIXME Friends public HashSet? MetabolizerTypes = null; @@ -47,7 +47,7 @@ namespace Content.Server.Body.Components /// Should this metabolizer remove chemicals that have no metabolisms defined? /// As a stop-gap, basically. /// - [DataField] + [DataField("removeEmpty")] public bool RemoveEmpty = false; /// @@ -72,7 +72,7 @@ namespace Content.Server.Body.Components [DataDefinition] public sealed partial class MetabolismGroupEntry { - [DataField(required: true, customTypeSerializer:typeof(PrototypeIdSerializer))] + [DataField("id", required: true, customTypeSerializer:typeof(PrototypeIdSerializer))] public string Id = default!; [DataField("rateModifier")] diff --git a/Content.Server/Body/Components/StomachComponent.cs b/Content.Server/Body/Components/StomachComponent.cs index fe93468f74..30f9791525 100644 --- a/Content.Server/Body/Components/StomachComponent.cs +++ b/Content.Server/Body/Components/StomachComponent.cs @@ -2,6 +2,7 @@ using Content.Server.Nutrition.EntitySystems; using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Reagent; +using Content.Shared.FixedPoint; using Content.Shared.Whitelist; namespace Content.Server.Body.Components @@ -14,32 +15,26 @@ namespace Content.Server.Body.Components /// /// How fast should this component update, in seconds? /// - [DataField] + [DataField("updateInterval")] public float UpdateInterval = 1.0f; - /// - /// The solution inside of this stomach this transfers reagents to the body. - /// - [DataField] - public Entity? Solution = null; - /// /// What solution should this stomach push reagents into, on the body? /// - [DataField] + [DataField("bodySolutionName")] public string BodySolutionName = BloodstreamComponent.DefaultChemicalsSolutionName; /// /// Time in seconds between reagents being ingested and them being /// transferred to /// - [DataField] + [DataField("digestionDelay")] public float DigestionDelay = 20; /// /// A whitelist for what special-digestible-required foods this stomach is capable of eating. /// - [DataField] + [DataField("specialDigestible")] public EntityWhitelist? SpecialDigestible = null; /// diff --git a/Content.Server/Body/Systems/BloodstreamSystem.cs b/Content.Server/Body/Systems/BloodstreamSystem.cs index 21dc2f4526..cb83625615 100644 --- a/Content.Server/Body/Systems/BloodstreamSystem.cs +++ b/Content.Server/Body/Systems/BloodstreamSystem.cs @@ -1,8 +1,6 @@ using Content.Server.Body.Components; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Chemistry.ReactionEffects; using Content.Server.Fluids.EntitySystems; -using Content.Server.Forensics; using Content.Server.HealthExaminable; using Content.Server.Popups; using Content.Shared.Alert; @@ -18,9 +16,13 @@ using Content.Shared.Mobs.Systems; using Content.Shared.Popups; using Content.Shared.Rejuvenate; using Content.Shared.Speech.EntitySystems; -using Robust.Server.Audio; +using Robust.Server.GameObjects; using Robust.Shared.Prototypes; using Robust.Shared.Random; +using Content.Shared.Speech.EntitySystems; +using Robust.Server.Audio; +using Robust.Shared.GameObjects; +using Content.Server.Forensics; namespace Content.Server.Body.Systems; @@ -49,13 +51,14 @@ public sealed class BloodstreamSystem : EntitySystem SubscribeLocalEvent(OnBeingGibbed); SubscribeLocalEvent(OnApplyMetabolicMultiplier); SubscribeLocalEvent(OnReactionAttempt); - SubscribeLocalEvent>(OnReactionAttempt); SubscribeLocalEvent(OnRejuvenate); } - private void OnReactionAttempt(Entity entity, ref ReactionAttemptEvent args) + private void OnReactionAttempt(EntityUid uid, BloodstreamComponent component, ReactionAttemptEvent args) { - if (args.Cancelled) + if (args.Solution.Name != BloodstreamComponent.DefaultBloodSolutionName + && args.Solution.Name != BloodstreamComponent.DefaultChemicalsSolutionName + && args.Solution.Name != BloodstreamComponent.DefaultBloodTemporarySolutionName) return; foreach (var effect in args.Reaction.Effects) @@ -64,7 +67,7 @@ public sealed class BloodstreamSystem : EntitySystem { case CreateEntityReactionEffect: // Prevent entities from spawning in the bloodstream case AreaReactionEffect: // No spontaneous smoke or foam leaking out of blood vessels. - args.Cancelled = true; + args.Cancel(); return; } } @@ -78,16 +81,6 @@ public sealed class BloodstreamSystem : EntitySystem // Having cheese-clots form in your veins can't be good for you. } - private void OnReactionAttempt(Entity entity, ref SolutionRelayEvent args) - { - if (args.Name != entity.Comp.BloodSolutionName - && args.Name != entity.Comp.ChemicalSolutionName - && args.Name != entity.Comp.BloodTemporarySolutionName) - return; - - OnReactionAttempt(entity, ref args.Event); - } - public override void Update(float frameTime) { base.Update(frameTime); @@ -102,11 +95,8 @@ public sealed class BloodstreamSystem : EntitySystem bloodstream.AccumulatedFrametime -= bloodstream.UpdateInterval; - if (!_solutionContainerSystem.ResolveSolution(uid, bloodstream.BloodSolutionName, ref bloodstream.BloodSolution, out var bloodSolution)) - continue; - // Adds blood to their blood level if it is below the maximum; Blood regeneration. Must be alive. - if (bloodSolution.Volume < bloodSolution.MaxVolume && !_mobStateSystem.IsDead(uid)) + if (bloodstream.BloodSolution.Volume < bloodstream.BloodSolution.MaxVolume && !_mobStateSystem.IsDead(uid)) { TryModifyBloodLevel(uid, bloodstream.BloodRefreshAmount, bloodstream); } @@ -153,18 +143,19 @@ public sealed class BloodstreamSystem : EntitySystem } } - private void OnComponentInit(Entity entity, ref ComponentInit args) + private void OnComponentInit(EntityUid uid, BloodstreamComponent component, ComponentInit args) { - var chemicalSolution = _solutionContainerSystem.EnsureSolution(entity.Owner, entity.Comp.ChemicalSolutionName); - var bloodSolution = _solutionContainerSystem.EnsureSolution(entity.Owner, entity.Comp.BloodSolutionName); - var tempSolution = _solutionContainerSystem.EnsureSolution(entity.Owner, entity.Comp.BloodTemporarySolutionName); + component.ChemicalSolution = _solutionContainerSystem.EnsureSolution(uid, BloodstreamComponent.DefaultChemicalsSolutionName); + component.BloodSolution = _solutionContainerSystem.EnsureSolution(uid, BloodstreamComponent.DefaultBloodSolutionName); + component.BloodTemporarySolution = _solutionContainerSystem.EnsureSolution(uid, BloodstreamComponent.DefaultBloodTemporarySolutionName); - chemicalSolution.MaxVolume = entity.Comp.ChemicalMaxVolume; - bloodSolution.MaxVolume = entity.Comp.BloodMaxVolume; - tempSolution.MaxVolume = entity.Comp.BleedPuddleThreshold * 4; // give some leeway, for chemstream as well + component.ChemicalSolution.MaxVolume = component.ChemicalMaxVolume; + component.BloodSolution.MaxVolume = component.BloodMaxVolume; + component.BloodTemporarySolution.MaxVolume = component.BleedPuddleThreshold * 4; // give some leeway, for chemstream as well // Fill blood solution with BLOOD - bloodSolution.AddReagent(entity.Comp.BloodReagent, entity.Comp.BloodMaxVolume - bloodSolution.Volume); + _solutionContainerSystem.TryAddReagent(uid, component.BloodSolution, component.BloodReagent, + component.BloodMaxVolume, out _); } private void OnDamageChanged(EntityUid uid, BloodstreamComponent component, DamageChangedEvent args) @@ -259,45 +250,34 @@ public sealed class BloodstreamSystem : EntitySystem component.AccumulatedFrametime = component.UpdateInterval; } - private void OnRejuvenate(Entity entity, ref RejuvenateEvent args) + private void OnRejuvenate(EntityUid uid, BloodstreamComponent component, RejuvenateEvent args) { - TryModifyBleedAmount(entity.Owner, -entity.Comp.BleedAmount, entity.Comp); - - if (_solutionContainerSystem.ResolveSolution(entity.Owner, entity.Comp.BloodSolutionName, ref entity.Comp.BloodSolution, out var bloodSolution)) - TryModifyBloodLevel(entity.Owner, bloodSolution.AvailableVolume, entity.Comp); - - if (_solutionContainerSystem.ResolveSolution(entity.Owner, entity.Comp.ChemicalSolutionName, ref entity.Comp.ChemicalSolution)) - _solutionContainerSystem.RemoveAllSolution(entity.Comp.ChemicalSolution.Value); + TryModifyBleedAmount(uid, -component.BleedAmount, component); + TryModifyBloodLevel(uid, component.BloodSolution.AvailableVolume, component); + _solutionContainerSystem.RemoveAllSolution(uid, component.ChemicalSolution); } /// /// Attempt to transfer provided solution to internal solution. /// - public bool TryAddToChemicals(EntityUid uid, Solution solution, BloodstreamComponent? component = null) + public bool TryAddToChemicals(EntityUid uid, Solution solution, BloodstreamComponent? component=null) { if (!Resolve(uid, ref component, false)) return false; - if (!_solutionContainerSystem.ResolveSolution(uid, component.ChemicalSolutionName, ref component.ChemicalSolution)) - return false; - - return _solutionContainerSystem.TryAddSolution(component.ChemicalSolution.Value, solution); + return _solutionContainerSystem.TryAddSolution(uid, component.ChemicalSolution, solution); } - public bool FlushChemicals(EntityUid uid, string excludedReagentID, FixedPoint2 quantity, BloodstreamComponent? component = null) - { + public bool FlushChemicals(EntityUid uid, string excludedReagentID, FixedPoint2 quantity, BloodstreamComponent? component = null) { if (!Resolve(uid, ref component, false)) return false; - if (!_solutionContainerSystem.ResolveSolution(uid, component.ChemicalSolutionName, ref component.ChemicalSolution, out var chemSolution)) - return false; - - for (var i = chemSolution.Contents.Count - 1; i >= 0; i--) + for (var i = component.ChemicalSolution.Contents.Count - 1; i >= 0; i--) { - var (reagentId, _) = chemSolution.Contents[i]; + var (reagentId, _) = component.ChemicalSolution.Contents[i]; if (reagentId.Prototype != excludedReagentID) { - _solutionContainerSystem.RemoveReagent(component.ChemicalSolution.Value, reagentId, quantity); + _solutionContainerSystem.RemoveReagent(uid, component.ChemicalSolution, reagentId, quantity); } } @@ -309,10 +289,7 @@ public sealed class BloodstreamSystem : EntitySystem if (!Resolve(uid, ref component)) return 0.0f; - if (!_solutionContainerSystem.ResolveSolution(uid, component.BloodSolutionName, ref component.BloodSolution, out var bloodSolution)) - return 0.0f; - - return bloodSolution.FillFraction; + return component.BloodSolution.FillFraction; } public void SetBloodLossThreshold(EntityUid uid, float threshold, BloodstreamComponent? comp = null) @@ -331,41 +308,28 @@ public sealed class BloodstreamSystem : EntitySystem if (!Resolve(uid, ref component, false)) return false; - if (!_solutionContainerSystem.ResolveSolution(uid, component.BloodSolutionName, ref component.BloodSolution)) - return false; - if (amount >= 0) - return _solutionContainerSystem.TryAddReagent(component.BloodSolution.Value, component.BloodReagent, amount, out _); + return _solutionContainerSystem.TryAddReagent(uid, component.BloodSolution, component.BloodReagent, amount, out _); // Removal is more involved, // since we also wanna handle moving it to the temporary solution // and then spilling it if necessary. - var newSol = _solutionContainerSystem.SplitSolution(component.BloodSolution.Value, -amount); + var newSol = component.BloodSolution.SplitSolution(-amount); + component.BloodTemporarySolution.AddSolution(newSol, _prototypeManager); - if (!_solutionContainerSystem.ResolveSolution(uid, component.BloodTemporarySolutionName, ref component.TemporarySolution, out var tempSolution)) - return true; - - tempSolution.AddSolution(newSol, _prototypeManager); - - if (tempSolution.Volume > component.BleedPuddleThreshold) + if (component.BloodTemporarySolution.Volume > component.BleedPuddleThreshold) { // Pass some of the chemstream into the spilled blood. - if (_solutionContainerSystem.ResolveSolution(uid, component.ChemicalSolutionName, ref component.ChemicalSolution)) - { - var temp = _solutionContainerSystem.SplitSolution(component.ChemicalSolution.Value, tempSolution.Volume / 10); - tempSolution.AddSolution(temp, _prototypeManager); - } - - if (_puddleSystem.TrySpillAt(uid, tempSolution, out var puddleUid, false)) + var temp = component.ChemicalSolution.SplitSolution(component.BloodTemporarySolution.Volume / 10); + component.BloodTemporarySolution.AddSolution(temp, _prototypeManager); + if (_puddleSystem.TrySpillAt(uid, component.BloodTemporarySolution, out var puddleUid, false)) { _forensicsSystem.TransferDna(puddleUid, uid, false); } - tempSolution.RemoveAllSolution(); + component.BloodTemporarySolution.RemoveAllSolution(); } - _solutionContainerSystem.UpdateChemicals(component.TemporarySolution.Value); - return true; } @@ -399,28 +363,16 @@ public sealed class BloodstreamSystem : EntitySystem if (!Resolve(uid, ref component)) return; - var tempSol = new Solution(); + var max = component.BloodSolution.MaxVolume + component.BloodTemporarySolution.MaxVolume + + component.ChemicalSolution.MaxVolume; + var tempSol = new Solution() { MaxVolume = max }; - if (_solutionContainerSystem.ResolveSolution(uid, component.BloodSolutionName, ref component.BloodSolution, out var bloodSolution)) - { - tempSol.MaxVolume += bloodSolution.MaxVolume; - tempSol.AddSolution(bloodSolution, _prototypeManager); - _solutionContainerSystem.RemoveAllSolution(component.BloodSolution.Value); - } - - if (_solutionContainerSystem.ResolveSolution(uid, component.ChemicalSolutionName, ref component.ChemicalSolution, out var chemSolution)) - { - tempSol.MaxVolume += chemSolution.MaxVolume; - tempSol.AddSolution(chemSolution, _prototypeManager); - _solutionContainerSystem.RemoveAllSolution(component.ChemicalSolution.Value); - } - - if (_solutionContainerSystem.ResolveSolution(uid, component.BloodTemporarySolutionName, ref component.TemporarySolution, out var tempSolution)) - { - tempSol.MaxVolume += tempSolution.MaxVolume; - tempSol.AddSolution(tempSolution, _prototypeManager); - _solutionContainerSystem.RemoveAllSolution(component.TemporarySolution.Value); - } + tempSol.AddSolution(component.BloodSolution, _prototypeManager); + component.BloodSolution.RemoveAllSolution(); + tempSol.AddSolution(component.BloodTemporarySolution, _prototypeManager); + component.BloodTemporarySolution.RemoveAllSolution(); + tempSol.AddSolution(component.ChemicalSolution, _prototypeManager); + component.ChemicalSolution.RemoveAllSolution(); if (_puddleSystem.TrySpillAt(uid, tempSol, out var puddleUid)) { @@ -436,20 +388,13 @@ public sealed class BloodstreamSystem : EntitySystem if (!Resolve(uid, ref component, false)) return; - if (reagent == component.BloodReagent) + if(reagent == component.BloodReagent) return; - if (!_solutionContainerSystem.ResolveSolution(uid, component.BloodSolutionName, ref component.BloodSolution, out var bloodSolution)) - { - component.BloodReagent = reagent; - return; - } - - var currentVolume = bloodSolution.RemoveReagent(component.BloodReagent, bloodSolution.Volume); + var currentVolume = component.BloodSolution.Volume; component.BloodReagent = reagent; - - if (currentVolume > 0) - _solutionContainerSystem.TryAddReagent(component.BloodSolution.Value, component.BloodReagent, currentVolume, out _); + component.BloodSolution.RemoveAllSolution(); + _solutionContainerSystem.TryAddReagent(uid, component.BloodSolution, component.BloodReagent, currentVolume, out _); } } diff --git a/Content.Server/Body/Systems/LungSystem.cs b/Content.Server/Body/Systems/LungSystem.cs index b5bac50739..3aef2486e7 100644 --- a/Content.Server/Body/Systems/LungSystem.cs +++ b/Content.Server/Body/Systems/LungSystem.cs @@ -1,8 +1,8 @@ using Content.Server.Atmos.Components; using Content.Server.Atmos.EntitySystems; using Content.Server.Body.Components; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Shared.Atmos; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Clothing; using Content.Shared.Inventory.Events; @@ -44,11 +44,11 @@ public sealed class LungSystem : EntitySystem } } - private void OnComponentInit(Entity entity, ref ComponentInit args) + private void OnComponentInit(EntityUid uid, LungComponent component, ComponentInit args) { - var solution = _solutionContainerSystem.EnsureSolution(entity.Owner, entity.Comp.SolutionName); - solution.MaxVolume = 100.0f; - solution.CanReact = false; // No dexalin lungs + component.LungSolution = _solutionContainerSystem.EnsureSolution(uid, LungSolutionName); + component.LungSolution.MaxVolume = 100.0f; + component.LungSolution.CanReact = false; // No dexalin lungs } private void OnMaskToggled(Entity ent, ref ItemMaskToggledEvent args) @@ -71,9 +71,6 @@ public sealed class LungSystem : EntitySystem public void GasToReagent(EntityUid uid, LungComponent lung) { - if (!_solutionContainerSystem.ResolveSolution(uid, lung.SolutionName, ref lung.Solution, out var solution)) - return; - foreach (var gas in Enum.GetValues()) { var i = (int) gas; @@ -84,13 +81,11 @@ public sealed class LungSystem : EntitySystem if (reagent == null) continue; var amount = moles * Atmospherics.BreathMolesToReagentMultiplier; - solution.AddReagent(reagent, amount); + _solutionContainerSystem.TryAddReagent(uid, lung.LungSolution, reagent, amount, out _); // We don't remove the gas from the lung mix, // that's the responsibility of whatever gas is being metabolized. // Most things will just want to exhale again. } - - _solutionContainerSystem.UpdateChemicals(lung.Solution.Value); } } diff --git a/Content.Server/Body/Systems/MetabolizerSystem.cs b/Content.Server/Body/Systems/MetabolizerSystem.cs index d05e6c7f79..c8851b49ac 100644 --- a/Content.Server/Body/Systems/MetabolizerSystem.cs +++ b/Content.Server/Body/Systems/MetabolizerSystem.cs @@ -1,9 +1,9 @@ using Content.Server.Body.Components; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Shared.Administration.Logs; using Content.Shared.Body.Organ; using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Components.SolutionManager; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Chemistry.Reagent; using Content.Shared.Database; using Content.Shared.FixedPoint; @@ -37,15 +37,15 @@ namespace Content.Server.Body.Systems SubscribeLocalEvent(OnApplyMetabolicMultiplier); } - private void OnMetabolizerInit(Entity entity, ref ComponentInit args) + private void OnMetabolizerInit(EntityUid uid, MetabolizerComponent component, ComponentInit args) { - if (!entity.Comp.SolutionOnBody) + if (!component.SolutionOnBody) { - _solutionContainerSystem.EnsureSolution(entity.Owner, entity.Comp.SolutionName); + _solutionContainerSystem.EnsureSolution(uid, component.SolutionName); } - else if (_organQuery.CompOrNull(entity)?.Body is { } body) + else if (_organQuery.CompOrNull(uid)?.Body is { } body) { - _solutionContainerSystem.EnsureSolution(body, entity.Comp.SolutionName); + _solutionContainerSystem.EnsureSolution(body, component.SolutionName); } } @@ -95,7 +95,6 @@ namespace Content.Server.Body.Systems // First step is get the solution we actually care about Solution? solution = null; - Entity? soln = default!; EntityUid? solutionEntityUid = null; SolutionContainerManagerComponent? manager = null; @@ -107,7 +106,7 @@ namespace Content.Server.Body.Systems if (!_solutionQuery.Resolve(body, ref manager, false)) return; - _solutionContainerSystem.TryGetSolution((body, manager), meta.SolutionName, out soln, out solution); + _solutionContainerSystem.TryGetSolution(body, meta.SolutionName, out solution, manager); solutionEntityUid = body; } } @@ -116,11 +115,11 @@ namespace Content.Server.Body.Systems if (!_solutionQuery.Resolve(uid, ref manager, false)) return; - _solutionContainerSystem.TryGetSolution((uid, manager), meta.SolutionName, out soln, out solution); + _solutionContainerSystem.TryGetSolution(uid, meta.SolutionName, out solution, manager); solutionEntityUid = uid; } - if (solutionEntityUid == null || soln is null || solution is null || solution.Contents.Count == 0) + if (solutionEntityUid == null || solution == null || solution.Contents.Count == 0) return; // randomize the reagent list so we don't have any weird quirks @@ -139,7 +138,8 @@ namespace Content.Server.Body.Systems { if (meta.RemoveEmpty) { - solution.RemoveReagent(reagent, FixedPoint2.New(1)); + _solutionContainerSystem.RemoveReagent(solutionEntityUid.Value, solution, reagent, + FixedPoint2.New(1)); } continue; @@ -198,14 +198,12 @@ namespace Content.Server.Body.Systems // remove a certain amount of reagent if (mostToRemove > FixedPoint2.Zero) { - solution.RemoveReagent(reagent, mostToRemove); + _solutionContainerSystem.RemoveReagent(solutionEntityUid.Value, solution, reagent, mostToRemove); // We have processed a reagant, so count it towards the cap reagents += 1; } } - - _solutionContainerSystem.UpdateChemicals(soln.Value); } } diff --git a/Content.Server/Body/Systems/RespiratorSystem.cs b/Content.Server/Body/Systems/RespiratorSystem.cs index b814422181..3fa8f59a1d 100644 --- a/Content.Server/Body/Systems/RespiratorSystem.cs +++ b/Content.Server/Body/Systems/RespiratorSystem.cs @@ -2,7 +2,6 @@ using Content.Server.Administration.Logs; using Content.Server.Atmos; using Content.Server.Atmos.EntitySystems; using Content.Server.Body.Components; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Popups; using Content.Shared.Alert; using Content.Shared.Atmos; @@ -27,7 +26,6 @@ namespace Content.Server.Body.Systems [Dependency] private readonly LungSystem _lungSystem = default!; [Dependency] private readonly PopupSystem _popupSystem = default!; [Dependency] private readonly MobStateSystem _mobState = default!; - [Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!; public override void Initialize() { @@ -146,9 +144,7 @@ namespace Content.Server.Body.Systems { _atmosSys.Merge(outGas, lung.Air); lung.Air.Clear(); - - if (_solutionContainerSystem.ResolveSolution(lung.Owner, lung.SolutionName, ref lung.Solution)) - _solutionContainerSystem.RemoveAllSolution(lung.Solution.Value); + lung.LungSolution.RemoveAllSolution(); } _atmosSys.Merge(ev.Gas, outGas); diff --git a/Content.Server/Body/Systems/StomachSystem.cs b/Content.Server/Body/Systems/StomachSystem.cs index 4c11244c37..5a3f6cf31a 100644 --- a/Content.Server/Body/Systems/StomachSystem.cs +++ b/Content.Server/Body/Systems/StomachSystem.cs @@ -1,8 +1,8 @@ using Content.Server.Body.Components; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Shared.Body.Organ; using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Components.SolutionManager; +using Content.Shared.Chemistry.EntitySystems; using Robust.Shared.Utility; namespace Content.Server.Body.Systems @@ -31,7 +31,8 @@ namespace Content.Server.Body.Systems stomach.AccumulatedFrameTime -= stomach.UpdateInterval; // Get our solutions - if (!_solutionContainerSystem.ResolveSolution((uid, sol), DefaultSolutionName, ref stomach.Solution, out var stomachSolution)) + if (!_solutionContainerSystem.TryGetSolution(uid, DefaultSolutionName, + out var stomachSolution, sol)) continue; if (organ.Body is not { } body || !_solutionContainerSystem.TryGetSolution(body, stomach.BodySolutionName, out var bodySolution)) @@ -50,7 +51,7 @@ namespace Content.Server.Body.Systems if (reagent.Quantity > delta.ReagentQuantity.Quantity) reagent = new(reagent.Reagent, delta.ReagentQuantity.Quantity); - stomachSolution.RemoveReagent(reagent); + _solutionContainerSystem.RemoveReagent(uid, stomachSolution, reagent); transferSolution.AddReagent(reagent); } @@ -63,10 +64,8 @@ namespace Content.Server.Body.Systems stomach.ReagentDeltas.Remove(item); } - _solutionContainerSystem.UpdateChemicals(stomach.Solution.Value); - // Transfer everything to the body solution! - _solutionContainerSystem.TryAddSolution(bodySolution.Value, transferSolution); + _solutionContainerSystem.TryAddSolution(body, bodySolution, transferSolution); } } @@ -87,13 +86,12 @@ namespace Content.Server.Body.Systems } public bool CanTransferSolution(EntityUid uid, Solution solution, - StomachComponent? stomach = null, SolutionContainerManagerComponent? solutions = null) { - if (!Resolve(uid, ref stomach, ref solutions, false)) + if (!Resolve(uid, ref solutions, false)) return false; - if (!_solutionContainerSystem.ResolveSolution((uid, solutions), DefaultSolutionName, ref stomach.Solution, out var stomachSolution)) + if (!_solutionContainerSystem.TryGetSolution(uid, DefaultSolutionName, out var stomachSolution, solutions)) return false; // TODO: For now no partial transfers. Potentially change by design @@ -110,11 +108,11 @@ namespace Content.Server.Body.Systems if (!Resolve(uid, ref stomach, ref solutions, false)) return false; - if (!_solutionContainerSystem.ResolveSolution((uid, solutions), DefaultSolutionName, ref stomach.Solution) - || !CanTransferSolution(uid, solution, stomach, solutions)) + if (!_solutionContainerSystem.TryGetSolution(uid, DefaultSolutionName, out var stomachSolution, solutions) + || !CanTransferSolution(uid, solution, solutions)) return false; - _solutionContainerSystem.TryAddSolution(stomach.Solution.Value, solution); + _solutionContainerSystem.TryAddSolution(uid, stomachSolution, solution); // Add each reagent to ReagentDeltas. Used to track how long each reagent has been in the stomach foreach (var reagent in solution.Contents) { diff --git a/Content.Server/Botany/Components/PlantHolderComponent.cs b/Content.Server/Botany/Components/PlantHolderComponent.cs index 809af737ac..9825167ca2 100644 --- a/Content.Server/Botany/Components/PlantHolderComponent.cs +++ b/Content.Server/Botany/Components/PlantHolderComponent.cs @@ -1,4 +1,3 @@ -using Content.Shared.Chemistry.Components; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; namespace Content.Server.Botany.Components; @@ -91,7 +90,4 @@ public sealed partial class PlantHolderComponent : Component [ViewVariables(VVAccess.ReadWrite), DataField("solution")] public string SoilSolutionName = "soil"; - - [DataField] - public Entity? SoilSolution = null; } diff --git a/Content.Server/Botany/Systems/BotanySystem.Produce.cs b/Content.Server/Botany/Systems/BotanySystem.Produce.cs index 788c09821b..3cfb21f3c4 100644 --- a/Content.Server/Botany/Systems/BotanySystem.Produce.cs +++ b/Content.Server/Botany/Systems/BotanySystem.Produce.cs @@ -1,5 +1,6 @@ using Content.Server.Botany.Components; using Content.Shared.FixedPoint; +using Robust.Server.GameObjects; namespace Content.Server.Botany.Systems; @@ -10,7 +11,7 @@ public sealed partial class BotanySystem if (!TryGetSeed(produce, out var seed)) return; - var solutionContainer = _solutionContainerSystem.EnsureSolution(uid, produce.SolutionName, FixedPoint2.Zero, out _); + var solutionContainer = _solutionContainerSystem.EnsureSolution(uid, produce.SolutionName); solutionContainer.RemoveAllSolution(); foreach (var (chem, quantity) in seed.Chemicals) diff --git a/Content.Server/Botany/Systems/BotanySystem.Seed.cs b/Content.Server/Botany/Systems/BotanySystem.Seed.cs index 1fb6952e91..02fb1060f3 100644 --- a/Content.Server/Botany/Systems/BotanySystem.Seed.cs +++ b/Content.Server/Botany/Systems/BotanySystem.Seed.cs @@ -1,8 +1,10 @@ +using System.Diagnostics.CodeAnalysis; +using System.Linq; using Content.Server.Botany.Components; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Kitchen.Components; using Content.Server.Popups; using Content.Shared.Botany; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Examine; using Content.Shared.Hands.EntitySystems; using Content.Shared.Physics; @@ -18,8 +20,6 @@ using Robust.Shared.Physics.Components; using Robust.Shared.Physics.Systems; using Robust.Shared.Prototypes; using Robust.Shared.Random; -using System.Diagnostics.CodeAnalysis; -using System.Linq; namespace Content.Server.Botany.Systems; diff --git a/Content.Server/Botany/Systems/PlantHolderSystem.cs b/Content.Server/Botany/Systems/PlantHolderSystem.cs index 96fde08118..027ca9b038 100644 --- a/Content.Server/Botany/Systems/PlantHolderSystem.cs +++ b/Content.Server/Botany/Systems/PlantHolderSystem.cs @@ -1,12 +1,12 @@ using Content.Server.Atmos; using Content.Server.Atmos.EntitySystems; using Content.Server.Botany.Components; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Fluids.Components; using Content.Server.Ghost.Roles.Components; using Content.Server.Kitchen.Components; using Content.Server.Popups; using Content.Shared.Botany; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Chemistry.Reagent; using Content.Shared.Coordinates.Helpers; using Content.Shared.Examine; @@ -38,7 +38,7 @@ public sealed class PlantHolderSystem : EntitySystem [Dependency] private readonly PopupSystem _popup = default!; [Dependency] private readonly IGameTiming _gameTiming = default!; [Dependency] private readonly SharedPointLightSystem _pointLight = default!; - [Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!; + [Dependency] private readonly SolutionContainerSystem _solutionSystem = default!; [Dependency] private readonly TagSystem _tagSystem = default!; [Dependency] private readonly RandomHelperSystem _randomHelper = default!; [Dependency] private readonly IRobustRandom _random = default!; @@ -70,13 +70,11 @@ public sealed class PlantHolderSystem : EntitySystem } } - private void OnExamine(Entity entity, ref ExaminedEvent args) + private void OnExamine(EntityUid uid, PlantHolderComponent component, ExaminedEvent args) { if (!args.IsInDetailsRange) return; - var (_, component) = entity; - if (component.Seed == null) { args.PushMarkup(Loc.GetString("plant-holder-component-nothing-planted-message")); @@ -133,10 +131,8 @@ public sealed class PlantHolderSystem : EntitySystem } } - private void OnInteractUsing(Entity entity, ref InteractUsingEvent args) + private void OnInteractUsing(EntityUid uid, PlantHolderComponent component, InteractUsingEvent args) { - var (uid, component) = entity; - if (TryComp(args.Used, out SeedComponent? seeds)) { if (component.Seed == null) @@ -207,8 +203,8 @@ public sealed class PlantHolderSystem : EntitySystem return; } - if (_solutionContainerSystem.TryGetDrainableSolution(args.Used, out var solution, out _) - && _solutionContainerSystem.ResolveSolution(uid, component.SoilSolutionName, ref component.SoilSolution) + if (_solutionSystem.TryGetDrainableSolution(args.Used, out var solution) + && _solutionSystem.TryGetSolution(uid, component.SoilSolutionName, out var targetSolution) && TryComp(args.Used, out SprayComponent? spray)) { var amount = FixedPoint2.New(1); @@ -218,7 +214,7 @@ public sealed class PlantHolderSystem : EntitySystem _audio.PlayPvs(spray.SpraySound, args.Used, AudioParams.Default.WithVariation(0.125f)); - var split = _solutionContainerSystem.Drain(solutionEntity, solution.Value, amount); + var split = _solutionSystem.Drain(solutionEntity, solution, amount); if (split.Volume == 0) { @@ -231,7 +227,7 @@ public sealed class PlantHolderSystem : EntitySystem ("owner", uid), ("amount", split.Volume)), args.User, PopupType.Medium); - _solutionContainerSystem.TryAddSolution(component.SoilSolution.Value, split); + _solutionSystem.TryAddSolution(targetEntity, targetSolution, split); ForceUpdateByExternalCause(uid, component); @@ -294,15 +290,16 @@ public sealed class PlantHolderSystem : EntitySystem ("usingItem", args.Used), ("owner", uid)), uid, Filter.PvsExcept(args.User), true); - if (_solutionContainerSystem.TryGetSolution(args.Used, produce.SolutionName, out var soln2, out var solution2)) + if (_solutionSystem.TryGetSolution(args.Used, produce.SolutionName, out var solution2)) { - if (_solutionContainerSystem.ResolveSolution(uid, component.SoilSolutionName, ref component.SoilSolution, out var solution1)) + if (_solutionSystem.TryGetSolution(uid, component.SoilSolutionName, out var solution1)) { // We try to fit as much of the composted plant's contained solution into the hydroponics tray as we can, // since the plant will be consumed anyway. var fillAmount = FixedPoint2.Min(solution2.Volume, solution1.AvailableVolume); - _solutionContainerSystem.TryAddSolution(component.SoilSolution.Value, _solutionContainerSystem.SplitSolution(soln2.Value, fillAmount)); + _solutionSystem.TryAddSolution(uid, solution1, + _solutionSystem.SplitSolution(args.Used, solution2, fillAmount)); ForceUpdateByExternalCause(uid, component); } @@ -317,9 +314,9 @@ public sealed class PlantHolderSystem : EntitySystem } } - private void OnInteractHand(Entity entity, ref InteractHandEvent args) + private void OnInteractHand(EntityUid uid, PlantHolderComponent component, InteractHandEvent args) { - DoHarvest(entity, args.User, entity.Comp); + DoHarvest(uid, args.User, component); } public void WeedInvasion() @@ -822,13 +819,13 @@ public sealed class PlantHolderSystem : EntitySystem if (!Resolve(uid, ref component)) return; - if (!_solutionContainerSystem.ResolveSolution(uid, component.SoilSolutionName, ref component.SoilSolution, out var solution)) + if (!_solutionSystem.TryGetSolution(uid, component.SoilSolutionName, out var solution)) return; if (solution.Volume > 0 && component.MutationLevel < 25) { var amt = FixedPoint2.New(1); - foreach (var entry in _solutionContainerSystem.RemoveEachReagent(component.SoilSolution.Value, amt)) + foreach (var entry in _solutionSystem.RemoveEachReagent(uid, solution, amt)) { var reagentProto = _prototype.Index(entry.Reagent.Prototype); reagentProto.ReactionPlant(uid, entry, solution); diff --git a/Content.Server/Cargo/Systems/PricingSystem.cs b/Content.Server/Cargo/Systems/PricingSystem.cs index 6fb36c9608..5bbe1e5a6d 100644 --- a/Content.Server/Cargo/Systems/PricingSystem.cs +++ b/Content.Server/Cargo/Systems/PricingSystem.cs @@ -1,7 +1,7 @@ -using Content.Server.Administration; +using System.Linq; +using Content.Server.Administration; using Content.Server.Body.Systems; using Content.Server.Cargo.Components; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Shared.Administration; using Content.Shared.Body.Components; using Content.Shared.Chemistry.Components.SolutionManager; @@ -16,7 +16,6 @@ using Robust.Shared.Map; using Robust.Shared.Map.Components; using Robust.Shared.Prototypes; using Robust.Shared.Utility; -using System.Linq; namespace Content.Server.Cargo.Systems; @@ -31,7 +30,6 @@ public sealed class PricingSystem : EntitySystem [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly BodySystem _bodySystem = default!; [Dependency] private readonly MobStateSystem _mobStateSystem = default!; - [Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!; /// public override void Initialize() @@ -108,36 +106,13 @@ public sealed class PricingSystem : EntitySystem args.Price += (component.Price - partPenalty) * (_mobStateSystem.IsAlive(uid, state) ? 1.0 : component.DeathPenalty); } - private double GetSolutionPrice(Entity entity) - { - if (Comp(entity).EntityLifeStage < EntityLifeStage.MapInitialized) - return GetSolutionPrice(entity.Comp); - - var price = 0.0; - - foreach (var (_, soln) in _solutionContainerSystem.EnumerateSolutions((entity.Owner, entity.Comp))) - { - var solution = soln.Comp.Solution; - foreach (var (reagent, quantity) in solution.Contents) - { - if (!_prototypeManager.TryIndex(reagent.Prototype, out var reagentProto)) - continue; - - // TODO check ReagentData for price information? - price += (float) quantity * reagentProto.PricePerUnit; - } - } - - return price; - } - private double GetSolutionPrice(SolutionContainerManagerComponent component) { var price = 0.0; - foreach (var (_, prototype) in _solutionContainerSystem.EnumerateSolutions(component)) + foreach (var solution in component.Solutions.Values) { - foreach (var (reagent, quantity) in prototype.Contents) + foreach (var (reagent, quantity) in solution.Contents) { if (!_prototypeManager.TryIndex(reagent.Prototype, out var reagentProto)) continue; @@ -282,7 +257,7 @@ public sealed class PricingSystem : EntitySystem if (TryComp(uid, out var solComp)) { - price += GetSolutionPrice((uid, solComp)); + price += GetSolutionPrice(solComp); } return price; diff --git a/Content.Server/Chemistry/Components/HyposprayComponent.cs b/Content.Server/Chemistry/Components/HyposprayComponent.cs index 2a80cec801..76bb0e8d41 100644 --- a/Content.Server/Chemistry/Components/HyposprayComponent.cs +++ b/Content.Server/Chemistry/Components/HyposprayComponent.cs @@ -1,3 +1,4 @@ +using Content.Server.Chemistry.EntitySystems; using Content.Shared.Chemistry.Components; using Content.Shared.FixedPoint; using Robust.Shared.Audio; diff --git a/Content.Server/Chemistry/Components/SolutionRegenerationComponent.cs b/Content.Server/Chemistry/Components/SolutionRegenerationComponent.cs index 7fe2dacb67..1fc5772d4e 100644 --- a/Content.Server/Chemistry/Components/SolutionRegenerationComponent.cs +++ b/Content.Server/Chemistry/Components/SolutionRegenerationComponent.cs @@ -1,6 +1,8 @@ using Content.Server.Chemistry.EntitySystems; using Content.Shared.Chemistry.Components; +using Content.Shared.FixedPoint; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; namespace Content.Server.Chemistry.Components; @@ -15,13 +17,7 @@ public sealed partial class SolutionRegenerationComponent : Component /// The name of the solution to add to. /// [DataField("solution", required: true), ViewVariables(VVAccess.ReadWrite)] - public string SolutionName = string.Empty; - - /// - /// The solution to add reagents to. - /// - [DataField("solutionRef")] - public Entity? Solution = null; + public string Solution = string.Empty; /// /// The reagent(s) to be regenerated in the solution. diff --git a/Content.Server/Chemistry/Containers/EntitySystems/SolutionContainerSystem.cs b/Content.Server/Chemistry/Containers/EntitySystems/SolutionContainerSystem.cs deleted file mode 100644 index 5ccccdbbf5..0000000000 --- a/Content.Server/Chemistry/Containers/EntitySystems/SolutionContainerSystem.cs +++ /dev/null @@ -1,185 +0,0 @@ -using Content.Shared.Chemistry.Components; -using Content.Shared.Chemistry.Components.SolutionManager; -using Content.Shared.Chemistry.EntitySystems; -using Content.Shared.FixedPoint; -using Robust.Shared.Containers; -using Robust.Shared.Map; -using Robust.Shared.Network; -using Robust.Shared.Utility; -using System.Numerics; - -namespace Content.Server.Chemistry.Containers.EntitySystems; - -public sealed partial class SolutionContainerSystem : SharedSolutionContainerSystem -{ - [Dependency] private readonly INetManager _netManager = default!; - - public override void Initialize() - { - base.Initialize(); - - SubscribeLocalEvent(OnMapInit); - SubscribeLocalEvent(OnComponentShutdown); - SubscribeLocalEvent(OnComponentShutdown); - } - - - public Solution EnsureSolution(Entity entity, string name) - => EnsureSolution(entity, name, out _); - - public Solution EnsureSolution(Entity entity, string name, out bool existed) - => EnsureSolution(entity, name, FixedPoint2.Zero, out existed); - - public Solution EnsureSolution(Entity entity, string name, FixedPoint2 minVol, out bool existed) - => EnsureSolution(entity, name, minVol, null, out existed); - - public Solution EnsureSolution(Entity entity, string name, FixedPoint2 minVol, Solution? prototype, out bool existed) - { - var (uid, meta) = entity; - DebugTools.Assert(Resolve(uid, ref meta), $"Attempted to ensure solution on invalid entity {ToPrettyString(entity.Owner)}"); - - var manager = EnsureComp(uid); - if (meta.EntityLifeStage >= EntityLifeStage.MapInitialized) - return EnsureSolutionEntity((uid, manager), name, minVol, prototype, out existed).Comp.Solution; - else - return EnsureSolutionPrototype((uid, manager), name, minVol, prototype, out existed); - } - - public Entity EnsureSolutionEntity(Entity entity, string name, FixedPoint2 minVol, Solution? prototype, out bool existed) - { - existed = true; - - var (uid, container) = entity; - - var solutionSlot = ContainerSystem.EnsureContainer(uid, $"solution@{name}", out existed); - if (!Resolve(uid, ref container, logMissing: false)) - { - existed = false; - container = AddComp(uid); - container.Containers.Add(name); - } - else if (!existed) - { - container.Containers.Add(name); - Dirty(uid, container); - } - - var needsInit = false; - SolutionComponent solutionComp; - if (solutionSlot.ContainedEntity is not { } solutionId) - { - prototype ??= new() { MaxVolume = minVol }; - prototype.Name = name; - (solutionId, solutionComp, _) = SpawnSolutionUninitialized(solutionSlot, name, minVol, prototype); - existed = false; - needsInit = true; - Dirty(uid, container); - } - else - { - solutionComp = Comp(solutionId); - DebugTools.Assert(TryComp(solutionId, out ContainedSolutionComponent? relation) && relation.Container == uid && relation.ContainerName == name); - DebugTools.Assert(solutionComp.Solution.Name == name); - - var solution = solutionComp.Solution; - solution.MaxVolume = FixedPoint2.Max(solution.MaxVolume, minVol); - - // Depending on MapInitEvent order some systems can ensure solution empty solutions and conflict with the prototype solutions. - // We want the reagents from the prototype to exist even if something else already created the solution. - if (prototype is { Volume.Value: > 0 }) - solution.AddSolution(prototype, PrototypeManager); - - Dirty(solutionId, solutionComp); - } - - if (needsInit) - EntityManager.InitializeAndStartEntity(solutionId, Transform(solutionId).MapID); - - return (solutionId, solutionComp); - } - - private Solution EnsureSolutionPrototype(Entity entity, string name, FixedPoint2 minVol, Solution? prototype, out bool existed) - { - existed = true; - - var (uid, container) = entity; - if (!Resolve(uid, ref container, logMissing: false)) - { - container = AddComp(uid); - existed = false; - } - - if (container.Solutions is null) - container.Solutions = new(SolutionContainerManagerComponent.DefaultCapacity); - - if (!container.Solutions.TryGetValue(name, out var solution)) - { - solution = prototype ?? new() { Name = name, MaxVolume = minVol }; - container.Solutions.Add(name, solution); - existed = false; - } - else - solution.MaxVolume = FixedPoint2.Max(solution.MaxVolume, minVol); - - Dirty(uid, container); - return solution; - } - - - private Entity SpawnSolutionUninitialized(ContainerSlot container, string name, FixedPoint2 minVol, Solution prototype) - { - var coords = new EntityCoordinates(container.Owner, Vector2.Zero); - var uid = EntityManager.CreateEntityUninitialized(null, coords, null); - - var solution = new SolutionComponent() { Solution = prototype }; - AddComp(uid, solution); - - var relation = new ContainedSolutionComponent() { Container = container.Owner, ContainerName = name }; - AddComp(uid, relation); - - ContainerSystem.Insert(uid, container, force: true); - - return (uid, solution, relation); - } - - - #region Event Handlers - - private void OnMapInit(Entity entity, ref MapInitEvent args) - { - if (entity.Comp.Solutions is not { } prototypes) - return; - - foreach (var (name, prototype) in prototypes) - { - EnsureSolutionEntity((entity.Owner, entity.Comp), name, prototype.MaxVolume, prototype, out _); - } - - entity.Comp.Solutions = null; - Dirty(entity); - } - - private void OnComponentShutdown(Entity entity, ref ComponentShutdown args) - { - foreach (var name in entity.Comp.Containers) - { - if (ContainerSystem.TryGetContainer(entity, $"solution@{name}", out var solutionContainer)) - ContainerSystem.ShutdownContainer(solutionContainer); - } - entity.Comp.Containers.Clear(); - } - - private void OnComponentShutdown(Entity entity, ref ComponentShutdown args) - { - if (TryComp(entity.Comp.Container, out SolutionContainerManagerComponent? container)) - { - container.Containers.Remove(entity.Comp.ContainerName); - Dirty(entity.Comp.Container, container); - } - - if (ContainerSystem.TryGetContainer(entity, $"solution@{entity.Comp.ContainerName}", out var solutionContainer)) - ContainerSystem.ShutdownContainer(solutionContainer); - } - - #endregion Event Handlers -} diff --git a/Content.Server/Chemistry/EntitySystems/ChemMasterSystem.cs b/Content.Server/Chemistry/EntitySystems/ChemMasterSystem.cs index 2cc0f3d055..cbb84be83c 100644 --- a/Content.Server/Chemistry/EntitySystems/ChemMasterSystem.cs +++ b/Content.Server/Chemistry/EntitySystems/ChemMasterSystem.cs @@ -1,5 +1,6 @@ +using System.Diagnostics.CodeAnalysis; +using System.Linq; using Content.Server.Chemistry.Components; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Labels; using Content.Server.Popups; using Content.Server.Storage.EntitySystems; @@ -18,8 +19,6 @@ using Robust.Server.GameObjects; using Robust.Shared.Audio; using Robust.Shared.Containers; using Robust.Shared.Prototypes; -using System.Diagnostics.CodeAnalysis; -using System.Linq; namespace Content.Server.Chemistry.EntitySystems { @@ -48,7 +47,7 @@ namespace Content.Server.Chemistry.EntitySystems base.Initialize(); SubscribeLocalEvent(SubscribeUpdateUiState); - SubscribeLocalEvent(SubscribeUpdateUiState); + SubscribeLocalEvent(SubscribeUpdateUiState); SubscribeLocalEvent(SubscribeUpdateUiState); SubscribeLocalEvent(SubscribeUpdateUiState); SubscribeLocalEvent(SubscribeUpdateUiState); @@ -68,7 +67,7 @@ namespace Content.Server.Chemistry.EntitySystems private void UpdateUiState(Entity ent, bool updateLabel = false) { var (owner, chemMaster) = ent; - if (!_solutionContainerSystem.TryGetSolution(owner, SharedChemMaster.BufferSolutionName, out _, out var bufferSolution)) + if (!_solutionContainerSystem.TryGetSolution(owner, SharedChemMaster.BufferSolutionName, out var bufferSolution)) return; var inputContainer = _itemSlotsSystem.GetItemOrNull(owner, SharedChemMaster.InputSlotName); var outputContainer = _itemSlotsSystem.GetItemOrNull(owner, SharedChemMaster.OutputSlotName); @@ -131,8 +130,8 @@ namespace Content.Server.Chemistry.EntitySystems { var container = _itemSlotsSystem.GetItemOrNull(chemMaster, SharedChemMaster.InputSlotName); if (container is null || - !_solutionContainerSystem.TryGetFitsInDispenser(container.Value, out var containerSoln, out var containerSolution) || - !_solutionContainerSystem.TryGetSolution(chemMaster.Owner, SharedChemMaster.BufferSolutionName, out _, out var bufferSolution)) + !_solutionContainerSystem.TryGetFitsInDispenser(container.Value, out var containerSolution) || + !_solutionContainerSystem.TryGetSolution(chemMaster, SharedChemMaster.BufferSolutionName, out var bufferSolution)) { return; } @@ -141,12 +140,12 @@ namespace Content.Server.Chemistry.EntitySystems { amount = FixedPoint2.Min(amount, containerSolution.AvailableVolume); amount = bufferSolution.RemoveReagent(id, amount); - _solutionContainerSystem.TryAddReagent(containerSoln.Value, id, amount, out var _); + _solutionContainerSystem.TryAddReagent(container.Value, containerSolution, id, amount, out var _); } else // Container to buffer { amount = FixedPoint2.Min(amount, containerSolution.GetReagentQuantity(id)); - _solutionContainerSystem.RemoveReagent(containerSoln.Value, id, amount); + _solutionContainerSystem.RemoveReagent(container.Value, containerSolution, id, amount); bufferSolution.AddReagent(id, amount); } @@ -157,7 +156,7 @@ namespace Content.Server.Chemistry.EntitySystems { if (fromBuffer) { - if (_solutionContainerSystem.TryGetSolution(chemMaster.Owner, SharedChemMaster.BufferSolutionName, out _, out var bufferSolution)) + if (_solutionContainerSystem.TryGetSolution(chemMaster, SharedChemMaster.BufferSolutionName, out var bufferSolution)) bufferSolution.RemoveReagent(id, amount); else return; @@ -166,9 +165,9 @@ namespace Content.Server.Chemistry.EntitySystems { var container = _itemSlotsSystem.GetItemOrNull(chemMaster, SharedChemMaster.InputSlotName); if (container is not null && - _solutionContainerSystem.TryGetFitsInDispenser(container.Value, out var containerSolution, out _)) + _solutionContainerSystem.TryGetFitsInDispenser(container.Value, out var containerSolution)) { - _solutionContainerSystem.RemoveReagent(containerSolution.Value, id, amount); + _solutionContainerSystem.RemoveReagent(container.Value, containerSolution, id, amount); } else return; @@ -211,8 +210,10 @@ namespace Content.Server.Chemistry.EntitySystems _storageSystem.Insert(container, item, out _, user: user, storage); _labelSystem.Label(item, message.Label); - var itemSolution = _solutionContainerSystem.EnsureSolutionEntity(item, SharedChemMaster.PillSolutionName, message.Dosage, null, out _); - _solutionContainerSystem.TryAddSolution(itemSolution, withdrawal.SplitSolution(message.Dosage)); + var itemSolution = _solutionContainerSystem.EnsureSolution(item, SharedChemMaster.PillSolutionName); + + _solutionContainerSystem.TryAddSolution( + item, itemSolution, withdrawal.SplitSolution(message.Dosage)); var pill = EnsureComp(item); pill.PillType = chemMaster.Comp.PillType; @@ -222,13 +223,13 @@ namespace Content.Server.Chemistry.EntitySystems { // Log pill creation by a user _adminLogger.Add(LogType.Action, LogImpact.Low, - $"{ToPrettyString(user.Value):user} printed {ToPrettyString(item):pill} {SolutionContainerSystem.ToPrettyString(itemSolution.Comp.Solution)}"); + $"{ToPrettyString(user.Value):user} printed {ToPrettyString(item):pill} {SolutionContainerSystem.ToPrettyString(itemSolution)}"); } else { // Log pill creation by magic? This should never happen... right? _adminLogger.Add(LogType.Action, LogImpact.Low, - $"Unknown printed {ToPrettyString(item):pill} {SolutionContainerSystem.ToPrettyString(itemSolution.Comp.Solution)}"); + $"Unknown printed {ToPrettyString(item):pill} {SolutionContainerSystem.ToPrettyString(itemSolution)}"); } } @@ -241,7 +242,8 @@ namespace Content.Server.Chemistry.EntitySystems var user = message.Session.AttachedEntity; var maybeContainer = _itemSlotsSystem.GetItemOrNull(chemMaster, SharedChemMaster.OutputSlotName); if (maybeContainer is not { Valid: true } container - || !_solutionContainerSystem.TryGetSolution(container, SharedChemMaster.BottleSolutionName, out var soln, out var solution)) + || !_solutionContainerSystem.TryGetSolution( + container, SharedChemMaster.BottleSolutionName, out var solution)) { return; // output can't fit reagents } @@ -258,7 +260,8 @@ namespace Content.Server.Chemistry.EntitySystems return; _labelSystem.Label(container, message.Label); - _solutionContainerSystem.TryAddSolution(soln.Value, withdrawal); + _solutionContainerSystem.TryAddSolution( + container, solution, withdrawal); if (user.HasValue) { @@ -284,7 +287,8 @@ namespace Content.Server.Chemistry.EntitySystems { outputSolution = null; - if (!_solutionContainerSystem.TryGetSolution(chemMaster.Owner, SharedChemMaster.BufferSolutionName, out _, out var solution)) + if (!_solutionContainerSystem.TryGetSolution( + chemMaster, SharedChemMaster.BufferSolutionName, out var solution)) { return false; } @@ -319,7 +323,7 @@ namespace Content.Server.Chemistry.EntitySystems return null; if (!TryComp(container, out FitsInDispenserComponent? fits) - || !_solutionContainerSystem.TryGetSolution(container.Value, fits.Solution, out _, out var solution)) + || !_solutionContainerSystem.TryGetSolution(container.Value, fits.Solution, out var solution)) { return null; } @@ -335,7 +339,7 @@ namespace Content.Server.Chemistry.EntitySystems var name = Name(container.Value); { if (_solutionContainerSystem.TryGetSolution( - container.Value, SharedChemMaster.BottleSolutionName, out _, out var solution)) + container.Value, SharedChemMaster.BottleSolutionName, out var solution)) { return BuildContainerInfo(name, solution); } @@ -346,7 +350,7 @@ namespace Content.Server.Chemistry.EntitySystems var pills = storage.Container.ContainedEntities.Select((Func) (pill => { - _solutionContainerSystem.TryGetSolution(pill, SharedChemMaster.PillSolutionName, out _, out var solution); + _solutionContainerSystem.TryGetSolution(pill, SharedChemMaster.PillSolutionName, out var solution); var quantity = solution?.Volume ?? FixedPoint2.Zero; return (Name(pill), quantity); })).ToList(); diff --git a/Content.Server/Chemistry/EntitySystems/ChemistrySystem.Injector.cs b/Content.Server/Chemistry/EntitySystems/ChemistrySystem.Injector.cs index 5f7427eacc..c618094d1b 100644 --- a/Content.Server/Chemistry/EntitySystems/ChemistrySystem.Injector.cs +++ b/Content.Server/Chemistry/EntitySystems/ChemistrySystem.Injector.cs @@ -1,22 +1,21 @@ using Content.Server.Body.Components; using Content.Server.Chemistry.Components; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Components.SolutionManager; using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Chemistry.Reagent; using Content.Shared.Database; -using Content.Shared.DoAfter; using Content.Shared.FixedPoint; -using Content.Shared.Forensics; using Content.Shared.IdentityManagement; using Content.Shared.Interaction; using Content.Shared.Interaction.Events; -using Content.Shared.Mobs.Components; -using Content.Shared.Stacks; -using Content.Shared.Verbs; using Robust.Shared.GameStates; +using Content.Shared.DoAfter; +using Content.Shared.Mobs.Components; +using Content.Shared.Verbs; +using Content.Shared.Stacks; using Robust.Shared.Player; +using Content.Shared.Forensics; namespace Content.Server.Chemistry.EntitySystems; @@ -26,11 +25,11 @@ public sealed partial class ChemistrySystem /// /// Default transfer amounts for the set-transfer verb. /// - public static readonly List TransferAmounts = new() { 1, 5, 10, 15 }; + public static readonly List TransferAmounts = new() {1, 5, 10, 15}; private void InitializeInjector() { SubscribeLocalEvent>(AddSetTransferVerbs); - SubscribeLocalEvent(OnSolutionChange); + SubscribeLocalEvent(OnSolutionChange); SubscribeLocalEvent(OnInjectDoAfter); SubscribeLocalEvent(OnInjectorStartup); SubscribeLocalEvent(OnInjectorUse); @@ -38,7 +37,7 @@ public sealed partial class ChemistrySystem SubscribeLocalEvent(OnInjectorGetState); } - private void AddSetTransferVerbs(Entity entity, ref GetVerbsEvent args) + private void AddSetTransferVerbs(EntityUid uid, InjectorComponent component, GetVerbsEvent args) { if (!args.CanAccess || !args.CanInteract || args.Hands == null) return; @@ -46,14 +45,11 @@ public sealed partial class ChemistrySystem if (!EntityManager.TryGetComponent(args.User, out ActorComponent? actor)) return; - var (uid, component) = entity; - // Add specific transfer verbs according to the container's size var priority = 0; - var user = args.User; foreach (var amount in TransferAmounts) { - if (amount < component.MinimumTransferAmount.Int() || amount > component.MaximumTransferAmount.Int()) + if ( amount < component.MinimumTransferAmount.Int() || amount > component.MaximumTransferAmount.Int()) continue; AlternativeVerb verb = new(); @@ -62,7 +58,7 @@ public sealed partial class ChemistrySystem verb.Act = () => { component.TransferAmount = FixedPoint2.New(amount); - _popup.PopupEntity(Loc.GetString("comp-solution-transfer-set-amount", ("amount", amount)), user, user); + _popup.PopupEntity(Loc.GetString("comp-solution-transfer-set-amount", ("amount", amount)), args.User, args.User); }; // we want to sort by size, not alphabetically by the verb text. @@ -73,22 +69,22 @@ public sealed partial class ChemistrySystem } } - private void UseInjector(Entity injector, EntityUid target, EntityUid user) + private void UseInjector(EntityUid target, EntityUid user, EntityUid injector, InjectorComponent component) { // Handle injecting/drawing for solutions - if (injector.Comp.ToggleState == SharedInjectorComponent.InjectorToggleMode.Inject) + if (component.ToggleState == SharedInjectorComponent.InjectorToggleMode.Inject) { - if (_solutionContainers.TryGetInjectableSolution(target, out var injectableSolution, out _)) + if (_solutions.TryGetInjectableSolution(target, out var injectableSolution)) { - TryInject(injector, target, injectableSolution.Value, user, false); + TryInject(component, injector, target, injectableSolution, user, false); } - else if (_solutionContainers.TryGetRefillableSolution(target, out var refillableSolution, out _)) + else if (_solutions.TryGetRefillableSolution(target, out var refillableSolution)) { - TryInject(injector, target, refillableSolution.Value, user, true); + TryInject(component, injector, target, refillableSolution, user, true); } else if (TryComp(target, out var bloodstream)) { - TryInjectIntoBloodstream(injector, (target, bloodstream), user); + TryInjectIntoBloodstream(component, injector, target, bloodstream, user); } else { @@ -96,112 +92,111 @@ public sealed partial class ChemistrySystem ("target", Identity.Entity(target, EntityManager))), injector, user); } } - else if (injector.Comp.ToggleState == SharedInjectorComponent.InjectorToggleMode.Draw) + else if (component.ToggleState == SharedInjectorComponent.InjectorToggleMode.Draw) { // Draw from a bloodstream, if the target has that - if (TryComp(target, out var stream) && - _solutionContainers.ResolveSolution(target, stream.BloodSolutionName, ref stream.BloodSolution)) + if (TryComp(target, out var stream)) { - TryDraw(injector, (target, stream), stream.BloodSolution.Value, user); + TryDraw(component, injector, target, stream.BloodSolution, user, stream); return; } // Draw from an object (food, beaker, etc) - if (_solutionContainers.TryGetDrawableSolution(target, out var drawableSolution, out _)) + if (_solutions.TryGetDrawableSolution(target, out var drawableSolution)) { - TryDraw(injector, target, drawableSolution.Value, user); + TryDraw(component, injector, target, drawableSolution, user); } else { _popup.PopupEntity(Loc.GetString("injector-component-cannot-draw-message", - ("target", Identity.Entity(target, EntityManager))), injector.Owner, user); + ("target", Identity.Entity(target, EntityManager))), injector, user); } } } - private void OnSolutionChange(Entity entity, ref SolutionContainerChangedEvent args) + private void OnSolutionChange(EntityUid uid, InjectorComponent component, SolutionChangedEvent args) { - Dirty(entity); + Dirty(component); } - private void OnInjectorGetState(Entity entity, ref ComponentGetState args) + private void OnInjectorGetState(EntityUid uid, InjectorComponent component, ref ComponentGetState args) { - _solutionContainers.TryGetSolution(entity.Owner, InjectorComponent.SolutionName, out _, out var solution); + _solutions.TryGetSolution(uid, InjectorComponent.SolutionName, out var solution); var currentVolume = solution?.Volume ?? FixedPoint2.Zero; var maxVolume = solution?.MaxVolume ?? FixedPoint2.Zero; - args.State = new SharedInjectorComponent.InjectorComponentState(currentVolume, maxVolume, entity.Comp.ToggleState); + args.State = new SharedInjectorComponent.InjectorComponentState(currentVolume, maxVolume, component.ToggleState); } - private void OnInjectDoAfter(Entity entity, ref InjectorDoAfterEvent args) + private void OnInjectDoAfter(EntityUid uid, InjectorComponent component, DoAfterEvent args) { if (args.Cancelled || args.Handled || args.Args.Target == null) return; - UseInjector(entity, args.Args.Target.Value, args.Args.User); + UseInjector(args.Args.Target.Value, args.Args.User, uid, component); args.Handled = true; } - private void OnInjectorAfterInteract(Entity entity, ref AfterInteractEvent args) + private void OnInjectorAfterInteract(EntityUid uid, InjectorComponent component, AfterInteractEvent args) { if (args.Handled || !args.CanReach) return; //Make sure we have the attacking entity - if (args.Target is not { Valid: true } target || !HasComp(entity)) + if (args.Target is not { Valid: true } target || !HasComp(uid)) return; // Is the target a mob? If yes, use a do-after to give them time to respond. if (HasComp(target) || HasComp(target)) { // Are use using an injector capible of targeting a mob? - if (entity.Comp.IgnoreMobs) + if (component.IgnoreMobs) return; - InjectDoAfter(entity, target, args.User); + InjectDoAfter(component, args.User, target, uid); args.Handled = true; return; } - UseInjector(entity, target, args.User); + UseInjector(target, args.User, uid, component); args.Handled = true; } - private void OnInjectorStartup(Entity entity, ref ComponentStartup args) + private void OnInjectorStartup(EntityUid uid, InjectorComponent component, ComponentStartup args) { // ???? why ????? - Dirty(entity); + Dirty(component); } - private void OnInjectorUse(Entity entity, ref UseInHandEvent args) + private void OnInjectorUse(EntityUid uid, InjectorComponent component, UseInHandEvent args) { if (args.Handled) return; - Toggle(entity, args.User); + Toggle(component, args.User, uid); args.Handled = true; } /// /// Toggle between draw/inject state if applicable /// - private void Toggle(Entity injector, EntityUid user) + private void Toggle(InjectorComponent component, EntityUid user, EntityUid injector) { - if (injector.Comp.InjectOnly) + if (component.InjectOnly) { return; } string msg; - switch (injector.Comp.ToggleState) + switch (component.ToggleState) { case SharedInjectorComponent.InjectorToggleMode.Inject: - injector.Comp.ToggleState = SharedInjectorComponent.InjectorToggleMode.Draw; + component.ToggleState = SharedInjectorComponent.InjectorToggleMode.Draw; msg = "injector-component-drawing-text"; break; case SharedInjectorComponent.InjectorToggleMode.Draw: - injector.Comp.ToggleState = SharedInjectorComponent.InjectorToggleMode.Inject; + component.ToggleState = SharedInjectorComponent.InjectorToggleMode.Inject; msg = "injector-component-injecting-text"; break; default: @@ -214,18 +209,18 @@ public sealed partial class ChemistrySystem /// /// Send informative pop-up messages and wait for a do-after to complete. /// - private void InjectDoAfter(Entity injector, EntityUid target, EntityUid user) + private void InjectDoAfter(InjectorComponent component, EntityUid user, EntityUid target, EntityUid injector) { // Create a pop-up for the user _popup.PopupEntity(Loc.GetString("injector-component-injecting-user"), target, user); - if (!_solutionContainers.TryGetSolution(injector.Owner, InjectorComponent.SolutionName, out _, out var solution)) + if (!_solutions.TryGetSolution(injector, InjectorComponent.SolutionName, out var solution)) return; - var actualDelay = MathF.Max(injector.Comp.Delay, 1f); + var actualDelay = MathF.Max(component.Delay, 1f); // Injections take 0.5 seconds longer per additional 5u - actualDelay += (float) injector.Comp.TransferAmount / injector.Comp.Delay - 0.5f; + actualDelay += (float) component.TransferAmount / component.Delay - 0.5f; var isTarget = user != target; @@ -249,7 +244,7 @@ public sealed partial class ChemistrySystem } // Add an admin log, using the "force feed" log type. It's not quite feeding, but the effect is the same. - if (injector.Comp.ToggleState == SharedInjectorComponent.InjectorToggleMode.Inject) + if (component.ToggleState == SharedInjectorComponent.InjectorToggleMode.Inject) { _adminLogger.Add(LogType.ForceFeed, $"{EntityManager.ToPrettyString(user):user} is attempting to inject {EntityManager.ToPrettyString(target):target} with a solution {SolutionContainerSystem.ToPrettyString(solution):solution}"); @@ -260,11 +255,11 @@ public sealed partial class ChemistrySystem // Self-injections take half as long. actualDelay /= 2; - if (injector.Comp.ToggleState == SharedInjectorComponent.InjectorToggleMode.Inject) + if (component.ToggleState == SharedInjectorComponent.InjectorToggleMode.Inject) _adminLogger.Add(LogType.Ingestion, $"{EntityManager.ToPrettyString(user):user} is attempting to inject themselves with a solution {SolutionContainerSystem.ToPrettyString(solution):solution}."); } - _doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager, user, actualDelay, new InjectorDoAfterEvent(), injector.Owner, target: target, used: injector.Owner) + _doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager, user, actualDelay, new InjectorDoAfterEvent(), injector, target: target, used: injector) { BreakOnUserMove = true, BreakOnDamage = true, @@ -273,80 +268,77 @@ public sealed partial class ChemistrySystem }); } - private void TryInjectIntoBloodstream(Entity injector, Entity target, EntityUid user) + private void TryInjectIntoBloodstream(InjectorComponent component, EntityUid injector, EntityUid target, BloodstreamComponent targetBloodstream, EntityUid user) { // Get transfer amount. May be smaller than _transferAmount if not enough room - if (!_solutionContainers.ResolveSolution(target.Owner, target.Comp.ChemicalSolutionName, ref target.Comp.ChemicalSolution, out var chemSolution)) - { - _popup.PopupEntity(Loc.GetString("injector-component-cannot-inject-message", ("target", Identity.Entity(target, EntityManager))), injector.Owner, user); - return; - } + var realTransferAmount = FixedPoint2.Min(component.TransferAmount, targetBloodstream.ChemicalSolution.AvailableVolume); - var realTransferAmount = FixedPoint2.Min(injector.Comp.TransferAmount, chemSolution.AvailableVolume); if (realTransferAmount <= 0) { - _popup.PopupEntity(Loc.GetString("injector-component-cannot-inject-message", ("target", Identity.Entity(target, EntityManager))), injector.Owner, user); + _popup.PopupEntity(Loc.GetString("injector-component-cannot-inject-message", ("target", Identity.Entity(target, EntityManager))), injector, user); return; } // Move units from attackSolution to targetSolution - var removedSolution = _solutionContainers.SplitSolution(target.Comp.ChemicalSolution.Value, realTransferAmount); + var removedSolution = _solutions.SplitSolution(user, targetBloodstream.ChemicalSolution, realTransferAmount); - _blood.TryAddToChemicals(target, removedSolution, target.Comp); + _blood.TryAddToChemicals(target, removedSolution, targetBloodstream); _reactiveSystem.DoEntityReaction(target, removedSolution, ReactionMethod.Injection); _popup.PopupEntity(Loc.GetString("injector-component-inject-success-message", ("amount", removedSolution.Volume), - ("target", Identity.Entity(target, EntityManager))), injector.Owner, user); + ("target", Identity.Entity(target, EntityManager))), injector, user); - Dirty(injector); - AfterInject(injector, target); + Dirty(component); + AfterInject(component, injector, target); } - private void TryInject(Entity injector, EntityUid targetEntity, Entity targetSolution, EntityUid user, bool asRefill) + private void TryInject(InjectorComponent component, EntityUid injector, EntityUid targetEntity, Solution targetSolution, EntityUid user, bool asRefill) { - if (!_solutionContainers.TryGetSolution(injector.Owner, InjectorComponent.SolutionName, out var soln, out var solution) || solution.Volume == 0) + if (!_solutions.TryGetSolution(injector, InjectorComponent.SolutionName, out var solution) + || solution.Volume == 0) return; // Get transfer amount. May be smaller than _transferAmount if not enough room - var realTransferAmount = FixedPoint2.Min(injector.Comp.TransferAmount, targetSolution.Comp.Solution.AvailableVolume); + var realTransferAmount = FixedPoint2.Min(component.TransferAmount, targetSolution.AvailableVolume); if (realTransferAmount <= 0) { _popup.PopupEntity(Loc.GetString("injector-component-target-already-full-message", ("target", Identity.Entity(targetEntity, EntityManager))), - injector.Owner, user); + injector, user); return; } // Move units from attackSolution to targetSolution Solution removedSolution; if (TryComp(targetEntity, out var stack)) - removedSolution = _solutionContainers.SplitStackSolution(soln.Value, realTransferAmount, stack.Count); + removedSolution = _solutions.SplitStackSolution(injector, solution, realTransferAmount, stack.Count); else - removedSolution = _solutionContainers.SplitSolution(soln.Value, realTransferAmount); + removedSolution = _solutions.SplitSolution(injector, solution, realTransferAmount); _reactiveSystem.DoEntityReaction(targetEntity, removedSolution, ReactionMethod.Injection); if (!asRefill) - _solutionContainers.Inject(targetEntity, targetSolution, removedSolution); + _solutions.Inject(targetEntity, targetSolution, removedSolution); else - _solutionContainers.Refill(targetEntity, targetSolution, removedSolution); + _solutions.Refill(targetEntity, targetSolution, removedSolution); _popup.PopupEntity(Loc.GetString("injector-component-transfer-success-message", ("amount", removedSolution.Volume), - ("target", Identity.Entity(targetEntity, EntityManager))), injector.Owner, user); + ("target", Identity.Entity(targetEntity, EntityManager))), injector, user); - Dirty(injector); - AfterInject(injector, targetEntity); + Dirty(component); + AfterInject(component, injector, targetEntity); } - private void AfterInject(Entity injector, EntityUid target) + private void AfterInject(InjectorComponent component, EntityUid injector, EntityUid target) { // Automatically set syringe to draw after completely draining it. - if (_solutionContainers.TryGetSolution(injector.Owner, InjectorComponent.SolutionName, out _, out var solution) && solution.Volume == 0) + if (_solutions.TryGetSolution(injector, InjectorComponent.SolutionName, out var solution) + && solution.Volume == 0) { - injector.Comp.ToggleState = SharedInjectorComponent.InjectorToggleMode.Draw; + component.ToggleState = SharedInjectorComponent.InjectorToggleMode.Draw; } // Leave some DNA from the injectee on it @@ -354,12 +346,13 @@ public sealed partial class ChemistrySystem RaiseLocalEvent(target, ref ev); } - private void AfterDraw(Entity injector, EntityUid target) + private void AfterDraw(InjectorComponent component, EntityUid injector, EntityUid target) { // Automatically set syringe to inject after completely filling it. - if (_solutionContainers.TryGetSolution(injector.Owner, InjectorComponent.SolutionName, out _, out var solution) && solution.AvailableVolume == 0) + if (_solutions.TryGetSolution(injector, InjectorComponent.SolutionName, out var solution) + && solution.AvailableVolume == 0) { - injector.Comp.ToggleState = SharedInjectorComponent.InjectorToggleMode.Inject; + component.ToggleState = SharedInjectorComponent.InjectorToggleMode.Inject; } // Leave some DNA from the drawee on it @@ -367,68 +360,70 @@ public sealed partial class ChemistrySystem RaiseLocalEvent(target, ref ev); } - private void TryDraw(Entity injector, Entity target, Entity targetSolution, EntityUid user) + private void TryDraw(InjectorComponent component, EntityUid injector, EntityUid targetEntity, Solution targetSolution, EntityUid user, BloodstreamComponent? stream = null) { - if (!_solutionContainers.TryGetSolution(injector.Owner, InjectorComponent.SolutionName, out var soln, out var solution) || solution.AvailableVolume == 0) + if (!_solutions.TryGetSolution(injector, InjectorComponent.SolutionName, out var solution) + || solution.AvailableVolume == 0) { return; } // Get transfer amount. May be smaller than _transferAmount if not enough room, also make sure there's room in the injector - var realTransferAmount = FixedPoint2.Min(injector.Comp.TransferAmount, targetSolution.Comp.Solution.Volume, solution.AvailableVolume); + var realTransferAmount = FixedPoint2.Min(component.TransferAmount, targetSolution.Volume, solution.AvailableVolume); if (realTransferAmount <= 0) { - _popup.PopupEntity(Loc.GetString("injector-component-target-is-empty-message", ("target", Identity.Entity(target, EntityManager))), - injector.Owner, user); + _popup.PopupEntity(Loc.GetString("injector-component-target-is-empty-message", ("target", Identity.Entity(targetEntity, EntityManager))), + injector, user); return; } // We have some snowflaked behavior for streams. - if (target.Comp != null) + if (stream != null) { - DrawFromBlood(injector, (target.Owner, target.Comp), soln.Value, realTransferAmount, user); + DrawFromBlood(user, injector, targetEntity, component, solution, stream, realTransferAmount); return; } // Move units from attackSolution to targetSolution - var removedSolution = _solutionContainers.Draw(target.Owner, targetSolution, realTransferAmount); + var removedSolution = _solutions.Draw(targetEntity, targetSolution, realTransferAmount); - if (!_solutionContainers.TryAddSolution(soln.Value, removedSolution)) + if (!_solutions.TryAddSolution(injector, solution, removedSolution)) { return; } _popup.PopupEntity(Loc.GetString("injector-component-draw-success-message", ("amount", removedSolution.Volume), - ("target", Identity.Entity(target, EntityManager))), injector.Owner, user); + ("target", Identity.Entity(targetEntity, EntityManager))), injector, user); - Dirty(injector); - AfterDraw(injector, target); + Dirty(component); + AfterDraw(component, injector, targetEntity); } - private void DrawFromBlood(Entity injector, Entity target, Entity injectorSolution, FixedPoint2 transferAmount, EntityUid user) + private void DrawFromBlood(EntityUid user, EntityUid injector, EntityUid target, InjectorComponent component, Solution injectorSolution, BloodstreamComponent stream, FixedPoint2 transferAmount) { var drawAmount = (float) transferAmount; - - if (_solutionContainers.ResolveSolution(target.Owner, target.Comp.ChemicalSolutionName, ref target.Comp.ChemicalSolution)) + var bloodAmount = drawAmount; + var chemAmount = 0f; + if (stream.ChemicalSolution.Volume > 0f) // If they have stuff in their chem stream, we'll draw some of that { - var chemTemp = _solutionContainers.SplitSolution(target.Comp.ChemicalSolution.Value, drawAmount * 0.15f); - _solutionContainers.TryAddSolution(injectorSolution, chemTemp); - drawAmount -= (float) chemTemp.Volume; + bloodAmount = drawAmount * 0.85f; + chemAmount = drawAmount * 0.15f; } - if (_solutionContainers.ResolveSolution(target.Owner, target.Comp.BloodSolutionName, ref target.Comp.BloodSolution)) - { - var bloodTemp = _solutionContainers.SplitSolution(target.Comp.BloodSolution.Value, drawAmount); - _solutionContainers.TryAddSolution(injectorSolution, bloodTemp); - } + var bloodTemp = stream.BloodSolution.SplitSolution(bloodAmount); + var chemTemp = stream.ChemicalSolution.SplitSolution(chemAmount); + + _solutions.TryAddSolution(injector, injectorSolution, bloodTemp); + _solutions.TryAddSolution(injector, injectorSolution, chemTemp); _popup.PopupEntity(Loc.GetString("injector-component-draw-success-message", ("amount", transferAmount), - ("target", Identity.Entity(target, EntityManager))), injector.Owner, user); + ("target", Identity.Entity(target, EntityManager))), injector, user); - Dirty(injector); - AfterDraw(injector, target); + Dirty(component); + AfterDraw(component, injector, target); } + } diff --git a/Content.Server/Chemistry/EntitySystems/ChemistrySystem.cs b/Content.Server/Chemistry/EntitySystems/ChemistrySystem.cs index a2b4f399e2..759d403ace 100644 --- a/Content.Server/Chemistry/EntitySystems/ChemistrySystem.cs +++ b/Content.Server/Chemistry/EntitySystems/ChemistrySystem.cs @@ -1,12 +1,13 @@ using Content.Server.Administration.Logs; using Content.Server.Body.Systems; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Interaction; using Content.Server.Popups; -using Content.Shared.Chemistry; using Content.Shared.CombatMode; +using Content.Shared.Chemistry; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.DoAfter; using Content.Shared.Mobs.Systems; +using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; namespace Content.Server.Chemistry.EntitySystems; @@ -23,7 +24,7 @@ public sealed partial class ChemistrySystem : EntitySystem [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly MobStateSystem _mobState = default!; [Dependency] private readonly SharedCombatModeSystem _combat = default!; - [Dependency] private readonly SolutionContainerSystem _solutionContainers = default!; + [Dependency] private readonly SolutionContainerSystem _solutions = default!; public override void Initialize() { diff --git a/Content.Server/Chemistry/EntitySystems/ChemistrySystemHypospray.cs b/Content.Server/Chemistry/EntitySystems/ChemistrySystemHypospray.cs index 9c1b5130a2..cb4feb8064 100644 --- a/Content.Server/Chemistry/EntitySystems/ChemistrySystemHypospray.cs +++ b/Content.Server/Chemistry/EntitySystems/ChemistrySystemHypospray.cs @@ -1,21 +1,20 @@ +using System.Linq; +using System.Diagnostics.CodeAnalysis; using Content.Server.Chemistry.Components; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Components.SolutionManager; using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Chemistry.Reagent; using Content.Shared.Database; using Content.Shared.FixedPoint; -using Content.Shared.Forensics; using Content.Shared.IdentityManagement; using Content.Shared.Interaction; using Content.Shared.Interaction.Events; using Content.Shared.Mobs.Components; -using Content.Shared.Timing; using Content.Shared.Weapons.Melee.Events; +using Content.Shared.Timing; using Robust.Shared.GameStates; -using System.Diagnostics.CodeAnalysis; -using System.Linq; +using Content.Shared.Forensics; namespace Content.Server.Chemistry.EntitySystems { @@ -27,33 +26,33 @@ namespace Content.Server.Chemistry.EntitySystems { SubscribeLocalEvent(OnAfterInteract); SubscribeLocalEvent(OnAttack); - SubscribeLocalEvent(OnSolutionChange); + SubscribeLocalEvent(OnSolutionChange); SubscribeLocalEvent(OnUseInHand); SubscribeLocalEvent(OnHypoGetState); } - private void OnHypoGetState(Entity entity, ref ComponentGetState args) + private void OnHypoGetState(EntityUid uid, HyposprayComponent component, ref ComponentGetState args) { - args.State = _solutionContainers.TryGetSolution(entity.Owner, entity.Comp.SolutionName, out _, out var solution) + args.State = _solutions.TryGetSolution(uid, component.SolutionName, out var solution) ? new HyposprayComponentState(solution.Volume, solution.MaxVolume) : new HyposprayComponentState(FixedPoint2.Zero, FixedPoint2.Zero); } - private void OnUseInHand(Entity entity, ref UseInHandEvent args) + private void OnUseInHand(EntityUid uid, HyposprayComponent component, UseInHandEvent args) { if (args.Handled) return; - TryDoInject(entity, args.User, args.User); + TryDoInject(uid, args.User, args.User); args.Handled = true; } - private void OnSolutionChange(Entity entity, ref SolutionContainerChangedEvent args) + private void OnSolutionChange(EntityUid uid, HyposprayComponent component, SolutionChangedEvent args) { - Dirty(entity); + Dirty(component); } - public void OnAfterInteract(Entity entity, ref AfterInteractEvent args) + public void OnAfterInteract(EntityUid uid, HyposprayComponent component, AfterInteractEvent args) { if (!args.CanReach) return; @@ -61,20 +60,21 @@ namespace Content.Server.Chemistry.EntitySystems var target = args.Target; var user = args.User; - TryDoInject(entity, target, user); + TryDoInject(uid, target, user); } - public void OnAttack(Entity entity, ref MeleeHitEvent args) + public void OnAttack(EntityUid uid, HyposprayComponent component, MeleeHitEvent args) { if (!args.HitEntities.Any()) return; - TryDoInject(entity, args.HitEntities.First(), args.User); + TryDoInject(uid, args.HitEntities.First(), args.User); } - public bool TryDoInject(Entity hypo, EntityUid? target, EntityUid user) + public bool TryDoInject(EntityUid uid, EntityUid? target, EntityUid user, HyposprayComponent? component=null) { - var (uid, component) = hypo; + if (!Resolve(uid, ref component)) + return false; if (!EligibleEntity(target, _entMan, component)) return false; @@ -92,13 +92,15 @@ namespace Content.Server.Chemistry.EntitySystems target = user; } - if (!_solutionContainers.TryGetSolution(uid, component.SolutionName, out var hypoSpraySoln, out var hypoSpraySolution) || hypoSpraySolution.Volume == 0) + _solutions.TryGetSolution(uid, component.SolutionName, out var hypoSpraySolution); + + if (hypoSpraySolution == null || hypoSpraySolution.Volume == 0) { _popup.PopupCursor(Loc.GetString("hypospray-component-empty-message"), user); return true; } - if (!_solutionContainers.TryGetInjectableSolution(target.Value, out var targetSoln, out var targetSolution)) + if (!_solutions.TryGetInjectableSolution(target.Value, out var targetSolution)) { _popup.PopupCursor(Loc.GetString("hypospray-cant-inject", ("target", Identity.Entity(target.Value, _entMan))), user); return false; @@ -125,17 +127,17 @@ namespace Content.Server.Chemistry.EntitySystems if (realTransferAmount <= 0) { - _popup.PopupCursor(Loc.GetString("hypospray-component-transfer-already-full-message", ("owner", target)), user); + _popup.PopupCursor(Loc.GetString("hypospray-component-transfer-already-full-message",("owner", target)), user); return true; } // Move units from attackSolution to targetSolution - var removedSolution = _solutionContainers.SplitSolution(hypoSpraySoln.Value, realTransferAmount); + var removedSolution = _solutions.SplitSolution(uid, hypoSpraySolution, realTransferAmount); if (!targetSolution.CanAddSolution(removedSolution)) return true; _reactiveSystem.DoEntityReaction(target.Value, removedSolution, ReactionMethod.Injection); - _solutionContainers.TryAddSolution(targetSoln.Value, removedSolution); + _solutions.TryAddSolution(target.Value, targetSolution, removedSolution); var ev = new TransferDnaEvent { Donor = target.Value, Recipient = uid }; RaiseLocalEvent(target.Value, ref ev); diff --git a/Content.Server/Chemistry/EntitySystems/ChemistrySystemMixer.cs b/Content.Server/Chemistry/EntitySystems/ChemistrySystemMixer.cs index 0230671ec9..207282421d 100644 --- a/Content.Server/Chemistry/EntitySystems/ChemistrySystemMixer.cs +++ b/Content.Server/Chemistry/EntitySystems/ChemistrySystemMixer.cs @@ -1,6 +1,10 @@ +using Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Components; +using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Reaction; using Content.Shared.IdentityManagement; using Content.Shared.Interaction; +using Content.Shared.Interaction.Events; +using Robust.Shared.Player; namespace Content.Server.Chemistry.EntitySystems; @@ -11,26 +15,27 @@ public sealed partial class ChemistrySystem SubscribeLocalEvent(OnAfterInteract); } - private void OnAfterInteract(Entity entity, ref AfterInteractEvent args) + private void OnAfterInteract(EntityUid uid, ReactionMixerComponent component, AfterInteractEvent args) { if (!args.Target.HasValue || !args.CanReach) return; - var mixAttemptEvent = new MixingAttemptEvent(entity); - RaiseLocalEvent(entity, ref mixAttemptEvent); - if (mixAttemptEvent.Cancelled) + var mixAttemptEvent = new MixingAttemptEvent(uid); + RaiseLocalEvent(uid, ref mixAttemptEvent); + if(mixAttemptEvent.Cancelled) { return; } - if (!_solutionContainers.TryGetMixableSolution(args.Target.Value, out var solution)) - return; + Solution? solution = null; + if (!_solutions.TryGetMixableSolution(args.Target.Value, out solution)) + return; - _popup.PopupEntity(Loc.GetString(entity.Comp.MixMessage, ("mixed", Identity.Entity(args.Target.Value, EntityManager)), ("mixer", Identity.Entity(entity.Owner, EntityManager))), args.User, args.User); + _popup.PopupEntity(Loc.GetString(component.MixMessage, ("mixed", Identity.Entity(args.Target.Value, EntityManager)), ("mixer", Identity.Entity(uid, EntityManager))), args.User, args.User); - _solutionContainers.UpdateChemicals(solution.Value, true, entity.Comp); + _solutions.UpdateChemicals(args.Target.Value, solution, true, component); - var afterMixingEvent = new AfterMixingEvent(entity, args.Target.Value); - RaiseLocalEvent(entity, afterMixingEvent); + var afterMixingEvent = new AfterMixingEvent(uid, args.Target.Value); + RaiseLocalEvent(uid, afterMixingEvent); } } diff --git a/Content.Server/Chemistry/EntitySystems/DeleteOnSolutionEmptySystem.cs b/Content.Server/Chemistry/EntitySystems/DeleteOnSolutionEmptySystem.cs index cfc6ba988a..fd7933e66a 100644 --- a/Content.Server/Chemistry/EntitySystems/DeleteOnSolutionEmptySystem.cs +++ b/Content.Server/Chemistry/EntitySystems/DeleteOnSolutionEmptySystem.cs @@ -1,5 +1,4 @@ using Content.Server.Chemistry.Components.DeleteOnSolutionEmptyComponent; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Shared.Chemistry.Components.SolutionManager; using Content.Shared.Chemistry.EntitySystems; @@ -13,27 +12,27 @@ namespace Content.Server.Chemistry.EntitySystems.DeleteOnSolutionEmptySystem { base.Initialize(); SubscribeLocalEvent(OnStartup); - SubscribeLocalEvent(OnSolutionChange); + SubscribeLocalEvent(OnSolutionChange); } - public void OnStartup(Entity entity, ref ComponentStartup args) + public void OnStartup(EntityUid uid, DeleteOnSolutionEmptyComponent component, ComponentStartup args) { - CheckSolutions(entity); + CheckSolutions(uid, component); } - public void OnSolutionChange(Entity entity, ref SolutionContainerChangedEvent args) + public void OnSolutionChange(EntityUid uid, DeleteOnSolutionEmptyComponent component, SolutionChangedEvent args) { - CheckSolutions(entity); + CheckSolutions(uid, component); } - public void CheckSolutions(Entity entity) + public void CheckSolutions(EntityUid uid, DeleteOnSolutionEmptyComponent component) { - if (!TryComp(entity, out SolutionContainerManagerComponent? solutions)) + if (!EntityManager.HasComponent(uid)) return; - if (_solutionContainerSystem.TryGetSolution((entity.Owner, solutions), entity.Comp.Solution, out _, out var solution)) + if (_solutionContainerSystem.TryGetSolution(uid, component.Solution, out var solution)) if (solution.Volume <= 0) - EntityManager.QueueDeleteEntity(entity); + EntityManager.QueueDeleteEntity(uid); } } } diff --git a/Content.Server/Chemistry/EntitySystems/ReagentDispenserSystem.cs b/Content.Server/Chemistry/EntitySystems/ReagentDispenserSystem.cs index aeb141fe35..3768ee1051 100644 --- a/Content.Server/Chemistry/EntitySystems/ReagentDispenserSystem.cs +++ b/Content.Server/Chemistry/EntitySystems/ReagentDispenserSystem.cs @@ -1,6 +1,6 @@ +using System.Linq; using Content.Server.Administration.Logs; using Content.Server.Chemistry.Components; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Shared.Chemistry; using Content.Shared.Chemistry.Dispenser; using Content.Shared.Chemistry.EntitySystems; @@ -15,7 +15,6 @@ using Robust.Server.GameObjects; using Robust.Shared.Audio; using Robust.Shared.Containers; using Robust.Shared.Prototypes; -using System.Linq; namespace Content.Server.Chemistry.EntitySystems { @@ -37,7 +36,7 @@ namespace Content.Server.Chemistry.EntitySystems base.Initialize(); SubscribeLocalEvent(SubscribeUpdateUiState); - SubscribeLocalEvent(SubscribeUpdateUiState); + SubscribeLocalEvent(SubscribeUpdateUiState); SubscribeLocalEvent(SubscribeUpdateUiState); SubscribeLocalEvent(SubscribeUpdateUiState); SubscribeLocalEvent(SubscribeUpdateUiState); @@ -69,7 +68,7 @@ namespace Content.Server.Chemistry.EntitySystems if (container is not { Valid: true }) return null; - if (_solutionContainerSystem.TryGetFitsInDispenser(container.Value, out _, out var solution)) + if (_solutionContainerSystem.TryGetFitsInDispenser(container.Value, out var solution)) { return new ContainerInfo(Name(container.Value), solution.Volume, solution.MaxVolume) { @@ -123,10 +122,10 @@ namespace Content.Server.Chemistry.EntitySystems return; var outputContainer = _itemSlotsSystem.GetItemOrNull(reagentDispenser, SharedReagentDispenser.OutputSlotName); - if (outputContainer is not { Valid: true } || !_solutionContainerSystem.TryGetFitsInDispenser(outputContainer.Value, out var solution, out _)) + if (outputContainer is not {Valid: true} || !_solutionContainerSystem.TryGetFitsInDispenser(outputContainer.Value, out var solution)) return; - if (_solutionContainerSystem.TryAddReagent(solution.Value, message.ReagentId, (int) reagentDispenser.Comp.DispenseAmount, out var dispensedAmount) + if (_solutionContainerSystem.TryAddReagent(outputContainer.Value, solution, message.ReagentId, (int)reagentDispenser.Comp.DispenseAmount, out var dispensedAmount) && message.Session.AttachedEntity is not null) { _adminLogger.Add(LogType.ChemicalReaction, LogImpact.Medium, @@ -140,10 +139,10 @@ namespace Content.Server.Chemistry.EntitySystems private void OnClearContainerSolutionMessage(Entity reagentDispenser, ref ReagentDispenserClearContainerSolutionMessage message) { var outputContainer = _itemSlotsSystem.GetItemOrNull(reagentDispenser, SharedReagentDispenser.OutputSlotName); - if (outputContainer is not { Valid: true } || !_solutionContainerSystem.TryGetFitsInDispenser(outputContainer.Value, out var solution, out _)) + if (outputContainer is not {Valid: true} || !_solutionContainerSystem.TryGetFitsInDispenser(outputContainer.Value, out var solution)) return; - _solutionContainerSystem.RemoveAllSolution(solution.Value); + _solutionContainerSystem.RemoveAllSolution(outputContainer.Value, solution); UpdateUiState(reagentDispenser); ClickSound(reagentDispenser); } diff --git a/Content.Server/Chemistry/EntitySystems/RehydratableSystem.cs b/Content.Server/Chemistry/EntitySystems/RehydratableSystem.cs index e1cdfd2066..b75aa311e3 100644 --- a/Content.Server/Chemistry/EntitySystems/RehydratableSystem.cs +++ b/Content.Server/Chemistry/EntitySystems/RehydratableSystem.cs @@ -1,5 +1,4 @@ using Content.Server.Chemistry.Components; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Shared.Chemistry.EntitySystems; using Content.Shared.FixedPoint; using Content.Shared.Popups; @@ -17,23 +16,21 @@ public sealed class RehydratableSystem : EntitySystem { base.Initialize(); - SubscribeLocalEvent(OnSolutionChange); + SubscribeLocalEvent(OnSolutionChange); } - private void OnSolutionChange(Entity entity, ref SolutionContainerChangedEvent args) + private void OnSolutionChange(EntityUid uid, RehydratableComponent comp, SolutionChangedEvent args) { - var quantity = _solutions.GetTotalPrototypeQuantity(entity, entity.Comp.CatalystPrototype); - if (quantity != FixedPoint2.Zero && quantity >= entity.Comp.CatalystMinimum) + var quantity = _solutions.GetTotalPrototypeQuantity(uid, comp.CatalystPrototype); + if (quantity != FixedPoint2.Zero && quantity >= comp.CatalystMinimum) { - Expand(entity); + Expand(uid, comp); } } // Try not to make this public if you can help it. - private void Expand(Entity entity) + private void Expand(EntityUid uid, RehydratableComponent comp) { - var (uid, comp) = entity; - _popups.PopupEntity(Loc.GetString("rehydratable-component-expands-message", ("owner", uid)), uid); var randomMob = _random.Pick(comp.PossibleSpawns); diff --git a/Content.Server/Chemistry/EntitySystems/SolutionHeaterSystem.cs b/Content.Server/Chemistry/EntitySystems/SolutionHeaterSystem.cs index 1ef589ab5c..3e839bee50 100644 --- a/Content.Server/Chemistry/EntitySystems/SolutionHeaterSystem.cs +++ b/Content.Server/Chemistry/EntitySystems/SolutionHeaterSystem.cs @@ -1,10 +1,10 @@ using Content.Server.Chemistry.Components; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Construction; using Content.Server.Power.Components; using Content.Server.Power.EntitySystems; using Content.Shared.Chemistry; using Content.Shared.Chemistry.Components.SolutionManager; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Placeable; namespace Content.Server.Chemistry.EntitySystems; @@ -13,7 +13,7 @@ public sealed class SolutionHeaterSystem : EntitySystem { [Dependency] private readonly PowerReceiverSystem _powerReceiver = default!; [Dependency] private readonly SharedAppearanceSystem _appearance = default!; - [Dependency] private readonly SolutionContainerSystem _solutionContainer = default!; + [Dependency] private readonly SolutionContainerSystem _solution = default!; /// public override void Initialize() @@ -51,41 +51,41 @@ public sealed class SolutionHeaterSystem : EntitySystem RemComp(uid); } - private void OnPowerChanged(Entity entity, ref PowerChangedEvent args) + private void OnPowerChanged(EntityUid uid, SolutionHeaterComponent component, ref PowerChangedEvent args) { - var placer = Comp(entity); + var placer = Comp(uid); if (args.Powered && placer.PlacedEntities.Count > 0) { - TurnOn(entity); + TurnOn(uid); } else { - TurnOff(entity); + TurnOff(uid); } } - private void OnRefreshParts(Entity entity, ref RefreshPartsEvent args) + private void OnRefreshParts(EntityUid uid, SolutionHeaterComponent component, RefreshPartsEvent args) { - var heatRating = args.PartRatings[entity.Comp.MachinePartHeatMultiplier] - 1; + var heatRating = args.PartRatings[component.MachinePartHeatMultiplier] - 1; - entity.Comp.HeatPerSecond = entity.Comp.BaseHeatPerSecond * MathF.Pow(entity.Comp.PartRatingHeatMultiplier, heatRating); + component.HeatPerSecond = component.BaseHeatPerSecond * MathF.Pow(component.PartRatingHeatMultiplier, heatRating); } - private void OnUpgradeExamine(Entity entity, ref UpgradeExamineEvent args) + private void OnUpgradeExamine(EntityUid uid, SolutionHeaterComponent component, UpgradeExamineEvent args) { - args.AddPercentageUpgrade("solution-heater-upgrade-heat", entity.Comp.HeatPerSecond / entity.Comp.BaseHeatPerSecond); + args.AddPercentageUpgrade("solution-heater-upgrade-heat", component.HeatPerSecond / component.BaseHeatPerSecond); } - private void OnItemPlaced(Entity entity, ref ItemPlacedEvent args) + private void OnItemPlaced(EntityUid uid, SolutionHeaterComponent comp, ref ItemPlacedEvent args) { - TryTurnOn(entity); + TryTurnOn(uid); } - private void OnItemRemoved(Entity entity, ref ItemRemovedEvent args) + private void OnItemRemoved(EntityUid uid, SolutionHeaterComponent component, ref ItemRemovedEvent args) { - var placer = Comp(entity); + var placer = Comp(uid); if (placer.PlacedEntities.Count == 0) // Last entity was removed - TurnOff(entity); + TurnOff(uid); } public override void Update(float frameTime) @@ -97,13 +97,13 @@ public sealed class SolutionHeaterSystem : EntitySystem { foreach (var heatingEntity in placer.PlacedEntities) { - if (!TryComp(heatingEntity, out var container)) + if (!TryComp(heatingEntity, out var solution)) continue; var energy = heater.HeatPerSecond * frameTime; - foreach (var (_, soln) in _solutionContainer.EnumerateSolutions((heatingEntity, container))) + foreach (var s in solution.Solutions.Values) { - _solutionContainer.AddThermalEnergy(soln, energy); + _solution.AddThermalEnergy(heatingEntity, s, energy); } } } diff --git a/Content.Server/Chemistry/EntitySystems/SolutionInjectOnCollideSystem.cs b/Content.Server/Chemistry/EntitySystems/SolutionInjectOnCollideSystem.cs index f881240a09..e053ce9720 100644 --- a/Content.Server/Chemistry/EntitySystems/SolutionInjectOnCollideSystem.cs +++ b/Content.Server/Chemistry/EntitySystems/SolutionInjectOnCollideSystem.cs @@ -1,17 +1,19 @@ using Content.Server.Body.Components; using Content.Server.Body.Systems; using Content.Server.Chemistry.Components; -using Content.Server.Chemistry.Containers.EntitySystems; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Inventory; using JetBrains.Annotations; using Robust.Shared.Physics.Events; +using Robust.Shared.Prototypes; namespace Content.Server.Chemistry.EntitySystems { [UsedImplicitly] internal sealed class SolutionInjectOnCollideSystem : EntitySystem { - [Dependency] private readonly SolutionContainerSystem _solutionContainersSystem = default!; + [Dependency] private readonly IPrototypeManager _protoManager = default!; + [Dependency] private readonly SolutionContainerSystem _solutionsSystem = default!; [Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!; [Dependency] private readonly InventorySystem _inventorySystem = default!; @@ -28,7 +30,7 @@ namespace Content.Server.Chemistry.EntitySystems if (!args.OtherBody.Hard || !EntityManager.TryGetComponent(target, out var bloodstream) || - !_solutionContainersSystem.TryGetInjectableSolution(ent.Owner, out var solution, out _)) + !_solutionsSystem.TryGetInjectableSolution(ent, out var solution)) { return; } @@ -42,7 +44,7 @@ namespace Content.Server.Chemistry.EntitySystems return; } - var solRemoved = _solutionContainersSystem.SplitSolution(solution.Value, component.TransferAmount); + var solRemoved = solution.SplitSolution(component.TransferAmount); var solRemovedVol = solRemoved.Volume; var solToInject = solRemoved.SplitSolution(solRemovedVol * component.TransferEfficiency); diff --git a/Content.Server/Chemistry/EntitySystems/SolutionPurgeSystem.cs b/Content.Server/Chemistry/EntitySystems/SolutionPurgeSystem.cs index e6e003a7f5..c918fa929c 100644 --- a/Content.Server/Chemistry/EntitySystems/SolutionPurgeSystem.cs +++ b/Content.Server/Chemistry/EntitySystems/SolutionPurgeSystem.cs @@ -1,6 +1,7 @@ using Content.Server.Chemistry.Components; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Shared.Chemistry.Components.SolutionManager; +using Content.Shared.Chemistry.EntitySystems; +using Content.Shared.FixedPoint; using Robust.Shared.Timing; namespace Content.Server.Chemistry.EntitySystems; @@ -29,13 +30,13 @@ public sealed class SolutionPurgeSystem : EntitySystem // timer ignores if it's empty, it's just a fixed cycle purge.NextPurgeTime += purge.Duration; - if (_solutionContainer.TryGetSolution((uid, manager), purge.Solution, out var solution)) - _solutionContainer.SplitSolutionWithout(solution.Value, purge.Quantity, purge.Preserve.ToArray()); + if (_solutionContainer.TryGetSolution(uid, purge.Solution, out var solution, manager)) + _solutionContainer.SplitSolutionWithout(uid, solution, purge.Quantity, purge.Preserve.ToArray()); } } - private void OnUnpaused(Entity entity, ref EntityUnpausedEvent args) + private void OnUnpaused(EntityUid uid, SolutionPurgeComponent comp, ref EntityUnpausedEvent args) { - entity.Comp.NextPurgeTime += args.PausedTime; + comp.NextPurgeTime += args.PausedTime; } } diff --git a/Content.Server/Chemistry/EntitySystems/SolutionRandomFillSystem.cs b/Content.Server/Chemistry/EntitySystems/SolutionRandomFillSystem.cs index 6685fb485f..c2b8efac6f 100644 --- a/Content.Server/Chemistry/EntitySystems/SolutionRandomFillSystem.cs +++ b/Content.Server/Chemistry/EntitySystems/SolutionRandomFillSystem.cs @@ -1,5 +1,5 @@ using Content.Server.Chemistry.Components; -using Content.Server.Chemistry.Containers.EntitySystems; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Chemistry.Reagent; using Content.Shared.Random; using Content.Shared.Random.Helpers; @@ -21,12 +21,13 @@ public sealed class SolutionRandomFillSystem : EntitySystem SubscribeLocalEvent(OnRandomSolutionFillMapInit); } - private void OnRandomSolutionFillMapInit(Entity entity, ref MapInitEvent args) + private void OnRandomSolutionFillMapInit(EntityUid uid, RandomFillSolutionComponent component, MapInitEvent args) { - if (entity.Comp.WeightedRandomId == null) + if (component.WeightedRandomId == null) return; - var pick = _proto.Index(entity.Comp.WeightedRandomId).Pick(_random); + var target = _solutionsSystem.EnsureSolution(uid, component.Solution); + var pick = _proto.Index(component.WeightedRandomId).Pick(_random); var reagent = pick.reagent; var quantity = pick.quantity; @@ -37,7 +38,6 @@ public sealed class SolutionRandomFillSystem : EntitySystem return; } - var target = _solutionsSystem.EnsureSolutionEntity(entity.Owner, entity.Comp.Solution, pick.quantity, null, out _); - _solutionsSystem.TryAddReagent(target, reagent, quantity, out _); + target.AddReagent(reagent, quantity); } } diff --git a/Content.Server/Chemistry/EntitySystems/SolutionRegenerationSystem.cs b/Content.Server/Chemistry/EntitySystems/SolutionRegenerationSystem.cs index 37458846e3..95908dd703 100644 --- a/Content.Server/Chemistry/EntitySystems/SolutionRegenerationSystem.cs +++ b/Content.Server/Chemistry/EntitySystems/SolutionRegenerationSystem.cs @@ -1,7 +1,7 @@ using Content.Server.Chemistry.Components; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Components.SolutionManager; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.FixedPoint; using Robust.Shared.Timing; @@ -31,7 +31,7 @@ public sealed class SolutionRegenerationSystem : EntitySystem // timer ignores if its full, it's just a fixed cycle regen.NextRegenTime = _timing.CurTime + regen.Duration; - if (_solutionContainer.ResolveSolution((uid, manager), regen.SolutionName, ref regen.Solution, out var solution)) + if (_solutionContainer.TryGetSolution(uid, regen.Solution, out var solution, manager)) { var amount = FixedPoint2.Min(solution.AvailableVolume, regen.Generated.Volume); if (amount <= FixedPoint2.Zero) @@ -48,13 +48,13 @@ public sealed class SolutionRegenerationSystem : EntitySystem generated = regen.Generated.Clone().SplitSolution(amount); } - _solutionContainer.TryAddSolution(regen.Solution.Value, generated); + _solutionContainer.TryAddSolution(uid, solution, generated); } } } - private void OnUnpaused(Entity entity, ref EntityUnpausedEvent args) + private void OnUnpaused(EntityUid uid, SolutionRegenerationComponent comp, ref EntityUnpausedEvent args) { - entity.Comp.NextRegenTime += args.PausedTime; + comp.NextRegenTime += args.PausedTime; } } diff --git a/Content.Server/Chemistry/EntitySystems/SolutionSpikableSystem.cs b/Content.Server/Chemistry/EntitySystems/SolutionSpikableSystem.cs index 7518b45a8b..04aa6546a9 100644 --- a/Content.Server/Chemistry/EntitySystems/SolutionSpikableSystem.cs +++ b/Content.Server/Chemistry/EntitySystems/SolutionSpikableSystem.cs @@ -1,10 +1,12 @@ using Content.Server.Chemistry.Components; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Explosion.EntitySystems; using Content.Server.Popups; using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Components.SolutionManager; +using Content.Shared.Chemistry.EntitySystems; +using Content.Shared.FixedPoint; using Content.Shared.Interaction; +using Robust.Shared.Player; namespace Content.Server.Chemistry.EntitySystems; @@ -19,7 +21,7 @@ namespace Content.Server.Chemistry.EntitySystems; /// public sealed class SolutionSpikableSystem : EntitySystem { - [Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!; + [Dependency] private readonly SolutionContainerSystem _solutionSystem = default!; [Dependency] private readonly TriggerSystem _triggerSystem = default!; [Dependency] private readonly PopupSystem _popupSystem = default!; @@ -28,9 +30,9 @@ public sealed class SolutionSpikableSystem : EntitySystem SubscribeLocalEvent(OnInteractUsing); } - private void OnInteractUsing(Entity entity, ref InteractUsingEvent args) + private void OnInteractUsing(EntityUid uid, RefillableSolutionComponent target, InteractUsingEvent args) { - TrySpike(args.Used, args.Target, args.User, entity.Comp); + TrySpike(args.Used, args.Target, args.User, target); } /// @@ -47,8 +49,8 @@ public sealed class SolutionSpikableSystem : EntitySystem { if (!Resolve(source, ref spikableSource, ref managerSource, false) || !Resolve(target, ref spikableTarget, ref managerTarget, false) - || !_solutionContainerSystem.TryGetRefillableSolution((target, spikableTarget, managerTarget), out var targetSoln, out var targetSolution) - || !_solutionContainerSystem.TryGetSolution((source, managerSource), spikableSource.SourceSolution, out _, out var sourceSolution)) + || !_solutionSystem.TryGetRefillableSolution(target, out var targetSolution, managerTarget, spikableTarget) + || !managerSource.Solutions.TryGetValue(spikableSource.SourceSolution, out var sourceSolution)) { return; } @@ -59,7 +61,7 @@ public sealed class SolutionSpikableSystem : EntitySystem return; } - if (!_solutionContainerSystem.ForceAddSolution(targetSoln.Value, sourceSolution)) + if (!_solutionSystem.ForceAddSolution(target, targetSolution, sourceSolution)) return; _popupSystem.PopupEntity(Loc.GetString(spikableSource.Popup, ("spiked-entity", target), ("spike-entity", source)), user, user); diff --git a/Content.Server/Chemistry/EntitySystems/SolutionTransferSystem.cs b/Content.Server/Chemistry/EntitySystems/SolutionTransferSystem.cs index 1ed5cec8dd..d2666417cf 100644 --- a/Content.Server/Chemistry/EntitySystems/SolutionTransferSystem.cs +++ b/Content.Server/Chemistry/EntitySystems/SolutionTransferSystem.cs @@ -1,14 +1,14 @@ using Content.Server.Administration.Logs; -using Content.Server.Chemistry.Containers.EntitySystems; +using Content.Shared.Verbs; +using JetBrains.Annotations; +using Robust.Server.GameObjects; using Content.Shared.Chemistry; using Content.Shared.Chemistry.Components; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Database; using Content.Shared.FixedPoint; using Content.Shared.Interaction; using Content.Shared.Popups; -using Content.Shared.Verbs; -using JetBrains.Annotations; -using Robust.Server.GameObjects; using Robust.Shared.Player; namespace Content.Server.Chemistry.EntitySystems @@ -24,7 +24,7 @@ namespace Content.Server.Chemistry.EntitySystems /// /// Default transfer amounts for the set-transfer verb. /// - public static readonly List DefaultTransferAmounts = new() { 1, 5, 10, 25, 50, 100, 250, 500, 1000 }; + public static readonly List DefaultTransferAmounts = new() { 1, 5, 10, 25, 50, 100, 250, 500, 1000}; public override void Initialize() { @@ -35,19 +35,17 @@ namespace Content.Server.Chemistry.EntitySystems SubscribeLocalEvent(OnTransferAmountSetValueMessage); } - private void OnTransferAmountSetValueMessage(Entity entity, ref TransferAmountSetValueMessage message) + private void OnTransferAmountSetValueMessage(EntityUid uid, SolutionTransferComponent solutionTransfer, TransferAmountSetValueMessage message) { - var newTransferAmount = FixedPoint2.Clamp(message.Value, entity.Comp.MinimumTransferAmount, entity.Comp.MaximumTransferAmount); - entity.Comp.TransferAmount = newTransferAmount; + var newTransferAmount = FixedPoint2.Clamp(message.Value, solutionTransfer.MinimumTransferAmount, solutionTransfer.MaximumTransferAmount); + solutionTransfer.TransferAmount = newTransferAmount; - if (message.Session.AttachedEntity is { Valid: true } user) - _popupSystem.PopupEntity(Loc.GetString("comp-solution-transfer-set-amount", ("amount", newTransferAmount)), entity.Owner, user); + if (message.Session.AttachedEntity is {Valid: true} user) + _popupSystem.PopupEntity(Loc.GetString("comp-solution-transfer-set-amount", ("amount", newTransferAmount)), uid, user); } - private void AddSetTransferVerbs(Entity entity, ref GetVerbsEvent args) + private void AddSetTransferVerbs(EntityUid uid, SolutionTransferComponent component, GetVerbsEvent args) { - var (uid, component) = entity; - if (!args.CanAccess || !args.CanInteract || !component.CanChangeTransferAmount || args.Hands == null) return; @@ -58,16 +56,15 @@ namespace Content.Server.Chemistry.EntitySystems AlternativeVerb custom = new(); custom.Text = Loc.GetString("comp-solution-transfer-verb-custom-amount"); custom.Category = VerbCategory.SetTransferAmount; - custom.Act = () => _userInterfaceSystem.TryOpen(uid, TransferAmountUiKey.Key, actor.PlayerSession); + custom.Act = () => _userInterfaceSystem.TryOpen(args.Target, TransferAmountUiKey.Key, actor.PlayerSession); custom.Priority = 1; args.Verbs.Add(custom); // Add specific transfer verbs according to the container's size var priority = 0; - var user = args.User; foreach (var amount in DefaultTransferAmounts) { - if (amount < component.MinimumTransferAmount.Int() || amount > component.MaximumTransferAmount.Int()) + if ( amount < component.MinimumTransferAmount.Int() || amount > component.MaximumTransferAmount.Int()) continue; AlternativeVerb verb = new(); @@ -76,7 +73,7 @@ namespace Content.Server.Chemistry.EntitySystems verb.Act = () => { component.TransferAmount = FixedPoint2.New(amount); - _popupSystem.PopupEntity(Loc.GetString("comp-solution-transfer-set-amount", ("amount", amount)), uid, user); + _popupSystem.PopupEntity(Loc.GetString("comp-solution-transfer-set-amount", ("amount", amount)), uid, args.User); }; // we want to sort by size, not alphabetically by the verb text. @@ -87,19 +84,18 @@ namespace Content.Server.Chemistry.EntitySystems } } - private void OnAfterInteract(Entity entity, ref AfterInteractEvent args) + private void OnAfterInteract(EntityUid uid, SolutionTransferComponent component, AfterInteractEvent args) { if (!args.CanReach || args.Target == null) return; var target = args.Target!.Value; - var (uid, component) = entity; //Special case for reagent tanks, because normally clicking another container will give solution, not take it. - if (component.CanReceive && !EntityManager.HasComponent(target) // target must not be refillable (e.g. Reagent Tanks) - && _solutionContainerSystem.TryGetDrainableSolution(target, out var targetSoln, out _) // target must be drainable - && EntityManager.TryGetComponent(uid, out RefillableSolutionComponent? refillComp) - && _solutionContainerSystem.TryGetRefillableSolution((uid, refillComp, null), out var ownerSoln, out var ownerRefill)) + if (component.CanReceive && !EntityManager.HasComponent(target) // target must not be refillable (e.g. Reagent Tanks) + && _solutionContainerSystem.TryGetDrainableSolution(target, out var targetDrain) // target must be drainable + && EntityManager.TryGetComponent(uid, out RefillableSolutionComponent? refillComp) + && _solutionContainerSystem.TryGetRefillableSolution(uid, out var ownerRefill, refillable: refillComp)) { @@ -110,7 +106,7 @@ namespace Content.Server.Chemistry.EntitySystems transferAmount = FixedPoint2.Min(transferAmount, (FixedPoint2) refill.MaxRefill); // if the receiver has a smaller transfer limit, use that instead } - var transferred = Transfer(args.User, target, targetSoln.Value, uid, ownerSoln.Value, transferAmount); + var transferred = Transfer(args.User, target, targetDrain, uid, ownerRefill, transferAmount); if (transferred > 0) { var toTheBrim = ownerRefill.AvailableVolume == 0; @@ -126,8 +122,8 @@ namespace Content.Server.Chemistry.EntitySystems } // if target is refillable, and owner is drainable - if (component.CanSend && _solutionContainerSystem.TryGetRefillableSolution(target, out targetSoln, out var targetRefill) - && _solutionContainerSystem.TryGetDrainableSolution(uid, out ownerSoln, out var ownerDrain)) + if (component.CanSend && _solutionContainerSystem.TryGetRefillableSolution(target, out var targetRefill) + && _solutionContainerSystem.TryGetDrainableSolution(uid, out var ownerDrain)) { var transferAmount = component.TransferAmount; @@ -136,7 +132,7 @@ namespace Content.Server.Chemistry.EntitySystems transferAmount = FixedPoint2.Min(transferAmount, (FixedPoint2) refill.MaxRefill); } - var transferred = Transfer(args.User, uid, ownerSoln.Value, target, targetSoln.Value, transferAmount); + var transferred = Transfer(args.User, uid, ownerDrain, target, targetRefill, transferAmount); if (transferred > 0) { @@ -154,9 +150,9 @@ namespace Content.Server.Chemistry.EntitySystems /// The actual amount transferred. public FixedPoint2 Transfer(EntityUid user, EntityUid sourceEntity, - Entity source, + Solution source, EntityUid targetEntity, - Entity target, + Solution target, FixedPoint2 amount) { var transferAttempt = new SolutionTransferAttemptEvent(sourceEntity, targetEntity); @@ -169,8 +165,7 @@ namespace Content.Server.Chemistry.EntitySystems return FixedPoint2.Zero; } - var sourceSolution = source.Comp.Solution; - if (sourceSolution.Volume == 0) + if (source.Volume == 0) { _popupSystem.PopupEntity(Loc.GetString("comp-solution-transfer-is-empty", ("target", sourceEntity)), sourceEntity, user); return FixedPoint2.Zero; @@ -184,20 +179,19 @@ namespace Content.Server.Chemistry.EntitySystems return FixedPoint2.Zero; } - var targetSolution = target.Comp.Solution; - if (targetSolution.AvailableVolume == 0) + if (target.AvailableVolume == 0) { _popupSystem.PopupEntity(Loc.GetString("comp-solution-transfer-is-full", ("target", targetEntity)), targetEntity, user); return FixedPoint2.Zero; } - var actualAmount = FixedPoint2.Min(amount, FixedPoint2.Min(sourceSolution.Volume, targetSolution.AvailableVolume)); + var actualAmount = FixedPoint2.Min(amount, FixedPoint2.Min(source.Volume, target.AvailableVolume)); var solution = _solutionContainerSystem.Drain(sourceEntity, source, actualAmount); _solutionContainerSystem.Refill(targetEntity, target, solution); _adminLogger.Add(LogType.Action, LogImpact.Medium, - $"{EntityManager.ToPrettyString(user):player} transferred {string.Join(", ", solution.Contents)} to {EntityManager.ToPrettyString(targetEntity):entity}, which now contains {SolutionContainerSystem.ToPrettyString(targetSolution)}"); + $"{EntityManager.ToPrettyString(user):player} transferred {string.Join(", ", solution.Contents)} to {EntityManager.ToPrettyString(targetEntity):entity}, which now contains {string.Join(", ", target.Contents)}"); return actualAmount; } diff --git a/Content.Server/Chemistry/EntitySystems/TransformableContainerSystem.cs b/Content.Server/Chemistry/EntitySystems/TransformableContainerSystem.cs index 94a3fe2186..ac1cc1edd5 100644 --- a/Content.Server/Chemistry/EntitySystems/TransformableContainerSystem.cs +++ b/Content.Server/Chemistry/EntitySystems/TransformableContainerSystem.cs @@ -1,5 +1,4 @@ using Content.Server.Chemistry.Components; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Chemistry.Reagent; using Robust.Shared.Prototypes; @@ -17,38 +16,38 @@ public sealed class TransformableContainerSystem : EntitySystem base.Initialize(); SubscribeLocalEvent(OnMapInit); - SubscribeLocalEvent(OnSolutionChange); + SubscribeLocalEvent(OnSolutionChange); } - private void OnMapInit(Entity entity, ref MapInitEvent args) + private void OnMapInit(EntityUid uid, TransformableContainerComponent component, MapInitEvent args) { - var meta = MetaData(entity.Owner); - if (string.IsNullOrEmpty(entity.Comp.InitialName)) + var meta = MetaData(uid); + if (string.IsNullOrEmpty(component.InitialName)) { - entity.Comp.InitialName = meta.EntityName; + component.InitialName = meta.EntityName; } - if (string.IsNullOrEmpty(entity.Comp.InitialDescription)) + if (string.IsNullOrEmpty(component.InitialDescription)) { - entity.Comp.InitialDescription = meta.EntityDescription; + component.InitialDescription = meta.EntityDescription; } } - private void OnSolutionChange(Entity entity, ref SolutionContainerChangedEvent args) + private void OnSolutionChange(EntityUid owner, TransformableContainerComponent component, + SolutionChangedEvent args) { - if (!_solutionsSystem.TryGetFitsInDispenser(entity.Owner, out _, out var solution)) + if (!_solutionsSystem.TryGetFitsInDispenser(owner, out var solution)) return; - //Transform container into initial state when emptied - if (entity.Comp.CurrentReagent != null && solution.Contents.Count == 0) + if (component.CurrentReagent != null && solution.Contents.Count == 0) { - CancelTransformation(entity); + CancelTransformation(owner, component); } //the biggest reagent in the solution decides the appearance var reagentId = solution.GetPrimaryReagentId(); //If biggest reagent didn't changed - don't change anything at all - if (entity.Comp.CurrentReagent != null && entity.Comp.CurrentReagent.ID == reagentId?.Prototype) + if (component.CurrentReagent != null && component.CurrentReagent.ID == reagentId?.Prototype) { return; } @@ -57,29 +56,29 @@ public sealed class TransformableContainerSystem : EntitySystem if (!string.IsNullOrWhiteSpace(reagentId?.Prototype) && _prototypeManager.TryIndex(reagentId.Value.Prototype, out ReagentPrototype? proto)) { - var metadata = MetaData(entity.Owner); + var metadata = MetaData(owner); var val = Loc.GetString("transformable-container-component-glass", ("name", proto.LocalizedName)); - _metadataSystem.SetEntityName(entity.Owner, val, metadata); - _metadataSystem.SetEntityDescription(entity.Owner, proto.LocalizedDescription, metadata); - entity.Comp.CurrentReagent = proto; - entity.Comp.Transformed = true; + _metadataSystem.SetEntityName(owner, val, metadata); + _metadataSystem.SetEntityDescription(owner, proto.LocalizedDescription, metadata); + component.CurrentReagent = proto; + component.Transformed = true; } } - private void CancelTransformation(Entity entity) + private void CancelTransformation(EntityUid owner, TransformableContainerComponent component) { - entity.Comp.CurrentReagent = null; - entity.Comp.Transformed = false; + component.CurrentReagent = null; + component.Transformed = false; - var metadata = MetaData(entity); + var metadata = MetaData(owner); - if (!string.IsNullOrEmpty(entity.Comp.InitialName)) + if (!string.IsNullOrEmpty(component.InitialName)) { - _metadataSystem.SetEntityName(entity.Owner, entity.Comp.InitialName, metadata); + _metadataSystem.SetEntityName(owner, component.InitialName, metadata); } - if (!string.IsNullOrEmpty(entity.Comp.InitialDescription)) + if (!string.IsNullOrEmpty(component.InitialDescription)) { - _metadataSystem.SetEntityDescription(entity.Owner, entity.Comp.InitialDescription, metadata); + _metadataSystem.SetEntityDescription(owner, component.InitialDescription, metadata); } } } diff --git a/Content.Server/Chemistry/EntitySystems/VaporSystem.cs b/Content.Server/Chemistry/EntitySystems/VaporSystem.cs index 2c23b8f039..02788d5a47 100644 --- a/Content.Server/Chemistry/EntitySystems/VaporSystem.cs +++ b/Content.Server/Chemistry/EntitySystems/VaporSystem.cs @@ -1,8 +1,9 @@ +using System.Numerics; using Content.Server.Chemistry.Components; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Shared.Chemistry; using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Components.SolutionManager; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Chemistry.Reagent; using Content.Shared.FixedPoint; using Content.Shared.Physics; @@ -15,7 +16,6 @@ using Robust.Shared.Physics.Events; using Robust.Shared.Physics.Systems; using Robust.Shared.Prototypes; using Robust.Shared.Spawners; -using System.Numerics; namespace Content.Server.Chemistry.EntitySystems { @@ -40,20 +40,19 @@ namespace Content.Server.Chemistry.EntitySystems SubscribeLocalEvent(HandleCollide); } - private void HandleCollide(Entity entity, ref StartCollideEvent args) + private void HandleCollide(EntityUid uid, VaporComponent component, ref StartCollideEvent args) { - if (!EntityManager.TryGetComponent(entity.Owner, out SolutionContainerManagerComponent? contents)) return; + if (!EntityManager.TryGetComponent(uid, out SolutionContainerManagerComponent? contents)) return; - foreach (var (_, soln) in _solutionContainerSystem.EnumerateSolutions((entity.Owner, contents))) + foreach (var value in contents.Solutions.Values) { - var solution = soln.Comp.Solution; - _reactive.DoEntityReaction(args.OtherEntity, solution, ReactionMethod.Touch); + _reactive.DoEntityReaction(args.OtherEntity, value, ReactionMethod.Touch); } // Check for collision with a impassable object (e.g. wall) and stop if ((args.OtherFixture.CollisionLayer & (int) CollisionGroup.Impassable) != 0 && args.OtherFixture.Hard) { - EntityManager.QueueDeleteEntity(entity); + EntityManager.QueueDeleteEntity(uid); } } @@ -84,27 +83,28 @@ namespace Content.Server.Chemistry.EntitySystems return false; } - if (!_solutionContainerSystem.TryGetSolution(vapor.Owner, VaporComponent.SolutionName, out var vaporSolution)) + if (!_solutionContainerSystem.TryGetSolution(vapor, VaporComponent.SolutionName, + out var vaporSolution)) { return false; } - return _solutionContainerSystem.TryAddSolution(vaporSolution.Value, solution); + return _solutionContainerSystem.TryAddSolution(vapor, vaporSolution, solution); } public override void Update(float frameTime) { var query = EntityQueryEnumerator(); - while (query.MoveNext(out var uid, out var vaporComp, out var container, out var xform)) + while (query.MoveNext(out var uid, out var vaporComp, out var solution, out var xform)) { - foreach (var (_, soln) in _solutionContainerSystem.EnumerateSolutions((uid, container))) + foreach (var (_, value) in solution.Solutions) { - Update(frameTime, (uid, vaporComp), soln, xform); + Update(frameTime, (uid, vaporComp), value, xform); } } } - private void Update(float frameTime, Entity ent, Entity soln, TransformComponent xform) + private void Update(float frameTime, Entity ent, Solution contents, TransformComponent xform) { var (entity, vapor) = ent; if (!vapor.Active) @@ -112,7 +112,6 @@ namespace Content.Server.Chemistry.EntitySystems vapor.ReactTimer += frameTime; - var contents = soln.Comp.Solution; if (vapor.ReactTimer >= ReactTime && TryComp(xform.GridUid, out MapGridComponent? gridComp)) { vapor.ReactTimer = 0; @@ -132,7 +131,7 @@ namespace Content.Server.Chemistry.EntitySystems reaction = reagentQuantity.Quantity; } - _solutionContainerSystem.RemoveReagent(soln, reagentQuantity.Reagent, reaction); + _solutionContainerSystem.RemoveReagent(entity, contents, reagentQuantity.Reagent, reaction); } } diff --git a/Content.Server/Chemistry/ReactionEffects/AreaReactionEffect.cs b/Content.Server/Chemistry/ReactionEffects/AreaReactionEffect.cs index 024558f8de..fc807069f7 100644 --- a/Content.Server/Chemistry/ReactionEffects/AreaReactionEffect.cs +++ b/Content.Server/Chemistry/ReactionEffects/AreaReactionEffect.cs @@ -1,5 +1,6 @@ using Content.Server.Fluids.EntitySystems; using Content.Shared.Audio; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Chemistry.Reagent; using Content.Shared.Coordinates.Helpers; using Content.Shared.Database; @@ -29,7 +30,7 @@ namespace Content.Server.Chemistry.ReactionEffects /// /// How many units of reaction for 1 smoke entity. /// - [DataField] public FixedPoint2 OverflowThreshold = FixedPoint2.New(2.5); + [DataField("overflowThreshold")] public FixedPoint2 OverflowThreshold = FixedPoint2.New(2.5); /// /// The entity prototype that will be spawned as the effect. @@ -55,7 +56,7 @@ namespace Content.Server.Chemistry.ReactionEffects return; var spreadAmount = (int) Math.Max(0, Math.Ceiling((args.Quantity / OverflowThreshold).Float())); - var splitSolution = args.Source.SplitSolution(args.Source.Volume); + var splitSolution = args.EntityManager.System().SplitSolution(args.SolutionEntity, args.Source, args.Source.Volume); var transform = args.EntityManager.GetComponent(args.SolutionEntity); var mapManager = IoCManager.Resolve(); diff --git a/Content.Server/Chemistry/ReactionEffects/CreateEntityReactionEffect.cs b/Content.Server/Chemistry/ReactionEffects/CreateEntityReactionEffect.cs index f8c0378452..53c4f676a8 100644 --- a/Content.Server/Chemistry/ReactionEffects/CreateEntityReactionEffect.cs +++ b/Content.Server/Chemistry/ReactionEffects/CreateEntityReactionEffect.cs @@ -11,13 +11,13 @@ public sealed partial class CreateEntityReactionEffect : ReagentEffect /// /// What entity to create. /// - [DataField(required: true, customTypeSerializer: typeof(PrototypeIdSerializer))] + [DataField("entity", required: true, customTypeSerializer: typeof(PrototypeIdSerializer))] public string Entity = default!; /// /// How many entities to create per unit reaction. /// - [DataField] + [DataField("number")] public uint Number = 1; protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) diff --git a/Content.Server/Chemistry/ReactionEffects/EmpReactionEffect.cs b/Content.Server/Chemistry/ReactionEffects/EmpReactionEffect.cs index b6714ca28d..2efdff93af 100644 --- a/Content.Server/Chemistry/ReactionEffects/EmpReactionEffect.cs +++ b/Content.Server/Chemistry/ReactionEffects/EmpReactionEffect.cs @@ -23,7 +23,7 @@ public sealed partial class EmpReactionEffect : ReagentEffect /// /// How much energy will be drain from sources /// - [DataField] + [DataField("energyConsumption")] public float EnergyConsumption = 12500; /// diff --git a/Content.Server/Chemistry/ReactionEffects/ExplosionReactionEffect.cs b/Content.Server/Chemistry/ReactionEffects/ExplosionReactionEffect.cs index 8a558a3ffd..41a389ee2f 100644 --- a/Content.Server/Chemistry/ReactionEffects/ExplosionReactionEffect.cs +++ b/Content.Server/Chemistry/ReactionEffects/ExplosionReactionEffect.cs @@ -1,10 +1,10 @@ +using System.Text.Json.Serialization; using Content.Server.Explosion.EntitySystems; using Content.Shared.Chemistry.Reagent; using Content.Shared.Database; using Content.Shared.Explosion; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; -using System.Text.Json.Serialization; namespace Content.Server.Chemistry.ReactionEffects { @@ -14,7 +14,7 @@ namespace Content.Server.Chemistry.ReactionEffects /// /// The type of explosion. Determines damage types and tile break chance scaling. /// - [DataField(required: true, customTypeSerializer: typeof(PrototypeIdSerializer))] + [DataField("explosionType", required: true, customTypeSerializer: typeof(PrototypeIdSerializer))] [JsonIgnore] public string ExplosionType = default!; @@ -22,14 +22,14 @@ namespace Content.Server.Chemistry.ReactionEffects /// The max intensity the explosion can have at a given tile. Places an upper limit of damage and tile break /// chance. /// - [DataField] + [DataField("maxIntensity")] [JsonIgnore] public float MaxIntensity = 5; /// /// How quickly intensity drops off as you move away from the epicenter /// - [DataField] + [DataField("intensitySlope")] [JsonIgnore] public float IntensitySlope = 1; @@ -40,14 +40,14 @@ namespace Content.Server.Chemistry.ReactionEffects /// /// A slope of 1 and MaxTotalIntensity of 100 corresponds to a radius of around 4.5 tiles. /// - [DataField] + [DataField("maxTotalIntensity")] [JsonIgnore] public float MaxTotalIntensity = 100; /// /// The intensity of the explosion per unit reaction. /// - [DataField] + [DataField("intensityPerUnit")] [JsonIgnore] public float IntensityPerUnit = 1; diff --git a/Content.Server/Chemistry/ReactionEffects/SmokeAreaReactionEffect.cs b/Content.Server/Chemistry/ReactionEffects/SmokeAreaReactionEffect.cs new file mode 100644 index 0000000000..5f282702bb --- /dev/null +++ b/Content.Server/Chemistry/ReactionEffects/SmokeAreaReactionEffect.cs @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Content.Server/Chemistry/ReactionEffects/SolutionTemperatureEffects.cs b/Content.Server/Chemistry/ReactionEffects/SolutionTemperatureEffects.cs index ec58754883..6117132831 100644 --- a/Content.Server/Chemistry/ReactionEffects/SolutionTemperatureEffects.cs +++ b/Content.Server/Chemistry/ReactionEffects/SolutionTemperatureEffects.cs @@ -1,5 +1,7 @@ +using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Reagent; using Robust.Shared.Prototypes; +using static Robust.Shared.Physics.DynamicTree; namespace Content.Server.Chemistry.ReactionEffects { @@ -119,3 +121,5 @@ namespace Content.Server.Chemistry.ReactionEffects } } + + diff --git a/Content.Server/Chemistry/ReagentEffectConditions/BodyTemperature.cs b/Content.Server/Chemistry/ReagentEffectConditions/BodyTemperature.cs index 9c47bb58ab..fbb1894813 100644 --- a/Content.Server/Chemistry/ReagentEffectConditions/BodyTemperature.cs +++ b/Content.Server/Chemistry/ReagentEffectConditions/BodyTemperature.cs @@ -10,10 +10,10 @@ namespace Content.Server.Chemistry.ReagentEffectConditions /// public sealed partial class Temperature : ReagentEffectCondition { - [DataField] + [DataField("min")] public float Min = 0; - [DataField] + [DataField("max")] public float Max = float.PositiveInfinity; public override bool Condition(ReagentEffectArgs args) { diff --git a/Content.Server/Chemistry/ReagentEffectConditions/HasTagCondition.cs b/Content.Server/Chemistry/ReagentEffectConditions/HasTagCondition.cs index 52d4d00eb3..e2f4ca0968 100644 --- a/Content.Server/Chemistry/ReagentEffectConditions/HasTagCondition.cs +++ b/Content.Server/Chemistry/ReagentEffectConditions/HasTagCondition.cs @@ -9,10 +9,10 @@ namespace Content.Server.Chemistry.ReagentEffectConditions; [UsedImplicitly] public sealed partial class HasTag : ReagentEffectCondition { - [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] + [DataField("tag", customTypeSerializer: typeof(PrototypeIdSerializer))] public string Tag = default!; - [DataField] + [DataField("invert")] public bool Invert = false; public override bool Condition(ReagentEffectArgs args) diff --git a/Content.Server/Chemistry/ReagentEffectConditions/MobStateCondition.cs b/Content.Server/Chemistry/ReagentEffectConditions/MobStateCondition.cs index 377eb7d906..4585cc6d8a 100644 --- a/Content.Server/Chemistry/ReagentEffectConditions/MobStateCondition.cs +++ b/Content.Server/Chemistry/ReagentEffectConditions/MobStateCondition.cs @@ -7,14 +7,16 @@ namespace Content.Server.Chemistry.ReagentEffectConditions { public sealed partial class MobStateCondition : ReagentEffectCondition { - [DataField] - public MobState Mobstate = MobState.Alive; + + + [DataField("mobstate")] + public MobState mobstate = MobState.Alive; public override bool Condition(ReagentEffectArgs args) { if (args.EntityManager.TryGetComponent(args.SolutionEntity, out MobStateComponent? mobState)) { - if (mobState.CurrentState == Mobstate) + if (mobState.CurrentState == mobstate) return true; } @@ -23,7 +25,7 @@ namespace Content.Server.Chemistry.ReagentEffectConditions public override string GuidebookExplanation(IPrototypeManager prototype) { - return Loc.GetString("reagent-effect-condition-guidebook-mob-state-condition", ("state", Mobstate)); + return Loc.GetString("reagent-effect-condition-guidebook-mob-state-condition", ("state", mobstate)); } } } diff --git a/Content.Server/Chemistry/ReagentEffectConditions/OrganType.cs b/Content.Server/Chemistry/ReagentEffectConditions/OrganType.cs index 3b7bffb9cf..a8e9e3077b 100644 --- a/Content.Server/Chemistry/ReagentEffectConditions/OrganType.cs +++ b/Content.Server/Chemistry/ReagentEffectConditions/OrganType.cs @@ -11,13 +11,13 @@ namespace Content.Server.Chemistry.ReagentEffectConditions /// public sealed partial class OrganType : ReagentEffectCondition { - [DataField(required: true, customTypeSerializer: typeof(PrototypeIdSerializer))] + [DataField("type", required: true, customTypeSerializer: typeof(PrototypeIdSerializer))] public string Type = default!; /// /// Does this condition pass when the organ has the type, or when it doesn't have the type? /// - [DataField] + [DataField("shouldHave")] public bool ShouldHave = true; public override bool Condition(ReagentEffectArgs args) diff --git a/Content.Server/Chemistry/ReagentEffectConditions/ReagentThreshold.cs b/Content.Server/Chemistry/ReagentEffectConditions/ReagentThreshold.cs index 664569d7be..203656be73 100644 --- a/Content.Server/Chemistry/ReagentEffectConditions/ReagentThreshold.cs +++ b/Content.Server/Chemistry/ReagentEffectConditions/ReagentThreshold.cs @@ -13,14 +13,14 @@ namespace Content.Server.Chemistry.ReagentEffectConditions /// public sealed partial class ReagentThreshold : ReagentEffectCondition { - [DataField] + [DataField("min")] public FixedPoint2 Min = FixedPoint2.Zero; - [DataField] + [DataField("max")] public FixedPoint2 Max = FixedPoint2.MaxValue; // TODO use ReagentId - [DataField] + [DataField("reagent")] public string? Reagent; public override bool Condition(ReagentEffectArgs args) diff --git a/Content.Server/Chemistry/ReagentEffectConditions/SolutionTemperature.cs b/Content.Server/Chemistry/ReagentEffectConditions/SolutionTemperature.cs index 4387f2ba93..974f2fb81a 100644 --- a/Content.Server/Chemistry/ReagentEffectConditions/SolutionTemperature.cs +++ b/Content.Server/Chemistry/ReagentEffectConditions/SolutionTemperature.cs @@ -9,10 +9,10 @@ namespace Content.Server.Chemistry.ReagentEffectConditions /// public sealed partial class SolutionTemperature : ReagentEffectCondition { - [DataField] + [DataField("min")] public float Min = 0.0f; - [DataField] + [DataField("max")] public float Max = float.PositiveInfinity; public override bool Condition(ReagentEffectArgs args) { diff --git a/Content.Server/Chemistry/ReagentEffectConditions/TotalDamage.cs b/Content.Server/Chemistry/ReagentEffectConditions/TotalDamage.cs index 49630ef9ab..81f6475449 100644 --- a/Content.Server/Chemistry/ReagentEffectConditions/TotalDamage.cs +++ b/Content.Server/Chemistry/ReagentEffectConditions/TotalDamage.cs @@ -7,10 +7,10 @@ namespace Content.Server.Chemistry.ReagentEffectConditions { public sealed partial class TotalDamage : ReagentEffectCondition { - [DataField] + [DataField("max")] public FixedPoint2 Max = FixedPoint2.MaxValue; - [DataField] + [DataField("min")] public FixedPoint2 Min = FixedPoint2.Zero; public override bool Condition(ReagentEffectArgs args) diff --git a/Content.Server/Chemistry/ReagentEffects/AddToSolutionReaction.cs b/Content.Server/Chemistry/ReagentEffects/AddToSolutionReaction.cs index 6a43739b0e..d150854e1e 100644 --- a/Content.Server/Chemistry/ReagentEffects/AddToSolutionReaction.cs +++ b/Content.Server/Chemistry/ReagentEffects/AddToSolutionReaction.cs @@ -1,4 +1,4 @@ -using Content.Server.Chemistry.Containers.EntitySystems; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Chemistry.Reagent; using JetBrains.Annotations; using Robust.Shared.Prototypes; @@ -17,11 +17,12 @@ namespace Content.Server.Chemistry.ReagentEffects return; // TODO see if this is correct - var solutionContainerSystem = args.EntityManager.System(); - if (!solutionContainerSystem.TryGetSolution(args.SolutionEntity, _solution, out var solutionContainer)) + if (!EntitySystem.Get() + .TryGetSolution(args.SolutionEntity, _solution, out var solutionContainer)) return; - if (solutionContainerSystem.TryAddReagent(solutionContainer.Value, args.Reagent.ID, args.Quantity, out var accepted)) + if (EntitySystem.Get() + .TryAddReagent(args.SolutionEntity, solutionContainer, args.Reagent.ID, args.Quantity, out var accepted)) args.Source?.RemoveReagent(args.Reagent.ID, accepted); } diff --git a/Content.Server/Chemistry/ReagentEffects/AdjustAlert.cs b/Content.Server/Chemistry/ReagentEffects/AdjustAlert.cs index cf3d71405b..ee384a2834 100644 --- a/Content.Server/Chemistry/ReagentEffects/AdjustAlert.cs +++ b/Content.Server/Chemistry/ReagentEffects/AdjustAlert.cs @@ -10,13 +10,13 @@ public sealed partial class AdjustAlert : ReagentEffect [DataField("alertType", required: true)] public AlertType Type; - [DataField] + [DataField("clear")] public bool Clear; - [DataField] + [DataField("cooldown")] public bool Cooldown; - [DataField] + [DataField("time")] public float Time; //JUSTIFICATION: This just changes some visuals, doesn't need to be documented. diff --git a/Content.Server/Chemistry/ReagentEffects/AdjustReagent.cs b/Content.Server/Chemistry/ReagentEffects/AdjustReagent.cs index e70626f1d3..5a216b9753 100644 --- a/Content.Server/Chemistry/ReagentEffects/AdjustReagent.cs +++ b/Content.Server/Chemistry/ReagentEffects/AdjustReagent.cs @@ -1,4 +1,5 @@ using Content.Shared.Body.Prototypes; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Chemistry.Reagent; using Content.Shared.FixedPoint; using JetBrains.Annotations; @@ -13,7 +14,7 @@ namespace Content.Server.Chemistry.ReagentEffects /// /// The reagent ID to remove. Only one of this and should be active. /// - [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] + [DataField("reagent", customTypeSerializer:typeof(PrototypeIdSerializer))] public string? Reagent = null; // TODO use ReagentId @@ -21,39 +22,41 @@ namespace Content.Server.Chemistry.ReagentEffects /// The metabolism group to remove, if the reagent satisfies any. /// Only one of this and should be active. /// - [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] + [DataField("group", customTypeSerializer:typeof(PrototypeIdSerializer))] public string? Group = null; - [DataField(required: true)] + [DataField("amount", required: true)] public FixedPoint2 Amount = default!; public override void Effect(ReagentEffectArgs args) { - if (args.Source == null) - return; - - var amount = Amount; - amount *= args.Scale; - - if (Reagent != null) + if (args.Source != null) { - if (amount < 0 && args.Source.ContainsPrototype(Reagent)) - args.Source.RemoveReagent(Reagent, -amount); - if (amount > 0) - args.Source.AddReagent(Reagent, amount); - } - else if (Group != null) - { - var prototypeMan = IoCManager.Resolve(); - foreach (var quant in args.Source.Contents.ToArray()) + var solutionSys = args.EntityManager.EntitySysManager.GetEntitySystem(); + var amount = Amount; + + amount *= args.Scale; + + if (Reagent != null) { - var proto = prototypeMan.Index(quant.Reagent.Prototype); - if (proto.Metabolisms != null && proto.Metabolisms.ContainsKey(Group)) + if (amount < 0 && args.Source.ContainsPrototype(Reagent)) + solutionSys.RemoveReagent(args.SolutionEntity, args.Source, Reagent, -amount); + if (amount > 0) + solutionSys.TryAddReagent(args.SolutionEntity, args.Source, Reagent, amount, out _); + } + else if (Group != null) + { + var prototypeMan = IoCManager.Resolve(); + foreach (var quant in args.Source.Contents.ToArray()) { - if (amount < 0) - args.Source.RemoveReagent(quant.Reagent, amount); - if (amount > 0) - args.Source.AddReagent(quant.Reagent, amount); + var proto = prototypeMan.Index(quant.Reagent.Prototype); + if (proto.Metabolisms != null && proto.Metabolisms.ContainsKey(Group)) + { + if (amount < 0) + solutionSys.RemoveReagent(args.SolutionEntity, args.Source, quant.Reagent, amount); + if (amount > 0) + solutionSys.TryAddReagent(args.SolutionEntity, args.Source, quant.Reagent, amount, out _); + } } } } diff --git a/Content.Server/Chemistry/ReagentEffects/AdjustTemperature.cs b/Content.Server/Chemistry/ReagentEffects/AdjustTemperature.cs index 9b97572067..66ae5ba1db 100644 --- a/Content.Server/Chemistry/ReagentEffects/AdjustTemperature.cs +++ b/Content.Server/Chemistry/ReagentEffects/AdjustTemperature.cs @@ -7,7 +7,7 @@ namespace Content.Server.Chemistry.ReagentEffects { public sealed partial class AdjustTemperature : ReagentEffect { - [DataField] + [DataField("amount")] public float Amount; protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) diff --git a/Content.Server/Chemistry/ReagentEffects/CauseZombieInfection.cs b/Content.Server/Chemistry/ReagentEffects/CauseZombieInfection.cs index 029b149500..ed3098dbdc 100644 --- a/Content.Server/Chemistry/ReagentEffects/CauseZombieInfection.cs +++ b/Content.Server/Chemistry/ReagentEffects/CauseZombieInfection.cs @@ -1,8 +1,10 @@ -using Content.Server.Zombies; using Content.Shared.Chemistry.Reagent; -using Robust.Shared.Configuration; using Robust.Shared.Prototypes; +using Robust.Shared.Configuration; +using Content.Server.Zombies; + + namespace Content.Server.Chemistry.ReagentEffects; public sealed partial class CauseZombieInfection : ReagentEffect diff --git a/Content.Server/Chemistry/ReagentEffects/ChemCleanBoodstream.cs b/Content.Server/Chemistry/ReagentEffects/ChemCleanBoodstream.cs index 402b30a069..f0deb29f87 100644 --- a/Content.Server/Chemistry/ReagentEffects/ChemCleanBoodstream.cs +++ b/Content.Server/Chemistry/ReagentEffects/ChemCleanBoodstream.cs @@ -1,6 +1,6 @@ -using Content.Server.Body.Systems; using Content.Shared.Chemistry.Reagent; using JetBrains.Annotations; +using Content.Server.Body.Systems; using Robust.Shared.Prototypes; namespace Content.Server.Chemistry.ReactionEffects @@ -11,7 +11,7 @@ namespace Content.Server.Chemistry.ReactionEffects [UsedImplicitly] public sealed partial class ChemCleanBloodstream : ReagentEffect { - [DataField] + [DataField("cleanseRate")] public float CleanseRate = 3.0f; protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) diff --git a/Content.Server/Chemistry/ReagentEffects/ChemHealEyeDamage.cs b/Content.Server/Chemistry/ReagentEffects/ChemHealEyeDamage.cs index 206b8ed04d..9f074bca52 100644 --- a/Content.Server/Chemistry/ReagentEffects/ChemHealEyeDamage.cs +++ b/Content.Server/Chemistry/ReagentEffects/ChemHealEyeDamage.cs @@ -15,7 +15,7 @@ namespace Content.Server.Chemistry.ReagentEffects /// /// How much eye damage to add. /// - [DataField] + [DataField("amount")] public int Amount = -1; protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) diff --git a/Content.Server/Chemistry/ReagentEffects/ChemVomit.cs b/Content.Server/Chemistry/ReagentEffects/ChemVomit.cs index 851c0adf5f..630d00124c 100644 --- a/Content.Server/Chemistry/ReagentEffects/ChemVomit.cs +++ b/Content.Server/Chemistry/ReagentEffects/ChemVomit.cs @@ -1,5 +1,5 @@ -using Content.Server.Medical; using Content.Shared.Chemistry.Reagent; +using Content.Server.Medical; using JetBrains.Annotations; using Robust.Shared.Prototypes; @@ -12,10 +12,10 @@ namespace Content.Server.Chemistry.ReagentEffects public sealed partial class ChemVomit : ReagentEffect { /// How many units of thirst to add each time we vomit - [DataField] + [DataField("thirstAmount")] public float ThirstAmount = -8f; /// How many units of hunger to add each time we vomit - [DataField] + [DataField("hungerAmount")] public float HungerAmount = -8f; protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) diff --git a/Content.Server/Chemistry/ReagentEffects/CreateGas.cs b/Content.Server/Chemistry/ReagentEffects/CreateGas.cs index c1da3c48db..ca9ecd67d1 100644 --- a/Content.Server/Chemistry/ReagentEffects/CreateGas.cs +++ b/Content.Server/Chemistry/ReagentEffects/CreateGas.cs @@ -8,13 +8,13 @@ namespace Content.Server.Chemistry.ReagentEffects; public sealed partial class CreateGas : ReagentEffect { - [DataField(required: true)] + [DataField("gas", required: true)] public Gas Gas = default!; /// /// For each unit consumed, how many moles of gas should be created? /// - [DataField] + [DataField("multiplier")] public float Multiplier = 3f; public override bool ShouldLog => true; diff --git a/Content.Server/Chemistry/ReagentEffects/CureZombieInfection.cs b/Content.Server/Chemistry/ReagentEffects/CureZombieInfection.cs index d56fc11531..4e1733e60a 100644 --- a/Content.Server/Chemistry/ReagentEffects/CureZombieInfection.cs +++ b/Content.Server/Chemistry/ReagentEffects/CureZombieInfection.cs @@ -1,13 +1,14 @@ -using Content.Server.Zombies; using Content.Shared.Chemistry.Reagent; -using Robust.Shared.Configuration; using Robust.Shared.Prototypes; +using Robust.Shared.Configuration; +using Content.Server.Zombies; + namespace Content.Server.Chemistry.ReagentEffects; public sealed partial class CureZombieInfection : ReagentEffect { - [DataField] + [DataField("innoculate")] public bool Innoculate; protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) diff --git a/Content.Server/Chemistry/ReagentEffects/Drunk.cs b/Content.Server/Chemistry/ReagentEffects/Drunk.cs index dbce995ca2..8053c8100f 100644 --- a/Content.Server/Chemistry/ReagentEffects/Drunk.cs +++ b/Content.Server/Chemistry/ReagentEffects/Drunk.cs @@ -9,13 +9,13 @@ public sealed partial class Drunk : ReagentEffect /// /// BoozePower is how long each metabolism cycle will make the drunk effect last for. /// - [DataField] + [DataField("boozePower")] public float BoozePower = 3f; /// /// Whether speech should be slurred. /// - [DataField] + [DataField("slurSpeech")] public bool SlurSpeech = true; protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) diff --git a/Content.Server/Chemistry/ReagentEffects/Electrocute.cs b/Content.Server/Chemistry/ReagentEffects/Electrocute.cs index 272a0fce42..85819d36ea 100644 --- a/Content.Server/Chemistry/ReagentEffects/Electrocute.cs +++ b/Content.Server/Chemistry/ReagentEffects/Electrocute.cs @@ -6,14 +6,14 @@ namespace Content.Server.Chemistry.ReagentEffects; public sealed partial class Electrocute : ReagentEffect { - [DataField] public int ElectrocuteTime = 2; + [DataField("electrocuteTime")] public int ElectrocuteTime = 2; - [DataField] public int ElectrocuteDamageScale = 5; + [DataField("electrocuteDamageScale")] public int ElectrocuteDamageScale = 5; /// /// true - refresh electrocute time, false - accumulate electrocute time /// - [DataField] public bool Refresh = true; + [DataField("refresh")] public bool Refresh = true; protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) => Loc.GetString("reagent-effect-guidebook-electrocute", ("chance", Probability), ("time", ElectrocuteTime)); diff --git a/Content.Server/Chemistry/ReagentEffects/Emote.cs b/Content.Server/Chemistry/ReagentEffects/Emote.cs index a4d49e4ad1..45da55ea1a 100644 --- a/Content.Server/Chemistry/ReagentEffects/Emote.cs +++ b/Content.Server/Chemistry/ReagentEffects/Emote.cs @@ -16,7 +16,7 @@ public sealed partial class Emote : ReagentEffect [DataField("emote", customTypeSerializer: typeof(PrototypeIdSerializer))] public string? EmoteId; - [DataField] + [DataField("showInChat")] public bool ShowInChat; // JUSTIFICATION: Emoting is flavor, so same reason popup messages are not in here. diff --git a/Content.Server/Chemistry/ReagentEffects/FlammableReaction.cs b/Content.Server/Chemistry/ReagentEffects/FlammableReaction.cs index 5b36967f6a..26bd4c8b7e 100644 --- a/Content.Server/Chemistry/ReagentEffects/FlammableReaction.cs +++ b/Content.Server/Chemistry/ReagentEffects/FlammableReaction.cs @@ -10,7 +10,7 @@ namespace Content.Server.Chemistry.ReagentEffects [UsedImplicitly] public sealed partial class FlammableReaction : ReagentEffect { - [DataField] + [DataField("multiplier")] public float Multiplier = 0.05f; public override bool ShouldLog => true; diff --git a/Content.Server/Chemistry/ReagentEffects/HealthChange.cs b/Content.Server/Chemistry/ReagentEffects/HealthChange.cs index a0c976bdc9..6d22db742f 100644 --- a/Content.Server/Chemistry/ReagentEffects/HealthChange.cs +++ b/Content.Server/Chemistry/ReagentEffects/HealthChange.cs @@ -1,3 +1,5 @@ +using System.Linq; +using System.Text.Json.Serialization; using Content.Shared.Chemistry.Reagent; using Content.Shared.Damage; using Content.Shared.Damage.Prototypes; @@ -5,8 +7,6 @@ using Content.Shared.FixedPoint; using Content.Shared.Localizations; using JetBrains.Annotations; using Robust.Shared.Prototypes; -using System.Linq; -using System.Text.Json.Serialization; namespace Content.Server.Chemistry.ReagentEffects { @@ -19,19 +19,19 @@ namespace Content.Server.Chemistry.ReagentEffects /// /// Damage to apply every metabolism cycle. Damage Ignores resistances. /// - [DataField(required: true)] [JsonPropertyName("damage")] + [DataField("damage", required: true)] public DamageSpecifier Damage = default!; /// /// Should this effect scale the damage by the amount of chemical in the solution? /// Useful for touch reactions, like styptic powder or acid. /// - [DataField] [JsonPropertyName("scaleByQuantity")] + [DataField("scaleByQuantity")] public bool ScaleByQuantity; - [DataField] + [DataField("ignoreResistances")] [JsonPropertyName("ignoreResistances")] public bool IgnoreResistances = true; diff --git a/Content.Server/Chemistry/ReagentEffects/ModifyBleedAmount.cs b/Content.Server/Chemistry/ReagentEffects/ModifyBleedAmount.cs index 7b966ea478..bb990214f1 100644 --- a/Content.Server/Chemistry/ReagentEffects/ModifyBleedAmount.cs +++ b/Content.Server/Chemistry/ReagentEffects/ModifyBleedAmount.cs @@ -7,10 +7,10 @@ namespace Content.Server.Chemistry.ReagentEffects; public sealed partial class ModifyBleedAmount : ReagentEffect { - [DataField] + [DataField("scaled")] public bool Scaled = false; - [DataField] + [DataField("amount")] public float Amount = -1.0f; protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) diff --git a/Content.Server/Chemistry/ReagentEffects/ModifyBloodLevel.cs b/Content.Server/Chemistry/ReagentEffects/ModifyBloodLevel.cs index 748aa71083..42fb14809f 100644 --- a/Content.Server/Chemistry/ReagentEffects/ModifyBloodLevel.cs +++ b/Content.Server/Chemistry/ReagentEffects/ModifyBloodLevel.cs @@ -8,10 +8,10 @@ namespace Content.Server.Chemistry.ReagentEffects; public sealed partial class ModifyBloodLevel : ReagentEffect { - [DataField] + [DataField("scaled")] public bool Scaled = false; - [DataField] + [DataField("amount")] public FixedPoint2 Amount = 1.0f; protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) diff --git a/Content.Server/Chemistry/ReagentEffects/MovespeedModifier.cs b/Content.Server/Chemistry/ReagentEffects/MovespeedModifier.cs index 0301742c5a..948726bb06 100644 --- a/Content.Server/Chemistry/ReagentEffects/MovespeedModifier.cs +++ b/Content.Server/Chemistry/ReagentEffects/MovespeedModifier.cs @@ -15,19 +15,19 @@ namespace Content.Server.Chemistry.ReagentEffects /// /// How much the entities' walk speed is multiplied by. /// - [DataField] + [DataField("walkSpeedModifier")] public float WalkSpeedModifier { get; set; } = 1; /// /// How much the entities' run speed is multiplied by. /// - [DataField] + [DataField("sprintSpeedModifier")] public float SprintSpeedModifier { get; set; } = 1; /// /// How long the modifier applies (in seconds) when metabolized. /// - [DataField] + [DataField("statusLifetime")] public float StatusLifetime = 2f; protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) diff --git a/Content.Server/Chemistry/ReagentEffects/Oxygenate.cs b/Content.Server/Chemistry/ReagentEffects/Oxygenate.cs index 34a2454139..28356bbd30 100644 --- a/Content.Server/Chemistry/ReagentEffects/Oxygenate.cs +++ b/Content.Server/Chemistry/ReagentEffects/Oxygenate.cs @@ -7,7 +7,7 @@ namespace Content.Server.Chemistry.ReagentEffects; public sealed partial class Oxygenate : ReagentEffect { - [DataField] + [DataField("factor")] public float Factor = 1f; // JUSTIFICATION: This is internal magic that players never directly interact with. diff --git a/Content.Server/Chemistry/ReagentEffects/Paralyze.cs b/Content.Server/Chemistry/ReagentEffects/Paralyze.cs index 077d1abf2c..262d942fa9 100644 --- a/Content.Server/Chemistry/ReagentEffects/Paralyze.cs +++ b/Content.Server/Chemistry/ReagentEffects/Paralyze.cs @@ -1,17 +1,17 @@ -using Content.Server.Stunnable; using Content.Shared.Chemistry.Reagent; +using Content.Server.Stunnable; using Robust.Shared.Prototypes; namespace Content.Server.Chemistry.ReagentEffects; public sealed partial class Paralyze : ReagentEffect { - [DataField] public double ParalyzeTime = 2; + [DataField("paralyzeTime")] public double ParalyzeTime = 2; /// /// true - refresh paralyze time, false - accumulate paralyze time /// - [DataField] public bool Refresh = true; + [DataField("refresh")] public bool Refresh = true; protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) => Loc.GetString("reagent-effect-guidebook-paralyze", diff --git a/Content.Server/Chemistry/ReagentEffects/PlantMetabolism/PlantAdjustAttribute.cs b/Content.Server/Chemistry/ReagentEffects/PlantMetabolism/PlantAdjustAttribute.cs index f43b4828f9..a2d35c8264 100644 --- a/Content.Server/Chemistry/ReagentEffects/PlantMetabolism/PlantAdjustAttribute.cs +++ b/Content.Server/Chemistry/ReagentEffects/PlantMetabolism/PlantAdjustAttribute.cs @@ -1,19 +1,16 @@ -using Content.Server.Botany.Components; +using System.Diagnostics.CodeAnalysis; +using Content.Server.Botany.Components; using Content.Shared.Chemistry.Reagent; using Robust.Shared.Prototypes; using Robust.Shared.Random; -using System.Diagnostics.CodeAnalysis; namespace Content.Server.Chemistry.ReagentEffects.PlantMetabolism { [ImplicitDataDefinitionForInheritors] public abstract partial class PlantAdjustAttribute : ReagentEffect { - [DataField] - public float Amount { get; protected set; } = 1; - - [DataField] - public float Prob { get; protected set; } = 1; // = (80); + [DataField("amount")] public float Amount { get; protected set; } = 1; + [DataField("prob")] public float Prob { get; protected set; } = 1; // = (80); /// /// Checks if the plant holder can metabolize the reagent or not. Checks if it has an alive plant by default. diff --git a/Content.Server/Chemistry/ReagentEffects/PlantMetabolism/RobustHarvest.cs b/Content.Server/Chemistry/ReagentEffects/PlantMetabolism/RobustHarvest.cs index 990a5a5003..bcd5a01170 100644 --- a/Content.Server/Chemistry/ReagentEffects/PlantMetabolism/RobustHarvest.cs +++ b/Content.Server/Chemistry/ReagentEffects/PlantMetabolism/RobustHarvest.cs @@ -11,13 +11,13 @@ namespace Content.Server.Chemistry.ReagentEffects.PlantMetabolism [DataDefinition] public sealed partial class RobustHarvest : ReagentEffect { - [DataField] + [DataField("potencyLimit")] public int PotencyLimit = 50; - [DataField] + [DataField("potencyIncrease")] public int PotencyIncrease = 3; - [DataField] + [DataField("potencySeedlessThreshold")] public int PotencySeedlessThreshold = 30; public override void Effect(ReagentEffectArgs args) diff --git a/Content.Server/Chemistry/ReagentEffects/PopupMessage.cs b/Content.Server/Chemistry/ReagentEffects/PopupMessage.cs index 8278e95c1d..660a539e8a 100644 --- a/Content.Server/Chemistry/ReagentEffects/PopupMessage.cs +++ b/Content.Server/Chemistry/ReagentEffects/PopupMessage.cs @@ -8,13 +8,13 @@ namespace Content.Server.Chemistry.ReagentEffects { public sealed partial class PopupMessage : ReagentEffect { - [DataField(required: true)] + [DataField("messages", required: true)] public string[] Messages = default!; - [DataField] + [DataField("type")] public PopupRecipients Type = PopupRecipients.Local; - [DataField] + [DataField("visualType")] public PopupType VisualType = PopupType.Small; // JUSTIFICATION: This is purely cosmetic. diff --git a/Content.Server/Chemistry/ReagentEffects/StatusEffects/GenericStatusEffect.cs b/Content.Server/Chemistry/ReagentEffects/StatusEffects/GenericStatusEffect.cs index 66454b25fd..06608df4bb 100644 --- a/Content.Server/Chemistry/ReagentEffects/StatusEffects/GenericStatusEffect.cs +++ b/Content.Server/Chemistry/ReagentEffects/StatusEffects/GenericStatusEffect.cs @@ -17,25 +17,25 @@ namespace Content.Server.Chemistry.ReagentEffects.StatusEffects [UsedImplicitly] public sealed partial class GenericStatusEffect : ReagentEffect { - [DataField(required: true)] + [DataField("key", required: true)] public string Key = default!; - [DataField] + [DataField("component")] public string Component = String.Empty; - [DataField] + [DataField("time")] public float Time = 2.0f; /// /// true - refresh status effect time, false - accumulate status effect time /// - [DataField] + [DataField("refresh")] public bool Refresh = true; /// /// Should this effect add the status effect, remove time from it, or set its cooldown? /// - [DataField] + [DataField("type")] public StatusEffectMetabolismType Type = StatusEffectMetabolismType.Add; public override void Effect(ReagentEffectArgs args) diff --git a/Content.Server/Chemistry/ReagentEffects/StatusEffects/Jitter.cs b/Content.Server/Chemistry/ReagentEffects/StatusEffects/Jitter.cs index 7ee70957b7..7ceb91a0d1 100644 --- a/Content.Server/Chemistry/ReagentEffects/StatusEffects/Jitter.cs +++ b/Content.Server/Chemistry/ReagentEffects/StatusEffects/Jitter.cs @@ -11,19 +11,19 @@ namespace Content.Server.Chemistry.ReagentEffects.StatusEffects /// public sealed partial class Jitter : ReagentEffect { - [DataField] + [DataField("amplitude")] public float Amplitude = 10.0f; - [DataField] + [DataField("frequency")] public float Frequency = 4.0f; - [DataField] + [DataField("time")] public float Time = 2.0f; /// /// true - refresh jitter time, false - accumulate jitter time /// - [DataField] + [DataField("refresh")] public bool Refresh = true; public override void Effect(ReagentEffectArgs args) diff --git a/Content.Server/Chemistry/TileReactions/CleanDecalsReaction.cs b/Content.Server/Chemistry/TileReactions/CleanDecalsReaction.cs index a20f54728e..c23956760a 100644 --- a/Content.Server/Chemistry/TileReactions/CleanDecalsReaction.cs +++ b/Content.Server/Chemistry/TileReactions/CleanDecalsReaction.cs @@ -1,3 +1,4 @@ +using System.Numerics; using Content.Server.Decals; using Content.Shared.Chemistry.Reaction; using Content.Shared.Chemistry.Reagent; @@ -5,7 +6,6 @@ using Content.Shared.Decals; using Content.Shared.FixedPoint; using Robust.Shared.Map; using Robust.Shared.Map.Components; -using System.Numerics; namespace Content.Server.Chemistry.TileReactions; @@ -18,7 +18,7 @@ public sealed partial class CleanDecalsReaction : ITileReaction /// /// For every cleaned decal we lose this much reagent. /// - [DataField] + [DataField("cleanCost")] public FixedPoint2 CleanCost { get; private set; } = FixedPoint2.New(0.25f); public FixedPoint2 TileReact(TileRef tile, ReagentPrototype reagent, FixedPoint2 reactVolume) diff --git a/Content.Server/Chemistry/TileReactions/CleanTileReaction.cs b/Content.Server/Chemistry/TileReactions/CleanTileReaction.cs index 9d358de07e..4e2f52d3bc 100644 --- a/Content.Server/Chemistry/TileReactions/CleanTileReaction.cs +++ b/Content.Server/Chemistry/TileReactions/CleanTileReaction.cs @@ -1,12 +1,12 @@ -using Content.Server.Chemistry.Containers.EntitySystems; +using System.Linq; using Content.Shared.Chemistry.Components; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Chemistry.Reaction; using Content.Shared.Chemistry.Reagent; using Content.Shared.FixedPoint; using Content.Shared.Fluids.Components; using Robust.Shared.Map; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; -using System.Linq; namespace Content.Server.Chemistry.TileReactions; @@ -28,7 +28,7 @@ public sealed partial class CleanTileReaction : ITileReaction /// /// What reagent to replace the tile conents with. /// - [DataField("reagent", customTypeSerializer: typeof(PrototypeIdSerializer))] + [DataField("reagent", customTypeSerializer:typeof(PrototypeIdSerializer))] public string ReplacementReagent = "Water"; FixedPoint2 ITileReaction.TileReact(TileRef tile, ReagentPrototype reagent, FixedPoint2 reactVolume) @@ -43,16 +43,17 @@ public sealed partial class CleanTileReaction : ITileReaction foreach (var entity in entities) { if (!puddleQuery.TryGetComponent(entity, out var puddle) || - !solutionContainerSystem.TryGetSolution(entity, puddle.SolutionName, out var puddleSolution, out _)) + !solutionContainerSystem.TryGetSolution(entity, puddle.SolutionName, out var puddleSolution)) { continue; } - var purgeable = solutionContainerSystem.SplitSolutionWithout(puddleSolution.Value, purgeAmount, ReplacementReagent, reagent.ID); + var purgeable = + solutionContainerSystem.SplitSolutionWithout(entity, puddleSolution, purgeAmount, ReplacementReagent, reagent.ID); purgeAmount -= purgeable.Volume; - solutionContainerSystem.TryAddSolution(puddleSolution.Value, new Solution(ReplacementReagent, purgeable.Volume)); + solutionContainerSystem.TryAddSolution(entity, puddleSolution, new Solution(ReplacementReagent, purgeable.Volume)); if (purgeable.Volume <= FixedPoint2.Zero) break; diff --git a/Content.Server/Chemistry/TileReactions/CreateEntityTileReaction.cs b/Content.Server/Chemistry/TileReactions/CreateEntityTileReaction.cs index 9cb1ba201d..3b1494cc2f 100644 --- a/Content.Server/Chemistry/TileReactions/CreateEntityTileReaction.cs +++ b/Content.Server/Chemistry/TileReactions/CreateEntityTileReaction.cs @@ -1,4 +1,5 @@ -using Content.Shared.Chemistry.Reaction; +using System.Numerics; +using Content.Shared.Chemistry.Reaction; using Content.Shared.Chemistry.Reagent; using Content.Shared.FixedPoint; using Content.Shared.Maps; @@ -7,23 +8,22 @@ using Robust.Shared.Map; using Robust.Shared.Prototypes; using Robust.Shared.Random; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; -using System.Numerics; namespace Content.Server.Chemistry.TileReactions; [DataDefinition] public sealed partial class CreateEntityTileReaction : ITileReaction { - [DataField(required: true, customTypeSerializer: typeof(PrototypeIdSerializer))] + [DataField("entity", required: true, customTypeSerializer:typeof(PrototypeIdSerializer))] public string Entity = default!; - [DataField] + [DataField("usage")] public FixedPoint2 Usage = FixedPoint2.New(1); /// /// How many of the whitelisted entity can fit on one tile? /// - [DataField] + [DataField("maxOnTile")] public int MaxOnTile = 1; /// @@ -32,7 +32,7 @@ public sealed partial class CreateEntityTileReaction : ITileReaction [DataField("maxOnTileWhitelist")] public EntityWhitelist? Whitelist; - [DataField] + [DataField("randomOffsetMax")] public float RandomOffsetMax = 0.0f; public FixedPoint2 TileReact(TileRef tile, ReagentPrototype reagent, FixedPoint2 reactVolume) diff --git a/Content.Server/Cloning/CloningSystem.cs b/Content.Server/Cloning/CloningSystem.cs index 95b0bd7310..6156a88c38 100644 --- a/Content.Server/Cloning/CloningSystem.cs +++ b/Content.Server/Cloning/CloningSystem.cs @@ -29,6 +29,7 @@ using Content.Shared.Roles.Jobs; using Robust.Server.Containers; using Robust.Server.GameObjects; using Robust.Server.Player; +using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; using Robust.Shared.Configuration; using Robust.Shared.Containers; diff --git a/Content.Server/Construction/Conditions/MinSolution.cs b/Content.Server/Construction/Conditions/MinSolution.cs index f98d639b7b..d70e84761d 100644 --- a/Content.Server/Construction/Conditions/MinSolution.cs +++ b/Content.Server/Construction/Conditions/MinSolution.cs @@ -1,4 +1,4 @@ -using Content.Server.Chemistry.Containers.EntitySystems; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Chemistry.Reagent; using Content.Shared.Construction; using Content.Shared.Examine; @@ -34,7 +34,7 @@ public sealed partial class MinSolution : IGraphCondition public bool Condition(EntityUid uid, IEntityManager entMan) { var containerSys = entMan.System(); - if (!containerSys.TryGetSolution(uid, Solution, out _, out var solution)) + if (!containerSys.TryGetSolution(uid, Solution, out var solution)) return false; solution.TryGetReagentQuantity(Reagent, out var quantity); @@ -47,7 +47,7 @@ public sealed partial class MinSolution : IGraphCondition var uid = args.Examined; var containerSys = entMan.System(); - if (!containerSys.TryGetSolution(uid, Solution, out _, out var solution)) + if (!containerSys.TryGetSolution(uid, Solution, out var solution)) return false; solution.TryGetReagentQuantity(Reagent, out var quantity); diff --git a/Content.Server/Construction/Conditions/SolutionEmpty.cs b/Content.Server/Construction/Conditions/SolutionEmpty.cs index 9235a187eb..d3cbd7356e 100644 --- a/Content.Server/Construction/Conditions/SolutionEmpty.cs +++ b/Content.Server/Construction/Conditions/SolutionEmpty.cs @@ -1,4 +1,4 @@ -using Content.Server.Chemistry.Containers.EntitySystems; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Construction; using Content.Shared.Examine; @@ -19,7 +19,7 @@ public sealed partial class SolutionEmpty : IGraphCondition public bool Condition(EntityUid uid, IEntityManager entMan) { var containerSys = entMan.System(); - if (!containerSys.TryGetSolution(uid, Solution, out _, out var solution)) + if (!containerSys.TryGetSolution(uid, Solution, out var solution)) return false; return solution.Volume == 0; @@ -31,7 +31,7 @@ public sealed partial class SolutionEmpty : IGraphCondition var uid = args.Examined; var containerSys = entMan.System(); - if (!containerSys.TryGetSolution(uid, Solution, out _, out var solution)) + if (!containerSys.TryGetSolution(uid, Solution, out var solution)) return false; // already empty so dont show examine diff --git a/Content.Server/Destructible/DestructibleSystem.cs b/Content.Server/Destructible/DestructibleSystem.cs index 16c54fd3b0..7e43e72007 100644 --- a/Content.Server/Destructible/DestructibleSystem.cs +++ b/Content.Server/Destructible/DestructibleSystem.cs @@ -1,7 +1,7 @@ +using System.Linq; using Content.Server.Administration.Logs; using Content.Server.Atmos.EntitySystems; using Content.Server.Body.Systems; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Construction; using Content.Server.Destructible.Thresholds; using Content.Server.Destructible.Thresholds.Behaviors; @@ -9,6 +9,7 @@ using Content.Server.Destructible.Thresholds.Triggers; using Content.Server.Explosion.EntitySystems; using Content.Server.Fluids.EntitySystems; using Content.Server.Stack; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Damage; using Content.Shared.Database; using Content.Shared.Destructible; @@ -19,7 +20,6 @@ using Robust.Server.GameObjects; using Robust.Shared.Containers; using Robust.Shared.Prototypes; using Robust.Shared.Random; -using System.Linq; namespace Content.Server.Destructible { diff --git a/Content.Server/Destructible/Thresholds/Behaviors/SolutionExplosionBehavior.cs b/Content.Server/Destructible/Thresholds/Behaviors/SolutionExplosionBehavior.cs index 5166aaccab..97ea392450 100644 --- a/Content.Server/Destructible/Thresholds/Behaviors/SolutionExplosionBehavior.cs +++ b/Content.Server/Destructible/Thresholds/Behaviors/SolutionExplosionBehavior.cs @@ -10,12 +10,12 @@ namespace Content.Server.Destructible.Thresholds.Behaviors [DataDefinition] public sealed partial class SolutionExplosionBehavior : IThresholdBehavior { - [DataField(required: true)] + [DataField("solution", required: true)] public string Solution = default!; public void Execute(EntityUid owner, DestructibleSystem system, EntityUid? cause = null) { - if (system.SolutionContainerSystem.TryGetSolution(owner, Solution, out _, out var explodingSolution) + if (system.SolutionContainerSystem.TryGetSolution(owner, Solution, out var explodingSolution) && system.EntityManager.TryGetComponent(owner, out ExplosiveComponent? explosiveComponent)) { // Don't explode if there's no solution diff --git a/Content.Server/Destructible/Thresholds/Behaviors/SpillBehavior.cs b/Content.Server/Destructible/Thresholds/Behaviors/SpillBehavior.cs index 9e22510307..66f42857cf 100644 --- a/Content.Server/Destructible/Thresholds/Behaviors/SpillBehavior.cs +++ b/Content.Server/Destructible/Thresholds/Behaviors/SpillBehavior.cs @@ -1,6 +1,6 @@ -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Fluids.Components; using Content.Server.Fluids.EntitySystems; +using Content.Shared.Chemistry.EntitySystems; using JetBrains.Annotations; namespace Content.Server.Destructible.Thresholds.Behaviors @@ -9,7 +9,7 @@ namespace Content.Server.Destructible.Thresholds.Behaviors [DataDefinition] public sealed partial class SpillBehavior : IThresholdBehavior { - [DataField] + [DataField("solution")] public string? Solution; /// @@ -28,12 +28,13 @@ namespace Content.Server.Destructible.Thresholds.Behaviors var coordinates = system.EntityManager.GetComponent(owner).Coordinates; if (system.EntityManager.TryGetComponent(owner, out SpillableComponent? spillableComponent) && - solutionContainerSystem.TryGetSolution(owner, spillableComponent.SolutionName, out _, out var compSolution)) + solutionContainerSystem.TryGetSolution(owner, spillableComponent.SolutionName, + out var compSolution)) { spillableSystem.TrySplashSpillAt(owner, coordinates, compSolution, out _, false, user: cause); } else if (Solution != null && - solutionContainerSystem.TryGetSolution(owner, Solution, out _, out var behaviorSolution)) + solutionContainerSystem.TryGetSolution(owner, Solution, out var behaviorSolution)) { spillableSystem.TrySplashSpillAt(owner, coordinates, behaviorSolution, out _, user: cause); } diff --git a/Content.Server/Explosion/EntitySystems/TriggerSystem.cs b/Content.Server/Explosion/EntitySystems/TriggerSystem.cs index 5bb60abdc9..323dae493a 100644 --- a/Content.Server/Explosion/EntitySystems/TriggerSystem.cs +++ b/Content.Server/Explosion/EntitySystems/TriggerSystem.cs @@ -1,30 +1,30 @@ +using System.Linq; using Content.Server.Administration.Logs; using Content.Server.Body.Systems; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Explosion.Components; using Content.Server.Flash; using Content.Server.Flash.Components; using Content.Server.Radio.EntitySystems; -using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Components.SolutionManager; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Database; using Content.Shared.Implants.Components; using Content.Shared.Interaction; -using Content.Shared.Mobs; -using Content.Shared.Mobs.Components; using Content.Shared.Payload.Components; +using Robust.Shared.Prototypes; using Content.Shared.Radio; using Content.Shared.Slippery; using Content.Shared.StepTrigger.Systems; using Content.Shared.Trigger; -using Content.Shared.Weapons.Ranged.Events; using JetBrains.Annotations; using Robust.Shared.Audio; -using Robust.Shared.Audio.Systems; using Robust.Shared.Containers; using Robust.Shared.Physics.Events; using Robust.Shared.Physics.Systems; -using Robust.Shared.Prototypes; +using Content.Shared.Mobs; +using Content.Shared.Mobs.Components; +using Content.Shared.Weapons.Ranged.Events; +using Robust.Shared.Audio.Systems; using Robust.Shared.Random; namespace Content.Server.Explosion.EntitySystems @@ -65,7 +65,6 @@ namespace Content.Server.Explosion.EntitySystems [Dependency] private readonly RadioSystem _radioSystem = default!; [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; - [Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!; public override void Initialize() { @@ -234,7 +233,7 @@ namespace Content.Server.Explosion.EntitySystems comp.TimeRemaining += amount; } - public void HandleTimerTrigger(EntityUid uid, EntityUid? user, float delay, float beepInterval, float? initialBeepDelay, SoundSpecifier? beepSound) + public void HandleTimerTrigger(EntityUid uid, EntityUid? user, float delay , float beepInterval, float? initialBeepDelay, SoundSpecifier? beepSound) { if (delay <= 0) { @@ -254,18 +253,12 @@ namespace Content.Server.Explosion.EntitySystems TryComp(container.ContainedEntities[0], out ChemicalPayloadComponent? chemicalPayloadComponent)) { // If a beaker is missing, the entity won't explode, so no reason to log it - if (chemicalPayloadComponent?.BeakerSlotA.Item is not { } beakerA || - chemicalPayloadComponent?.BeakerSlotB.Item is not { } beakerB || - !TryComp(beakerA, out SolutionContainerManagerComponent? containerA) || - !TryComp(beakerB, out SolutionContainerManagerComponent? containerB) || - !TryComp(beakerA, out FitsInDispenserComponent? fitsA) || - !TryComp(beakerB, out FitsInDispenserComponent? fitsB) || - !_solutionContainerSystem.TryGetSolution((beakerA, containerA), fitsA.Solution, out _, out var solutionA) || - !_solutionContainerSystem.TryGetSolution((beakerB, containerB), fitsB.Solution, out _, out var solutionB)) + if (!TryComp(chemicalPayloadComponent?.BeakerSlotA.Item, out SolutionContainerManagerComponent? beakerA) || + !TryComp(chemicalPayloadComponent?.BeakerSlotB.Item, out SolutionContainerManagerComponent? beakerB)) return; _adminLogger.Add(LogType.Trigger, - $"{ToPrettyString(user.Value):user} started a {delay} second timer trigger on entity {ToPrettyString(uid):timer}, which contains {SolutionContainerSystem.ToPrettyString(solutionA)} in one beaker and {SolutionContainerSystem.ToPrettyString(solutionB)} in the other."); + $"{ToPrettyString(user.Value):user} started a {delay} second timer trigger on entity {ToPrettyString(uid):timer}, which contains [{string.Join(", ", beakerA.Solutions.Values.First())}] in one beaker and [{string.Join(", ", beakerB.Solutions.Values.First())}] in the other."); } else { diff --git a/Content.Server/Extinguisher/FireExtinguisherSystem.cs b/Content.Server/Extinguisher/FireExtinguisherSystem.cs index 5adf067d9b..30895deb4c 100644 --- a/Content.Server/Extinguisher/FireExtinguisherSystem.cs +++ b/Content.Server/Extinguisher/FireExtinguisherSystem.cs @@ -1,7 +1,8 @@ -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Fluids.EntitySystems; using Content.Server.Popups; +using Content.Shared.Audio; using Content.Shared.Chemistry.Components; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Extinguisher; using Content.Shared.FixedPoint; using Content.Shared.Interaction; @@ -9,6 +10,7 @@ using Content.Shared.Interaction.Events; using Content.Shared.Verbs; using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; +using Robust.Shared.Player; namespace Content.Server.Extinguisher; @@ -30,25 +32,25 @@ public sealed class FireExtinguisherSystem : EntitySystem SubscribeLocalEvent(OnSprayAttempt); } - private void OnFireExtinguisherInit(Entity entity, ref ComponentInit args) + private void OnFireExtinguisherInit(EntityUid uid, FireExtinguisherComponent component, ComponentInit args) { - if (entity.Comp.HasSafety) + if (component.HasSafety) { - UpdateAppearance((entity.Owner, entity.Comp)); + UpdateAppearance(uid, component); } } - private void OnUseInHand(Entity entity, ref UseInHandEvent args) + private void OnUseInHand(EntityUid uid, FireExtinguisherComponent component, UseInHandEvent args) { if (args.Handled) return; - ToggleSafety((entity.Owner, entity.Comp), args.User); + ToggleSafety(uid, args.User, component); args.Handled = true; } - private void OnAfterInteract(Entity entity, ref AfterInteractEvent args) + private void OnAfterInteract(EntityUid uid, FireExtinguisherComponent component, AfterInteractEvent args) { if (args.Target == null || !args.CanReach) { @@ -58,23 +60,24 @@ public sealed class FireExtinguisherSystem : EntitySystem if (args.Handled) return; - if (entity.Comp.HasSafety && entity.Comp.Safety) + if (component.HasSafety && component.Safety) { - _popupSystem.PopupEntity(Loc.GetString("fire-extinguisher-component-safety-on-message"), entity.Owner, args.User); + _popupSystem.PopupEntity(Loc.GetString("fire-extinguisher-component-safety-on-message"), uid, + args.User); return; } - if (args.Target is not { Valid: true } target || - !_solutionContainerSystem.TryGetDrainableSolution(target, out var targetSoln, out var targetSolution) || - !_solutionContainerSystem.TryGetRefillableSolution(entity.Owner, out var containerSoln, out var containerSolution)) + if (args.Target is not {Valid: true} target || + !_solutionContainerSystem.TryGetDrainableSolution(target, out var targetSolution) || + !_solutionContainerSystem.TryGetRefillableSolution(uid, out var container)) { return; } args.Handled = true; - var transfer = containerSolution.AvailableVolume; - if (TryComp(entity.Owner, out var solTrans)) + var transfer = container.AvailableVolume; + if (TryComp(uid, out var solTrans)) { transfer = solTrans.TransferAmount; } @@ -82,57 +85,59 @@ public sealed class FireExtinguisherSystem : EntitySystem if (transfer > 0) { - var drained = _solutionContainerSystem.Drain(target, targetSoln.Value, transfer); - _solutionContainerSystem.TryAddSolution(containerSoln.Value, drained); + var drained = _solutionContainerSystem.Drain(target, targetSolution, transfer); + _solutionContainerSystem.TryAddSolution(uid, container, drained); - _audio.PlayPvs(entity.Comp.RefillSound, entity.Owner); - _popupSystem.PopupEntity(Loc.GetString("fire-extinguisher-component-after-interact-refilled-message", ("owner", entity.Owner)), - entity.Owner, args.Target.Value); + _audio.PlayPvs(component.RefillSound, uid); + _popupSystem.PopupEntity(Loc.GetString("fire-extinguisher-component-after-interact-refilled-message", ("owner", uid)), + uid, args.Target.Value); } } - private void OnGetInteractionVerbs(Entity entity, ref GetVerbsEvent args) + private void OnGetInteractionVerbs(EntityUid uid, FireExtinguisherComponent component, GetVerbsEvent args) { if (!args.CanInteract) return; - var user = args.User; var verb = new InteractionVerb { - Act = () => ToggleSafety((entity.Owner, entity.Comp), user), + Act = () => ToggleSafety(uid, args.User, component), Text = Loc.GetString("fire-extinguisher-component-verb-text"), }; args.Verbs.Add(verb); } - private void OnSprayAttempt(Entity entity, ref SprayAttemptEvent args) + private void OnSprayAttempt(EntityUid uid, FireExtinguisherComponent component, SprayAttemptEvent args) { - if (entity.Comp.HasSafety && entity.Comp.Safety) + if (component.HasSafety && component.Safety) { - _popupSystem.PopupEntity(Loc.GetString("fire-extinguisher-component-safety-on-message"), entity, args.User); + _popupSystem.PopupEntity(Loc.GetString("fire-extinguisher-component-safety-on-message"), uid, + args.User); args.Cancel(); } } - private void UpdateAppearance(Entity entity) + private void UpdateAppearance(EntityUid uid, FireExtinguisherComponent comp, + AppearanceComponent? appearance=null) { - if (!Resolve(entity, ref entity.Comp2, false)) + if (!Resolve(uid, ref appearance, false)) return; - if (entity.Comp1.HasSafety) + if (comp.HasSafety) { - _appearance.SetData(entity, FireExtinguisherVisuals.Safety, entity.Comp1.Safety, entity.Comp2); + _appearance.SetData(uid, FireExtinguisherVisuals.Safety, comp.Safety, appearance); } } - public void ToggleSafety(Entity extinguisher, EntityUid user) + public void ToggleSafety(EntityUid uid, EntityUid user, + FireExtinguisherComponent? extinguisher = null) { - if (!Resolve(extinguisher, ref extinguisher.Comp)) + if (!Resolve(uid, ref extinguisher)) return; - extinguisher.Comp.Safety = !extinguisher.Comp.Safety; - _audio.PlayPvs(extinguisher.Comp.SafetySound, extinguisher, AudioParams.Default.WithVariation(0.125f).WithVolume(-4f)); - UpdateAppearance((extinguisher.Owner, extinguisher.Comp)); + extinguisher.Safety = !extinguisher.Safety; + _audio.PlayPvs(extinguisher.SafetySound, uid, AudioParams.Default.WithVariation(0.125f).WithVolume(-4f)); + UpdateAppearance(uid, extinguisher); } } diff --git a/Content.Server/Fluids/EntitySystems/AbsorbentSystem.cs b/Content.Server/Fluids/EntitySystems/AbsorbentSystem.cs index 3fd2ca00e2..a2c89d4e42 100644 --- a/Content.Server/Fluids/EntitySystems/AbsorbentSystem.cs +++ b/Content.Server/Fluids/EntitySystems/AbsorbentSystem.cs @@ -1,4 +1,3 @@ -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Popups; using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.EntitySystems; @@ -25,7 +24,7 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem [Dependency] private readonly PuddleSystem _puddleSystem = default!; [Dependency] private readonly SharedMeleeWeaponSystem _melee = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; - [Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!; + [Dependency] private readonly SolutionContainerSystem _solutionSystem = default!; [Dependency] private readonly UseDelaySystem _useDelay = default!; public override void Initialize() @@ -34,7 +33,7 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem SubscribeLocalEvent(OnAbsorbentInit); SubscribeLocalEvent(OnAfterInteract); SubscribeLocalEvent(OnInteractNoHand); - SubscribeLocalEvent(OnAbsorbentSolutionChange); + SubscribeLocalEvent(OnAbsorbentSolutionChange); } private void OnAbsorbentInit(EntityUid uid, AbsorbentComponent component, ComponentInit args) @@ -43,14 +42,14 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem UpdateAbsorbent(uid, component); } - private void OnAbsorbentSolutionChange(EntityUid uid, AbsorbentComponent component, ref SolutionContainerChangedEvent args) + private void OnAbsorbentSolutionChange(EntityUid uid, AbsorbentComponent component, SolutionChangedEvent args) { UpdateAbsorbent(uid, component); } private void UpdateAbsorbent(EntityUid uid, AbsorbentComponent component) { - if (!_solutionContainerSystem.TryGetSolution(uid, AbsorbentComponent.SolutionName, out _, out var solution)) + if (!_solutionSystem.TryGetSolution(uid, AbsorbentComponent.SolutionName, out var solution)) return; var oldProgress = component.Progress.ShallowClone(); @@ -103,17 +102,17 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem public void Mop(EntityUid user, EntityUid target, EntityUid used, AbsorbentComponent component) { - if (!_solutionContainerSystem.TryGetSolution(used, AbsorbentComponent.SolutionName, out var absorberSoln)) + if (!_solutionSystem.TryGetSolution(used, AbsorbentComponent.SolutionName, out var absorbentSolution)) return; if (_useDelay.ActiveDelay(used)) return; // If it's a puddle try to grab from - if (!TryPuddleInteract(user, used, target, component, absorberSoln.Value)) + if (!TryPuddleInteract(user, used, target, component, absorbentSolution)) { // If it's refillable try to transfer - if (!TryRefillableInteract(user, used, target, component, absorberSoln.Value)) + if (!TryRefillableInteract(user, used, target, component, absorbentSolution)) return; } } @@ -121,24 +120,24 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem /// /// Logic for an absorbing entity interacting with a refillable. /// - private bool TryRefillableInteract(EntityUid user, EntityUid used, EntityUid target, AbsorbentComponent component, Entity absorbentSoln) + private bool TryRefillableInteract(EntityUid user, EntityUid used, EntityUid target, AbsorbentComponent component, Solution absorbentSolution) { if (!TryComp(target, out RefillableSolutionComponent? refillable)) return false; - if (!_solutionContainerSystem.TryGetRefillableSolution((target, refillable, null), out var refillableSoln, out var refillableSolution)) + if (!_solutionSystem.TryGetRefillableSolution(target, out var refillableSolution, refillable: refillable)) return false; if (refillableSolution.Volume <= 0) { // Target empty - only transfer absorbent contents into refillable - if (!TryTransferFromAbsorbentToRefillable(user, used, target, component, absorbentSoln, refillableSoln.Value)) + if (!TryTransferFromAbsorbentToRefillable(user, used, target, component, absorbentSolution, refillableSolution)) return false; } else { // Target non-empty - do a two-way transfer - if (!TryTwoWayAbsorbentRefillableTransfer(user, used, target, component, absorbentSoln, refillableSoln.Value)) + if (!TryTwoWayAbsorbentRefillableTransfer(user, used, target, component, absorbentSolution, refillableSolution)) return false; } @@ -155,17 +154,15 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem EntityUid used, EntityUid target, AbsorbentComponent component, - Entity absorbentSoln, - Entity refillableSoln) + Solution absorbentSolution, + Solution refillableSolution) { - var absorbentSolution = absorbentSoln.Comp.Solution; if (absorbentSolution.Volume <= 0) { _popups.PopupEntity(Loc.GetString("mopping-system-target-container-empty", ("target", target)), user, user); return false; } - var refillableSolution = refillableSoln.Comp.Solution; var transferAmount = component.PickupAmount < refillableSolution.AvailableVolume ? component.PickupAmount : refillableSolution.AvailableVolume; @@ -177,15 +174,17 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem } // Prioritize transferring non-evaporatives if absorbent has any - var contaminants = _solutionContainerSystem.SplitSolutionWithout(absorbentSoln, transferAmount, PuddleSystem.EvaporationReagents); + var contaminants = absorbentSolution.SplitSolutionWithout(transferAmount, PuddleSystem.EvaporationReagents); if (contaminants.Volume > 0) { - _solutionContainerSystem.TryAddSolution(refillableSoln, contaminants); + _solutionSystem.UpdateChemicals(used, absorbentSolution, true); + _solutionSystem.TryAddSolution(target, refillableSolution, contaminants); } else { - var evaporatives = _solutionContainerSystem.SplitSolution(absorbentSoln, transferAmount); - _solutionContainerSystem.TryAddSolution(refillableSoln, evaporatives); + var evaporatives = absorbentSolution.SplitSolution(transferAmount); + _solutionSystem.UpdateChemicals(used, absorbentSolution, true); + _solutionSystem.TryAddSolution(target, refillableSolution, evaporatives); } return true; @@ -199,12 +198,12 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem EntityUid used, EntityUid target, AbsorbentComponent component, - Entity absorbentSoln, - Entity refillableSoln) + Solution absorbentSolution, + Solution refillableSolution) { - var contaminantsFromAbsorbent = _solutionContainerSystem.SplitSolutionWithout(absorbentSoln, component.PickupAmount, PuddleSystem.EvaporationReagents); + var contaminantsFromAbsorbent = absorbentSolution.SplitSolutionWithout(component.PickupAmount, PuddleSystem.EvaporationReagents); + _solutionSystem.UpdateChemicals(used, absorbentSolution, true); - var absorbentSolution = absorbentSoln.Comp.Solution; if (contaminantsFromAbsorbent.Volume == FixedPoint2.Zero && absorbentSolution.AvailableVolume == FixedPoint2.Zero) { // Nothing to transfer to refillable and no room to absorb anything extra @@ -218,9 +217,8 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem component.PickupAmount : absorbentSolution.AvailableVolume; - var refillableSolution = refillableSoln.Comp.Solution; var waterFromRefillable = refillableSolution.SplitSolutionWithOnly(waterPulled, PuddleSystem.EvaporationReagents); - _solutionContainerSystem.UpdateChemicals(refillableSoln); + _solutionSystem.UpdateChemicals(target, refillableSolution); if (waterFromRefillable.Volume == FixedPoint2.Zero && contaminantsFromAbsorbent.Volume == FixedPoint2.Zero) { @@ -236,7 +234,7 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem if (waterFromRefillable.Volume > FixedPoint2.Zero) { // transfer water to absorbent - _solutionContainerSystem.TryAddSolution(absorbentSoln, waterFromRefillable); + _solutionSystem.TryAddSolution(used, absorbentSolution, waterFromRefillable); anyTransferOccurred = true; } @@ -250,12 +248,12 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem { // transfer as much contaminants to refillable as will fit var contaminantsForRefillable = contaminantsFromAbsorbent.SplitSolution(refillableSolution.AvailableVolume); - _solutionContainerSystem.TryAddSolution(refillableSoln, contaminantsForRefillable); + _solutionSystem.TryAddSolution(target, refillableSolution, contaminantsForRefillable); anyTransferOccurred = true; } // absorb everything that did not fit in the refillable back by the absorbent - _solutionContainerSystem.TryAddSolution(absorbentSoln, contaminantsFromAbsorbent); + _solutionSystem.TryAddSolution(used, absorbentSolution, contaminantsFromAbsorbent); } return anyTransferOccurred; @@ -264,24 +262,23 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem /// /// Logic for an absorbing entity interacting with a puddle. /// - private bool TryPuddleInteract(EntityUid user, EntityUid used, EntityUid target, AbsorbentComponent absorber, Entity absorberSoln) + private bool TryPuddleInteract(EntityUid user, EntityUid used, EntityUid target, AbsorbentComponent absorber, Solution absorberSoln) { if (!TryComp(target, out PuddleComponent? puddle)) return false; - if (!_solutionContainerSystem.ResolveSolution(target, puddle.SolutionName, ref puddle.Solution, out var puddleSolution) || puddleSolution.Volume <= 0) + if (!_solutionSystem.TryGetSolution(target, puddle.SolutionName, out var puddleSoln) || puddleSoln.Volume <= 0) return false; // Check if the puddle has any non-evaporative reagents - if (_puddleSystem.CanFullyEvaporate(puddleSolution)) + if (_puddleSystem.CanFullyEvaporate(puddleSoln)) { _popups.PopupEntity(Loc.GetString("mopping-system-puddle-evaporate", ("target", target)), user, user); return true; } // Check if we have any evaporative reagents on our absorber to transfer - var absorberSolution = absorberSoln.Comp.Solution; - var available = absorberSolution.GetTotalPrototypeQuantity(PuddleSystem.EvaporationReagents); + var available = absorberSoln.GetTotalPrototypeQuantity(PuddleSystem.EvaporationReagents); // No material if (available == FixedPoint2.Zero) @@ -293,8 +290,8 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem var transferMax = absorber.PickupAmount; var transferAmount = available > transferMax ? transferMax : available; - var puddleSplit = puddleSolution.SplitSolutionWithout(transferAmount, PuddleSystem.EvaporationReagents); - var absorberSplit = absorberSolution.SplitSolutionWithOnly(puddleSplit.Volume, PuddleSystem.EvaporationReagents); + var puddleSplit = puddleSoln.SplitSolutionWithout(transferAmount, PuddleSystem.EvaporationReagents); + var absorberSplit = absorberSoln.SplitSolutionWithOnly(puddleSplit.Volume, PuddleSystem.EvaporationReagents); // Do tile reactions first var coordinates = Transform(target).Coordinates; @@ -303,9 +300,11 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem _puddleSystem.DoTileReactions(mapGrid.GetTileRef(coordinates), absorberSplit); } - _solutionContainerSystem.AddSolution(puddle.Solution.Value, absorberSplit); - _solutionContainerSystem.AddSolution(absorberSoln, puddleSplit); + puddleSoln.AddSolution(absorberSplit, _prototype); + absorberSoln.AddSolution(puddleSplit, _prototype); + _solutionSystem.UpdateChemicals(used, absorberSoln); + _solutionSystem.UpdateChemicals(target, puddleSoln); _audio.PlayPvs(absorber.PickupSound, target); _useDelay.BeginDelay(used); diff --git a/Content.Server/Fluids/EntitySystems/DrainSystem.cs b/Content.Server/Fluids/EntitySystems/DrainSystem.cs index 726ed0b13c..505ce71261 100644 --- a/Content.Server/Fluids/EntitySystems/DrainSystem.cs +++ b/Content.Server/Fluids/EntitySystems/DrainSystem.cs @@ -1,9 +1,9 @@ -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.DoAfter; using Content.Server.Fluids.Components; using Content.Server.Popups; using Content.Shared.Audio; using Content.Shared.Chemistry.Components.SolutionManager; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Database; using Content.Shared.DoAfter; using Content.Shared.Examine; @@ -13,9 +13,10 @@ using Content.Shared.Fluids.Components; using Content.Shared.Interaction; using Content.Shared.Tag; using Content.Shared.Verbs; +using Content.Shared.Fluids.Components; +using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; using Robust.Shared.Collections; -using Robust.Shared.Prototypes; using Robust.Shared.Random; using Robust.Shared.Utility; @@ -24,7 +25,7 @@ namespace Content.Server.Fluids.EntitySystems; public sealed class DrainSystem : SharedDrainSystem { [Dependency] private readonly EntityLookupSystem _lookup = default!; - [Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!; + [Dependency] private readonly SolutionContainerSystem _solutionSystem = default!; [Dependency] private readonly SharedAmbientSoundSystem _ambientSoundSystem = default!; [Dependency] private readonly SharedAudioSystem _audioSystem = default!; [Dependency] private readonly PopupSystem _popupSystem = default!; @@ -32,7 +33,6 @@ public sealed class DrainSystem : SharedDrainSystem [Dependency] private readonly DoAfterSystem _doAfterSystem = default!; [Dependency] private readonly PuddleSystem _puddleSystem = default!; [Dependency] private readonly IRobustRandom _random = default!; - [Dependency] private readonly IPrototypeManager _prototypeManager = default!; public override void Initialize() { @@ -43,7 +43,7 @@ public sealed class DrainSystem : SharedDrainSystem SubscribeLocalEvent(OnDoAfter); } - private void AddEmptyVerb(Entity entity, ref GetVerbsEvent args) + private void AddEmptyVerb(EntityUid uid, DrainComponent component, GetVerbsEvent args) { if (!args.CanAccess || !args.CanInteract || args.Using == null) return; @@ -52,14 +52,12 @@ public sealed class DrainSystem : SharedDrainSystem !TryComp(args.Target, out DrainComponent? drain)) return; - var used = args.Using.Value; - var target = args.Target; Verb verb = new() { - Text = Loc.GetString("drain-component-empty-verb-inhand", ("object", Name(used))), + Text = Loc.GetString("drain-component-empty-verb-inhand", ("object", Name(args.Using.Value))), Act = () => { - Empty(used, spillable, target, drain); + Empty(args.Using.Value, spillable, args.Target, drain); }, Impact = LogImpact.Low, Icon = new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/VerbIcons/eject.svg.192dpi.png")) @@ -71,7 +69,8 @@ public sealed class DrainSystem : SharedDrainSystem private void Empty(EntityUid container, SpillableComponent spillable, EntityUid target, DrainComponent drain) { // Find the solution in the container that is emptied - if (!_solutionContainerSystem.TryGetDrainableSolution(container, out var containerSoln, out var containerSolution) || containerSolution.Volume == FixedPoint2.Zero) + if (!_solutionSystem.TryGetDrainableSolution(container, out var containerSolution) || + containerSolution.Volume == FixedPoint2.Zero) { _popupSystem.PopupEntity( Loc.GetString("drain-component-empty-verb-using-is-empty-message", ("object", container)), @@ -80,17 +79,17 @@ public sealed class DrainSystem : SharedDrainSystem } // try to find the drain's solution - if (!_solutionContainerSystem.ResolveSolution(target, DrainComponent.SolutionName, ref drain.Solution, out var drainSolution)) + if (!_solutionSystem.TryGetSolution(target, DrainComponent.SolutionName, out var drainSolution)) { return; } // Try to transfer as much solution as possible to the drain - var transferSolution = _solutionContainerSystem.SplitSolution(containerSoln.Value, + var transferSolution = _solutionSystem.SplitSolution(container, containerSolution, FixedPoint2.Min(containerSolution.Volume, drainSolution.AvailableVolume)); - _solutionContainerSystem.TryAddSolution(drain.Solution.Value, transferSolution); + _solutionSystem.TryAddSolution(target, drainSolution, transferSolution); _audioSystem.PlayPvs(drain.ManualDrainSound, target); _ambientSoundSystem.SetAmbience(target, true); @@ -112,7 +111,7 @@ public sealed class DrainSystem : SharedDrainSystem var managerQuery = GetEntityQuery(); var xformQuery = GetEntityQuery(); var puddleQuery = GetEntityQuery(); - var puddles = new ValueList<(Entity Entity, string Solution)>(); + var puddles = new ValueList<(EntityUid Entity, string Solution)>(); var query = EntityQueryEnumerator(); while (query.MoveNext(out var uid, out var drain)) @@ -135,7 +134,9 @@ public sealed class DrainSystem : SharedDrainSystem continue; // Best to do this one every second rather than once every tick... - if (!_solutionContainerSystem.ResolveSolution((uid, manager), DrainComponent.SolutionName, ref drain.Solution, out var drainSolution)) + _solutionSystem.TryGetSolution(uid, DrainComponent.SolutionName, out var drainSolution, manager); + + if (drainSolution is null) continue; if (drainSolution.AvailableVolume <= 0) @@ -145,7 +146,7 @@ public sealed class DrainSystem : SharedDrainSystem } // Remove a bit from the buffer - _solutionContainerSystem.SplitSolution(drain.Solution.Value, (drain.UnitsDestroyedPerSecond * drain.DrainFrequency)); + _solutionSystem.SplitSolution(uid, drainSolution, (drain.UnitsDestroyedPerSecond * drain.DrainFrequency)); // This will ensure that UnitsPerSecond is per second... var amount = drain.UnitsPerSecond * drain.DrainFrequency; @@ -161,7 +162,7 @@ public sealed class DrainSystem : SharedDrainSystem // and these are placed by mappers and not buildable/movable so shouldnt really be a problem... if (puddleQuery.TryGetComponent(entity, out var puddle)) { - puddles.Add(((entity, puddle), puddle.SolutionName)); + puddles.Add((entity, puddle.SolutionName)); } } @@ -179,7 +180,7 @@ public sealed class DrainSystem : SharedDrainSystem { // Queue the solution deletion if it's empty. EvaporationSystem might also do this // but queuedelete should be pretty safe. - if (!_solutionContainerSystem.ResolveSolution(puddle.Owner, solution, ref puddle.Comp.Solution, out var puddleSolution)) + if (!_solutionSystem.TryGetSolution(puddle, solution, out var puddleSolution)) { EntityManager.QueueDeleteEntity(puddle); continue; @@ -189,26 +190,24 @@ public sealed class DrainSystem : SharedDrainSystem // the drain component's units per second adjusted for # of puddles // the puddle's remaining volume (making it cleanly zero) // the drain's remaining volume in its buffer. - var transferSolution = _solutionContainerSystem.SplitSolution(puddle.Comp.Solution.Value, + var transferSolution = _solutionSystem.SplitSolution(puddle, puddleSolution, FixedPoint2.Min(FixedPoint2.New(amount), puddleSolution.Volume, drainSolution.AvailableVolume)); - drainSolution.AddSolution(transferSolution, _prototypeManager); + _solutionSystem.TryAddSolution(uid, drainSolution, transferSolution); if (puddleSolution.Volume <= 0) { QueueDel(puddle); } } - - _solutionContainerSystem.UpdateChemicals(drain.Solution.Value); } } - private void OnExamined(Entity entity, ref ExaminedEvent args) + private void OnExamined(EntityUid uid, DrainComponent component, ExaminedEvent args) { if (!args.IsInDetailsRange || - !HasComp(entity) || - !_solutionContainerSystem.ResolveSolution(entity.Owner, DrainComponent.SolutionName, ref entity.Comp.Solution, out var drainSolution)) + !HasComp(uid) || + !_solutionSystem.TryGetSolution(uid, DrainComponent.SolutionName, out var drainSolution)) { return; } @@ -219,11 +218,11 @@ public sealed class DrainSystem : SharedDrainSystem args.Message.AddMarkup($"\n\n{text}"); } - private void OnInteract(Entity entity, ref AfterInteractUsingEvent args) + private void OnInteract(EntityUid uid, DrainComponent component, InteractEvent args) { if (!args.CanReach || args.Target == null || !_tagSystem.HasTag(args.Used, DrainComponent.PlungerTag) || - !_solutionContainerSystem.ResolveSolution(args.Target.Value, DrainComponent.SolutionName, ref entity.Comp.Solution, out var drainSolution)) + !_solutionSystem.TryGetSolution(args.Target.Value, DrainComponent.SolutionName, out var drainSolution)) { return; } @@ -234,10 +233,10 @@ public sealed class DrainSystem : SharedDrainSystem return; } - _audioSystem.PlayPvs(entity.Comp.PlungerSound, entity); + _audioSystem.PlayPvs(component.PlungerSound, uid); - var doAfterArgs = new DoAfterArgs(EntityManager, args.User, entity.Comp.UnclogDuration, new DrainDoAfterEvent(), entity, args.Target, args.Used) + var doAfterArgs = new DoAfterArgs(EntityManager, args.User, component.UnclogDuration, new DrainDoAfterEvent(),uid, args.Target, args.Used) { BreakOnTargetMove = true, BreakOnUserMove = true, @@ -248,26 +247,27 @@ public sealed class DrainSystem : SharedDrainSystem _doAfterSystem.TryStartDoAfter(doAfterArgs); } - private void OnDoAfter(Entity entity, ref DrainDoAfterEvent args) + private void OnDoAfter(EntityUid uid, DrainComponent component, DoAfterEvent args) { if (args.Target == null) return; - if (!_random.Prob(entity.Comp.UnclogProbability)) + if (!_random.Prob(component.UnclogProbability)) { _popupSystem.PopupEntity(Loc.GetString("drain-component-unclog-fail", ("object", args.Target.Value)), args.Target.Value); return; } - if (!_solutionContainerSystem.ResolveSolution(args.Target.Value, DrainComponent.SolutionName, ref entity.Comp.Solution)) + if (!_solutionSystem.TryGetSolution(args.Target.Value, DrainComponent.SolutionName, + out var drainSolution)) { return; } - _solutionContainerSystem.RemoveAllSolution(entity.Comp.Solution.Value); - _audioSystem.PlayPvs(entity.Comp.UnclogSound, args.Target.Value); + _solutionSystem.RemoveAllSolution(args.Target.Value, drainSolution); + _audioSystem.PlayPvs(component.UnclogSound, args.Target.Value); _popupSystem.PopupEntity(Loc.GetString("drain-component-unclog-success", ("object", args.Target.Value)), args.Target.Value); } } diff --git a/Content.Server/Fluids/EntitySystems/PuddleSystem.Evaporation.cs b/Content.Server/Fluids/EntitySystems/PuddleSystem.Evaporation.cs index f3489ba7c6..d0df5e0505 100644 --- a/Content.Server/Fluids/EntitySystems/PuddleSystem.Evaporation.cs +++ b/Content.Server/Fluids/EntitySystems/PuddleSystem.Evaporation.cs @@ -18,9 +18,9 @@ public sealed partial class PuddleSystem public static string[] EvaporationReagents = new[] { Water, SoapyWater }; - private void OnEvaporationMapInit(Entity entity, ref MapInitEvent args) + private void OnEvaporationMapInit(EntityUid uid, EvaporationComponent component, MapInitEvent args) { - entity.Comp.NextTick = _timing.CurTime + EvaporationCooldown; + component.NextTick = _timing.CurTime + EvaporationCooldown; } private void UpdateEvaporation(EntityUid uid, Solution solution) @@ -52,7 +52,7 @@ public sealed partial class PuddleSystem evaporation.NextTick += EvaporationCooldown; - if (!_solutionContainerSystem.ResolveSolution(uid, puddle.SolutionName, ref puddle.Solution, out var puddleSolution)) + if (!_solutionContainerSystem.TryGetSolution(uid, puddle.SolutionName, out var puddleSolution)) continue; var reagentTick = evaporation.EvaporationAmount * EvaporationCooldown.TotalSeconds; diff --git a/Content.Server/Fluids/EntitySystems/PuddleSystem.Spillable.cs b/Content.Server/Fluids/EntitySystems/PuddleSystem.Spillable.cs index 083d15c22e..e1681d8731 100644 --- a/Content.Server/Fluids/EntitySystems/PuddleSystem.Spillable.cs +++ b/Content.Server/Fluids/EntitySystems/PuddleSystem.Spillable.cs @@ -1,4 +1,4 @@ -using Content.Server.Chemistry.Containers.EntitySystems; +using Content.Server.Chemistry.EntitySystems; using Content.Server.Fluids.Components; using Content.Server.Nutrition.EntitySystems; using Content.Shared.Chemistry.Components; @@ -36,29 +36,29 @@ public sealed partial class PuddleSystem SubscribeLocalEvent(SplashOnMeleeHit, after: new[] { typeof(OpenableSystem) }); SubscribeLocalEvent>(AddSpillVerb); SubscribeLocalEvent(OnGotEquipped); - SubscribeLocalEvent(OnOverflow); + SubscribeLocalEvent(OnOverflow); SubscribeLocalEvent(OnDoAfter); SubscribeLocalEvent(OnAttemptPacifiedThrow); } - private void OnExamined(Entity entity, ref ExaminedEvent args) + private void OnExamined(EntityUid uid, SpillableComponent component, ExaminedEvent args) { args.PushMarkup(Loc.GetString("spill-examine-is-spillable")); - if (HasComp(entity)) + if (HasComp(uid)) args.PushMarkup(Loc.GetString("spill-examine-spillable-weapon")); } - private void OnOverflow(Entity entity, ref SolutionContainerOverflowEvent args) + private void OnOverflow(EntityUid uid, SpillableComponent component, ref SolutionOverflowEvent args) { if (args.Handled) return; - TrySpillAt(Transform(entity).Coordinates, args.Overflow, out _); + TrySpillAt(Transform(uid).Coordinates, args.Overflow, out _); args.Handled = true; } - private void SplashOnMeleeHit(Entity entity, ref MeleeHitEvent args) + private void SplashOnMeleeHit(EntityUid uid, SpillableComponent component, MeleeHitEvent args) { if (args.Handled) return; @@ -68,20 +68,20 @@ public sealed partial class PuddleSystem // If this also has solution transfer, then assume the transfer amount is how much we want to spill. // Otherwise let's say they want to spill a quarter of its max volume. - if (!_solutionContainerSystem.TryGetDrainableSolution(entity.Owner, out var soln, out var solution)) + if (!_solutionContainerSystem.TryGetDrainableSolution(uid, out var solution)) return; var hitCount = args.HitEntities.Count; var totalSplit = FixedPoint2.Min(solution.MaxVolume * 0.25, solution.Volume); - if (TryComp(entity, out var transfer)) + if (TryComp(uid, out var transfer)) { totalSplit = FixedPoint2.Min(transfer.TransferAmount, solution.Volume); } // a little lame, but reagent quantity is not very balanced and we don't want people // spilling like 100u of reagent on someone at once! - totalSplit = FixedPoint2.Min(totalSplit, entity.Comp.MaxMeleeSpillAmount); + totalSplit = FixedPoint2.Min(totalSplit, component.MaxMeleeSpillAmount); if (totalSplit == 0) return; @@ -95,29 +95,29 @@ public sealed partial class PuddleSystem continue; } - var splitSolution = _solutionContainerSystem.SplitSolution(soln.Value, totalSplit / hitCount); + var splitSolution = _solutionContainerSystem.SplitSolution(uid, solution, totalSplit / hitCount); - _adminLogger.Add(LogType.MeleeHit, $"{ToPrettyString(args.User)} splashed {SolutionContainerSystem.ToPrettyString(splitSolution):solution} from {ToPrettyString(entity.Owner):entity} onto {ToPrettyString(hit):target}"); + _adminLogger.Add(LogType.MeleeHit, $"{ToPrettyString(args.User)} splashed {SolutionContainerSystem.ToPrettyString(splitSolution):solution} from {ToPrettyString(uid):entity} onto {ToPrettyString(hit):target}"); _reactive.DoEntityReaction(hit, splitSolution, ReactionMethod.Touch); _popups.PopupEntity( - Loc.GetString("spill-melee-hit-attacker", ("amount", totalSplit / hitCount), ("spillable", entity.Owner), + Loc.GetString("spill-melee-hit-attacker", ("amount", totalSplit / hitCount), ("spillable", uid), ("target", Identity.Entity(hit, EntityManager))), hit, args.User); _popups.PopupEntity( - Loc.GetString("spill-melee-hit-others", ("attacker", args.User), ("spillable", entity.Owner), + Loc.GetString("spill-melee-hit-others", ("attacker", args.User), ("spillable", uid), ("target", Identity.Entity(hit, EntityManager))), hit, Filter.PvsExcept(args.User), true, PopupType.SmallCaution); } } - private void OnGotEquipped(Entity entity, ref GotEquippedEvent args) + private void OnGotEquipped(EntityUid uid, SpillableComponent component, GotEquippedEvent args) { - if (!entity.Comp.SpillWorn) + if (!component.SpillWorn) return; - if (!TryComp(entity, out ClothingComponent? clothing)) + if (!TryComp(uid, out ClothingComponent? clothing)) return; // check if entity was actually used as clothing @@ -126,33 +126,33 @@ public sealed partial class PuddleSystem if (!isCorrectSlot) return; - if (!_solutionContainerSystem.TryGetSolution(entity.Owner, entity.Comp.SolutionName, out var soln, out var solution)) + if (!_solutionContainerSystem.TryGetSolution(uid, component.SolutionName, out var solution)) return; if (solution.Volume == 0) return; // spill all solution on the player - var drainedSolution = _solutionContainerSystem.Drain(entity.Owner, soln.Value, solution.Volume); - TrySplashSpillAt(entity.Owner, Transform(args.Equipee).Coordinates, drainedSolution, out _); + var drainedSolution = _solutionContainerSystem.Drain(uid, solution, solution.Volume); + TrySplashSpillAt(uid, Transform(args.Equipee).Coordinates, drainedSolution, out _); } - private void SpillOnLand(Entity entity, ref LandEvent args) + private void SpillOnLand(EntityUid uid, SpillableComponent component, ref LandEvent args) { - if (!_solutionContainerSystem.TryGetSolution(entity.Owner, entity.Comp.SolutionName, out var soln, out var solution)) + if (!_solutionContainerSystem.TryGetSolution(uid, component.SolutionName, out var solution)) return; - if (_openable.IsClosed(entity.Owner)) + if (_openable.IsClosed(uid)) return; if (args.User != null) { _adminLogger.Add(LogType.Landed, - $"{ToPrettyString(entity.Owner):entity} spilled a solution {SolutionContainerSystem.ToPrettyString(solution):solution} on landing"); + $"{ToPrettyString(uid):entity} spilled a solution {SolutionContainerSystem.ToPrettyString(solution):solution} on landing"); } - var drainedSolution = _solutionContainerSystem.Drain(entity.Owner, soln.Value, solution.Volume); - TrySplashSpillAt(entity.Owner, Transform(entity).Coordinates, drainedSolution, out _); + var drainedSolution = _solutionContainerSystem.Drain(uid, solution, solution.Volume); + TrySplashSpillAt(uid, Transform(uid).Coordinates, drainedSolution, out _); } /// @@ -165,18 +165,18 @@ public sealed partial class PuddleSystem return; // Don’t care about empty containers. - if (!_solutionContainerSystem.TryGetSolution(ent.Owner, ent.Comp.SolutionName, out _, out var solution) || solution.Volume <= 0) + if (!_solutionContainerSystem.TryGetSolution(ent, ent.Comp.SolutionName, out var solution)) return; args.Cancel("pacified-cannot-throw-spill"); } - private void AddSpillVerb(Entity entity, ref GetVerbsEvent args) + private void AddSpillVerb(EntityUid uid, SpillableComponent component, GetVerbsEvent args) { if (!args.CanAccess || !args.CanInteract) return; - if (!_solutionContainerSystem.TryGetSolution(args.Target, entity.Comp.SolutionName, out var soln, out var solution)) + if (!_solutionContainerSystem.TryGetSolution(args.Target, component.SolutionName, out var solution)) return; if (_openable.IsClosed(args.Target)) @@ -195,21 +195,20 @@ public sealed partial class PuddleSystem }; // TODO VERB ICONS spill icon? pouring out a glass/beaker? - if (entity.Comp.SpillDelay == null) + if (component.SpillDelay == null) { - var target = args.Target; verb.Act = () => { - var puddleSolution = _solutionContainerSystem.SplitSolution(soln.Value, solution.Volume); - TrySpillAt(Transform(target).Coordinates, puddleSolution, out _); + var puddleSolution = _solutionContainerSystem.SplitSolution(args.Target, + solution, solution.Volume); + TrySpillAt(Transform(args.Target).Coordinates, puddleSolution, out _); }; } else { - var user = args.User; verb.Act = () => { - _doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager, user, entity.Comp.SpillDelay ?? 0, new SpillDoAfterEvent(), entity.Owner, target: entity.Owner) + _doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager, args.User, component.SpillDelay ?? 0, new SpillDoAfterEvent(), uid, target: uid) { BreakOnTargetMove = true, BreakOnUserMove = true, @@ -223,17 +222,17 @@ public sealed partial class PuddleSystem args.Verbs.Add(verb); } - private void OnDoAfter(Entity entity, ref SpillDoAfterEvent args) + private void OnDoAfter(EntityUid uid, SpillableComponent component, DoAfterEvent args) { if (args.Handled || args.Cancelled || args.Args.Target == null) return; //solution gone by other means before doafter completes - if (!_solutionContainerSystem.TryGetDrainableSolution(entity.Owner, out var soln, out var solution) || solution.Volume == 0) + if (!_solutionContainerSystem.TryGetDrainableSolution(uid, out var solution) || solution.Volume == 0) return; - var puddleSolution = _solutionContainerSystem.SplitSolution(soln.Value, solution.Volume); - TrySpillAt(Transform(entity).Coordinates, puddleSolution, out _); + var puddleSolution = _solutionContainerSystem.SplitSolution(uid, solution, solution.Volume); + TrySpillAt(Transform(uid).Coordinates, puddleSolution, out _); args.Handled = true; } } diff --git a/Content.Server/Fluids/EntitySystems/PuddleSystem.Transfers.cs b/Content.Server/Fluids/EntitySystems/PuddleSystem.Transfers.cs index 04bbf55c58..ba73adf389 100644 --- a/Content.Server/Fluids/EntitySystems/PuddleSystem.Transfers.cs +++ b/Content.Server/Fluids/EntitySystems/PuddleSystem.Transfers.cs @@ -1,7 +1,9 @@ +using Content.Server.Fluids.Components; using Content.Shared.Chemistry.Components; using Content.Shared.DragDrop; using Content.Shared.FixedPoint; using Content.Shared.Fluids; +using Content.Shared.Fluids.Components; namespace Content.Server.Fluids.EntitySystems; @@ -12,30 +14,33 @@ public sealed partial class PuddleSystem SubscribeLocalEvent(OnRefillableDragged); } - private void OnRefillableDragged(Entity entity, ref DragDropDraggedEvent args) + private void OnRefillableDragged(EntityUid uid, RefillableSolutionComponent component, ref DragDropDraggedEvent args) { - if (!_solutionContainerSystem.TryGetSolution(entity.Owner, entity.Comp.Solution, out var soln, out var solution) || solution.Volume == FixedPoint2.Zero) + _solutionContainerSystem.TryGetSolution(uid, component.Solution, out var solution); + + if (solution?.Volume == FixedPoint2.Zero) { - _popups.PopupEntity(Loc.GetString("mopping-system-empty", ("used", entity.Owner)), entity, args.User); + _popups.PopupEntity(Loc.GetString("mopping-system-empty", ("used", uid)), uid, args.User); return; } // Dump reagents into DumpableSolution if (TryComp(args.Target, out var dump)) { - if (!_solutionContainerSystem.TryGetDumpableSolution((args.Target, dump, null), out var dumpableSoln, out var dumpableSolution)) + _solutionContainerSystem.TryGetDumpableSolution(args.Target, out var dumpableSolution, dump); + if (dumpableSolution == null || solution == null) return; bool success = true; if (dump.Unlimited) { - var split = _solutionContainerSystem.SplitSolution(soln.Value, solution.Volume); + var split = _solutionContainerSystem.SplitSolution(uid, solution, solution.Volume); dumpableSolution.AddSolution(split, _prototypeManager); } else { - var split = _solutionContainerSystem.SplitSolution(soln.Value, dumpableSolution.AvailableVolume); - success = _solutionContainerSystem.TryAddSolution(dumpableSoln.Value, split); + var split = _solutionContainerSystem.SplitSolution(uid, solution, dumpableSolution.AvailableVolume); + success = _solutionContainerSystem.TryAddSolution(args.Target, dumpableSolution, split); } if (success) @@ -50,21 +55,25 @@ public sealed partial class PuddleSystem return; } + TryComp(args.Target, out var drainable); + + _solutionContainerSystem.TryGetDrainableSolution(args.Target, out var drainableSolution, drainable); + // Take reagents from target - if (!TryComp(args.Target, out var drainable)) + if (drainable != null) { - if (!_solutionContainerSystem.TryGetDrainableSolution((args.Target, drainable, null), out var drainableSolution, out _)) + if (drainableSolution == null || solution == null) return; - var split = _solutionContainerSystem.SplitSolution(drainableSolution.Value, solution.AvailableVolume); + var split = _solutionContainerSystem.SplitSolution(args.Target, drainableSolution, solution.AvailableVolume); - if (_solutionContainerSystem.TryAddSolution(soln.Value, split)) + if (_solutionContainerSystem.TryAddSolution(uid, solution, split)) { - _audio.PlayPvs(AbsorbentComponent.DefaultTransferSound, entity); + _audio.PlayPvs(AbsorbentComponent.DefaultTransferSound, uid); } else { - _popups.PopupEntity(Loc.GetString("mopping-system-full", ("used", entity.Owner)), entity, args.User); + _popups.PopupEntity(Loc.GetString("mopping-system-full", ("used", uid)), uid, args.User); } } } diff --git a/Content.Server/Fluids/EntitySystems/PuddleSystem.cs b/Content.Server/Fluids/EntitySystems/PuddleSystem.cs index 844f43a5e4..05d0809bb2 100644 --- a/Content.Server/Fluids/EntitySystems/PuddleSystem.cs +++ b/Content.Server/Fluids/EntitySystems/PuddleSystem.cs @@ -1,5 +1,4 @@ using Content.Server.Administration.Logs; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.DoAfter; using Content.Server.Fluids.Components; using Content.Server.Spreader; @@ -23,13 +22,19 @@ using Content.Shared.Popups; using Content.Shared.Slippery; using Content.Shared.StepTrigger.Components; using Content.Shared.StepTrigger.Systems; -using Robust.Server.Audio; +using Robust.Server.GameObjects; +using Robust.Shared.Audio; using Robust.Shared.Map; using Robust.Shared.Map.Components; using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Random; using Robust.Shared.Timing; +using Content.Shared.Movement.Components; +using Content.Shared.Movement.Systems; +using Content.Shared.Maps; +using Content.Shared.Effects; +using Robust.Server.Audio; namespace Content.Server.Fluids.EntitySystems; @@ -86,7 +91,7 @@ public sealed partial class PuddleSystem : SharedPuddleSystem // Shouldn't need re-anchoring. SubscribeLocalEvent(OnAnchorChanged); SubscribeLocalEvent(HandlePuddleExamined); - SubscribeLocalEvent(OnSolutionUpdate); + SubscribeLocalEvent(OnSolutionUpdate); SubscribeLocalEvent(OnPuddleInit); SubscribeLocalEvent(OnPuddleSpread); SubscribeLocalEvent(OnPuddleSlip); @@ -97,13 +102,13 @@ public sealed partial class PuddleSystem : SharedPuddleSystem InitializeTransfers(); } - private void OnPuddleSpread(Entity entity, ref SpreadNeighborsEvent args) + private void OnPuddleSpread(EntityUid uid, PuddleComponent component, ref SpreadNeighborsEvent args) { - var overflow = GetOverflowSolution(entity.Owner, entity.Comp); + var overflow = GetOverflowSolution(uid, component); if (overflow.Volume == FixedPoint2.Zero) { - RemCompDeferred(entity); + RemCompDeferred(uid); return; } @@ -120,7 +125,7 @@ public sealed partial class PuddleSystem : SharedPuddleSystem foreach (var neighbor in args.Neighbors) { if (!puddleQuery.TryGetComponent(neighbor, out var puddle) || - !_solutionContainerSystem.ResolveSolution(neighbor, puddle.SolutionName, ref puddle.Solution, out var neighborSolution) || + !_solutionContainerSystem.TryGetSolution(neighbor, puddle.SolutionName, out var neighborSolution) || CanFullyEvaporate(neighborSolution)) { continue; @@ -133,7 +138,7 @@ public sealed partial class PuddleSystem : SharedPuddleSystem var split = overflow.SplitSolution(remaining); - if (!_solutionContainerSystem.TryAddSolution(puddle.Solution.Value, split)) + if (!_solutionContainerSystem.TryAddSolution(neighbor, neighborSolution, split)) continue; args.Updates--; @@ -145,7 +150,7 @@ public sealed partial class PuddleSystem : SharedPuddleSystem if (overflow.Volume == FixedPoint2.Zero) { - RemCompDeferred(entity); + RemCompDeferred(uid); return; } } @@ -168,7 +173,7 @@ public sealed partial class PuddleSystem : SharedPuddleSystem break; } - RemCompDeferred(entity); + RemCompDeferred(uid); return; } @@ -181,7 +186,7 @@ public sealed partial class PuddleSystem : SharedPuddleSystem { // Overflow to neighbours (unless it's pure water) if (!puddleQuery.TryGetComponent(neighbor, out var puddle) || - !_solutionContainerSystem.ResolveSolution(neighbor, puddle.SolutionName, ref puddle.Solution, out var neighborSolution) || + !_solutionContainerSystem.TryGetSolution(neighbor, puddle.SolutionName, out var neighborSolution) || CanFullyEvaporate(neighborSolution)) { continue; @@ -189,7 +194,7 @@ public sealed partial class PuddleSystem : SharedPuddleSystem var split = overflow.SplitSolution(spillPerNeighbor); - if (!_solutionContainerSystem.TryAddSolution(puddle.Solution.Value, split)) + if (!_solutionContainerSystem.TryAddSolution(neighbor, neighborSolution, split)) continue; EnsureComp(neighbor); @@ -201,13 +206,13 @@ public sealed partial class PuddleSystem : SharedPuddleSystem } // Add the remainder back - if (_solutionContainerSystem.ResolveSolution(entity.Owner, entity.Comp.SolutionName, ref entity.Comp.Solution)) + if (_solutionContainerSystem.TryGetSolution(uid, component.SolutionName, out var puddleSolution)) { - _solutionContainerSystem.TryAddSolution(entity.Comp.Solution.Value, overflow); + _solutionContainerSystem.TryAddSolution(uid, puddleSolution, overflow); } } - private void OnPuddleSlip(Entity entity, ref SlipEvent args) + private void OnPuddleSlip(EntityUid uid, PuddleComponent component, ref SlipEvent args) { // Reactive entities have a chance to get a touch reaction from slipping on a puddle // (i.e. it is implied they fell face first onto it or something) @@ -219,14 +224,14 @@ public sealed partial class PuddleSystem : SharedPuddleSystem if (!_random.Prob(0.5f)) return; - if (!_solutionContainerSystem.ResolveSolution(entity.Owner, entity.Comp.SolutionName, ref entity.Comp.Solution, out var solution)) + if (!_solutionContainerSystem.TryGetSolution(uid, component.SolutionName, out var solution)) return; - _popups.PopupEntity(Loc.GetString("puddle-component-slipped-touch-reaction", ("puddle", entity.Owner)), + _popups.PopupEntity(Loc.GetString("puddle-component-slipped-touch-reaction", ("puddle", uid)), args.Slipped, args.Slipped, PopupType.SmallCaution); // Take 15% of the puddle solution - var splitSol = _solutionContainerSystem.SplitSolution(entity.Comp.Solution.Value, solution.Volume * 0.15f); + var splitSol = _solutionContainerSystem.SplitSolution(uid, solution, solution.Volume * 0.15f); _reactive.DoEntityReaction(args.Slipped, splitSol, ReactionMethod.Touch); } @@ -243,27 +248,27 @@ public sealed partial class PuddleSystem : SharedPuddleSystem TickEvaporation(); } - private void OnPuddleInit(Entity entity, ref ComponentInit args) + private void OnPuddleInit(EntityUid uid, PuddleComponent component, ComponentInit args) { - _solutionContainerSystem.EnsureSolution(entity.Owner, entity.Comp.SolutionName, FixedPoint2.New(PuddleVolume), out _); + _solutionContainerSystem.EnsureSolution(uid, component.SolutionName, FixedPoint2.New(PuddleVolume), out _); } - private void OnSolutionUpdate(Entity entity, ref SolutionContainerChangedEvent args) + private void OnSolutionUpdate(EntityUid uid, PuddleComponent component, SolutionChangedEvent args) { - if (args.SolutionId != entity.Comp.SolutionName) + if (args.Solution.Name != component.SolutionName) return; if (args.Solution.Volume <= 0) { - _deletionQueue.Add(entity); + _deletionQueue.Add(uid); return; } - _deletionQueue.Remove(entity); - UpdateSlip(entity, entity.Comp, args.Solution); - UpdateSlow(entity, args.Solution); - UpdateEvaporation(entity, args.Solution); - UpdateAppearance(entity, entity.Comp); + _deletionQueue.Remove(uid); + UpdateSlip(uid, component, args.Solution); + UpdateSlow(uid, args.Solution); + UpdateEvaporation(uid, args.Solution); + UpdateAppearance(uid, component); } private void UpdateAppearance(EntityUid uid, PuddleComponent? puddleComponent = null, AppearanceComponent? appearance = null) @@ -276,7 +281,7 @@ public sealed partial class PuddleSystem : SharedPuddleSystem var volume = FixedPoint2.Zero; Color color = Color.White; - if (_solutionContainerSystem.ResolveSolution(uid, puddleComponent.SolutionName, ref puddleComponent.Solution, out var solution)) + if (_solutionContainerSystem.TryGetSolution(uid, puddleComponent.SolutionName, out var solution)) { volume = solution.Volume / puddleComponent.OverflowVolume; @@ -359,31 +364,39 @@ public sealed partial class PuddleSystem : SharedPuddleSystem } } - private void HandlePuddleExamined(Entity entity, ref ExaminedEvent args) + private void HandlePuddleExamined(EntityUid uid, PuddleComponent component, ExaminedEvent args) { - if (TryComp(entity, out var slippery) && slippery.Active) + if (TryComp(uid, out var slippery) && slippery.Active) { args.PushMarkup(Loc.GetString("puddle-component-examine-is-slipper-text")); } - if (HasComp(entity) && - _solutionContainerSystem.ResolveSolution(entity.Owner, entity.Comp.SolutionName, ref entity.Comp.Solution, out var solution)) + if (HasComp(uid)) { - if (CanFullyEvaporate(solution)) + if (_solutionContainerSystem.TryGetSolution(uid, component.SolutionName, out var solution) && + CanFullyEvaporate(solution)) + { args.PushMarkup(Loc.GetString("puddle-component-examine-evaporating")); - else if (solution.GetTotalPrototypeQuantity(EvaporationReagents) > FixedPoint2.Zero) + } + else if (solution?.GetTotalPrototypeQuantity(EvaporationReagents) > FixedPoint2.Zero) + { args.PushMarkup(Loc.GetString("puddle-component-examine-evaporating-partial")); + } else + { args.PushMarkup(Loc.GetString("puddle-component-examine-evaporating-no")); + } } else + { args.PushMarkup(Loc.GetString("puddle-component-examine-evaporating-no")); + } } - private void OnAnchorChanged(Entity entity, ref AnchorStateChangedEvent args) + private void OnAnchorChanged(EntityUid uid, PuddleComponent puddle, ref AnchorStateChangedEvent args) { if (!args.Anchored) - QueueDel(entity); + QueueDel(uid); } /// @@ -394,7 +407,8 @@ public sealed partial class PuddleSystem : SharedPuddleSystem if (!Resolve(uid, ref puddleComponent)) return FixedPoint2.Zero; - return _solutionContainerSystem.ResolveSolution(uid, puddleComponent.SolutionName, ref puddleComponent.Solution, out var solution) + return _solutionContainerSystem.TryGetSolution(uid, puddleComponent.SolutionName, + out var solution) ? solution.Volume : FixedPoint2.Zero; } @@ -418,12 +432,14 @@ public sealed partial class PuddleSystem : SharedPuddleSystem return false; if (addedSolution.Volume == 0 || - !_solutionContainerSystem.ResolveSolution(puddleUid, puddleComponent.SolutionName, ref puddleComponent.Solution)) + !_solutionContainerSystem.TryGetSolution(puddleUid, puddleComponent.SolutionName, + out var solution)) { return false; } - _solutionContainerSystem.AddSolution(puddleComponent.Solution.Value, addedSolution); + solution.AddSolution(addedSolution, _prototypeManager); + _solutionContainerSystem.UpdateChemicals(puddleUid, solution, true); if (checkForOverflow && IsOverflowing(puddleUid, puddleComponent)) { @@ -466,14 +482,15 @@ public sealed partial class PuddleSystem : SharedPuddleSystem /// public Solution GetOverflowSolution(EntityUid uid, PuddleComponent? puddle = null) { - if (!Resolve(uid, ref puddle) || !_solutionContainerSystem.ResolveSolution(uid, puddle.SolutionName, ref puddle.Solution)) + if (!Resolve(uid, ref puddle) || !_solutionContainerSystem.TryGetSolution(uid, puddle.SolutionName, + out var solution)) { return new Solution(0); } // TODO: This is going to fail with struct solutions. var remaining = puddle.OverflowVolume; - var split = _solutionContainerSystem.SplitSolution(puddle.Solution.Value, CurrentVolume(uid, puddle) - remaining); + var split = _solutionContainerSystem.SplitSolution(uid, solution, CurrentVolume(uid, puddle) - remaining); return split; } diff --git a/Content.Server/Fluids/EntitySystems/SmokeSystem.cs b/Content.Server/Fluids/EntitySystems/SmokeSystem.cs index 795655068f..5459dacf0b 100644 --- a/Content.Server/Fluids/EntitySystems/SmokeSystem.cs +++ b/Content.Server/Fluids/EntitySystems/SmokeSystem.cs @@ -1,7 +1,7 @@ +using System.Linq; using Content.Server.Administration.Logs; using Content.Server.Body.Components; using Content.Server.Body.Systems; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Chemistry.ReactionEffects; using Content.Server.Spreader; using Content.Shared.Chemistry; @@ -21,8 +21,6 @@ using Robust.Shared.Physics.Systems; using Robust.Shared.Prototypes; using Robust.Shared.Random; using Robust.Shared.Timing; -using System.Linq; - using TimedDespawnComponent = Robust.Shared.Spawners.TimedDespawnComponent; namespace Content.Server.Fluids.EntitySystems; @@ -44,7 +42,7 @@ public sealed class SmokeSystem : EntitySystem [Dependency] private readonly ReactiveSystem _reactive = default!; [Dependency] private readonly SharedBroadphaseSystem _broadphase = default!; [Dependency] private readonly SharedPhysicsSystem _physics = default!; - [Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!; + [Dependency] private readonly SolutionContainerSystem _solutionSystem = default!; [Dependency] private readonly TransformSystem _transform = default!; private EntityQuery _smokeQuery; @@ -61,7 +59,6 @@ public sealed class SmokeSystem : EntitySystem SubscribeLocalEvent(OnStartCollide); SubscribeLocalEvent(OnEndCollide); SubscribeLocalEvent(OnReactionAttempt); - SubscribeLocalEvent>(OnReactionAttempt); SubscribeLocalEvent(OnSmokeSpread); SubscribeLocalEvent(OnAffectedUnpaused); } @@ -83,33 +80,33 @@ public sealed class SmokeSystem : EntitySystem } } - private void OnStartCollide(Entity entity, ref StartCollideEvent args) + private void OnStartCollide(EntityUid uid, SmokeComponent component, ref StartCollideEvent args) { if (_smokeAffectedQuery.HasComponent(args.OtherEntity)) return; var smokeAffected = AddComp(args.OtherEntity); - smokeAffected.SmokeEntity = entity; + smokeAffected.SmokeEntity = uid; smokeAffected.NextSecond = _timing.CurTime + TimeSpan.FromSeconds(1); } - private void OnEndCollide(Entity entity, ref EndCollideEvent args) + private void OnEndCollide(EntityUid uid, SmokeComponent component, ref EndCollideEvent args) { // if we are already in smoke, make sure the thing we are exiting is the current smoke we are in. if (_smokeAffectedQuery.TryGetComponent(args.OtherEntity, out var smokeAffectedComponent)) { - if (smokeAffectedComponent.SmokeEntity != entity.Owner) + if (smokeAffectedComponent.SmokeEntity != uid) return; } - var exists = Exists(entity); + var exists = Exists(uid); if (!TryComp(args.OtherEntity, out var body)) return; foreach (var ent in _physics.GetContactingEntities(args.OtherEntity, body)) { - if (exists && ent == entity.Owner) + if (exists && ent == uid) continue; if (!_smokeQuery.HasComponent(ent)) @@ -124,51 +121,51 @@ public sealed class SmokeSystem : EntitySystem RemComp(args.OtherEntity, smokeAffectedComponent); } - private void OnAffectedUnpaused(Entity entity, ref EntityUnpausedEvent args) + private void OnAffectedUnpaused(EntityUid uid, SmokeAffectedComponent component, ref EntityUnpausedEvent args) { - entity.Comp.NextSecond += args.PausedTime; + component.NextSecond += args.PausedTime; } - private void OnSmokeSpread(Entity entity, ref SpreadNeighborsEvent args) + private void OnSmokeSpread(EntityUid uid, SmokeComponent component, ref SpreadNeighborsEvent args) { - if (entity.Comp.SpreadAmount == 0 || !_solutionContainerSystem.ResolveSolution(entity.Owner, SmokeComponent.SolutionName, ref entity.Comp.Solution, out var solution)) + if (component.SpreadAmount == 0 || !_solutionSystem.TryGetSolution(uid, SmokeComponent.SolutionName, out var solution)) { - RemCompDeferred(entity); + RemCompDeferred(uid); return; } - if (Prototype(entity) is not { } prototype) + if (Prototype(uid) is not { } prototype) { - RemCompDeferred(entity); + RemCompDeferred(uid); return; } if (!args.NeighborFreeTiles.Any()) return; - TryComp(entity, out var timer); + TryComp(uid, out var timer); // wtf is the logic behind any of this. - var smokePerSpread = entity.Comp.SpreadAmount / Math.Max(1, args.NeighborFreeTiles.Count); + var smokePerSpread = component.SpreadAmount / Math.Max(1, args.NeighborFreeTiles.Count); foreach (var neighbor in args.NeighborFreeTiles) { var coords = neighbor.Grid.GridTileToLocal(neighbor.Tile); var ent = Spawn(prototype.ID, coords); var spreadAmount = Math.Max(0, smokePerSpread); - entity.Comp.SpreadAmount -= args.NeighborFreeTiles.Count(); + component.SpreadAmount -= args.NeighborFreeTiles.Count(); - StartSmoke(ent, solution.Clone(), timer?.Lifetime ?? entity.Comp.Duration, spreadAmount); + StartSmoke(ent, solution.Clone(), timer?.Lifetime ?? component.Duration, spreadAmount); - if (entity.Comp.SpreadAmount == 0) + if (component.SpreadAmount == 0) { - RemCompDeferred(entity); + RemCompDeferred(uid); break; } } args.Updates--; - if (args.NeighborFreeTiles.Count > 0 || args.Neighbors.Count == 0 || entity.Comp.SpreadAmount < 1) + if (args.NeighborFreeTiles.Count > 0 || args.Neighbors.Count == 0 || component.SpreadAmount < 1) return; // We have no more neighbours to spread to. So instead we will randomly distribute our volume to neighbouring smoke tiles. @@ -182,21 +179,21 @@ public sealed class SmokeSystem : EntitySystem continue; smoke.SpreadAmount++; - entity.Comp.SpreadAmount--; + component.SpreadAmount--; EnsureComp(neighbor); - if (entity.Comp.SpreadAmount == 0) + if (component.SpreadAmount == 0) { - RemCompDeferred(entity); + RemCompDeferred(uid); break; } } } - private void OnReactionAttempt(Entity entity, ref ReactionAttemptEvent args) + private void OnReactionAttempt(EntityUid uid, SmokeComponent component, ReactionAttemptEvent args) { - if (args.Cancelled) + if (args.Solution.Name != SmokeComponent.SolutionName) return; // Prevent smoke/foam fork bombs (smoke creating more smoke). @@ -204,18 +201,12 @@ public sealed class SmokeSystem : EntitySystem { if (effect is AreaReactionEffect) { - args.Cancelled = true; + args.Cancel(); return; } } } - private void OnReactionAttempt(Entity entity, ref SolutionRelayEvent args) - { - if (args.Name == SmokeComponent.SolutionName) - OnReactionAttempt(entity, ref args.Event); - } - /// /// Sets up a smoke component for spreading. /// @@ -254,14 +245,14 @@ public sealed class SmokeSystem : EntitySystem if (!Resolve(smokeUid, ref component)) return; - if (!_solutionContainerSystem.ResolveSolution(smokeUid, SmokeComponent.SolutionName, ref component.Solution, out var solution) || + if (!_solutionSystem.TryGetSolution(smokeUid, SmokeComponent.SolutionName, out var solution) || solution.Contents.Count == 0) { return; } ReactWithEntity(entity, smokeUid, solution, component); - UpdateVisuals((smokeUid, component)); + UpdateVisuals(smokeUid); } private void ReactWithEntity(EntityUid entity, EntityUid smokeUid, Solution solution, SmokeComponent? component = null) @@ -272,14 +263,11 @@ public sealed class SmokeSystem : EntitySystem if (!TryComp(entity, out var bloodstream)) return; - if (!_solutionContainerSystem.ResolveSolution(entity, bloodstream.ChemicalSolutionName, ref bloodstream.ChemicalSolution, out var chemSolution) || chemSolution.AvailableVolume <= 0) - return; - - var blockIngestion = _internals.AreInternalsWorking(entity); + var blockIngestion = _internals.AreInternalsWorking(entity); var cloneSolution = solution.Clone(); var availableTransfer = FixedPoint2.Min(cloneSolution.Volume, component.TransferRate); - var transferAmount = FixedPoint2.Min(availableTransfer, chemSolution.AvailableVolume); + var transferAmount = FixedPoint2.Min(availableTransfer, bloodstream.ChemicalSolution.AvailableVolume); var transferSolution = cloneSolution.SplitSolution(transferAmount); foreach (var reagentQuantity in transferSolution.Contents.ToArray()) @@ -308,7 +296,7 @@ public sealed class SmokeSystem : EntitySystem if (!Resolve(uid, ref component, ref xform)) return; - if (!_solutionContainerSystem.ResolveSolution(uid, SmokeComponent.SolutionName, ref component.Solution, out var solution) || !solution.Any()) + if (!_solutionSystem.TryGetSolution(uid, SmokeComponent.SolutionName, out var solution) || !solution.Any()) return; if (!_mapManager.TryGetGrid(xform.GridUid, out var mapGrid)) @@ -329,30 +317,29 @@ public sealed class SmokeSystem : EntitySystem /// /// Adds the specified solution to the relevant smoke solution. /// - private void TryAddSolution(Entity smoke, Solution solution) + private void TryAddSolution(EntityUid uid, Solution solution) { if (solution.Volume == FixedPoint2.Zero) return; - if (!Resolve(smoke, ref smoke.Comp)) + if (!_solutionSystem.TryGetSolution(uid, SmokeComponent.SolutionName, out var solutionArea)) return; - if (!_solutionContainerSystem.ResolveSolution(smoke.Owner, SmokeComponent.SolutionName, ref smoke.Comp.Solution, out var solutionArea)) - return; + var addSolution = + solution.SplitSolution(FixedPoint2.Min(solution.Volume, solutionArea.AvailableVolume)); - var addSolution = solution.SplitSolution(FixedPoint2.Min(solution.Volume, solutionArea.AvailableVolume)); - _solutionContainerSystem.TryAddSolution(smoke.Comp.Solution.Value, addSolution); + _solutionSystem.TryAddSolution(uid, solutionArea, addSolution); - UpdateVisuals(smoke); + UpdateVisuals(uid); } - private void UpdateVisuals(Entity smoke) + private void UpdateVisuals(EntityUid uid) { - if (!Resolve(smoke, ref smoke.Comp1, ref smoke.Comp2) || - !_solutionContainerSystem.ResolveSolution(smoke.Owner, SmokeComponent.SolutionName, ref smoke.Comp1.Solution, out var solution)) + if (!TryComp(uid, out AppearanceComponent? appearance) || + !_solutionSystem.TryGetSolution(uid, SmokeComponent.SolutionName, out var solution)) return; var color = solution.GetColor(_prototype); - _appearance.SetData(smoke.Owner, SmokeVisuals.Color, color, smoke.Comp2); + _appearance.SetData(uid, SmokeVisuals.Color, color, appearance); } } diff --git a/Content.Server/Fluids/EntitySystems/SpraySystem.cs b/Content.Server/Fluids/EntitySystems/SpraySystem.cs index 5acd2c9118..1b87b3ef24 100644 --- a/Content.Server/Fluids/EntitySystems/SpraySystem.cs +++ b/Content.Server/Fluids/EntitySystems/SpraySystem.cs @@ -1,21 +1,22 @@ +using System.Numerics; using Content.Server.Chemistry.Components; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Chemistry.EntitySystems; using Content.Server.Cooldown; using Content.Server.Extinguisher; using Content.Server.Fluids.Components; using Content.Server.Gravity; using Content.Server.Popups; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Cooldown; using Content.Shared.FixedPoint; using Content.Shared.Interaction; using Content.Shared.Vapor; using Robust.Server.GameObjects; +using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; using Robust.Shared.Physics.Components; using Robust.Shared.Prototypes; using Robust.Shared.Timing; -using System.Numerics; namespace Content.Server.Fluids.EntitySystems; @@ -39,23 +40,23 @@ public sealed class SpraySystem : EntitySystem SubscribeLocalEvent(OnAfterInteract, after: new[] { typeof(FireExtinguisherSystem) }); } - private void OnAfterInteract(Entity entity, ref AfterInteractEvent args) + private void OnAfterInteract(EntityUid uid, SprayComponent component, AfterInteractEvent args) { if (args.Handled) return; args.Handled = true; - if (!_solutionContainer.TryGetSolution(entity.Owner, SprayComponent.SolutionName, out var soln, out var solution)) + if (!_solutionContainer.TryGetSolution(uid, SprayComponent.SolutionName, out var solution)) return; var ev = new SprayAttemptEvent(args.User); - RaiseLocalEvent(entity, ev); + RaiseLocalEvent(uid, ev); if (ev.Cancelled) return; var curTime = _gameTiming.CurTime; - if (TryComp(entity, out var cooldown) + if (TryComp(uid, out var cooldown) && curTime < cooldown.CooldownEnd) { return; @@ -63,7 +64,8 @@ public sealed class SpraySystem : EntitySystem if (solution.Volume <= 0) { - _popupSystem.PopupEntity(Loc.GetString("spray-component-is-empty-message"), entity.Owner, args.User); + _popupSystem.PopupEntity(Loc.GetString("spray-component-is-empty-message"), uid, + args.User); return; } @@ -80,9 +82,9 @@ public sealed class SpraySystem : EntitySystem var diffNorm = diffPos.Normalized(); var diffLength = diffPos.Length(); - if (diffLength > entity.Comp.SprayDistance) + if (diffLength > component.SprayDistance) { - diffLength = entity.Comp.SprayDistance; + diffLength = component.SprayDistance; } var diffAngle = diffNorm.ToAngle(); @@ -91,8 +93,8 @@ public sealed class SpraySystem : EntitySystem var threeQuarters = diffNorm * 0.75f; var quarter = diffNorm * 0.25f; - var amount = Math.Max(Math.Min((solution.Volume / entity.Comp.TransferAmount).Int(), entity.Comp.VaporAmount), 1); - var spread = entity.Comp.VaporSpread / amount; + var amount = Math.Max(Math.Min((solution.Volume / component.TransferAmount).Int(), component.VaporAmount), 1); + var spread = component.VaporSpread / amount; // TODO: Just use usedelay homie. var cooldownTime = 0f; @@ -106,18 +108,18 @@ public sealed class SpraySystem : EntitySystem .Offset((diffNorm + rotation.ToVec()).Normalized() * diffLength + quarter); var distance = (target.Position - userMapPos.Position).Length(); - if (distance > entity.Comp.SprayDistance) - target = userMapPos.Offset(diffNorm * entity.Comp.SprayDistance); + if (distance > component.SprayDistance) + target = userMapPos.Offset(diffNorm * component.SprayDistance); - var adjustedSolutionAmount = entity.Comp.TransferAmount / entity.Comp.VaporAmount; - var newSolution = _solutionContainer.SplitSolution(soln.Value, adjustedSolutionAmount); + var adjustedSolutionAmount = component.TransferAmount / component.VaporAmount; + var newSolution = _solutionContainer.SplitSolution(uid, solution, adjustedSolutionAmount); if (newSolution.Volume <= FixedPoint2.Zero) break; // Spawn the vapor cloud onto the grid/map the user is present on. Offset the start position based on how far the target destination is. var vaporPos = userMapPos.Offset(distance < 1 ? quarter : threeQuarters); - var vapor = Spawn(entity.Comp.SprayedPrototype, vaporPos); + var vapor = Spawn(component.SprayedPrototype, vaporPos); var vaporXform = xformQuery.GetComponent(vapor); _transform.SetWorldRotation(vaporXform, rotation); @@ -135,21 +137,22 @@ public sealed class SpraySystem : EntitySystem // impulse direction is defined in world-coordinates, not local coordinates var impulseDirection = rotation.ToVec(); - var time = diffLength / entity.Comp.SprayVelocity; + var time = diffLength / component.SprayVelocity; cooldownTime = MathF.Max(time, cooldownTime); - _vapor.Start(ent, vaporXform, impulseDirection * diffLength, entity.Comp.SprayVelocity, target, time, args.User); + _vapor.Start(ent, vaporXform, impulseDirection * diffLength, component.SprayVelocity, target, time, args.User); if (TryComp(args.User, out var body)) { if (_gravity.IsWeightless(args.User, body)) - _physics.ApplyLinearImpulse(args.User, -impulseDirection.Normalized() * entity.Comp.PushbackAmount, body: body); + _physics.ApplyLinearImpulse(args.User, -impulseDirection.Normalized() * component.PushbackAmount, body: body); } } - _audio.PlayPvs(entity.Comp.SpraySound, entity, entity.Comp.SpraySound.Params.WithVariation(0.125f)); + _audio.PlayPvs(component.SpraySound, uid, component.SpraySound.Params.WithVariation(0.125f)); - RaiseLocalEvent(entity, new RefreshItemCooldownEvent(curTime, curTime + TimeSpan.FromSeconds(cooldownTime)), true); + RaiseLocalEvent(uid, + new RefreshItemCooldownEvent(curTime, curTime + TimeSpan.FromSeconds(cooldownTime)), true); } } diff --git a/Content.Server/Glue/GlueSystem.cs b/Content.Server/Glue/GlueSystem.cs index 2b7f0060bc..58eed00c49 100644 --- a/Content.Server/Glue/GlueSystem.cs +++ b/Content.Server/Glue/GlueSystem.cs @@ -1,15 +1,16 @@ using Content.Server.Administration.Logs; -using Content.Server.Chemistry.Containers.EntitySystems; -using Content.Server.Nutrition.EntitySystems; -using Content.Shared.Database; -using Content.Shared.Glue; -using Content.Shared.Hands; -using Content.Shared.Interaction; -using Content.Shared.Interaction.Components; -using Content.Shared.Item; using Content.Shared.Popups; -using Robust.Shared.Audio.Systems; +using Content.Shared.Item; +using Content.Shared.Glue; +using Content.Shared.Interaction; +using Content.Server.Nutrition.EntitySystems; +using Content.Shared.Chemistry.EntitySystems; +using Content.Shared.Database; +using Content.Shared.Hands; using Robust.Shared.Timing; +using Content.Shared.Interaction.Components; +using Robust.Shared.Audio; +using Robust.Shared.Audio.Systems; namespace Content.Server.Glue; @@ -32,7 +33,7 @@ public sealed class GlueSystem : SharedGlueSystem } // When glue bottle is used on item it will apply the glued and unremoveable components. - private void OnInteract(Entity entity, ref AfterInteractEvent args) + private void OnInteract(EntityUid uid, GlueComponent component, AfterInteractEvent args) { if (args.Handled) return; @@ -40,10 +41,10 @@ public sealed class GlueSystem : SharedGlueSystem if (!args.CanReach || args.Target is not { Valid: true } target) return; - if (TryGlue(entity, target, args.User)) + if (TryGlue(uid, component, target, args.User)) { args.Handled = true; - _audio.PlayPvs(entity.Comp.Squeeze, entity); + _audio.PlayPvs(component.Squeeze, uid); _popup.PopupEntity(Loc.GetString("glue-success", ("target", target)), args.User, args.User, PopupType.Medium); } else @@ -52,7 +53,7 @@ public sealed class GlueSystem : SharedGlueSystem } } - private bool TryGlue(Entity glue, EntityUid target, EntityUid actor) + private bool TryGlue(EntityUid uid, GlueComponent component, EntityUid target, EntityUid actor) { // if item is glued then don't apply glue again so it can be removed for reasonable time if (HasComp(target) || !HasComp(target)) @@ -60,13 +61,13 @@ public sealed class GlueSystem : SharedGlueSystem return false; } - if (HasComp(target) && _solutionContainer.TryGetSolution(glue.Owner, glue.Comp.Solution, out _, out var solution)) + if (HasComp(target) && _solutionContainer.TryGetSolution(uid, component.Solution, out var solution)) { - var quantity = solution.RemoveReagent(glue.Comp.Reagent, glue.Comp.ConsumptionUnit); + var quantity = solution.RemoveReagent(component.Reagent, component.ConsumptionUnit); if (quantity > 0) { - EnsureComp(target).Duration = quantity.Double() * glue.Comp.DurationPerUnit; - _adminLogger.Add(LogType.Action, LogImpact.Medium, $"{ToPrettyString(actor):actor} glued {ToPrettyString(target):subject} with {ToPrettyString(glue.Owner):tool}"); + EnsureComp(target).Duration = quantity.Double() * component.DurationPerUnit; + _adminLogger.Add(LogType.Action, LogImpact.Medium, $"{ToPrettyString(actor):actor} glued {ToPrettyString(target):subject} with {ToPrettyString(uid):tool}"); return true; } } @@ -89,17 +90,17 @@ public sealed class GlueSystem : SharedGlueSystem } } - private void OnGluedInit(Entity entity, ref ComponentInit args) + private void OnGluedInit(EntityUid uid, GluedComponent component, ComponentInit args) { - var meta = MetaData(entity); + var meta = MetaData(uid); var name = meta.EntityName; - entity.Comp.BeforeGluedEntityName = meta.EntityName; - _metaData.SetEntityName(entity.Owner, Loc.GetString("glued-name-prefix", ("target", name))); + component.BeforeGluedEntityName = meta.EntityName; + _metaData.SetEntityName(uid, Loc.GetString("glued-name-prefix", ("target", name))); } - private void OnHandPickUp(Entity entity, ref GotEquippedHandEvent args) + private void OnHandPickUp(EntityUid uid, GluedComponent component, GotEquippedHandEvent args) { - EnsureComp(entity); - entity.Comp.Until = _timing.CurTime + entity.Comp.Duration; + EnsureComp(uid); + component.Until = _timing.CurTime + component.Duration; } } diff --git a/Content.Server/Kitchen/EntitySystems/MicrowaveSystem.cs b/Content.Server/Kitchen/EntitySystems/MicrowaveSystem.cs index c7e1824c40..e4159f89ef 100644 --- a/Content.Server/Kitchen/EntitySystems/MicrowaveSystem.cs +++ b/Content.Server/Kitchen/EntitySystems/MicrowaveSystem.cs @@ -1,8 +1,9 @@ +using System.Linq; using Content.Server.Body.Systems; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Construction; using Content.Server.DeviceLinking.Events; using Content.Server.DeviceLinking.Systems; +using Content.Server.DeviceNetwork; using Content.Server.Hands.Systems; using Content.Server.Kitchen.Components; using Content.Server.Power.Components; @@ -30,7 +31,6 @@ using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; using Robust.Shared.Containers; using Robust.Shared.Player; -using System.Linq; namespace Content.Server.Kitchen.EntitySystems { @@ -57,7 +57,7 @@ namespace Content.Server.Kitchen.EntitySystems SubscribeLocalEvent(OnInit); SubscribeLocalEvent(OnMapInit); - SubscribeLocalEvent(OnSolutionChange); + SubscribeLocalEvent(OnSolutionChange); SubscribeLocalEvent(OnInteractUsing, after: new[] { typeof(AnchorableSystem) }); SubscribeLocalEvent(OnBreak); SubscribeLocalEvent(OnPowerChanged); @@ -76,21 +76,21 @@ namespace Content.Server.Kitchen.EntitySystems SubscribeLocalEvent(OnCookStop); } - private void OnCookStart(Entity ent, ref ComponentStartup args) + private void OnCookStart(EntityUid uid, ActiveMicrowaveComponent component, ComponentStartup args) { - if (!TryComp(ent, out var microwaveComponent)) + if (!TryComp(uid, out var microwaveComponent)) return; - SetAppearance(ent.Owner, MicrowaveVisualState.Cooking, microwaveComponent); + SetAppearance(uid, MicrowaveVisualState.Cooking, microwaveComponent); microwaveComponent.PlayingStream = - _audio.PlayPvs(microwaveComponent.LoopingSound, ent, AudioParams.Default.WithLoop(true).WithMaxDistance(5)).Value.Entity; + _audio.PlayPvs(microwaveComponent.LoopingSound, uid, AudioParams.Default.WithLoop(true).WithMaxDistance(5)).Value.Entity; } - private void OnCookStop(Entity ent, ref ComponentShutdown args) + private void OnCookStop(EntityUid uid, ActiveMicrowaveComponent component, ComponentShutdown args) { - if (!TryComp(ent, out var microwaveComponent)) + if (!TryComp(uid, out var microwaveComponent)) return; - SetAppearance(ent.Owner, MicrowaveVisualState.Idle, microwaveComponent); + SetAppearance(uid, MicrowaveVisualState.Idle, microwaveComponent); microwaveComponent.PlayingStream = _audio.Stop(microwaveComponent.PlayingStream); } @@ -111,13 +111,12 @@ namespace Content.Server.Kitchen.EntitySystems if (!TryComp(entity, out var solutions)) continue; - foreach (var (_, soln) in _solutionContainer.EnumerateSolutions((entity, solutions))) + foreach (var (_, solution) in solutions.Solutions) { - var solution = soln.Comp.Solution; if (solution.Temperature > component.TemperatureUpperThreshold) continue; - _solutionContainer.AddThermalEnergy(soln, heatToAdd); + _solutionContainer.AddThermalEnergy(entity, solution, heatToAdd); } } } @@ -135,9 +134,8 @@ namespace Content.Server.Kitchen.EntitySystems continue; // go over every solution - foreach (var (_, soln) in _solutionContainer.EnumerateSolutions((item, solMan))) + foreach (var (_, solution) in solMan.Solutions) { - var solution = soln.Comp.Solution; foreach (var (reagent, _) in recipe.IngredientsReagents) { // removed everything @@ -156,7 +154,7 @@ namespace Content.Server.Kitchen.EntitySystems totalReagentsToRemove[reagent] -= quant; } - _solutionContainer.RemoveReagent(soln, reagent, quant); + _solutionContainer.RemoveReagent(item, solution, reagent, quant); } } } @@ -195,7 +193,7 @@ namespace Content.Server.Kitchen.EntitySystems _deviceLink.EnsureSinkPorts(ent, ent.Comp.OnPort); } - private void OnSuicide(Entity ent, ref SuicideEvent args) + private void OnSuicide(EntityUid uid, MicrowaveComponent component, SuicideEvent args) { if (args.Handled) return; @@ -210,7 +208,7 @@ namespace Content.Server.Kitchen.EntitySystems foreach (var part in headSlots) { - _container.Insert(part.Id, ent.Comp.Storage); + _container.Insert(part.Id, component.Storage); headCount++; } } @@ -226,73 +224,73 @@ namespace Content.Server.Kitchen.EntitySystems _popupSystem.PopupEntity(othersMessage, victim, Filter.PvsExcept(victim), true); _popupSystem.PopupEntity(selfMessage, victim, victim); - _audio.PlayPvs(ent.Comp.ClickSound, ent.Owner, AudioParams.Default.WithVolume(-2)); - ent.Comp.CurrentCookTimerTime = 10; - Wzhzhzh(ent.Owner, ent.Comp, args.Victim); - UpdateUserInterfaceState(ent.Owner, ent.Comp); + _audio.PlayPvs(component.ClickSound, uid, AudioParams.Default.WithVolume(-2)); + component.CurrentCookTimerTime = 10; + Wzhzhzh(uid, component, args.Victim); + UpdateUserInterfaceState(uid, component); } - private void OnSolutionChange(Entity ent, ref SolutionContainerChangedEvent args) + private void OnSolutionChange(EntityUid uid, MicrowaveComponent component, SolutionChangedEvent args) { - UpdateUserInterfaceState(ent, ent.Comp); + UpdateUserInterfaceState(uid, component); } - private void OnInteractUsing(Entity ent, ref InteractUsingEvent args) + private void OnInteractUsing(EntityUid uid, MicrowaveComponent component, InteractUsingEvent args) { if (args.Handled) return; - if (!(TryComp(ent, out var apc) && apc.Powered)) + if (!(TryComp(uid, out var apc) && apc.Powered)) { - _popupSystem.PopupEntity(Loc.GetString("microwave-component-interact-using-no-power"), ent, args.User); + _popupSystem.PopupEntity(Loc.GetString("microwave-component-interact-using-no-power"), uid, args.User); return; } - if (ent.Comp.Broken) + if (component.Broken) { - _popupSystem.PopupEntity(Loc.GetString("microwave-component-interact-using-broken"), ent, args.User); + _popupSystem.PopupEntity(Loc.GetString("microwave-component-interact-using-broken"), uid, args.User); return; } if (!HasComp(args.Used)) { - _popupSystem.PopupEntity(Loc.GetString("microwave-component-interact-using-transfer-fail"), ent, args.User); + _popupSystem.PopupEntity(Loc.GetString("microwave-component-interact-using-transfer-fail"), uid, args.User); return; } args.Handled = true; - _handsSystem.TryDropIntoContainer(args.User, args.Used, ent.Comp.Storage); - UpdateUserInterfaceState(ent, ent.Comp); + _handsSystem.TryDropIntoContainer(args.User, args.Used, component.Storage); + UpdateUserInterfaceState(uid, component); } - private void OnBreak(Entity ent, ref BreakageEventArgs args) + private void OnBreak(EntityUid uid, MicrowaveComponent component, BreakageEventArgs args) { - ent.Comp.Broken = true; - SetAppearance(ent, MicrowaveVisualState.Broken, ent.Comp); - RemComp(ent); - _sharedContainer.EmptyContainer(ent.Comp.Storage); - UpdateUserInterfaceState(ent, ent.Comp); + component.Broken = true; + SetAppearance(uid, MicrowaveVisualState.Broken, component); + RemComp(uid); + _sharedContainer.EmptyContainer(component.Storage); + UpdateUserInterfaceState(uid, component); } - private void OnPowerChanged(Entity ent, ref PowerChangedEvent args) + private void OnPowerChanged(EntityUid uid, MicrowaveComponent component, ref PowerChangedEvent args) { if (!args.Powered) { - SetAppearance(ent, MicrowaveVisualState.Idle, ent.Comp); - RemComp(ent); - _sharedContainer.EmptyContainer(ent.Comp.Storage); + SetAppearance(uid, MicrowaveVisualState.Idle, component); + RemComp(uid); + _sharedContainer.EmptyContainer(component.Storage); } - UpdateUserInterfaceState(ent, ent.Comp); + UpdateUserInterfaceState(uid, component); } - private void OnRefreshParts(Entity ent, ref RefreshPartsEvent args) + private void OnRefreshParts(EntityUid uid, MicrowaveComponent component, RefreshPartsEvent args) { - var cookRating = args.PartRatings[ent.Comp.MachinePartCookTimeMultiplier]; - ent.Comp.CookTimeMultiplier = MathF.Pow(ent.Comp.CookTimeScalingConstant, cookRating - 1); + var cookRating = args.PartRatings[component.MachinePartCookTimeMultiplier]; + component.CookTimeMultiplier = MathF.Pow(component.CookTimeScalingConstant, cookRating - 1); } - private void OnUpgradeExamine(Entity ent, ref UpgradeExamineEvent args) + private void OnUpgradeExamine(EntityUid uid, MicrowaveComponent component, UpgradeExamineEvent args) { - args.AddPercentageUpgrade("microwave-component-upgrade-cook-time", ent.Comp.CookTimeMultiplier); + args.AddPercentageUpgrade("microwave-component-upgrade-cook-time", component.CookTimeMultiplier); } private void OnSignalReceived(Entity ent, ref SignalReceivedEvent args) @@ -393,9 +391,8 @@ namespace Content.Server.Kitchen.EntitySystems if (!TryComp(item, out var solMan)) continue; - foreach (var (_, soln) in _solutionContainer.EnumerateSolutions((item, solMan))) + foreach (var (_, solution) in solMan.Solutions) { - var solution = soln.Comp.Solution; foreach (var (reagent, quantity) in solution.Contents) { if (reagentDict.ContainsKey(reagent.Prototype)) @@ -492,38 +489,38 @@ namespace Content.Server.Kitchen.EntitySystems } #region ui - private void OnEjectMessage(Entity ent, ref MicrowaveEjectMessage args) + private void OnEjectMessage(EntityUid uid, MicrowaveComponent component, MicrowaveEjectMessage args) { - if (!HasContents(ent.Comp) || HasComp(ent)) + if (!HasContents(component) || HasComp(uid)) return; - _sharedContainer.EmptyContainer(ent.Comp.Storage); - _audio.PlayPvs(ent.Comp.ClickSound, ent, AudioParams.Default.WithVolume(-2)); - UpdateUserInterfaceState(ent, ent.Comp); + _sharedContainer.EmptyContainer(component.Storage); + _audio.PlayPvs(component.ClickSound, uid, AudioParams.Default.WithVolume(-2)); + UpdateUserInterfaceState(uid, component); } - private void OnEjectIndex(Entity ent, ref MicrowaveEjectSolidIndexedMessage args) + private void OnEjectIndex(EntityUid uid, MicrowaveComponent component, MicrowaveEjectSolidIndexedMessage args) { - if (!HasContents(ent.Comp) || HasComp(ent)) + if (!HasContents(component) || HasComp(uid)) return; - _sharedContainer.Remove(EntityManager.GetEntity(args.EntityID), ent.Comp.Storage); - UpdateUserInterfaceState(ent, ent.Comp); + _sharedContainer.Remove(EntityManager.GetEntity(args.EntityID), component.Storage); + UpdateUserInterfaceState(uid, component); } - private void OnSelectTime(Entity ent, ref MicrowaveSelectCookTimeMessage args) + private void OnSelectTime(EntityUid uid, MicrowaveComponent comp, MicrowaveSelectCookTimeMessage args) { - if (!HasContents(ent.Comp) || HasComp(ent) || !(TryComp(ent, out var apc) && apc.Powered)) + if (!HasContents(comp) || HasComp(uid) || !(TryComp(uid, out var apc) && apc.Powered)) return; // some validation to prevent trollage - if (args.NewCookTime % 5 != 0 || args.NewCookTime > ent.Comp.MaxCookTime) + if (args.NewCookTime % 5 != 0 || args.NewCookTime > comp.MaxCookTime) return; - ent.Comp.CurrentCookTimeButtonIndex = args.ButtonIndex; - ent.Comp.CurrentCookTimerTime = args.NewCookTime; - _audio.PlayPvs(ent.Comp.ClickSound, ent, AudioParams.Default.WithVolume(-2)); - UpdateUserInterfaceState(ent, ent.Comp); + comp.CurrentCookTimeButtonIndex = args.ButtonIndex; + comp.CurrentCookTimerTime = args.NewCookTime; + _audio.PlayPvs(comp.ClickSound, uid, AudioParams.Default.WithVolume(-2)); + UpdateUserInterfaceState(uid, comp); } #endregion } diff --git a/Content.Server/Kitchen/EntitySystems/ReagentGrinderSystem.cs b/Content.Server/Kitchen/EntitySystems/ReagentGrinderSystem.cs index cd9a82a072..ba6795ad9f 100644 --- a/Content.Server/Kitchen/EntitySystems/ReagentGrinderSystem.cs +++ b/Content.Server/Kitchen/EntitySystems/ReagentGrinderSystem.cs @@ -1,10 +1,11 @@ -using Content.Server.Chemistry.Containers.EntitySystems; +using System.Linq; using Content.Server.Construction; using Content.Server.Kitchen.Components; using Content.Server.Power.Components; using Content.Server.Power.EntitySystems; using Content.Server.Stack; using Content.Shared.Chemistry.Components; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Containers.ItemSlots; using Content.Shared.FixedPoint; using Content.Shared.Interaction; @@ -18,7 +19,6 @@ using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; using Robust.Shared.Containers; using Robust.Shared.Timing; -using System.Linq; namespace Content.Server.Kitchen.EntitySystems { @@ -26,7 +26,7 @@ namespace Content.Server.Kitchen.EntitySystems internal sealed class ReagentGrinderSystem : EntitySystem { [Dependency] private readonly IGameTiming _timing = default!; - [Dependency] private readonly SolutionContainerSystem _solutionContainersSystem = default!; + [Dependency] private readonly SolutionContainerSystem _solutionsSystem = default!; [Dependency] private readonly ItemSlotsSystem _itemSlotsSystem = default!; [Dependency] private readonly SharedPopupSystem _popupSystem = default!; [Dependency] private readonly UserInterfaceSystem _userInterfaceSystem = default!; @@ -70,7 +70,7 @@ namespace Content.Server.Kitchen.EntitySystems var inputContainer = _containerSystem.EnsureContainer(uid, SharedReagentGrinder.InputContainerId); var outputContainer = _itemSlotsSystem.GetItemOrNull(uid, SharedReagentGrinder.BeakerSlotId); - if (outputContainer is null || !_solutionContainersSystem.TryGetFitsInDispenser(outputContainer.Value, out var containerSoln, out var containerSolution)) + if (outputContainer is null || !_solutionsSystem.TryGetFitsInDispenser(outputContainer.Value, out var containerSolution)) continue; foreach (var item in inputContainer.ContainedEntities.ToList()) @@ -108,7 +108,7 @@ namespace Content.Server.Kitchen.EntitySystems QueueDel(item); } - _solutionContainersSystem.TryAddSolution(containerSoln.Value, solution); + _solutionsSystem.TryAddSolution(outputContainer.Value, containerSolution, solution); } _userInterfaceSystem.TrySendUiMessage(uid, ReagentGrinderUiKey.Key, @@ -118,9 +118,9 @@ namespace Content.Server.Kitchen.EntitySystems } } - private void OnEntRemoveAttempt(Entity entity, ref ContainerIsRemovingAttemptEvent args) + private void OnEntRemoveAttempt(EntityUid uid, ReagentGrinderComponent reagentGrinder, ContainerIsRemovingAttemptEvent args) { - if (HasComp(entity)) + if (HasComp(uid)) args.Cancel(); } @@ -132,17 +132,17 @@ namespace Content.Server.Kitchen.EntitySystems _appearanceSystem.SetData(uid, ReagentGrinderVisualState.BeakerAttached, outputContainer.HasValue); } - private void OnInteractUsing(Entity entity, ref InteractUsingEvent args) + private void OnInteractUsing(EntityUid uid, ReagentGrinderComponent reagentGrinder, InteractUsingEvent args) { var heldEnt = args.Used; - var inputContainer = _containerSystem.EnsureContainer(entity.Owner, SharedReagentGrinder.InputContainerId); + var inputContainer = _containerSystem.EnsureContainer(uid, SharedReagentGrinder.InputContainerId); if (!HasComp(heldEnt)) { if (!HasComp(heldEnt)) { // This is ugly but we can't use whitelistFailPopup because there are 2 containers with different whitelists. - _popupSystem.PopupEntity(Loc.GetString("reagent-grinder-component-cannot-put-entity-message"), entity.Owner, args.User); + _popupSystem.PopupEntity(Loc.GetString("reagent-grinder-component-cannot-put-entity-message"), uid, args.User); } // Entity did NOT pass the whitelist for grind/juice. @@ -156,7 +156,7 @@ namespace Content.Server.Kitchen.EntitySystems // Cap the chamber. Don't want someone putting in 500 entities and ejecting them all at once. // Maybe I should have done that for the microwave too? - if (inputContainer.ContainedEntities.Count >= entity.Comp.StorageMaxEntities) + if (inputContainer.ContainedEntities.Count >= reagentGrinder.StorageMaxEntities) return; if (!_containerSystem.Insert(heldEnt, inputContainer)) @@ -168,19 +168,19 @@ namespace Content.Server.Kitchen.EntitySystems /// /// Gotta be efficient, you know? you're saving a whole extra second here and everything. /// - private void OnRefreshParts(Entity entity, ref RefreshPartsEvent args) + private void OnRefreshParts(EntityUid uid, ReagentGrinderComponent component, RefreshPartsEvent args) { - var ratingWorkTime = args.PartRatings[entity.Comp.MachinePartWorkTime]; - var ratingStorage = args.PartRatings[entity.Comp.MachinePartStorageMax]; + var ratingWorkTime = args.PartRatings[component.MachinePartWorkTime]; + var ratingStorage = args.PartRatings[component.MachinePartStorageMax]; - entity.Comp.WorkTimeMultiplier = MathF.Pow(entity.Comp.PartRatingWorkTimerMulitplier, ratingWorkTime - 1); - entity.Comp.StorageMaxEntities = entity.Comp.BaseStorageMaxEntities + (int) (entity.Comp.StoragePerPartRating * (ratingStorage - 1)); + component.WorkTimeMultiplier = MathF.Pow(component.PartRatingWorkTimerMulitplier, ratingWorkTime - 1); + component.StorageMaxEntities = component.BaseStorageMaxEntities + (int) (component.StoragePerPartRating * (ratingStorage - 1)); } - private void OnUpgradeExamine(Entity entity, ref UpgradeExamineEvent args) + private void OnUpgradeExamine(EntityUid uid, ReagentGrinderComponent component, UpgradeExamineEvent args) { - args.AddPercentageUpgrade("reagent-grinder-component-upgrade-work-time", entity.Comp.WorkTimeMultiplier); - args.AddNumberUpgrade("reagent-grinder-component-upgrade-storage", entity.Comp.StorageMaxEntities - entity.Comp.BaseStorageMaxEntities); + args.AddPercentageUpgrade("reagent-grinder-component-upgrade-work-time", component.WorkTimeMultiplier); + args.AddNumberUpgrade("reagent-grinder-component-upgrade-storage", component.StorageMaxEntities - component.BaseStorageMaxEntities); } private void UpdateUiState(EntityUid uid) @@ -193,7 +193,7 @@ namespace Content.Server.Kitchen.EntitySystems var canGrind = false; if (outputContainer is not null - && _solutionContainersSystem.TryGetFitsInDispenser(outputContainer.Value, out _, out containerSolution) + && _solutionsSystem.TryGetFitsInDispenser(outputContainer.Value, out containerSolution) && inputContainer.ContainedEntities.Count > 0) { canGrind = inputContainer.ContainedEntities.All(CanGrind); @@ -212,43 +212,43 @@ namespace Content.Server.Kitchen.EntitySystems _userInterfaceSystem.TrySetUiState(uid, ReagentGrinderUiKey.Key, state); } - private void OnStartMessage(Entity entity, ref ReagentGrinderStartMessage message) + private void OnStartMessage(EntityUid uid, ReagentGrinderComponent reagentGrinder, ReagentGrinderStartMessage message) { - if (!this.IsPowered(entity.Owner, EntityManager) || HasComp(entity)) + if (!this.IsPowered(uid, EntityManager) || HasComp(uid)) return; - DoWork(entity.Owner, entity.Comp, message.Program); + DoWork(uid, reagentGrinder, message.Program); } - private void OnEjectChamberAllMessage(Entity entity, ref ReagentGrinderEjectChamberAllMessage message) + private void OnEjectChamberAllMessage(EntityUid uid, ReagentGrinderComponent reagentGrinder, ReagentGrinderEjectChamberAllMessage message) { - var inputContainer = _containerSystem.EnsureContainer(entity.Owner, SharedReagentGrinder.InputContainerId); + var inputContainer = _containerSystem.EnsureContainer(uid, SharedReagentGrinder.InputContainerId); - if (HasComp(entity) || inputContainer.ContainedEntities.Count <= 0) + if (HasComp(uid) || inputContainer.ContainedEntities.Count <= 0) return; - ClickSound(entity); - foreach (var toEject in inputContainer.ContainedEntities.ToList()) + ClickSound(uid, reagentGrinder); + foreach (var entity in inputContainer.ContainedEntities.ToList()) { - _containerSystem.Remove(toEject, inputContainer); - _randomHelper.RandomOffset(toEject, 0.4f); + _containerSystem.Remove(entity, inputContainer); + _randomHelper.RandomOffset(entity, 0.4f); } - UpdateUiState(entity); + UpdateUiState(uid); } - private void OnEjectChamberContentMessage(Entity entity, ref ReagentGrinderEjectChamberContentMessage message) + private void OnEjectChamberContentMessage(EntityUid uid, ReagentGrinderComponent reagentGrinder, ReagentGrinderEjectChamberContentMessage message) { - if (HasComp(entity)) + if (HasComp(uid)) return; - var inputContainer = _containerSystem.EnsureContainer(entity.Owner, SharedReagentGrinder.InputContainerId); + var inputContainer = _containerSystem.EnsureContainer(uid, SharedReagentGrinder.InputContainerId); var ent = GetEntity(message.EntityId); if (_containerSystem.Remove(ent, inputContainer)) { _randomHelper.RandomOffset(ent, 0.4f); - ClickSound(entity); - UpdateUiState(entity); + ClickSound(uid, reagentGrinder); + UpdateUiState(uid); } } @@ -290,16 +290,16 @@ namespace Content.Server.Kitchen.EntitySystems new ReagentGrinderWorkStartedMessage(program)); } - private void ClickSound(Entity reagentGrinder) + private void ClickSound(EntityUid uid, ReagentGrinderComponent reagentGrinder) { - _audioSystem.PlayPvs(reagentGrinder.Comp.ClickSound, reagentGrinder.Owner, AudioParams.Default.WithVolume(-2f)); + _audioSystem.PlayPvs(reagentGrinder.ClickSound, uid, AudioParams.Default.WithVolume(-2f)); } private Solution? GetGrindSolution(EntityUid uid) { if (TryComp(uid, out var extractable) && extractable.GrindableSolution is not null - && _solutionContainersSystem.TryGetSolution(uid, extractable.GrindableSolution, out _, out var solution)) + && _solutionsSystem.TryGetSolution(uid, extractable.GrindableSolution, out var solution)) { return solution; } @@ -311,7 +311,7 @@ namespace Content.Server.Kitchen.EntitySystems { var solutionName = CompOrNull(uid)?.GrindableSolution; - return solutionName is not null && _solutionContainersSystem.TryGetSolution(uid, solutionName, out _, out _); + return solutionName is not null && _solutionsSystem.TryGetSolution(uid, solutionName, out _); } private bool CanJuice(EntityUid uid) diff --git a/Content.Server/Lube/LubeSystem.cs b/Content.Server/Lube/LubeSystem.cs index d777ae9406..86921d222c 100644 --- a/Content.Server/Lube/LubeSystem.cs +++ b/Content.Server/Lube/LubeSystem.cs @@ -1,6 +1,6 @@ using Content.Server.Administration.Logs; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Nutrition.EntitySystems; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Database; using Content.Shared.IdentityManagement; using Content.Shared.Interaction; @@ -28,7 +28,7 @@ public sealed class LubeSystem : EntitySystem SubscribeLocalEvent(OnInteract, after: new[] { typeof(OpenableSystem) }); } - private void OnInteract(Entity entity, ref AfterInteractEvent args) + private void OnInteract(EntityUid uid, LubeComponent component, AfterInteractEvent args) { if (args.Handled) return; @@ -36,10 +36,10 @@ public sealed class LubeSystem : EntitySystem if (!args.CanReach || args.Target is not { Valid: true } target) return; - if (TryLube(entity, target, args.User)) + if (TryLube(uid, component, target, args.User)) { args.Handled = true; - _audio.PlayPvs(entity.Comp.Squeeze, entity); + _audio.PlayPvs(component.Squeeze, uid); _popup.PopupEntity(Loc.GetString("lube-success", ("target", Identity.Entity(target, EntityManager))), args.User, args.User, PopupType.Medium); } else @@ -48,22 +48,22 @@ public sealed class LubeSystem : EntitySystem } } - private bool TryLube(Entity lube, EntityUid target, EntityUid actor) + private bool TryLube(EntityUid uid, LubeComponent component, EntityUid target, EntityUid actor) { if (HasComp(target) || !HasComp(target)) { return false; } - if (HasComp(target) && _solutionContainer.TryGetSolution(lube.Owner, lube.Comp.Solution, out _, out var solution)) + if (HasComp(target) && _solutionContainer.TryGetSolution(uid, component.Solution, out var solution)) { - var quantity = solution.RemoveReagent(lube.Comp.Reagent, lube.Comp.Consumption); + var quantity = solution.RemoveReagent(component.Reagent, component.Consumption); if (quantity > 0) { var lubed = EnsureComp(target); - lubed.SlipsLeft = _random.Next(lube.Comp.MinSlips * quantity.Int(), lube.Comp.MaxSlips * quantity.Int()); - lubed.SlipStrength = lube.Comp.SlipStrength; - _adminLogger.Add(LogType.Action, LogImpact.Medium, $"{ToPrettyString(actor):actor} lubed {ToPrettyString(target):subject} with {ToPrettyString(lube.Owner):tool}"); + lubed.SlipsLeft = _random.Next(component.MinSlips * quantity.Int(), component.MaxSlips * quantity.Int()); + lubed.SlipStrength = component.SlipStrength; + _adminLogger.Add(LogType.Action, LogImpact.Medium, $"{ToPrettyString(actor):actor} lubed {ToPrettyString(target):subject} with {ToPrettyString(uid):tool}"); return true; } } diff --git a/Content.Server/Materials/MaterialReclaimerSystem.cs b/Content.Server/Materials/MaterialReclaimerSystem.cs index ff05a72ef0..d6a94ec6d2 100644 --- a/Content.Server/Materials/MaterialReclaimerSystem.cs +++ b/Content.Server/Materials/MaterialReclaimerSystem.cs @@ -1,4 +1,4 @@ -using Content.Server.Chemistry.Containers.EntitySystems; +using System.Linq; using Content.Server.Chemistry.EntitySystems; using Content.Server.Construction; using Content.Server.Fluids.EntitySystems; @@ -11,6 +11,7 @@ using Content.Server.Wires; using Content.Shared.Body.Systems; using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Components.SolutionManager; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.IdentityManagement; using Content.Shared.Interaction; using Content.Shared.Interaction.Events; @@ -19,7 +20,6 @@ using Content.Shared.Mind; using Robust.Server.GameObjects; using Robust.Shared.Player; using Robust.Shared.Utility; -using System.Linq; namespace Content.Server.Materials; @@ -51,40 +51,40 @@ public sealed class MaterialReclaimerSystem : SharedMaterialReclaimerSystem SubscribeLocalEvent(OnSuicide); SubscribeLocalEvent(OnActivePowerChanged); } - private void OnStartup(Entity entity, ref ComponentStartup args) + private void OnStartup(EntityUid uid, MaterialReclaimerComponent component, ComponentStartup args) { - _solutionContainer.EnsureSolution(entity.Owner, entity.Comp.SolutionContainerId); + component.OutputSolution = _solutionContainer.EnsureSolution(uid, component.SolutionContainerId); } - private void OnUpgradeExamine(Entity entity, ref UpgradeExamineEvent args) + private void OnUpgradeExamine(EntityUid uid, MaterialReclaimerComponent component, UpgradeExamineEvent args) { - args.AddPercentageUpgrade(Loc.GetString("material-reclaimer-upgrade-process-rate"), entity.Comp.MaterialProcessRate / entity.Comp.BaseMaterialProcessRate); + args.AddPercentageUpgrade(Loc.GetString("material-reclaimer-upgrade-process-rate"), component.MaterialProcessRate / component.BaseMaterialProcessRate); } - private void OnRefreshParts(Entity entity, ref RefreshPartsEvent args) + private void OnRefreshParts(EntityUid uid, MaterialReclaimerComponent component, RefreshPartsEvent args) { - var rating = args.PartRatings[entity.Comp.MachinePartProcessRate] - 1; - entity.Comp.MaterialProcessRate = entity.Comp.BaseMaterialProcessRate * MathF.Pow(entity.Comp.PartRatingProcessRateMultiplier, rating); - Dirty(entity); + var rating = args.PartRatings[component.MachinePartProcessRate] - 1; + component.MaterialProcessRate = component.BaseMaterialProcessRate * MathF.Pow(component.PartRatingProcessRateMultiplier, rating); + Dirty(component); } - private void OnPowerChanged(Entity entity, ref PowerChangedEvent args) + private void OnPowerChanged(EntityUid uid, MaterialReclaimerComponent component, ref PowerChangedEvent args) { - AmbientSound.SetAmbience(entity.Owner, entity.Comp.Enabled && args.Powered); - entity.Comp.Powered = args.Powered; - Dirty(entity); + AmbientSound.SetAmbience(uid, component.Enabled && args.Powered); + component.Powered = args.Powered; + Dirty(component); } - private void OnInteractUsing(Entity entity, ref InteractUsingEvent args) + private void OnInteractUsing(EntityUid uid, MaterialReclaimerComponent component, InteractUsingEvent args) { if (args.Handled) return; // if we're trying to get a solution out of the reclaimer, don't destroy it - if (_solutionContainer.TryGetSolution(entity.Owner, entity.Comp.SolutionContainerId, out _, out var outputSolution) && outputSolution.Contents.Any()) + if (component.OutputSolution.Contents.Any()) { if (TryComp(args.Used, out var managerComponent) && - _solutionContainer.EnumerateSolutions((args.Used, managerComponent)).Any(s => s.Solution.Comp.Solution.AvailableVolume > 0)) + managerComponent.Solutions.Any(s => s.Value.AvailableVolume > 0)) { if (_openable.IsClosed(args.Used)) return; @@ -95,10 +95,10 @@ public sealed class MaterialReclaimerSystem : SharedMaterialReclaimerSystem } } - args.Handled = TryStartProcessItem(entity.Owner, args.Used, entity.Comp, args.User); + args.Handled = TryStartProcessItem(uid, args.Used, component, args.User); } - private void OnSuicide(Entity entity, ref SuicideEvent args) + private void OnSuicide(EntityUid uid, MaterialReclaimerComponent component, SuicideEvent args) { if (args.Handled) return; @@ -109,9 +109,9 @@ public sealed class MaterialReclaimerSystem : SharedMaterialReclaimerSystem _mind.TryGetMind(actor.PlayerSession, out var mindId, out var mind)) { _ticker.OnGhostAttempt(mindId, false, mind: mind); - if (mind.OwnedEntity is { Valid: true } suicider) + if (mind.OwnedEntity is { Valid: true } entity) { - _popup.PopupEntity(Loc.GetString("recycler-component-suicide-message"), suicider); + _popup.PopupEntity(Loc.GetString("recycler-component-suicide-message"), entity); } } @@ -120,13 +120,13 @@ public sealed class MaterialReclaimerSystem : SharedMaterialReclaimerSystem Filter.PvsExcept(victim, entityManager: EntityManager), true); _body.GibBody(victim, true); - _appearance.SetData(entity.Owner, RecyclerVisuals.Bloody, true); + _appearance.SetData(uid, RecyclerVisuals.Bloody, true); } - private void OnActivePowerChanged(Entity entity, ref PowerChangedEvent args) + private void OnActivePowerChanged(EntityUid uid, ActiveMaterialReclaimerComponent component, ref PowerChangedEvent args) { if (!args.Powered) - TryFinishProcessItem(entity, null, entity.Comp); + TryFinishProcessItem(uid, null, component); } /// @@ -224,8 +224,6 @@ public sealed class MaterialReclaimerSystem : SharedMaterialReclaimerSystem { if (!Resolve(reclaimer, ref reclaimerComponent, ref xform)) return; - if (!_solutionContainer.TryGetSolution(reclaimer, reclaimerComponent.SolutionContainerId, out var outputSolution)) - return; efficiency *= reclaimerComponent.Efficiency; @@ -243,9 +241,8 @@ public sealed class MaterialReclaimerSystem : SharedMaterialReclaimerSystem // if the item we inserted has reagents, add it in. if (TryComp(item, out var solutionContainer)) { - foreach (var (_, soln) in _solutionContainer.EnumerateSolutions((item, solutionContainer))) + foreach (var solution in solutionContainer.Solutions.Values) { - var solution = soln.Comp.Solution; foreach (var quantity in solution.Contents) { totalChemicals.AddReagent(quantity.Reagent.Prototype, quantity.Quantity * efficiency, false); @@ -253,7 +250,7 @@ public sealed class MaterialReclaimerSystem : SharedMaterialReclaimerSystem } } - _solutionContainer.TryTransferSolution(outputSolution.Value, totalChemicals, totalChemicals.Volume); + _solutionContainer.TryTransferSolution(reclaimer, reclaimerComponent.OutputSolution, totalChemicals, totalChemicals.Volume); if (totalChemicals.Volume > 0) { _puddle.TrySpillAt(reclaimer, totalChemicals, out _, sound, transformComponent: xform); diff --git a/Content.Server/Medical/CryoPodSystem.cs b/Content.Server/Medical/CryoPodSystem.cs index 19cb62f836..b083c480f6 100644 --- a/Content.Server/Medical/CryoPodSystem.cs +++ b/Content.Server/Medical/CryoPodSystem.cs @@ -5,7 +5,6 @@ using Content.Server.Atmos.Piping.Components; using Content.Server.Atmos.Piping.Unary.EntitySystems; using Content.Server.Body.Components; using Content.Server.Body.Systems; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Medical.Components; using Content.Server.NodeContainer; using Content.Server.NodeContainer.EntitySystems; @@ -17,6 +16,7 @@ using Content.Server.UserInterface; using Content.Shared.Chemistry; using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Components.SolutionManager; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Chemistry.Reagent; using Content.Shared.Climbing.Systems; using Content.Shared.Containers.ItemSlots; @@ -28,6 +28,7 @@ using Content.Shared.Examine; using Content.Shared.Interaction; using Content.Shared.Medical.Cryogenics; using Content.Shared.MedicalScanner; +using Content.Shared.Tools; using Content.Shared.Verbs; using Robust.Server.GameObjects; using Robust.Shared.Timing; @@ -35,7 +36,7 @@ using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem; namespace Content.Server.Medical; -public sealed partial class CryoPodSystem : SharedCryoPodSystem +public sealed partial class CryoPodSystem: SharedCryoPodSystem { [Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!; [Dependency] private readonly GasCanisterSystem _gasCanisterSystem = default!; @@ -104,15 +105,14 @@ public sealed partial class CryoPodSystem : SharedCryoPodSystem && fitsInDispenserQuery.TryGetComponent(container, out var fitsInDispenserComponent) && solutionContainerManagerQuery.TryGetComponent(container, out var solutionContainerManagerComponent) - && _solutionContainerSystem.TryGetFitsInDispenser((container.Value, fitsInDispenserComponent, solutionContainerManagerComponent), - out var containerSolution, out _)) + && _solutionContainerSystem.TryGetFitsInDispenser(container.Value, out var containerSolution, dispenserFits: fitsInDispenserComponent, solutionManager: solutionContainerManagerComponent)) { if (!bloodStreamQuery.TryGetComponent(patient, out var bloodstream)) { continue; } - var solutionToInject = _solutionContainerSystem.SplitSolution(containerSolution.Value, cryoPod.BeakerTransferAmount); + var solutionToInject = _solutionContainerSystem.SplitSolution(container.Value, containerSolution, cryoPod.BeakerTransferAmount); _bloodstreamSystem.TryAddToChemicals(patient.Value, solutionToInject, bloodstream); _reactiveSystem.DoEntityReaction(patient.Value, solutionToInject, ReactionMethod.Injection); } @@ -123,7 +123,7 @@ public sealed partial class CryoPodSystem : SharedCryoPodSystem { if (!Resolve(uid, ref cryoPodComponent)) return null; - if (cryoPodComponent.BodyContainer.ContainedEntity is not { Valid: true } contained) + if (cryoPodComponent.BodyContainer.ContainedEntity is not {Valid: true} contained) return null; base.EjectBody(uid, cryoPodComponent); _climbSystem.ForciblySetClimbing(contained, uid); @@ -132,12 +132,12 @@ public sealed partial class CryoPodSystem : SharedCryoPodSystem #region Interaction - private void HandleDragDropOn(Entity entity, ref DragDropTargetEvent args) + private void HandleDragDropOn(EntityUid uid, CryoPodComponent cryoPodComponent, ref DragDropTargetEvent args) { - if (entity.Comp.BodyContainer.ContainedEntity != null) + if (cryoPodComponent.BodyContainer.ContainedEntity != null) return; - var doAfterArgs = new DoAfterArgs(EntityManager, args.User, entity.Comp.EntryDelay, new CryoPodDragFinished(), entity, target: args.Dragged, used: entity) + var doAfterArgs = new DoAfterArgs(EntityManager, args.User, cryoPodComponent.EntryDelay, new CryoPodDragFinished(), uid, target: args.Dragged, used: uid) { BreakOnDamage = true, BreakOnTargetMove = true, @@ -148,65 +148,61 @@ public sealed partial class CryoPodSystem : SharedCryoPodSystem args.Handled = true; } - private void OnDragFinished(Entity entity, ref CryoPodDragFinished args) + private void OnDragFinished(EntityUid uid, CryoPodComponent component, CryoPodDragFinished args) { if (args.Cancelled || args.Handled || args.Args.Target == null) return; - if (InsertBody(entity.Owner, args.Args.Target.Value, entity.Comp)) + if (InsertBody(uid, args.Args.Target.Value, component)) { - if (!TryComp(entity.Owner, out CryoPodAirComponent? cryoPodAir)) + if (!TryComp(uid, out CryoPodAirComponent? cryoPodAir)) _adminLogger.Add(LogType.Action, LogImpact.Medium, - $"{ToPrettyString(args.User)} inserted {ToPrettyString(args.Args.Target.Value)} into {ToPrettyString(entity.Owner)}"); + $"{ToPrettyString(args.User)} inserted {ToPrettyString(args.Args.Target.Value)} into {ToPrettyString(uid)}"); _adminLogger.Add(LogType.Action, LogImpact.Medium, - $"{ToPrettyString(args.User)} inserted {ToPrettyString(args.Args.Target.Value)} into {ToPrettyString(entity.Owner)} which contains gas: {cryoPodAir!.Air.ToPrettyString():gasMix}"); + $"{ToPrettyString(args.User)} inserted {ToPrettyString(args.Args.Target.Value)} into {ToPrettyString(uid)} which contains gas: {cryoPodAir!.Air.ToPrettyString():gasMix}"); } args.Handled = true; } - private void OnActivateUIAttempt(Entity entity, ref ActivatableUIOpenAttemptEvent args) + private void OnActivateUIAttempt(EntityUid uid, CryoPodComponent cryoPodComponent, ActivatableUIOpenAttemptEvent args) { if (args.Cancelled) { return; } - var containedEntity = entity.Comp.BodyContainer.ContainedEntity; - if (containedEntity == null || containedEntity == args.User || !HasComp(entity)) + var containedEntity = cryoPodComponent.BodyContainer.ContainedEntity; + if (containedEntity == null || containedEntity == args.User || !HasComp(uid)) { args.Cancel(); } } - private void OnActivateUI(Entity entity, ref AfterActivatableUIOpenEvent args) + private void OnActivateUI(EntityUid uid, CryoPodComponent cryoPodComponent, AfterActivatableUIOpenEvent args) { - TryComp(entity.Comp.BodyContainer.ContainedEntity, out var temp); - TryComp(entity.Comp.BodyContainer.ContainedEntity, out var bloodstream); + TryComp(cryoPodComponent.BodyContainer.ContainedEntity, out var temp); + TryComp(cryoPodComponent.BodyContainer.ContainedEntity, out var bloodstream); _userInterfaceSystem.TrySendUiMessage( - entity.Owner, + uid, HealthAnalyzerUiKey.Key, - new HealthAnalyzerScannedUserMessage(GetNetEntity(entity.Comp.BodyContainer.ContainedEntity), - temp?.CurrentTemperature ?? 0, - (bloodstream != null && _solutionContainerSystem.ResolveSolution(entity.Owner, bloodstream.BloodSolutionName, ref bloodstream.BloodSolution, out var bloodSolution)) - ? bloodSolution.FillFraction - : 0 - )); + new HealthAnalyzerScannedUserMessage(GetNetEntity(cryoPodComponent.BodyContainer.ContainedEntity), + temp?.CurrentTemperature ?? 0, bloodstream != null ? bloodstream.BloodSolution.FillFraction : 0)); } - private void OnInteractUsing(Entity entity, ref InteractUsingEvent args) + private void OnInteractUsing(EntityUid uid, CryoPodComponent cryoPodComponent, InteractUsingEvent args) { - if (args.Handled || !entity.Comp.Locked || entity.Comp.BodyContainer.ContainedEntity == null) + if (args.Handled || !cryoPodComponent.Locked || cryoPodComponent.BodyContainer.ContainedEntity == null) return; - args.Handled = _toolSystem.UseTool(args.Used, args.User, entity.Owner, entity.Comp.PryDelay, "Prying", new CryoPodPryFinished()); + args.Handled = _toolSystem.UseTool(args.Used, args.User, uid, cryoPodComponent.PryDelay, "Prying", new CryoPodPryFinished()); } - private void OnExamined(Entity entity, ref ExaminedEvent args) + private void OnExamined(EntityUid uid, CryoPodComponent component, ExaminedEvent args) { - var container = _itemSlotsSystem.GetItemOrNull(entity.Owner, entity.Comp.SolutionContainerName); - if (args.IsInDetailsRange && container != null && _solutionContainerSystem.TryGetFitsInDispenser(container.Value, out _, out var containerSolution)) + var container = _itemSlotsSystem.GetItemOrNull(uid, component.SolutionContainerName); + if (args.IsInDetailsRange && container != null && _solutionContainerSystem.TryGetFitsInDispenser(container.Value, out var containerSolution)) { args.PushMarkup(Loc.GetString("cryo-pod-examine", ("beaker", Name(container.Value)))); if (containerSolution.Volume == 0) @@ -216,63 +212,64 @@ public sealed partial class CryoPodSystem : SharedCryoPodSystem } } - private void OnPowerChanged(Entity entity, ref PowerChangedEvent args) + private void OnPowerChanged(EntityUid uid, CryoPodComponent component, ref PowerChangedEvent args) { // Needed to avoid adding/removing components on a deleted entity - if (Terminating(entity)) + if (Terminating(uid)) { return; } if (args.Powered) { - EnsureComp(entity); + EnsureComp(uid); } else { - RemComp(entity); - _uiSystem.TryCloseAll(entity.Owner, HealthAnalyzerUiKey.Key); + RemComp(uid); + _uiSystem.TryCloseAll(uid, HealthAnalyzerUiKey.Key); } - UpdateAppearance(entity.Owner, entity.Comp); + UpdateAppearance(uid, component); } #endregion #region Atmos handler - private void OnCryoPodUpdateAtmosphere(Entity entity, ref AtmosDeviceUpdateEvent args) + private void OnCryoPodUpdateAtmosphere(EntityUid uid, CryoPodComponent cryoPod, ref AtmosDeviceUpdateEvent args) { - if (!TryComp(entity, out NodeContainerComponent? nodeContainer)) + if (!TryComp(uid, out NodeContainerComponent? nodeContainer)) return; - if (!_nodeContainer.TryGetNode(nodeContainer, entity.Comp.PortName, out PortablePipeNode? portNode)) + if (!_nodeContainer.TryGetNode(nodeContainer, cryoPod.PortName, out PortablePipeNode? portNode)) return; - if (!TryComp(entity, out CryoPodAirComponent? cryoPodAir)) + if (!TryComp(uid, out CryoPodAirComponent? cryoPodAir)) return; _atmosphereSystem.React(cryoPodAir.Air, portNode); - if (portNode.NodeGroup is PipeNet { NodeCount: > 1 } net) + if (portNode.NodeGroup is PipeNet {NodeCount: > 1} net) { _gasCanisterSystem.MixContainerWithPipeNet(cryoPodAir.Air, net.Air); } } - private void OnGasAnalyzed(Entity entity, ref GasAnalyzerScanEvent args) + private void OnGasAnalyzed(EntityUid uid, CryoPodComponent component, GasAnalyzerScanEvent args) { - if (!TryComp(entity, out CryoPodAirComponent? cryoPodAir)) + if (!TryComp(uid, out CryoPodAirComponent? cryoPodAir)) return; - var gasMixDict = new Dictionary { { Name(entity.Owner), cryoPodAir.Air } }; + var gasMixDict = new Dictionary { { Name(uid), cryoPodAir.Air } }; // If it's connected to a port, include the port side - if (TryComp(entity, out NodeContainerComponent? nodeContainer)) + if (TryComp(uid, out NodeContainerComponent? nodeContainer)) { - if (_nodeContainer.TryGetNode(nodeContainer, entity.Comp.PortName, out PipeNode? port)) - gasMixDict.Add(entity.Comp.PortName, port.Air); + if (_nodeContainer.TryGetNode(nodeContainer, component.PortName, out PipeNode? port)) + gasMixDict.Add(component.PortName, port.Air); } args.GasMixtures = gasMixDict; } + #endregion } diff --git a/Content.Server/Medical/HealingSystem.cs b/Content.Server/Medical/HealingSystem.cs index 38f14ea9db..57f66f2378 100644 --- a/Content.Server/Medical/HealingSystem.cs +++ b/Content.Server/Medical/HealingSystem.cs @@ -1,9 +1,7 @@ using Content.Server.Administration.Logs; using Content.Server.Body.Components; using Content.Server.Body.Systems; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Medical.Components; -using Content.Server.Popups; using Content.Server.Stack; using Content.Shared.Audio; using Content.Shared.Damage; @@ -17,6 +15,8 @@ using Content.Shared.Mobs; using Content.Shared.Mobs.Components; using Content.Shared.Mobs.Systems; using Content.Shared.Stacks; +using Content.Server.Popups; +using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; using Robust.Shared.Random; @@ -34,7 +34,6 @@ public sealed class HealingSystem : EntitySystem [Dependency] private readonly SharedInteractionSystem _interactionSystem = default!; [Dependency] private readonly MobThresholdSystem _mobThresholdSystem = default!; [Dependency] private readonly PopupSystem _popupSystem = default!; - [Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!; public override void Initialize() { @@ -44,7 +43,7 @@ public sealed class HealingSystem : EntitySystem SubscribeLocalEvent(OnDoAfter); } - private void OnDoAfter(Entity entity, ref HealingDoAfterEvent args) + private void OnDoAfter(EntityUid uid, DamageableComponent component, HealingDoAfterEvent args) { var dontRepeat = false; @@ -55,8 +54,8 @@ public sealed class HealingSystem : EntitySystem return; if (healing.DamageContainers is not null && - entity.Comp.DamageContainerID is not null && - !healing.DamageContainers.Contains(entity.Comp.DamageContainerID)) + component.DamageContainerID is not null && + !healing.DamageContainers.Contains(component.DamageContainerID)) { return; } @@ -64,22 +63,22 @@ public sealed class HealingSystem : EntitySystem // Heal some bloodloss damage. if (healing.BloodlossModifier != 0) { - if (!TryComp(entity, out var bloodstream)) + if (!TryComp(uid, out var bloodstream)) return; var isBleeding = bloodstream.BleedAmount > 0; - _bloodstreamSystem.TryModifyBleedAmount(entity.Owner, healing.BloodlossModifier); + _bloodstreamSystem.TryModifyBleedAmount(uid, healing.BloodlossModifier); if (isBleeding != bloodstream.BleedAmount > 0) { dontRepeat = true; - _popupSystem.PopupEntity(Loc.GetString("medical-item-stop-bleeding"), entity, args.User); + _popupSystem.PopupEntity(Loc.GetString("medical-item-stop-bleeding"), uid, args.User); } } // Restores missing blood if (healing.ModifyBloodLevel != 0) - _bloodstreamSystem.TryModifyBloodLevel(entity.Owner, healing.ModifyBloodLevel); + _bloodstreamSystem.TryModifyBloodLevel(uid, healing.ModifyBloodLevel); - var healed = _damageable.TryChangeDamage(entity.Owner, healing.Damage, true, origin: args.Args.User); + var healed = _damageable.TryChangeDamage(uid, healing.Damage, true, origin: args.Args.User); if (healed == null && healing.BloodlossModifier != 0) return; @@ -100,10 +99,10 @@ public sealed class HealingSystem : EntitySystem QueueDel(args.Used.Value); } - if (entity.Owner != args.User) + if (uid != args.User) { _adminLogger.Add(LogType.Healed, - $"{EntityManager.ToPrettyString(args.User):user} healed {EntityManager.ToPrettyString(entity.Owner):target} for {total:damage} damage"); + $"{EntityManager.ToPrettyString(args.User):user} healed {EntityManager.ToPrettyString(uid):target} for {total:damage} damage"); } else { @@ -111,12 +110,12 @@ public sealed class HealingSystem : EntitySystem $"{EntityManager.ToPrettyString(args.User):user} healed themselves for {total:damage} damage"); } - _audio.PlayPvs(healing.HealingEndSound, entity.Owner, AudioHelpers.WithVariation(0.125f, _random).WithVolume(-5f)); + _audio.PlayPvs(healing.HealingEndSound, uid, AudioHelpers.WithVariation(0.125f, _random).WithVolume(-5f)); // Logic to determine the whether or not to repeat the healing action - args.Repeat = (HasDamage(entity.Comp, healing) && !dontRepeat); + args.Repeat = (HasDamage(component, healing) && !dontRepeat); if (!args.Repeat && !dontRepeat) - _popupSystem.PopupEntity(Loc.GetString("medical-item-finished-using", ("item", args.Used)), entity.Owner, args.User); + _popupSystem.PopupEntity(Loc.GetString("medical-item-finished-using", ("item", args.Used)), uid, args.User); args.Handled = true; } @@ -135,21 +134,21 @@ public sealed class HealingSystem : EntitySystem return false; } - private void OnHealingUse(Entity entity, ref UseInHandEvent args) + private void OnHealingUse(EntityUid uid, HealingComponent component, UseInHandEvent args) { if (args.Handled) return; - if (TryHeal(entity, args.User, args.User, entity.Comp)) + if (TryHeal(uid, args.User, args.User, component)) args.Handled = true; } - private void OnHealingAfterInteract(Entity entity, ref AfterInteractEvent args) + private void OnHealingAfterInteract(EntityUid uid, HealingComponent component, AfterInteractEvent args) { if (args.Handled || !args.CanReach || args.Target == null) return; - if (TryHeal(entity, args.User, args.Target.Value, entity.Comp)) + if (TryHeal(uid, args.User, args.Target.Value, component)) args.Handled = true; } @@ -171,14 +170,10 @@ public sealed class HealingSystem : EntitySystem if (TryComp(uid, out var stack) && stack.Count < 1) return false; - var anythingToDo = - HasDamage(targetDamage, component) || - component.ModifyBloodLevel > 0 // Special case if healing item can restore lost blood... - && TryComp(target, out var bloodstream) - && _solutionContainerSystem.ResolveSolution(target, bloodstream.BloodSolutionName, ref bloodstream.BloodSolution, out var bloodSolution) - && bloodSolution.Volume < bloodSolution.MaxVolume; // ...and there is lost blood to restore. + if (!TryComp(target, out var bloodstream)) + return false; - if (!anythingToDo) + if (!HasDamage(targetDamage, component) && !(bloodstream.BloodSolution.Volume < bloodstream.BloodSolution.MaxVolume && component.ModifyBloodLevel > 0)) { _popupSystem.PopupEntity(Loc.GetString("medical-item-cant-use", ("item", uid)), uid, user); return false; diff --git a/Content.Server/Medical/HealthAnalyzerSystem.cs b/Content.Server/Medical/HealthAnalyzerSystem.cs index d9559a9626..fe3944b21e 100644 --- a/Content.Server/Medical/HealthAnalyzerSystem.cs +++ b/Content.Server/Medical/HealthAnalyzerSystem.cs @@ -1,14 +1,14 @@ -using Content.Server.Body.Components; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Medical.Components; using Content.Server.PowerCell; -using Content.Server.Temperature.Components; using Content.Shared.Damage; using Content.Shared.DoAfter; using Content.Shared.Interaction; using Content.Shared.MedicalScanner; using Content.Shared.Mobs.Components; using Robust.Server.GameObjects; +using Content.Server.Temperature.Components; +using Content.Server.Body.Components; +using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; using Robust.Shared.Player; @@ -19,7 +19,6 @@ namespace Content.Server.Medical [Dependency] private readonly PowerCellSystem _cell = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!; - [Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!; [Dependency] private readonly UserInterfaceSystem _uiSystem = default!; public override void Initialize() @@ -29,14 +28,14 @@ namespace Content.Server.Medical SubscribeLocalEvent(OnDoAfter); } - private void OnAfterInteract(Entity entity, ref AfterInteractEvent args) + private void OnAfterInteract(EntityUid uid, HealthAnalyzerComponent healthAnalyzer, AfterInteractEvent args) { - if (args.Target == null || !args.CanReach || !HasComp(args.Target) || !_cell.HasActivatableCharge(entity.Owner, user: args.User)) + if (args.Target == null || !args.CanReach || !HasComp(args.Target) || !_cell.HasActivatableCharge(uid, user: args.User)) return; - _audio.PlayPvs(entity.Comp.ScanningBeginSound, entity); + _audio.PlayPvs(healthAnalyzer.ScanningBeginSound, uid); - _doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager, args.User, TimeSpan.FromSeconds(entity.Comp.ScanDelay), new HealthAnalyzerDoAfterEvent(), entity.Owner, target: args.Target, used: entity.Owner) + _doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager, args.User, healthAnalyzer.ScanDelay, new HealthAnalyzerDoAfterEvent(), uid, target: args.Target, used: uid) { BreakOnTargetMove = true, BreakOnUserMove = true, @@ -44,14 +43,14 @@ namespace Content.Server.Medical }); } - private void OnDoAfter(Entity entity, ref HealthAnalyzerDoAfterEvent args) + private void OnDoAfter(EntityUid uid, HealthAnalyzerComponent component, DoAfterEvent args) { - if (args.Handled || args.Cancelled || args.Target == null || !_cell.TryUseActivatableCharge(entity.Owner, user: args.User)) + if (args.Handled || args.Cancelled || args.Args.Target == null || !_cell.TryUseActivatableCharge(uid, user: args.User)) return; - _audio.PlayPvs(entity.Comp.ScanningEndSound, args.User); + _audio.PlayPvs(component.ScanningEndSound, args.Args.User); - UpdateScannedUser(entity, args.User, args.Target.Value, entity.Comp); + UpdateScannedUser(uid, args.Args.User, args.Args.Target.Value, component); args.Handled = true; } @@ -74,26 +73,13 @@ namespace Content.Server.Medical if (!HasComp(target)) return; - float bodyTemperature; - if (TryComp(target, out var temp)) - bodyTemperature = temp.CurrentTemperature; - else - bodyTemperature = float.NaN; - - float bloodAmount; - if (TryComp(target, out var bloodstream) && - _solutionContainerSystem.ResolveSolution(target.Value, bloodstream.BloodSolutionName, ref bloodstream.BloodSolution, out var bloodSolution)) - bloodAmount = bloodSolution.FillFraction; - else - bloodAmount = float.NaN; + TryComp(target, out var temp); + TryComp(target, out var bloodstream); OpenUserInterface(user, uid); - _uiSystem.SendUiMessage(ui, new HealthAnalyzerScannedUserMessage( - GetNetEntity(target), - bodyTemperature, - bloodAmount - )); + _uiSystem.SendUiMessage(ui, new HealthAnalyzerScannedUserMessage(GetNetEntity(target), temp != null ? temp.CurrentTemperature : float.NaN, + bloodstream != null ? bloodstream.BloodSolution.FillFraction : float.NaN)); } } } diff --git a/Content.Server/Medical/VomitSystem.cs b/Content.Server/Medical/VomitSystem.cs index 8c3b15aed3..fedb6d2357 100644 --- a/Content.Server/Medical/VomitSystem.cs +++ b/Content.Server/Medical/VomitSystem.cs @@ -1,16 +1,17 @@ using Content.Server.Body.Components; using Content.Server.Body.Systems; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Fluids.EntitySystems; using Content.Server.Forensics; using Content.Server.Popups; using Content.Server.Stunnable; using Content.Shared.Chemistry.Components; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.IdentityManagement; using Content.Shared.Nutrition.Components; using Content.Shared.Nutrition.EntitySystems; using Content.Shared.StatusEffect; using Robust.Server.Audio; +using Robust.Server.GameObjects; using Robust.Shared.Audio; using Robust.Shared.Prototypes; @@ -58,32 +59,29 @@ namespace Content.Server.Medical // Empty the stomach out into it foreach (var stomach in stomachList) { - if (_solutionContainer.ResolveSolution(stomach.Comp.Owner, StomachSystem.DefaultSolutionName, ref stomach.Comp.Solution, out var sol)) + if (_solutionContainer.TryGetSolution(stomach.Comp.Owner, StomachSystem.DefaultSolutionName, + out var sol)) { solution.AddSolution(sol, _proto); sol.RemoveAllSolution(); - _solutionContainer.UpdateChemicals(stomach.Comp.Solution.Value); + _solutionContainer.UpdateChemicals(stomach.Comp.Owner, sol); } } // Adds a tiny amount of the chem stream from earlier along with vomit if (TryComp(uid, out var bloodStream)) { - const float chemMultiplier = 0.1f; - - var vomitAmount = solutionSize; - - // Takes 10% of the chemicals removed from the chem stream - if (_solutionContainer.ResolveSolution(uid, bloodStream.ChemicalSolutionName, ref bloodStream.ChemicalSolution)) - { - var vomitChemstreamAmount = _solutionContainer.SplitSolution(bloodStream.ChemicalSolution.Value, vomitAmount); - vomitChemstreamAmount.ScaleSolution(chemMultiplier); - solution.AddSolution(vomitChemstreamAmount, _proto); - - vomitAmount -= (float) vomitChemstreamAmount.Volume; - } + var chemMultiplier = 0.1; + var vomitMultiplier = 0.9; // Makes a vomit solution the size of 90% of the chemicals removed from the chemstream - solution.AddReagent("Vomit", vomitAmount); // TODO: Dehardcode vomit prototype + var vomitAmount = new Solution("Vomit", solutionSize * vomitMultiplier); + + // Takes 10% of the chemicals removed from the chem stream + var vomitChemstreamAmount = _solutionContainer.SplitSolution(uid, bloodStream.ChemicalSolution, solutionSize * chemMultiplier); + + _solutionContainer.SplitSolution(uid, bloodStream.ChemicalSolution, solutionSize * vomitMultiplier); + solution.AddSolution(vomitAmount, _proto); + solution.AddSolution(vomitChemstreamAmount, _proto); } if (_puddle.TrySpillAt(uid, solution, out var puddle, false)) diff --git a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Specific/MedibotInjectOperator.cs b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Specific/MedibotInjectOperator.cs index 01cfbd113d..7b66cff1f8 100644 --- a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Specific/MedibotInjectOperator.cs +++ b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Specific/MedibotInjectOperator.cs @@ -1,13 +1,15 @@ using Content.Server.Chat.Systems; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.NPC.Components; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Damage; using Content.Shared.Emag.Components; using Content.Shared.Interaction; using Content.Shared.Mobs.Components; using Content.Shared.Popups; using Content.Shared.Silicons.Bots; +using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; +using Robust.Shared.Player; namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators.Specific; @@ -19,7 +21,7 @@ public sealed partial class MedibotInjectOperator : HTNOperator private SharedAudioSystem _audio = default!; private SharedInteractionSystem _interaction = default!; private SharedPopupSystem _popup = default!; - private SolutionContainerSystem _solutionContainer = default!; + private SolutionContainerSystem _solution = default!; /// /// Target entity to inject. @@ -35,7 +37,7 @@ public sealed partial class MedibotInjectOperator : HTNOperator _audio = sysManager.GetEntitySystem(); _interaction = sysManager.GetEntitySystem(); _popup = sysManager.GetEntitySystem(); - _solutionContainer = sysManager.GetEntitySystem(); + _solution = sysManager.GetEntitySystem(); } public override void TaskShutdown(NPCBlackboard blackboard, HTNOperatorStatus status) @@ -59,7 +61,7 @@ public sealed partial class MedibotInjectOperator : HTNOperator if (!_entMan.TryGetComponent(target, out var damage)) return HTNOperatorStatus.Failed; - if (!_solutionContainer.TryGetInjectableSolution(target, out var injectable, out _)) + if (!_solution.TryGetInjectableSolution(target, out var injectable)) return HTNOperatorStatus.Failed; if (!_interaction.InRangeUnobstructed(owner, target)) @@ -79,7 +81,7 @@ public sealed partial class MedibotInjectOperator : HTNOperator return HTNOperatorStatus.Failed; _entMan.EnsureComponent(target); - _solutionContainer.TryAddReagent(injectable.Value, treatment.Reagent, treatment.Quantity, out _); + _solution.TryAddReagent(target, injectable, treatment.Reagent, treatment.Quantity, out _); _popup.PopupEntity(Loc.GetString("hypospray-component-feel-prick-message"), target, target); _audio.PlayPvs(botComp.InjectSound, target); _chat.TrySendInGameICMessage(owner, Loc.GetString("medibot-finish-inject"), InGameICChatType.Speak, hideChat: true, hideLog: true); diff --git a/Content.Server/NPC/Systems/NPCUtilitySystem.cs b/Content.Server/NPC/Systems/NPCUtilitySystem.cs index 76d0ebe83a..641b8c20e1 100644 --- a/Content.Server/NPC/Systems/NPCUtilitySystem.cs +++ b/Content.Server/NPC/Systems/NPCUtilitySystem.cs @@ -1,4 +1,4 @@ -using Content.Server.Chemistry.Containers.EntitySystems; +using System.Linq; using Content.Server.Fluids.EntitySystems; using Content.Server.NPC.Queries; using Content.Server.NPC.Queries.Considerations; @@ -7,6 +7,7 @@ using Content.Server.NPC.Queries.Queries; using Content.Server.Nutrition.Components; using Content.Server.Nutrition.EntitySystems; using Content.Server.Storage.Components; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Examine; using Content.Shared.Fluids.Components; using Content.Shared.Hands.Components; @@ -19,9 +20,9 @@ using Content.Shared.Weapons.Ranged.Components; using Content.Shared.Weapons.Ranged.Events; using Microsoft.Extensions.ObjectPool; using Robust.Server.Containers; +using Robust.Shared.Collections; using Robust.Shared.Prototypes; using Robust.Shared.Utility; -using System.Linq; namespace Content.Server.NPC.Systems; @@ -491,7 +492,7 @@ public sealed class NPCUtilitySystem : EntitySystem foreach (var ent in entities) { if (!_puddleQuery.TryGetComponent(ent, out var puddleComp) || - !_solutions.TryGetSolution(ent, puddleComp.SolutionName, out _, out var sol) || + !_solutions.TryGetSolution(ent, puddleComp.SolutionName, out var sol) || _puddle.CanFullyEvaporate(sol)) { _entityList.Add(ent); diff --git a/Content.Server/Nutrition/EntitySystems/CreamPieSystem.cs b/Content.Server/Nutrition/EntitySystems/CreamPieSystem.cs index 45d868cdbf..eebe7f98d8 100644 --- a/Content.Server/Nutrition/EntitySystems/CreamPieSystem.cs +++ b/Content.Server/Nutrition/EntitySystems/CreamPieSystem.cs @@ -1,9 +1,9 @@ -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Explosion.Components; using Content.Server.Explosion.EntitySystems; using Content.Server.Fluids.EntitySystems; using Content.Server.Nutrition.Components; using Content.Server.Popups; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Containers.ItemSlots; using Content.Shared.Interaction; using Content.Shared.Nutrition.Components; @@ -11,6 +11,7 @@ using Content.Shared.Nutrition.EntitySystems; using Content.Shared.Rejuvenate; using Content.Shared.Throwing; using JetBrains.Annotations; +using Robust.Server.GameObjects; using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; using Robust.Shared.Player; @@ -41,7 +42,7 @@ namespace Content.Server.Nutrition.EntitySystems if (EntityManager.TryGetComponent(uid, out FoodComponent? foodComp)) { - if (_solutions.TryGetSolution(uid, foodComp.Solution, out _, out var solution)) + if (_solutions.TryGetSolution(uid, foodComp.Solution, out var solution)) { _puddle.TrySpillAt(uid, solution, out _, false); } @@ -55,9 +56,9 @@ namespace Content.Server.Nutrition.EntitySystems EntityManager.QueueDeleteEntity(uid); } - private void OnInteractUsing(Entity entity, ref InteractUsingEvent args) + private void OnInteractUsing(EntityUid uid, CreamPieComponent component, InteractUsingEvent args) { - ActivatePayload(entity); + ActivatePayload(uid); } private void ActivatePayload(EntityUid uid) @@ -88,12 +89,12 @@ namespace Content.Server.Nutrition.EntitySystems { otherPlayers.RemovePlayer(actor.PlayerSession); } - _popup.PopupEntity(Loc.GetString("cream-pied-component-on-hit-by-message-others", ("owner", uid), ("thrower", args.Thrown)), uid, otherPlayers, false); + _popup.PopupEntity(Loc.GetString("cream-pied-component-on-hit-by-message-others", ("owner", uid),("thrower", args.Thrown)), uid, otherPlayers, false); } - private void OnRejuvenate(Entity entity, ref RejuvenateEvent args) + private void OnRejuvenate(EntityUid uid, CreamPiedComponent component, RejuvenateEvent args) { - SetCreamPied(entity, entity.Comp, false); + SetCreamPied(uid, component, false); } } } diff --git a/Content.Server/Nutrition/EntitySystems/DrinkSystem.cs b/Content.Server/Nutrition/EntitySystems/DrinkSystem.cs index b32f5a7f63..e41c834c80 100644 --- a/Content.Server/Nutrition/EntitySystems/DrinkSystem.cs +++ b/Content.Server/Nutrition/EntitySystems/DrinkSystem.cs @@ -1,6 +1,6 @@ using Content.Server.Body.Components; using Content.Server.Body.Systems; -using Content.Server.Chemistry.Containers.EntitySystems; +using Content.Server.Chemistry.EntitySystems; using Content.Server.Chemistry.ReagentEffects; using Content.Server.Fluids.EntitySystems; using Content.Server.Forensics; @@ -61,7 +61,7 @@ public sealed class DrinkSystem : EntitySystem base.Initialize(); // TODO add InteractNoHandEvent for entities like mice. - SubscribeLocalEvent(OnSolutionChange); + SubscribeLocalEvent(OnSolutionChange); SubscribeLocalEvent(OnDrinkInit); // run before inventory so for bucket it always tries to drink before equipping (when empty) // run after openable so its always open -> drink @@ -80,7 +80,7 @@ public sealed class DrinkSystem : EntitySystem if (!Resolve(uid, ref component)) return FixedPoint2.Zero; - if (!_solutionContainer.TryGetSolution(uid, component.Solution, out _, out var sol)) + if (!_solutionContainer.TryGetSolution(uid, component.Solution, out var sol)) return FixedPoint2.Zero; return sol.Volume; @@ -102,7 +102,7 @@ public sealed class DrinkSystem : EntitySystem if (!Resolve(uid, ref comp)) return 0f; - if (!_solutionContainer.TryGetSolution(uid, comp.Solution, out _, out var solution)) + if (!_solutionContainer.TryGetSolution(uid, comp.Solution, out var solution)) return 0f; var total = 0f; @@ -128,31 +128,31 @@ public sealed class DrinkSystem : EntitySystem return total; } - private void OnExamined(Entity entity, ref ExaminedEvent args) + private void OnExamined(EntityUid uid, DrinkComponent component, ExaminedEvent args) { - var hasOpenable = TryComp(entity, out var openable); - if (_openable.IsClosed(entity.Owner, null, openable) || !args.IsInDetailsRange || !entity.Comp.Examinable) + var hasOpenable = TryComp(uid, out var openable); + if (_openable.IsClosed(uid, null, openable) || !args.IsInDetailsRange || !component.Examinable) return; // put Empty / Xu after Opened, or start a new line args.Message.AddMarkup(hasOpenable ? " - " : "\n"); - var empty = IsEmpty(entity, entity.Comp); + var empty = IsEmpty(uid, component); if (empty) { args.Message.AddMarkup(Loc.GetString("drink-component-on-examine-is-empty")); return; } - if (TryComp(entity, out var comp)) + if (TryComp(uid, out var comp)) { //provide exact measurement for beakers - args.Message.AddMarkup(Loc.GetString("drink-component-on-examine-exact-volume", ("amount", DrinkVolume(entity, entity.Comp)))); + args.Message.AddMarkup(Loc.GetString("drink-component-on-examine-exact-volume", ("amount", DrinkVolume(uid, component)))); } else { //general approximation - var remainingString = (int) _solutionContainer.PercentFull(entity) switch + var remainingString = (int) _solutionContainer.PercentFull(uid) switch { 100 => "drink-component-on-examine-is-full", > 66 => "drink-component-on-examine-is-mostly-full", @@ -163,65 +163,65 @@ public sealed class DrinkSystem : EntitySystem } } - private void AfterInteract(Entity entity, ref AfterInteractEvent args) + private void AfterInteract(EntityUid uid, DrinkComponent component, AfterInteractEvent args) { if (args.Handled || args.Target == null || !args.CanReach) return; - args.Handled = TryDrink(args.User, args.Target.Value, entity.Comp, entity); + args.Handled = TryDrink(args.User, args.Target.Value, component, uid); } - private void OnUse(Entity entity, ref UseInHandEvent args) + private void OnUse(EntityUid uid, DrinkComponent component, UseInHandEvent args) { if (args.Handled) return; - args.Handled = TryDrink(args.User, args.User, entity.Comp, entity); + args.Handled = TryDrink(args.User, args.User, component, uid); } - private void OnPressurizedDrinkLand(Entity entity, ref LandEvent args) + private void OnPressurizedDrinkLand(EntityUid uid, PressurizedDrinkComponent comp, ref LandEvent args) { - if (!TryComp(entity, out var drink) || !TryComp(entity, out var openable)) + if (!TryComp(uid, out var drink) || !TryComp(uid, out var openable)) return; if (!openable.Opened && - _random.Prob(entity.Comp.BurstChance) && - _solutionContainer.TryGetSolution(entity.Owner, drink.Solution, out var soln, out var interactions)) + _random.Prob(comp.BurstChance) && + _solutionContainer.TryGetSolution(uid, drink.Solution, out var interactions)) { // using SetOpen instead of TryOpen to not play 2 sounds - _openable.SetOpen(entity, true, openable); + _openable.SetOpen(uid, true, openable); - var solution = _solutionContainer.SplitSolution(soln.Value, interactions.Volume); - _puddle.TrySpillAt(entity, solution, out _); + var solution = _solutionContainer.SplitSolution(uid, interactions, interactions.Volume); + _puddle.TrySpillAt(uid, solution, out _); - _audio.PlayPvs(entity.Comp.BurstSound, entity); + _audio.PlayPvs(comp.BurstSound, uid); } } - private void OnDrinkInit(Entity entity, ref ComponentInit args) + private void OnDrinkInit(EntityUid uid, DrinkComponent component, ComponentInit args) { - if (TryComp(entity, out var existingDrainable)) + if (TryComp(uid, out var existingDrainable)) { // Beakers have Drink component but they should use the existing Drainable - entity.Comp.Solution = existingDrainable.Solution; + component.Solution = existingDrainable.Solution; } else { - _solutionContainer.EnsureSolution(entity.Owner, entity.Comp.Solution); + _solutionContainer.EnsureSolution(uid, component.Solution); } - UpdateAppearance(entity, entity.Comp); + UpdateAppearance(uid, component); - if (TryComp(entity, out RefillableSolutionComponent? refillComp)) - refillComp.Solution = entity.Comp.Solution; + if (TryComp(uid, out RefillableSolutionComponent? refillComp)) + refillComp.Solution = component.Solution; - if (TryComp(entity, out DrainableSolutionComponent? drainComp)) - drainComp.Solution = entity.Comp.Solution; + if (TryComp(uid, out DrainableSolutionComponent? drainComp)) + drainComp.Solution = component.Solution; } - private void OnSolutionChange(Entity entity, ref SolutionContainerChangedEvent args) + private void OnSolutionChange(EntityUid uid, DrinkComponent component, SolutionChangedEvent args) { - UpdateAppearance(entity, entity.Comp); + UpdateAppearance(uid, component); } public void UpdateAppearance(EntityUid uid, DrinkComponent component) @@ -244,7 +244,8 @@ public sealed class DrinkSystem : EntitySystem if (_openable.IsClosed(item, user)) return true; - if (!_solutionContainer.TryGetSolution(item, drink.Solution, out _, out var drinkSolution) || drinkSolution.Volume <= 0) + if (!_solutionContainer.TryGetSolution(item, drink.Solution, out var drinkSolution) || + drinkSolution.Volume <= 0) { if (drink.IgnoreEmpty) return false; @@ -253,6 +254,9 @@ public sealed class DrinkSystem : EntitySystem return true; } + if (drinkSolution.Name == null) + return false; + if (_food.IsMouthBlocked(target, user)) return true; @@ -281,7 +285,7 @@ public sealed class DrinkSystem : EntitySystem var doAfterEventArgs = new DoAfterArgs(EntityManager, user, forceDrink ? drink.ForceFeedDelay : drink.Delay, - new ConsumeDoAfterEvent(drink.Solution, flavors), + new ConsumeDoAfterEvent(drinkSolution.Name, flavors), eventTarget: item, target: target, used: item) @@ -303,15 +307,15 @@ public sealed class DrinkSystem : EntitySystem /// /// Raised directed at a victim when someone has force fed them a drink. /// - private void OnDoAfter(Entity entity, ref ConsumeDoAfterEvent args) + private void OnDoAfter(EntityUid uid, DrinkComponent component, ConsumeDoAfterEvent args) { - if (args.Handled || args.Cancelled || entity.Comp.Deleted) + if (args.Handled || args.Cancelled || component.Deleted) return; if (!TryComp(args.Target, out var body)) return; - if (args.Used is null || !_solutionContainer.TryGetSolution(args.Used.Value, args.Solution, out var soln, out var solution)) + if (!_solutionContainer.TryGetSolution(args.Used, args.Solution, out var solution)) return; // TODO this should really be checked every tick. @@ -322,8 +326,8 @@ public sealed class DrinkSystem : EntitySystem if (!_interaction.InRangeUnobstructed(args.User, args.Target.Value)) return; - var transferAmount = FixedPoint2.Min(entity.Comp.TransferAmount, solution.Volume); - var drained = _solutionContainer.SplitSolution(soln.Value, transferAmount); + var transferAmount = FixedPoint2.Min(component.TransferAmount, solution.Volume); + var drained = _solutionContainer.SplitSolution(uid, solution, transferAmount); var forceDrink = args.User != args.Target; args.Handled = true; @@ -340,11 +344,11 @@ public sealed class DrinkSystem : EntitySystem return; } - _solutionContainer.Refill(args.Target.Value, soln.Value, drained); + _solutionContainer.Refill(args.Target.Value, solution, drained); return; } - var firstStomach = stomachs.FirstOrNull(stomach => _stomach.CanTransferSolution(stomach.Comp.Owner, drained, stomach.Comp)); + var firstStomach = stomachs.FirstOrNull(stomach => _stomach.CanTransferSolution(stomach.Comp.Owner, drained)); //All stomachs are full or can't handle whatever solution we have. if (firstStomach == null) @@ -357,7 +361,7 @@ public sealed class DrinkSystem : EntitySystem _puddle.TrySpillAt(args.Target.Value, drained, out _); } else - _solutionContainer.TryAddSolution(soln.Value, drained); + _solutionContainer.TryAddSolution(uid, solution, drained); return; } @@ -376,7 +380,7 @@ public sealed class DrinkSystem : EntitySystem args.User, args.User); // log successful forced drinking - _adminLogger.Add(LogType.ForceFeed, LogImpact.Medium, $"{ToPrettyString(entity.Owner):user} forced {ToPrettyString(args.User):target} to drink {ToPrettyString(entity.Owner):drink}"); + _adminLogger.Add(LogType.ForceFeed, LogImpact.Medium, $"{ToPrettyString(uid):user} forced {ToPrettyString(args.User):target} to drink {ToPrettyString(uid):drink}"); } else { @@ -387,24 +391,24 @@ public sealed class DrinkSystem : EntitySystem Loc.GetString("drink-component-try-use-drink-success-slurp"), args.User, Filter.PvsExcept(args.User), true); // log successful voluntary drinking - _adminLogger.Add(LogType.Ingestion, LogImpact.Low, $"{ToPrettyString(args.User):target} drank {ToPrettyString(entity.Owner):drink}"); + _adminLogger.Add(LogType.Ingestion, LogImpact.Low, $"{ToPrettyString(args.User):target} drank {ToPrettyString(uid):drink}"); } - _audio.PlayPvs(entity.Comp.UseSound, args.Target.Value, AudioParams.Default.WithVolume(-2f)); + _audio.PlayPvs(component.UseSound, args.Target.Value, AudioParams.Default.WithVolume(-2f)); _reaction.DoEntityReaction(args.Target.Value, solution, ReactionMethod.Ingestion); //TODO: Grab the stomach UIDs somehow without using Owner _stomach.TryTransferSolution(firstStomach.Value.Comp.Owner, drained, firstStomach.Value.Comp); - _forensics.TransferDna(entity, args.Target.Value); + _forensics.TransferDna(uid, args.Target.Value); if (!forceDrink && solution.Volume > 0) args.Repeat = true; } - private void AddDrinkVerb(Entity entity, ref GetVerbsEvent ev) + private void AddDrinkVerb(EntityUid uid, DrinkComponent component, GetVerbsEvent ev) { - if (entity.Owner == ev.User || + if (uid == ev.User || !ev.CanInteract || !ev.CanAccess || !TryComp(ev.User, out var body) || @@ -412,17 +416,16 @@ public sealed class DrinkSystem : EntitySystem return; // no drinking from living drinks, have to kill them first. - if (_mobState.IsAlive(entity)) + if (_mobState.IsAlive(uid)) return; - var user = ev.User; AlternativeVerb verb = new() { Act = () => { - TryDrink(user, user, entity.Comp, entity); + TryDrink(ev.User, ev.User, component, uid); }, - Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/drink.svg.192dpi.png")), + Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/drink.svg.192dpi.png")), Text = Loc.GetString("drink-system-verb-drink"), Priority = 2 }; diff --git a/Content.Server/Nutrition/EntitySystems/FlavorProfileSystem.cs b/Content.Server/Nutrition/EntitySystems/FlavorProfileSystem.cs index 4a18696cea..e01f199ae1 100644 --- a/Content.Server/Nutrition/EntitySystems/FlavorProfileSystem.cs +++ b/Content.Server/Nutrition/EntitySystems/FlavorProfileSystem.cs @@ -1,10 +1,13 @@ +using System.Linq; +using System.Text; using Content.Server.Nutrition.Components; using Content.Shared.CCVar; using Content.Shared.Chemistry.Components; +using Content.Shared.Chemistry.Reagent; using Content.Shared.Nutrition; +using Microsoft.VisualBasic; using Robust.Shared.Configuration; using Robust.Shared.Prototypes; -using System.Linq; namespace Content.Server.Nutrition.EntitySystems; diff --git a/Content.Server/Nutrition/EntitySystems/FoodSystem.cs b/Content.Server/Nutrition/EntitySystems/FoodSystem.cs index 95a40a9409..b18c77fffb 100644 --- a/Content.Server/Nutrition/EntitySystems/FoodSystem.cs +++ b/Content.Server/Nutrition/EntitySystems/FoodSystem.cs @@ -1,6 +1,6 @@ +using System.Linq; using Content.Server.Body.Components; using Content.Server.Body.Systems; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Inventory; using Content.Server.Nutrition.Components; using Content.Server.Popups; @@ -9,6 +9,7 @@ using Content.Shared.Administration.Logs; using Content.Shared.Body.Components; using Content.Shared.Body.Organ; using Content.Shared.Chemistry; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Chemistry.Reagent; using Content.Shared.Database; using Content.Shared.DoAfter; @@ -26,9 +27,11 @@ using Content.Shared.Stacks; using Content.Shared.Storage; using Content.Shared.Verbs; using Robust.Shared.Audio; -using Robust.Shared.Audio.Systems; +using Robust.Shared.Player; using Robust.Shared.Utility; -using System.Linq; +using Content.Shared.Tag; +using Content.Shared.Storage; +using Robust.Shared.Audio.Systems; namespace Content.Server.Nutrition.EntitySystems; @@ -72,24 +75,24 @@ public sealed class FoodSystem : EntitySystem /// /// Eat item /// - private void OnUseFoodInHand(Entity entity, ref UseInHandEvent ev) + private void OnUseFoodInHand(EntityUid uid, FoodComponent foodComponent, UseInHandEvent ev) { if (ev.Handled) return; - var result = TryFeed(ev.User, ev.User, entity, entity.Comp); + var result = TryFeed(ev.User, ev.User, uid, foodComponent); ev.Handled = result.Handled; } /// /// Feed someone else /// - private void OnFeedFood(Entity entity, ref AfterInteractEvent args) + private void OnFeedFood(EntityUid uid, FoodComponent foodComponent, AfterInteractEvent args) { if (args.Handled || args.Target == null || !args.CanReach) return; - var result = TryFeed(args.User, args.Target.Value, entity, entity.Comp); + var result = TryFeed(args.User, args.Target.Value, uid, foodComponent); args.Handled = result.Handled; } @@ -109,7 +112,7 @@ public sealed class FoodSystem : EntitySystem if (_openable.IsClosed(food, user)) return (false, true); - if (!_solutionContainer.TryGetSolution(food, foodComp.Solution, out _, out var foodSolution)) + if (!_solutionContainer.TryGetSolution(food, foodComp.Solution, out var foodSolution) || foodSolution.Name == null) return (false, false); if (!_body.TryGetBodyOrganComponents(target, out var stomachs, body)) @@ -174,7 +177,7 @@ public sealed class FoodSystem : EntitySystem var doAfterArgs = new DoAfterArgs(EntityManager, user, forceFeed ? foodComp.ForceFeedDelay : foodComp.Delay, - new ConsumeDoAfterEvent(foodComp.Solution, flavors), + new ConsumeDoAfterEvent(foodSolution.Name, flavors), eventTarget: food, target: target, used: food) @@ -193,9 +196,9 @@ public sealed class FoodSystem : EntitySystem return (true, true); } - private void OnDoAfter(Entity entity, ref ConsumeDoAfterEvent args) + private void OnDoAfter(EntityUid uid, FoodComponent component, ConsumeDoAfterEvent args) { - if (args.Cancelled || args.Handled || entity.Comp.Deleted || args.Target == null) + if (args.Cancelled || args.Handled || component.Deleted || args.Target == null) return; if (!TryComp(args.Target.Value, out var body)) @@ -204,10 +207,10 @@ public sealed class FoodSystem : EntitySystem if (!_body.TryGetBodyOrganComponents(args.Target.Value, out var stomachs, body)) return; - if (args.Used is null || !_solutionContainer.TryGetSolution(args.Used.Value, args.Solution, out var soln, out var solution)) + if (!_solutionContainer.TryGetSolution(args.Used, args.Solution, out var solution)) return; - if (!TryGetRequiredUtensils(args.User, entity.Comp, out var utensils)) + if (!TryGetRequiredUtensils(args.User, component, out var utensils)) return; // TODO this should really be checked every tick. @@ -221,9 +224,9 @@ public sealed class FoodSystem : EntitySystem var forceFeed = args.User != args.Target; args.Handled = true; - var transferAmount = entity.Comp.TransferAmount != null ? FixedPoint2.Min((FixedPoint2) entity.Comp.TransferAmount, solution.Volume) : solution.Volume; + var transferAmount = component.TransferAmount != null ? FixedPoint2.Min((FixedPoint2) component.TransferAmount, solution.Volume) : solution.Volume; - var split = _solutionContainer.SplitSolution(soln.Value, transferAmount); + var split = _solutionContainer.SplitSolution(uid, solution, transferAmount); //TODO: Get the stomach UID somehow without nabbing owner // Get the stomach with the highest available solution volume @@ -232,10 +235,11 @@ public sealed class FoodSystem : EntitySystem foreach (var (stomach, _) in stomachs) { var owner = stomach.Owner; - if (!_stomach.CanTransferSolution(owner, split, stomach)) + if (!_stomach.CanTransferSolution(owner, split)) continue; - if (!_solutionContainer.ResolveSolution(owner, StomachSystem.DefaultSolutionName, ref stomach.Solution, out var stomachSol)) + if (!_solutionContainer.TryGetSolution(owner, StomachSystem.DefaultSolutionName, + out var stomachSol)) continue; if (stomachSol.AvailableVolume <= highestAvailable) @@ -248,7 +252,7 @@ public sealed class FoodSystem : EntitySystem // No stomach so just popup a message that they can't eat. if (stomachToUse == null) { - _solutionContainer.TryAddSolution(soln.Value, split); + _solutionContainer.TryAddSolution(uid, solution, split); _popup.PopupEntity(forceFeed ? Loc.GetString("food-system-you-cannot-eat-any-more-other") : Loc.GetString("food-system-you-cannot-eat-any-more"), args.Target.Value, args.User); return; } @@ -262,22 +266,23 @@ public sealed class FoodSystem : EntitySystem { var targetName = Identity.Entity(args.Target.Value, EntityManager); var userName = Identity.Entity(args.User, EntityManager); - _popup.PopupEntity(Loc.GetString("food-system-force-feed-success", ("user", userName), ("flavors", flavors)), entity.Owner, entity.Owner); + _popup.PopupEntity(Loc.GetString("food-system-force-feed-success", ("user", userName), ("flavors", flavors)), + uid, uid); _popup.PopupEntity(Loc.GetString("food-system-force-feed-success-user", ("target", targetName)), args.User, args.User); // log successful force feed - _adminLogger.Add(LogType.ForceFeed, LogImpact.Medium, $"{ToPrettyString(entity.Owner):user} forced {ToPrettyString(args.User):target} to eat {ToPrettyString(entity.Owner):food}"); + _adminLogger.Add(LogType.ForceFeed, LogImpact.Medium, $"{ToPrettyString(uid):user} forced {ToPrettyString(args.User):target} to eat {ToPrettyString(uid):food}"); } else { - _popup.PopupEntity(Loc.GetString(entity.Comp.EatMessage, ("food", entity.Owner), ("flavors", flavors)), args.User, args.User); + _popup.PopupEntity(Loc.GetString(component.EatMessage, ("food", uid), ("flavors", flavors)), args.User, args.User); // log successful voluntary eating - _adminLogger.Add(LogType.Ingestion, LogImpact.Low, $"{ToPrettyString(args.User):target} ate {ToPrettyString(entity.Owner):food}"); + _adminLogger.Add(LogType.Ingestion, LogImpact.Low, $"{ToPrettyString(args.User):target} ate {ToPrettyString(uid):food}"); } - _audio.PlayPvs(entity.Comp.UseSound, args.Target.Value, AudioParams.Default.WithVolume(-1f)); + _audio.PlayPvs(component.UseSound, args.Target.Value, AudioParams.Default.WithVolume(-1f)); // Try to break all used utensils foreach (var utensil in utensils) @@ -287,24 +292,24 @@ public sealed class FoodSystem : EntitySystem args.Repeat = !forceFeed; - if (TryComp(entity, out var stack)) + if (TryComp(uid, out var stack)) { //Not deleting whole stack piece will make troubles with grinding object if (stack.Count > 1) { - _stack.SetCount(entity.Owner, stack.Count - 1); - _solutionContainer.TryAddSolution(soln.Value, split); + _stack.SetCount(uid, stack.Count - 1); + _solutionContainer.TryAddSolution(uid, solution, split); return; } } - else if (GetUsesRemaining(entity.Owner, entity.Comp) > 0) + else if (GetUsesRemaining(uid, component) > 0) { return; } // don't try to repeat if its being deleted args.Repeat = false; - DeleteAndSpawnTrash(entity.Comp, entity.Owner, args.User); + DeleteAndSpawnTrash(component, uid, args.User); } public void DeleteAndSpawnTrash(FoodComponent component, EntityUid food, EntityUid user) @@ -340,9 +345,9 @@ public sealed class FoodSystem : EntitySystem QueueDel(food); } - private void AddEatVerb(Entity entity, ref GetVerbsEvent ev) + private void AddEatVerb(EntityUid uid, FoodComponent component, GetVerbsEvent ev) { - if (entity.Owner == ev.User || + if (uid == ev.User || !ev.CanInteract || !ev.CanAccess || !TryComp(ev.User, out var body) || @@ -350,21 +355,20 @@ public sealed class FoodSystem : EntitySystem return; // have to kill mouse before eating it - if (_mobState.IsAlive(entity) && entity.Comp.RequireDead) + if (_mobState.IsAlive(uid) && component.RequireDead) return; // only give moths eat verb for clothes since it would just fail otherwise - if (!IsDigestibleBy(entity, entity.Comp, stomachs)) + if (!IsDigestibleBy(uid, component, stomachs)) return; - var user = ev.User; AlternativeVerb verb = new() { Act = () => { - TryFeed(user, user, entity, entity.Comp); + TryFeed(ev.User, ev.User, uid, component); }, - Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/cutlery.svg.192dpi.png")), + Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/cutlery.svg.192dpi.png")), Text = Loc.GetString("food-system-verb-eat"), Priority = -1 }; @@ -412,7 +416,7 @@ public sealed class FoodSystem : EntitySystem } if (component.RequiresSpecialDigestion) - return false; + return false; return digestible; } @@ -458,14 +462,14 @@ public sealed class FoodSystem : EntitySystem /// /// Block ingestion attempts based on the equipped mask or head-wear /// - private void OnInventoryIngestAttempt(Entity entity, ref IngestionAttemptEvent args) + private void OnInventoryIngestAttempt(EntityUid uid, InventoryComponent component, IngestionAttemptEvent args) { if (args.Cancelled) return; IngestionBlockerComponent? blocker; - if (_inventory.TryGetSlotEntity(entity.Owner, "mask", out var maskUid) && + if (_inventory.TryGetSlotEntity(uid, "mask", out var maskUid) && TryComp(maskUid, out blocker) && blocker.Enabled) { @@ -474,7 +478,7 @@ public sealed class FoodSystem : EntitySystem return; } - if (_inventory.TryGetSlotEntity(entity.Owner, "head", out var headUid) && + if (_inventory.TryGetSlotEntity(uid, "head", out var headUid) && TryComp(headUid, out blocker) && blocker.Enabled) { @@ -512,7 +516,7 @@ public sealed class FoodSystem : EntitySystem if (!Resolve(uid, ref comp)) return 0; - if (!_solutionContainer.TryGetSolution(uid, comp.Solution, out _, out var solution) || solution.Volume == 0) + if (!_solutionContainer.TryGetSolution(uid, comp.Solution, out var solution) || solution.Volume == 0) return 0; // eat all in 1 go, so non empty is 1 bite diff --git a/Content.Server/Nutrition/EntitySystems/SliceableFoodSystem.cs b/Content.Server/Nutrition/EntitySystems/SliceableFoodSystem.cs index 064d316bef..56f5d9adeb 100644 --- a/Content.Server/Nutrition/EntitySystems/SliceableFoodSystem.cs +++ b/Content.Server/Nutrition/EntitySystems/SliceableFoodSystem.cs @@ -1,6 +1,7 @@ -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Nutrition.Components; using Content.Shared.Chemistry.Components; +using Content.Shared.Chemistry.Components.SolutionManager; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Examine; using Content.Shared.FixedPoint; using Content.Shared.Hands.EntitySystems; @@ -8,6 +9,7 @@ using Content.Shared.Interaction; using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; using Robust.Shared.Containers; +using Robust.Shared.Player; namespace Content.Server.Nutrition.EntitySystems { @@ -27,12 +29,12 @@ namespace Content.Server.Nutrition.EntitySystems SubscribeLocalEvent(OnComponentStartup); } - private void OnInteractUsing(Entity entity, ref InteractUsingEvent args) + private void OnInteractUsing(EntityUid uid, SliceableFoodComponent component, InteractUsingEvent args) { if (args.Handled) return; - if (TrySliceFood(entity, args.User, args.Used, entity.Comp)) + if (TrySliceFood(uid, args.User, args.Used, component)) args.Handled = true; } @@ -45,7 +47,7 @@ namespace Content.Server.Nutrition.EntitySystems return false; } - if (!_solutionContainerSystem.TryGetSolution(uid, food.Solution, out var soln, out var solution)) + if (!_solutionContainerSystem.TryGetSolution(uid, food.Solution, out var solution)) { return false; } @@ -57,7 +59,8 @@ namespace Content.Server.Nutrition.EntitySystems var sliceUid = Slice(uid, user, component, transform); - var lostSolution = _solutionContainerSystem.SplitSolution(soln.Value, solution.Volume / FixedPoint2.New(component.Count)); + var lostSolution = _solutionContainerSystem.SplitSolution(uid, solution, + solution.Volume / FixedPoint2.New(component.Count)); // Fill new slice FillSlice(sliceUid, lostSolution); @@ -134,26 +137,27 @@ namespace Content.Server.Nutrition.EntitySystems { // Replace all reagents on prototype not just copying poisons (example: slices of eaten pizza should have less nutrition) if (TryComp(sliceUid, out var sliceFoodComp) && - _solutionContainerSystem.TryGetSolution(sliceUid, sliceFoodComp.Solution, out var itsSoln, out var itsSolution)) + _solutionContainerSystem.TryGetSolution(sliceUid, sliceFoodComp.Solution, out var itsSolution)) { - _solutionContainerSystem.RemoveAllSolution(itsSoln.Value); + _solutionContainerSystem.RemoveAllSolution(sliceUid, itsSolution); var lostSolutionPart = solution.SplitSolution(itsSolution.AvailableVolume); - _solutionContainerSystem.TryAddSolution(itsSoln.Value, lostSolutionPart); + _solutionContainerSystem.TryAddSolution(sliceUid, itsSolution, lostSolutionPart); } } - private void OnComponentStartup(Entity entity, ref ComponentStartup args) + private void OnComponentStartup(EntityUid uid, SliceableFoodComponent component, ComponentStartup args) { - entity.Comp.Count = entity.Comp.TotalCount; + component.Count = component.TotalCount; + var foodComp = EnsureComp(uid); - var foodComp = EnsureComp(entity); - _solutionContainerSystem.EnsureSolution(entity.Owner, foodComp.Solution); + EnsureComp(uid); + _solutionContainerSystem.EnsureSolution(uid, foodComp.Solution); } - private void OnExamined(Entity entity, ref ExaminedEvent args) + private void OnExamined(EntityUid uid, SliceableFoodComponent component, ExaminedEvent args) { - args.PushMarkup(Loc.GetString("sliceable-food-component-on-examine-remaining-slices-text", ("remainingCount", entity.Comp.Count))); + args.PushMarkup(Loc.GetString("sliceable-food-component-on-examine-remaining-slices-text", ("remainingCount", component.Count))); } } } diff --git a/Content.Server/Nutrition/EntitySystems/SmokingSystem.Cigar.cs b/Content.Server/Nutrition/EntitySystems/SmokingSystem.Cigar.cs index 4e672444d1..99a96fd2b3 100644 --- a/Content.Server/Nutrition/EntitySystems/SmokingSystem.Cigar.cs +++ b/Content.Server/Nutrition/EntitySystems/SmokingSystem.Cigar.cs @@ -1,6 +1,6 @@ using Content.Server.Nutrition.Components; -using Content.Shared.Interaction; using Content.Shared.Nutrition.Components; +using Content.Shared.Interaction; using Content.Shared.Smoking; using Content.Shared.Temperature; @@ -16,27 +16,27 @@ namespace Content.Server.Nutrition.EntitySystems SubscribeLocalEvent(OnCigarAfterInteract); } - private void OnCigarActivatedEvent(Entity entity, ref ActivateInWorldEvent args) + private void OnCigarActivatedEvent(EntityUid uid, CigarComponent component, ActivateInWorldEvent args) { if (args.Handled) return; - if (!EntityManager.TryGetComponent(entity, out SmokableComponent? smokable)) + if (!EntityManager.TryGetComponent(uid, out SmokableComponent? smokable)) return; if (smokable.State != SmokableState.Lit) return; - SetSmokableState(entity, SmokableState.Burnt, smokable); + SetSmokableState(uid, SmokableState.Burnt, smokable); args.Handled = true; } - private void OnCigarInteractUsingEvent(Entity entity, ref InteractUsingEvent args) + private void OnCigarInteractUsingEvent(EntityUid uid, CigarComponent component, InteractUsingEvent args) { if (args.Handled) return; - if (!EntityManager.TryGetComponent(entity, out SmokableComponent? smokable)) + if (!EntityManager.TryGetComponent(uid, out SmokableComponent? smokable)) return; if (smokable.State != SmokableState.Unlit) @@ -48,16 +48,16 @@ namespace Content.Server.Nutrition.EntitySystems if (!isHotEvent.IsHot) return; - SetSmokableState(entity, SmokableState.Lit, smokable); + SetSmokableState(uid, SmokableState.Lit, smokable); args.Handled = true; } - public void OnCigarAfterInteract(Entity entity, ref AfterInteractEvent args) + public void OnCigarAfterInteract(EntityUid uid, CigarComponent component, AfterInteractEvent args) { var targetEntity = args.Target; if (targetEntity == null || !args.CanReach || - !EntityManager.TryGetComponent(entity, out SmokableComponent? smokable) || + !EntityManager.TryGetComponent(uid, out SmokableComponent? smokable) || smokable.State == SmokableState.Lit) return; @@ -67,13 +67,13 @@ namespace Content.Server.Nutrition.EntitySystems if (!isHotEvent.IsHot) return; - SetSmokableState(entity, SmokableState.Lit, smokable); + SetSmokableState(uid, SmokableState.Lit, smokable); args.Handled = true; } - private void OnCigarSolutionEmptyEvent(Entity entity, ref SmokableSolutionEmptyEvent args) + private void OnCigarSolutionEmptyEvent(EntityUid uid, CigarComponent component, SmokableSolutionEmptyEvent args) { - SetSmokableState(entity, SmokableState.Burnt); + SetSmokableState(uid, SmokableState.Burnt); } } } diff --git a/Content.Server/Nutrition/EntitySystems/SmokingSystem.SmokingPipe.cs b/Content.Server/Nutrition/EntitySystems/SmokingSystem.SmokingPipe.cs index 3950c73eb4..772847e8df 100644 --- a/Content.Server/Nutrition/EntitySystems/SmokingSystem.SmokingPipe.cs +++ b/Content.Server/Nutrition/EntitySystems/SmokingSystem.SmokingPipe.cs @@ -1,8 +1,8 @@ using Content.Server.Nutrition.Components; +using Content.Shared.Nutrition.Components; using Content.Shared.Chemistry.Components.SolutionManager; using Content.Shared.Containers.ItemSlots; using Content.Shared.Interaction; -using Content.Shared.Nutrition.Components; using Content.Shared.Smoking; using Content.Shared.Temperature; @@ -20,17 +20,17 @@ namespace Content.Server.Nutrition.EntitySystems SubscribeLocalEvent(OnComponentInit); } - public void OnComponentInit(Entity entity, ref ComponentInit args) + public void OnComponentInit(EntityUid uid, SmokingPipeComponent pipe, ComponentInit args) { - _itemSlotsSystem.AddItemSlot(entity, SmokingPipeComponent.BowlSlotId, entity.Comp.BowlSlot); + _itemSlotsSystem.AddItemSlot(uid, SmokingPipeComponent.BowlSlotId, pipe.BowlSlot); } - private void OnPipeInteractUsingEvent(Entity entity, ref InteractUsingEvent args) + private void OnPipeInteractUsingEvent(EntityUid uid, SmokingPipeComponent component, InteractUsingEvent args) { if (args.Handled) return; - if (!EntityManager.TryGetComponent(entity, out SmokableComponent? smokable)) + if (!EntityManager.TryGetComponent(uid, out SmokableComponent? smokable)) return; if (smokable.State != SmokableState.Unlit) @@ -42,17 +42,17 @@ namespace Content.Server.Nutrition.EntitySystems if (!isHotEvent.IsHot) return; - if (TryTransferReagents(entity.Comp, smokable)) - SetSmokableState(entity, SmokableState.Lit, smokable); + if (TryTransferReagents(component, smokable)) + SetSmokableState(uid, SmokableState.Lit, smokable); args.Handled = true; } - public void OnPipeAfterInteract(Entity entity, ref AfterInteractEvent args) + public void OnPipeAfterInteract(EntityUid uid, SmokingPipeComponent component, AfterInteractEvent args) { var targetEntity = args.Target; if (targetEntity == null || !args.CanReach || - !EntityManager.TryGetComponent(entity, out SmokableComponent? smokable) || + !EntityManager.TryGetComponent(uid, out SmokableComponent? smokable) || smokable.State == SmokableState.Lit) return; @@ -62,15 +62,15 @@ namespace Content.Server.Nutrition.EntitySystems if (!isHotEvent.IsHot) return; - if (TryTransferReagents(entity.Comp, smokable)) - SetSmokableState(entity, SmokableState.Lit, smokable); + if(TryTransferReagents(component, smokable)) + SetSmokableState(uid, SmokableState.Lit, smokable); args.Handled = true; } - private void OnPipeSolutionEmptyEvent(Entity entity, ref SmokableSolutionEmptyEvent args) + private void OnPipeSolutionEmptyEvent(EntityUid uid, SmokingPipeComponent component, SmokableSolutionEmptyEvent args) { - _itemSlotsSystem.SetLock(entity, entity.Comp.BowlSlot, false); - SetSmokableState(entity, SmokableState.Unlit); + _itemSlotsSystem.SetLock(component.Owner, component.BowlSlot, false); + SetSmokableState(uid, SmokableState.Unlit); } // Convert smokable item into reagents to be smoked @@ -82,13 +82,12 @@ namespace Content.Server.Nutrition.EntitySystems EntityUid contents = component.BowlSlot.Item.Value; if (!TryComp(contents, out var reagents) || - !_solutionContainerSystem.TryGetSolution(smokable.Owner, smokable.Solution, out var pipeSolution, out _)) + !_solutionContainerSystem.TryGetSolution(smokable.Owner, smokable.Solution, out var pipeSolution)) return false; - foreach (var (_, soln) in _solutionContainerSystem.EnumerateSolutions((contents, reagents))) + foreach (var reagentSolution in reagents.Solutions) { - var reagentSolution = soln.Comp.Solution; - _solutionContainerSystem.TryAddSolution(pipeSolution.Value, reagentSolution); + _solutionContainerSystem.TryAddSolution(smokable.Owner, pipeSolution, reagentSolution.Value); } EntityManager.DeleteEntity(contents); diff --git a/Content.Server/Nutrition/EntitySystems/SmokingSystem.Vape.cs b/Content.Server/Nutrition/EntitySystems/SmokingSystem.Vape.cs index fe0d1d0c16..4dd9aff9ac 100644 --- a/Content.Server/Nutrition/EntitySystems/SmokingSystem.Vape.cs +++ b/Content.Server/Nutrition/EntitySystems/SmokingSystem.Vape.cs @@ -1,18 +1,18 @@ -using Content.Server.Atmos; -using Content.Server.Atmos.EntitySystems; -using Content.Server.Body.Components; -using Content.Server.DoAfter; -using Content.Server.Explosion.EntitySystems; using Content.Server.Nutrition.Components; -using Content.Server.Popups; -using Content.Shared.Damage; -using Content.Shared.DoAfter; -using Content.Shared.Emag.Components; -using Content.Shared.Emag.Systems; -using Content.Shared.IdentityManagement; +using Content.Server.Body.Components; using Content.Shared.Interaction; -using Content.Shared.Nutrition; +using Content.Server.DoAfter; using System.Threading; +using Content.Server.Explosion.EntitySystems; +using Content.Shared.Damage; +using Content.Server.Popups; +using Content.Shared.IdentityManagement; +using Content.Shared.DoAfter; +using Content.Shared.Emag.Systems; +using Content.Shared.Emag.Components; +using Content.Shared.Nutrition; +using Content.Server.Atmos.EntitySystems; +using Content.Server.Atmos; /// /// System for vapes @@ -35,14 +35,16 @@ namespace Content.Server.Nutrition.EntitySystems SubscribeLocalEvent(OnEmagged); } - private void OnVapeInteraction(Entity entity, ref AfterInteractEvent args) + private void OnVapeInteraction(EntityUid uid, VapeComponent comp, AfterInteractEvent args) { - var delay = entity.Comp.Delay; + _solutionContainerSystem.TryGetRefillableSolution(uid, out var solution); + + var delay = comp.Delay; var forced = true; var exploded = false; if (!args.CanReach - || !_solutionContainerSystem.TryGetRefillableSolution(entity.Owner, out _, out var solution) + || solution == null || !HasComp(args.Target) || _foodSystem.IsMouthBlocked(args.Target.Value, args.User)) { @@ -59,14 +61,14 @@ namespace Content.Server.Nutrition.EntitySystems if (args.Target == args.User) { - delay = entity.Comp.UserDelay; + delay = comp.UserDelay; forced = false; } - if (entity.Comp.ExplodeOnUse || HasComp(entity.Owner)) + if (comp.ExplodeOnUse || HasComp(uid)) { - _explosionSystem.QueueExplosion(entity.Owner, "Default", entity.Comp.ExplosionIntensity, 0.5f, 3, canCreateVacuum: false); - EntityManager.DeleteEntity(entity); + _explosionSystem.QueueExplosion(uid, "Default", comp.ExplosionIntensity, 0.5f, 3, canCreateVacuum: false); + EntityManager.DeleteEntity(uid); exploded = true; } else @@ -78,11 +80,11 @@ namespace Content.Server.Nutrition.EntitySystems // just re-use the existing RiggableSystem. foreach (var name in solution.Contents) { - if (name.Reagent.Prototype != entity.Comp.SolutionNeeded) + if (name.Reagent.Prototype != comp.SolutionNeeded) { exploded = true; - _explosionSystem.QueueExplosion(entity.Owner, "Default", entity.Comp.ExplosionIntensity, 0.5f, 3, canCreateVacuum: false); - EntityManager.DeleteEntity(entity); + _explosionSystem.QueueExplosion(uid, "Default", comp.ExplosionIntensity, 0.5f, 3, canCreateVacuum: false); + EntityManager.DeleteEntity(uid); break; } } @@ -111,7 +113,7 @@ namespace Content.Server.Nutrition.EntitySystems if (!exploded) { var vapeDoAfterEvent = new VapeDoAfterEvent(solution, forced); - _doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager, args.User, delay, vapeDoAfterEvent, entity.Owner, target: args.Target, used: entity.Owner) + _doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager, args.User, delay, vapeDoAfterEvent, uid, target: args.Target, used: uid) { BreakOnTargetMove = true, BreakOnUserMove = false, @@ -119,9 +121,9 @@ namespace Content.Server.Nutrition.EntitySystems }); } args.Handled = true; - } + } - private void OnVapeDoAfter(Entity entity, ref VapeDoAfterEvent args) + private void OnVapeDoAfter(EntityUid uid, VapeComponent comp, VapeDoAfterEvent args) { if (args.Handled || args.Args.Target == null) @@ -134,10 +136,10 @@ namespace Content.Server.Nutrition.EntitySystems } //Smoking kills(your lungs, but there is no organ damage yet) - _damageableSystem.TryChangeDamage(args.Args.Target.Value, entity.Comp.Damage, true); + _damageableSystem.TryChangeDamage(args.Args.Target.Value, comp.Damage, true); - var merger = new GasMixture(1) { Temperature = args.Solution.Temperature }; - merger.SetMoles(entity.Comp.GasType, args.Solution.Volume.Value / entity.Comp.ReductionFactor); + var merger = new GasMixture(1) { Temperature = args.Solution.Temperature}; + merger.SetMoles(comp.GasType, args.Solution.Volume.Value / comp.ReductionFactor); _atmosphereSystem.Merge(environment, merger); @@ -163,9 +165,9 @@ namespace Content.Server.Nutrition.EntitySystems args.Args.Target.Value); } } - private void OnEmagged(Entity entity, ref GotEmaggedEvent args) + private void OnEmagged(EntityUid uid, VapeComponent component, ref GotEmaggedEvent args) { args.Handled = true; } - } + } } diff --git a/Content.Server/Nutrition/EntitySystems/SmokingSystem.cs b/Content.Server/Nutrition/EntitySystems/SmokingSystem.cs index a33c944c99..63a558238b 100644 --- a/Content.Server/Nutrition/EntitySystems/SmokingSystem.cs +++ b/Content.Server/Nutrition/EntitySystems/SmokingSystem.cs @@ -1,22 +1,22 @@ using Content.Server.Atmos.EntitySystems; using Content.Server.Body.Components; using Content.Server.Body.Systems; -using Content.Server.Chemistry.Containers.EntitySystems; -using Content.Server.Forensics; +using Content.Shared.Nutrition.Components; using Content.Shared.Chemistry; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Chemistry.Reagent; using Content.Shared.Clothing.Components; using Content.Shared.Clothing.EntitySystems; using Content.Shared.FixedPoint; using Content.Shared.Inventory; -using Content.Shared.Inventory.Events; using Content.Shared.Item; -using Content.Shared.Nutrition.Components; using Content.Shared.Smoking; using Content.Shared.Temperature; using Robust.Server.GameObjects; using Robust.Shared.Containers; using System.Linq; +using Content.Shared.Inventory.Events; +using Content.Server.Forensics; namespace Content.Server.Nutrition.EntitySystems { @@ -79,21 +79,21 @@ namespace Content.Server.Nutrition.EntitySystems _active.Remove(uid); } - private void OnSmokableIsHotEvent(Entity entity, ref IsHotEvent args) + private void OnSmokableIsHotEvent(EntityUid uid, SmokableComponent component, IsHotEvent args) { - args.IsHot = entity.Comp.State == SmokableState.Lit; + args.IsHot = component.State == SmokableState.Lit; } - private void OnSmokableShutdownEvent(Entity entity, ref ComponentShutdown args) + private void OnSmokableShutdownEvent(EntityUid uid, SmokableComponent component, ComponentShutdown args) { - _active.Remove(entity); + _active.Remove(uid); } - private void OnSmokeableEquipEvent(Entity entity, ref GotEquippedEvent args) + private void OnSmokeableEquipEvent(EntityUid uid, SmokableComponent component, GotEquippedEvent args) { if (args.Slot == "mask") { - _forensics.TransferDna(entity.Owner, args.Equipee, false); + _forensics.TransferDna(uid, args.Equipee, false); } } @@ -113,7 +113,7 @@ namespace Content.Server.Nutrition.EntitySystems continue; } - if (!_solutionContainerSystem.TryGetSolution(uid, smokable.Solution, out var soln, out var solution)) + if (!_solutionContainerSystem.TryGetSolution(uid, smokable.Solution, out var solution)) { _active.Remove(uid); continue; @@ -123,14 +123,14 @@ namespace Content.Server.Nutrition.EntitySystems { var transform = Transform(uid); - if (transform.GridUid is { } gridUid) + if (transform.GridUid is {} gridUid) { var position = _transformSystem.GetGridOrMapTilePosition(uid, transform); _atmos.HotspotExpose(gridUid, position, smokable.ExposeTemperature, smokable.ExposeVolume, uid, true); } } - var inhaledSolution = _solutionContainerSystem.SplitSolution(soln.Value, smokable.InhaleAmount * _timer); + var inhaledSolution = _solutionContainerSystem.SplitSolution(uid, solution, smokable.InhaleAmount * _timer); if (solution.Volume == FixedPoint2.Zero) { diff --git a/Content.Server/Nutrition/EntitySystems/TrashOnSolutionEmptySystem.cs b/Content.Server/Nutrition/EntitySystems/TrashOnSolutionEmptySystem.cs index 249c6b5239..22360b6492 100644 --- a/Content.Server/Nutrition/EntitySystems/TrashOnSolutionEmptySystem.cs +++ b/Content.Server/Nutrition/EntitySystems/TrashOnSolutionEmptySystem.cs @@ -1,4 +1,3 @@ -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Nutrition.Components; using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Components.SolutionManager; @@ -16,37 +15,37 @@ namespace Content.Server.Nutrition.EntitySystems { base.Initialize(); SubscribeLocalEvent(OnStartup); - SubscribeLocalEvent(OnSolutionChange); + SubscribeLocalEvent(OnSolutionChange); } - public void OnStartup(Entity entity, ref ComponentStartup args) + public void OnStartup(EntityUid uid, TrashOnSolutionEmptyComponent component, ComponentStartup args) { - CheckSolutions(entity); + CheckSolutions(component); } - public void OnSolutionChange(Entity entity, ref SolutionContainerChangedEvent args) + public void OnSolutionChange(EntityUid uid, TrashOnSolutionEmptyComponent component, SolutionChangedEvent args) { - CheckSolutions(entity); + CheckSolutions(component); } - public void CheckSolutions(Entity entity) + public void CheckSolutions(TrashOnSolutionEmptyComponent component) { - if (!EntityManager.HasComponent(entity)) + if (!EntityManager.HasComponent((component).Owner)) return; - if (_solutionContainerSystem.TryGetSolution(entity.Owner, entity.Comp.Solution, out _, out var solution)) - UpdateTags(entity, solution); + if (_solutionContainerSystem.TryGetSolution(component.Owner, component.Solution, out var solution)) + UpdateTags(component, solution); } - public void UpdateTags(Entity entity, Solution solution) + public void UpdateTags(TrashOnSolutionEmptyComponent component, Solution solution) { if (solution.Volume <= 0) { - _tagSystem.AddTag(entity.Owner, "Trash"); + _tagSystem.AddTag(component.Owner, "Trash"); return; } - if (_tagSystem.HasTag(entity.Owner, "Trash")) - _tagSystem.RemoveTag(entity.Owner, "Trash"); + if (_tagSystem.HasTag(component.Owner, "Trash")) + _tagSystem.RemoveTag(component.Owner, "Trash"); } } } diff --git a/Content.Server/Payload/EntitySystems/PayloadSystem.cs b/Content.Server/Payload/EntitySystems/PayloadSystem.cs index 78a2de22d1..f57024087d 100644 --- a/Content.Server/Payload/EntitySystems/PayloadSystem.cs +++ b/Content.Server/Payload/EntitySystems/PayloadSystem.cs @@ -1,7 +1,8 @@ +using System.Linq; using Content.Server.Administration.Logs; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Explosion.EntitySystems; using Content.Shared.Chemistry.Components; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Database; using Content.Shared.Examine; using Content.Shared.Payload.Components; @@ -9,15 +10,14 @@ using Content.Shared.Tag; using Robust.Shared.Containers; using Robust.Shared.Serialization.Manager; using Robust.Shared.Utility; -using System.Linq; namespace Content.Server.Payload.EntitySystems; public sealed class PayloadSystem : EntitySystem { [Dependency] private readonly TagSystem _tagSystem = default!; - [Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!; - [Dependency] private readonly IAdminLogManager _adminLogger = default!; + [Dependency] private readonly SolutionContainerSystem _solutionSystem = default!; + [Dependency] private readonly IAdminLogManager _adminLogger= default!; [Dependency] private readonly IComponentFactory _componentFactory = default!; [Dependency] private readonly ISerializationManager _serializationManager = default!; @@ -33,7 +33,7 @@ public sealed class PayloadSystem : EntitySystem SubscribeLocalEvent(HandleChemicalPayloadTrigger); } - public IEnumerable GetAllPayloads(EntityUid uid, ContainerManagerComponent? contMan = null) + public IEnumerable GetAllPayloads(EntityUid uid, ContainerManagerComponent? contMan=null) { if (!Resolve(uid, ref contMan, false)) yield break; @@ -98,7 +98,7 @@ public sealed class PayloadSystem : EntitySystem var temp = (object) component; _serializationManager.CopyTo(data.Component, ref temp); - EntityManager.AddComponent(uid, (Component) temp!); + EntityManager.AddComponent(uid, (Component)temp!); trigger.GrantedComponents.Add(registration.Type); } @@ -137,14 +137,14 @@ public sealed class PayloadSystem : EntitySystem } } - private void HandleChemicalPayloadTrigger(Entity entity, ref TriggerEvent args) + private void HandleChemicalPayloadTrigger(EntityUid uid, ChemicalPayloadComponent component, TriggerEvent args) { - if (entity.Comp.BeakerSlotA.Item is not EntityUid beakerA - || entity.Comp.BeakerSlotB.Item is not EntityUid beakerB + if (component.BeakerSlotA.Item is not EntityUid beakerA + || component.BeakerSlotB.Item is not EntityUid beakerB || !TryComp(beakerA, out FitsInDispenserComponent? compA) || !TryComp(beakerB, out FitsInDispenserComponent? compB) - || !_solutionContainerSystem.TryGetSolution(beakerA, compA.Solution, out var solnA, out var solutionA) - || !_solutionContainerSystem.TryGetSolution(beakerB, compB.Solution, out var solnB, out var solutionB) + || !_solutionSystem.TryGetSolution(beakerA, compA.Solution, out var solutionA) + || !_solutionSystem.TryGetSolution(beakerB, compB.Solution, out var solutionB) || solutionA.Volume == 0 || solutionB.Volume == 0) { @@ -155,17 +155,17 @@ public sealed class PayloadSystem : EntitySystem var solStringB = SolutionContainerSystem.ToPrettyString(solutionB); _adminLogger.Add(LogType.ChemicalReaction, - $"Chemical bomb payload {ToPrettyString(entity.Owner):payload} at {Transform(entity.Owner).MapPosition:location} is combining two solutions: {solStringA:solutionA} and {solStringB:solutionB}"); + $"Chemical bomb payload {ToPrettyString(uid):payload} at {Transform(uid).MapPosition:location} is combining two solutions: {solStringA:solutionA} and {solStringB:solutionB}"); solutionA.MaxVolume += solutionB.MaxVolume; - _solutionContainerSystem.TryAddSolution(solnA.Value, solutionB); - _solutionContainerSystem.RemoveAllSolution(solnB.Value); + _solutionSystem.TryAddSolution(beakerA, solutionA, solutionB); + _solutionSystem.RemoveAllSolution(beakerB, solutionB); // The grenade might be a dud. Redistribute solution: - var tmpSol = _solutionContainerSystem.SplitSolution(solnA.Value, solutionA.Volume * solutionB.MaxVolume / solutionA.MaxVolume); - _solutionContainerSystem.TryAddSolution(solnB.Value, tmpSol); + var tmpSol = _solutionSystem.SplitSolution(beakerA, solutionA, solutionA.Volume * solutionB.MaxVolume / solutionA.MaxVolume); + _solutionSystem.TryAddSolution(beakerB, solutionB, tmpSol); solutionA.MaxVolume -= solutionB.MaxVolume; - _solutionContainerSystem.UpdateChemicals(solnA.Value); + _solutionSystem.UpdateChemicals(beakerA, solutionA, false); args.Handled = true; } diff --git a/Content.Server/Power/EntitySystems/RiggableSystem.cs b/Content.Server/Power/EntitySystems/RiggableSystem.cs index 26eaca80fe..995aeb7700 100644 --- a/Content.Server/Power/EntitySystems/RiggableSystem.cs +++ b/Content.Server/Power/EntitySystems/RiggableSystem.cs @@ -13,6 +13,7 @@ namespace Content.Server.Power.EntitySystems; /// public sealed class RiggableSystem : EntitySystem { + [Dependency] private readonly SolutionContainerSystem _solutionsSystem = default!; [Dependency] private readonly ExplosionSystem _explosionSystem = default!; [Dependency] private readonly IAdminLogManager _adminLogger = default!; @@ -21,17 +22,17 @@ public sealed class RiggableSystem : EntitySystem base.Initialize(); SubscribeLocalEvent(OnRejuvenate); SubscribeLocalEvent(OnMicrowaved); - SubscribeLocalEvent(OnSolutionChanged); + SubscribeLocalEvent(OnSolutionChanged); } - private void OnRejuvenate(Entity entity, ref RejuvenateEvent args) + private void OnRejuvenate(EntityUid uid, RiggableComponent component, RejuvenateEvent args) { - entity.Comp.IsRigged = false; + component.IsRigged = false; } - private void OnMicrowaved(Entity entity, ref BeingMicrowavedEvent args) + private void OnMicrowaved(EntityUid uid, RiggableComponent component, BeingMicrowavedEvent args) { - if (TryComp(entity, out var batteryComponent)) + if (TryComp(uid, out var batteryComponent)) { if (batteryComponent.CurrentCharge == 0) return; @@ -40,21 +41,21 @@ public sealed class RiggableSystem : EntitySystem args.Handled = true; // What the fuck are you doing??? - Explode(entity.Owner, batteryComponent, args.User); + Explode(uid, batteryComponent, args.User); } - private void OnSolutionChanged(Entity entity, ref SolutionContainerChangedEvent args) + private void OnSolutionChanged(EntityUid uid, RiggableComponent component, SolutionChangedEvent args) { - if (args.SolutionId != entity.Comp.Solution) + if (args.SolutionId != component.Solution) return; - var wasRigged = entity.Comp.IsRigged; - var quantity = args.Solution.GetReagentQuantity(entity.Comp.RequiredQuantity.Reagent); - entity.Comp.IsRigged = quantity >= entity.Comp.RequiredQuantity.Quantity; + var wasRigged = component.IsRigged; + var quantity = args.Solution.GetReagentQuantity(component.RequiredQuantity.Reagent); + component.IsRigged = quantity >= component.RequiredQuantity.Quantity; - if (entity.Comp.IsRigged && !wasRigged) + if (component.IsRigged && !wasRigged) { - _adminLogger.Add(LogType.Explosion, LogImpact.Medium, $"{ToPrettyString(entity.Owner)} has been rigged up to explode when used."); + _adminLogger.Add(LogType.Explosion, LogImpact.Medium, $"{ToPrettyString(uid)} has been rigged up to explode when used."); } } diff --git a/Content.Server/Power/Generator/ChemicalFuelGeneratorAdapterComponent.cs b/Content.Server/Power/Generator/ChemicalFuelGeneratorAdapterComponent.cs index 20d7149332..abaf1c4d94 100644 --- a/Content.Server/Power/Generator/ChemicalFuelGeneratorAdapterComponent.cs +++ b/Content.Server/Power/Generator/ChemicalFuelGeneratorAdapterComponent.cs @@ -1,5 +1,5 @@ -using Content.Shared.Chemistry.Components; -using Content.Shared.Chemistry.Components.SolutionManager; +using Content.Shared.Chemistry.Components.SolutionManager; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Chemistry.Reagent; using Content.Shared.FixedPoint; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; @@ -20,17 +20,11 @@ public sealed partial class ChemicalFuelGeneratorAdapterComponent : Component public string Reagent = "WeldingFuel"; /// - /// The name of . + /// The solution on the to use. /// [DataField("solution")] [ViewVariables(VVAccess.ReadWrite)] - public string SolutionName = "tank"; - - /// - /// The solution on the to use. - /// - [DataField("solutionRef")] - public Entity? Solution = null; + public string Solution = "tank"; /// /// Value to multiply reagent amount by to get fuel amount. diff --git a/Content.Server/Power/Generator/GeneratorSystem.cs b/Content.Server/Power/Generator/GeneratorSystem.cs index a23b0b8eed..7d88061f62 100644 --- a/Content.Server/Power/Generator/GeneratorSystem.cs +++ b/Content.Server/Power/Generator/GeneratorSystem.cs @@ -1,10 +1,10 @@ using Content.Server.Audio; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Fluids.EntitySystems; using Content.Server.Materials; using Content.Server.Popups; using Content.Server.Power.Components; using Content.Server.Power.EntitySystems; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.FixedPoint; using Content.Shared.Popups; using Content.Shared.Power.Generator; @@ -65,23 +65,23 @@ public sealed class GeneratorSystem : SharedGeneratorSystem _materialStorage.EjectAllMaterial(uid); } - private void ChemicalEmpty(Entity entity, ref GeneratorEmpty args) + private void ChemicalEmpty(EntityUid uid, ChemicalFuelGeneratorAdapterComponent component, GeneratorEmpty args) { - if (!_solutionContainer.ResolveSolution(entity.Owner, entity.Comp.SolutionName, ref entity.Comp.Solution, out var solution)) + if (!_solutionContainer.TryGetSolution(uid, component.Solution, out var solution)) return; - var spillSolution = _solutionContainer.SplitSolution(entity.Comp.Solution.Value, solution.Volume); - _puddle.TrySpillAt(entity.Owner, spillSolution, out _); + var spillSolution = _solutionContainer.SplitSolution(uid, solution, solution.Volume); + _puddle.TrySpillAt(uid, spillSolution, out _); } - private void ChemicalGetClogged(Entity entity, ref GeneratorGetCloggedEvent args) + private void ChemicalGetClogged(EntityUid uid, ChemicalFuelGeneratorAdapterComponent component, ref GeneratorGetCloggedEvent args) { - if (!_solutionContainer.ResolveSolution(entity.Owner, entity.Comp.SolutionName, ref entity.Comp.Solution, out var solution)) + if (!_solutionContainer.TryGetSolution(uid, component.Solution, out var solution)) return; foreach (var reagentQuantity in solution) { - if (reagentQuantity.Reagent.Prototype != entity.Comp.Reagent) + if (reagentQuantity.Reagent.Prototype != component.Reagent) { args.Clogged = true; return; @@ -89,29 +89,32 @@ public sealed class GeneratorSystem : SharedGeneratorSystem } } - private void ChemicalUseFuel(Entity entity, ref GeneratorUseFuel args) + private void ChemicalUseFuel(EntityUid uid, ChemicalFuelGeneratorAdapterComponent component, GeneratorUseFuel args) { - if (!_solutionContainer.ResolveSolution(entity.Owner, entity.Comp.SolutionName, ref entity.Comp.Solution, out var solution)) + if (!_solutionContainer.TryGetSolution(uid, component.Solution, out var solution)) return; - var availableReagent = solution.GetTotalPrototypeQuantity(entity.Comp.Reagent).Value; + var availableReagent = solution.GetTotalPrototypeQuantity(component.Reagent).Value; var toRemove = RemoveFractionalFuel( - ref entity.Comp.FractionalReagent, + ref component.FractionalReagent, args.FuelUsed, - entity.Comp.Multiplier * FixedPoint2.Epsilon.Float(), + component.Multiplier * FixedPoint2.Epsilon.Float(), availableReagent); - _solutionContainer.RemoveReagent(entity.Comp.Solution.Value, entity.Comp.Reagent, FixedPoint2.FromCents(toRemove)); + solution.RemoveReagent(component.Reagent, FixedPoint2.FromCents(toRemove)); } - private void ChemicalGetFuel(Entity entity, ref GeneratorGetFuelEvent args) + private void ChemicalGetFuel( + EntityUid uid, + ChemicalFuelGeneratorAdapterComponent component, + ref GeneratorGetFuelEvent args) { - if (!_solutionContainer.ResolveSolution(entity.Owner, entity.Comp.SolutionName, ref entity.Comp.Solution, out var solution)) + if (!_solutionContainer.TryGetSolution(uid, component.Solution, out var solution)) return; - var availableReagent = solution.GetTotalPrototypeQuantity(entity.Comp.Reagent).Float(); - var reagent = entity.Comp.FractionalReagent * FixedPoint2.Epsilon.Float() + availableReagent; - args.Fuel = reagent * entity.Comp.Multiplier; + var availableReagent = solution.GetTotalPrototypeQuantity(component.Reagent).Float(); + var reagent = component.FractionalReagent * FixedPoint2.Epsilon.Float() + availableReagent; + args.Fuel = reagent * component.Multiplier; } private void SolidUseFuel(EntityUid uid, SolidFuelGeneratorAdapterComponent component, GeneratorUseFuel args) diff --git a/Content.Server/Stunnable/Systems/StunbatonSystem.cs b/Content.Server/Stunnable/Systems/StunbatonSystem.cs index 8064434031..2ed30d8942 100644 --- a/Content.Server/Stunnable/Systems/StunbatonSystem.cs +++ b/Content.Server/Stunnable/Systems/StunbatonSystem.cs @@ -25,50 +25,49 @@ namespace Content.Server.Stunnable.Systems base.Initialize(); SubscribeLocalEvent(OnExamined); - SubscribeLocalEvent(OnSolutionChange); + SubscribeLocalEvent(OnSolutionChange); SubscribeLocalEvent(OnStaminaHitAttempt); SubscribeLocalEvent(TryTurnOn); SubscribeLocalEvent(ToggleDone); } - private void OnStaminaHitAttempt(Entity entity, ref StaminaDamageOnHitAttemptEvent args) + private void OnStaminaHitAttempt(EntityUid uid, StunbatonComponent component, ref StaminaDamageOnHitAttemptEvent args) { - if (!_itemToggle.IsActivated(entity.Owner) || - !TryComp(entity.Owner, out var battery) || !_battery.TryUseCharge(entity.Owner, entity.Comp.EnergyPerUse, battery)) + if (!_itemToggle.IsActivated(uid) || + !TryComp(uid, out var battery) || !_battery.TryUseCharge(uid, component.EnergyPerUse, battery)) { args.Cancelled = true; return; } - if (battery.CurrentCharge < entity.Comp.EnergyPerUse) + if (battery.CurrentCharge < component.EnergyPerUse) { - _itemToggle.Toggle(entity.Owner, predicted: false); + _itemToggle.Toggle(uid, predicted: false); } } - private void OnExamined(Entity entity, ref ExaminedEvent args) + private void OnExamined(EntityUid uid, BatteryComponent battery, ExaminedEvent args) { - var onMsg = _itemToggle.IsActivated(entity.Owner) + var onMsg = _itemToggle.IsActivated(uid) ? Loc.GetString("comp-stunbaton-examined-on") : Loc.GetString("comp-stunbaton-examined-off"); args.PushMarkup(onMsg); var chargeMessage = Loc.GetString("stunbaton-component-on-examine-charge", - ("charge", (int) (entity.Comp.CurrentCharge / entity.Comp.MaxCharge * 100))); + ("charge", (int) (battery.CurrentCharge / battery.MaxCharge * 100))); args.PushMarkup(chargeMessage); } - private void ToggleDone(Entity entity, ref ItemToggleDoneEvent args) + private void ToggleDone(EntityUid uid, StunbatonComponent comp, ref ItemToggleDoneEvent args) { - if (!TryComp(entity, out var item)) + if (!TryComp(uid, out var item)) return; - - _item.SetHeldPrefix(entity.Owner, args.Activated ? "on" : "off", item); + _item.SetHeldPrefix(uid, args.Activated ? "on" : "off", item); } - private void TryTurnOn(Entity entity, ref ItemToggleActivateAttemptEvent args) + private void TryTurnOn(EntityUid uid, StunbatonComponent comp, ref ItemToggleActivateAttemptEvent args) { - if (!TryComp(entity, out var battery) || battery.CurrentCharge < entity.Comp.EnergyPerUse) + if (!TryComp(uid, out var battery) || battery.CurrentCharge < comp.EnergyPerUse) { args.Cancelled = true; if (args.User != null) @@ -78,22 +77,22 @@ namespace Content.Server.Stunnable.Systems return; } - if (TryComp(entity, out var rig) && rig.IsRigged) + if (TryComp(uid, out var rig) && rig.IsRigged) { - _riggableSystem.Explode(entity.Owner, battery, args.User); + _riggableSystem.Explode(uid, battery, args.User); } } // https://github.com/space-wizards/space-station-14/pull/17288#discussion_r1241213341 - private void OnSolutionChange(Entity entity, ref SolutionContainerChangedEvent args) + private void OnSolutionChange(EntityUid uid, StunbatonComponent component, SolutionChangedEvent args) { // Explode if baton is activated and rigged. - if (!TryComp(entity, out var riggable) || - !TryComp(entity, out var battery)) + if (!TryComp(uid, out var riggable) || + !TryComp(uid, out var battery)) return; - if (_itemToggle.IsActivated(entity.Owner) && riggable.IsRigged) - _riggableSystem.Explode(entity.Owner, battery); + if (_itemToggle.IsActivated(uid) && riggable.IsRigged) + _riggableSystem.Explode(uid, battery); } private void SendPowerPulse(EntityUid target, EntityUid? user, EntityUid used) diff --git a/Content.Server/Tools/Components/WelderComponent.cs b/Content.Server/Tools/Components/WelderComponent.cs index b0db2c58e8..a620fa2ef4 100644 --- a/Content.Server/Tools/Components/WelderComponent.cs +++ b/Content.Server/Tools/Components/WelderComponent.cs @@ -1,4 +1,3 @@ -using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Reagent; using Content.Shared.FixedPoint; using Content.Shared.Tools.Components; @@ -10,41 +9,35 @@ namespace Content.Server.Tools.Components [RegisterComponent] public sealed partial class WelderComponent : SharedWelderComponent { - /// - /// Name of . - /// - [DataField("fuelSolution"), ViewVariables(VVAccess.ReadWrite)] - public string FuelSolutionName = "Welder"; - /// /// Solution on the entity that contains the fuel. /// - [DataField("fuelSolutionRef")] - public Entity? FuelSolution = null; + [DataField, ViewVariables(VVAccess.ReadWrite)] + public string FuelSolution { get; private set; } = "Welder"; /// /// Reagent that will be used as fuel for welding. /// [DataField, ViewVariables(VVAccess.ReadWrite)] - public ProtoId FuelReagent = "WeldingFuel"; + public ProtoId FuelReagent { get; private set; } = "WeldingFuel"; /// /// Fuel consumption per second while the welder is active. /// [DataField, ViewVariables(VVAccess.ReadWrite)] - public FixedPoint2 FuelConsumption = FixedPoint2.New(2.0f); + public FixedPoint2 FuelConsumption { get; private set; } = FixedPoint2.New(2.0f); /// /// A fuel amount to be consumed when the welder goes from being unlit to being lit. /// [DataField, ViewVariables(VVAccess.ReadWrite)] - public FixedPoint2 FuelLitCost = FixedPoint2.New(0.5f); + public FixedPoint2 FuelLitCost { get; private set; } = FixedPoint2.New(0.5f); /// /// Sound played when refilling the welder. /// [DataField] - public SoundSpecifier WelderRefill = new SoundPathSpecifier("/Audio/Effects/refill.ogg"); + public SoundSpecifier WelderRefill { get; private set; } = new SoundPathSpecifier("/Audio/Effects/refill.ogg"); /// /// Whether the item is safe to refill while lit without exploding the tank. diff --git a/Content.Server/Tools/ToolSystem.Welder.cs b/Content.Server/Tools/ToolSystem.Welder.cs index 88037cedb4..f4eca32a3d 100644 --- a/Content.Server/Tools/ToolSystem.Welder.cs +++ b/Content.Server/Tools/ToolSystem.Welder.cs @@ -1,3 +1,4 @@ +using System.Linq; using Content.Server.Chemistry.Components; using Content.Server.IgnitionSource; using Content.Server.Tools.Components; @@ -11,7 +12,6 @@ using Content.Shared.Item; using Content.Shared.Item.ItemToggle; using Content.Shared.Tools.Components; using Robust.Shared.GameStates; -using System.Linq; namespace Content.Server.Tools { @@ -38,67 +38,66 @@ namespace Content.Server.Tools public (FixedPoint2 fuel, FixedPoint2 capacity) GetWelderFuelAndCapacity(EntityUid uid, WelderComponent? welder = null, SolutionContainerManagerComponent? solutionContainer = null) { if (!Resolve(uid, ref welder, ref solutionContainer) - || !_solutionContainer.ResolveSolution((uid, solutionContainer), welder.FuelSolutionName, ref welder.FuelSolution, out var fuelSolution)) + || !_solutionContainer.TryGetSolution(uid, welder.FuelSolution, out var fuelSolution, solutionContainer)) return (FixedPoint2.Zero, FixedPoint2.Zero); - return (fuelSolution.GetTotalPrototypeQuantity(welder.FuelReagent), fuelSolution.MaxVolume); + return (_solutionContainer.GetTotalPrototypeQuantity(uid, welder.FuelReagent), fuelSolution.MaxVolume); } - public void TryTurnOn(Entity entity, ref ItemToggleActivateAttemptEvent args) + public void TryTurnOn(EntityUid uid, WelderComponent welder, ref ItemToggleActivateAttemptEvent args) { - if (!_solutionContainer.ResolveSolution(entity.Owner, entity.Comp.FuelSolutionName, ref entity.Comp.FuelSolution, out var solution) || - !TryComp(entity, out var transform)) + if (!_solutionContainer.TryGetSolution(uid, welder.FuelSolution, out var solution) || + !TryComp(uid, out var transform)) { args.Cancelled = true; return; } - - var fuel = solution.GetTotalPrototypeQuantity(entity.Comp.FuelReagent); + var fuel = solution.GetTotalPrototypeQuantity(welder.FuelReagent); // Not enough fuel to lit welder. - if (fuel == FixedPoint2.Zero || fuel < entity.Comp.FuelLitCost) + if (fuel == FixedPoint2.Zero || fuel < welder.FuelLitCost) { if (args.User != null) { - _popup.PopupEntity(Loc.GetString("welder-component-no-fuel-message"), entity, (EntityUid) args.User); + _popup.PopupEntity(Loc.GetString("welder-component-no-fuel-message"), uid, (EntityUid) args.User); } args.Cancelled = true; return; } - _solutionContainer.RemoveReagent(entity.Comp.FuelSolution.Value, entity.Comp.FuelReagent, entity.Comp.FuelLitCost); + solution.RemoveReagent(welder.FuelReagent, welder.FuelLitCost); // Logging - _adminLogger.Add(LogType.InteractActivate, LogImpact.Low, $"{ToPrettyString(args.User):user} toggled {ToPrettyString(entity.Owner):welder} on"); + _adminLogger.Add(LogType.InteractActivate, LogImpact.Low, $"{ToPrettyString(args.User):user} toggled {ToPrettyString(uid):welder} on"); - _ignitionSource.SetIgnited(entity.Owner); + _ignitionSource.SetIgnited(uid); if (transform.GridUid is { } gridUid) { - var position = _transformSystem.GetGridOrMapTilePosition(entity.Owner, transform); - _atmosphereSystem.HotspotExpose(gridUid, position, 700, 50, entity.Owner, true); + var position = _transformSystem.GetGridOrMapTilePosition(uid, transform); + _atmosphereSystem.HotspotExpose(gridUid, position, 700, 50, uid, true); } - Dirty(entity); + Dirty(uid, welder); - _activeWelders.Add(entity); + _activeWelders.Add(uid); } - public void TurnOff(Entity entity, ref ItemToggleDeactivateAttemptEvent args) + public void TurnOff(EntityUid uid, WelderComponent welder, ref ItemToggleDeactivateAttemptEvent args) { // Logging - _adminLogger.Add(LogType.InteractActivate, LogImpact.Low, $"{ToPrettyString(args.User):user} toggled {ToPrettyString(entity.Owner):welder} off"); + _adminLogger.Add(LogType.InteractActivate, LogImpact.Low, $"{ToPrettyString(args.User):user} toggled {ToPrettyString(uid):welder} off"); - _ignitionSource.SetIgnited(entity.Owner, false); + _ignitionSource.SetIgnited(uid, false); - Dirty(entity); + Dirty(uid, welder); - _activeWelders.Remove(entity); + _activeWelders.Remove(uid); } - private void OnWelderExamine(Entity entity, ref ExaminedEvent args) + private void OnWelderExamine(EntityUid uid, WelderComponent welder, ExaminedEvent args) { - if (_itemToggle.IsActivated(entity.Owner)) + if (_itemToggle.IsActivated(uid)) { args.PushMarkup(Loc.GetString("welder-component-on-examine-welder-lit-message")); } @@ -109,7 +108,7 @@ namespace Content.Server.Tools if (args.IsInDetailsRange) { - var (fuel, capacity) = GetWelderFuelAndCapacity(entity.Owner, entity.Comp); + var (fuel, capacity) = GetWelderFuelAndCapacity(uid, welder); args.PushMarkup(Loc.GetString("welder-component-on-examine-detailed-message", ("colorName", fuel < capacity / FixedPoint2.New(4f) ? "darkorange" : "orange"), @@ -119,7 +118,7 @@ namespace Content.Server.Tools } } - private void OnWelderAfterInteract(Entity entity, ref AfterInteractEvent args) + private void OnWelderAfterInteract(EntityUid uid, WelderComponent welder, AfterInteractEvent args) { if (args.Handled) return; @@ -129,49 +128,49 @@ namespace Content.Server.Tools if (TryComp(target, out ReagentTankComponent? tank) && tank.TankType == ReagentTankType.Fuel - && _solutionContainer.TryGetDrainableSolution(target, out var targetSoln, out var targetSolution) - && _solutionContainer.ResolveSolution(entity.Owner, entity.Comp.FuelSolutionName, ref entity.Comp.FuelSolution, out var welderSolution)) + && _solutionContainer.TryGetDrainableSolution(target, out var targetSolution) + && _solutionContainer.TryGetSolution(uid, welder.FuelSolution, out var welderSolution)) { var trans = FixedPoint2.Min(welderSolution.AvailableVolume, targetSolution.Volume); if (trans > 0) { - var drained = _solutionContainer.Drain(target, targetSoln.Value, trans); - _solutionContainer.TryAddSolution(entity.Comp.FuelSolution.Value, drained); - _audio.PlayPvs(entity.Comp.WelderRefill, entity); - _popup.PopupEntity(Loc.GetString("welder-component-after-interact-refueled-message"), entity, args.User); + var drained = _solutionContainer.Drain(target, targetSolution, trans); + _solutionContainer.TryAddSolution(uid, welderSolution, drained); + _audio.PlayPvs(welder.WelderRefill, uid); + _popup.PopupEntity(Loc.GetString("welder-component-after-interact-refueled-message"), uid, args.User); } else if (welderSolution.AvailableVolume <= 0) { - _popup.PopupEntity(Loc.GetString("welder-component-already-full"), entity, args.User); + _popup.PopupEntity(Loc.GetString("welder-component-already-full"), uid, args.User); } else { - _popup.PopupEntity(Loc.GetString("welder-component-no-fuel-in-tank", ("owner", args.Target)), entity, args.User); + _popup.PopupEntity(Loc.GetString("welder-component-no-fuel-in-tank", ("owner", args.Target)), uid, args.User); } } args.Handled = true; } - private void OnWelderToolUseAttempt(Entity entity, ref DoAfterAttemptEvent args) + private void OnWelderToolUseAttempt(EntityUid uid, WelderComponent welder, DoAfterAttemptEvent args) { var user = args.DoAfter.Args.User; - if (!_itemToggle.IsActivated(entity.Owner)) + if (!_itemToggle.IsActivated(uid)) { - _popup.PopupEntity(Loc.GetString("welder-component-welder-not-lit-message"), entity, user); + _popup.PopupEntity(Loc.GetString("welder-component-welder-not-lit-message"), uid, user); args.Cancel(); } } - private void OnWelderShutdown(Entity entity, ref ComponentShutdown args) + private void OnWelderShutdown(EntityUid uid, WelderComponent welder, ComponentShutdown args) { - _activeWelders.Remove(entity); + _activeWelders.Remove(uid); } - private void OnWelderGetState(Entity entity, ref ComponentGetState args) + private void OnWelderGetState(EntityUid uid, WelderComponent welder, ref ComponentGetState args) { - var (fuel, capacity) = GetWelderFuelAndCapacity(entity.Owner, entity.Comp); + var (fuel, capacity) = GetWelderFuelAndCapacity(uid, welder); args.State = new WelderComponentState(capacity.Float(), fuel.Float()); } @@ -189,10 +188,10 @@ namespace Content.Server.Tools || !TryComp(tool, out SolutionContainerManagerComponent? solutionContainer)) continue; - if (!_solutionContainer.ResolveSolution((tool, solutionContainer), welder.FuelSolutionName, ref welder.FuelSolution, out var solution)) + if (!_solutionContainer.TryGetSolution(tool, welder.FuelSolution, out var solution, solutionContainer)) continue; - _solutionContainer.RemoveReagent(welder.FuelSolution.Value, welder.FuelReagent, welder.FuelConsumption * _welderTimer); + solution.RemoveReagent(welder.FuelReagent, welder.FuelConsumption * _welderTimer); if (solution.GetTotalPrototypeQuantity(welder.FuelReagent) <= FixedPoint2.Zero) { diff --git a/Content.Server/Tools/ToolSystem.cs b/Content.Server/Tools/ToolSystem.cs index 6153b579a1..7366bfce40 100644 --- a/Content.Server/Tools/ToolSystem.cs +++ b/Content.Server/Tools/ToolSystem.cs @@ -1,11 +1,13 @@ using Content.Server.Atmos.EntitySystems; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Popups; using Content.Server.Tools.Components; +using Content.Shared.Chemistry.EntitySystems; +using Content.Shared.Maps; +using Content.Shared.Tools; using Robust.Server.GameObjects; +using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; using Robust.Shared.Map; - using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem; namespace Content.Server.Tools diff --git a/Content.Server/Weapons/Melee/MeleeWeaponSystem.cs b/Content.Server/Weapons/Melee/MeleeWeaponSystem.cs index 1c672796c6..0e085cdfe0 100644 --- a/Content.Server/Weapons/Melee/MeleeWeaponSystem.cs +++ b/Content.Server/Weapons/Melee/MeleeWeaponSystem.cs @@ -1,13 +1,15 @@ +using System.Linq; +using System.Numerics; using Content.Server.Body.Components; using Content.Server.Body.Systems; using Content.Server.Chat.Systems; using Content.Server.Chemistry.Components; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.CombatMode.Disarm; using Content.Server.Contests; using Content.Server.Movement.Systems; using Content.Shared.Actions.Events; using Content.Shared.Administration.Components; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.CombatMode; using Content.Shared.Damage.Events; using Content.Shared.Damage.Systems; @@ -27,8 +29,6 @@ using Robust.Shared.Audio; using Robust.Shared.Map; using Robust.Shared.Player; using Robust.Shared.Random; -using System.Linq; -using System.Numerics; namespace Content.Server.Weapons.Melee; @@ -250,11 +250,11 @@ public sealed class MeleeWeaponSystem : SharedMeleeWeaponSystem } - private void OnChemicalInjectorHit(Entity entity, ref MeleeHitEvent args) + private void OnChemicalInjectorHit(EntityUid owner, MeleeChemicalInjectorComponent comp, MeleeHitEvent args) { if (!args.IsHit || !args.HitEntities.Any() || - !_solutions.TryGetSolution(entity.Owner, entity.Comp.Solution, out var solutionContainer)) + !_solutions.TryGetSolution(owner, comp.Solution, out var solutionContainer)) { return; } @@ -262,28 +262,28 @@ public sealed class MeleeWeaponSystem : SharedMeleeWeaponSystem var hitBloodstreams = new List<(EntityUid Entity, BloodstreamComponent Component)>(); var bloodQuery = GetEntityQuery(); - foreach (var hit in args.HitEntities) + foreach (var entity in args.HitEntities) { - if (Deleted(hit)) + if (Deleted(entity)) continue; // prevent deathnettles injecting through hardsuits - if (!entity.Comp.PierceArmor && _inventory.TryGetSlotEntity(hit, "outerClothing", out var suit) && _tag.HasTag(suit.Value, "Hardsuit")) + if (!comp.PierceArmor && _inventory.TryGetSlotEntity(entity, "outerClothing", out var suit) && _tag.HasTag(suit.Value, "Hardsuit")) { - PopupSystem.PopupEntity(Loc.GetString("melee-inject-failed-hardsuit", ("weapon", entity.Owner)), args.User, args.User, PopupType.SmallCaution); + PopupSystem.PopupEntity(Loc.GetString("melee-inject-failed-hardsuit", ("weapon", owner)), args.User, args.User, PopupType.SmallCaution); continue; } - if (bloodQuery.TryGetComponent(hit, out var bloodstream)) - hitBloodstreams.Add((hit, bloodstream)); + if (bloodQuery.TryGetComponent(entity, out var bloodstream)) + hitBloodstreams.Add((entity, bloodstream)); } if (!hitBloodstreams.Any()) return; - var removedSolution = _solutions.SplitSolution(solutionContainer.Value, entity.Comp.TransferAmount * hitBloodstreams.Count); + var removedSolution = solutionContainer.SplitSolution(comp.TransferAmount * hitBloodstreams.Count); var removedVol = removedSolution.Volume; - var solutionToInject = removedSolution.SplitSolution(removedVol * entity.Comp.TransferEfficiency); + var solutionToInject = removedSolution.SplitSolution(removedVol * comp.TransferEfficiency); var volPerBloodstream = solutionToInject.Volume * (1 / hitBloodstreams.Count); foreach (var (ent, bloodstream) in hitBloodstreams) diff --git a/Content.Server/Weapons/Ranged/Systems/ChemicalAmmoSystem.cs b/Content.Server/Weapons/Ranged/Systems/ChemicalAmmoSystem.cs index e896e2b373..3d8601cc8e 100644 --- a/Content.Server/Weapons/Ranged/Systems/ChemicalAmmoSystem.cs +++ b/Content.Server/Weapons/Ranged/Systems/ChemicalAmmoSystem.cs @@ -1,34 +1,34 @@ -using Content.Server.Chemistry.Containers.EntitySystems; +using System.Linq; using Content.Server.Weapons.Ranged.Components; using Content.Shared.Chemistry.Components; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Weapons.Ranged.Events; -using System.Linq; namespace Content.Server.Weapons.Ranged.Systems { public sealed class ChemicalAmmoSystem : EntitySystem { - [Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!; + [Dependency] private readonly SolutionContainerSystem _solutionSystem = default!; public override void Initialize() { SubscribeLocalEvent(OnFire); } - private void OnFire(Entity entity, ref AmmoShotEvent args) + private void OnFire(EntityUid uid, ChemicalAmmoComponent component, AmmoShotEvent args) { - if (!_solutionContainerSystem.TryGetSolution(entity.Owner, entity.Comp.SolutionName, out var ammoSoln, out var ammoSolution)) + if (!_solutionSystem.TryGetSolution(uid, component.SolutionName, out var ammoSolution)) return; var projectiles = args.FiredProjectiles; - var projectileSolutionContainers = new List<(EntityUid, Entity)>(); + var projectileSolutionContainers = new List<(EntityUid, Solution)>(); foreach (var projectile in projectiles) { - if (_solutionContainerSystem - .TryGetSolution(projectile, entity.Comp.SolutionName, out var projectileSoln, out _)) + if (_solutionSystem + .TryGetSolution(projectile, component.SolutionName, out var projectileSolutionContainer)) { - projectileSolutionContainers.Add((projectile, projectileSoln.Value)); + projectileSolutionContainers.Add((uid, projectileSolutionContainer)); } } @@ -37,13 +37,13 @@ namespace Content.Server.Weapons.Ranged.Systems var solutionPerProjectile = ammoSolution.Volume * (1 / projectileSolutionContainers.Count); - foreach (var (_, projectileSolution) in projectileSolutionContainers) + foreach (var (projectileUid, projectileSolution) in projectileSolutionContainers) { - var solutionToTransfer = _solutionContainerSystem.SplitSolution(ammoSoln.Value, solutionPerProjectile); - _solutionContainerSystem.TryAddSolution(projectileSolution, solutionToTransfer); + var solutionToTransfer = _solutionSystem.SplitSolution(uid, ammoSolution, solutionPerProjectile); + _solutionSystem.TryAddSolution(projectileUid, projectileSolution, solutionToTransfer); } - _solutionContainerSystem.RemoveAllSolution(ammoSoln.Value); + _solutionSystem.RemoveAllSolution(uid, ammoSolution); } } } diff --git a/Content.Server/Weapons/Ranged/Systems/GunSystem.Solution.cs b/Content.Server/Weapons/Ranged/Systems/GunSystem.Solution.cs index 7ad4b15ffc..734a01602c 100644 --- a/Content.Server/Weapons/Ranged/Systems/GunSystem.Solution.cs +++ b/Content.Server/Weapons/Ranged/Systems/GunSystem.Solution.cs @@ -1,5 +1,4 @@ using Content.Server.Chemistry.Components; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.EntitySystems; using Content.Shared.FixedPoint; @@ -19,29 +18,29 @@ public sealed partial class GunSystem base.InitializeSolution(); SubscribeLocalEvent(OnSolutionMapInit); - SubscribeLocalEvent(OnSolutionChanged); + SubscribeLocalEvent(OnSolutionChanged); } - private void OnSolutionMapInit(Entity entity, ref MapInitEvent args) + private void OnSolutionMapInit(EntityUid uid, SolutionAmmoProviderComponent component, MapInitEvent args) { - UpdateSolutionShots(entity.Owner, entity.Comp); + UpdateSolutionShots(uid, component); } - private void OnSolutionChanged(Entity entity, ref SolutionContainerChangedEvent args) + private void OnSolutionChanged(EntityUid uid, SolutionAmmoProviderComponent component, SolutionChangedEvent args) { - if (args.Solution.Name == entity.Comp.SolutionId) - UpdateSolutionShots(entity.Owner, entity.Comp, args.Solution); + if (args.Solution.Name == component.SolutionId) + UpdateSolutionShots(uid, component, args.Solution); } protected override void UpdateSolutionShots(EntityUid uid, SolutionAmmoProviderComponent component, Solution? solution = null) { var shots = 0; var maxShots = 0; - if (solution == null && !_solutionContainer.TryGetSolution(uid, component.SolutionId, out _, out solution)) + if (solution == null && !_solutionContainer.TryGetSolution(uid, component.SolutionId, out solution)) { component.Shots = shots; component.MaxShots = maxShots; - Dirty(uid, component); + Dirty(component); return; } @@ -50,7 +49,7 @@ public sealed partial class GunSystem component.Shots = shots; component.MaxShots = maxShots; - Dirty(uid, component); + Dirty(component); UpdateSolutionAppearance(uid, component); } @@ -59,10 +58,10 @@ public sealed partial class GunSystem { var (ent, shootable) = base.GetSolutionShot(uid, component, position); - if (!_solutionContainer.TryGetSolution(uid, component.SolutionId, out var solution, out _)) + if (!_solutionContainer.TryGetSolution(uid, component.SolutionId, out var solution)) return (ent, shootable); - var newSolution = _solutionContainer.SplitSolution(solution.Value, component.FireCost); + var newSolution = _solutionContainer.SplitSolution(uid, solution, component.FireCost); if (newSolution.Volume <= FixedPoint2.Zero) return (ent, shootable); @@ -74,9 +73,9 @@ public sealed partial class GunSystem } // Add the solution to the vapor and actually send the thing - if (_solutionContainer.TryGetSolution(ent, VaporComponent.SolutionName, out var vaporSolution, out _)) + if (_solutionContainer.TryGetSolution(ent, VaporComponent.SolutionName, out var vaporSolution)) { - _solutionContainer.TryAddSolution(vaporSolution.Value, newSolution); + _solutionContainer.TryAddSolution(ent, vaporSolution, newSolution); } return (ent, shootable); } diff --git a/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Components/ChemicalPuddleArtifactComponent.cs b/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Components/ChemicalPuddleArtifactComponent.cs index 3065b1c417..1e40807f6e 100644 --- a/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Components/ChemicalPuddleArtifactComponent.cs +++ b/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Components/ChemicalPuddleArtifactComponent.cs @@ -1,6 +1,8 @@ using Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Systems; using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Reagent; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components; diff --git a/Content.Shared/Administration/EditSolutionsEuiState.cs b/Content.Shared/Administration/EditSolutionsEuiState.cs index 12fae34962..782c4b84f2 100644 --- a/Content.Shared/Administration/EditSolutionsEuiState.cs +++ b/Content.Shared/Administration/EditSolutionsEuiState.cs @@ -1,5 +1,6 @@ using Content.Shared.Eui; using Robust.Shared.Serialization; +using Content.Shared.Chemistry.Components; namespace Content.Shared.Administration { @@ -7,9 +8,9 @@ namespace Content.Shared.Administration public sealed class EditSolutionsEuiState : EuiStateBase { public readonly NetEntity Target; - public readonly List<(string, NetEntity)>? Solutions; + public readonly Dictionary? Solutions; - public EditSolutionsEuiState(NetEntity target, List<(string, NetEntity)>? solutions) + public EditSolutionsEuiState(NetEntity target, Dictionary? solutions) { Target = target; Solutions = solutions; diff --git a/Content.Shared/Chemistry/Components/DrainableSolutionComponent.cs b/Content.Shared/Chemistry/Components/DrainableSolutionComponent.cs index 0a6ace0943..4cdff566f6 100644 --- a/Content.Shared/Chemistry/Components/DrainableSolutionComponent.cs +++ b/Content.Shared/Chemistry/Components/DrainableSolutionComponent.cs @@ -12,6 +12,7 @@ public sealed partial class DrainableSolutionComponent : Component /// /// Solution name that can be drained. /// - [DataField, ViewVariables(VVAccess.ReadWrite)] - public string Solution = "default"; + [ViewVariables(VVAccess.ReadWrite)] + [DataField("solution")] + public string Solution { get; set; } = "default"; } diff --git a/Content.Shared/Chemistry/Components/DumpableSolutionComponent.cs b/Content.Shared/Chemistry/Components/DumpableSolutionComponent.cs index 43fbe137b6..ad9e1f19a6 100644 --- a/Content.Shared/Chemistry/Components/DumpableSolutionComponent.cs +++ b/Content.Shared/Chemistry/Components/DumpableSolutionComponent.cs @@ -12,12 +12,14 @@ public sealed partial class DumpableSolutionComponent : Component /// /// Solution name that can be dumped into. /// - [DataField, ViewVariables(VVAccess.ReadWrite)] - public string Solution = "default"; + [ViewVariables(VVAccess.ReadWrite)] + [DataField("solution")] + public string Solution { get; set; } = "default"; /// /// Whether the solution can be dumped into infinitely. /// - [DataField, ViewVariables(VVAccess.ReadWrite)] - public bool Unlimited = false; + [ViewVariables(VVAccess.ReadWrite)] + [DataField("unlimited")] + public bool Unlimited { get; set; } = false; } diff --git a/Content.Shared/Chemistry/Components/FitsInDispenserComponent.cs b/Content.Shared/Chemistry/Components/FitsInDispenserComponent.cs index f295dcc5bd..a479dcdbe8 100644 --- a/Content.Shared/Chemistry/Components/FitsInDispenserComponent.cs +++ b/Content.Shared/Chemistry/Components/FitsInDispenserComponent.cs @@ -1,21 +1,23 @@ using Robust.Shared.GameStates; -namespace Content.Shared.Chemistry.Components; - -/// -/// Allows the entity with this component to be placed in a SharedReagentDispenserComponent. -/// Otherwise it's considered to be too large or the improper shape to fit. -/// Allows us to have obscenely large containers that are harder to abuse in chem dispensers -/// since they can't be placed directly in them. -/// -/// -[RegisterComponent] -[NetworkedComponent] // only needed for white-lists. Client doesn't actually need Solution data; -public sealed partial class FitsInDispenserComponent : Component +namespace Content.Shared.Chemistry.Components { /// - /// Solution name that will interact with ReagentDispenserComponent. + /// Allows the entity with this component to be placed in a SharedReagentDispenserComponent. + /// Otherwise it's considered to be too large or the improper shape to fit. + /// Allows us to have obscenely large containers that are harder to abuse in chem dispensers + /// since they can't be placed directly in them. + /// /// - [DataField, ViewVariables(VVAccess.ReadWrite)] - public string Solution = "default"; + [RegisterComponent] + [NetworkedComponent] // only needed for white-lists. Client doesn't actually need Solution data; + public sealed partial class FitsInDispenserComponent : Component + { + /// + /// Solution name that will interact with ReagentDispenserComponent. + /// + [ViewVariables(VVAccess.ReadWrite)] + [DataField("solution")] + public string Solution { get; set; } = "default"; + } } diff --git a/Content.Shared/Chemistry/Components/RefillableSolutionComponent.cs b/Content.Shared/Chemistry/Components/RefillableSolutionComponent.cs index 245b7398a7..cb5ab7679d 100644 --- a/Content.Shared/Chemistry/Components/RefillableSolutionComponent.cs +++ b/Content.Shared/Chemistry/Components/RefillableSolutionComponent.cs @@ -14,12 +14,14 @@ public sealed partial class RefillableSolutionComponent : Component /// /// Solution name that can added to easily. /// - [DataField, ViewVariables(VVAccess.ReadWrite)] - public string Solution = "default"; + [ViewVariables(VVAccess.ReadWrite)] + [DataField("solution")] + public string Solution { get; set; } = "default"; /// /// The maximum amount that can be transferred to the solution at once /// - [DataField, ViewVariables(VVAccess.ReadWrite)] - public FixedPoint2? MaxRefill = null; + [DataField("maxRefill")] + [ViewVariables(VVAccess.ReadWrite)] + public FixedPoint2? MaxRefill { get; set; } = null; } diff --git a/Content.Shared/Chemistry/Components/SmokeComponent.cs b/Content.Shared/Chemistry/Components/SmokeComponent.cs index f07a77c1ac..9d88fcac94 100644 --- a/Content.Shared/Chemistry/Components/SmokeComponent.cs +++ b/Content.Shared/Chemistry/Components/SmokeComponent.cs @@ -13,12 +13,6 @@ public sealed partial class SmokeComponent : Component { public const string SolutionName = "solutionArea"; - /// - /// The solution on the entity with touch and ingestion reactions. - /// - [DataField] - public Entity? Solution = null; - /// /// The max amount of tiles this smoke cloud can spread to. /// diff --git a/Content.Shared/Chemistry/Components/Solution.cs b/Content.Shared/Chemistry/Components/Solution.cs index 8598e1ad99..ca597710d4 100644 --- a/Content.Shared/Chemistry/Components/Solution.cs +++ b/Content.Shared/Chemistry/Components/Solution.cs @@ -71,7 +71,6 @@ namespace Content.Shared.Chemistry.Components /// /// The name of this solution, if it is contained in some /// - [DataField] public string? Name; /// @@ -101,7 +100,7 @@ namespace Content.Shared.Chemistry.Components foreach (var (reagent, quantity) in Contents) { _heatCapacity += (float) quantity * - protoMan.Index(reagent.Prototype).SpecificHeat; + protoMan.Index(reagent.Prototype).SpecificHeat; } } @@ -159,12 +158,10 @@ namespace Content.Shared.Chemistry.Components public Solution(Solution solution) { - Contents = solution.Contents.ShallowClone(); Volume = solution.Volume; - MaxVolume = solution.MaxVolume; - Temperature = solution.Temperature; _heatCapacity = solution._heatCapacity; _heatCapacityDirty = solution._heatCapacityDirty; + Contents = solution.Contents.ShallowClone(); ValidateSolution(); } @@ -177,7 +174,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); @@ -195,7 +192,7 @@ namespace Content.Shared.Chemistry.Components UpdateHeatCapacity(null); DebugTools.Assert(MathHelper.CloseTo(_heatCapacity, cur)); } - #endif +#endif } void ISerializationHooks.AfterDeserialization() diff --git a/Content.Shared/Chemistry/Components/SolutionComponent.cs b/Content.Shared/Chemistry/Components/SolutionComponent.cs deleted file mode 100644 index 687a545b00..0000000000 --- a/Content.Shared/Chemistry/Components/SolutionComponent.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Content.Shared.Chemistry.Components.SolutionManager; -using Content.Shared.Materials; -using Robust.Shared.GameStates; - -namespace Content.Shared.Chemistry.Components; - -/// -/// Holds the composition of an entity made from reagents and its reagent temperature. -/// If the entity is used to represent a collection of reagents inside of a container such as a beaker, syringe, bloodstream, food, or similar the entity is tracked by a on the container and has a tracking which container it's in. -/// -/// -/// Once reagents and materials have been merged this component should be depricated in favor of using a combination of and . May require minor reworks to both. -/// -[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] -public sealed partial class SolutionComponent : Component -{ - /// - /// The reagents the entity is composed of and their temperature. - /// - [DataField, AutoNetworkedField] - public Solution Solution = new(); -} diff --git a/Content.Shared/Chemistry/Components/SolutionManager/ContainedSolutionComponent.cs b/Content.Shared/Chemistry/Components/SolutionManager/ContainedSolutionComponent.cs deleted file mode 100644 index d648a9f00c..0000000000 --- a/Content.Shared/Chemistry/Components/SolutionManager/ContainedSolutionComponent.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Content.Shared.Chemistry.EntitySystems; -using Robust.Shared.GameStates; -using Robust.Shared.Serialization; - -namespace Content.Shared.Chemistry.Components.SolutionManager; - -/// -/// Component used to relate a solution to its container. -/// -/// -/// When containers are finally ECS'd have this attach to the container entity. -/// The field should then be extracted out into this component. -/// Solution entities would just become an apporpriately composed entity hanging out in the container. -/// Will probably require entities in components being given a relation to associate themselves with their container. -/// -[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] -[Access(typeof(SharedSolutionContainerSystem))] -public sealed partial class ContainedSolutionComponent : Component -{ - /// - /// The entity that the solution is contained in. - /// - [DataField(required: true), AutoNetworkedField] - public EntityUid Container; - - /// - /// The name/key of the container the solution is located in. - /// - [DataField(required: true), AutoNetworkedField] - public string ContainerName = default!; -} diff --git a/Content.Shared/Chemistry/Components/SolutionManager/DrawableSolutionComponent.cs b/Content.Shared/Chemistry/Components/SolutionManager/DrawableSolutionComponent.cs index a949ae72e2..f9cd6e8e8e 100644 --- a/Content.Shared/Chemistry/Components/SolutionManager/DrawableSolutionComponent.cs +++ b/Content.Shared/Chemistry/Components/SolutionManager/DrawableSolutionComponent.cs @@ -9,6 +9,7 @@ public sealed partial class DrawableSolutionComponent : Component /// /// Solution name that can be removed with syringes. /// - [DataField, ViewVariables(VVAccess.ReadWrite)] - public string Solution = "default"; + [ViewVariables(VVAccess.ReadWrite)] + [DataField("solution")] + public string Solution { get; set; } = "default"; } diff --git a/Content.Shared/Chemistry/Components/SolutionManager/ExaminableSolutionComponent.cs b/Content.Shared/Chemistry/Components/SolutionManager/ExaminableSolutionComponent.cs index 76e7967db2..b12a5bd6e4 100644 --- a/Content.Shared/Chemistry/Components/SolutionManager/ExaminableSolutionComponent.cs +++ b/Content.Shared/Chemistry/Components/SolutionManager/ExaminableSolutionComponent.cs @@ -3,6 +3,7 @@ [RegisterComponent] public sealed partial class ExaminableSolutionComponent : Component { - [DataField, ViewVariables(VVAccess.ReadWrite)] - public string Solution = "default"; + [ViewVariables(VVAccess.ReadWrite)] + [DataField("solution")] + public string Solution { get; set; } = "default"; } diff --git a/Content.Shared/Chemistry/Components/SolutionManager/InjectableSolutionComponent.cs b/Content.Shared/Chemistry/Components/SolutionManager/InjectableSolutionComponent.cs index 97266764dc..a696244956 100644 --- a/Content.Shared/Chemistry/Components/SolutionManager/InjectableSolutionComponent.cs +++ b/Content.Shared/Chemistry/Components/SolutionManager/InjectableSolutionComponent.cs @@ -10,6 +10,7 @@ public sealed partial class InjectableSolutionComponent : Component /// /// Solution name which can be added with syringes. /// - [DataField, ViewVariables(VVAccess.ReadWrite)] - public string Solution = "default"; + [ViewVariables(VVAccess.ReadWrite)] + [DataField("solution")] + public string Solution { get; set; } = "default"; } diff --git a/Content.Shared/Chemistry/Components/SolutionManager/SolutionContainerManagerComponent.cs b/Content.Shared/Chemistry/Components/SolutionManager/SolutionContainerManagerComponent.cs index fe62555f0d..9dfa4a71fd 100644 --- a/Content.Shared/Chemistry/Components/SolutionManager/SolutionContainerManagerComponent.cs +++ b/Content.Shared/Chemistry/Components/SolutionManager/SolutionContainerManagerComponent.cs @@ -1,36 +1,12 @@ using Content.Shared.Chemistry.EntitySystems; -using Robust.Shared.Containers; -using Robust.Shared.GameStates; namespace Content.Shared.Chemistry.Components.SolutionManager; -/// -/// A map of the solution entities contained within this entity. -/// Every solution entity this maps should have a to track its state and a to track its container. -/// -[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] -[Access(typeof(SharedSolutionContainerSystem))] +[RegisterComponent] +[Access(typeof(SolutionContainerSystem))] public sealed partial class SolutionContainerManagerComponent : Component { - /// - /// The default amount of space that will be allocated for solutions in solution containers. - /// Most solution containers will only contain 1-2 solutions. - /// - public const int DefaultCapacity = 2; - - /// - /// The names of each solution container attached to this entity. - /// Actually accessing them must be done via . - /// - [DataField, AutoNetworkedField] - public HashSet Containers = new(DefaultCapacity); - - /// - /// The set of solutions to load onto this entity during mapinit. - /// - /// - /// Should be null after mapinit. - /// - [DataField(serverOnly: true)] // Needs to be serverOnly or these will get loaded on the client and never cleared. Can be reworked when entity spawning is predicted. - public Dictionary? Solutions = null; + [DataField("solutions")] + [Access(typeof(SolutionContainerSystem), Other = AccessPermissions.ReadExecute)] // FIXME Friends + public Dictionary Solutions = new(); } diff --git a/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerMixerSystem.cs b/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerMixerSystem.cs index 8795706612..14c4560dd8 100644 --- a/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerMixerSystem.cs +++ b/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerMixerSystem.cs @@ -20,7 +20,7 @@ public abstract class SharedSolutionContainerMixerSystem : EntitySystem [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly SharedContainerSystem _container = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; - [Dependency] private readonly SharedSolutionContainerSystem _solution = default!; + [Dependency] private readonly SolutionContainerSystem _solution = default!; /// public override void Initialize() @@ -98,10 +98,10 @@ public abstract class SharedSolutionContainerMixerSystem : EntitySystem foreach (var ent in container.ContainedEntities) { - if (!_solution.TryGetFitsInDispenser(ent, out var soln, out _)) + if (!_solution.TryGetFitsInDispenser(ent, out var solution)) continue; - _solution.UpdateChemicals(soln.Value, true, reactionMixer); + _solution.UpdateChemicals(ent, solution, true, reactionMixer); } } diff --git a/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.Capabilities.cs b/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.Capabilities.cs deleted file mode 100644 index 0d4912a504..0000000000 --- a/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.Capabilities.cs +++ /dev/null @@ -1,183 +0,0 @@ -using Content.Shared.Chemistry.Components; -using Content.Shared.Chemistry.Components.SolutionManager; -using Content.Shared.Chemistry.Reaction; -using Content.Shared.FixedPoint; -using Robust.Shared.Utility; -using System.Diagnostics.CodeAnalysis; -using System.Text; - -namespace Content.Shared.Chemistry.EntitySystems; - -public abstract partial class SharedSolutionContainerSystem -{ - #region Solution Accessors - - public bool TryGetRefillableSolution(Entity entity, [NotNullWhen(true)] out Entity? soln, [NotNullWhen(true)] out Solution? solution) - { - if (!Resolve(entity, ref entity.Comp1, logMissing: false)) - { - (soln, solution) = (default!, null); - return false; - } - - return TryGetSolution((entity.Owner, entity.Comp2), entity.Comp1.Solution, out soln, out solution); - } - - public bool TryGetDrainableSolution(Entity entity, [NotNullWhen(true)] out Entity? soln, [NotNullWhen(true)] out Solution? solution) - { - if (!Resolve(entity, ref entity.Comp1, logMissing: false)) - { - (soln, solution) = (default!, null); - return false; - } - - return TryGetSolution((entity.Owner, entity.Comp2), entity.Comp1.Solution, out soln, out solution); - } - - public bool TryGetDumpableSolution(Entity entity, [NotNullWhen(true)] out Entity? soln, [NotNullWhen(true)] out Solution? solution) - { - if (!Resolve(entity, ref entity.Comp1, logMissing: false)) - { - (soln, solution) = (default!, null); - return false; - } - - return TryGetSolution((entity.Owner, entity.Comp2), entity.Comp1.Solution, out soln, out solution); - } - - public bool TryGetDrawableSolution(Entity entity, [NotNullWhen(true)] out Entity? soln, [NotNullWhen(true)] out Solution? solution) - { - if (!Resolve(entity, ref entity.Comp1, logMissing: false)) - { - (soln, solution) = (default!, null); - return false; - } - - return TryGetSolution((entity.Owner, entity.Comp2), entity.Comp1.Solution, out soln, out solution); - } - - public bool TryGetInjectableSolution(Entity entity, [NotNullWhen(true)] out Entity? soln, [NotNullWhen(true)] out Solution? solution) - { - if (!Resolve(entity, ref entity.Comp1, logMissing: false)) - { - (soln, solution) = (default!, null); - return false; - } - - return TryGetSolution((entity.Owner, entity.Comp2), entity.Comp1.Solution, out soln, out solution); - } - - public bool TryGetFitsInDispenser(Entity entity, [NotNullWhen(true)] out Entity? soln, [NotNullWhen(true)] out Solution? solution) - { - if (!Resolve(entity, ref entity.Comp1, logMissing: false)) - { - (soln, solution) = (default!, null); - return false; - } - - return TryGetSolution((entity.Owner, entity.Comp2), entity.Comp1.Solution, out soln, out solution); - } - - public bool TryGetMixableSolution(Entity container, [NotNullWhen(true)] out Entity? solution) - { - var getMixableSolutionAttempt = new GetMixableSolutionAttemptEvent(container); - RaiseLocalEvent(container, ref getMixableSolutionAttempt); - if (getMixableSolutionAttempt.MixedSolution != null) - { - solution = getMixableSolutionAttempt.MixedSolution; - return true; - } - - if (!Resolve(container, ref container.Comp, false)) - { - solution = default!; - return false; - } - - var tryGetSolution = EnumerateSolutions(container).FirstOrNull(x => x.Solution.Comp.Solution.CanMix); - if (tryGetSolution.HasValue) - { - solution = tryGetSolution.Value.Solution; - return true; - } - - solution = default!; - return false; - } - - #endregion Solution Accessors - - #region Solution Modifiers - - public void Refill(Entity entity, Entity soln, Solution refill) - { - if (!Resolve(entity, ref entity.Comp, logMissing: false)) - return; - - AddSolution(soln, refill); - } - - public void Inject(Entity entity, Entity soln, Solution inject) - { - if (!Resolve(entity, ref entity.Comp, logMissing: false)) - return; - - AddSolution(soln, inject); - } - - public Solution Drain(Entity entity, Entity soln, FixedPoint2 quantity) - { - if (!Resolve(entity, ref entity.Comp, logMissing: false)) - return new(); - - return SplitSolution(soln, quantity); - } - - public Solution Draw(Entity entity, Entity soln, FixedPoint2 quantity) - { - if (!Resolve(entity, ref entity.Comp, logMissing: false)) - return new(); - - return SplitSolution(soln, quantity); - } - - #endregion Solution Modifiers - - public float PercentFull(EntityUid uid) - { - if (!TryGetDrainableSolution(uid, out _, out var solution) || solution.MaxVolume.Equals(FixedPoint2.Zero)) - return 0; - - return solution.FillFraction * 100; - } - - #region Static Methods - - public static string ToPrettyString(Solution solution) - { - var sb = new StringBuilder(); - if (solution.Name == null) - sb.Append("["); - else - sb.Append($"{solution.Name}:["); - var first = true; - foreach (var (id, quantity) in solution.Contents) - { - if (first) - { - first = false; - } - else - { - sb.Append(", "); - } - - sb.AppendFormat("{0}: {1}u", id, quantity); - } - - sb.Append(']'); - return sb.ToString(); - } - - #endregion Static Methods -} diff --git a/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.Relays.cs b/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.Relays.cs deleted file mode 100644 index e6e96fa80a..0000000000 --- a/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.Relays.cs +++ /dev/null @@ -1,148 +0,0 @@ -using Content.Shared.Chemistry.Components; -using Content.Shared.Chemistry.Components.SolutionManager; -using Content.Shared.Chemistry.Reaction; -using Content.Shared.FixedPoint; - -namespace Content.Shared.Chemistry.EntitySystems; - -#region Events - -/// -/// This event alerts system that the solution was changed -/// -[ByRefEvent] -public record struct SolutionContainerChangedEvent -{ - public readonly Solution Solution; - public readonly string SolutionId; - - public SolutionContainerChangedEvent(Solution solution, string solutionId) - { - SolutionId = solutionId; - Solution = solution; - } -} - -/// -/// An event raised when more reagents are added to a (managed) solution than it can hold. -/// -[ByRefEvent] -public record struct SolutionContainerOverflowEvent(EntityUid SolutionEnt, Solution SolutionHolder, Solution Overflow) -{ - /// The entity which contains the solution that has overflowed. - public readonly EntityUid SolutionEnt = SolutionEnt; - /// The solution that has overflowed. - public readonly Solution SolutionHolder = SolutionHolder; - /// The reagents that have overflowed the solution. - public readonly Solution Overflow = Overflow; - /// The volume by which the solution has overflowed. - public readonly FixedPoint2 OverflowVol = Overflow.Volume; - /// Whether some subscriber has taken care of the effects of the overflow. - public bool Handled = false; -} - -/// -/// Ref event used to relay events raised on solution entities to their containers. -/// -/// -/// The event that is being relayed. -/// The container entity that the event is being relayed to. -/// The name of the solution entity that the event is being relayed from. -[ByRefEvent] -public record struct SolutionRelayEvent(TEvent Event, EntityUid ContainerEnt, string Name) -{ - public readonly EntityUid ContainerEnt = ContainerEnt; - public readonly string Name = Name; - public TEvent Event = Event; -} - -/// -/// Ref event used to relay events raised on solution containers to their contained solutions. -/// -/// -/// The event that is being relayed. -/// The solution entity that the event is being relayed to. -/// The name of the solution entity that the event is being relayed to. -[ByRefEvent] -public record struct SolutionContainerRelayEvent(TEvent Event, Entity SolutionEnt, string Name) -{ - public readonly Entity SolutionEnt = SolutionEnt; - public readonly string Name = Name; - public TEvent Event = Event; -} - -#endregion Events - -public abstract partial class SharedSolutionContainerSystem -{ - protected void InitializeRelays() - { - SubscribeLocalEvent(OnSolutionChanged); - SubscribeLocalEvent(OnSolutionOverflow); - SubscribeLocalEvent(RelaySolutionRefEvent); - } - - #region Event Handlers - - protected virtual void OnSolutionChanged(Entity entity, ref SolutionChangedEvent args) - { - var (solutionId, solutionComp) = args.Solution; - var solution = solutionComp.Solution; - - UpdateAppearance(entity.Comp.Container, (solutionId, solutionComp, entity.Comp)); - - var relayEvent = new SolutionContainerChangedEvent(solution, entity.Comp.ContainerName); - RaiseLocalEvent(entity.Comp.Container, ref relayEvent); - } - - protected virtual void OnSolutionOverflow(Entity entity, ref SolutionOverflowEvent args) - { - var solution = args.Solution.Comp.Solution; - var overflow = solution.SplitSolution(args.Overflow); - var relayEv = new SolutionContainerOverflowEvent(entity.Owner, solution, overflow) - { - Handled = args.Handled, - }; - - RaiseLocalEvent(entity.Comp.Container, ref relayEv); - args.Handled = relayEv.Handled; - } - - #region Relay Event Handlers - - private void RelaySolutionValEvent(EntityUid uid, ContainedSolutionComponent comp, TEvent @event) - { - var relayEvent = new SolutionRelayEvent(@event, uid, comp.ContainerName); - RaiseLocalEvent(comp.Container, ref relayEvent); - } - - private void RelaySolutionRefEvent(Entity entity, ref TEvent @event) - { - var relayEvent = new SolutionRelayEvent(@event, entity.Owner, entity.Comp.ContainerName); - RaiseLocalEvent(entity.Comp.Container, ref relayEvent); - @event = relayEvent.Event; - } - - private void RelaySolutionContainerEvent(EntityUid uid, SolutionContainerManagerComponent comp, TEvent @event) - { - foreach (var (name, soln) in EnumerateSolutions((uid, comp))) - { - var relayEvent = new SolutionContainerRelayEvent(@event, soln, name!); - RaiseLocalEvent(soln, ref relayEvent); - } - } - - private void RelaySolutionContainerEvent(Entity entity, ref TEvent @event) - { - foreach (var (name, soln) in EnumerateSolutions((entity.Owner, entity.Comp))) - { - var relayEvent = new SolutionContainerRelayEvent(@event, soln, name!); - RaiseLocalEvent(soln, ref relayEvent); - @event = relayEvent.Event; - } - } - - #endregion Relay Event Handlers - - #endregion Event Handlers -} diff --git a/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.cs b/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.cs deleted file mode 100644 index 392b83fe97..0000000000 --- a/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.cs +++ /dev/null @@ -1,857 +0,0 @@ -using Content.Shared.Chemistry.Components; -using Content.Shared.Chemistry.Components.SolutionManager; -using Content.Shared.Chemistry.Reaction; -using Content.Shared.Chemistry.Reagent; -using Content.Shared.Examine; -using Content.Shared.FixedPoint; -using Content.Shared.Verbs; -using JetBrains.Annotations; -using Robust.Shared.Containers; -using Robust.Shared.Prototypes; -using Robust.Shared.Utility; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Text; -using Dependency = Robust.Shared.IoC.DependencyAttribute; - -namespace Content.Shared.Chemistry.EntitySystems; - -/// -/// The event raised whenever a solution entity is modified. -/// -/// -/// Raised after chemcial reactions and are handled. -/// -/// The solution entity that has been modified. -[ByRefEvent] -public readonly partial record struct SolutionChangedEvent(Entity Solution); - -/// -/// The event raised whenever a solution entity is filled past its capacity. -/// -/// The solution entity that has been overfilled. -/// The amount by which the solution entity has been overfilled. -[ByRefEvent] -public partial record struct SolutionOverflowEvent(Entity Solution, FixedPoint2 Overflow) -{ - /// The solution entity that has been overfilled. - public readonly Entity Solution = Solution; - /// The amount by which the solution entity has been overfilled. - public readonly FixedPoint2 Overflow = Overflow; - /// Whether any of the event handlers for this event have handled overflow behaviour. - public bool Handled = false; -} - -/// -/// Part of Chemistry system deal with SolutionContainers -/// -[UsedImplicitly] -public abstract partial class SharedSolutionContainerSystem : EntitySystem -{ - [Dependency] protected readonly IPrototypeManager PrototypeManager = default!; - [Dependency] protected readonly ChemicalReactionSystem ChemicalReactionSystem = default!; - [Dependency] protected readonly ExamineSystemShared ExamineSystem = default!; - [Dependency] protected readonly SharedAppearanceSystem AppearanceSystem = default!; - [Dependency] protected readonly SharedContainerSystem ContainerSystem = default!; - - public override void Initialize() - { - base.Initialize(); - - InitializeRelays(); - - SubscribeLocalEvent(OnComponentInit); - SubscribeLocalEvent(OnComponentStartup); - SubscribeLocalEvent(OnComponentShutdown); - - SubscribeLocalEvent(OnComponentInit); - - SubscribeLocalEvent(OnExamineSolution); - SubscribeLocalEvent>(OnSolutionExaminableVerb); - } - - - /// - /// Attempts to resolve a solution associated with an entity. - /// - /// The entity that holdes the container the solution entity is in. - /// The name of the solution entities container. - /// A reference to a solution entity to load the associated solution entity into. Will be unchanged if not null. - /// Returns the solution state of the solution entity. - /// Whether the solution was successfully resolved. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool ResolveSolution(Entity container, string? name, [NotNullWhen(true)] ref Entity? entity, [NotNullWhen(true)] out Solution? solution) - { - if (!ResolveSolution(container, name, ref entity)) - { - solution = null; - return false; - } - - solution = entity.Value.Comp.Solution; - return true; - } - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool ResolveSolution(Entity container, string? name, [NotNullWhen(true)] ref Entity? entity) - { - if (entity is not null) - { - DebugTools.Assert(TryGetSolution(container, name, out var debugEnt) - && debugEnt.Value.Owner == entity.Value.Owner); - return true; - } - - return TryGetSolution(container, name, out entity); - } - - /// - /// Attempts to fetch a solution entity associated with an entity. - /// - /// - /// If the solution entity will be frequently accessed please use the equivalent method and cache the result. - /// - /// The entity the solution entity should be associated with. - /// The name of the solution entity to fetch. - /// Returns the solution entity that was fetched. - /// Returns the solution state of the solution entity that was fetched. - /// - public bool TryGetSolution(Entity container, string? name, [NotNullWhen(true)] out Entity? entity, [NotNullWhen(true)] out Solution? solution) - { - if (!TryGetSolution(container, name, out entity)) - { - solution = null; - return false; - } - - solution = entity.Value.Comp.Solution; - return true; - } - - /// - public bool TryGetSolution(Entity container, string? name, [NotNullWhen(true)] out Entity? entity) - { - EntityUid uid; - if (name is null) - uid = container; - else if ( - ContainerSystem.TryGetContainer(container, $"solution@{name}", out var solutionContainer) && - solutionContainer is ContainerSlot solutionSlot && - solutionSlot.ContainedEntity is { } containedSolution - ) - uid = containedSolution; - else - { - entity = null; - return false; - } - - if (!TryComp(uid, out SolutionComponent? comp)) - { - entity = null; - return false; - } - - entity = (uid, comp); - return true; - } - - public IEnumerable<(string? Name, Entity Solution)> EnumerateSolutions(Entity container, bool includeSelf = true) - { - if (includeSelf && TryComp(container, out SolutionComponent? solutionComp)) - yield return (null, (container.Owner, solutionComp)); - - if (!Resolve(container, ref container.Comp, logMissing: false)) - yield break; - - foreach (var name in container.Comp.Containers) - { - if (ContainerSystem.GetContainer(container, $"solution@{name}") is ContainerSlot slot && slot.ContainedEntity is { } solutionId) - yield return (name, (solutionId, Comp(solutionId))); - } - } - - public IEnumerable<(string Name, Solution Solution)> EnumerateSolutions(SolutionContainerManagerComponent container) - { - if (container.Solutions is not { Count: > 0 } solutions) - yield break; - - foreach (var (name, solution) in solutions) - { - yield return (name, solution); - } - } - - - protected void UpdateAppearance(Entity container, Entity soln) - { - var (uid, appearanceComponent) = container; - if (!HasComp(uid) || !Resolve(uid, ref appearanceComponent, logMissing: false)) - return; - - var (_, comp, relation) = soln; - var solution = comp.Solution; - - AppearanceSystem.SetData(uid, SolutionContainerVisuals.FillFraction, solution.FillFraction, appearanceComponent); - AppearanceSystem.SetData(uid, SolutionContainerVisuals.Color, solution.GetColor(PrototypeManager), appearanceComponent); - AppearanceSystem.SetData(uid, SolutionContainerVisuals.SolutionName, relation.ContainerName, appearanceComponent); - - if (solution.GetPrimaryReagentId() is { } reagent) - AppearanceSystem.SetData(uid, SolutionContainerVisuals.BaseOverride, reagent.ToString(), appearanceComponent); - else - AppearanceSystem.SetData(uid, SolutionContainerVisuals.BaseOverride, string.Empty, appearanceComponent); - } - - - public FixedPoint2 GetTotalPrototypeQuantity(EntityUid owner, string reagentId) - { - var reagentQuantity = FixedPoint2.New(0); - if (EntityManager.EntityExists(owner) - && EntityManager.TryGetComponent(owner, out SolutionContainerManagerComponent? managerComponent)) - { - foreach (var (_, soln) in EnumerateSolutions((owner, managerComponent))) - { - var solution = soln.Comp.Solution; - reagentQuantity += solution.GetTotalPrototypeQuantity(reagentId); - } - } - - return reagentQuantity; - } - - - /// - /// Dirties a solution entity that has been modified and prompts updates to chemical reactions and overflow state. - /// Should be invoked whenever a solution entity is modified. - /// - /// - /// 90% of this system is ensuring that this proc is invoked whenever a solution entity is changed. The other 10% is this proc. - /// - /// - /// - /// - public void UpdateChemicals(Entity soln, bool needsReactionsProcessing = true, ReactionMixerComponent? mixerComponent = null) - { - Dirty(soln); - - var (uid, comp) = soln; - var solution = comp.Solution; - - // Process reactions - if (needsReactionsProcessing && solution.CanReact) - ChemicalReactionSystem.FullyReactSolution(soln, mixerComponent); - - var overflow = solution.Volume - solution.MaxVolume; - if (overflow > FixedPoint2.Zero) - { - var overflowEv = new SolutionOverflowEvent(soln, overflow); - RaiseLocalEvent(uid, ref overflowEv); - } - - UpdateAppearance((uid, comp, null)); - - var changedEv = new SolutionChangedEvent(soln); - RaiseLocalEvent(uid, ref changedEv); - } - - public void UpdateAppearance(Entity soln) - { - var (uid, comp, appearanceComponent) = soln; - var solution = comp.Solution; - - if (!EntityManager.EntityExists(uid) || !Resolve(uid, ref appearanceComponent, false)) - return; - - AppearanceSystem.SetData(uid, SolutionContainerVisuals.FillFraction, solution.FillFraction, appearanceComponent); - AppearanceSystem.SetData(uid, SolutionContainerVisuals.Color, solution.GetColor(PrototypeManager), appearanceComponent); - - if (solution.GetPrimaryReagentId() is { } reagent) - AppearanceSystem.SetData(uid, SolutionContainerVisuals.BaseOverride, reagent.ToString(), appearanceComponent); - else - AppearanceSystem.SetData(uid, SolutionContainerVisuals.BaseOverride, string.Empty, appearanceComponent); - } - - /// - /// Removes part of the solution in the container. - /// - /// - /// - /// the volume of solution to remove. - /// The solution that was removed. - public Solution SplitSolution(Entity soln, FixedPoint2 quantity) - { - var (uid, comp) = soln; - var solution = comp.Solution; - - var splitSol = solution.SplitSolution(quantity); - UpdateChemicals(soln); - return splitSol; - } - - public Solution SplitStackSolution(Entity soln, FixedPoint2 quantity, int stackCount) - { - var (uid, comp) = soln; - var solution = comp.Solution; - - var splitSol = solution.SplitSolution(quantity / stackCount); - solution.SplitSolution(quantity - splitSol.Volume); - UpdateChemicals(soln); - return splitSol; - } - - /// - /// Splits a solution without the specified reagent(s). - /// - public Solution SplitSolutionWithout(Entity soln, FixedPoint2 quantity, params string[] reagents) - { - var (uid, comp) = soln; - var solution = comp.Solution; - - var splitSol = solution.SplitSolutionWithout(quantity, reagents); - UpdateChemicals(soln); - return splitSol; - } - - public void RemoveAllSolution(Entity soln) - { - var (uid, comp) = soln; - var solution = comp.Solution; - - if (solution.Volume == 0) - return; - - solution.RemoveAllSolution(); - UpdateChemicals(soln); - } - - /// - /// Sets the capacity (maximum volume) of a solution to a new value. - /// - /// The entity containing the solution. - /// The solution to set the capacity of. - /// The value to set the capacity of the solution to. - public void SetCapacity(Entity soln, FixedPoint2 capacity) - { - var (uid, comp) = soln; - var solution = comp.Solution; - - if (solution.MaxVolume == capacity) - return; - - solution.MaxVolume = capacity; - UpdateChemicals(soln); - } - - /// - /// Adds reagent of an Id to the container. - /// - /// - /// Container to which we are adding reagent - /// The reagent to add. - /// The amount of reagent successfully added. - /// If all the reagent could be added. - public bool TryAddReagent(Entity soln, ReagentQuantity reagentQuantity, out FixedPoint2 acceptedQuantity, float? temperature = null) - { - var (uid, comp) = soln; - var solution = comp.Solution; - - acceptedQuantity = solution.AvailableVolume > reagentQuantity.Quantity - ? reagentQuantity.Quantity - : solution.AvailableVolume; - - if (acceptedQuantity <= 0) - return reagentQuantity.Quantity == 0; - - if (temperature == null) - { - solution.AddReagent(reagentQuantity.Reagent, acceptedQuantity); - } - else - { - var proto = PrototypeManager.Index(reagentQuantity.Reagent.Prototype); - solution.AddReagent(proto, acceptedQuantity, temperature.Value, PrototypeManager); - } - - UpdateChemicals(soln); - return acceptedQuantity == reagentQuantity.Quantity; - } - - /// - /// Adds reagent of an Id to the container. - /// - /// - /// Container to which we are adding reagent - /// The Id of the reagent to add. - /// The amount of reagent to add. - /// If all the reagent could be added. - [PublicAPI] - public bool TryAddReagent(Entity soln, string prototype, FixedPoint2 quantity, float? temperature = null, ReagentData? data = null) - => TryAddReagent(soln, new ReagentQuantity(prototype, quantity, data), out _, temperature); - - /// - /// Adds reagent of an Id to the container. - /// - /// - /// Container to which we are adding reagent - /// The Id of the reagent to add. - /// The amount of reagent to add. - /// The amount of reagent successfully added. - /// If all the reagent could be added. - public bool TryAddReagent(Entity soln, string prototype, FixedPoint2 quantity, out FixedPoint2 acceptedQuantity, float? temperature = null, ReagentData? data = null) - { - var reagent = new ReagentQuantity(prototype, quantity, data); - return TryAddReagent(soln, reagent, out acceptedQuantity, temperature); - } - - /// - /// Adds reagent of an Id to the container. - /// - /// - /// Container to which we are adding reagent - /// The reagent to add. - /// The amount of reagent to add. - /// The amount of reagent successfully added. - /// If all the reagent could be added. - public bool TryAddReagent(Entity soln, ReagentId reagentId, FixedPoint2 quantity, out FixedPoint2 acceptedQuantity, float? temperature = null) - { - var quant = new ReagentQuantity(reagentId, quantity); - return TryAddReagent(soln, quant, out acceptedQuantity, temperature); - } - - /// - /// Removes reagent from a container. - /// - /// - /// Solution container from which we are removing reagent - /// The reagent to remove. - /// If the reagent to remove was found in the container. - public bool RemoveReagent(Entity soln, ReagentQuantity reagentQuantity) - { - var (uid, comp) = soln; - var solution = comp.Solution; - - var quant = solution.RemoveReagent(reagentQuantity); - if (quant <= FixedPoint2.Zero) - return false; - - UpdateChemicals(soln); - return true; - } - - /// - /// Removes reagent from a container. - /// - /// - /// Solution container from which we are removing reagent - /// The Id of the reagent to remove. - /// The amount of reagent to remove. - /// If the reagent to remove was found in the container. - public bool RemoveReagent(Entity soln, string prototype, FixedPoint2 quantity, ReagentData? data = null) - { - return RemoveReagent(soln, new ReagentQuantity(prototype, quantity, data)); - } - - /// - /// Removes reagent from a container. - /// - /// - /// Solution container from which we are removing reagent - /// The reagent to remove. - /// The amount of reagent to remove. - /// If the reagent to remove was found in the container. - public bool RemoveReagent(Entity soln, ReagentId reagentId, FixedPoint2 quantity) - { - return RemoveReagent(soln, new ReagentQuantity(reagentId, quantity)); - } - - /// - /// Moves some quantity of a solution from one solution to another. - /// - /// entity holding the source solution - /// entity holding the target solution - /// source solution - /// target solution - /// quantity of solution to move from source to target. If this is a negative number, the source & target roles are reversed. - public bool TryTransferSolution(Entity soln, Solution source, FixedPoint2 quantity) - { - var (uid, comp) = soln; - var solution = comp.Solution; - - if (quantity < 0) - throw new InvalidOperationException("Quantity must be positive"); - - quantity = FixedPoint2.Min(quantity, solution.AvailableVolume, source.Volume); - if (quantity == 0) - return false; - - // TODO This should be made into a function that directly transfers reagents. - // Currently this is quite inefficient. - solution.AddSolution(source.SplitSolution(quantity), PrototypeManager); - - UpdateChemicals(soln); - return true; - } - - /// - /// Adds a solution to the container, if it can fully fit. - /// - /// entity holding targetSolution - /// entity holding targetSolution - /// solution being added - /// If the solution could be added. - public bool TryAddSolution(Entity soln, Solution toAdd) - { - var (uid, comp) = soln; - var solution = comp.Solution; - - if (toAdd.Volume == FixedPoint2.Zero) - return true; - if (toAdd.Volume > solution.AvailableVolume) - return false; - - ForceAddSolution(soln, toAdd); - return true; - } - - /// - /// Adds as much of a solution to a container as can fit. - /// - /// The entity containing - /// The solution being added to. - /// The solution being added to - /// The quantity of the solution actually added. - public FixedPoint2 AddSolution(Entity soln, Solution toAdd) - { - var (uid, comp) = soln; - var solution = 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); - else - ForceAddSolution(soln, toAdd); - - return quantity; - } - - /// - /// Adds a solution to a container and updates the container. - /// - /// The entity containing - /// The solution being added to. - /// The solution being added to - /// Whether any reagents were added to the solution. - public bool ForceAddSolution(Entity soln, Solution toAdd) - { - var (uid, comp) = soln; - var solution = comp.Solution; - - if (toAdd.Volume == FixedPoint2.Zero) - return false; - - solution.AddSolution(toAdd, PrototypeManager); - UpdateChemicals(soln); - return true; - } - - /// - /// Adds a solution to the container, removing the overflow. - /// Unlike it will ignore size limits. - /// - /// The entity containing - /// The solution being added to. - /// The solution being added to - /// The combined volume above which the overflow will be returned. - /// If the combined volume is below this an empty solution is returned. - /// Solution that exceeded overflowThreshold - /// Whether any reagents were added to . - public bool TryMixAndOverflow(Entity soln, Solution toAdd, FixedPoint2 overflowThreshold, [MaybeNullWhen(false)] out Solution overflowingSolution) - { - var (uid, comp) = soln; - var solution = comp.Solution; - - if (toAdd.Volume == 0 || overflowThreshold > solution.MaxVolume) - { - overflowingSolution = null; - return false; - } - - solution.AddSolution(toAdd, PrototypeManager); - overflowingSolution = solution.SplitSolution(FixedPoint2.Max(FixedPoint2.Zero, solution.Volume - overflowThreshold)); - UpdateChemicals(soln); - return true; - } - - /// - /// Removes an amount from all reagents in a solution, adding it to a new solution. - /// - /// The entity containing the solution. - /// The solution to remove reagents from. - /// The amount to remove from every reagent in the solution. - /// A new solution containing every removed reagent from the original solution. - public Solution RemoveEachReagent(Entity soln, FixedPoint2 quantity) - { - var (uid, comp) = soln; - var solution = comp.Solution; - - if (quantity <= 0) - return new Solution(); - - var removedSolution = new Solution(); - - // RemoveReagent does a RemoveSwap, meaning we don't have to copy the list if we iterate it backwards. - for (var i = solution.Contents.Count - 1; i >= 0; i--) - { - var (reagent, _) = solution.Contents[i]; - var removedQuantity = solution.RemoveReagent(reagent, quantity); - removedSolution.AddReagent(reagent, removedQuantity); - } - - UpdateChemicals(soln); - return removedSolution; - } - - // Thermal energy and temperature management. - - #region Thermal Energy and Temperature - - /// - /// Sets the temperature of a solution to a new value and then checks for reaction processing. - /// - /// The entity in which the solution is located. - /// The solution to set the temperature of. - /// The new value to set the temperature to. - public void SetTemperature(Entity soln, float temperature) - { - var (_, comp) = soln; - var solution = comp.Solution; - - if (temperature == solution.Temperature) - return; - - solution.Temperature = temperature; - UpdateChemicals(soln); - } - - /// - /// Sets the thermal energy of a solution to a new value and then checks for reaction processing. - /// - /// The entity in which the solution is located. - /// The solution to set the thermal energy of. - /// The new value to set the thermal energy to. - public void SetThermalEnergy(Entity soln, float thermalEnergy) - { - var (_, comp) = soln; - var solution = comp.Solution; - - var heatCap = solution.GetHeatCapacity(PrototypeManager); - solution.Temperature = heatCap == 0 ? 0 : thermalEnergy / heatCap; - UpdateChemicals(soln); - } - - /// - /// Adds some thermal energy to a solution and then checks for reaction processing. - /// - /// The entity in which the solution is located. - /// The solution to set the thermal energy of. - /// The new value to set the thermal energy to. - public void AddThermalEnergy(Entity soln, float thermalEnergy) - { - var (_, comp) = soln; - var solution = comp.Solution; - - if (thermalEnergy == 0.0f) - return; - - var heatCap = solution.GetHeatCapacity(PrototypeManager); - solution.Temperature += heatCap == 0 ? 0 : thermalEnergy / heatCap; - UpdateChemicals(soln); - } - - #endregion Thermal Energy and Temperature - - #region Event Handlers - - private void OnComponentInit(Entity entity, ref ComponentInit args) - { - entity.Comp.Solution.ValidateSolution(); - } - - private void OnComponentStartup(Entity entity, ref ComponentStartup args) - { - UpdateChemicals(entity); - } - - private void OnComponentShutdown(Entity entity, ref ComponentShutdown args) - { - RemoveAllSolution(entity); - } - - private void OnComponentInit(Entity entity, ref ComponentInit args) - { - if (entity.Comp.Containers is not { Count: > 0 } containers) - return; - - var containerManager = EnsureComp(entity); - foreach (var name in containers) - { - // The actual solution entity should be directly held within the corresponding slot. - ContainerSystem.EnsureContainer(entity.Owner, $"solution@{name}", containerManager); - } - } - - private void OnExamineSolution(Entity entity, ref ExaminedEvent args) - { - if (!TryGetSolution(entity.Owner, entity.Comp.Solution, out _, out var solution)) - { - return; - } - - var primaryReagent = solution.GetPrimaryReagentId(); - - if (string.IsNullOrEmpty(primaryReagent?.Prototype)) - { - args.PushText(Loc.GetString("shared-solution-container-component-on-examine-empty-container")); - return; - } - - if (!PrototypeManager.TryIndex(primaryReagent.Value.Prototype, out ReagentPrototype? primary)) - { - Log.Error($"{nameof(Solution)} could not find the prototype associated with {primaryReagent}."); - return; - } - - var colorHex = solution.GetColor(PrototypeManager) - .ToHexNoAlpha(); //TODO: If the chem has a dark color, the examine text becomes black on a black background, which is unreadable. - var messageString = "shared-solution-container-component-on-examine-main-text"; - - args.PushMarkup(Loc.GetString(messageString, - ("color", colorHex), - ("wordedAmount", Loc.GetString(solution.Contents.Count == 1 - ? "shared-solution-container-component-on-examine-worded-amount-one-reagent" - : "shared-solution-container-component-on-examine-worded-amount-multiple-reagents")), - ("desc", primary.LocalizedPhysicalDescription))); - - var reagentPrototypes = solution.GetReagentPrototypes(PrototypeManager); - - // Sort the reagents by amount, descending then alphabetically - var sortedReagentPrototypes = reagentPrototypes - .OrderByDescending(pair => pair.Value.Value) - .ThenBy(pair => pair.Key.LocalizedName); - - // Add descriptions of immediately recognizable reagents, like water or beer - var recognized = new List(); - foreach (var keyValuePair in sortedReagentPrototypes) - { - var proto = keyValuePair.Key; - if (!proto.Recognizable) - { - continue; - } - - recognized.Add(proto); - } - - // Skip if there's nothing recognizable - if (recognized.Count == 0) - return; - - var msg = new StringBuilder(); - foreach (var reagent in recognized) - { - string part; - if (reagent == recognized[0]) - { - part = "examinable-solution-recognized-first"; - } - else if (reagent == recognized[^1]) - { - // this loc specifically requires space to be appended, fluent doesnt support whitespace - msg.Append(' '); - part = "examinable-solution-recognized-last"; - } - else - { - part = "examinable-solution-recognized-next"; - } - - msg.Append(Loc.GetString(part, ("color", reagent.SubstanceColor.ToHexNoAlpha()), - ("chemical", reagent.LocalizedName))); - } - - args.PushMarkup(Loc.GetString("examinable-solution-has-recognizable-chemicals", ("recognizedString", msg.ToString()))); - } - - private void OnSolutionExaminableVerb(Entity entity, ref GetVerbsEvent args) - { - if (!args.CanInteract || !args.CanAccess) - return; - - var scanEvent = new SolutionScanEvent(); - RaiseLocalEvent(args.User, scanEvent); - if (!scanEvent.CanScan) - { - return; - } - - if (!TryGetSolution(args.Target, entity.Comp.Solution, out _, out var solutionHolder)) - { - return; - } - - var target = args.Target; - var user = args.User; - var verb = new ExamineVerb() - { - Act = () => - { - var markup = GetSolutionExamine(solutionHolder); - ExamineSystem.SendExamineTooltip(user, target, markup, false, false); - }, - Text = Loc.GetString("scannable-solution-verb-text"), - Message = Loc.GetString("scannable-solution-verb-message"), - Category = VerbCategory.Examine, - Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/drink.svg.192dpi.png")), - }; - - args.Verbs.Add(verb); - } - - private FormattedMessage GetSolutionExamine(Solution solution) - { - var msg = new FormattedMessage(); - - if (solution.Volume == 0) - { - msg.AddMarkup(Loc.GetString("scannable-solution-empty-container")); - return msg; - } - - msg.AddMarkup(Loc.GetString("scannable-solution-main-text")); - - var reagentPrototypes = solution.GetReagentPrototypes(PrototypeManager); - - // Sort the reagents by amount, descending then alphabetically - var sortedReagentPrototypes = reagentPrototypes - .OrderByDescending(pair => pair.Value.Value) - .ThenBy(pair => pair.Key.LocalizedName); - - foreach (var (proto, quantity) in sortedReagentPrototypes) - { - msg.PushNewline(); - msg.AddMarkup(Loc.GetString("scannable-solution-chemical" - , ("type", proto.LocalizedName) - , ("color", proto.SubstanceColor.ToHexNoAlpha()) - , ("amount", quantity))); - } - - return msg; - } - - #endregion Event Handlers -} diff --git a/Content.Shared/Chemistry/EntitySystems/SolutionContainerSystem.Capabilities.cs b/Content.Shared/Chemistry/EntitySystems/SolutionContainerSystem.Capabilities.cs new file mode 100644 index 0000000000..3647ddb852 --- /dev/null +++ b/Content.Shared/Chemistry/EntitySystems/SolutionContainerSystem.Capabilities.cs @@ -0,0 +1,179 @@ +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Content.Shared.Chemistry.Components; +using Content.Shared.Chemistry.Components.SolutionManager; +using Content.Shared.FixedPoint; + +namespace Content.Shared.Chemistry.EntitySystems; + +public sealed partial class SolutionContainerSystem +{ + public void Refill(EntityUid targetUid, Solution targetSolution, Solution addedSolution, + RefillableSolutionComponent? refillableSolution = null) + { + if (!Resolve(targetUid, ref refillableSolution, false)) + return; + + TryAddSolution(targetUid, targetSolution, addedSolution); + } + + public void Inject(EntityUid targetUid, Solution targetSolution, Solution addedSolution, + InjectableSolutionComponent? injectableSolution = null) + { + if (!Resolve(targetUid, ref injectableSolution, false)) + return; + + TryAddSolution(targetUid, targetSolution, addedSolution); + } + + public Solution Draw(EntityUid targetUid, Solution solution, FixedPoint2 amount, + DrawableSolutionComponent? drawableSolution = null) + { + if (!Resolve(targetUid, ref drawableSolution, false)) + return new Solution(); + + return SplitSolution(targetUid, solution, amount); + } + + public Solution Drain(EntityUid targetUid, Solution targetSolution, FixedPoint2 amount, + DrainableSolutionComponent? drainableSolution = null) + { + if (!Resolve(targetUid, ref drainableSolution, false)) + return new Solution(); + + return SplitSolution(targetUid, targetSolution, amount); + } + + public bool TryGetInjectableSolution(EntityUid targetUid, + [NotNullWhen(true)] out Solution? solution, + InjectableSolutionComponent? injectable = null, + SolutionContainerManagerComponent? manager = null + ) + { + if (!Resolve(targetUid, ref manager, ref injectable, false) + || !manager.Solutions.TryGetValue(injectable.Solution, out solution)) + { + solution = null; + return false; + } + + return true; + } + + public bool TryGetRefillableSolution(EntityUid targetUid, + [NotNullWhen(true)] out Solution? solution, + SolutionContainerManagerComponent? solutionManager = null, + RefillableSolutionComponent? refillable = null) + { + if (!Resolve(targetUid, ref solutionManager, ref refillable, false) + || !solutionManager.Solutions.TryGetValue(refillable.Solution, out var refillableSolution)) + { + solution = null; + return false; + } + + solution = refillableSolution; + return true; + } + + public bool TryGetDrainableSolution(EntityUid uid, + [NotNullWhen(true)] out Solution? solution, + DrainableSolutionComponent? drainable = null, + SolutionContainerManagerComponent? manager = null) + { + if (!Resolve(uid, ref drainable, ref manager, false) + || !manager.Solutions.TryGetValue(drainable.Solution, out solution)) + { + solution = null; + return false; + } + + return true; + } + + public bool TryGetDumpableSolution(EntityUid uid, + [NotNullWhen(true)] out Solution? solution, + DumpableSolutionComponent? dumpable = null, + SolutionContainerManagerComponent? manager = null) + { + if (!Resolve(uid, ref dumpable, ref manager, false) + || !manager.Solutions.TryGetValue(dumpable.Solution, out solution)) + { + solution = null; + return false; + } + + return true; + } + + public bool TryGetDrawableSolution(EntityUid uid, + [NotNullWhen(true)] out Solution? solution, + DrawableSolutionComponent? drawable = null, + SolutionContainerManagerComponent? manager = null) + { + if (!Resolve(uid, ref drawable, ref manager, false) + || !manager.Solutions.TryGetValue(drawable.Solution, out solution)) + { + solution = null; + return false; + } + + return true; + } + + public FixedPoint2 DrainAvailable(EntityUid uid) + { + return !TryGetDrainableSolution(uid, out var solution) + ? FixedPoint2.Zero + : solution.Volume; + } + + public float PercentFull(EntityUid uid) + { + if (!TryGetDrainableSolution(uid, out var solution) || solution.MaxVolume.Equals(FixedPoint2.Zero)) + return 0; + + return solution.FillFraction * 100; + } + + public bool TryGetFitsInDispenser(EntityUid owner, + [NotNullWhen(true)] out Solution? solution, + FitsInDispenserComponent? dispenserFits = null, + SolutionContainerManagerComponent? solutionManager = null) + { + if (!Resolve(owner, ref dispenserFits, ref solutionManager, false) + || !solutionManager.Solutions.TryGetValue(dispenserFits.Solution, out solution)) + { + solution = null; + return false; + } + + return true; + } + + public static string ToPrettyString(Solution solution) + { + var sb = new StringBuilder(); + if (solution.Name == null) + sb.Append("["); + else + sb.Append($"{solution.Name}:["); + var first = true; + foreach (var (id, quantity) in solution.Contents) + { + if (first) + { + first = false; + } + else + { + sb.Append(", "); + } + + sb.AppendFormat("{0}: {1}u", id, quantity); + } + + sb.Append(']'); + return sb.ToString(); + } +} diff --git a/Content.Shared/Chemistry/EntitySystems/SolutionContainerSystem.cs b/Content.Shared/Chemistry/EntitySystems/SolutionContainerSystem.cs new file mode 100644 index 0000000000..f8fcbf996e --- /dev/null +++ b/Content.Shared/Chemistry/EntitySystems/SolutionContainerSystem.cs @@ -0,0 +1,871 @@ +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text; +using Content.Shared.Chemistry.Components; +using Content.Shared.Chemistry.Components.SolutionManager; +using Content.Shared.Chemistry.Reaction; +using Content.Shared.Chemistry.Reagent; +using Content.Shared.Examine; +using Content.Shared.FixedPoint; +using Content.Shared.Verbs; +using JetBrains.Annotations; +using Robust.Shared.Audio; +using Robust.Shared.Prototypes; +using Robust.Shared.Utility; + +namespace Content.Shared.Chemistry.EntitySystems; + +/// +/// This event alerts system that the solution was changed +/// +public sealed class SolutionChangedEvent : EntityEventArgs +{ + public readonly Solution Solution; + public readonly string SolutionId; + + public SolutionChangedEvent(Solution solution, string solutionId) + { + SolutionId = solutionId; + Solution = solution; + } +} + +/// +/// An event raised when more reagents are added to a (managed) solution than it can hold. +/// +[ByRefEvent] +public record struct SolutionOverflowEvent(EntityUid SolutionEnt, Solution SolutionHolder, Solution Overflow) +{ + /// The entity which contains the solution that has overflowed. + public readonly EntityUid SolutionEnt = SolutionEnt; + /// The solution that has overflowed. + public readonly Solution SolutionHolder = SolutionHolder; + /// The reagents that have overflowed the solution. + public readonly Solution Overflow = Overflow; + /// The volume by which the solution has overflowed. + public readonly FixedPoint2 OverflowVol = Overflow.Volume; + /// Whether some subscriber has taken care of the effects of the overflow. + public bool Handled = false; +} + +/// +/// Part of Chemistry system deal with SolutionContainers +/// +[UsedImplicitly] +public sealed partial class SolutionContainerSystem : EntitySystem +{ + [Dependency] private readonly ChemicalReactionSystem _chemistrySystem = default!; + + [Dependency] private readonly SharedAppearanceSystem _appearance = default!; + + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly ExamineSystemShared _examine = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(InitSolution); + SubscribeLocalEvent(OnExamineSolution); + SubscribeLocalEvent>(OnSolutionExaminableVerb); + } + + private void InitSolution(EntityUid uid, SolutionContainerManagerComponent component, ComponentInit args) + { + foreach (var (name, solutionHolder) in component.Solutions) + { + solutionHolder.Name = name; + solutionHolder.ValidateSolution(); + UpdateAppearance(uid, solutionHolder); + } + } + + private void OnSolutionExaminableVerb(EntityUid uid, ExaminableSolutionComponent component, GetVerbsEvent args) + { + if (!args.CanInteract || !args.CanAccess) + return; + + var scanEvent = new SolutionScanEvent(); + RaiseLocalEvent(args.User, scanEvent); + if (!scanEvent.CanScan) + { + return; + } + + SolutionContainerManagerComponent? solutionsManager = null; + if (!Resolve(args.Target, ref solutionsManager) + || !solutionsManager.Solutions.TryGetValue(component.Solution, out var solutionHolder)) + { + return; + } + + var verb = new ExamineVerb() + { + Act = () => + { + var markup = GetSolutionExamine(solutionHolder); + _examine.SendExamineTooltip(args.User, uid, markup, false, false); + }, + Text = Loc.GetString("scannable-solution-verb-text"), + Message = Loc.GetString("scannable-solution-verb-message"), + Category = VerbCategory.Examine, + Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/drink.svg.192dpi.png")), + }; + + args.Verbs.Add(verb); + } + + private FormattedMessage GetSolutionExamine(Solution solution) + { + var msg = new FormattedMessage(); + + if (solution.Volume == 0) + { + msg.AddMarkup(Loc.GetString("scannable-solution-empty-container")); + return msg; + } + + msg.AddMarkup(Loc.GetString("scannable-solution-main-text")); + + foreach (var (proto, quantity) in solution.GetReagentPrototypes(_prototypeManager)) + { + msg.PushNewline(); + msg.AddMarkup(Loc.GetString("scannable-solution-chemical" + , ("type", proto.LocalizedName) + , ("color", proto.SubstanceColor.ToHexNoAlpha()) + , ("amount", quantity))); + } + + return msg; + } + + private void OnExamineSolution(EntityUid uid, ExaminableSolutionComponent examinableComponent, + ExaminedEvent args) + { + SolutionContainerManagerComponent? solutionsManager = null; + if (!Resolve(args.Examined, ref solutionsManager) + || !solutionsManager.Solutions.TryGetValue(examinableComponent.Solution, out var solution)) + { + return; + } + + var primaryReagent = solution.GetPrimaryReagentId(); + + if (string.IsNullOrEmpty(primaryReagent?.Prototype)) + { + args.PushText(Loc.GetString("shared-solution-container-component-on-examine-empty-container")); + return; + } + + if (!_prototypeManager.TryIndex(primaryReagent.Value.Prototype, out ReagentPrototype? primary)) + { + Log.Error($"{nameof(Solution)} could not find the prototype associated with {primaryReagent}."); + return; + } + + var colorHex = solution.GetColor(_prototypeManager) + .ToHexNoAlpha(); //TODO: If the chem has a dark color, the examine text becomes black on a black background, which is unreadable. + var messageString = "shared-solution-container-component-on-examine-main-text"; + + args.PushMarkup(Loc.GetString(messageString, + ("color", colorHex), + ("wordedAmount", Loc.GetString(solution.Contents.Count == 1 + ? "shared-solution-container-component-on-examine-worded-amount-one-reagent" + : "shared-solution-container-component-on-examine-worded-amount-multiple-reagents")), + ("desc", primary.LocalizedPhysicalDescription))); + + + var reagentPrototypes = solution.GetReagentPrototypes(_prototypeManager); + + // Sort the reagents by amount, descending then alphabetically + var sortedReagentPrototypes = reagentPrototypes + .OrderByDescending(pair => pair.Value.Value) + .ThenBy(pair => pair.Key.LocalizedName); + + // Add descriptions of immediately recognizable reagents, like water or beer + var recognized = new List(); + foreach (var keyValuePair in sortedReagentPrototypes) + { + var proto = keyValuePair.Key; + if (!proto.Recognizable) + { + continue; + } + + recognized.Add(proto); + } + + // Skip if there's nothing recognizable + if (recognized.Count == 0) + return; + + var msg = new StringBuilder(); + foreach (var reagent in recognized) + { + string part; + if (reagent == recognized[0]) + { + part = "examinable-solution-recognized-first"; + } + else if (reagent == recognized[^1]) + { + // this loc specifically requires space to be appended, fluent doesnt support whitespace + msg.Append(' '); + part = "examinable-solution-recognized-last"; + } + else + { + part = "examinable-solution-recognized-next"; + } + + msg.Append(Loc.GetString(part, ("color", reagent.SubstanceColor.ToHexNoAlpha()), + ("chemical", reagent.LocalizedName))); + } + + args.PushMarkup(Loc.GetString("examinable-solution-has-recognizable-chemicals", ("recognizedString", msg.ToString()))); + } + + public void UpdateAppearance(EntityUid uid, Solution solution, + AppearanceComponent? appearanceComponent = null) + { + if (!HasComp(uid) || !Resolve(uid, ref appearanceComponent, false)) + return; + + _appearance.SetData(uid, SolutionContainerVisuals.FillFraction, solution.FillFraction, appearanceComponent); + _appearance.SetData(uid, SolutionContainerVisuals.Color, solution.GetColor(_prototypeManager), appearanceComponent); + if (solution.Name != null) + { + _appearance.SetData(uid, SolutionContainerVisuals.SolutionName, solution.Name, appearanceComponent); + } + + if (solution.GetPrimaryReagentId() is { } reagent) + { + _appearance.SetData(uid, SolutionContainerVisuals.BaseOverride, reagent.ToString(), appearanceComponent); + } + else + { + _appearance.SetData(uid, SolutionContainerVisuals.BaseOverride, string.Empty, appearanceComponent); + } + } + + /// + /// Removes part of the solution in the container. + /// + /// + /// + /// the volume of solution to remove. + /// The solution that was removed. + public Solution SplitSolution(EntityUid targetUid, Solution solutionHolder, FixedPoint2 quantity) + { + var splitSol = solutionHolder.SplitSolution(quantity); + UpdateChemicals(targetUid, solutionHolder); + return splitSol; + } + + public Solution SplitStackSolution(EntityUid targetUid, Solution solutionHolder, FixedPoint2 quantity, int stackCount) + { + var splitSol = solutionHolder.SplitSolution(quantity / stackCount); + solutionHolder.SplitSolution(quantity - splitSol.Volume); + UpdateChemicals(targetUid, solutionHolder); + return splitSol; + } + + /// + /// Splits a solution without the specified reagent(s). + /// + public Solution SplitSolutionWithout(EntityUid targetUid, Solution solutionHolder, FixedPoint2 quantity, + params string[] reagents) + { + var splitSol = solutionHolder.SplitSolutionWithout(quantity, reagents); + UpdateChemicals(targetUid, solutionHolder); + return splitSol; + } + + public void UpdateChemicals(EntityUid uid, Solution solutionHolder, bool needsReactionsProcessing = false, ReactionMixerComponent? mixerComponent = null) + { + DebugTools.Assert(solutionHolder.Name != null && TryGetSolution(uid, solutionHolder.Name, out var tmp) && tmp == solutionHolder); + + // Process reactions + if (needsReactionsProcessing && solutionHolder.CanReact) + { + _chemistrySystem.FullyReactSolution(solutionHolder, uid, solutionHolder.MaxVolume, mixerComponent); + } + + var overflowVol = solutionHolder.Volume - solutionHolder.MaxVolume; + if (overflowVol > FixedPoint2.Zero) + { + var overflow = solutionHolder.SplitSolution(overflowVol); + var overflowEv = new SolutionOverflowEvent(uid, solutionHolder, overflow); + RaiseLocalEvent(uid, ref overflowEv); + } + + UpdateAppearance(uid, solutionHolder); + RaiseLocalEvent(uid, new SolutionChangedEvent(solutionHolder, solutionHolder.Name)); + } + + public void RemoveAllSolution(EntityUid uid, Solution solutionHolder) + { + if (solutionHolder.Volume == 0) + return; + + solutionHolder.RemoveAllSolution(); + UpdateChemicals(uid, solutionHolder); + } + + public void RemoveAllSolution(EntityUid uid, SolutionContainerManagerComponent? solutionContainerManager = null) + { + if (!Resolve(uid, ref solutionContainerManager)) + return; + + foreach (var solution in solutionContainerManager.Solutions.Values) + { + RemoveAllSolution(uid, solution); + } + } + + /// + /// Sets the capacity (maximum volume) of a solution to a new value. + /// + /// The entity containing the solution. + /// The solution to set the capacity of. + /// The value to set the capacity of the solution to. + public void SetCapacity(EntityUid targetUid, Solution targetSolution, FixedPoint2 capacity) + { + if (targetSolution.MaxVolume == capacity) + return; + + targetSolution.MaxVolume = capacity; + if (capacity < targetSolution.Volume) + targetSolution.RemoveSolution(targetSolution.Volume - capacity); + + UpdateChemicals(targetUid, targetSolution); + } + + /// + /// Adds reagent of an Id to the container. + /// + /// + /// Container to which we are adding reagent + /// The reagent to add. + /// The amount of reagent successfully added. + /// If all the reagent could be added. + public bool TryAddReagent(EntityUid targetUid, Solution targetSolution, ReagentQuantity reagentQuantity, + out FixedPoint2 acceptedQuantity, float? temperature = null) + { + acceptedQuantity = targetSolution.AvailableVolume > reagentQuantity.Quantity + ? reagentQuantity.Quantity + : targetSolution.AvailableVolume; + + if (acceptedQuantity <= 0) + return reagentQuantity.Quantity == 0; + + if (temperature == null) + { + targetSolution.AddReagent(reagentQuantity.Reagent, acceptedQuantity); + } + else + { + var proto = _prototypeManager.Index(reagentQuantity.Reagent.Prototype); + targetSolution.AddReagent(proto, acceptedQuantity, temperature.Value, _prototypeManager); + } + + UpdateChemicals(targetUid, targetSolution, true); + return acceptedQuantity == reagentQuantity.Quantity; + } + + /// + /// Adds reagent of an Id to the container. + /// + /// + /// Container to which we are adding reagent + /// The Id of the reagent to add. + /// The amount of reagent to add. + /// If all the reagent could be added. + [PublicAPI] + public bool TryAddReagent(EntityUid targetUid, Solution targetSolution, string prototype, FixedPoint2 quantity, + float? temperature = null, ReagentData? data = null) + { + var reagent = new ReagentQuantity(prototype, quantity, data); + return TryAddReagent(targetUid, targetSolution, reagent, out _, temperature); + } + + /// + /// Adds reagent of an Id to the container. + /// + /// + /// Container to which we are adding reagent + /// The Id of the reagent to add. + /// The amount of reagent to add. + /// The amount of reagent successfully added. + /// If all the reagent could be added. + public bool TryAddReagent(EntityUid targetUid, Solution targetSolution, string prototype, FixedPoint2 quantity, + out FixedPoint2 acceptedQuantity, float? temperature = null, ReagentData? data = null) + { + var reagent = new ReagentQuantity(prototype, quantity, data); + return TryAddReagent(targetUid, targetSolution, reagent, out acceptedQuantity, temperature); + } + + /// + /// Adds reagent of an Id to the container. + /// + /// + /// Container to which we are adding reagent + /// The reagent to add. + /// The amount of reagent to add. + /// The amount of reagent successfully added. + /// If all the reagent could be added. + public bool TryAddReagent(EntityUid targetUid, Solution targetSolution, ReagentId reagentId, FixedPoint2 quantity, + out FixedPoint2 acceptedQuantity, float? temperature = null) + { + var quant = new ReagentQuantity(reagentId, quantity); + return TryAddReagent(targetUid, targetSolution, quant, out acceptedQuantity, temperature); + } + + /// + /// Removes reagent from a container. + /// + /// + /// Solution container from which we are removing reagent + /// The reagent to remove. + /// If the reagent to remove was found in the container. + public bool RemoveReagent(EntityUid targetUid, Solution? container, ReagentQuantity reagentQuantity) + { + if (container == null) + return false; + + var quant = container.RemoveReagent(reagentQuantity); + if (quant <= FixedPoint2.Zero) + return false; + + UpdateChemicals(targetUid, container); + return true; + } + + /// + /// Removes reagent from a container. + /// + /// + /// Solution container from which we are removing reagent + /// The Id of the reagent to remove. + /// The amount of reagent to remove. + /// If the reagent to remove was found in the container. + public bool RemoveReagent(EntityUid targetUid, Solution? container, string prototype, FixedPoint2 quantity, ReagentData? data = null) + { + return RemoveReagent(targetUid, container, new ReagentQuantity(prototype, quantity, data)); + } + + /// + /// Removes reagent from a container. + /// + /// + /// Solution container from which we are removing reagent + /// The reagent to remove. + /// The amount of reagent to remove. + /// If the reagent to remove was found in the container. + public bool RemoveReagent(EntityUid targetUid, Solution? container, ReagentId reagentId, FixedPoint2 quantity) + { + return RemoveReagent(targetUid, container, new ReagentQuantity(reagentId, quantity)); + } + + /// + /// Moves some quantity of a solution from one solution to another. + /// + /// entity holding the source solution + /// entity holding the target solution + /// source solution + /// target solution + /// quantity of solution to move from source to target. If this is a negative number, the source & target roles are reversed. + public bool TryTransferSolution(EntityUid sourceUid, EntityUid targetUid, Solution source, Solution target, FixedPoint2 quantity) + { + if (!TryTransferSolution(targetUid, target, source, quantity)) + return false; + + UpdateChemicals(sourceUid, source, false); + return true; + } + + /// + /// Moves some quantity of a solution from one solution to another. + /// + /// entity holding the source solution + /// entity holding the target solution + /// source solution + /// target solution + /// quantity of solution to move from source to target. If this is a negative number, the source & target roles are reversed. + public bool TryTransferSolution(EntityUid targetUid, Solution target, Solution source, FixedPoint2 quantity) + { + if (quantity < 0) + throw new InvalidOperationException("Quantity must be positive"); + + quantity = FixedPoint2.Min(quantity, target.AvailableVolume, source.Volume); + if (quantity == 0) + return false; + + // TODO This should be made into a function that directly transfers reagents. + // Currently this is quite inefficient. + target.AddSolution(source.SplitSolution(quantity), _prototypeManager); + + UpdateChemicals(targetUid, target, true); + return true; + } + + /// + /// Moves some quantity of a solution from one solution to another. + /// + /// entity holding the source solution + /// entity holding the target solution + /// source solution + /// target solution + /// quantity of solution to move from source to target. If this is a negative number, the source & target roles are reversed. + public bool TryTransferSolution(EntityUid sourceUid, EntityUid targetUid, string source, string target, FixedPoint2 quantity) + { + if (!TryGetSolution(sourceUid, source, out var sourceSoln)) + return false; + + if (!TryGetSolution(targetUid, target, out var targetSoln)) + return false; + + return TryTransferSolution(sourceUid, targetUid, sourceSoln, targetSoln, quantity); + } + + /// + /// Adds a solution to the container, if it can fully fit. + /// + /// entity holding targetSolution + /// entity holding targetSolution + /// solution being added + /// If the solution could be added. + public bool TryAddSolution(EntityUid targetUid, Solution targetSolution, Solution toAdd) + { + if (toAdd.Volume == FixedPoint2.Zero) + return true; + if (toAdd.Volume > targetSolution.AvailableVolume) + return false; + + ForceAddSolution(targetUid, targetSolution, toAdd); + return true; + } + + /// + /// Adds as much of a solution to a container as can fit. + /// + /// The entity containing + /// The solution being added to. + /// The solution being added to + /// The quantity of the solution actually added. + public FixedPoint2 AddSolution(EntityUid targetUid, Solution targetSolution, Solution toAdd) + { + if (toAdd.Volume == FixedPoint2.Zero) + return FixedPoint2.Zero; + + var quantity = FixedPoint2.Max(FixedPoint2.Zero, FixedPoint2.Min(toAdd.Volume, targetSolution.AvailableVolume)); + if (quantity < toAdd.Volume) + TryTransferSolution(targetUid, targetSolution, toAdd, quantity); + else + ForceAddSolution(targetUid, targetSolution, toAdd); + + return quantity; + } + + /// + /// Adds a solution to a container and updates the container. + /// + /// The entity containing + /// The solution being added to. + /// The solution being added to + /// Whether any reagents were added to the solution. + public bool ForceAddSolution(EntityUid targetUid, Solution targetSolution, Solution toAdd) + { + if (toAdd.Volume == FixedPoint2.Zero) + return false; + + targetSolution.AddSolution(toAdd, _prototypeManager); + UpdateChemicals(targetUid, targetSolution, needsReactionsProcessing: true); + return true; + } + + /// + /// Adds a solution to the container, removing the overflow. + /// Unlike it will ignore size limits. + /// + /// The entity containing + /// The solution being added to. + /// The solution being added to + /// The combined volume above which the overflow will be returned. + /// If the combined volume is below this an empty solution is returned. + /// Solution that exceeded overflowThreshold + /// Whether any reagents were added to . + public bool TryMixAndOverflow(EntityUid targetUid, Solution targetSolution, + Solution toAdd, + FixedPoint2 overflowThreshold, + [NotNullWhen(true)] out Solution? overflowingSolution) + { + if (toAdd.Volume == 0 || overflowThreshold > targetSolution.MaxVolume) + { + overflowingSolution = null; + return false; + } + + targetSolution.AddSolution(toAdd, _prototypeManager); + overflowingSolution = targetSolution.SplitSolution(FixedPoint2.Max(FixedPoint2.Zero, targetSolution.Volume - overflowThreshold)); + UpdateChemicals(targetUid, targetSolution, true); + return true; + } + + public bool TryGetSolution([NotNullWhen(true)] EntityUid? uid, string name, + [NotNullWhen(true)] out Solution? solution, + SolutionContainerManagerComponent? solutionsMgr = null) + { + if (uid == null || !Resolve(uid.Value, ref solutionsMgr, false)) + { + solution = null; + return false; + } + + return solutionsMgr.Solutions.TryGetValue(name, out solution); + } + + + /// + /// Will ensure a solution is added to given entity even if it's missing solutionContainerManager + /// + /// EntityUid to which to add solution + /// name for the solution + /// solution components used in resolves + /// true if the solution already existed + /// solution + public Solution EnsureSolution(EntityUid uid, string name, out bool existed, + SolutionContainerManagerComponent? solutionsMgr = null) + { + if (!Resolve(uid, ref solutionsMgr, false)) + { + solutionsMgr = EntityManager.EnsureComponent(uid); + } + + if (!solutionsMgr.Solutions.TryGetValue(name, out var existing)) + { + var newSolution = new Solution() { Name = name }; + solutionsMgr.Solutions.Add(name, newSolution); + existed = false; + return newSolution; + } + + existed = true; + return existing; + } + + /// + /// Will ensure a solution is added to given entity even if it's missing solutionContainerManager + /// + /// EntityUid to which to add solution + /// name for the solution + /// solution components used in resolves + /// solution + public Solution EnsureSolution(EntityUid uid, string name, SolutionContainerManagerComponent? solutionsMgr = null) + => EnsureSolution(uid, name, out _, solutionsMgr); + + /// + /// Will ensure a solution is added to given entity even if it's missing solutionContainerManager + /// + /// EntityUid to which to add solution + /// name for the solution + /// Ensures that the solution's maximum volume is larger than this value. + /// solution components used in resolves + /// solution + public Solution EnsureSolution(EntityUid uid, string name, FixedPoint2 minVol, out bool existed, + SolutionContainerManagerComponent? solutionsMgr = null) + { + if (!Resolve(uid, ref solutionsMgr, false)) + { + solutionsMgr = EntityManager.EnsureComponent(uid); + } + + if (!solutionsMgr.Solutions.TryGetValue(name, out var existing)) + { + var newSolution = new Solution() { Name = name }; + solutionsMgr.Solutions.Add(name, newSolution); + existed = false; + newSolution.MaxVolume = minVol; + return newSolution; + } + + existed = true; + existing.MaxVolume = FixedPoint2.Max(existing.MaxVolume, minVol); + return existing; + } + + public Solution EnsureSolution(EntityUid uid, string name, + IEnumerable reagents, + bool setMaxVol = true, + SolutionContainerManagerComponent? solutionsMgr = null) + { + if (!Resolve(uid, ref solutionsMgr, false)) + solutionsMgr = EntityManager.EnsureComponent(uid); + + if (!solutionsMgr.Solutions.TryGetValue(name, out var existing)) + { + var newSolution = new Solution(reagents, setMaxVol); + solutionsMgr.Solutions.Add(name, newSolution); + return newSolution; + } + + existing.SetContents(reagents, setMaxVol); + return existing; + } + /// + /// Removes an amount from all reagents in a solution, adding it to a new solution. + /// + /// The entity containing the solution. + /// The solution to remove reagents from. + /// The amount to remove from every reagent in the solution. + /// A new solution containing every removed reagent from the original solution. + public Solution RemoveEachReagent(EntityUid uid, Solution solution, FixedPoint2 quantity) + { + if (quantity <= 0) + return new Solution(); + + var removedSolution = new Solution(); + + // RemoveReagent does a RemoveSwap, meaning we don't have to copy the list if we iterate it backwards. + for (var i = solution.Contents.Count - 1; i >= 0; i--) + { + var (reagent, _) = solution.Contents[i]; + var removedQuantity = solution.RemoveReagent(reagent, quantity); + removedSolution.AddReagent(reagent, removedQuantity); + } + + UpdateChemicals(uid, solution); + return removedSolution; + } + + public FixedPoint2 GetTotalPrototypeQuantity(EntityUid owner, string reagentId) + { + var reagentQuantity = FixedPoint2.New(0); + if (EntityManager.EntityExists(owner) + && EntityManager.TryGetComponent(owner, out SolutionContainerManagerComponent? managerComponent)) + { + foreach (var solution in managerComponent.Solutions.Values) + { + reagentQuantity += solution.GetTotalPrototypeQuantity(reagentId); + } + } + + return reagentQuantity; + } + + public bool TryGetMixableSolution(EntityUid uid, + [NotNullWhen(true)] out Solution? solution, + SolutionContainerManagerComponent? solutionsMgr = null) + { + + if (!Resolve(uid, ref solutionsMgr, false)) + { + solution = null; + return false; + } + + var getMixableSolutionAttempt = new GetMixableSolutionAttemptEvent(uid); + RaiseLocalEvent(uid, ref getMixableSolutionAttempt); + if (getMixableSolutionAttempt.MixedSolution != null) + { + solution = getMixableSolutionAttempt.MixedSolution; + return true; + } + + var tryGetSolution = solutionsMgr.Solutions.FirstOrNull(x => x.Value.CanMix); + if (tryGetSolution.HasValue) + { + solution = tryGetSolution.Value.Value; + return true; + } + + solution = null; + return false; + } + + /// + /// Gets the most common reagent across all solutions by volume. + /// + /// + public ReagentPrototype? GetMaxReagent(SolutionContainerManagerComponent component) + { + if (component.Solutions.Count == 0) + return null; + + var reagentCounts = new Dictionary(); + + foreach (var solution in component.Solutions.Values) + { + foreach (var (reagent, quantity) in solution.Contents) + { + reagentCounts.TryGetValue(reagent, out var existing); + existing += quantity; + reagentCounts[reagent] = existing; + } + } + + var max = reagentCounts.Max(); + + return _prototypeManager.Index(max.Key.Prototype); + } + + public SoundSpecifier? GetSound(SolutionContainerManagerComponent component) + { + var max = GetMaxReagent(component); + return max?.FootstepSound; + } + + // Thermal energy and temperature management. + + #region Thermal Energy and Temperature + + /// + /// Sets the temperature of a solution to a new value and then checks for reaction processing. + /// + /// The entity in which the solution is located. + /// The solution to set the temperature of. + /// The new value to set the temperature to. + public void SetTemperature(EntityUid owner, Solution solution, float temperature) + { + if (temperature == solution.Temperature) + return; + + solution.Temperature = temperature; + UpdateChemicals(owner, solution, true); + } + + /// + /// Sets the thermal energy of a solution to a new value and then checks for reaction processing. + /// + /// The entity in which the solution is located. + /// The solution to set the thermal energy of. + /// The new value to set the thermal energy to. + public void SetThermalEnergy(EntityUid owner, Solution solution, float thermalEnergy) + { + var heatCap = solution.GetHeatCapacity(_prototypeManager); + solution.Temperature = heatCap == 0 ? 0 : thermalEnergy / heatCap; + UpdateChemicals(owner, solution, true); + } + + /// + /// Adds some thermal energy to a solution and then checks for reaction processing. + /// + /// The entity in which the solution is located. + /// The solution to set the thermal energy of. + /// The new value to set the thermal energy to. + public void AddThermalEnergy(EntityUid owner, Solution solution, float thermalEnergy) + { + if (thermalEnergy == 0.0f) + return; + + var heatCap = solution.GetHeatCapacity(_prototypeManager); + solution.Temperature += heatCap == 0 ? 0 : thermalEnergy / heatCap; + UpdateChemicals(owner, solution, true); + } + + #endregion Thermal Energy and Temperature + + #region Event Handlers + + #endregion Event Handlers +} diff --git a/Content.Shared/Chemistry/Reaction/ChemicalReactionSystem.cs b/Content.Shared/Chemistry/Reaction/ChemicalReactionSystem.cs index dcd135e3ab..05e176da5b 100644 --- a/Content.Shared/Chemistry/Reaction/ChemicalReactionSystem.cs +++ b/Content.Shared/Chemistry/Reaction/ChemicalReactionSystem.cs @@ -1,13 +1,14 @@ +using System.Collections.Frozen; +using System.Linq; using Content.Shared.Administration.Logs; using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Reagent; using Content.Shared.Database; using Content.Shared.FixedPoint; +using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; using Robust.Shared.Prototypes; using Robust.Shared.Utility; -using System.Collections.Frozen; -using System.Linq; namespace Content.Shared.Chemistry.Reaction { @@ -48,7 +49,7 @@ namespace Content.Shared.Chemistry.Reaction { // Construct single-reaction dictionary. var dict = new Dictionary>(); - foreach (var reaction in _prototypeManager.EnumeratePrototypes()) + foreach(var reaction in _prototypeManager.EnumeratePrototypes()) { // For this dictionary we only need to cache based on the first reagent. var reagent = reaction.Reactants.Keys.First(); @@ -58,7 +59,7 @@ namespace Content.Shared.Chemistry.Reaction _reactionsSingle = dict.ToFrozenDictionary(); dict.Clear(); - foreach (var reaction in _prototypeManager.EnumeratePrototypes()) + foreach(var reaction in _prototypeManager.EnumeratePrototypes()) { foreach (var reagent in reaction.Reactants.Keys) { @@ -86,10 +87,8 @@ namespace Content.Shared.Chemistry.Reaction /// The reaction to check. /// How many times this reaction can occur. /// - private bool CanReact(Entity soln, ReactionPrototype reaction, ReactionMixerComponent? mixerComponent, out FixedPoint2 lowestUnitReactions) + private bool CanReact(Solution solution, ReactionPrototype reaction, EntityUid owner, ReactionMixerComponent? mixerComponent, out FixedPoint2 lowestUnitReactions) { - var solution = soln.Comp.Solution; - lowestUnitReactions = FixedPoint2.MaxValue; if (solution.Temperature < reaction.MinimumTemperature) { @@ -102,15 +101,15 @@ namespace Content.Shared.Chemistry.Reaction return false; } - if ((mixerComponent == null && reaction.MixingCategories != null) || + if((mixerComponent == null && reaction.MixingCategories != null) || mixerComponent != null && reaction.MixingCategories != null && reaction.MixingCategories.Except(mixerComponent.ReactionTypes).Any()) { lowestUnitReactions = FixedPoint2.Zero; return false; } - var attempt = new ReactionAttemptEvent(reaction, soln); - RaiseLocalEvent(soln, ref attempt); + var attempt = new ReactionAttemptEvent(reaction, solution); + RaiseLocalEvent(owner, attempt); if (attempt.Cancelled) { lowestUnitReactions = FixedPoint2.Zero; @@ -156,11 +155,8 @@ namespace Content.Shared.Chemistry.Reaction /// Perform a reaction on a solution. This assumes all reaction criteria are met. /// Removes the reactants from the solution, adds products, and returns a list of products. /// - private List PerformReaction(Entity soln, ReactionPrototype reaction, FixedPoint2 unitReactions) + private List PerformReaction(Solution solution, EntityUid owner, ReactionPrototype reaction, FixedPoint2 unitReactions) { - var (uid, comp) = soln; - var solution = comp.Solution; - var energy = reaction.ConserveEnergy ? solution.GetThermalEnergy(_prototypeManager) : 0; //Remove reactants @@ -188,20 +184,20 @@ namespace Content.Shared.Chemistry.Reaction solution.Temperature = energy / newCap; } - OnReaction(soln, reaction, null, unitReactions); + OnReaction(solution, reaction, null, owner, unitReactions); return products; } - private void OnReaction(Entity soln, ReactionPrototype reaction, ReagentPrototype? reagent, FixedPoint2 unitReactions) + private void OnReaction(Solution solution, ReactionPrototype reaction, ReagentPrototype? reagent, EntityUid owner, FixedPoint2 unitReactions) { - var args = new ReagentEffectArgs(soln, null, soln.Comp.Solution, + var args = new ReagentEffectArgs(owner, null, solution, reagent, unitReactions, EntityManager, null, 1f); - var coordinates = Transform(soln).Coordinates; + var coordinates = Transform(owner).Coordinates; _adminLogger.Add(LogType.ChemicalReaction, reaction.Impact, - $"Chemical reaction {reaction.ID:reaction} occurred with strength {unitReactions:strength} on entity {ToPrettyString(soln):metabolizer} at {coordinates}"); + $"Chemical reaction {reaction.ID:reaction} occurred with strength {unitReactions:strength} on entity {ToPrettyString(owner):metabolizer} at {coordinates}"); foreach (var effect in reaction.Effects) { @@ -218,7 +214,7 @@ namespace Content.Shared.Chemistry.Reaction effect.Effect(args); } - _audio.PlayPvs(reaction.Sound, soln); + _audio.PlayPvs(reaction.Sound, owner); } /// @@ -226,7 +222,7 @@ namespace Content.Shared.Chemistry.Reaction /// Removes the reactants from the solution, then returns a solution with all products. /// WARNING: Does not trigger reactions between solution and new products. /// - private bool ProcessReactions(Entity soln, SortedSet reactions, ReactionMixerComponent? mixerComponent) + private bool ProcessReactions(Solution solution, EntityUid owner, FixedPoint2 maxVolume, SortedSet reactions, ReactionMixerComponent? mixerComponent) { HashSet toRemove = new(); List? products = null; @@ -234,13 +230,13 @@ namespace Content.Shared.Chemistry.Reaction // attempt to perform any applicable reaction foreach (var reaction in reactions) { - if (!CanReact(soln, reaction, mixerComponent, out var unitReactions)) + if (!CanReact(solution, reaction, owner, mixerComponent, out var unitReactions)) { toRemove.Add(reaction); continue; } - products = PerformReaction(soln, reaction, unitReactions); + products = PerformReaction(solution, owner, reaction, unitReactions); break; } @@ -265,11 +261,11 @@ namespace Content.Shared.Chemistry.Reaction /// /// Continually react a solution until no more reactions occur, with a volume constraint. /// - public void FullyReactSolution(Entity soln, ReactionMixerComponent? mixerComponent = null) + public void FullyReactSolution(Solution solution, EntityUid owner, FixedPoint2 maxVolume, ReactionMixerComponent? mixerComponent = null) { // construct the initial set of reactions to check. SortedSet reactions = new(); - foreach (var reactant in soln.Comp.Solution.Contents) + foreach (var reactant in solution.Contents) { if (_reactionsSingle.TryGetValue(reactant.Reagent.Prototype, out var reactantReactions)) reactions.UnionWith(reactantReactions); @@ -279,11 +275,11 @@ namespace Content.Shared.Chemistry.Reaction // exceed the iteration limit. for (var i = 0; i < MaxReactionIterations; i++) { - if (!ProcessReactions(soln, reactions, mixerComponent)) + if (!ProcessReactions(solution, owner, maxVolume, reactions, mixerComponent)) return; } - Log.Error($"{nameof(Solution)} {soln.Owner} could not finish reacting in under {MaxReactionIterations} loops."); + Log.Error($"{nameof(Solution)} {owner} could not finish reacting in under {MaxReactionIterations} loops."); } } @@ -293,11 +289,15 @@ namespace Content.Shared.Chemistry.Reaction /// /// Some solution containers (e.g., bloodstream, smoke, foam) use this to block certain reactions from occurring. /// - [ByRefEvent] - public record struct ReactionAttemptEvent(ReactionPrototype Reaction, Entity Solution) + public sealed class ReactionAttemptEvent : CancellableEntityEventArgs { - public readonly ReactionPrototype Reaction = Reaction; - public readonly Entity Solution = Solution; - public bool Cancelled = false; + public readonly ReactionPrototype Reaction; + public readonly Solution Solution; + + public ReactionAttemptEvent(ReactionPrototype reaction, Solution solution) + { + Reaction = reaction; + Solution = solution; + } } } diff --git a/Content.Shared/Chemistry/Reaction/ReactionMixerComponent.cs b/Content.Shared/Chemistry/Reaction/ReactionMixerComponent.cs index ede73c4969..a88bf02bf8 100644 --- a/Content.Shared/Chemistry/Reaction/ReactionMixerComponent.cs +++ b/Content.Shared/Chemistry/Reaction/ReactionMixerComponent.cs @@ -27,4 +27,4 @@ public record struct MixingAttemptEvent(EntityUid Mixed, bool Cancelled = false) public readonly record struct AfterMixingEvent(EntityUid Mixed, EntityUid Mixer); [ByRefEvent] -public record struct GetMixableSolutionAttemptEvent(EntityUid Mixed, Entity? MixedSolution = null); +public record struct GetMixableSolutionAttemptEvent(EntityUid Mixed, Solution? MixedSolution = null); diff --git a/Content.Shared/Chemistry/ReactiveSystem.cs b/Content.Shared/Chemistry/ReactiveSystem.cs index 57b008de0c..4881a6bf96 100644 --- a/Content.Shared/Chemistry/ReactiveSystem.cs +++ b/Content.Shared/Chemistry/ReactiveSystem.cs @@ -3,6 +3,7 @@ using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Reaction; using Content.Shared.Chemistry.Reagent; using Content.Shared.Database; +using Content.Shared.FixedPoint; using JetBrains.Annotations; using Robust.Shared.Prototypes; using Robust.Shared.Random; diff --git a/Content.Shared/Chemistry/SharedChemMaster.cs b/Content.Shared/Chemistry/SharedChemMaster.cs index 762131d761..027002098e 100644 --- a/Content.Shared/Chemistry/SharedChemMaster.cs +++ b/Content.Shared/Chemistry/SharedChemMaster.cs @@ -1,3 +1,4 @@ +using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Reagent; using Content.Shared.FixedPoint; using Robust.Shared.Serialization; diff --git a/Content.Shared/Fluids/Components/DrainComponent.cs b/Content.Shared/Fluids/Components/DrainComponent.cs index 4fb4fe9438..84331851d1 100644 --- a/Content.Shared/Fluids/Components/DrainComponent.cs +++ b/Content.Shared/Fluids/Components/DrainComponent.cs @@ -1,4 +1,3 @@ -using Content.Shared.Chemistry.Components; using Content.Shared.Tag; using Robust.Shared.Audio; @@ -20,9 +19,6 @@ public sealed partial class DrainComponent : Component [ValidatePrototypeId] public const string PlungerTag = "Plunger"; - [DataField] - public Entity? Solution = null; - [DataField("accumulator")] public float Accumulator = 0f; diff --git a/Content.Shared/Fluids/Components/PuddleComponent.cs b/Content.Shared/Fluids/Components/PuddleComponent.cs index bc40e9960c..4abacf1ac9 100644 --- a/Content.Shared/Fluids/Components/PuddleComponent.cs +++ b/Content.Shared/Fluids/Components/PuddleComponent.cs @@ -1,4 +1,3 @@ -using Content.Shared.Chemistry.Components; using Content.Shared.FixedPoint; using Robust.Shared.Audio; using Robust.Shared.GameStates; @@ -18,8 +17,5 @@ namespace Content.Shared.Fluids.Components public FixedPoint2 OverflowVolume = FixedPoint2.New(20); [DataField("solution")] public string SolutionName = "puddle"; - - [DataField("solutionRef")] - public Entity? Solution; } } diff --git a/Content.Shared/Fluids/SharedPuddleSystem.cs b/Content.Shared/Fluids/SharedPuddleSystem.cs index 08a7624c4a..056c3ba919 100644 --- a/Content.Shared/Fluids/SharedPuddleSystem.cs +++ b/Content.Shared/Fluids/SharedPuddleSystem.cs @@ -1,5 +1,6 @@ using Content.Shared.Chemistry.Components; using Content.Shared.DragDrop; +using Content.Shared.Fluids.Components; namespace Content.Shared.Fluids; @@ -21,12 +22,12 @@ public abstract class SharedPuddleSystem : EntitySystem SubscribeLocalEvent(OnRefillableCanDropDragged); } - private void OnRefillableCanDrag(Entity entity, ref CanDragEvent args) + private void OnRefillableCanDrag(EntityUid uid, RefillableSolutionComponent component, ref CanDragEvent args) { args.Handled = true; } - private void OnDumpCanDropTarget(Entity entity, ref CanDropTargetEvent args) + private void OnDumpCanDropTarget(EntityUid uid, DumpableSolutionComponent component, ref CanDropTargetEvent args) { if (HasComp(args.Dragged)) { @@ -35,7 +36,7 @@ public abstract class SharedPuddleSystem : EntitySystem } } - private void OnDrainCanDropTarget(Entity entity, ref CanDropTargetEvent args) + private void OnDrainCanDropTarget(EntityUid uid, DrainableSolutionComponent component, ref CanDropTargetEvent args) { if (HasComp(args.Dragged)) { @@ -44,7 +45,7 @@ public abstract class SharedPuddleSystem : EntitySystem } } - private void OnRefillableCanDropDragged(Entity entity, ref CanDropDraggedEvent args) + private void OnRefillableCanDropDragged(EntityUid uid, RefillableSolutionComponent component, ref CanDropDraggedEvent args) { if (!HasComp(args.Target) && !HasComp(args.Target)) return; diff --git a/Content.Shared/Kitchen/Components/SharedMicrowave.cs b/Content.Shared/Kitchen/Components/SharedMicrowave.cs index ed07fd1287..e86ecf01c5 100644 --- a/Content.Shared/Kitchen/Components/SharedMicrowave.cs +++ b/Content.Shared/Kitchen/Components/SharedMicrowave.cs @@ -1,3 +1,4 @@ +using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Reagent; using Robust.Shared.Serialization; diff --git a/Content.Shared/Kitchen/SharedReagentGrinder.cs b/Content.Shared/Kitchen/SharedReagentGrinder.cs index f5d679c293..dc94884288 100644 --- a/Content.Shared/Kitchen/SharedReagentGrinder.cs +++ b/Content.Shared/Kitchen/SharedReagentGrinder.cs @@ -1,3 +1,4 @@ +using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Reagent; using Robust.Shared.Serialization; diff --git a/Content.Shared/Materials/MaterialReclaimerComponent.cs b/Content.Shared/Materials/MaterialReclaimerComponent.cs index 91bd59614a..eda5cc4058 100644 --- a/Content.Shared/Materials/MaterialReclaimerComponent.cs +++ b/Content.Shared/Materials/MaterialReclaimerComponent.cs @@ -1,4 +1,5 @@ -using Content.Shared.Construction.Prototypes; +using Content.Shared.Chemistry.Components; +using Content.Shared.Construction.Prototypes; using Content.Shared.Whitelist; using Robust.Shared.Audio; using Robust.Shared.GameStates; @@ -83,6 +84,12 @@ public sealed partial class MaterialReclaimerComponent : Component [DataField, ViewVariables(VVAccess.ReadWrite)] public string SolutionContainerId = "output"; + /// + /// The solution itself. + /// + [ViewVariables(VVAccess.ReadWrite)] + public Solution OutputSolution = default!; + /// /// a whitelist for what entities can be inserted into this reclaimer /// diff --git a/Content.Shared/Nutrition/Events.cs b/Content.Shared/Nutrition/Events.cs index e27603763f..97d96e7bff 100644 --- a/Content.Shared/Nutrition/Events.cs +++ b/Content.Shared/Nutrition/Events.cs @@ -1,6 +1,6 @@ -using Content.Shared.Chemistry.Components; -using Content.Shared.DoAfter; +using Content.Shared.DoAfter; using Robust.Shared.Serialization; +using Content.Shared.Chemistry.Components; namespace Content.Shared.Nutrition; @@ -47,8 +47,8 @@ public sealed partial class VapeDoAfterEvent : DoAfterEvent public VapeDoAfterEvent(Solution solution, bool forced) { - Solution = solution; - Forced = forced; + Solution = solution; + Forced = forced; } public override DoAfterEvent Clone() => this; diff --git a/Content.Tests/Shared/Chemistry/SolutionTests.cs b/Content.Tests/Shared/Chemistry/SolutionTests.cs index 7f6e335b36..0fa23d2491 100644 --- a/Content.Tests/Shared/Chemistry/SolutionTests.cs +++ b/Content.Tests/Shared/Chemistry/SolutionTests.cs @@ -1,8 +1,9 @@ using Content.Shared.Chemistry.Components; using Content.Shared.FixedPoint; -using NUnit.Framework; using Robust.Shared.IoC; using Robust.Shared.Prototypes; +using NUnit.Framework; +using Robust.Shared.Utility; namespace Content.Tests.Shared.Chemistry;