diff --git a/Content.Server/GameObjects/Components/Fluids/SpillExtensions.cs b/Content.Server/GameObjects/Components/Fluids/SpillExtensions.cs index ee800441c0..5576b9276a 100644 --- a/Content.Server/GameObjects/Components/Fluids/SpillExtensions.cs +++ b/Content.Server/GameObjects/Components/Fluids/SpillExtensions.cs @@ -1,7 +1,9 @@ #nullable enable using System.Diagnostics.CodeAnalysis; +using System.Linq; using Content.Server.Utility; using Content.Shared.Chemistry; +using Content.Shared.GameObjects.Components.Chemistry; using Robust.Server.GameObjects; using Robust.Shared.GameObjects; using Robust.Shared.IoC; @@ -23,8 +25,7 @@ namespace Content.Server.GameObjects.Components.Fluids /// The puddle if one was created, null otherwise. public static PuddleComponent? SpillAt(this Solution solution, IEntity entity, string prototype, bool sound = true) { - var coordinates = entity.Transform.Coordinates; - return solution.SpillAt(coordinates, prototype, sound); + return solution.SpillAt(entity.Transform.Coordinates, prototype, sound); } /// @@ -52,61 +53,16 @@ namespace Content.Server.GameObjects.Components.Fluids /// The prototype to use. /// Whether or not to play the spill sound. /// The puddle if one was created, null otherwise. - public static PuddleComponent? SpillAt(this Solution solution, EntityCoordinates coordinates, string prototype, bool sound = true) + public static PuddleComponent? SpillAt(this Solution solution, EntityCoordinates coordinates, string prototype, bool overflow = true, bool sound = true) { - if (solution.TotalVolume == 0) - { - return null; - } + if (solution.TotalVolume == 0) return null; var mapManager = IoCManager.Resolve(); var entityManager = IoCManager.Resolve(); - var serverEntityManager = IoCManager.Resolve(); - if (!mapManager.TryGetGrid(coordinates.GetGridId(entityManager), out var mapGrid)) - return null; // Let's not spill to space. + if (!mapManager.TryGetGrid(coordinates.GetGridId(entityManager), out var mapGrid)) return null; // Let's not spill to space. - // If space return early, let that spill go out into the void - var tileRef = mapGrid.GetTileRef(coordinates); - if (tileRef.Tile.IsEmpty) - { - return null; - } - - // Get normalized co-ordinate for spill location and spill it in the centre - // TODO: Does SnapGrid or something else already do this? - var spillGridCoords = mapGrid.GridTileToLocal(tileRef.GridIndices); - - var spilt = false; - - foreach (var spillEntity in entityManager.GetEntitiesAt(mapGrid.ParentMapId, spillGridCoords.Position)) - { - if (!spillEntity.TryGetComponent(out PuddleComponent? puddleComponent)) - { - continue; - } - - if (!puddleComponent.TryAddSolution(solution, sound)) - { - continue; - } - - spilt = true; - break; - } - - // Did we add to an existing puddle - if (spilt) - { - return null; - } - - var puddle = serverEntityManager.SpawnEntity(prototype, spillGridCoords); - var newPuddleComponent = puddle.GetComponent(); - - newPuddleComponent.TryAddSolution(solution, sound); - - return newPuddleComponent; + return SpillAt(mapGrid.GetTileRef(coordinates), solution, prototype, overflow, sound); } /// @@ -141,44 +97,44 @@ namespace Content.Server.GameObjects.Components.Fluids public static PuddleComponent? SpillAt(this TileRef tileRef, Solution solution, string prototype, bool overflow = true, bool sound = true) { - if (solution.TotalVolume <= 0) - { - return null; - } + if (solution.TotalVolume <= 0) return null; var mapManager = IoCManager.Resolve(); var entityManager = IoCManager.Resolve(); var serverEntityManager = IoCManager.Resolve(); - var gridId = tileRef.GridIndex; - // If space return early, let that spill go out into the void - if (tileRef.Tile.IsEmpty) - { - return null; - } + if (tileRef.Tile.IsEmpty) return null; - PuddleComponent? puddle = null; + var gridId = tileRef.GridIndex; + if (!mapManager.TryGetGrid(gridId, out var mapGrid)) return null; // Let's not spill to invalid grids. // Get normalized co-ordinate for spill location and spill it in the centre // TODO: Does SnapGrid or something else already do this? - if (!mapManager.TryGetGrid(gridId, out var spillTileMapGrid)) - return null; // Let's not spill to invalid grids. - - var spillGridCoords = spillTileMapGrid.GridTileToLocal(tileRef.GridIndices); + var spillGridCoords = mapGrid.GridTileToLocal(tileRef.GridIndices); + PuddleComponent? puddle = null; var spilt = false; - foreach (var spillEntity in entityManager.GetEntitiesAt(spillTileMapGrid.ParentMapId, spillGridCoords.Position)) + var spillEntities = entityManager.GetEntitiesIntersecting(mapGrid.ParentMapId, spillGridCoords.Position).ToArray(); + foreach (var spillEntity in spillEntities) { - if (!spillEntity.TryGetComponent(out PuddleComponent? puddleComponent)) - continue; + if (spillEntity.TryGetComponent(out ISolutionInteractionsComponent? solutionContainerComponent) && + solutionContainerComponent.CanRefill) + { + solutionContainerComponent.Refill( + solution.SplitSolution(ReagentUnit.Min(solutionContainerComponent.RefillSpaceAvailable, solutionContainerComponent.MaxSpillRefill)) + ); + } + } - if (!overflow && puddleComponent.WouldOverflow(solution)) - return null; + foreach (var spillEntity in spillEntities) + { + if (!spillEntity.TryGetComponent(out PuddleComponent? puddleComponent)) continue; - if (!puddleComponent.TryAddSolution(solution, sound)) - continue; + if (!overflow && puddleComponent.WouldOverflow(solution)) return null; + + if (!puddleComponent.TryAddSolution(solution, sound)) continue; puddle = puddleComponent; spilt = true; @@ -186,17 +142,14 @@ namespace Content.Server.GameObjects.Components.Fluids } // Did we add to an existing puddle - if (spilt) - { - return puddle; - } + if (spilt) return puddle; var puddleEnt = serverEntityManager.SpawnEntity(prototype, spillGridCoords); - puddle = puddleEnt.GetComponent(); + var newPuddleComponent = puddleEnt.GetComponent(); - puddle.TryAddSolution(solution, sound); + newPuddleComponent.TryAddSolution(solution, sound); - return puddle; + return newPuddleComponent; } } } diff --git a/Content.Shared/GameObjects/Components/Chemistry/ISolutionInteractionsComponent.cs b/Content.Shared/GameObjects/Components/Chemistry/ISolutionInteractionsComponent.cs index d74afbc84f..0b391be562 100644 --- a/Content.Shared/GameObjects/Components/Chemistry/ISolutionInteractionsComponent.cs +++ b/Content.Shared/GameObjects/Components/Chemistry/ISolutionInteractionsComponent.cs @@ -64,6 +64,11 @@ namespace Content.Shared.GameObjects.Components.Chemistry bool CanRefill => false; ReagentUnit RefillSpaceAvailable => ReagentUnit.Zero; + /// + /// The amount that will transfer if something is spilled on the container. + /// + ReagentUnit MaxSpillRefill => ReagentUnit.Zero; + void Refill(Solution solution) { diff --git a/Content.Shared/GameObjects/Components/Chemistry/SharedSolutionContainerComponent.cs b/Content.Shared/GameObjects/Components/Chemistry/SharedSolutionContainerComponent.cs index d6e189a834..4cc238cb66 100644 --- a/Content.Shared/GameObjects/Components/Chemistry/SharedSolutionContainerComponent.cs +++ b/Content.Shared/GameObjects/Components/Chemistry/SharedSolutionContainerComponent.cs @@ -73,6 +73,7 @@ namespace Content.Shared.GameObjects.Components.Chemistry serializer.DataField(this, x => x.MaxVolume, "maxVol", ReagentUnit.New(0)); serializer.DataField(this, x => x.Solution, "contents", new Solution()); serializer.DataField(this, x => x.Capabilities, "caps", SolutionContainerCaps.None); + serializer.DataField(this, x => x.MaxSpillRefill, "maxSpillRefill", MaxVolume / ReagentUnit.New(4)); } public void RemoveAllSolution() @@ -214,6 +215,7 @@ namespace Content.Shared.GameObjects.Components.Chemistry ReagentUnit ISolutionInteractionsComponent.InjectSpaceAvailable => EmptyVolume; ReagentUnit ISolutionInteractionsComponent.DrawAvailable => CurrentVolume; ReagentUnit ISolutionInteractionsComponent.DrainAvailable => CurrentVolume; + public ReagentUnit MaxSpillRefill { get; set; } void ISolutionInteractionsComponent.Refill(Solution solution) {