]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Generalizes solution overflow & slightly increases space lube yield (#21094)
authorTemporalOroboros <TemporalOroboros@gmail.com>
Sat, 28 Oct 2023 16:46:59 +0000 (09:46 -0700)
committerGitHub <noreply@github.com>
Sat, 28 Oct 2023 16:46:59 +0000 (12:46 -0400)
* generalize SolutionSpikeOverflowEvent

* let reactions overflow

* spacelube: 3 -> 5

* restore TryMixAndOverflow threshold cap

Content.Server/Chemistry/EntitySystems/SolutionSpikableSystem.cs
Content.Server/Fluids/EntitySystems/PuddleSystem.Spillable.cs
Content.Shared/Chemistry/EntitySystems/SolutionContainerSystem.cs
Content.Shared/Chemistry/Reaction/ChemicalReactionSystem.cs
Resources/Prototypes/Recipes/Reactions/cleaning.yml

index e27063b1b5766f8bd0cb7676570f3dd85acba24f..04aa6546a90fcc8cd013c7ae145cc5b282fdcfb3 100644 (file)
@@ -61,35 +61,11 @@ public sealed class SolutionSpikableSystem : EntitySystem
             return;
         }
 
-        if (_solutionSystem.TryMixAndOverflow(target,
-                targetSolution,
-                sourceSolution,
-                targetSolution.MaxVolume,
-                out var overflow))
-        {
-            if (overflow.Volume > 0)
-            {
-                RaiseLocalEvent(target, new SolutionSpikeOverflowEvent(overflow));
-            }
-
-            _popupSystem.PopupEntity(Loc.GetString(spikableSource.Popup, ("spiked-entity", target), ("spike-entity", source)), user, user);
-
-            sourceSolution.RemoveAllSolution();
-
-            _triggerSystem.Trigger(source, user);
-        }
-    }
-}
-
-public sealed class SolutionSpikeOverflowEvent : HandledEntityEventArgs
-{
-    /// <summary>
-    ///     The solution that's been overflowed from the spike.
-    /// </summary>
-    public Solution Overflow { get; }
+        if (!_solutionSystem.ForceAddSolution(target, targetSolution, sourceSolution))
+            return;
 
-    public SolutionSpikeOverflowEvent(Solution overflow)
-    {
-        Overflow = overflow;
+        _popupSystem.PopupEntity(Loc.GetString(spikableSource.Popup, ("spiked-entity", target), ("spike-entity", source)), user, user);
+        sourceSolution.RemoveAllSolution();
+        _triggerSystem.Trigger(source, user);
     }
 }
index 39485d60f790c12cbe250b382bff19a19a69ae47..a6d6a5b2043ed88b3fa6ca81b10c2dd1526b3636 100644 (file)
@@ -34,7 +34,7 @@ public sealed partial class PuddleSystem
         SubscribeLocalEvent<SpillableComponent, MeleeHitEvent>(SplashOnMeleeHit, after: new[] { typeof(OpenableSystem) });
         SubscribeLocalEvent<SpillableComponent, GetVerbsEvent<Verb>>(AddSpillVerb);
         SubscribeLocalEvent<SpillableComponent, GotEquippedEvent>(OnGotEquipped);
-        SubscribeLocalEvent<SpillableComponent, SolutionSpikeOverflowEvent>(OnSpikeOverflow);
+        SubscribeLocalEvent<SpillableComponent, SolutionOverflowEvent>(OnOverflow);
         SubscribeLocalEvent<SpillableComponent, SpillDoAfterEvent>(OnDoAfter);
     }
 
@@ -46,13 +46,12 @@ public sealed partial class PuddleSystem
             args.PushMarkup(Loc.GetString("spill-examine-spillable-weapon"));
     }
 
-    private void OnSpikeOverflow(EntityUid uid, SpillableComponent component, SolutionSpikeOverflowEvent args)
+    private void OnOverflow(EntityUid uid, SpillableComponent component, ref SolutionOverflowEvent args)
     {
-        if (!args.Handled)
-        {
-            TrySpillAt(Transform(uid).Coordinates, args.Overflow, out _);
-        }
+        if (args.Handled)
+            return;
 
+        TrySpillAt(Transform(uid).Coordinates, args.Overflow, out _);
         args.Handled = true;
     }
 
index d4c599557bc49987f7e013f513f8480e7b48e283..a5c35b5e6ce9932b642f0b92cf7044ec34518839 100644 (file)
@@ -30,6 +30,24 @@ public sealed class SolutionChangedEvent : EntityEventArgs
     }
 }
 
+/// <summary>
+/// An event raised when more reagents are added to a (managed) solution than it can hold.
+/// </summary>
+[ByRefEvent]
+public record struct SolutionOverflowEvent(EntityUid SolutionEnt, Solution SolutionHolder, Solution Overflow)
+{
+    /// <summary>The entity which contains the solution that has overflowed.</summary>
+    public readonly EntityUid SolutionEnt = SolutionEnt;
+    /// <summary>The solution that has overflowed.</summary>
+    public readonly Solution SolutionHolder = SolutionHolder;
+    /// <summary>The reagents that have overflowed the solution.</summary>
+    public readonly Solution Overflow = Overflow;
+    /// <summary>The volume by which the solution has overflowed.</summary>
+    public readonly FixedPoint2 OverflowVol = Overflow.Volume;
+    /// <summary>Whether some subscriber has taken care of the effects of the overflow.</summary>
+    public bool Handled = false;
+}
+
 /// <summary>
 /// Part of Chemistry system deal with SolutionContainers
 /// </summary>
@@ -265,6 +283,14 @@ public sealed partial class SolutionContainerSystem : EntitySystem
             _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));
     }
@@ -417,24 +443,6 @@ public sealed partial class SolutionContainerSystem : EntitySystem
         return RemoveReagent(targetUid, container, new ReagentQuantity(reagentId, quantity));
     }
 
-    /// <summary>
-    ///     Adds a solution to the container, if it can fully fit.
-    /// </summary>
-    /// <param name="targetUid">entity holding targetSolution</param>
-    ///  <param name="targetSolution">entity holding targetSolution</param>
-    /// <param name="addedSolution">solution being added</param>
-    /// <returns>If the solution could be added.</returns>
-    public bool TryAddSolution(EntityUid targetUid, Solution? targetSolution, Solution addedSolution)
-    {
-        if (targetSolution == null
-            || !targetSolution.CanAddSolution(addedSolution) || addedSolution.Volume == 0)
-            return false;
-
-        targetSolution.AddSolution(addedSolution, _prototypeManager);
-        UpdateChemicals(targetUid, targetSolution, true);
-        return true;
-    }
-
     /// <summary>
     ///     Moves some quantity of a solution from one solution to another.
     /// </summary>
@@ -497,32 +505,86 @@ public sealed partial class SolutionContainerSystem : EntitySystem
     }
 
     /// <summary>
-    ///     Adds a solution to the container, overflowing the rest.
-    ///     It will
-    ///     Unlike <see cref="TryAddSolution"/> it will ignore size limits.
+    ///     Adds a solution to the container, if it can fully fit.
     /// </summary>
     /// <param name="targetUid">entity holding targetSolution</param>
-    /// <param name="targetSolution">The container to which we try to add.</param>
-    /// <param name="addedSolution">solution being added</param>
-    /// <param name="overflowThreshold">After addition this much will be left in targetSolution. Should be less
-    /// than targetSolution.TotalVolume</param>
+    ///  <param name="targetSolution">entity holding targetSolution</param>
+    /// <param name="toAdd">solution being added</param>
+    /// <returns>If the solution could be added.</returns>
+    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;
+    }
+
+    /// <summary>
+    ///     Adds as much of a solution to a container as can fit.
+    /// </summary>
+    /// <param name="targetUid">The entity containing <paramref cref="targetSolution"/></param>
+    /// <param name="targetSolution">The solution being added to.</param>
+    /// <param name="toAdd">The solution being added to <paramref cref="targetSolution"/></param>
+    /// <returns>The quantity of the solution actually added.</returns>
+    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;
+    }
+
+    /// <summary>
+    ///     Adds a solution to a container and updates the container.
+    /// </summary>
+    /// <param name="targetUid">The entity containing <paramref cref="targetSolution"/></param>
+    /// <param name="targetSolution">The solution being added to.</param>
+    /// <param name="toAdd">The solution being added to <paramref cref="targetSolution"/></param>
+    /// <returns>Whether any reagents were added to the solution.</returns>
+    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;
+    }
+
+    /// <summary>
+    ///     Adds a solution to the container, removing the overflow.
+    ///     Unlike <see cref="TryAddSolution"/> it will ignore size limits.
+    /// </summary>
+    /// <param name="targetUid">The entity containing <paramref cref="targetSolution"/></param>
+    /// <param name="targetSolution">The solution being added to.</param>
+    /// <param name="toAdd">The solution being added to <paramref cref="targetSolution"/></param>
+    /// <param name="overflowThreshold">The combined volume above which the overflow will be returned.
+    /// If the combined volume is below this an empty solution is returned.</param>
     /// <param name="overflowingSolution">Solution that exceeded overflowThreshold</param>
-    /// <returns></returns>
+    /// <returns>Whether any reagents were added to <paramref cref="targetSolution"/>.</returns>
     public bool TryMixAndOverflow(EntityUid targetUid, Solution targetSolution,
-        Solution addedSolution,
+        Solution toAdd,
         FixedPoint2 overflowThreshold,
         [NotNullWhen(true)] out Solution? overflowingSolution)
     {
-        if (addedSolution.Volume == 0 || overflowThreshold > targetSolution.MaxVolume)
+        if (toAdd.Volume == 0 || overflowThreshold > targetSolution.MaxVolume)
         {
             overflowingSolution = null;
             return false;
         }
 
-        targetSolution.AddSolution(addedSolution, _prototypeManager);
+        targetSolution.AddSolution(toAdd, _prototypeManager);
+        overflowingSolution = targetSolution.SplitSolution(FixedPoint2.Max(FixedPoint2.Zero, targetSolution.Volume - overflowThreshold));
         UpdateChemicals(targetUid, targetSolution, true);
-        overflowingSolution = targetSolution.SplitSolution(FixedPoint2.Max(FixedPoint2.Zero,
-            targetSolution.Volume - overflowThreshold));
         return true;
     }
 
@@ -778,4 +840,8 @@ public sealed partial class SolutionContainerSystem : EntitySystem
     }
 
     #endregion Thermal Energy and Temperature
+
+    #region Event Handlers
+
+    #endregion Event Handlers
 }
index 4ec50bc61ad564ebb3566752f08f9a0ffa80d904..ed53b78466eba00cace489e891dbe849d1acd3ac 100644 (file)
@@ -262,12 +262,6 @@ namespace Content.Shared.Chemistry.Reaction
             if (products.Count == 0)
                 return true;
 
-            // remove excess product
-            // TODO spill excess?
-            var excessVolume = solution.Volume - maxVolume;
-            if (excessVolume > 0)
-                solution.RemoveSolution(excessVolume);
-
             // Add any reactions associated with the new products. This may re-add reactions that were already iterated
             // over previously. The new product may mean the reactions are applicable again and need to be processed.
             foreach (var product in products)
@@ -279,16 +273,10 @@ namespace Content.Shared.Chemistry.Reaction
             return true;
         }
 
-        /// <summary>
-        ///     Continually react a solution until no more reactions occur.
-        /// </summary>
-        public void FullyReactSolution(Solution solution, EntityUid owner) => FullyReactSolution(solution, owner, FixedPoint2.MaxValue, null);
-
         /// <summary>
         ///     Continually react a solution until no more reactions occur, with a volume constraint.
-        ///     If a reaction's products would exceed the max volume, some product is deleted.
         /// </summary>
-        public void FullyReactSolution(Solution solution, EntityUid owner, FixedPoint2 maxVolume, ReactionMixerComponent? mixerComponent)
+        public void FullyReactSolution(Solution solution, EntityUid owner, FixedPoint2 maxVolume, ReactionMixerComponent? mixerComponent = null)
         {
             // construct the initial set of reactions to check.
             SortedSet<ReactionPrototype> reactions = new();
index 8ae72853be4419be0caecc90183e33bc19fcc13f..1c68aeb2e371ab9671363ca3e2474eca7133b317 100644 (file)
@@ -31,4 +31,4 @@
     Oxygen:
       amount: 1
   products:
-    SpaceLube: 3
+    SpaceLube: 5