]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Remove update from DeviceLinkSystem (#37152)
authorPieter-Jan Briers <pieterjan.briers+git@gmail.com>
Sun, 4 May 2025 16:14:23 +0000 (18:14 +0200)
committerGitHub <noreply@github.com>
Sun, 4 May 2025 16:14:23 +0000 (12:14 -0400)
The tick updates were purely used to decrease the invoke counter once per tick. Now instead we just calculate the effective counter value with some trivial math on the tick number. This completely removes the need for an update function.

The relative tick is not stored to map files. If we really need this, we can add a TickOffsetSerializer (similar to TimeOffsetSerializer), but I doubt it matters.

Content.Server/DeviceLinking/Systems/DeviceLinkSystem.cs
Content.Shared/DeviceLinking/DeviceLinkSinkComponent.cs
Content.Shared/DeviceLinking/SharedDeviceLinkSystem.cs

index cec92db44cae886bee34ddc9bbe3a4b25ae2184b..d957f0171e71fbc9a1d04672c8e47fcc87f1d7bb 100644 (file)
@@ -20,23 +20,6 @@ public sealed class DeviceLinkSystem : SharedDeviceLinkSystem
         SubscribeLocalEvent<DeviceLinkSourceComponent, NewLinkEvent>(OnNewLink);
     }
 
-    public override void Update(float frameTime)
-    {
-        var query = EntityQueryEnumerator<DeviceLinkSinkComponent>();
-
-        while (query.MoveNext(out var component))
-        {
-            if (component.InvokeLimit < 1)
-            {
-                component.InvokeCounter = 0;
-                continue;
-            }
-
-            if(component.InvokeCounter > 0)
-                component.InvokeCounter--;
-        }
-    }
-
     #region Sending & Receiving
     public override void InvokePort(EntityUid uid, string port, NetworkPayload? data = null, DeviceLinkSourceComponent? sourceComponent = null)
     {
@@ -67,16 +50,17 @@ public sealed class DeviceLinkSystem : SharedDeviceLinkSystem
         if (!Resolve(sink, ref sink.Comp))
             return;
 
-        if (sink.Comp.InvokeCounter > sink.Comp.InvokeLimit)
+        var invokeCounter = GetEffectiveInvokeCounter(sink.Comp);
+        if (invokeCounter > sink.Comp.InvokeLimit)
         {
-            sink.Comp.InvokeCounter = 0;
+            SetInvokeCounter(sink.Comp, 0);
             var args = new DeviceLinkOverloadedEvent();
             RaiseLocalEvent(sink, ref args);
             RemoveAllFromSink(sink, sink.Comp);
             return;
         }
 
-        sink.Comp.InvokeCounter++;
+        SetInvokeCounter(sink.Comp, invokeCounter + 1);
 
         //Just skip using device networking if the source or the sink doesn't support it
         if (!HasComp<DeviceNetworkComponent>(source) || !TryComp<DeviceNetworkComponent>(sink, out var sinkNetwork))
index 5d901b3fa68b4e0a2d7094755f540c3bd6899192..83a55a9bb60bd87be9877f391b713a89104b893a 100644 (file)
@@ -1,6 +1,7 @@
 using Robust.Shared.GameStates;
 using Robust.Shared.Prototypes;
 using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set;
+using Robust.Shared.Timing;
 
 namespace Content.Shared.DeviceLinking;
 
@@ -23,11 +24,20 @@ public sealed partial class DeviceLinkSinkComponent : Component
     public HashSet<EntityUid> LinkedSources = new();
 
     /// <summary>
-    /// Counts the amount of times a sink has been invoked for severing the link if this counter gets to high
-    /// The counter is counted down by one every tick if it's higher than 0
-    /// This is for preventing infinite loops
+    /// The tick <see cref="InvokeCounter"/> was set at. Used to calculate the real value for the current tick.
     /// </summary>
+    [Access(typeof(SharedDeviceLinkSystem), Other = AccessPermissions.None)]
+    public GameTick InvokeCounterTick;
+
+    /// <summary>
+    /// Counter used to throttle device invocations to avoid infinite loops.
+    /// </summary>
+    /// <remarks>
+    /// This is stored relative to <see cref="InvokeCounterTick"/>. For reading the real value,
+    /// <see cref="SharedDeviceLinkSystem.GetEffectiveInvokeCounter"/> should be used.
+    /// </remarks>
     [DataField]
+    [Access(typeof(SharedDeviceLinkSystem), Other = AccessPermissions.None)]
     public int InvokeCounter;
 
     /// <summary>
index 3f969684b64f7d47552d5e17ec621bf6a83a1758..e51087fdf6b734ea5b93541d8054ab04d6d39666 100644 (file)
@@ -4,6 +4,7 @@ using Content.Shared.DeviceLinking.Events;
 using Content.Shared.DeviceNetwork;
 using Content.Shared.Popups;
 using Robust.Shared.Prototypes;
+using Robust.Shared.Timing;
 using Robust.Shared.Utility;
 
 namespace Content.Shared.DeviceLinking;
@@ -14,6 +15,7 @@ public abstract class SharedDeviceLinkSystem : EntitySystem
     [Dependency] private readonly SharedPopupSystem _popupSystem = default!;
     [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
     [Dependency] private readonly SharedTransformSystem _transform = default!;
+    [Dependency] private readonly IGameTiming _gameTiming = default!;
 
     public const string InvokedPort = "link_port";
 
@@ -525,4 +527,30 @@ public abstract class SharedDeviceLinkSystem : EntitySystem
         // NOOP on client for the moment.
     }
     #endregion
+
+    /// <summary>
+    /// Gets how many times a <see cref="DeviceLinkSinkComponent"/> has been invoked recently.
+    /// </summary>
+    /// <remarks>
+    /// The return value of this function goes up by one every time a sink is invoked, and goes down by one every tick.
+    /// </remarks>
+    public int GetEffectiveInvokeCounter(DeviceLinkSinkComponent sink)
+    {
+        // Shouldn't be possible but just to be safe.
+        var curTick = _gameTiming.CurTick;
+        if (curTick < sink.InvokeCounterTick)
+            return 0;
+
+        var tickDelta = curTick.Value - sink.InvokeCounterTick.Value;
+        if (tickDelta >= sink.InvokeCounter)
+            return 0;
+
+        return Math.Max(0, sink.InvokeCounter - (int)tickDelta);
+    }
+
+    protected void SetInvokeCounter(DeviceLinkSinkComponent sink, int value)
+    {
+        sink.InvokeCounterTick = _gameTiming.CurTick;
+        sink.InvokeCounter = value;
+    }
 }