]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
DoAfter Refactor Fixes (#14278)
authorkeronshb <54602815+keronshb@users.noreply.github.com>
Sun, 26 Feb 2023 05:33:06 +0000 (00:33 -0500)
committerGitHub <noreply@github.com>
Sun, 26 Feb 2023 05:33:06 +0000 (23:33 -0600)
* Doafterfixes

* Injector blocker

13 files changed:
Content.Server/Botany/Systems/BotanySwabSystem.cs
Content.Server/Chemistry/EntitySystems/ChemistrySystem.Injector.cs
Content.Server/Disease/DiseaseDiagnosisSystem.cs
Content.Server/Medical/Components/HealingComponent.cs
Content.Server/Medical/HealingSystem.cs
Content.Server/Nutrition/Components/DrinkComponent.cs
Content.Server/Nutrition/Components/FoodComponent.cs
Content.Server/Nutrition/EntitySystems/DrinkSystem.cs
Content.Server/Nutrition/EntitySystems/FoodSystem.cs
Content.Server/Tools/Components/TilePryingComponent.cs
Content.Server/Tools/ToolSystem.TilePrying.cs
Content.Shared/Chemistry/Components/SharedInjectorComponent.cs
Content.Shared/Tools/Systems/SharedToolSystem.MultipleTool.cs

index 09b6c38ccc5d73492997659db1882a44feab5d11..ef7cc1760b34e603f91a15a8050093a326f317bd 100644 (file)
@@ -18,7 +18,7 @@ public sealed class BotanySwabSystem : EntitySystem
         base.Initialize();
         SubscribeLocalEvent<BotanySwabComponent, ExaminedEvent>(OnExamined);
         SubscribeLocalEvent<BotanySwabComponent, AfterInteractEvent>(OnAfterInteract);
-        SubscribeLocalEvent<DoAfterEvent>(OnDoAfter);
+        SubscribeLocalEvent<BotanySwabComponent, DoAfterEvent>(OnDoAfter);
     }
 
     /// <summary>
@@ -41,7 +41,7 @@ public sealed class BotanySwabSystem : EntitySystem
     /// </summary>
     private void OnAfterInteract(EntityUid uid, BotanySwabComponent swab, AfterInteractEvent args)
     {
-        if (args.Target == null || !args.CanReach)
+        if (args.Target == null || !args.CanReach || !HasComp<PlantHolderComponent>(args.Target))
             return;
 
         _doAfterSystem.DoAfter(new DoAfterEventArgs(args.User, swab.SwabDelay, target: args.Target, used: uid)
@@ -57,7 +57,7 @@ public sealed class BotanySwabSystem : EntitySystem
     /// <summary>
     /// Save seed data or cross-pollenate.
     /// </summary>
-    private void OnDoAfter(DoAfterEvent args)
+    private void OnDoAfter(EntityUid uid, BotanySwabComponent component, DoAfterEvent args)
     {
         if (args.Cancelled || args.Handled || !TryComp<PlantHolderComponent>(args.Args.Target, out var plant) || !TryComp<BotanySwabComponent>(args.Args.Used, out var swab))
             return;
index b011f39f5d89c1d710dcd7772c1db458421f3d9e..598f470d6e734bf94a149fc7fa177ae7a680e60e 100644 (file)
@@ -129,11 +129,18 @@ public sealed partial class ChemistrySystem
 
     private void OnInjectDoAfter(EntityUid uid, InjectorComponent component, DoAfterEvent args)
     {
-        if (args.Handled || args.Cancelled || args.Args.Target == null)
+        if (args.Cancelled)
+        {
+            component.IsInjecting = false;
+            return;
+        }
+
+        if (args.Handled || args.Args.Target == null)
             return;
 
         UseInjector(args.Args.Target.Value, args.Args.User, uid, component);
 
+        component.IsInjecting = false;
         args.Handled = true;
     }
 
@@ -216,12 +223,18 @@ public sealed partial class ChemistrySystem
         if (!_solutions.TryGetSolution(injector, InjectorComponent.SolutionName, out var solution))
             return;
 
+        //If it found it's injecting
+        if (component.IsInjecting)
+            return;
+
         var actualDelay = MathF.Max(component.Delay, 1f);
 
         // Injections take 1 second longer per additional 5u
         actualDelay += (float) component.TransferAmount / component.Delay - 1;
 
-        if (user != target)
+        var isTarget = user != target;
+
+        if (isTarget)
         {
             // Create a pop-up for the target
             var userName = Identity.Entity(user, EntityManager);
@@ -256,8 +269,12 @@ public sealed partial class ChemistrySystem
                 _adminLogger.Add(LogType.Ingestion, $"{EntityManager.ToPrettyString(user):user} is attempting to inject themselves with a solution {SolutionContainerSystem.ToPrettyString(solution):solution}.");
         }
 
+        component.IsInjecting = true;
+
         _doAfter.DoAfter(new DoAfterEventArgs(user, actualDelay, target:target, used:injector)
         {
+            RaiseOnTarget = isTarget,
+            RaiseOnUser = !isTarget,
             BreakOnUserMove = true,
             BreakOnDamage = true,
             BreakOnStun = true,
index 28b4dcd7c6cb671e9722cbfcf781360537b7217d..98b4d6c23026c4501ac1a7e114de24192ea1d690 100644 (file)
@@ -47,7 +47,7 @@ namespace Content.Server.Disease
             // Private Events
             SubscribeLocalEvent<DiseaseDiagnoserComponent, DiseaseMachineFinishedEvent>(OnDiagnoserFinished);
             SubscribeLocalEvent<DiseaseVaccineCreatorComponent, DiseaseMachineFinishedEvent>(OnVaccinatorFinished);
-            SubscribeLocalEvent<DoAfterEvent>(OnSwabDoAfter);
+            SubscribeLocalEvent<DiseaseSwabComponent, DoAfterEvent>(OnSwabDoAfter);
         }
 
         private Queue<EntityUid> AddQueue = new();
@@ -99,7 +99,7 @@ namespace Content.Server.Disease
         /// </summary>
         private void OnAfterInteract(EntityUid uid, DiseaseSwabComponent swab, AfterInteractEvent args)
         {
-            if (args.Target == null || !args.CanReach)
+            if (args.Target == null || !args.CanReach || !HasComp<DiseaseCarrierComponent>(args.Target))
                 return;
 
             if (swab.Used)
@@ -116,8 +116,12 @@ namespace Content.Server.Disease
                 return;
             }
 
+            var isTarget = args.User != args.Target;
+
             _doAfterSystem.DoAfter(new DoAfterEventArgs(args.User, swab.SwabDelay, target: args.Target, used: uid)
             {
+                RaiseOnTarget = isTarget,
+                RaiseOnUser = !isTarget,
                 BreakOnTargetMove = true,
                 BreakOnUserMove = true,
                 BreakOnStun = true,
@@ -301,9 +305,9 @@ namespace Content.Server.Disease
         /// Copies a disease prototype to the swab
         /// after the doafter completes.
         /// </summary>
-        private void OnSwabDoAfter(DoAfterEvent args)
+        private void OnSwabDoAfter(EntityUid uid, DiseaseSwabComponent component, DoAfterEvent args)
         {
-            if (args.Handled || args.Cancelled || !TryComp<DiseaseCarrierComponent>(args.Args.Target, out var carrier) || !TryComp<DiseaseSwabComponent>(args.Args.Target, out var swab))
+            if (args.Handled || args.Cancelled || !TryComp<DiseaseCarrierComponent>(args.Args.Target, out var carrier) || !TryComp<DiseaseSwabComponent>(args.Args.Used, out var swab))
                 return;
 
             swab.Used = true;
@@ -313,7 +317,6 @@ namespace Content.Server.Disease
                 return;
 
             swab.Disease = _random.Pick(carrier.Diseases);
-
         }
 
 
index edebf7697afb895020d8d0687de5cc48c154ff26..5f3120cff01a00827195aeac5623b1f3e7d58e72 100644 (file)
@@ -39,6 +39,12 @@ namespace Content.Server.Medical.Components
         [DataField("delay")]
         public float Delay = 3f;
 
+        /// <summary>
+        /// Cancel token to prevent rapid healing
+        /// </summary>
+        [DataField("cancelToken")]
+        public CancellationTokenSource? CancelToken;
+
         /// <summary>
         /// Delay multiplier when healing yourself.
         /// </summary>
index a908801605af665b51de820bda3ccd1415a33267..9b4d9e77ed5bc49c52c6c8baff73f5883707fe2c 100644 (file)
@@ -1,3 +1,4 @@
+using System.Threading;
 using Content.Server.Administration.Logs;
 using Content.Server.Body.Systems;
 using Content.Server.DoAfter;
@@ -40,6 +41,12 @@ public sealed class HealingSystem : EntitySystem
 
     private void OnDoAfter(EntityUid uid, DamageableComponent component, DoAfterEvent<HealingData> args)
     {
+        if (args.Cancelled)
+        {
+            args.AdditionalData.HealingComponent.CancelToken = null;
+            return;
+        }
+
         if (args.Handled || args.Cancelled || _mobStateSystem.IsDead(uid) || args.Args.Used == null)
             return;
 
@@ -67,6 +74,7 @@ public sealed class HealingSystem : EntitySystem
         if (args.AdditionalData.HealingComponent.HealingEndSound != null)
             _audio.PlayPvs(args.AdditionalData.HealingComponent.HealingEndSound, uid, AudioHelpers.WithVariation(0.125f, _random).WithVolume(-5f));
 
+        args.AdditionalData.HealingComponent.CancelToken = null;
         args.Handled = true;
     }
 
@@ -90,7 +98,7 @@ public sealed class HealingSystem : EntitySystem
 
     private bool TryHeal(EntityUid uid, EntityUid user, EntityUid target, HealingComponent component)
     {
-        if (_mobStateSystem.IsDead(target) || !TryComp<DamageableComponent>(target, out var targetDamage))
+        if (_mobStateSystem.IsDead(target) || !TryComp<DamageableComponent>(target, out var targetDamage) || component.CancelToken != null)
             return false;
 
         if (targetDamage.TotalDamage == 0)
@@ -108,14 +116,21 @@ public sealed class HealingSystem : EntitySystem
         if (component.HealingBeginSound != null)
             _audio.PlayPvs(component.HealingBeginSound, uid, AudioHelpers.WithVariation(0.125f, _random).WithVolume(-5f));
 
-        var delay = user != target
+        var isNotSelf = user != target;
+
+        var delay = isNotSelf
             ? component.Delay
             : component.Delay * GetScaledHealingPenalty(user, component);
 
+        component.CancelToken = new CancellationTokenSource();
+
         var healingData = new HealingData(component, stack);
 
-        var doAfterEventArgs = new DoAfterEventArgs(user, delay, target: target, used: uid)
+        var doAfterEventArgs = new DoAfterEventArgs(user, delay, cancelToken: component.CancelToken.Token,target: target, used: uid)
         {
+            //Raise the event on the target if it's not self, otherwise raise it on self.
+            RaiseOnTarget = isNotSelf,
+            RaiseOnUser = !isNotSelf,
             BreakOnUserMove = true,
             BreakOnTargetMove = true,
             // Didn't break on damage as they may be trying to prevent it and
index be882f7947ac1ca3400c843861fd7359adcc8451..14c9712fa8376c7789466886ab38f21801d7ddca 100644 (file)
@@ -34,6 +34,13 @@ namespace Content.Server.Nutrition.Components
         [DataField("burstSound")]
         public SoundSpecifier BurstSound = new SoundPathSpecifier("/Audio/Effects/flash_bang.ogg");
 
+        /// <summary>
+        /// Is this drink being forced on someone else?
+        /// </summary>
+        /// <returns></returns>
+        [DataField("forceDrink")]
+        public bool ForceDrink;
+
         /// <summary>
         /// How long it takes to drink this yourself.
         /// </summary>
index 5d7d325b0226fad0397fdf4dc76125813e1b0c2f..c5c12e0fa680fb47a2de43580bf84397452df2fd 100644 (file)
@@ -40,6 +40,13 @@ namespace Content.Server.Nutrition.Components
         [DataField("eatMessage")]
         public string EatMessage = "food-nom";
 
+        /// <summary>
+        /// Is this entity being forcefed?
+        /// Prevents the entity from being forced to eat multiple times if not self
+        /// </summary>
+        [DataField("forceFeed")]
+        public bool ForceFeed;
+
         /// <summary>
         /// How long it takes to eat the food personally.
         /// </summary>
index 04c6ee7159b1a5388b1b00e952932651388d154d..2c21e83c96152b3d677b53adde039b36c3fe0fd7 100644 (file)
@@ -217,7 +217,7 @@ namespace Content.Server.Nutrition.EntitySystems
 
         private bool TryDrink(EntityUid user, EntityUid target, DrinkComponent drink, EntityUid item)
         {
-            if (!EntityManager.HasComponent<BodyComponent>(target))
+            if (!EntityManager.HasComponent<BodyComponent>(target) || drink.ForceDrink)
                 return false;
 
             if (!drink.Opened)
@@ -241,9 +241,9 @@ namespace Content.Server.Nutrition.EntitySystems
             if (!_interactionSystem.InRangeUnobstructed(user, item, popup: true))
                 return true;
 
-            var forceDrink = user != target;
+            drink.ForceDrink = user != target;
 
-            if (forceDrink)
+            if (drink.ForceDrink)
             {
                 var userName = Identity.Entity(user, EntityManager);
 
@@ -264,7 +264,7 @@ namespace Content.Server.Nutrition.EntitySystems
 
             var drinkData = new DrinkData(drinkSolution, flavors);
 
-            var doAfterEventArgs = new DoAfterEventArgs(user, forceDrink ? drink.ForceFeedDelay : drink.Delay,
+            var doAfterEventArgs = new DoAfterEventArgs(user, drink.ForceDrink ? drink.ForceFeedDelay : drink.Delay,
                 target: target, used: item)
             {
                 BreakOnUserMove = moveBreak,
@@ -286,6 +286,14 @@ namespace Content.Server.Nutrition.EntitySystems
         /// </summary>
         private void OnDoAfter(EntityUid uid, DrinkComponent component, DoAfterEvent<DrinkData> args)
         {
+            //Special cancel if they're force feeding someone.
+            //Allows self to drink multiple times but prevents force feeding drinks to others rapidly.
+            if (args.Cancelled && component.ForceDrink)
+            {
+                component.ForceDrink = false;
+                return;
+            }
+
             if (args.Handled || args.Cancelled || component.Deleted)
                 return;
 
@@ -295,11 +303,11 @@ namespace Content.Server.Nutrition.EntitySystems
             var transferAmount = FixedPoint2.Min(component.TransferAmount, args.AdditionalData.DrinkSolution.Volume);
             var drained = _solutionContainerSystem.Drain(uid, args.AdditionalData.DrinkSolution, transferAmount);
 
-            var forceDrink = args.Args.Target.Value != args.Args.User;
+            //var forceDrink = args.Args.Target.Value != args.Args.User;
 
             if (!_bodySystem.TryGetBodyOrganComponents<StomachComponent>(args.Args.Target.Value, out var stomachs, body))
             {
-                _popupSystem.PopupEntity(forceDrink ? Loc.GetString("drink-component-try-use-drink-cannot-drink-other") : Loc.GetString("drink-component-try-use-drink-had-enough"), args.Args.Target.Value, args.Args.User);
+                _popupSystem.PopupEntity(component.ForceDrink ? Loc.GetString("drink-component-try-use-drink-cannot-drink-other") : Loc.GetString("drink-component-try-use-drink-had-enough"), args.Args.Target.Value, args.Args.User);
 
                 if (HasComp<RefillableSolutionComponent>(args.Args.Target.Value))
                 {
@@ -320,7 +328,7 @@ namespace Content.Server.Nutrition.EntitySystems
             {
                 _popupSystem.PopupEntity(Loc.GetString("drink-component-try-use-drink-had-enough"), args.Args.Target.Value, args.Args.Target.Value);
 
-                if (forceDrink)
+                if (component.ForceDrink)
                 {
                     _popupSystem.PopupEntity(Loc.GetString("drink-component-try-use-drink-had-enough-other"), args.Args.Target.Value, args.Args.User);
                     _spillableSystem.SpillAt(args.Args.Target.Value, drained, "PuddleSmear");
@@ -334,7 +342,7 @@ namespace Content.Server.Nutrition.EntitySystems
 
             var flavors = args.AdditionalData.FlavorMessage;
 
-            if (forceDrink)
+            if (component.ForceDrink)
             {
                 var targetName = Identity.Entity(args.Args.Target.Value, EntityManager);
                 var userName = Identity.Entity(args.Args.User, EntityManager);
@@ -366,6 +374,7 @@ namespace Content.Server.Nutrition.EntitySystems
             //TODO: Grab the stomach UIDs somehow without using Owner
             _stomachSystem.TryTransferSolution(firstStomach.Value.Comp.Owner, drained, firstStomach.Value.Comp);
 
+            component.ForceDrink = false;
             args.Handled = true;
         }
 
index 0768313eb11f74456e1c1f35849add027585be02..2ff765f855680b6be0cce228c9d89b1f4693d823 100644 (file)
@@ -86,8 +86,8 @@ namespace Content.Server.Nutrition.EntitySystems
             if (food == user || EntityManager.TryGetComponent<MobStateComponent>(food, out var mobState) && _mobStateSystem.IsAlive(food, mobState)) // Suppresses eating alive mobs
                 return false;
 
-            // Target can't be fed
-            if (!EntityManager.HasComponent<BodyComponent>(target))
+            // Target can't be fed or they're already forcefeeding
+            if (!EntityManager.HasComponent<BodyComponent>(target) || foodComp.ForceFeed)
                 return false;
 
             if (!_solutionContainerSystem.TryGetSolution(food, foodComp.SolutionName, out var foodSolution))
@@ -111,9 +111,9 @@ namespace Content.Server.Nutrition.EntitySystems
             if (!_interactionSystem.InRangeUnobstructed(user, food, popup: true))
                 return true;
 
-            var forceFeed = user != target;
+            foodComp.ForceFeed = user != target;
 
-            if (forceFeed)
+            if (foodComp.ForceFeed)
             {
                 var userName = Identity.Entity(user, EntityManager);
                 _popupSystem.PopupEntity(Loc.GetString("food-system-force-feed", ("user", userName)),
@@ -128,16 +128,16 @@ namespace Content.Server.Nutrition.EntitySystems
                 _adminLogger.Add(LogType.Ingestion, LogImpact.Low, $"{ToPrettyString(target):target} is eating {ToPrettyString(food):food} {SolutionContainerSystem.ToPrettyString(foodSolution)}");
             }
 
-            var moveBreak = user != target;
-
             var foodData = new FoodData(foodSolution, flavors, utensils);
 
-            var doAfterEventArgs = new DoAfterEventArgs(user, forceFeed ? foodComp.ForceFeedDelay : foodComp.Delay, target: target, used: food)
+            var doAfterEventArgs = new DoAfterEventArgs(user, foodComp.ForceFeed ? foodComp.ForceFeedDelay : foodComp.Delay, target: target, used: food)
             {
-                BreakOnUserMove = moveBreak,
+                RaiseOnTarget = foodComp.ForceFeed,
+                RaiseOnUser = !foodComp.ForceFeed,
+                BreakOnUserMove = foodComp.ForceFeed,
                 BreakOnDamage = true,
                 BreakOnStun = true,
-                BreakOnTargetMove = moveBreak,
+                BreakOnTargetMove = foodComp.ForceFeed,
                 MovementThreshold = 0.01f,
                 DistanceThreshold = 1.0f,
                 NeedHand = true
@@ -151,6 +151,13 @@ namespace Content.Server.Nutrition.EntitySystems
 
         private void OnDoAfter(EntityUid uid, FoodComponent component, DoAfterEvent<FoodData> args)
         {
+            //Prevents the target from being force fed food but allows the user to chow down
+            if (args.Cancelled && component.ForceFeed)
+            {
+                component.ForceFeed = false;
+                return;
+            }
+
             if (args.Cancelled || args.Handled || component.Deleted || args.Args.Target == null)
                 return;
 
@@ -166,13 +173,11 @@ namespace Content.Server.Nutrition.EntitySystems
             //TODO: Get the stomach UID somehow without nabbing owner
             var firstStomach = stomachs.FirstOrNull(stomach => _stomachSystem.CanTransferSolution(stomach.Comp.Owner, split));
 
-            var forceFeed = args.Args.Target.Value != args.Args.User;
-
             // No stomach so just popup a message that they can't eat.
             if (firstStomach == null)
             {
                 _solutionContainerSystem.TryAddSolution(uid, args.AdditionalData.FoodSolution, split);
-                _popupSystem.PopupEntity(forceFeed ? Loc.GetString("food-system-you-cannot-eat-any-more-other") : Loc.GetString("food-system-you-cannot-eat-any-more"), args.Args.Target.Value, args.Args.User);
+                _popupSystem.PopupEntity(component.ForceFeed ? Loc.GetString("food-system-you-cannot-eat-any-more-other") : Loc.GetString("food-system-you-cannot-eat-any-more"), args.Args.Target.Value, args.Args.User);
                 args.Handled = true;
                 return;
             }
@@ -182,7 +187,7 @@ namespace Content.Server.Nutrition.EntitySystems
 
             var flavors = args.AdditionalData.FlavorMessage;
 
-            if (forceFeed)
+            if (component.ForceFeed)
             {
                 var targetName = Identity.Entity(args.Args.Target.Value, EntityManager);
                 var userName = Identity.Entity(args.Args.User, EntityManager);
index 82566e355930ce8cd0aab7e410c091f3a6a78041..9dee4fc00449677ab957ae817da05010dd51c6ce 100644 (file)
@@ -15,5 +15,8 @@ namespace Content.Server.Tools.Components
 
         [DataField("delay")]
         public float Delay = 1f;
+
+        [DataField("cancelToken")]
+        public CancellationTokenSource? CancelToken;
     }
 }
index 1af417a533be68a8fb07af25cd09d7603387a391..ea257548d386fddca7e69a7bd3190ba893e30076 100644 (file)
@@ -19,10 +19,20 @@ public sealed partial class ToolSystem
     {
         SubscribeLocalEvent<TilePryingComponent, AfterInteractEvent>(OnTilePryingAfterInteract);
         SubscribeLocalEvent<TilePryingComponent, TilePryingCompleteEvent>(OnTilePryComplete);
+        SubscribeLocalEvent<TilePryingComponent, TilePryingCancelledEvent>(OnTilePryCancelled);
+    }
+
+    private void OnTilePryingAfterInteract(EntityUid uid, TilePryingComponent component, AfterInteractEvent args)
+    {
+        if (args.Handled || !args.CanReach || (args.Target != null && !HasComp<PuddleComponent>(args.Target))) return;
+
+        if (TryPryTile(uid, args.User, component, args.ClickLocation))
+            args.Handled = true;
     }
 
     private void OnTilePryComplete(EntityUid uid, TilePryingComponent component, TilePryingCompleteEvent args)
     {
+        component.CancelToken = null;
         var gridUid = args.Coordinates.GetGridUid(EntityManager);
         if (!_mapManager.TryGetGrid(gridUid, out var grid))
         {
@@ -34,17 +44,14 @@ public sealed partial class ToolSystem
         _tile.PryTile(tile);
     }
 
-    private void OnTilePryingAfterInteract(EntityUid uid, TilePryingComponent component, AfterInteractEvent args)
+    private void OnTilePryCancelled(EntityUid uid, TilePryingComponent component, TilePryingCancelledEvent args)
     {
-        if (args.Handled || !args.CanReach || (args.Target != null && !HasComp<PuddleComponent>(args.Target))) return;
-
-        if (TryPryTile(uid, args.User, component, args.ClickLocation))
-            args.Handled = true;
+        component.CancelToken = null;
     }
 
     private bool TryPryTile(EntityUid toolEntity, EntityUid user, TilePryingComponent component, EntityCoordinates clickLocation)
     {
-        if (!TryComp<ToolComponent?>(toolEntity, out var tool) && component.ToolComponentNeeded)
+        if (!TryComp<ToolComponent?>(toolEntity, out var tool) && component.ToolComponentNeeded || component.CancelToken != null)
             return false;
 
         if (!_mapManager.TryGetGrid(clickLocation.GetGridUid(EntityManager), out var mapGrid))
@@ -62,9 +69,11 @@ public sealed partial class ToolSystem
         if (!tileDef.CanCrowbar)
             return false;
 
-        var toolEvData = new ToolEventData(new TilePryingCompleteEvent(clickLocation), targetEntity:toolEntity);
+        component.CancelToken = new CancellationTokenSource();
+
+        var toolEvData = new ToolEventData(new TilePryingCompleteEvent(clickLocation), cancelledEv:new TilePryingCancelledEvent() ,targetEntity:toolEntity);
 
-        if (!UseTool(toolEntity, user, null, component.Delay, new[] { component.QualityNeeded }, toolEvData, toolComponent: tool))
+        if (!UseTool(toolEntity, user, null, component.Delay, new[] { component.QualityNeeded }, toolEvData, toolComponent: tool, cancelToken: component.CancelToken))
             return false;
 
         return true;
index e90126689eb3343fa8cec721278ef87634b67eda..7c81495f086697df2fa9d7b15ca5d9d56c9d623c 100644 (file)
@@ -10,6 +10,12 @@ namespace Content.Shared.Chemistry.Components
     [NetworkedComponent, ComponentProtoName("Injector")]
     public abstract class SharedInjectorComponent : Component
     {
+        /// <summary>
+        /// Checks to see if the entity being injected
+        /// </summary>
+        [DataField("isInjecting")]
+        public bool IsInjecting;
+
         /// <summary>
         /// Component data used for net updates. Used by client for item status ui
         /// </summary>
index b723395885d01a57a572ae2ef5cef9060c396e1e..3006c95b89cd026e28e5c31263315d430147ba5f 100644 (file)
@@ -1,4 +1,5 @@
 using System.Linq;
+using System.Threading;
 using Content.Shared.Audio;
 using Content.Shared.DoAfter;
 using Content.Shared.Interaction;
@@ -31,30 +32,36 @@ public abstract class SharedToolSystem : EntitySystem
 
     private void OnDoAfter(EntityUid uid, ToolComponent component, DoAfterEvent<ToolEventData> args)
     {
-        if (args.Handled || args.Cancelled || args.AdditionalData.Ev == null)
+        if (args.Handled || args.AdditionalData.Ev == null)
             return;
 
-        if (ToolFinishUse(uid, args.Args.User, args.AdditionalData.Fuel))
+        if (args.Cancelled)
         {
-            if (args.AdditionalData.TargetEntity != null)
-                RaiseLocalEvent(args.AdditionalData.TargetEntity.Value, args.AdditionalData.Ev);
-            else
-                RaiseLocalEvent(args.AdditionalData.Ev);
+            if (args.AdditionalData.CancelledEv != null)
+            {
+                if (args.AdditionalData.TargetEntity != null)
+                    RaiseLocalEvent(args.AdditionalData.TargetEntity.Value, args.AdditionalData.CancelledEv);
+                else
+                    RaiseLocalEvent(args.AdditionalData.CancelledEv);
 
-            args.Handled = true;
+                args.Handled = true;
+            }
+
+            return;
         }
-        else if (args.AdditionalData.CancelledEv != null)
+
+        if (ToolFinishUse(uid, args.Args.User, args.AdditionalData.Fuel))
         {
             if (args.AdditionalData.TargetEntity != null)
-                RaiseLocalEvent(args.AdditionalData.TargetEntity.Value, args.AdditionalData.CancelledEv);
+                RaiseLocalEvent(args.AdditionalData.TargetEntity.Value, args.AdditionalData.Ev);
             else
-                RaiseLocalEvent(args.AdditionalData.CancelledEv);
+                RaiseLocalEvent(args.AdditionalData.Ev);
 
             args.Handled = true;
         }
     }
 
-    public bool UseTool(EntityUid tool, EntityUid user, EntityUid? target, float doAfterDelay, IEnumerable<string> toolQualitiesNeeded, ToolEventData toolEventData, float fuel = 0f, ToolComponent? toolComponent = null, Func<bool>? doAfterCheck = null)
+    public bool UseTool(EntityUid tool, EntityUid user, EntityUid? target, float doAfterDelay, IEnumerable<string> toolQualitiesNeeded, ToolEventData toolEventData, float fuel = 0f, ToolComponent? toolComponent = null, Func<bool>? doAfterCheck = null, CancellationTokenSource? cancelToken = null)
     {
         // No logging here, after all that'd mean the caller would need to check if the component is there or not.
         if (!Resolve(tool, ref toolComponent, false))
@@ -70,7 +77,7 @@ public abstract class SharedToolSystem : EntitySystem
 
         if (doAfterDelay > 0f)
         {
-            var doAfterArgs = new DoAfterEventArgs(user, doAfterDelay / toolComponent.SpeedModifier, target:target, used:tool)
+            var doAfterArgs = new DoAfterEventArgs(user, doAfterDelay / toolComponent.SpeedModifier, cancelToken:cancelToken?.Token ?? default, target:target, used:tool)
             {
                 ExtraCheck = doAfterCheck,
                 BreakOnDamage = true,