]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Predict passive welding fuel consumption (#38876)
authorslarticodefast <161409025+slarticodefast@users.noreply.github.com>
Wed, 30 Jul 2025 22:38:38 +0000 (00:38 +0200)
committerGitHub <noreply@github.com>
Wed, 30 Jul 2025 22:38:38 +0000 (00:38 +0200)
* predict welding fuel consumption

* autopaused

* review

Co-authored-by: ArtisticRoomba <145879011+ArtisticRoomba@users.noreply.github.com>
---------

Co-authored-by: ArtisticRoomba <145879011+ArtisticRoomba@users.noreply.github.com>
Content.Server/Tools/ToolSystem.cs
Content.Shared/Tools/Components/WelderComponent.cs
Content.Shared/Tools/Systems/SharedToolSystem.Welder.cs
Content.Shared/Tools/Systems/SharedToolSystem.cs

index a88dbd3653ffabe56b4eb213fa66ef75a659a0ea..c8defb5ef9e906a623454484871d523fdee45497 100644 (file)
@@ -1,47 +1,5 @@
-using Content.Shared.Chemistry.Components.SolutionManager;
-using Content.Shared.FixedPoint;
-using Content.Shared.Tools.Components;
-
-using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem;
+using Content.Shared.Tools.Systems;
 
 namespace Content.Server.Tools;
 
-public sealed class ToolSystem : SharedToolSystem
-{
-    public override void Update(float frameTime)
-    {
-        base.Update(frameTime);
-
-        UpdateWelders(frameTime);
-    }
-
-    //todo move to shared once you can remove reagents from shared without it freaking out.
-    private void UpdateWelders(float frameTime)
-    {
-        var query = EntityQueryEnumerator<WelderComponent, SolutionContainerManagerComponent>();
-        while (query.MoveNext(out var uid, out var welder, out var solutionContainer))
-        {
-            if (!welder.Enabled)
-                continue;
-
-            welder.WelderTimer += frameTime;
-
-            if (welder.WelderTimer < welder.WelderUpdateTimer)
-                continue;
-
-            if (!SolutionContainerSystem.TryGetSolution((uid, solutionContainer), welder.FuelSolutionName, out var solutionComp, out var solution))
-                continue;
-
-            SolutionContainerSystem.RemoveReagent(solutionComp.Value, welder.FuelReagent, welder.FuelConsumption * welder.WelderTimer);
-
-            if (solution.GetTotalPrototypeQuantity(welder.FuelReagent) <= FixedPoint2.Zero)
-            {
-                ItemToggle.Toggle(uid, predicted: false);
-            }
-
-            Dirty(uid, welder);
-            welder.WelderTimer -= welder.WelderUpdateTimer;
-        }
-    }
-}
-
+public sealed class ToolSystem : SharedToolSystem;
index 3c78a03fdeb14e7853f280651a42fee5675c41a9..a9111c7f53458888e42f4f840547c2e651b45e74 100644 (file)
@@ -1,58 +1,76 @@
-using Content.Shared.Chemistry.Components;
 using Content.Shared.Chemistry.Reagent;
 using Content.Shared.FixedPoint;
 using Content.Shared.Tools.Systems;
 using Robust.Shared.Audio;
 using Robust.Shared.GameStates;
 using Robust.Shared.Prototypes;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
 
 namespace Content.Shared.Tools.Components;
 
-[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true), Access(typeof(SharedToolSystem))]
+/// <summary>
+/// Handles fuel consumption for the tool and allows it to explode welding fuel tanks.
+/// </summary>
+/// <summary>
+/// TODO: De-hardcode welder bombing.
+/// </summary>
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true), AutoGenerateComponentPause]
+[Access(typeof(SharedToolSystem))]
 public sealed partial class WelderComponent : Component
 {
+    /// <summary>
+    /// Is the welder currently enabled?
+    /// </summary>
     [DataField, AutoNetworkedField]
     public bool Enabled;
 
+    /// <summary>
+    /// Timestamp for the next update loop update.
+    /// </summary>
+    [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
+    [AutoNetworkedField, AutoPausedField]
+    public TimeSpan NextUpdate;
+
+    /// <summary>
+    /// Delay between updates.
+    /// </summary>
     [DataField]
-    public float WelderTimer;
+    public TimeSpan WelderUpdateTimer = TimeSpan.FromSeconds(1);
 
     /// <summary>
-    ///     Name of <see cref="FuelSolution"/>.
+    /// Name of the fuel solution.
     /// </summary>
     [DataField]
     public string FuelSolutionName = "Welder";
 
     /// <summary>
-    ///     Reagent that will be used as fuel for welding.
+    /// Reagent that will be used as fuel for welding.
     /// </summary>
     [DataField]
     public ProtoId<ReagentPrototype> FuelReagent = "WeldingFuel";
 
     /// <summary>
-    ///     Fuel consumption per second while the welder is active.
+    /// Fuel consumption per second while the welder is active.
+    /// In u/s
     /// </summary>
     [DataField, AutoNetworkedField]
     public FixedPoint2 FuelConsumption = FixedPoint2.New(1.0f);
 
     /// <summary>
-    ///     A fuel amount to be consumed when the welder goes from being unlit to being lit.
+    /// A fuel amount to be consumed when the welder goes from being unlit to being lit.
     /// </summary>
     [DataField, AutoNetworkedField]
     public FixedPoint2 FuelLitCost = FixedPoint2.New(0.5f);
 
     /// <summary>
-    ///     Sound played when refilling the welder.
+    /// Sound played when refilling the welder.
     /// </summary>
     [DataField]
     public SoundSpecifier WelderRefill = new SoundPathSpecifier("/Audio/Effects/refill.ogg");
 
     /// <summary>
-    ///     Whether the item is safe to refill while lit without exploding the tank.
+    /// Whether the item is safe to refill while lit without exploding the tank.
     /// </summary>
     [DataField]
     public bool TankSafe;
-
-    [DataField]
-    public float WelderUpdateTimer = 1f;
 }
index af1dc85137edb165fdccf849323a7fe95170ab71..1507b1d6e867c99e0a24701b3f7b991a5436b799 100644 (file)
@@ -17,13 +17,16 @@ public abstract partial class SharedToolSystem
 
     public void InitializeWelder()
     {
+        SubscribeLocalEvent<WelderComponent, MapInitEvent>(OnWelderInit);
         SubscribeLocalEvent<WelderComponent, ExaminedEvent>(OnWelderExamine);
         SubscribeLocalEvent<WelderComponent, AfterInteractEvent>(OnWelderAfterInteract);
 
-        SubscribeLocalEvent<WelderComponent, ToolUseAttemptEvent>((uid, comp, ev) => {
+        SubscribeLocalEvent<WelderComponent, ToolUseAttemptEvent>((uid, comp, ev) =>
+        {
             CanCancelWelderUse((uid, comp), ev.User, ev.Fuel, ev);
         });
-        SubscribeLocalEvent<WelderComponent, DoAfterAttemptEvent<ToolDoAfterEvent>>((uid, comp, ev) => {
+        SubscribeLocalEvent<WelderComponent, DoAfterAttemptEvent<ToolDoAfterEvent>>((uid, comp, ev) =>
+        {
             CanCancelWelderUse((uid, comp), ev.Event.User, ev.Event.Fuel, ev);
         });
         SubscribeLocalEvent<WelderComponent, ToolDoAfterEvent>(OnWelderDoAfter);
@@ -71,6 +74,12 @@ public abstract partial class SharedToolSystem
         return (fuelSolution.GetTotalPrototypeQuantity(welder.FuelReagent), fuelSolution.MaxVolume);
     }
 
+    private void OnWelderInit(Entity<WelderComponent> ent, ref MapInitEvent args)
+    {
+        ent.Comp.NextUpdate = _timing.CurTime + ent.Comp.WelderUpdateTimer;
+        Dirty(ent);
+    }
+
     private void OnWelderExamine(Entity<WelderComponent> entity, ref ExaminedEvent args)
     {
         using (args.PushGroup(nameof(WelderComponent)))
@@ -169,7 +178,8 @@ public abstract partial class SharedToolSystem
 
     private void OnActivateAttempt(Entity<WelderComponent> entity, ref ItemToggleActivateAttemptEvent args)
     {
-        if (args.User != null && !_actionBlocker.CanComplexInteract(args.User.Value)) {
+        if (args.User != null && !_actionBlocker.CanComplexInteract(args.User.Value))
+        {
             args.Cancelled = true;
             return;
         }
@@ -191,9 +201,34 @@ public abstract partial class SharedToolSystem
 
     private void OnDeactivateAttempt(Entity<WelderComponent> entity, ref ItemToggleDeactivateAttemptEvent args)
     {
-        if (args.User != null && !_actionBlocker.CanComplexInteract(args.User.Value)) {
+        if (args.User != null && !_actionBlocker.CanComplexInteract(args.User.Value))
+        {
             args.Cancelled = true;
-            return;
+        }
+    }
+
+    private void UpdateWelders()
+    {
+        var query = EntityQueryEnumerator<WelderComponent, SolutionContainerManagerComponent>();
+        var curTime = _timing.CurTime;
+        while (query.MoveNext(out var uid, out var welder, out var solutionContainer))
+        {
+            if (curTime < welder.NextUpdate)
+                continue;
+
+            welder.NextUpdate += welder.WelderUpdateTimer;
+            Dirty(uid, welder);
+
+            if (!welder.Enabled)
+                continue;
+
+            if (!SolutionContainerSystem.TryGetSolution((uid, solutionContainer), welder.FuelSolutionName, out var solutionComp, out var solution))
+                continue;
+
+            SolutionContainerSystem.RemoveReagent(solutionComp.Value, welder.FuelReagent, welder.FuelConsumption * welder.WelderUpdateTimer.TotalSeconds);
+
+            if (solution.GetTotalPrototypeQuantity(welder.FuelReagent) <= FixedPoint2.Zero)
+                ItemToggle.Toggle(uid);
         }
     }
 }
index bf98a365e7b76915ee228b596e700b9e570e4c55..7051cfea00f153b89c568c1d3996a62f3b40a1bc 100644 (file)
@@ -12,12 +12,14 @@ using Robust.Shared.Audio.Systems;
 using Robust.Shared.Map;
 using Robust.Shared.Prototypes;
 using Robust.Shared.Serialization;
+using Robust.Shared.Timing;
 using Robust.Shared.Utility;
 
 namespace Content.Shared.Tools.Systems;
 
 public abstract partial class SharedToolSystem : EntitySystem
 {
+    [Dependency] private   readonly IGameTiming _timing = default!;
     [Dependency] private   readonly IMapManager _mapManager = default!;
     [Dependency] private   readonly IPrototypeManager _protoMan = default!;
     [Dependency] protected readonly ISharedAdminLogManager AdminLogger = default!;
@@ -263,6 +265,13 @@ public abstract partial class SharedToolSystem : EntitySystem
         return !beforeAttempt.Cancelled;
     }
 
+    public override void Update(float frameTime)
+    {
+        base.Update(frameTime);
+
+        UpdateWelders();
+    }
+
     #region DoAfterEvents
 
     [Serializable, NetSerializable]