]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Fix gas pipe leaking when unanchoring or breaking them (#33774)
authorslarticodefast <161409025+slarticodefast@users.noreply.github.com>
Sun, 8 Dec 2024 23:20:04 +0000 (00:20 +0100)
committerGitHub <noreply@github.com>
Sun, 8 Dec 2024 23:20:04 +0000 (00:20 +0100)
* fix gas pipe unanchoring

* remove unneeded update

* revert popup change

Content.Server/Atmos/Piping/EntitySystems/AtmosUnsafeUnanchorSystem.cs
Content.Server/NodeContainer/EntitySystems/NodeGroupSystem.cs

index f594866fa23fec9854bd012bfb8f383fd89313d8..bc925e433ca61a4a4a8917cadc14b8be2c5220bd 100644 (file)
@@ -1,6 +1,7 @@
 using Content.Server.Atmos.EntitySystems;
 using Content.Server.Atmos.Piping.Components;
 using Content.Server.NodeContainer;
+using Content.Server.NodeContainer.EntitySystems;
 using Content.Server.NodeContainer.Nodes;
 using Content.Server.Popups;
 using Content.Shared.Atmos;
@@ -8,7 +9,6 @@ using Content.Shared.Construction.Components;
 using Content.Shared.Destructible;
 using Content.Shared.Popups;
 using JetBrains.Annotations;
-using Robust.Shared.Player;
 
 namespace Content.Server.Atmos.Piping.EntitySystems
 {
@@ -16,11 +16,12 @@ namespace Content.Server.Atmos.Piping.EntitySystems
     public sealed class AtmosUnsafeUnanchorSystem : EntitySystem
     {
         [Dependency] private readonly AtmosphereSystem _atmosphere = default!;
+        [Dependency] private readonly NodeGroupSystem _group = default!;
         [Dependency] private readonly PopupSystem _popup = default!;
 
         public override void Initialize()
         {
-            SubscribeLocalEvent<AtmosUnsafeUnanchorComponent, BeforeUnanchoredEvent>(OnBeforeUnanchored);
+            SubscribeLocalEvent<AtmosUnsafeUnanchorComponent, UserUnanchoredEvent>(OnUserUnanchored);
             SubscribeLocalEvent<AtmosUnsafeUnanchorComponent, UnanchorAttemptEvent>(OnUnanchorAttempt);
             SubscribeLocalEvent<AtmosUnsafeUnanchorComponent, BreakageEventArgs>(OnBreak);
         }
@@ -48,15 +49,22 @@ namespace Content.Server.Atmos.Piping.EntitySystems
             }
         }
 
-        private void OnBeforeUnanchored(EntityUid uid, AtmosUnsafeUnanchorComponent component, BeforeUnanchoredEvent args)
+        // When unanchoring a pipe, leak the gas that was inside the pipe element.
+        // At this point the pipe has been scheduled to be removed from the group, but that won't happen until the next Update() call in NodeGroupSystem,
+        // so we have to force an update.
+        // This way the gas inside other connected pipes stays unchanged, while the removed pipe is completely emptied.
+        private void OnUserUnanchored(EntityUid uid, AtmosUnsafeUnanchorComponent component, UserUnanchoredEvent args)
         {
             if (component.Enabled)
+            {
+                _group.ForceUpdate();
                 LeakGas(uid);
+            }
         }
 
         private void OnBreak(EntityUid uid, AtmosUnsafeUnanchorComponent component, BreakageEventArgs args)
         {
-            LeakGas(uid);
+            LeakGas(uid, false);
             // Can't use DoActsBehavior["Destruction"] in the same trigger because that would prevent us
             // from leaking. So we make up for this by queueing deletion here.
             QueueDel(uid);
@@ -64,32 +72,17 @@ namespace Content.Server.Atmos.Piping.EntitySystems
 
         /// <summary>
         /// Leak gas from the uid's NodeContainer into the tile atmosphere.
+        /// Setting removeFromPipe to false will duplicate the gas inside the pipe intead of moving it.
+        /// This is needed to properly handle the gas in the pipe getting deleted with the pipe.
         /// </summary>
-        public void LeakGas(EntityUid uid)
+        public void LeakGas(EntityUid uid, bool removeFromPipe = true)
         {
             if (!EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodes))
                 return;
 
-            if (_atmosphere.GetContainingMixture(uid, true, true) is not {} environment)
+            if (_atmosphere.GetContainingMixture(uid, true, true) is not { } environment)
                 environment = GasMixture.SpaceGas;
 
-            var lost = 0f;
-            var timesLost = 0;
-
-            foreach (var node in nodes.Nodes.Values)
-            {
-                if (node is not PipeNode pipe)
-                    continue;
-
-                var difference = pipe.Air.Pressure - environment.Pressure;
-                lost += Math.Min(
-                            pipe.Volume / pipe.Air.Volume * pipe.Air.TotalMoles,
-                            difference * environment.Volume / (environment.Temperature * Atmospherics.R)
-                        );
-                timesLost++;
-            }
-
-            var sharedLoss = lost / timesLost;
             var buffer = new GasMixture();
 
             foreach (var node in nodes.Nodes.Values)
@@ -97,7 +90,13 @@ namespace Content.Server.Atmos.Piping.EntitySystems
                 if (node is not PipeNode pipe)
                     continue;
 
-                _atmosphere.Merge(buffer, pipe.Air.Remove(sharedLoss));
+                if (removeFromPipe)
+                    _atmosphere.Merge(buffer, pipe.Air.RemoveVolume(pipe.Volume));
+                else
+                {
+                    var copy = new GasMixture(pipe.Air); //clone, then remove to keep the original untouched
+                    _atmosphere.Merge(buffer, copy.RemoveVolume(pipe.Volume));
+                }
             }
 
             _atmosphere.Merge(environment, buffer);
index 2296de2eb6a3e35b0f7926daf9fae3007b8f5b5c..62806fe84fb0b6ac15262202224392cc350215da 100644 (file)
@@ -149,6 +149,13 @@ namespace Content.Server.NodeContainer.EntitySystems
             }
         }
 
+        // used to manually force an update for the groups
+        // the VisDoUpdate will be done with the next scheduled update
+        public void ForceUpdate()
+        {
+            DoGroupUpdates();
+        }
+
         private void DoGroupUpdates()
         {
             // "Why is there a separate queue for group remakes and node refloods when they both cause eachother"