diff --git a/Content.Client/Cuffs/CuffableSystem.cs b/Content.Client/Cuffs/CuffableSystem.cs
index 42d0ae03fe..e69d292221 100644
--- a/Content.Client/Cuffs/CuffableSystem.cs
+++ b/Content.Client/Cuffs/CuffableSystem.cs
@@ -25,7 +25,6 @@ public sealed class CuffableSystem : SharedCuffableSystem
if (args.Current is not HandcuffComponentState state)
return;
- component.Cuffing = state.Cuffing;
component.OverlayIconState = state.IconState;
}
@@ -41,7 +40,6 @@ public sealed class CuffableSystem : SharedCuffableSystem
return;
component.CanStillInteract = cuffState.CanStillInteract;
- component.Uncuffing = cuffState.Uncuffing;
_actionBlocker.UpdateCanMove(uid);
var ev = new CuffedStateChangeEvent();
diff --git a/Content.Client/DoAfter/DoAfterOverlay.cs b/Content.Client/DoAfter/DoAfterOverlay.cs
index 1af3d8a6b2..090a8bc6a5 100644
--- a/Content.Client/DoAfter/DoAfterOverlay.cs
+++ b/Content.Client/DoAfter/DoAfterOverlay.cs
@@ -3,6 +3,7 @@ using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Shared.Enums;
using Robust.Shared.Prototypes;
+using Robust.Shared.Timing;
using Robust.Shared.Utility;
namespace Content.Client.DoAfter;
@@ -10,17 +11,30 @@ namespace Content.Client.DoAfter;
public sealed class DoAfterOverlay : Overlay
{
private readonly IEntityManager _entManager;
+ private readonly IGameTiming _timing;
private readonly SharedTransformSystem _transform;
+ private readonly MetaDataSystem _meta;
private readonly Texture _barTexture;
private readonly ShaderInstance _shader;
+ ///
+ /// Flash time for cancelled DoAfters
+ ///
+ private const float FlashTime = 0.125f;
+
+ // Hardcoded width of the progress bar because it doesn't match the texture.
+ private const float StartX = 2;
+ private const float EndX = 22f;
+
public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowFOV;
- public DoAfterOverlay(IEntityManager entManager, IPrototypeManager protoManager)
+ public DoAfterOverlay(IEntityManager entManager, IPrototypeManager protoManager, IGameTiming timing)
{
_entManager = entManager;
+ _timing = timing;
_transform = _entManager.EntitySysManager.GetEntitySystem();
+ _meta = _entManager.EntitySysManager.GetEntitySystem();
var sprite = new SpriteSpecifier.Rsi(new ResourcePath("/Textures/Interface/Misc/progress_bar.rsi"), "icon");
_barTexture = _entManager.EntitySysManager.GetEntitySystem().Frame0(sprite);
@@ -31,7 +45,6 @@ public sealed class DoAfterOverlay : Overlay
{
var handle = args.WorldHandle;
var rotation = args.Viewport.Eye?.Rotation ?? Angle.Zero;
- var spriteQuery = _entManager.GetEntityQuery();
var xformQuery = _entManager.GetEntityQuery();
// If you use the display UI scale then need to set max(1f, displayscale) because 0 is valid.
@@ -40,43 +53,42 @@ public sealed class DoAfterOverlay : Overlay
var rotationMatrix = Matrix3.CreateRotation(-rotation);
handle.UseShader(_shader);
- // TODO: Need active DoAfter component (or alternatively just make DoAfter itself active)
- foreach (var comp in _entManager.EntityQuery(true))
- {
- if (comp.DoAfters.Count == 0 ||
- !xformQuery.TryGetComponent(comp.Owner, out var xform) ||
- xform.MapID != args.MapId)
- {
- continue;
- }
+ var curTime = _timing.CurTime;
+
+ var bounds = args.WorldAABB.Enlarged(5f);
+
+ var metaQuery = _entManager.GetEntityQuery();
+ var enumerator = _entManager.AllEntityQueryEnumerator();
+ while (enumerator.MoveNext(out var uid, out _, out var comp, out var sprite, out var xform))
+ {
+ if (xform.MapID != args.MapId)
+ continue;
+
+ if (comp.DoAfters.Count == 0)
+ continue;
+
+ var worldPosition = _transform.GetWorldPosition(xform, xformQuery);
+ if (!bounds.Contains(worldPosition))
+ continue;
+
+ // If the entity is paused, we will draw the do-after as it was when the entity got paused.
+ var meta = metaQuery.GetComponent(uid);
+ var time = meta.EntityPaused
+ ? curTime - _meta.GetPauseTime(uid, meta)
+ : curTime;
- var worldPosition = _transform.GetWorldPosition(xform);
- var index = 0;
var worldMatrix = Matrix3.CreateTranslation(worldPosition);
+ Matrix3.Multiply(scaleMatrix, worldMatrix, out var scaledWorld);
+ Matrix3.Multiply(rotationMatrix, scaledWorld, out var matty);
+ handle.SetTransform(matty);
+
+ var offset = 0f;
foreach (var doAfter in comp.DoAfters.Values)
{
- var elapsed = doAfter.Elapsed;
- var displayRatio = MathF.Min(1.0f,
- (float)elapsed.TotalSeconds / doAfter.Delay);
-
- Matrix3.Multiply(scaleMatrix, worldMatrix, out var scaledWorld);
- Matrix3.Multiply(rotationMatrix, scaledWorld, out var matty);
-
- handle.SetTransform(matty);
- var offset = _barTexture.Height / scale * index;
-
// Use the sprite itself if we know its bounds. This means short or tall sprites don't get overlapped
// by the bar.
- float yOffset;
- if (spriteQuery.TryGetComponent(comp.Owner, out var sprite))
- {
- yOffset = sprite.Bounds.Height / 2f + 0.05f;
- }
- else
- {
- yOffset = 0.5f;
- }
+ float yOffset = sprite.Bounds.Height / 2f + 0.05f;
// Position above the entity (we've already applied the matrix transform to the entity itself)
// Offset by the texture size for every do_after we have.
@@ -86,33 +98,30 @@ public sealed class DoAfterOverlay : Overlay
// Draw the underlying bar texture
handle.DrawTexture(_barTexture, position);
- // Draw the bar itself
- var cancelled = doAfter.Cancelled;
Color color;
- const float flashTime = 0.125f;
+ float elapsedRatio;
// if we're cancelled then flick red / off.
- if (cancelled)
+ if (doAfter.CancelledTime != null)
{
- var flash = Math.Floor((float)doAfter.CancelledElapsed.TotalSeconds / flashTime) % 2 == 0;
+ var elapsed = doAfter.CancelledTime.Value - doAfter.StartTime;
+ elapsedRatio = (float) Math.Min(1, elapsed.TotalSeconds / doAfter.Args.Delay.TotalSeconds);
+ var cancelElapsed = (time - doAfter.CancelledTime.Value).TotalSeconds;
+ var flash = Math.Floor(cancelElapsed / FlashTime) % 2 == 0;
color = new Color(1f, 0f, 0f, flash ? 1f : 0f);
}
else
{
- color = GetProgressColor(displayRatio);
+ var elapsed = time - doAfter.StartTime;
+ elapsedRatio = (float) Math.Min(1, elapsed.TotalSeconds / doAfter.Args.Delay.TotalSeconds);
+ color = GetProgressColor(elapsedRatio);
}
- // Hardcoded width of the progress bar because it doesn't match the texture.
- const float startX = 2f;
- const float endX = 22f;
-
- var xProgress = (endX - startX) * displayRatio + startX;
-
- var box = new Box2(new Vector2(startX, 3f) / EyeManager.PixelsPerMeter, new Vector2(xProgress, 4f) / EyeManager.PixelsPerMeter);
+ var xProgress = (EndX - StartX) * elapsedRatio + StartX;
+ var box = new Box2(new Vector2(StartX, 3f) / EyeManager.PixelsPerMeter, new Vector2(xProgress, 4f) / EyeManager.PixelsPerMeter);
box = box.Translated(position);
handle.DrawRect(box, color);
-
- index++;
+ offset += _barTexture.Height / scale;
}
}
diff --git a/Content.Client/DoAfter/DoAfterSystem.cs b/Content.Client/DoAfter/DoAfterSystem.cs
index c4e06376da..ecabaa20e8 100644
--- a/Content.Client/DoAfter/DoAfterSystem.cs
+++ b/Content.Client/DoAfter/DoAfterSystem.cs
@@ -1,9 +1,8 @@
using Content.Shared.DoAfter;
+using Content.Shared.Hands.Components;
using Robust.Client.Graphics;
using Robust.Client.Player;
-using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
-using Robust.Shared.Utility;
namespace Content.Client.DoAfter;
@@ -16,19 +15,12 @@ public sealed class DoAfterSystem : SharedDoAfterSystem
[Dependency] private readonly IOverlayManager _overlay = default!;
[Dependency] private readonly IPlayerManager _player = default!;
[Dependency] private readonly IPrototypeManager _prototype = default!;
-
- ///
- /// We'll use an excess time so stuff like finishing effects can show.
- ///
- public const float ExcessTime = 0.5f;
+ [Dependency] private readonly MetaDataSystem _metadata = default!;
public override void Initialize()
{
base.Initialize();
- UpdatesOutsidePrediction = true;
- SubscribeNetworkEvent(OnCancelledDoAfter);
- SubscribeLocalEvent(OnDoAfterHandleState);
- _overlay.AddOverlay(new DoAfterOverlay(EntityManager, _prototype));
+ _overlay.AddOverlay(new DoAfterOverlay(EntityManager, _prototype, GameTiming));
}
public override void Shutdown()
@@ -37,147 +29,26 @@ public sealed class DoAfterSystem : SharedDoAfterSystem
_overlay.RemoveOverlay();
}
- private void OnDoAfterHandleState(EntityUid uid, DoAfterComponent component, ref ComponentHandleState args)
- {
- if (args.Current is not DoAfterComponentState state)
- return;
-
- foreach (var (_, doAfter) in state.DoAfters)
- {
- if (component.DoAfters.ContainsKey(doAfter.ID))
- continue;
-
- component.DoAfters.Add(doAfter.ID, doAfter);
- }
- }
-
- private void OnCancelledDoAfter(CancelledDoAfterMessage ev)
- {
- if (!TryComp(ev.Uid, out var doAfter))
- return;
-
- Cancel(doAfter, ev.ID);
- }
-
- ///
- /// Remove a DoAfter without showing a cancellation graphic.
- ///
- public void Remove(DoAfterComponent component, Shared.DoAfter.DoAfter doAfter, bool found = false)
- {
- component.DoAfters.Remove(doAfter.ID);
- component.CancelledDoAfters.Remove(doAfter.ID);
- }
-
- ///
- /// Mark a DoAfter as cancelled and show a cancellation graphic.
- ///
- /// Actual removal is handled by DoAfterEntitySystem.
- public void Cancel(DoAfterComponent component, byte id)
- {
- if (component.CancelledDoAfters.ContainsKey(id))
- return;
-
- if (!component.DoAfters.ContainsKey(id))
- return;
-
- var doAfterMessage = component.DoAfters[id];
- doAfterMessage.Cancelled = true;
- doAfterMessage.CancelledTime = GameTiming.CurTime;
- component.CancelledDoAfters.Add(id, doAfterMessage);
- }
-
- // TODO separate DoAfter & ActiveDoAfter components for the entity query.
public override void Update(float frameTime)
{
- if (!GameTiming.IsFirstTimePredicted)
- return;
+ // Currently this only predicts do afters initiated by the player.
+
+ // TODO maybe predict do-afters if the local player is the target of some other players do-after? Specifically
+ // ones that depend on the target not moving, because the cancellation of those do afters should be readily
+ // predictable by clients.
var playerEntity = _player.LocalPlayer?.ControlledEntity;
- foreach (var (comp, xform) in EntityQuery())
- {
- var doAfters = comp.DoAfters;
+ if (!TryComp(playerEntity, out ActiveDoAfterComponent? active))
+ return;
- if (doAfters.Count == 0)
- continue;
+ if (_metadata.EntityPaused(playerEntity.Value))
+ return;
- var userGrid = xform.Coordinates;
- var toRemove = new RemQueue();
-
- // Check cancellations / finishes
- foreach (var (id, doAfter) in doAfters)
- {
- // If we've passed the final time (after the excess to show completion graphic) then remove.
- if ((float)doAfter.Elapsed.TotalSeconds + (float)doAfter.CancelledElapsed.TotalSeconds >
- doAfter.Delay + ExcessTime)
- {
- toRemove.Add(doAfter);
- continue;
- }
-
- if (doAfter.Cancelled)
- {
- doAfter.CancelledElapsed = GameTiming.CurTime - doAfter.CancelledTime;
- continue;
- }
-
- doAfter.Elapsed = GameTiming.CurTime - doAfter.StartTime;
-
- // Well we finished so don't try to predict cancels.
- if ((float)doAfter.Elapsed.TotalSeconds > doAfter.Delay)
- continue;
-
- // Predictions
- if (comp.Owner != playerEntity)
- continue;
-
- // TODO: Add these back in when I work out some system for changing the accumulation rate
- // based on ping. Right now these would show as cancelled near completion if we moved at the end
- // despite succeeding.
- continue;
-
- if (doAfter.EventArgs.BreakOnUserMove)
- {
- if (!userGrid.InRange(EntityManager, doAfter.UserGrid, doAfter.EventArgs.MovementThreshold))
- {
- Cancel(comp, id);
- continue;
- }
- }
-
- if (doAfter.EventArgs.BreakOnTargetMove)
- {
- if (!Deleted(doAfter.EventArgs.Target) &&
- !Transform(doAfter.EventArgs.Target.Value).Coordinates.InRange(EntityManager,
- doAfter.TargetGrid,
- doAfter.EventArgs.MovementThreshold))
- {
- Cancel(comp, id);
- continue;
- }
- }
- }
-
- foreach (var doAfter in toRemove)
- {
- Remove(comp, doAfter);
- }
-
- // Remove cancelled DoAfters after ExcessTime has elapsed
- var toRemoveCancelled = new RemQueue();
-
- foreach (var (_, doAfter) in comp.CancelledDoAfters)
- {
- var cancelledElapsed = (float)doAfter.CancelledElapsed.TotalSeconds;
-
- if (cancelledElapsed > ExcessTime)
- toRemoveCancelled.Add(doAfter);
- }
-
- foreach (var doAfter in toRemoveCancelled)
- {
- Remove(comp, doAfter);
- }
- }
+ var time = GameTiming.CurTime;
+ var comp = Comp(playerEntity.Value);
+ var xformQuery = GetEntityQuery();
+ var handsQuery = GetEntityQuery();
+ Update(playerEntity.Value, active, comp, time, xformQuery, handsQuery);
}
}
diff --git a/Content.Client/Medical/Cryogenics/CryoPodSystem.cs b/Content.Client/Medical/Cryogenics/CryoPodSystem.cs
index fffbe3469b..d1918d75fb 100644
--- a/Content.Client/Medical/Cryogenics/CryoPodSystem.cs
+++ b/Content.Client/Medical/Cryogenics/CryoPodSystem.cs
@@ -19,7 +19,6 @@ public sealed class CryoPodSystem: SharedCryoPodSystem
SubscribeLocalEvent>(AddAlternativeVerbs);
SubscribeLocalEvent(OnEmagged);
SubscribeLocalEvent(OnCryoPodPryFinished);
- SubscribeLocalEvent(OnCryoPodPryInterrupted);
SubscribeLocalEvent(OnAppearanceChange);
SubscribeLocalEvent(OnCryoPodInsertion);
diff --git a/Content.Client/UserInterface/Systems/Alerts/AlertsUIController.cs b/Content.Client/UserInterface/Systems/Alerts/AlertsUIController.cs
index 5fe84b506c..826bbf199b 100644
--- a/Content.Client/UserInterface/Systems/Alerts/AlertsUIController.cs
+++ b/Content.Client/UserInterface/Systems/Alerts/AlertsUIController.cs
@@ -20,10 +20,22 @@ public sealed class AlertsUIController : UIController, IOnStateEntered();
gameplayStateLoad.OnScreenLoad += OnScreenLoad;
+ gameplayStateLoad.OnScreenUnload += OnScreenUnload;
+ }
+
+ private void OnScreenUnload()
+ {
+ var widget = UI;
+ if (widget != null)
+ widget.AlertPressed -= OnAlertPressed;
}
private void OnScreenLoad()
{
+ var widget = UI;
+ if (widget != null)
+ widget.AlertPressed += OnAlertPressed;
+
SyncAlerts();
}
@@ -43,14 +55,6 @@ public sealed class AlertsUIController : UIController, IOnStateEntered>(OnTestDoAfterFinishEvent);
+ return this;
}
-
- private void OnTestDoAfterFinishEvent(DoAfterEvent ev)
- {
- ev.AdditionalData.Cancelled = ev.Cancelled;
- }
- }
-
- private sealed class TestDoAfterData
- {
- public bool Cancelled;
};
+ [Test]
+ public async Task TestSerializable()
+ {
+ await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true});
+ var server = pairTracker.Pair.Server;
+ await server.WaitIdleAsync();
+ var refMan = server.ResolveDependency();
+
+ await server.WaitPost(() =>
+ {
+ Assert.Multiple(() =>
+ {
+ foreach (var type in refMan.GetAllChildren(true))
+ {
+ if (type.IsAbstract || type == typeof(TestDoAfterEvent))
+ continue;
+
+ Assert.That(type.HasCustomAttribute()
+ && type.HasCustomAttribute(),
+ $"{nameof(DoAfterEvent)} is not NetSerializable. Event: {type.Name}");
+ }
+ });
+ });
+
+ await pairTracker.CleanReturnAsync();
+ }
+
[Test]
public async Task TestFinished()
{
@@ -48,21 +67,21 @@ namespace Content.IntegrationTests.Tests.DoAfter
await server.WaitIdleAsync();
var entityManager = server.ResolveDependency();
- var doAfterSystem = entityManager.EntitySysManager.GetEntitySystem();
- var data = new TestDoAfterData();
+ var doAfterSystem = entityManager.EntitySysManager.GetEntitySystem();
+ var ev = new TestDoAfterEvent();
// That it finishes successfully
await server.WaitPost(() =>
{
var tickTime = 1.0f / IoCManager.Resolve().TickRate;
var mob = entityManager.SpawnEntity("Dummy", MapCoordinates.Nullspace);
- var cancelToken = new CancellationTokenSource();
- var args = new DoAfterEventArgs(mob, tickTime / 2, cancelToken.Token) { Broadcast = true };
- doAfterSystem.DoAfter(args, data);
+ var args = new DoAfterArgs(mob, tickTime / 2, ev, null) { Broadcast = true };
+ Assert.That(doAfterSystem.TryStartDoAfter(args));
+ Assert.That(ev.Cancelled, Is.False);
});
await server.WaitRunTicks(1);
- Assert.That(data.Cancelled, Is.False);
+ Assert.That(ev.Cancelled, Is.False);
await pairTracker.CleanReturnAsync();
}
@@ -73,22 +92,32 @@ namespace Content.IntegrationTests.Tests.DoAfter
await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes});
var server = pairTracker.Pair.Server;
var entityManager = server.ResolveDependency();
- var doAfterSystem = entityManager.EntitySysManager.GetEntitySystem();
- var data = new TestDoAfterData();
+ var doAfterSystem = entityManager.EntitySysManager.GetEntitySystem();
+ DoAfterId? id = default;
+ var ev = new TestDoAfterEvent();
+
await server.WaitPost(() =>
{
var tickTime = 1.0f / IoCManager.Resolve().TickRate;
var mob = entityManager.SpawnEntity("Dummy", MapCoordinates.Nullspace);
- var cancelToken = new CancellationTokenSource();
- var args = new DoAfterEventArgs(mob, tickTime * 2, cancelToken.Token) { Broadcast = true };
- doAfterSystem.DoAfter(args, data);
- cancelToken.Cancel();
+ var args = new DoAfterArgs(mob, tickTime * 2, ev, null) { Broadcast = true };
+
+ if (!doAfterSystem.TryStartDoAfter(args, out id))
+ {
+ Assert.Fail();
+ return;
+ }
+
+ Assert.That(!ev.Cancelled);
+ doAfterSystem.Cancel(id);
+ Assert.That(ev.Cancelled);
+
});
await server.WaitRunTicks(3);
- Assert.That(data.Cancelled, Is.True);
+ Assert.That(ev.Cancelled);
await pairTracker.CleanReturnAsync();
}
diff --git a/Content.Server/AirlockPainter/AirlockPainterSystem.cs b/Content.Server/AirlockPainter/AirlockPainterSystem.cs
index b21ee825e0..59f0d6ae7b 100644
--- a/Content.Server/AirlockPainter/AirlockPainterSystem.cs
+++ b/Content.Server/AirlockPainter/AirlockPainterSystem.cs
@@ -1,5 +1,4 @@
using Content.Server.Administration.Logs;
-using Content.Server.DoAfter;
using Content.Server.Popups;
using Content.Server.UserInterface;
using Content.Shared.AirlockPainter;
@@ -10,7 +9,6 @@ using Content.Shared.Doors.Components;
using Content.Shared.Interaction;
using JetBrains.Annotations;
using Robust.Server.GameObjects;
-using Robust.Shared.Player;
namespace Content.Server.AirlockPainter
{
@@ -22,7 +20,7 @@ namespace Content.Server.AirlockPainter
{
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
[Dependency] private readonly UserInterfaceSystem _userInterfaceSystem = default!;
- [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
@@ -34,23 +32,21 @@ namespace Content.Server.AirlockPainter
SubscribeLocalEvent(AfterInteractOn);
SubscribeLocalEvent(OnActivate);
SubscribeLocalEvent(OnSpritePicked);
- SubscribeLocalEvent>(OnDoAfter);
+ SubscribeLocalEvent(OnDoAfter);
}
- private void OnDoAfter(EntityUid uid, AirlockPainterComponent component, DoAfterEvent args)
+ private void OnDoAfter(EntityUid uid, AirlockPainterComponent component, AirlockPainterDoAfterEvent args)
{
+ component.IsSpraying = false;
+
if (args.Handled || args.Cancelled)
- {
- component.IsSpraying = false;
return;
- }
if (args.Args.Target != null)
{
- _audio.Play(component.SpraySound, Filter.Pvs(uid, entityManager:EntityManager), uid, true);
- _appearance.SetData(args.Args.Target.Value, DoorVisuals.BaseRSI, args.AdditionalData.Sprite);
+ _audio.PlayPvs(component.SpraySound, uid);
+ _appearance.SetData(args.Args.Target.Value, DoorVisuals.BaseRSI, args.Sprite);
_adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(args.Args.User):user} painted {ToPrettyString(args.Args.Target.Value):target}");
- component.IsSpraying = false;
}
args.Handled = true;
@@ -88,16 +84,14 @@ namespace Content.Server.AirlockPainter
}
component.IsSpraying = true;
- var airlockPainterData = new AirlockPainterData(sprite);
- var doAfterEventArgs = new DoAfterEventArgs(args.User, component.SprayTime, target:target, used:uid)
+ var doAfterEventArgs = new DoAfterArgs(args.User, component.SprayTime, new AirlockPainterDoAfterEvent(sprite), uid, target: target, used: uid)
{
BreakOnTargetMove = true,
BreakOnUserMove = true,
BreakOnDamage = true,
- BreakOnStun = true,
NeedHand = true,
};
- _doAfterSystem.DoAfter(doAfterEventArgs, airlockPainterData);
+ _doAfterSystem.TryStartDoAfter(doAfterEventArgs);
// Log attempt
_adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(args.User):user} is painting {ToPrettyString(uid):target} to '{style}' at {Transform(uid).Coordinates:targetlocation}");
@@ -118,10 +112,5 @@ namespace Content.Server.AirlockPainter
_userInterfaceSystem.TrySetUiState(uid, AirlockPainterUiKey.Key,
new AirlockPainterBoundUserInterfaceState(component.Index));
}
-
- private record struct AirlockPainterData(string Sprite)
- {
- public string Sprite = Sprite;
- }
}
}
diff --git a/Content.Server/Alert/Click/RemoveEnsnare.cs b/Content.Server/Alert/Click/RemoveEnsnare.cs
index 975734152a..1913dea905 100644
--- a/Content.Server/Alert/Click/RemoveEnsnare.cs
+++ b/Content.Server/Alert/Click/RemoveEnsnare.cs
@@ -18,7 +18,7 @@ public sealed class RemoveEnsnare : IAlertClick
if (!entManager.TryGetComponent(ensnare, out EnsnaringComponent? ensnaringComponent))
return;
- entManager.EntitySysManager.GetEntitySystem().TryFree(player, ensnare, ensnaringComponent);
+ entManager.EntitySysManager.GetEntitySystem().TryFree(player, player, ensnare, ensnaringComponent);
}
}
}
diff --git a/Content.Server/Animals/Components/UdderComponent.cs b/Content.Server/Animals/Components/UdderComponent.cs
index f47b9a855c..ad591022c1 100644
--- a/Content.Server/Animals/Components/UdderComponent.cs
+++ b/Content.Server/Animals/Components/UdderComponent.cs
@@ -37,7 +37,5 @@ namespace Content.Server.Animals.Components
public float UpdateRate = 5;
public float AccumulatedFrameTime;
-
- public bool BeingMilked;
}
}
diff --git a/Content.Server/Animals/Systems/UdderSystem.cs b/Content.Server/Animals/Systems/UdderSystem.cs
index adb8a2bf83..ad0e6be27f 100644
--- a/Content.Server/Animals/Systems/UdderSystem.cs
+++ b/Content.Server/Animals/Systems/UdderSystem.cs
@@ -1,13 +1,13 @@
using Content.Server.Animals.Components;
using Content.Server.Chemistry.Components.SolutionManager;
using Content.Server.Chemistry.EntitySystems;
-using Content.Server.DoAfter;
using Content.Server.Nutrition.Components;
using Content.Server.Popups;
using Content.Shared.DoAfter;
using Content.Shared.IdentityManagement;
using Content.Shared.Nutrition.Components;
using Content.Shared.Popups;
+using Content.Shared.Udder;
using Content.Shared.Verbs;
namespace Content.Server.Animals.Systems
@@ -18,7 +18,7 @@ namespace Content.Server.Animals.Systems
internal sealed class UdderSystem : EntitySystem
{
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
- [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
public override void Initialize()
@@ -26,7 +26,7 @@ namespace Content.Server.Animals.Systems
base.Initialize();
SubscribeLocalEvent>(AddMilkVerb);
- SubscribeLocalEvent(OnDoAfter);
+ SubscribeLocalEvent(OnDoAfter);
}
public override void Update(float frameTime)
{
@@ -64,38 +64,21 @@ namespace Content.Server.Animals.Systems
if (!Resolve(uid, ref udder))
return;
- if (udder.BeingMilked)
- {
- _popupSystem.PopupEntity(Loc.GetString("udder-system-already-milking"), uid, userUid);
- return;
- }
-
- udder.BeingMilked = true;
-
- var doargs = new DoAfterEventArgs(userUid, 5, target:uid, used:containerUid)
+ var doargs = new DoAfterArgs(userUid, 5, new MilkingDoAfterEvent(), uid, uid, used: containerUid)
{
BreakOnUserMove = true,
BreakOnDamage = true,
- BreakOnStun = true,
BreakOnTargetMove = true,
- MovementThreshold = 1.0f
+ MovementThreshold = 1.0f,
};
- _doAfterSystem.DoAfter(doargs);
+ _doAfterSystem.TryStartDoAfter(doargs);
}
- private void OnDoAfter(EntityUid uid, UdderComponent component, DoAfterEvent args)
+ private void OnDoAfter(EntityUid uid, UdderComponent component, MilkingDoAfterEvent args)
{
- if (args.Cancelled)
- {
- component.BeingMilked = false;
+ if (args.Cancelled || args.Handled || args.Args.Used == null)
return;
- }
-
- if (args.Handled || args.Args.Used == null)
- return;
-
- component.BeingMilked = false;
if (!_solutionContainerSystem.TryGetSolution(uid, component.TargetSolutionName, out var solution))
return;
@@ -103,6 +86,7 @@ namespace Content.Server.Animals.Systems
if (!_solutionContainerSystem.TryGetRefillableSolution(args.Args.Used.Value, out var targetSolution))
return;
+ args.Handled = true;
var quantity = solution.Volume;
if(quantity == 0)
{
@@ -118,8 +102,6 @@ namespace Content.Server.Animals.Systems
_popupSystem.PopupEntity(Loc.GetString("udder-system-success", ("amount", quantity), ("target", Identity.Entity(args.Args.Used.Value, EntityManager))), uid,
args.Args.User, PopupType.Medium);
-
- args.Handled = true;
}
private void AddMilkVerb(EntityUid uid, UdderComponent component, GetVerbsEvent args)
diff --git a/Content.Server/Anomaly/AnomalySystem.Scanner.cs b/Content.Server/Anomaly/AnomalySystem.Scanner.cs
index 3cd08b0de1..2b090c1689 100644
--- a/Content.Server/Anomaly/AnomalySystem.Scanner.cs
+++ b/Content.Server/Anomaly/AnomalySystem.Scanner.cs
@@ -17,7 +17,7 @@ public sealed partial class AnomalySystem
{
SubscribeLocalEvent(OnScannerUiOpened);
SubscribeLocalEvent(OnScannerAfterInteract);
- SubscribeLocalEvent(OnDoAfter);
+ SubscribeLocalEvent(OnDoAfter);
SubscribeLocalEvent(OnScannerAnomalyShutdown);
SubscribeLocalEvent(OnScannerAnomalySeverityChanged);
@@ -81,7 +81,7 @@ public sealed partial class AnomalySystem
if (!HasComp(target))
return;
- _doAfter.DoAfter(new DoAfterEventArgs(args.User, component.ScanDoAfterDuration, target:target, used:uid)
+ _doAfter.TryStartDoAfter(new DoAfterArgs(args.User, component.ScanDoAfterDuration, new ScannerDoAfterEvent(), uid, target: target, used: uid)
{
DistanceThreshold = 2f
});
diff --git a/Content.Server/Anomaly/AnomalySystem.cs b/Content.Server/Anomaly/AnomalySystem.cs
index 3de46afb46..45e4836480 100644
--- a/Content.Server/Anomaly/AnomalySystem.cs
+++ b/Content.Server/Anomaly/AnomalySystem.cs
@@ -1,12 +1,12 @@
using Content.Server.Anomaly.Components;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Audio;
-using Content.Server.DoAfter;
using Content.Server.Explosion.EntitySystems;
using Content.Server.Materials;
using Content.Server.Radio.EntitySystems;
using Content.Shared.Anomaly;
using Content.Shared.Anomaly.Components;
+using Content.Shared.DoAfter;
using Robust.Server.GameObjects;
using Robust.Shared.Configuration;
using Robust.Shared.Physics.Events;
@@ -24,7 +24,7 @@ public sealed partial class AnomalySystem : SharedAnomalySystem
[Dependency] private readonly IPrototypeManager _prototype = default!;
[Dependency] private readonly AmbientSoundSystem _ambient = default!;
[Dependency] private readonly AtmosphereSystem _atmosphere = default!;
- [Dependency] private readonly DoAfterSystem _doAfter = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly ExplosionSystem _explosion = default!;
[Dependency] private readonly MaterialStorageSystem _material = default!;
[Dependency] private readonly RadioSystem _radio = default!;
diff --git a/Content.Server/Body/Systems/InternalsSystem.cs b/Content.Server/Body/Systems/InternalsSystem.cs
index ed6ed288cc..6b0c8e046e 100644
--- a/Content.Server/Body/Systems/InternalsSystem.cs
+++ b/Content.Server/Body/Systems/InternalsSystem.cs
@@ -9,8 +9,8 @@ using Robust.Shared.Containers;
using Robust.Shared.Prototypes;
using Content.Shared.Verbs;
using Content.Server.Popups;
-using Content.Server.DoAfter;
using Content.Shared.DoAfter;
+using Content.Shared.Internals;
using Robust.Shared.Utility;
namespace Content.Server.Body.Systems;
@@ -20,7 +20,7 @@ public sealed class InternalsSystem : EntitySystem
[Dependency] private readonly IPrototypeManager _protoManager = default!;
[Dependency] private readonly AlertsSystem _alerts = default!;
[Dependency] private readonly AtmosphereSystem _atmos = default!;
- [Dependency] private readonly DoAfterSystem _doAfter = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly GasTankSystem _gasTank = default!;
[Dependency] private readonly HandsSystem _hands = default!;
[Dependency] private readonly InventorySystem _inventory = default!;
@@ -34,7 +34,7 @@ public sealed class InternalsSystem : EntitySystem
SubscribeLocalEvent(OnInternalsStartup);
SubscribeLocalEvent(OnInternalsShutdown);
SubscribeLocalEvent>(OnGetInteractionVerbs);
- SubscribeLocalEvent>(OnDoAfter);
+ SubscribeLocalEvent(OnDoAfter);
}
private void OnGetInteractionVerbs(EntityUid uid, InternalsComponent component, GetVerbsEvent args)
@@ -85,24 +85,19 @@ public sealed class InternalsSystem : EntitySystem
var isUser = uid == user;
- var internalsData = new InternalsData();
-
if (!force)
{
// Is the target not you? If yes, use a do-after to give them time to respond.
//If no, do a short delay. There's no reason it should be beyond 1 second.
var delay = !isUser ? internals.Delay : 1.0f;
- _doAfter.DoAfter(new DoAfterEventArgs(user, delay, target:uid)
+ _doAfter.TryStartDoAfter(new DoAfterArgs(user, delay, new InternalsDoAfterEvent(), uid, target: uid)
{
BreakOnUserMove = true,
BreakOnDamage = true,
- BreakOnStun = true,
BreakOnTargetMove = true,
MovementThreshold = 0.1f,
- RaiseOnUser = isUser,
- RaiseOnTarget = !isUser
- }, internalsData);
+ });
return;
}
@@ -110,12 +105,12 @@ public sealed class InternalsSystem : EntitySystem
_gasTank.ConnectToInternals(tank);
}
- private void OnDoAfter(EntityUid uid, InternalsComponent component, DoAfterEvent args)
+ private void OnDoAfter(EntityUid uid, InternalsComponent component, InternalsDoAfterEvent args)
{
if (args.Cancelled || args.Handled)
return;
- ToggleInternals(uid, args.Args.User, true, component);
+ ToggleInternals(uid, args.User, true, component);
args.Handled = true;
}
@@ -266,9 +261,4 @@ public sealed class InternalsSystem : EntitySystem
return null;
}
-
- private record struct InternalsData
- {
-
- }
}
diff --git a/Content.Server/Botany/Systems/BotanySwabSystem.cs b/Content.Server/Botany/Systems/BotanySwabSystem.cs
index ef7cc1760b..5e5bff0f5c 100644
--- a/Content.Server/Botany/Systems/BotanySwabSystem.cs
+++ b/Content.Server/Botany/Systems/BotanySwabSystem.cs
@@ -1,15 +1,15 @@
using Content.Server.Botany.Components;
-using Content.Server.DoAfter;
using Content.Server.Popups;
using Content.Shared.DoAfter;
using Content.Shared.Examine;
using Content.Shared.Interaction;
+using Content.Shared.Swab;
namespace Content.Server.Botany.Systems;
public sealed class BotanySwabSystem : EntitySystem
{
- [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly MutationSystem _mutationSystem = default!;
@@ -18,7 +18,7 @@ public sealed class BotanySwabSystem : EntitySystem
base.Initialize();
SubscribeLocalEvent(OnExamined);
SubscribeLocalEvent(OnAfterInteract);
- SubscribeLocalEvent(OnDoAfter);
+ SubscribeLocalEvent(OnDoAfter);
}
///
@@ -44,12 +44,11 @@ public sealed class BotanySwabSystem : EntitySystem
if (args.Target == null || !args.CanReach || !HasComp(args.Target))
return;
- _doAfterSystem.DoAfter(new DoAfterEventArgs(args.User, swab.SwabDelay, target: args.Target, used: uid)
+ _doAfterSystem.TryStartDoAfter(new DoAfterArgs(args.User, swab.SwabDelay, new BotanySwabDoAfterEvent(), uid, target: args.Target, used: uid)
{
Broadcast = true,
BreakOnTargetMove = true,
BreakOnUserMove = true,
- BreakOnStun = true,
NeedHand = true
});
}
@@ -57,9 +56,9 @@ public sealed class BotanySwabSystem : EntitySystem
///
/// Save seed data or cross-pollenate.
///
- private void OnDoAfter(EntityUid uid, BotanySwabComponent component, DoAfterEvent args)
+ private void OnDoAfter(EntityUid uid, BotanySwabComponent swab, DoAfterEvent args)
{
- if (args.Cancelled || args.Handled || !TryComp(args.Args.Target, out var plant) || !TryComp(args.Args.Used, out var swab))
+ if (args.Cancelled || args.Handled || !TryComp(args.Args.Target, out var plant))
return;
if (swab.SeedData == null)
diff --git a/Content.Server/Chemistry/EntitySystems/ChemistrySystem.Injector.cs b/Content.Server/Chemistry/EntitySystems/ChemistrySystem.Injector.cs
index 598f470d6e..08bcf300d1 100644
--- a/Content.Server/Chemistry/EntitySystems/ChemistrySystem.Injector.cs
+++ b/Content.Server/Chemistry/EntitySystems/ChemistrySystem.Injector.cs
@@ -1,6 +1,7 @@
using Content.Server.Body.Components;
using Content.Server.Chemistry.Components;
using Content.Server.Chemistry.Components.SolutionManager;
+using Content.Shared.Chemistry;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.Database;
@@ -28,7 +29,7 @@ public sealed partial class ChemistrySystem
{
SubscribeLocalEvent>(AddSetTransferVerbs);
SubscribeLocalEvent(OnSolutionChange);
- SubscribeLocalEvent(OnInjectDoAfter);
+ SubscribeLocalEvent(OnInjectDoAfter);
SubscribeLocalEvent(OnInjectorStartup);
SubscribeLocalEvent(OnInjectorUse);
SubscribeLocalEvent(OnInjectorAfterInteract);
@@ -129,18 +130,10 @@ public sealed partial class ChemistrySystem
private void OnInjectDoAfter(EntityUid uid, InjectorComponent component, DoAfterEvent args)
{
- if (args.Cancelled)
- {
- component.IsInjecting = false;
- return;
- }
-
- if (args.Handled || args.Args.Target == null)
+ if (args.Cancelled || args.Handled || args.Args.Target == null)
return;
UseInjector(args.Args.Target.Value, args.Args.User, uid, component);
-
- component.IsInjecting = false;
args.Handled = true;
}
@@ -223,10 +216,6 @@ 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
@@ -269,17 +258,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)
+ _doAfter.TryStartDoAfter(new DoAfterArgs(user, actualDelay, new InjectorDoAfterEvent(), injector, target: target, used: injector)
{
- RaiseOnTarget = isTarget,
- RaiseOnUser = !isTarget,
BreakOnUserMove = true,
BreakOnDamage = true,
- BreakOnStun = true,
BreakOnTargetMove = true,
- MovementThreshold = 0.1f
+ MovementThreshold = 0.1f,
});
}
@@ -434,4 +418,5 @@ public sealed partial class ChemistrySystem
Dirty(component);
AfterDraw(component, injector);
}
+
}
diff --git a/Content.Server/Chemistry/EntitySystems/ChemistrySystem.cs b/Content.Server/Chemistry/EntitySystems/ChemistrySystem.cs
index 6efb96b55b..b4425f66ce 100644
--- a/Content.Server/Chemistry/EntitySystems/ChemistrySystem.cs
+++ b/Content.Server/Chemistry/EntitySystems/ChemistrySystem.cs
@@ -1,10 +1,10 @@
using Content.Server.Administration.Logs;
using Content.Server.Body.Systems;
-using Content.Server.DoAfter;
using Content.Server.Interaction;
using Content.Server.Popups;
using Content.Shared.CombatMode;
using Content.Shared.Chemistry;
+using Content.Shared.DoAfter;
using Content.Shared.Mobs.Systems;
namespace Content.Server.Chemistry.EntitySystems;
@@ -15,7 +15,7 @@ public sealed partial class ChemistrySystem : EntitySystem
[Dependency] private readonly IEntityManager _entMan = default!;
[Dependency] private readonly InteractionSystem _interaction = default!;
[Dependency] private readonly BloodstreamSystem _blood = default!;
- [Dependency] private readonly DoAfterSystem _doAfter = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly PopupSystem _popup = default!;
[Dependency] private readonly ReactiveSystem _reactiveSystem = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
diff --git a/Content.Server/Chemistry/EntitySystems/SolutionContainerSystem.cs b/Content.Server/Chemistry/EntitySystems/SolutionContainerSystem.cs
index 13ee95be14..8f9a20e239 100644
--- a/Content.Server/Chemistry/EntitySystems/SolutionContainerSystem.cs
+++ b/Content.Server/Chemistry/EntitySystems/SolutionContainerSystem.cs
@@ -317,11 +317,11 @@ public sealed partial class SolutionContainerSystem : EntitySystem
return true;
}
- public bool TryGetSolution(EntityUid uid, string name,
+ public bool TryGetSolution([NotNullWhen(true)] EntityUid? uid, string name,
[NotNullWhen(true)] out Solution? solution,
SolutionContainerManagerComponent? solutionsMgr = null)
{
- if (!Resolve(uid, ref solutionsMgr, false))
+ if (uid == null || !Resolve(uid.Value, ref solutionsMgr, false))
{
solution = null;
return false;
diff --git a/Content.Server/Climbing/ClimbSystem.cs b/Content.Server/Climbing/ClimbSystem.cs
index 3befaa3e87..82e41d66ce 100644
--- a/Content.Server/Climbing/ClimbSystem.cs
+++ b/Content.Server/Climbing/ClimbSystem.cs
@@ -1,6 +1,5 @@
using Content.Server.Body.Systems;
using Content.Server.Climbing.Components;
-using Content.Server.DoAfter;
using Content.Server.Interaction;
using Content.Server.Popups;
using Content.Server.Stunnable;
@@ -36,7 +35,7 @@ public sealed class ClimbSystem : SharedClimbSystem
[Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!;
[Dependency] private readonly BodySystem _bodySystem = default!;
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
- [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly FixtureSystem _fixtureSystem = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly InteractionSystem _interactionSystem = default!;
@@ -57,7 +56,7 @@ public sealed class ClimbSystem : SharedClimbSystem
SubscribeLocalEvent>(AddClimbableVerb);
SubscribeLocalEvent(OnClimbableDragDrop);
- SubscribeLocalEvent>(OnDoAfter);
+ SubscribeLocalEvent(OnDoAfter);
SubscribeLocalEvent(OnClimbEndCollide);
SubscribeLocalEvent(OnBuckleChange);
SubscribeLocalEvent(OnClimbingGetState);
@@ -114,22 +113,17 @@ public sealed class ClimbSystem : SharedClimbSystem
if (_bonkSystem.TryBonk(entityToMove, climbable))
return;
- var ev = new ClimbExtraEvent();
-
- var args = new DoAfterEventArgs(user, component.ClimbDelay, target: climbable, used: entityToMove)
+ var args = new DoAfterArgs(user, component.ClimbDelay, new ClimbDoAfterEvent(), entityToMove, target: climbable, used: entityToMove)
{
BreakOnTargetMove = true,
BreakOnUserMove = true,
- BreakOnDamage = true,
- BreakOnStun = true,
- RaiseOnUser = false,
- RaiseOnTarget = false,
+ BreakOnDamage = true
};
- _doAfterSystem.DoAfter(args, ev);
+ _doAfterSystem.TryStartDoAfter(args);
}
- private void OnDoAfter(EntityUid uid, ClimbingComponent component, DoAfterEvent args)
+ private void OnDoAfter(EntityUid uid, ClimbingComponent component, ClimbDoAfterEvent args)
{
if (args.Handled || args.Cancelled || args.Args.Target == null || args.Args.Used == null)
return;
@@ -436,10 +430,6 @@ public sealed class ClimbSystem : SharedClimbSystem
_fixtureRemoveQueue.Clear();
}
- private sealed class ClimbExtraEvent : EntityEventArgs
- {
- //Honestly this is only here because otherwise this activates on every single doafter on a human
- }
}
///
diff --git a/Content.Server/Construction/AnchorableSystem.cs b/Content.Server/Construction/AnchorableSystem.cs
index 3cb09d642f..4d22fa5fb1 100644
--- a/Content.Server/Construction/AnchorableSystem.cs
+++ b/Content.Server/Construction/AnchorableSystem.cs
@@ -5,6 +5,7 @@ using Content.Server.Pulling;
using Content.Shared.Construction.Components;
using Content.Shared.Construction.EntitySystems;
using Content.Shared.Database;
+using Content.Shared.DoAfter;
using Content.Shared.Examine;
using Content.Shared.Pulling.Components;
using Content.Shared.Tools;
@@ -40,23 +41,29 @@ namespace Content.Server.Construction
private void OnUnanchorComplete(EntityUid uid, AnchorableComponent component, TryUnanchorCompletedEvent args)
{
+ if (args.Cancelled || args.Used is not { } used)
+ return;
+
var xform = Transform(uid);
- RaiseLocalEvent(uid, new BeforeUnanchoredEvent(args.User, args.Using));
+ RaiseLocalEvent(uid, new BeforeUnanchoredEvent(args.User, used));
xform.Anchored = false;
- RaiseLocalEvent(uid, new UserUnanchoredEvent(args.User, args.Using));
+ RaiseLocalEvent(uid, new UserUnanchoredEvent(args.User, used));
_popup.PopupEntity(Loc.GetString("anchorable-unanchored"), uid);
_adminLogger.Add(
LogType.Unanchor,
LogImpact.Low,
- $"{EntityManager.ToPrettyString(args.User):user} unanchored {EntityManager.ToPrettyString(uid):anchored} using {EntityManager.ToPrettyString(args.Using):using}"
+ $"{EntityManager.ToPrettyString(args.User):user} unanchored {EntityManager.ToPrettyString(uid):anchored} using {EntityManager.ToPrettyString(used):using}"
);
}
private void OnAnchorComplete(EntityUid uid, AnchorableComponent component, TryAnchorCompletedEvent args)
{
+ if (args.Cancelled || args.Used is not { } used)
+ return;
+
var xform = Transform(uid);
if (TryComp(uid, out var anchorBody) &&
!TileFree(xform.Coordinates, anchorBody))
@@ -78,16 +85,16 @@ namespace Content.Server.Construction
if (component.Snap)
xform.Coordinates = xform.Coordinates.SnapToGrid(EntityManager, _mapManager);
- RaiseLocalEvent(uid, new BeforeAnchoredEvent(args.User, args.Using));
+ RaiseLocalEvent(uid, new BeforeAnchoredEvent(args.User, used));
xform.Anchored = true;
- RaiseLocalEvent(uid, new UserAnchoredEvent(args.User, args.Using));
+ RaiseLocalEvent(uid, new UserAnchoredEvent(args.User, used));
_popup.PopupEntity(Loc.GetString("anchorable-anchored"), uid);
_adminLogger.Add(
LogType.Anchor,
LogImpact.Low,
- $"{EntityManager.ToPrettyString(args.User):user} anchored {EntityManager.ToPrettyString(uid):anchored} using {EntityManager.ToPrettyString(args.Using):using}"
+ $"{EntityManager.ToPrettyString(args.User):user} anchored {EntityManager.ToPrettyString(uid):anchored} using {EntityManager.ToPrettyString(used):using}"
);
}
@@ -182,8 +189,7 @@ namespace Content.Server.Construction
return;
}
- var toolEvData = new ToolEventData(new TryAnchorCompletedEvent(userUid, usingUid), targetEntity:uid);
- _tool.UseTool(usingUid, userUid, uid, anchorable.Delay, usingTool.Qualities, toolEvData);
+ _tool.UseTool(usingUid, userUid, uid, anchorable.Delay, usingTool.Qualities, new TryAnchorCompletedEvent());
}
///
@@ -204,8 +210,7 @@ namespace Content.Server.Construction
if (!Valid(uid, userUid, usingUid, false))
return;
- var toolEvData = new ToolEventData(new TryUnanchorCompletedEvent(userUid, usingUid), targetEntity:uid);
- _tool.UseTool(usingUid, userUid, uid, anchorable.Delay, usingTool.Qualities, toolEvData);
+ _tool.UseTool(usingUid, userUid, uid, anchorable.Delay, usingTool.Qualities, new TryUnanchorCompletedEvent());
}
///
@@ -236,32 +241,5 @@ namespace Content.Server.Construction
_adminLogger.Add(LogType.Anchor, LogImpact.Low, $"{ToPrettyString(userUid):user} is trying to anchor {ToPrettyString(uid):entity} to {transform.Coordinates:targetlocation}");
}
}
-
- private abstract class AnchorEvent : EntityEventArgs
- {
- public EntityUid User;
- public EntityUid Using;
-
- protected AnchorEvent(EntityUid userUid, EntityUid usingUid)
- {
- User = userUid;
- Using = usingUid;
- }
- }
-
- private sealed class TryUnanchorCompletedEvent : AnchorEvent
- {
- public TryUnanchorCompletedEvent(EntityUid userUid, EntityUid usingUid) : base(userUid, usingUid)
- {
- }
- }
-
-
- private sealed class TryAnchorCompletedEvent : AnchorEvent
- {
- public TryAnchorCompletedEvent(EntityUid userUid, EntityUid usingUid) : base(userUid, usingUid)
- {
- }
- }
}
}
diff --git a/Content.Server/Construction/Components/ConstructionComponent.cs b/Content.Server/Construction/Components/ConstructionComponent.cs
index 6274128423..08ffb99fe8 100644
--- a/Content.Server/Construction/Components/ConstructionComponent.cs
+++ b/Content.Server/Construction/Components/ConstructionComponent.cs
@@ -1,4 +1,5 @@
using Content.Shared.Construction.Prototypes;
+using Content.Shared.DoAfter;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Server.Construction.Components
@@ -33,10 +34,12 @@ namespace Content.Server.Construction.Components
[DataField("deconstructionTarget")]
public string? DeconstructionNode { get; set; } = "start";
- [ViewVariables]
- public bool WaitingDoAfter { get; set; } = false;
+ [DataField("doAfter")]
+ public DoAfterId? DoAfter;
[ViewVariables]
+ // TODO Force flush interaction queue before serializing to YAML.
+ // Otherwise you can end up with entities stuck in invalid states (e.g., waiting for DoAfters).
public readonly Queue
None,
- ///
- /// If Validation, we want to validate whether the specified event would handle the step or not.
- /// Will NOT modify the construction state at all.
- ///
- Validation,
-
///
/// If Completed, this is the second (and last) time we're seeing this event, and
/// the doAfter that was called the first time successfully completed. Handle completion logic now.
///
- Completed,
-
- ///
- /// If Cancelled, this is the second (and last) time we're seeing this event, and
- /// the doAfter that was called the first time was cancelled. Handle cleanup logic now.
- ///
- Cancelled
+ Completed
}
///
diff --git a/Content.Server/Construction/ConstructionSystem.cs b/Content.Server/Construction/ConstructionSystem.cs
index 45b8f232df..237540f9fe 100644
--- a/Content.Server/Construction/ConstructionSystem.cs
+++ b/Content.Server/Construction/ConstructionSystem.cs
@@ -1,7 +1,7 @@
using Content.Server.Construction.Components;
-using Content.Server.DoAfter;
using Content.Server.Stack;
using Content.Shared.Construction;
+using Content.Shared.DoAfter;
using Content.Shared.Tools;
using JetBrains.Annotations;
using Robust.Server.Containers;
@@ -19,7 +19,7 @@ namespace Content.Server.Construction
[Dependency] private readonly ILogManager _logManager = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IRobustRandom _robustRandom = default!;
- [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly ContainerSystem _container = default!;
[Dependency] private readonly StackSystem _stackSystem = default!;
[Dependency] private readonly SharedToolSystem _toolSystem = default!;
diff --git a/Content.Server/Construction/PartExchangerSystem.cs b/Content.Server/Construction/PartExchangerSystem.cs
index c865f47926..2ea4cd10f3 100644
--- a/Content.Server/Construction/PartExchangerSystem.cs
+++ b/Content.Server/Construction/PartExchangerSystem.cs
@@ -1,10 +1,10 @@
using System.Linq;
using Content.Server.Construction.Components;
-using Content.Server.DoAfter;
using Content.Server.Storage.Components;
using Content.Server.Storage.EntitySystems;
using Content.Shared.DoAfter;
using Content.Shared.Construction.Components;
+using Content.Shared.Exchanger;
using Content.Shared.Interaction;
using Content.Shared.Popups;
using Robust.Shared.Containers;
@@ -16,7 +16,7 @@ namespace Content.Server.Construction;
public sealed class PartExchangerSystem : EntitySystem
{
[Dependency] private readonly ConstructionSystem _construction = default!;
- [Dependency] private readonly DoAfterSystem _doAfter = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly SharedContainerSystem _container = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
@@ -26,18 +26,14 @@ public sealed class PartExchangerSystem : EntitySystem
public override void Initialize()
{
SubscribeLocalEvent(OnAfterInteract);
- SubscribeLocalEvent(OnDoAfter);
+ SubscribeLocalEvent(OnDoAfter);
}
private void OnDoAfter(EntityUid uid, PartExchangerComponent component, DoAfterEvent args)
{
- if (args.Cancelled || args.Handled || args.Args.Target == null)
- {
- component.AudioStream?.Stop();
- return;
- }
-
component.AudioStream?.Stop();
+ if (args.Cancelled || args.Handled || args.Args.Target == null)
+ return;
if (!TryComp(args.Args.Target.Value, out var machine))
return;
@@ -112,11 +108,11 @@ public sealed class PartExchangerSystem : EntitySystem
component.AudioStream = _audio.PlayPvs(component.ExchangeSound, uid);
- _doAfter.DoAfter(new DoAfterEventArgs(args.User, component.ExchangeDuration, target:args.Target, used:args.Used)
+ _doAfter.TryStartDoAfter(new DoAfterArgs(args.User, component.ExchangeDuration, new ExchangerDoAfterEvent(), uid, target: args.Target, used: uid)
{
BreakOnDamage = true,
- BreakOnStun = true,
BreakOnUserMove = true
});
}
+
}
diff --git a/Content.Server/Construction/RefiningSystem.cs b/Content.Server/Construction/RefiningSystem.cs
index 73b4f8d760..cd4eb533e3 100644
--- a/Content.Server/Construction/RefiningSystem.cs
+++ b/Content.Server/Construction/RefiningSystem.cs
@@ -1,9 +1,11 @@
using Content.Server.Construction.Components;
using Content.Server.Stack;
+using Content.Shared.Construction;
+using Content.Shared.DoAfter;
using Content.Shared.Interaction;
using Content.Shared.Stacks;
using Content.Shared.Tools;
-using Content.Shared.Tools.Components;
+using Robust.Shared.Serialization;
namespace Content.Server.Construction
{
@@ -15,29 +17,22 @@ namespace Content.Server.Construction
{
base.Initialize();
SubscribeLocalEvent(OnInteractUsing);
+ SubscribeLocalEvent(OnDoAfter);
}
- private async void OnInteractUsing(EntityUid uid, WelderRefinableComponent component, InteractUsingEvent args)
+ private void OnInteractUsing(EntityUid uid, WelderRefinableComponent component, InteractUsingEvent args)
{
- // check if object is welder
- if (!HasComp(args.Used))
+ if (args.Handled)
return;
- // check if someone is already welding object
- if (component.BeingWelded)
+ args.Handled = _toolSystem.UseTool(args.Used, args.User, uid, component.RefineTime, component.QualityNeeded, new WelderRefineDoAfterEvent(), component.RefineFuel);
+ }
+
+ private void OnDoAfter(EntityUid uid, WelderRefinableComponent component, WelderRefineDoAfterEvent args)
+ {
+ if (args.Cancelled)
return;
- component.BeingWelded = true;
-
- var toolEvData = new ToolEventData(null);
-
- if (!_toolSystem.UseTool(args.Used, args.User, uid, component.RefineTime, component.QualityNeeded, toolEvData, component.RefineFuel))
- {
- // failed to veld - abort refine
- component.BeingWelded = false;
- return;
- }
-
// get last owner coordinates and delete it
var resultPosition = Transform(uid).Coordinates;
EntityManager.DeleteEntity(uid);
@@ -50,7 +45,7 @@ namespace Content.Server.Construction
// TODO: If something has a stack... Just use a prototype with a single thing in the stack.
// This is not a good way to do it.
if (TryComp(droppedEnt, out var stack))
- _stackSystem.SetCount(droppedEnt,1, stack);
+ _stackSystem.SetCount(droppedEnt, 1, stack);
}
}
}
diff --git a/Content.Server/Cuffs/CuffableSystem.cs b/Content.Server/Cuffs/CuffableSystem.cs
index 3891941cad..2b65803673 100644
--- a/Content.Server/Cuffs/CuffableSystem.cs
+++ b/Content.Server/Cuffs/CuffableSystem.cs
@@ -18,7 +18,7 @@ namespace Content.Server.Cuffs
private void OnHandcuffGetState(EntityUid uid, HandcuffComponent component, ref ComponentGetState args)
{
- args.State = new HandcuffComponentState(component.OverlayIconState, component.Cuffing);
+ args.State = new HandcuffComponentState(component.OverlayIconState);
}
private void OnCuffableGetState(EntityUid uid, CuffableComponent component, ref ComponentGetState args)
@@ -33,7 +33,6 @@ namespace Content.Server.Cuffs
TryComp(component.LastAddedCuffs, out cuffs);
args.State = new CuffableComponentState(component.CuffedHandCount,
component.CanStillInteract,
- component.Uncuffing,
cuffs?.CuffedRSI,
$"{cuffs?.OverlayIconState}-{component.CuffedHandCount}",
cuffs?.Color);
diff --git a/Content.Server/Disease/DiseaseDiagnosisSystem.cs b/Content.Server/Disease/DiseaseDiagnosisSystem.cs
index 98b4d6c230..37136435a4 100644
--- a/Content.Server/Disease/DiseaseDiagnosisSystem.cs
+++ b/Content.Server/Disease/DiseaseDiagnosisSystem.cs
@@ -3,7 +3,6 @@ using Content.Shared.Disease;
using Content.Shared.Interaction;
using Content.Shared.Inventory;
using Content.Shared.Examine;
-using Content.Server.DoAfter;
using Content.Server.Popups;
using Content.Server.Hands.Components;
using Content.Server.Nutrition.EntitySystems;
@@ -18,7 +17,7 @@ using Content.Shared.Tools.Components;
using Content.Server.Station.Systems;
using Content.Shared.DoAfter;
using Content.Shared.IdentityManagement;
-using Robust.Server.GameObjects;
+using Content.Shared.Swab;
namespace Content.Server.Disease
{
@@ -27,7 +26,7 @@ namespace Content.Server.Disease
///
public sealed class DiseaseDiagnosisSystem : EntitySystem
{
- [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly InventorySystem _inventorySystem = default!;
@@ -47,7 +46,7 @@ namespace Content.Server.Disease
// Private Events
SubscribeLocalEvent(OnDiagnoserFinished);
SubscribeLocalEvent(OnVaccinatorFinished);
- SubscribeLocalEvent(OnSwabDoAfter);
+ SubscribeLocalEvent(OnSwabDoAfter);
}
private Queue AddQueue = new();
@@ -116,15 +115,10 @@ namespace Content.Server.Disease
return;
}
- var isTarget = args.User != args.Target;
-
- _doAfterSystem.DoAfter(new DoAfterEventArgs(args.User, swab.SwabDelay, target: args.Target, used: uid)
+ _doAfterSystem.TryStartDoAfter(new DoAfterArgs(args.User, swab.SwabDelay, new DiseaseSwabDoAfterEvent(), uid, target: args.Target, used: uid)
{
- RaiseOnTarget = isTarget,
- RaiseOnUser = !isTarget,
BreakOnTargetMove = true,
BreakOnUserMove = true,
- BreakOnStun = true,
NeedHand = true
});
}
diff --git a/Content.Server/Disease/DiseaseSystem.cs b/Content.Server/Disease/DiseaseSystem.cs
index db6f0dc6a5..93a1cab5a3 100644
--- a/Content.Server/Disease/DiseaseSystem.cs
+++ b/Content.Server/Disease/DiseaseSystem.cs
@@ -1,7 +1,6 @@
using Content.Server.Body.Systems;
using Content.Server.Chat.Systems;
using Content.Server.Disease.Components;
-using Content.Server.DoAfter;
using Content.Server.Nutrition.EntitySystems;
using Content.Server.Popups;
using Content.Shared.Clothing.Components;
@@ -37,7 +36,7 @@ namespace Content.Server.Disease
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly ISerializationManager _serializationManager = default!;
[Dependency] private readonly IRobustRandom _random = default!;
- [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly EntityLookupSystem _lookup = default!;
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
@@ -58,7 +57,7 @@ namespace Content.Server.Disease
// Handling stuff from other systems
SubscribeLocalEvent(OnApplyMetabolicMultiplier);
// Private events stuff
- SubscribeLocalEvent(OnDoAfter);
+ SubscribeLocalEvent(OnDoAfter);
}
private Queue AddQueue = new();
@@ -276,20 +275,21 @@ namespace Content.Server.Disease
///
private void OnAfterInteract(EntityUid uid, DiseaseVaccineComponent vaxx, AfterInteractEvent args)
{
- if (args.Target == null || !args.CanReach)
+ if (args.Target == null || !args.CanReach || args.Handled)
return;
+ args.Handled = true;
+
if (vaxx.Used)
{
_popupSystem.PopupEntity(Loc.GetString("vaxx-already-used"), args.User, args.User);
return;
}
- _doAfterSystem.DoAfter(new DoAfterEventArgs(args.User, vaxx.InjectDelay, target: args.Target, used:uid)
+ _doAfterSystem.TryStartDoAfter(new DoAfterArgs(args.User, vaxx.InjectDelay, new VaccineDoAfterEvent(), uid, target: args.Target, used: uid)
{
BreakOnTargetMove = true,
BreakOnUserMove = true,
- BreakOnStun = true,
NeedHand = true
});
}
diff --git a/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs b/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs
index 5a3c2ed642..e64f40a488 100644
--- a/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs
+++ b/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs
@@ -4,7 +4,6 @@ using Content.Server.Administration.Logs;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Disposal.Tube.Components;
using Content.Server.Disposal.Unit.Components;
-using Content.Server.DoAfter;
using Content.Server.Hands.Components;
using Content.Server.Popups;
using Content.Server.Power.Components;
@@ -42,7 +41,7 @@ namespace Content.Server.Disposal.Unit.EntitySystems
[Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!;
[Dependency] private readonly AppearanceSystem _appearance = default!;
[Dependency] private readonly AtmosphereSystem _atmosSystem = default!;
- [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly EntityLookupSystem _lookup = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
@@ -79,7 +78,7 @@ namespace Content.Server.Disposal.Unit.EntitySystems
SubscribeLocalEvent>(AddClimbInsideVerb);
// Units
- SubscribeLocalEvent(OnDoAfter);
+ SubscribeLocalEvent(OnDoAfter);
//UI
SubscribeLocalEvent(OnUiButtonPressed);
@@ -489,19 +488,15 @@ namespace Content.Server.Disposal.Unit.EntitySystems
// Can't check if our target AND disposals moves currently so we'll just check target.
// if you really want to check if disposals moves then add a predicate.
- var doAfterArgs = new DoAfterEventArgs(userId.Value, delay, target:toInsertId, used:unitId)
+ var doAfterArgs = new DoAfterArgs(userId.Value, delay, new DisposalDoAfterEvent(), unitId, target: toInsertId, used: unitId)
{
BreakOnDamage = true,
- BreakOnStun = true,
BreakOnTargetMove = true,
BreakOnUserMove = true,
- NeedHand = false,
- RaiseOnTarget = false,
- RaiseOnUser = false,
- RaiseOnUsed = true,
+ NeedHand = false
};
- _doAfterSystem.DoAfter(doAfterArgs);
+ _doAfterSystem.TryStartDoAfter(doAfterArgs);
return true;
}
diff --git a/Content.Server/DoAfter/DoAfterSystem.cs b/Content.Server/DoAfter/DoAfterSystem.cs
index ad0d8d27d8..b3d2711f7b 100644
--- a/Content.Server/DoAfter/DoAfterSystem.cs
+++ b/Content.Server/DoAfter/DoAfterSystem.cs
@@ -1,5 +1,4 @@
using Content.Shared.DoAfter;
-using Content.Shared.Mobs;
using JetBrains.Annotations;
namespace Content.Server.DoAfter;
diff --git a/Content.Server/Doors/Systems/DoorSystem.cs b/Content.Server/Doors/Systems/DoorSystem.cs
index bb01665b8d..d6ecd5d65b 100644
--- a/Content.Server/Doors/Systems/DoorSystem.cs
+++ b/Content.Server/Doors/Systems/DoorSystem.cs
@@ -20,6 +20,7 @@ using Content.Server.Power.EntitySystems;
using Content.Shared.Tools;
using Robust.Shared.Physics.Components;
using Robust.Shared.Physics.Events;
+using Content.Shared.DoAfter;
namespace Content.Server.Doors.Systems;
@@ -41,8 +42,7 @@ public sealed class DoorSystem : SharedDoorSystem
// Mob prying doors
SubscribeLocalEvent>(OnDoorAltVerb);
- SubscribeLocalEvent(OnPryFinished);
- SubscribeLocalEvent(OnPryCancelled);
+ SubscribeLocalEvent(OnPryFinished);
SubscribeLocalEvent(OnWeldAttempt);
SubscribeLocalEvent(OnWeldChanged);
SubscribeLocalEvent(OnEmagged);
@@ -174,9 +174,6 @@ public sealed class DoorSystem : SharedDoorSystem
///
public bool TryPryDoor(EntityUid target, EntityUid tool, EntityUid user, DoorComponent door, bool force = false)
{
- if (door.BeingPried)
- return false;
-
if (door.State == DoorState.Welded)
return false;
@@ -194,20 +191,14 @@ public sealed class DoorSystem : SharedDoorSystem
var modEv = new DoorGetPryTimeModifierEvent(user);
RaiseLocalEvent(target, modEv, false);
- door.BeingPried = true;
- var toolEvData = new ToolEventData(new PryFinishedEvent(), cancelledEv: new PryCancelledEvent(),targetEntity: target);
- _toolSystem.UseTool(tool, user, target, modEv.PryTimeModifier * door.PryTime, new[] { door.PryingQuality }, toolEvData);
+ _toolSystem.UseTool(tool, user, target, modEv.PryTimeModifier * door.PryTime, door.PryingQuality, new DoorPryDoAfterEvent());
return true; // we might not actually succeeded, but a do-after has started
}
- private void OnPryCancelled(EntityUid uid, DoorComponent door, PryCancelledEvent args)
+ private void OnPryFinished(EntityUid uid, DoorComponent door, DoAfterEvent args)
{
- door.BeingPried = false;
- }
-
- private void OnPryFinished(EntityUid uid, DoorComponent door, PryFinishedEvent args)
- {
- door.BeingPried = false;
+ if (args.Cancelled)
+ return;
if (door.State == DoorState.Closed)
StartOpening(uid, door);
@@ -309,6 +300,3 @@ public sealed class DoorSystem : SharedDoorSystem
}
}
-public sealed class PryFinishedEvent : EntityEventArgs { }
-public sealed class PryCancelledEvent : EntityEventArgs { }
-
diff --git a/Content.Server/Dragon/DragonSystem.cs b/Content.Server/Dragon/DragonSystem.cs
index f4d3809b85..d969272ab9 100644
--- a/Content.Server/Dragon/DragonSystem.cs
+++ b/Content.Server/Dragon/DragonSystem.cs
@@ -1,11 +1,9 @@
using Content.Server.Body.Systems;
-using Content.Server.DoAfter;
using Content.Server.Popups;
using Content.Shared.Actions;
using Content.Shared.Chemistry.Components;
using Robust.Shared.Containers;
using Robust.Shared.Player;
-using System.Threading;
using Content.Server.Chat.Systems;
using Content.Server.GameTicking;
using Content.Server.GameTicking.Rules;
@@ -33,7 +31,7 @@ namespace Content.Server.Dragon
[Dependency] private readonly ITileDefinitionManager _tileDef = default!;
[Dependency] private readonly ChatSystem _chat = default!;
[Dependency] private readonly SharedActionsSystem _actionsSystem = default!;
- [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!;
[Dependency] private readonly MovementSpeedModifierSystem _movement = default!;
@@ -63,7 +61,7 @@ namespace Content.Server.Dragon
SubscribeLocalEvent(OnDragonRift);
SubscribeLocalEvent(OnDragonMove);
- SubscribeLocalEvent(OnDoAfter);
+ SubscribeLocalEvent(OnDoAfter);
SubscribeLocalEvent(OnMobStateChanged);
@@ -75,7 +73,7 @@ namespace Content.Server.Dragon
SubscribeLocalEvent(OnRiftRoundEnd);
}
- private void OnDoAfter(EntityUid uid, DragonComponent component, DoAfterEvent args)
+ private void OnDoAfter(EntityUid uid, DragonComponent component, DragonDevourDoAfterEvent args)
{
if (args.Handled || args.Cancelled)
return;
@@ -95,8 +93,7 @@ namespace Content.Server.Dragon
else if (args.Args.Target != null)
EntityManager.QueueDeleteEntity(args.Args.Target.Value);
- if (component.SoundDevour != null)
- _audioSystem.PlayPvs(component.SoundDevour, uid, component.SoundDevour.Params);
+ _audioSystem.PlayPvs(component.SoundDevour, uid);
}
public override void Update(float frameTime)
@@ -355,11 +352,10 @@ namespace Content.Server.Dragon
case MobState.Critical:
case MobState.Dead:
- _doAfterSystem.DoAfter(new DoAfterEventArgs(uid, component.DevourTime, target:target)
+ _doAfterSystem.TryStartDoAfter(new DoAfterArgs(uid, component.DevourTime, new DragonDevourDoAfterEvent(), uid, target: target, used: uid)
{
BreakOnTargetMove = true,
BreakOnUserMove = true,
- BreakOnStun = true,
});
break;
default:
@@ -375,11 +371,10 @@ namespace Content.Server.Dragon
if (component.SoundStructureDevour != null)
_audioSystem.PlayPvs(component.SoundStructureDevour, uid, component.SoundStructureDevour.Params);
- _doAfterSystem.DoAfter(new DoAfterEventArgs(uid, component.StructureDevourTime, target:target)
+ _doAfterSystem.TryStartDoAfter(new DoAfterArgs(uid, component.StructureDevourTime, new DragonDevourDoAfterEvent(), uid, target: target, used: uid)
{
BreakOnTargetMove = true,
BreakOnUserMove = true,
- BreakOnStun = true,
});
}
}
diff --git a/Content.Server/Engineering/Components/DisassembleOnAltVerbComponent.cs b/Content.Server/Engineering/Components/DisassembleOnAltVerbComponent.cs
index 802c86518e..7bd620963c 100644
--- a/Content.Server/Engineering/Components/DisassembleOnAltVerbComponent.cs
+++ b/Content.Server/Engineering/Components/DisassembleOnAltVerbComponent.cs
@@ -12,7 +12,5 @@ namespace Content.Server.Engineering.Components
[DataField("doAfter")]
public float DoAfterTime = 0;
-
- public CancellationTokenSource TokenSource { get; } = new();
}
}
diff --git a/Content.Server/Engineering/EntitySystems/DisassembleOnAltVerbSystem.cs b/Content.Server/Engineering/EntitySystems/DisassembleOnAltVerbSystem.cs
index 79d25f3520..91bf49b7ec 100644
--- a/Content.Server/Engineering/EntitySystems/DisassembleOnAltVerbSystem.cs
+++ b/Content.Server/Engineering/EntitySystems/DisassembleOnAltVerbSystem.cs
@@ -1,4 +1,3 @@
-using Content.Server.DoAfter;
using Content.Server.Engineering.Components;
using Content.Shared.DoAfter;
using Content.Shared.Hands.EntitySystems;
@@ -41,18 +40,16 @@ namespace Content.Server.Engineering.EntitySystems
if (string.IsNullOrEmpty(component.Prototype))
return;
- if (component.DoAfterTime > 0 && TryGet(out var doAfterSystem))
+ if (component.DoAfterTime > 0 && TryGet(out var doAfterSystem))
{
- var doAfterArgs = new DoAfterEventArgs(user, component.DoAfterTime, component.TokenSource.Token)
+ var doAfterArgs = new DoAfterArgs(user, component.DoAfterTime, new AwaitedDoAfterEvent(), null)
{
BreakOnUserMove = true,
- BreakOnStun = true,
};
var result = await doAfterSystem.WaitDoAfter(doAfterArgs);
if (result != DoAfterStatus.Finished)
return;
- component.TokenSource.Cancel();
}
if (component.Deleted || Deleted(component.Owner))
diff --git a/Content.Server/Engineering/EntitySystems/SpawnAfterInteractSystem.cs b/Content.Server/Engineering/EntitySystems/SpawnAfterInteractSystem.cs
index 988b72ae88..89a74b2558 100644
--- a/Content.Server/Engineering/EntitySystems/SpawnAfterInteractSystem.cs
+++ b/Content.Server/Engineering/EntitySystems/SpawnAfterInteractSystem.cs
@@ -1,5 +1,4 @@
using Content.Server.Coordinates.Helpers;
-using Content.Server.DoAfter;
using Content.Server.Engineering.Components;
using Content.Server.Stack;
using Content.Shared.DoAfter;
@@ -15,7 +14,7 @@ namespace Content.Server.Engineering.EntitySystems
public sealed class SpawnAfterInteractSystem : EntitySystem
{
[Dependency] private readonly IMapManager _mapManager = default!;
- [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly StackSystem _stackSystem = default!;
public override void Initialize()
@@ -46,11 +45,9 @@ namespace Content.Server.Engineering.EntitySystems
if (component.DoAfterTime > 0)
{
- var doAfterArgs = new DoAfterEventArgs(args.User, component.DoAfterTime)
+ var doAfterArgs = new DoAfterArgs(args.User, component.DoAfterTime, new AwaitedDoAfterEvent(), null)
{
BreakOnUserMove = true,
- BreakOnStun = true,
- PostCheck = IsTileClear,
};
var result = await _doAfterSystem.WaitDoAfter(doAfterArgs);
@@ -58,7 +55,7 @@ namespace Content.Server.Engineering.EntitySystems
return;
}
- if (component.Deleted || Deleted(component.Owner))
+ if (component.Deleted || !IsTileClear())
return;
if (EntityManager.TryGetComponent(component.Owner, out var stackComp)
diff --git a/Content.Server/Ensnaring/EnsnareableSystem.Ensnaring.cs b/Content.Server/Ensnaring/EnsnareableSystem.Ensnaring.cs
index dbb45f1f9b..f65871ef99 100644
--- a/Content.Server/Ensnaring/EnsnareableSystem.Ensnaring.cs
+++ b/Content.Server/Ensnaring/EnsnareableSystem.Ensnaring.cs
@@ -1,7 +1,6 @@
-using System.Threading;
-using Content.Server.DoAfter;
using Content.Shared.Alert;
using Content.Shared.DoAfter;
+using Content.Shared.Ensnaring;
using Content.Shared.Ensnaring.Components;
using Content.Shared.IdentityManagement;
using Content.Shared.StepTrigger.Systems;
@@ -11,7 +10,7 @@ namespace Content.Server.Ensnaring;
public sealed partial class EnsnareableSystem
{
- [Dependency] private readonly DoAfterSystem _doAfter = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly AlertsSystem _alerts = default!;
public void InitializeEnsnaring()
@@ -74,40 +73,35 @@ public sealed partial class EnsnareableSystem
///
/// Used where you want to try to free an entity with the
///
- /// The entity that will be free
+ /// The entity that will be freed
+ /// The entity that is freeing the target
/// The entity used to ensnare
/// The ensnaring component
- public void TryFree(EntityUid target, EntityUid ensnare, EnsnaringComponent component, EntityUid? user = null)
+ public void TryFree(EntityUid target, EntityUid user, EntityUid ensnare, EnsnaringComponent component)
{
//Don't do anything if they don't have the ensnareable component.
if (!HasComp(target))
return;
- var isOwner = !(user != null && target != user);
- var freeTime = isOwner ? component.BreakoutTime : component.FreeTime;
- bool breakOnMove;
+ var freeTime = user == target ? component.BreakoutTime : component.FreeTime;
+ var breakOnMove = user != target || !component.CanMoveBreakout;
- if (isOwner)
- breakOnMove = !component.CanMoveBreakout;
- else
- breakOnMove = true;
-
- var doAfterEventArgs = new DoAfterEventArgs(target, freeTime, target: target, used:ensnare)
+ var doAfterEventArgs = new DoAfterArgs(user, freeTime, new EnsnareableDoAfterEvent(), target, target: target, used: ensnare)
{
BreakOnUserMove = breakOnMove,
BreakOnTargetMove = breakOnMove,
BreakOnDamage = false,
- BreakOnStun = true,
- NeedHand = true
+ NeedHand = true,
+ BlockDuplicate = true,
};
- _doAfter.DoAfter(doAfterEventArgs);
+ if (!_doAfter.TryStartDoAfter(doAfterEventArgs))
+ return;
- if (isOwner)
+ if (user == target)
_popup.PopupEntity(Loc.GetString("ensnare-component-try-free", ("ensnare", ensnare)), target, target);
-
- if (!isOwner && user != null)
- _popup.PopupEntity(Loc.GetString("ensnare-component-try-free-other", ("ensnare", ensnare), ("user", Identity.Entity(target, EntityManager))), user.Value, user.Value);
+ else
+ _popup.PopupEntity(Loc.GetString("ensnare-component-try-free-other", ("ensnare", ensnare), ("user", Identity.Entity(target, EntityManager))), user, user);
}
///
diff --git a/Content.Server/Ensnaring/EnsnareableSystem.cs b/Content.Server/Ensnaring/EnsnareableSystem.cs
index d883cdb418..48e34537f8 100644
--- a/Content.Server/Ensnaring/EnsnareableSystem.cs
+++ b/Content.Server/Ensnaring/EnsnareableSystem.cs
@@ -20,7 +20,7 @@ public sealed partial class EnsnareableSystem : SharedEnsnareableSystem
InitializeEnsnaring();
SubscribeLocalEvent(OnEnsnareableInit);
- SubscribeLocalEvent(OnDoAfter);
+ SubscribeLocalEvent(OnDoAfter);
}
private void OnEnsnareableInit(EntityUid uid, EnsnareableComponent component, ComponentInit args)
diff --git a/Content.Server/Fluids/EntitySystems/MoppingSystem.cs b/Content.Server/Fluids/EntitySystems/MoppingSystem.cs
index 4f7304ee6c..9aab13ba6e 100644
--- a/Content.Server/Fluids/EntitySystems/MoppingSystem.cs
+++ b/Content.Server/Fluids/EntitySystems/MoppingSystem.cs
@@ -1,7 +1,5 @@
-using System.Linq;
using Content.Server.Chemistry.Components.SolutionManager;
using Content.Server.Chemistry.EntitySystems;
-using Content.Server.DoAfter;
using Content.Server.Fluids.Components;
using Content.Server.Popups;
using Content.Shared.Chemistry.Components;
@@ -20,7 +18,7 @@ namespace Content.Server.Fluids.EntitySystems;
[UsedImplicitly]
public sealed class MoppingSystem : SharedMoppingSystem
{
- [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly SpillableSystem _spillableSystem = default!;
[Dependency] private readonly TagSystem _tagSystem = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
@@ -35,8 +33,8 @@ public sealed class MoppingSystem : SharedMoppingSystem
base.Initialize();
SubscribeLocalEvent(OnAbsorbentInit);
SubscribeLocalEvent(OnAfterInteract);
+ SubscribeLocalEvent(OnDoAfter);
SubscribeLocalEvent(OnAbsorbentSolutionChange);
- SubscribeLocalEvent>(OnDoAfter);
}
private void OnAbsorbentInit(EntityUid uid, AbsorbentComponent component, ComponentInit args)
@@ -256,48 +254,34 @@ public sealed class MoppingSystem : SharedMoppingSystem
if (!component.InteractingEntities.Add(target))
return;
- var aborbantData = new AbsorbantData(targetSolution, msg, sfx, transferAmount);
+ var ev = new AbsorbantDoAfterEvent(targetSolution, msg, sfx, transferAmount);
- var doAfterArgs = new DoAfterEventArgs(user, delay, target: target, used:used)
+ var doAfterArgs = new DoAfterArgs(user, delay, ev, used, target: target, used: used)
{
BreakOnUserMove = true,
- BreakOnStun = true,
BreakOnDamage = true,
MovementThreshold = 0.2f
};
- _doAfterSystem.DoAfter(doAfterArgs, aborbantData);
+ _doAfterSystem.TryStartDoAfter(doAfterArgs);
}
- private void OnDoAfter(EntityUid uid, AbsorbentComponent component, DoAfterEvent args)
+ private void OnDoAfter(EntityUid uid, AbsorbentComponent component, AbsorbantDoAfterEvent args)
{
- if (args.Args.Target == null)
+ if (args.Target == null)
return;
- if (args.Cancelled)
- {
- //Remove the interacting entities or else it breaks the mop
- component.InteractingEntities.Remove(args.Args.Target.Value);
- return;
- }
+ component.InteractingEntities.Remove(args.Target.Value);
- if (args.Handled)
+ if (args.Cancelled || args.Handled)
return;
- _audio.PlayPvs(args.AdditionalData.Sound, uid);
- _popups.PopupEntity(Loc.GetString(args.AdditionalData.Message, ("target", args.Args.Target.Value), ("used", uid)), uid);
- _solutionSystem.TryTransferSolution(args.Args.Target.Value, uid, args.AdditionalData.TargetSolution,
- AbsorbentComponent.SolutionName, args.AdditionalData.TransferAmount);
- component.InteractingEntities.Remove(args.Args.Target.Value);
+ _audio.PlayPvs(args.Sound, uid);
+ _popups.PopupEntity(Loc.GetString(args.Message, ("target", args.Target.Value), ("used", uid)), uid);
+ _solutionSystem.TryTransferSolution(args.Target.Value, uid, args.TargetSolution,
+ AbsorbentComponent.SolutionName, args.TransferAmount);
+ component.InteractingEntities.Remove(args.Target.Value);
args.Handled = true;
}
-
- private record struct AbsorbantData(string TargetSolution, string Message, SoundSpecifier Sound, FixedPoint2 TransferAmount)
- {
- public readonly string TargetSolution = TargetSolution;
- public readonly string Message = Message;
- public readonly SoundSpecifier Sound = Sound;
- public readonly FixedPoint2 TransferAmount = TransferAmount;
- }
}
diff --git a/Content.Server/Fluids/EntitySystems/SpillableSystem.cs b/Content.Server/Fluids/EntitySystems/SpillableSystem.cs
index 32e6dcbaa4..f98656e291 100644
--- a/Content.Server/Fluids/EntitySystems/SpillableSystem.cs
+++ b/Content.Server/Fluids/EntitySystems/SpillableSystem.cs
@@ -1,6 +1,5 @@
using Content.Server.Administration.Logs;
using Content.Server.Chemistry.EntitySystems;
-using Content.Server.DoAfter;
using Content.Server.Fluids.Components;
using Content.Server.Nutrition.Components;
using Content.Shared.Chemistry.Components;
@@ -17,6 +16,7 @@ using Robust.Shared.Prototypes;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Content.Shared.DoAfter;
+using Content.Shared.Spillable;
namespace Content.Server.Fluids.EntitySystems;
@@ -29,7 +29,7 @@ public sealed class SpillableSystem : EntitySystem
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly EntityLookupSystem _entityLookup = default!;
[Dependency] private readonly IAdminLogManager _adminLogger= default!;
- [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
public override void Initialize()
{
@@ -38,7 +38,7 @@ public sealed class SpillableSystem : EntitySystem
SubscribeLocalEvent>(AddSpillVerb);
SubscribeLocalEvent(OnGotEquipped);
SubscribeLocalEvent(OnSpikeOverflow);
- SubscribeLocalEvent(OnDoAfter);
+ SubscribeLocalEvent(OnDoAfter);
}
private void OnSpikeOverflow(EntityUid uid, SpillableComponent component, SolutionSpikeOverflowEvent args)
@@ -128,29 +128,17 @@ public sealed class SpillableSystem : EntitySystem
Verb verb = new();
verb.Text = Loc.GetString("spill-target-verb-get-data-text");
// TODO VERB ICONS spill icon? pouring out a glass/beaker?
- if (component.SpillDelay == null)
+
+ verb.Act = () =>
{
- verb.Act = () =>
+ _doAfterSystem.TryStartDoAfter(new DoAfterArgs(args.User, component.SpillDelay ?? 0, new SpillDoAfterEvent(), uid, target: uid)
{
- var puddleSolution = _solutionContainerSystem.SplitSolution(args.Target,
- solution, solution.Volume);
- SpillAt(puddleSolution, Transform(args.Target).Coordinates, "PuddleSmear");
- };
- }
- else
- {
- verb.Act = () =>
- {
- _doAfterSystem.DoAfter(new DoAfterEventArgs(args.User, component.SpillDelay.Value, target:uid)
- {
- BreakOnTargetMove = true,
- BreakOnUserMove = true,
- BreakOnDamage = true,
- BreakOnStun = true,
- NeedHand = true
- });
- };
- }
+ BreakOnTargetMove = true,
+ BreakOnUserMove = true,
+ BreakOnDamage = true,
+ NeedHand = true,
+ });
+ };
verb.Impact = LogImpact.Medium; // dangerous reagent reaction are logged separately.
verb.DoContactInteraction = true;
args.Verbs.Add(verb);
diff --git a/Content.Server/Forensics/Systems/ForensicPadSystem.cs b/Content.Server/Forensics/Systems/ForensicPadSystem.cs
index bf419e2f64..f7a79ef974 100644
--- a/Content.Server/Forensics/Systems/ForensicPadSystem.cs
+++ b/Content.Server/Forensics/Systems/ForensicPadSystem.cs
@@ -1,11 +1,10 @@
using Content.Shared.Examine;
using Content.Shared.Interaction;
using Content.Shared.Inventory;
-using Content.Server.DoAfter;
using Content.Server.Popups;
using Content.Shared.DoAfter;
+using Content.Shared.Forensics;
using Content.Shared.IdentityManagement;
-using Robust.Shared.Serialization;
namespace Content.Server.Forensics
{
@@ -14,7 +13,7 @@ namespace Content.Server.Forensics
///
public sealed class ForensicPadSystem : EntitySystem
{
- [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly InventorySystem _inventory = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
@@ -23,7 +22,7 @@ namespace Content.Server.Forensics
base.Initialize();
SubscribeLocalEvent(OnExamined);
SubscribeLocalEvent(OnAfterInteract);
- SubscribeLocalEvent>(OnDoAfter);
+ SubscribeLocalEvent(OnDoAfter);
}
private void OnExamined(EntityUid uid, ForensicPadComponent component, ExaminedEvent args)
@@ -79,25 +78,21 @@ namespace Content.Server.Forensics
private void StartScan(EntityUid used, EntityUid user, EntityUid target, ForensicPadComponent pad, string sample)
{
- var padData = new ForensicPadData(sample);
+ var ev = new ForensicPadDoAfterEvent(sample);
- var doAfterEventArgs = new DoAfterEventArgs(user, pad.ScanDelay, target: target, used: used)
+ var doAfterEventArgs = new DoAfterArgs(user, pad.ScanDelay, ev, used, target: target, used: used)
{
BreakOnTargetMove = true,
BreakOnUserMove = true,
- BreakOnStun = true,
- NeedHand = true,
- RaiseOnUser = false
+ NeedHand = true
};
- _doAfterSystem.DoAfter(doAfterEventArgs, padData);
+ _doAfterSystem.TryStartDoAfter(doAfterEventArgs);
}
- private void OnDoAfter(EntityUid uid, ForensicPadComponent component, DoAfterEvent args)
+ private void OnDoAfter(EntityUid uid, ForensicPadComponent padComponent, ForensicPadDoAfterEvent args)
{
- if (args.Handled
- || args.Cancelled
- || !EntityManager.TryGetComponent(args.Args.Used, out ForensicPadComponent? padComponent))
+ if (args.Handled || args.Cancelled)
{
return;
}
@@ -110,20 +105,10 @@ namespace Content.Server.Forensics
MetaData(uid).EntityName = Loc.GetString("forensic-pad-gloves-name", ("entity", args.Args.Target));
}
- padComponent.Sample = args.AdditionalData.Sample;
+ padComponent.Sample = args.Sample;
padComponent.Used = true;
args.Handled = true;
}
-
- private sealed class ForensicPadData
- {
- public string Sample;
-
- public ForensicPadData(string sample)
- {
- Sample = sample;
- }
- }
}
}
diff --git a/Content.Server/Forensics/Systems/ForensicScannerSystem.cs b/Content.Server/Forensics/Systems/ForensicScannerSystem.cs
index 83dfc87223..4f629590c8 100644
--- a/Content.Server/Forensics/Systems/ForensicScannerSystem.cs
+++ b/Content.Server/Forensics/Systems/ForensicScannerSystem.cs
@@ -3,7 +3,6 @@ using System.Text; // todo: remove this stinky LINQy
using Robust.Server.GameObjects;
using Robust.Shared.Audio;
using Robust.Shared.Timing;
-using Content.Server.DoAfter;
using Content.Server.Paper;
using Content.Server.Popups;
using Content.Server.UserInterface;
@@ -18,7 +17,7 @@ namespace Content.Server.Forensics
public sealed class ForensicScannerSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _gameTiming = default!;
- [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly PaperSystem _paperSystem = default!;
@@ -39,7 +38,7 @@ namespace Content.Server.Forensics
SubscribeLocalEvent>(OnUtilityVerb);
SubscribeLocalEvent(OnPrint);
SubscribeLocalEvent(OnClear);
- SubscribeLocalEvent(OnDoAfter);
+ SubscribeLocalEvent(OnDoAfter);
}
private void UpdateUserInterface(EntityUid uid, ForensicScannerComponent component)
@@ -91,11 +90,10 @@ namespace Content.Server.Forensics
///
private void StartScan(EntityUid uid, ForensicScannerComponent component, EntityUid user, EntityUid target)
{
- _doAfterSystem.DoAfter(new DoAfterEventArgs(user, component.ScanDelay, target: target, used: uid)
+ _doAfterSystem.TryStartDoAfter(new DoAfterArgs(user, component.ScanDelay, new ForensicScannerDoAfterEvent(), uid, target: target, used: uid)
{
BreakOnTargetMove = true,
BreakOnUserMove = true,
- BreakOnStun = true,
NeedHand = true
});
}
diff --git a/Content.Server/Gatherable/Components/GatheringToolComponent.cs b/Content.Server/Gatherable/Components/GatheringToolComponent.cs
index 9bf5bb2018..1d6f806904 100644
--- a/Content.Server/Gatherable/Components/GatheringToolComponent.cs
+++ b/Content.Server/Gatherable/Components/GatheringToolComponent.cs
@@ -32,6 +32,7 @@ namespace Content.Server.Gatherable.Components
public int MaxGatheringEntities = 1;
[ViewVariables]
+ [DataField("gatheringEntities")]
public readonly List GatheringEntities = new();
}
}
diff --git a/Content.Server/Gatherable/GatherableSystem.cs b/Content.Server/Gatherable/GatherableSystem.cs
index e82a5130d3..0aa8c256f8 100644
--- a/Content.Server/Gatherable/GatherableSystem.cs
+++ b/Content.Server/Gatherable/GatherableSystem.cs
@@ -1,11 +1,8 @@
-using System.Threading;
using Content.Server.Destructible;
-using Content.Server.DoAfter;
using Content.Server.Gatherable.Components;
-using Content.Shared.Damage;
using Content.Shared.DoAfter;
-using Content.Shared.Destructible;
using Content.Shared.EntityList;
+using Content.Shared.Gatherable;
using Content.Shared.Interaction;
using Content.Shared.Tag;
using Robust.Shared.Prototypes;
@@ -17,9 +14,8 @@ public sealed class GatherableSystem : EntitySystem
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IRobustRandom _random = default!;
- [Dependency] private readonly DamageableSystem _damageableSystem = default!;
[Dependency] private readonly DestructibleSystem _destructible = default!;
- [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly TagSystem _tagSystem = default!;
@@ -28,7 +24,7 @@ public sealed class GatherableSystem : EntitySystem
base.Initialize();
SubscribeLocalEvent(OnInteractUsing);
- SubscribeLocalEvent(OnDoAfter);
+ SubscribeLocalEvent(OnDoAfter);
}
private void OnInteractUsing(EntityUid uid, GatherableComponent component, InteractUsingEvent args)
@@ -44,33 +40,29 @@ public sealed class GatherableSystem : EntitySystem
var damageTime = (damageRequired / tool.Damage.Total).Float();
damageTime = Math.Max(1f, damageTime);
- var doAfter = new DoAfterEventArgs(args.User, damageTime, target: uid, used: args.Used)
+ var doAfter = new DoAfterArgs(args.User, damageTime, new GatherableDoAfterEvent(), uid, target: uid, used: args.Used)
{
BreakOnDamage = true,
- BreakOnStun = true,
BreakOnTargetMove = true,
BreakOnUserMove = true,
MovementThreshold = 0.25f,
};
- _doAfterSystem.DoAfter(doAfter);
+ _doAfterSystem.TryStartDoAfter(doAfter);
}
- private void OnDoAfter(EntityUid uid, GatherableComponent component, DoAfterEvent args)
+ private void OnDoAfter(EntityUid uid, GatherableComponent component, GatherableDoAfterEvent args)
{
if(!TryComp(args.Args.Used, out var tool) || args.Args.Target == null)
return;
+ tool.GatheringEntities.Remove(args.Args.Target.Value);
if (args.Handled || args.Cancelled)
- {
- tool.GatheringEntities.Remove(args.Args.Target.Value);
return;
- }
// Complete the gathering process
_destructible.DestroyEntity(args.Args.Target.Value);
_audio.PlayPvs(tool.GatheringSound, args.Args.Target.Value);
- tool.GatheringEntities.Remove(args.Args.Target.Value);
// Spawn the loot!
if (component.MappedLoot == null)
diff --git a/Content.Server/Guardian/GuardianCreatorComponent.cs b/Content.Server/Guardian/GuardianCreatorComponent.cs
index e120cc3b25..7729348453 100644
--- a/Content.Server/Guardian/GuardianCreatorComponent.cs
+++ b/Content.Server/Guardian/GuardianCreatorComponent.cs
@@ -28,7 +28,5 @@ namespace Content.Server.Guardian
///
[DataField("delay")]
public float InjectionDelay = 5f;
-
- public bool Injecting = false;
}
}
diff --git a/Content.Server/Guardian/GuardianSystem.cs b/Content.Server/Guardian/GuardianSystem.cs
index b1ca676e04..ed6811449b 100644
--- a/Content.Server/Guardian/GuardianSystem.cs
+++ b/Content.Server/Guardian/GuardianSystem.cs
@@ -1,10 +1,10 @@
-using Content.Server.DoAfter;
using Content.Server.Popups;
using Content.Shared.Actions;
using Content.Shared.Audio;
using Content.Shared.Damage;
using Content.Shared.DoAfter;
using Content.Shared.Examine;
+using Content.Shared.Guardian;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Interaction;
using Content.Shared.Interaction.Events;
@@ -22,7 +22,7 @@ namespace Content.Server.Guardian
///
public sealed class GuardianSystem : EntitySystem
{
- [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly DamageableSystem _damageSystem = default!;
[Dependency] private readonly SharedActionsSystem _actionSystem = default!;
@@ -35,7 +35,7 @@ namespace Content.Server.Guardian
SubscribeLocalEvent(OnCreatorUse);
SubscribeLocalEvent(OnCreatorInteract);
SubscribeLocalEvent(OnCreatorExamine);
- SubscribeLocalEvent(OnDoAfter);
+ SubscribeLocalEvent(OnDoAfter);
SubscribeLocalEvent(OnGuardianMove);
SubscribeLocalEvent(OnGuardianDamaged);
@@ -161,12 +161,7 @@ namespace Content.Server.Guardian
return;
}
- if (component.Injecting)
- return;
-
- component.Injecting = true;
-
- _doAfterSystem.DoAfter(new DoAfterEventArgs(user, component.InjectionDelay, target: target, used: injector)
+ _doAfterSystem.TryStartDoAfter(new DoAfterArgs(user, component.InjectionDelay, new GuardianCreatorDoAfterEvent(), injector, target: target, used: injector)
{
BreakOnTargetMove = true,
BreakOnUserMove = true
@@ -179,10 +174,7 @@ namespace Content.Server.Guardian
return;
if (args.Cancelled || component.Deleted || component.Used || !_handsSystem.IsHolding(args.Args.User, uid, out _) || HasComp(args.Args.Target))
- {
- component.Injecting = false;
return;
- }
var hostXform = Transform(args.Args.Target.Value);
var host = EnsureComp(args.Args.Target.Value);
diff --git a/Content.Server/Implants/ImplanterSystem.cs b/Content.Server/Implants/ImplanterSystem.cs
index 451f4d074e..f34d8eeb06 100644
--- a/Content.Server/Implants/ImplanterSystem.cs
+++ b/Content.Server/Implants/ImplanterSystem.cs
@@ -1,9 +1,6 @@
-using System.Threading;
-using Content.Server.DoAfter;
using Content.Server.Guardian;
using Content.Server.Popups;
using Content.Shared.DoAfter;
-using Content.Shared.Hands;
using Content.Shared.IdentityManagement;
using Content.Shared.Implants;
using Content.Shared.Implants.Components;
@@ -18,7 +15,7 @@ namespace Content.Server.Implants;
public sealed partial class ImplanterSystem : SharedImplanterSystem
{
[Dependency] private readonly PopupSystem _popup = default!;
- [Dependency] private readonly DoAfterSystem _doAfter = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly SharedContainerSystem _container = default!;
public override void Initialize()
@@ -26,12 +23,11 @@ public sealed partial class ImplanterSystem : SharedImplanterSystem
base.Initialize();
InitializeImplanted();
- SubscribeLocalEvent(OnHandDeselect);
SubscribeLocalEvent(OnImplanterAfterInteract);
SubscribeLocalEvent(OnImplanterGetState);
- SubscribeLocalEvent>(OnImplant);
- SubscribeLocalEvent>(OnDraw);
+ SubscribeLocalEvent(OnImplant);
+ SubscribeLocalEvent(OnDraw);
}
private void OnImplanterAfterInteract(EntityUid uid, ImplanterComponent component, AfterInteractEvent args)
@@ -62,12 +58,6 @@ public sealed partial class ImplanterSystem : SharedImplanterSystem
args.Handled = true;
}
- private void OnHandDeselect(EntityUid uid, ImplanterComponent component, HandDeselectedEvent args)
- {
- component.CancelToken?.Cancel();
- component.CancelToken = null;
- }
-
///
/// Attempt to implant someone else.
///
@@ -77,27 +67,21 @@ public sealed partial class ImplanterSystem : SharedImplanterSystem
/// The implanter being used
public void TryImplant(ImplanterComponent component, EntityUid user, EntityUid target, EntityUid implanter)
{
- if (component.CancelToken != null)
+ var args = new DoAfterArgs(user, component.ImplantTime, new ImplantEvent(), implanter, target: target, used: implanter)
+ {
+ BreakOnUserMove = true,
+ BreakOnTargetMove = true,
+ BreakOnDamage = true,
+ NeedHand = true,
+ };
+
+ if (!_doAfter.TryStartDoAfter(args))
return;
_popup.PopupEntity(Loc.GetString("injector-component-injecting-user"), target, user);
var userName = Identity.Entity(user, EntityManager);
_popup.PopupEntity(Loc.GetString("implanter-component-implanting-target", ("user", userName)), user, target, PopupType.LargeCaution);
-
- component.CancelToken?.Cancel();
- component.CancelToken = new CancellationTokenSource();
-
- var implantEvent = new ImplantEvent();
-
- _doAfter.DoAfter(new DoAfterEventArgs(user, component.ImplantTime, component.CancelToken.Token,target:target, used:implanter)
- {
- BreakOnUserMove = true,
- BreakOnTargetMove = true,
- BreakOnDamage = true,
- BreakOnStun = true,
- NeedHand = true
- }, implantEvent);
}
///
@@ -110,21 +94,17 @@ public sealed partial class ImplanterSystem : SharedImplanterSystem
//TODO: Remove when surgery is in
public void TryDraw(ImplanterComponent component, EntityUid user, EntityUid target, EntityUid implanter)
{
- _popup.PopupEntity(Loc.GetString("injector-component-injecting-user"), target, user);
-
- component.CancelToken?.Cancel();
- component.CancelToken = new CancellationTokenSource();
-
- var drawEvent = new DrawEvent();
-
- _doAfter.DoAfter(new DoAfterEventArgs(user, component.DrawTime, target:target,used:implanter)
+ var args = new DoAfterArgs(user, component.DrawTime, new DrawEvent(), implanter, target: target, used: implanter)
{
BreakOnUserMove = true,
BreakOnTargetMove = true,
BreakOnDamage = true,
- BreakOnStun = true,
- NeedHand = true
- }, drawEvent);
+ NeedHand = true,
+ };
+
+ if (_doAfter.TryStartDoAfter(args))
+ _popup.PopupEntity(Loc.GetString("injector-component-injecting-user"), target, user);
+
}
private void OnImplanterGetState(EntityUid uid, ImplanterComponent component, ref ComponentGetState args)
@@ -132,47 +112,23 @@ public sealed partial class ImplanterSystem : SharedImplanterSystem
args.State = new ImplanterComponentState(component.CurrentMode, component.ImplantOnly);
}
- private void OnImplant(EntityUid uid, ImplanterComponent component, DoAfterEvent args)
+ private void OnImplant(EntityUid uid, ImplanterComponent component, ImplantEvent args)
{
- if (args.Cancelled)
- {
- component.CancelToken = null;
- return;
- }
-
- if (args.Handled || args.Args.Target == null || args.Args.Used == null)
+ if (args.Cancelled || args.Handled || args.Target == null || args.Used == null)
return;
- Implant(args.Args.Used.Value, args.Args.Target.Value, component);
+ Implant(args.Used.Value, args.Target.Value, component);
args.Handled = true;
- component.CancelToken = null;
}
- private void OnDraw(EntityUid uid, ImplanterComponent component, DoAfterEvent args)
+ private void OnDraw(EntityUid uid, ImplanterComponent component, DrawEvent args)
{
- if (args.Cancelled)
- {
- component.CancelToken = null;
- return;
- }
-
- if (args.Handled || args.Args.Used == null || args.Args.Target == null)
+ if (args.Cancelled || args.Handled || args.Used == null || args.Target == null)
return;
- Draw(args.Args.Used.Value, args.Args.User, args.Args.Target.Value, component);
+ Draw(args.Used.Value, args.User, args.Target.Value, component);
args.Handled = true;
- component.CancelToken = null;
- }
-
- private sealed class ImplantEvent : EntityEventArgs
- {
-
- }
-
- private sealed class DrawEvent : EntityEventArgs
- {
-
}
}
diff --git a/Content.Server/Kitchen/EntitySystems/KitchenSpikeSystem.cs b/Content.Server/Kitchen/EntitySystems/KitchenSpikeSystem.cs
index 3b608ceb87..f9d41e82c0 100644
--- a/Content.Server/Kitchen/EntitySystems/KitchenSpikeSystem.cs
+++ b/Content.Server/Kitchen/EntitySystems/KitchenSpikeSystem.cs
@@ -1,5 +1,4 @@
using Content.Server.Administration.Logs;
-using Content.Server.DoAfter;
using Content.Server.Kitchen.Components;
using Content.Server.Popups;
using Content.Shared.Database;
@@ -25,7 +24,7 @@ namespace Content.Server.Kitchen.EntitySystems
public sealed class KitchenSpikeSystem : SharedKitchenSpikeSystem
{
[Dependency] private readonly PopupSystem _popupSystem = default!;
- [Dependency] private readonly DoAfterSystem _doAfter = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly IAdminLogManager _logger = default!;
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
[Dependency] private readonly IRobustRandom _random = default!;
@@ -43,7 +42,7 @@ namespace Content.Server.Kitchen.EntitySystems
SubscribeLocalEvent(OnDragDrop);
//DoAfter
- SubscribeLocalEvent(OnDoAfter);
+ SubscribeLocalEvent(OnDoAfter);
SubscribeLocalEvent(OnSuicide);
@@ -251,16 +250,15 @@ namespace Content.Server.Kitchen.EntitySystems
butcherable.BeingButchered = true;
component.InUse = true;
- var doAfterArgs = new DoAfterEventArgs(userUid, component.SpikeDelay + butcherable.ButcherDelay, target:victimUid, used:uid)
+ var doAfterArgs = new DoAfterArgs(userUid, component.SpikeDelay + butcherable.ButcherDelay, new SpikeDoAfterEvent(), uid, target: victimUid, used: uid)
{
BreakOnTargetMove = true,
BreakOnUserMove = true,
BreakOnDamage = true,
- BreakOnStun = true,
NeedHand = true
};
- _doAfter.DoAfter(doAfterArgs);
+ _doAfter.TryStartDoAfter(doAfterArgs);
return true;
}
diff --git a/Content.Server/Kitchen/EntitySystems/SharpSystem.cs b/Content.Server/Kitchen/EntitySystems/SharpSystem.cs
index 4a9e259e29..5a798132b9 100644
--- a/Content.Server/Kitchen/EntitySystems/SharpSystem.cs
+++ b/Content.Server/Kitchen/EntitySystems/SharpSystem.cs
@@ -1,5 +1,4 @@
using Content.Server.Body.Systems;
-using Content.Server.DoAfter;
using Content.Server.Kitchen.Components;
using Content.Shared.Body.Components;
using Content.Shared.Interaction;
@@ -9,6 +8,7 @@ using Content.Shared.Storage;
using Content.Shared.Verbs;
using Content.Shared.Destructible;
using Content.Shared.DoAfter;
+using Content.Shared.Kitchen;
using Content.Shared.Mobs.Components;
using Content.Shared.Mobs.Systems;
using Robust.Server.Containers;
@@ -21,7 +21,7 @@ public sealed class SharpSystem : EntitySystem
{
[Dependency] private readonly BodySystem _bodySystem = default!;
[Dependency] private readonly SharedDestructibleSystem _destructibleSystem = default!;
- [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
[Dependency] private readonly ContainerSystem _containerSystem = default!;
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
@@ -32,7 +32,7 @@ public sealed class SharpSystem : EntitySystem
base.Initialize();
SubscribeLocalEvent(OnAfterInteract);
- SubscribeLocalEvent(OnDoAfter);
+ SubscribeLocalEvent(OnDoAfter);
SubscribeLocalEvent>(OnGetInteractionVerbs);
}
@@ -63,16 +63,15 @@ public sealed class SharpSystem : EntitySystem
return;
var doAfter =
- new DoAfterEventArgs(user, sharp.ButcherDelayModifier * butcher.ButcherDelay, target: target, used: knife)
+ new DoAfterArgs(user, sharp.ButcherDelayModifier * butcher.ButcherDelay, new SharpDoAfterEvent(), knife, target: target, used: knife)
{
BreakOnTargetMove = true,
BreakOnUserMove = true,
BreakOnDamage = true,
- BreakOnStun = true,
NeedHand = true
};
- _doAfterSystem.DoAfter(doAfter);
+ _doAfterSystem.TryStartDoAfter(doAfter);
}
private void OnDoAfter(EntityUid uid, SharpComponent component, DoAfterEvent args)
diff --git a/Content.Server/Light/EntitySystems/PoweredLightSystem.cs b/Content.Server/Light/EntitySystems/PoweredLightSystem.cs
index 545ad4d4f3..9cd0c06dc4 100644
--- a/Content.Server/Light/EntitySystems/PoweredLightSystem.cs
+++ b/Content.Server/Light/EntitySystems/PoweredLightSystem.cs
@@ -1,7 +1,6 @@
using Content.Server.Administration.Logs;
using Content.Server.DeviceNetwork;
using Content.Server.DeviceNetwork.Systems;
-using Content.Server.DoAfter;
using Content.Server.Ghost;
using Content.Server.Light.Components;
using Content.Server.MachineLinking.Events;
@@ -40,7 +39,7 @@ namespace Content.Server.Light.EntitySystems
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
[Dependency] private readonly SignalLinkerSystem _signalSystem = default!;
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
- [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
@@ -63,8 +62,7 @@ namespace Content.Server.Light.EntitySystems
SubscribeLocalEvent(OnPowerChanged);
- SubscribeLocalEvent(OnDoAfter);
-
+ SubscribeLocalEvent(OnDoAfter);
SubscribeLocalEvent(OnEmpPulse);
}
@@ -140,11 +138,10 @@ namespace Content.Server.Light.EntitySystems
}
// removing a working bulb, so require a delay
- _doAfterSystem.DoAfter(new DoAfterEventArgs(userUid, light.EjectBulbDelay, target:uid)
+ _doAfterSystem.TryStartDoAfter(new DoAfterArgs(userUid, light.EjectBulbDelay, new PoweredLightDoAfterEvent(), uid, target: uid)
{
BreakOnUserMove = true,
BreakOnDamage = true,
- BreakOnStun = true
});
args.Handled = true;
@@ -428,7 +425,7 @@ namespace Content.Server.Light.EntitySystems
private void OnEmpPulse(EntityUid uid, PoweredLightComponent component, ref EmpPulseEvent args)
{
args.Affected = true;
- TryDestroyBulb(uid, component);
+ TryDestroyBulb(uid, component);
}
}
}
diff --git a/Content.Server/Magic/MagicSystem.cs b/Content.Server/Magic/MagicSystem.cs
index 5cdb549b7a..5374d9ab74 100644
--- a/Content.Server/Magic/MagicSystem.cs
+++ b/Content.Server/Magic/MagicSystem.cs
@@ -1,8 +1,6 @@
-using System.Threading;
using Content.Server.Body.Components;
using Content.Server.Body.Systems;
using Content.Server.Coordinates.Helpers;
-using Content.Server.DoAfter;
using Content.Server.Doors.Systems;
using Content.Server.Magic.Events;
using Content.Server.Weapons.Ranged.Systems;
@@ -13,6 +11,7 @@ using Content.Shared.DoAfter;
using Content.Shared.Doors.Components;
using Content.Shared.Doors.Systems;
using Content.Shared.Interaction.Events;
+using Content.Shared.Magic;
using Content.Shared.Maps;
using Content.Shared.Physics;
using Content.Shared.Spawners.Components;
@@ -42,7 +41,7 @@ public sealed class MagicSystem : EntitySystem
[Dependency] private readonly EntityLookupSystem _lookup = default!;
[Dependency] private readonly SharedDoorSystem _doorSystem = default!;
[Dependency] private readonly SharedActionsSystem _actionsSystem = default!;
- [Dependency] private readonly DoAfterSystem _doAfter = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly GunSystem _gunSystem = default!;
[Dependency] private readonly PhysicsSystem _physics = default!;
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
@@ -54,7 +53,7 @@ public sealed class MagicSystem : EntitySystem
SubscribeLocalEvent(OnInit);
SubscribeLocalEvent(OnUse);
- SubscribeLocalEvent(OnDoAfter);
+ SubscribeLocalEvent(OnDoAfter);
SubscribeLocalEvent(OnInstantSpawn);
SubscribeLocalEvent(OnTeleportSpell);
@@ -111,16 +110,15 @@ public sealed class MagicSystem : EntitySystem
private void AttemptLearn(EntityUid uid, SpellbookComponent component, UseInHandEvent args)
{
- var doAfterEventArgs = new DoAfterEventArgs(args.User, component.LearnTime, target:uid)
+ var doAfterEventArgs = new DoAfterArgs(args.User, component.LearnTime, new SpellbookDoAfterEvent(), uid, target: uid)
{
BreakOnTargetMove = true,
BreakOnUserMove = true,
BreakOnDamage = true,
- BreakOnStun = true,
NeedHand = true //What, are you going to read with your eyes only??
};
- _doAfter.DoAfter(doAfterEventArgs);
+ _doAfter.TryStartDoAfter(doAfterEventArgs);
}
#region Spells
diff --git a/Content.Server/Mech/Equipment/EntitySystems/MechGrabberSystem.cs b/Content.Server/Mech/Equipment/EntitySystems/MechGrabberSystem.cs
index baf4eafd21..310c5a50c8 100644
--- a/Content.Server/Mech/Equipment/EntitySystems/MechGrabberSystem.cs
+++ b/Content.Server/Mech/Equipment/EntitySystems/MechGrabberSystem.cs
@@ -1,11 +1,9 @@
using System.Linq;
-using Content.Server.DoAfter;
using Content.Server.Interaction;
using Content.Server.Mech.Components;
using Content.Server.Mech.Equipment.Components;
using Content.Server.Mech.Systems;
using Content.Shared.DoAfter;
-using Content.Shared.Construction.Components;
using Content.Shared.Interaction;
using Content.Shared.Mech;
using Content.Shared.Mech.Equipment.Components;
@@ -26,7 +24,7 @@ public sealed class MechGrabberSystem : EntitySystem
{
[Dependency] private readonly SharedContainerSystem _container = default!;
[Dependency] private readonly MechSystem _mech = default!;
- [Dependency] private readonly DoAfterSystem _doAfter = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly InteractionSystem _interaction = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly TransformSystem _transform = default!;
@@ -41,7 +39,7 @@ public sealed class MechGrabberSystem : EntitySystem
SubscribeLocalEvent(OnAttemptRemove);
SubscribeLocalEvent(OnInteract);
- SubscribeLocalEvent(OnMechGrab);
+ SubscribeLocalEvent(OnMechGrab);
}
private void OnGrabberMessage(EntityUid uid, MechGrabberComponent component, MechEquipmentUiMessageRelayEvent args)
@@ -150,7 +148,7 @@ public sealed class MechGrabberSystem : EntitySystem
args.Handled = true;
component.AudioStream = _audio.PlayPvs(component.GrabSound, uid);
- _doAfter.DoAfter(new DoAfterEventArgs(args.User, component.GrabDelay, target:target, used:uid)
+ _doAfter.TryStartDoAfter(new DoAfterArgs(args.User, component.GrabDelay, new GrabberDoAfterEvent(), uid, target: target, used: uid)
{
BreakOnTargetMove = true,
BreakOnUserMove = true
diff --git a/Content.Server/Mech/Systems/MechEquipmentSystem.cs b/Content.Server/Mech/Systems/MechEquipmentSystem.cs
index 8a9032a21d..9ffa1030e1 100644
--- a/Content.Server/Mech/Systems/MechEquipmentSystem.cs
+++ b/Content.Server/Mech/Systems/MechEquipmentSystem.cs
@@ -1,5 +1,4 @@
-using Content.Server.DoAfter;
-using Content.Server.Mech.Components;
+using Content.Server.Mech.Components;
using Content.Server.Popups;
using Content.Shared.DoAfter;
using Content.Shared.Interaction;
@@ -13,14 +12,14 @@ namespace Content.Server.Mech.Systems;
public sealed class MechEquipmentSystem : EntitySystem
{
[Dependency] private readonly MechSystem _mech = default!;
- [Dependency] private readonly DoAfterSystem _doAfter = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly PopupSystem _popup = default!;
///
public override void Initialize()
{
SubscribeLocalEvent(OnUsed);
- SubscribeLocalEvent>(OnInsertEquipment);
+ SubscribeLocalEvent(OnInsertEquipment);
}
private void OnUsed(EntityUid uid, MechEquipmentComponent component, AfterInteractEvent args)
@@ -46,18 +45,16 @@ public sealed class MechEquipmentSystem : EntitySystem
_popup.PopupEntity(Loc.GetString("mech-equipment-begin-install", ("item", uid)), mech);
- var insertEquipment = new InsertEquipmentEvent();
- var doAfterEventArgs = new DoAfterEventArgs(args.User, component.InstallDuration, target: mech, used: uid)
+ var doAfterEventArgs = new DoAfterArgs(args.User, component.InstallDuration, new InsertEquipmentEvent(), uid, target: mech, used: uid)
{
- BreakOnStun = true,
BreakOnTargetMove = true,
BreakOnUserMove = true
};
- _doAfter.DoAfter(doAfterEventArgs, insertEquipment);
+ _doAfter.TryStartDoAfter(doAfterEventArgs);
}
- private void OnInsertEquipment(EntityUid uid, MechEquipmentComponent component, DoAfterEvent args)
+ private void OnInsertEquipment(EntityUid uid, MechEquipmentComponent component, InsertEquipmentEvent args)
{
if (args.Handled || args.Cancelled || args.Args.Target == null)
return;
@@ -67,9 +64,4 @@ public sealed class MechEquipmentSystem : EntitySystem
args.Handled = true;
}
-
- private sealed class InsertEquipmentEvent : EntityEventArgs
- {
-
- }
}
diff --git a/Content.Server/Mech/Systems/MechSystem.cs b/Content.Server/Mech/Systems/MechSystem.cs
index cf41335f35..d264eb59b4 100644
--- a/Content.Server/Mech/Systems/MechSystem.cs
+++ b/Content.Server/Mech/Systems/MechSystem.cs
@@ -1,6 +1,5 @@
using System.Linq;
using Content.Server.Atmos.EntitySystems;
-using Content.Server.DoAfter;
using Content.Server.Mech.Components;
using Content.Server.Power.Components;
using Content.Shared.ActionBlocker;
@@ -27,7 +26,7 @@ public sealed class MechSystem : SharedMechSystem
[Dependency] private readonly AtmosphereSystem _atmosphere = default!;
[Dependency] private readonly ContainerSystem _container = default!;
[Dependency] private readonly DamageableSystem _damageable = default!;
- [Dependency] private readonly DoAfterSystem _doAfter = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly IMapManager _map = default!;
[Dependency] private readonly UserInterfaceSystem _ui = default!;
[Dependency] private readonly ActionBlockerSystem _actionBlocker = default!;
@@ -45,9 +44,9 @@ public sealed class MechSystem : SharedMechSystem
SubscribeLocalEvent(OnMapInit);
SubscribeLocalEvent>(OnAlternativeVerb);
SubscribeLocalEvent(OnOpenUi);
- SubscribeLocalEvent>(OnRemoveBattery);
- SubscribeLocalEvent>(OnMechEntry);
- SubscribeLocalEvent>(OnMechExit);
+ SubscribeLocalEvent(OnRemoveBattery);
+ SubscribeLocalEvent(OnMechEntry);
+ SubscribeLocalEvent(OnMechExit);
SubscribeLocalEvent(OnDamageChanged);
SubscribeLocalEvent(OnRemoveEquipmentMessage);
@@ -84,22 +83,17 @@ public sealed class MechSystem : SharedMechSystem
if (TryComp(args.Used, out var tool) && tool.Qualities.Contains("Prying") && component.BatterySlot.ContainedEntity != null)
{
- var removeBattery = new RemoveBatteryEvent();
-
- var doAfterEventArgs = new DoAfterEventArgs(args.User, component.BatteryRemovalDelay, target: uid, used: args.Target)
+ var doAfterEventArgs = new DoAfterArgs(args.User, component.BatteryRemovalDelay, new RemoveBatteryEvent(), uid, target: uid, used: args.Target)
{
BreakOnTargetMove = true,
BreakOnUserMove = true,
- RaiseOnTarget = true,
- RaiseOnUsed = false,
- RaiseOnUser = false,
};
- _doAfter.DoAfter(doAfterEventArgs, removeBattery);
+ _doAfter.TryStartDoAfter(doAfterEventArgs);
}
}
- private void OnRemoveBattery(EntityUid uid, MechComponent component, DoAfterEvent args)
+ private void OnRemoveBattery(EntityUid uid, MechComponent component, RemoveBatteryEvent args)
{
if (args.Cancelled || args.Handled)
return;
@@ -166,17 +160,12 @@ public sealed class MechSystem : SharedMechSystem
Text = Loc.GetString("mech-verb-enter"),
Act = () =>
{
- var mechEntryEvent = new MechEntryEvent();
- var doAfterEventArgs = new DoAfterEventArgs(args.User, component.EntryDelay, target: uid)
+ var doAfterEventArgs = new DoAfterArgs(args.User, component.EntryDelay, new MechEntryEvent(), uid, target: uid)
{
BreakOnUserMove = true,
- BreakOnStun = true,
- RaiseOnTarget = true,
- RaiseOnUsed = false,
- RaiseOnUser = false,
};
- _doAfter.DoAfter(doAfterEventArgs, mechEntryEvent);
+ _doAfter.TryStartDoAfter(doAfterEventArgs);
}
};
var openUiVerb = new AlternativeVerb //can't hijack someone else's mech
@@ -201,25 +190,20 @@ public sealed class MechSystem : SharedMechSystem
return;
}
- var mechExitEvent = new MechExitEvent();
- var doAfterEventArgs = new DoAfterEventArgs(args.User, component.ExitDelay, target: uid)
+ var doAfterEventArgs = new DoAfterArgs(args.User, component.ExitDelay, new MechExitEvent(), uid, target: uid)
{
BreakOnUserMove = true,
BreakOnTargetMove = true,
- BreakOnStun = true,
- RaiseOnTarget = true,
- RaiseOnUsed = false,
- RaiseOnUser = false,
};
- _doAfter.DoAfter(doAfterEventArgs, mechExitEvent);
+ _doAfter.TryStartDoAfter(doAfterEventArgs);
}
};
args.Verbs.Add(ejectVerb);
}
}
- private void OnMechEntry(EntityUid uid, MechComponent component, DoAfterEvent args)
+ private void OnMechEntry(EntityUid uid, MechComponent component, MechEntryEvent args)
{
if (args.Cancelled || args.Handled)
return;
@@ -230,7 +214,7 @@ public sealed class MechSystem : SharedMechSystem
args.Handled = true;
}
- private void OnMechExit(EntityUid uid, MechComponent component, DoAfterEvent args)
+ private void OnMechExit(EntityUid uid, MechComponent component, MechExitEvent args)
{
if (args.Cancelled || args.Handled)
return;
@@ -454,27 +438,4 @@ public sealed class MechSystem : SharedMechSystem
args.Handled = true;
}
#endregion
-
- ///
- /// Event raised when the battery is successfully removed from the mech,
- /// on both success and failure
- ///
- private sealed class RemoveBatteryEvent : EntityEventArgs
- {
- }
-
- ///
- /// Event raised when a person enters a mech, on both success and failure
- ///
- private sealed class MechEntryEvent : EntityEventArgs
- {
- }
-
- ///
- /// Event raised when a person removes someone from a mech,
- /// on both success and failure
- ///
- private sealed class MechExitEvent : EntityEventArgs
- {
- }
}
diff --git a/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerSystem.cs b/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerSystem.cs
index b418e6a6e3..a36bc01ed6 100644
--- a/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerSystem.cs
+++ b/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerSystem.cs
@@ -1,4 +1,3 @@
-using System.Threading;
using Content.Shared.Interaction;
using Content.Shared.Audio;
using Content.Shared.Jittering;
@@ -14,7 +13,6 @@ using Content.Server.Fluids.EntitySystems;
using Content.Server.Body.Components;
using Content.Server.Climbing;
using Content.Server.Construction;
-using Content.Server.DoAfter;
using Content.Server.Materials;
using Content.Server.Mind.Components;
using Content.Shared.DoAfter;
@@ -27,7 +25,7 @@ using Robust.Shared.Random;
using Robust.Shared.Configuration;
using Robust.Server.Player;
using Robust.Shared.Physics.Components;
-using Content.Shared.Humanoid;
+using Content.Shared.Medical;
namespace Content.Server.Medical.BiomassReclaimer
{
@@ -43,7 +41,7 @@ namespace Content.Server.Medical.BiomassReclaimer
[Dependency] private readonly ThrowingSystem _throwing = default!;
[Dependency] private readonly IRobustRandom _robustRandom = default!;
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
- [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly MaterialStorageSystem _material = default!;
@@ -97,7 +95,7 @@ namespace Content.Server.Medical.BiomassReclaimer
SubscribeLocalEvent(OnUpgradeExamine);
SubscribeLocalEvent(OnPowerChanged);
SubscribeLocalEvent(OnSuicide);
- SubscribeLocalEvent(OnDoAfter);
+ SubscribeLocalEvent(OnDoAfter);
}
private void OnSuicide(EntityUid uid, BiomassReclaimerComponent component, SuicideEvent args)
@@ -152,11 +150,10 @@ namespace Content.Server.Medical.BiomassReclaimer
if (!HasComp(args.Used) || !CanGib(uid, args.Used, component))
return;
- _doAfterSystem.DoAfter(new DoAfterEventArgs(args.User, 7f, target:args.Target, used:args.Used)
+ _doAfterSystem.TryStartDoAfter(new DoAfterArgs(args.User, 7f, new ReclaimerDoAfterEvent(), uid, target: args.Target, used: args.Used)
{
BreakOnTargetMove = true,
BreakOnUserMove = true,
- BreakOnStun = true,
NeedHand = true
});
}
diff --git a/Content.Server/Medical/Components/HealingComponent.cs b/Content.Server/Medical/Components/HealingComponent.cs
index 5f3120cff0..adb5857b32 100644
--- a/Content.Server/Medical/Components/HealingComponent.cs
+++ b/Content.Server/Medical/Components/HealingComponent.cs
@@ -1,6 +1,6 @@
-using System.Threading;
using Content.Shared.Damage;
using Content.Shared.Damage.Prototypes;
+using Content.Shared.DoAfter;
using Robust.Shared.Audio;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
@@ -39,12 +39,6 @@ namespace Content.Server.Medical.Components
[DataField("delay")]
public float Delay = 3f;
- ///
- /// Cancel token to prevent rapid healing
- ///
- [DataField("cancelToken")]
- public CancellationTokenSource? CancelToken;
-
///
/// Delay multiplier when healing yourself.
///
diff --git a/Content.Server/Medical/CryoPodSystem.cs b/Content.Server/Medical/CryoPodSystem.cs
index 886922986b..62c168c3e7 100644
--- a/Content.Server/Medical/CryoPodSystem.cs
+++ b/Content.Server/Medical/CryoPodSystem.cs
@@ -7,7 +7,6 @@ using Content.Server.Body.Systems;
using Content.Server.Chemistry.Components.SolutionManager;
using Content.Server.Chemistry.EntitySystems;
using Content.Server.Climbing;
-using Content.Server.DoAfter;
using Content.Server.Medical.Components;
using Content.Server.NodeContainer;
using Content.Server.NodeContainer.NodeGroups;
@@ -26,7 +25,6 @@ using Content.Shared.Interaction;
using Content.Shared.Medical.Cryogenics;
using Content.Shared.MedicalScanner;
using Content.Shared.Tools;
-using Content.Shared.Tools.Components;
using Content.Shared.Verbs;
using Robust.Server.GameObjects;
using Robust.Shared.Timing;
@@ -42,7 +40,7 @@ public sealed partial class CryoPodSystem: SharedCryoPodSystem
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
[Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!;
[Dependency] private readonly UserInterfaceSystem _userInterfaceSystem = default!;
- [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
[Dependency] private readonly SharedToolSystem _toolSystem = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
@@ -56,9 +54,8 @@ public sealed partial class CryoPodSystem: SharedCryoPodSystem
SubscribeLocalEvent(OnComponentInit);
SubscribeLocalEvent>(AddAlternativeVerbs);
SubscribeLocalEvent(OnEmagged);
- SubscribeLocalEvent(OnDoAfter);
+ SubscribeLocalEvent(OnDragFinished);
SubscribeLocalEvent(OnCryoPodPryFinished);
- SubscribeLocalEvent(OnCryoPodPryInterrupted);
SubscribeLocalEvent(OnCryoPodUpdateAtmosphere);
SubscribeLocalEvent(HandleDragDropOn);
@@ -130,25 +127,23 @@ public sealed partial class CryoPodSystem: SharedCryoPodSystem
if (cryoPodComponent.BodyContainer.ContainedEntity != null)
return;
- var doAfterArgs = new DoAfterEventArgs(args.User, cryoPodComponent.EntryDelay, target:args.Dragged, used:uid)
+ var doAfterArgs = new DoAfterArgs(args.User, cryoPodComponent.EntryDelay, new CryoPodDragFinished(), uid, target: args.Dragged, used: uid)
{
BreakOnDamage = true,
- BreakOnStun = true,
BreakOnTargetMove = true,
BreakOnUserMove = true,
NeedHand = false,
};
- _doAfterSystem.DoAfter(doAfterArgs);
+ _doAfterSystem.TryStartDoAfter(doAfterArgs);
args.Handled = true;
}
- private void OnDoAfter(EntityUid uid, CryoPodComponent component, DoAfterEvent args)
+ private void OnDragFinished(EntityUid uid, CryoPodComponent component, CryoPodDragFinished args)
{
if (args.Cancelled || args.Handled || args.Args.Target == null)
return;
InsertBody(uid, args.Args.Target.Value, component);
-
args.Handled = true;
}
@@ -179,18 +174,7 @@ public sealed partial class CryoPodSystem: SharedCryoPodSystem
if (args.Handled || !cryoPodComponent.Locked || cryoPodComponent.BodyContainer.ContainedEntity == null)
return;
- if (TryComp(args.Used, out ToolComponent? tool)
- && tool.Qualities.Contains("Prying")) // Why aren't those enums?
- {
- if (cryoPodComponent.IsPrying)
- return;
- cryoPodComponent.IsPrying = true;
-
- var toolEvData = new ToolEventData(new CryoPodPryFinished(), targetEntity:uid);
- _toolSystem.UseTool(args.Used, args.User, uid, cryoPodComponent.PryDelay, new [] {"Prying"}, toolEvData);
-
- args.Handled = true;
- }
+ args.Handled = _toolSystem.UseTool(args.Used, args.User, uid, cryoPodComponent.PryDelay, "Prying", new CryoPodPryFinished());
}
private void OnExamined(EntityUid uid, CryoPodComponent component, ExaminedEvent args)
diff --git a/Content.Server/Medical/HealingSystem.cs b/Content.Server/Medical/HealingSystem.cs
index 9b4d9e77ed..d4382848f0 100644
--- a/Content.Server/Medical/HealingSystem.cs
+++ b/Content.Server/Medical/HealingSystem.cs
@@ -1,15 +1,15 @@
-using System.Threading;
using Content.Server.Administration.Logs;
using Content.Server.Body.Systems;
-using Content.Server.DoAfter;
using Content.Server.Medical.Components;
using Content.Server.Stack;
using Content.Shared.Audio;
using Content.Shared.Damage;
using Content.Shared.Database;
using Content.Shared.DoAfter;
+using Content.Shared.FixedPoint;
using Content.Shared.Interaction;
using Content.Shared.Interaction.Events;
+using Content.Shared.Medical;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Components;
using Content.Shared.Mobs.Systems;
@@ -24,7 +24,7 @@ public sealed class HealingSystem : EntitySystem
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
[Dependency] private readonly DamageableSystem _damageable = default!;
[Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!;
- [Dependency] private readonly DoAfterSystem _doAfter = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly StackSystem _stacks = default!;
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
@@ -36,45 +36,43 @@ public sealed class HealingSystem : EntitySystem
base.Initialize();
SubscribeLocalEvent(OnHealingUse);
SubscribeLocalEvent(OnHealingAfterInteract);
- SubscribeLocalEvent>(OnDoAfter);
+ SubscribeLocalEvent(OnDoAfter);
}
- private void OnDoAfter(EntityUid uid, DamageableComponent component, DoAfterEvent args)
+ private void OnDoAfter(EntityUid uid, DamageableComponent component, HealingDoAfterEvent args)
{
- if (args.Cancelled)
- {
- args.AdditionalData.HealingComponent.CancelToken = null;
+ if (!TryComp(args.Used, out HealingComponent? healing))
return;
- }
- if (args.Handled || args.Cancelled || _mobStateSystem.IsDead(uid) || args.Args.Used == null)
+ if (args.Handled || args.Cancelled || _mobStateSystem.IsDead(uid))
return;
if (component.DamageContainerID is not null && !component.DamageContainerID.Equals(component.DamageContainerID))
return;
// Heal some bloodloss damage.
- if (args.AdditionalData.HealingComponent.BloodlossModifier != 0)
- _bloodstreamSystem.TryModifyBleedAmount(uid, args.AdditionalData.HealingComponent.BloodlossModifier);
+ if (healing.BloodlossModifier != 0)
+ _bloodstreamSystem.TryModifyBleedAmount(uid, healing.BloodlossModifier);
- var healed = _damageable.TryChangeDamage(uid, args.AdditionalData.HealingComponent.Damage, true, origin: args.Args.User);
+ var healed = _damageable.TryChangeDamage(uid, healing.Damage, true, origin: args.Args.User);
- if (healed == null)
+ if (healed == null && healing.BloodlossModifier != 0)
return;
+ var total = healed?.Total ?? FixedPoint2.Zero;
+
// Reverify that we can heal the damage.
- _stacks.Use(args.Args.Used.Value, 1, args.AdditionalData.Stack);
-
- if (uid != args.Args.User)
- _adminLogger.Add(LogType.Healed, $"{EntityManager.ToPrettyString(args.Args.User):user} healed {EntityManager.ToPrettyString(uid):target} for {healed.Total:damage} damage");
+ _stacks.Use(args.Used.Value, 1);
+ if (uid != args.User)
+ _adminLogger.Add(LogType.Healed,
+ $"{EntityManager.ToPrettyString(args.User):user} healed {EntityManager.ToPrettyString(uid):target} for {total:damage} damage");
else
- _adminLogger.Add(LogType.Healed, $"{EntityManager.ToPrettyString(args.Args.User):user} healed themselves for {healed.Total:damage} damage");
+ _adminLogger.Add(LogType.Healed,
+ $"{EntityManager.ToPrettyString(args.User):user} healed themselves for {total:damage} damage");
- if (args.AdditionalData.HealingComponent.HealingEndSound != null)
- _audio.PlayPvs(args.AdditionalData.HealingComponent.HealingEndSound, uid, AudioHelpers.WithVariation(0.125f, _random).WithVolume(-5f));
+ _audio.PlayPvs(healing.HealingEndSound, uid, AudioHelpers.WithVariation(0.125f, _random).WithVolume(-5f));
- args.AdditionalData.HealingComponent.CancelToken = null;
args.Handled = true;
}
@@ -98,13 +96,14 @@ public sealed class HealingSystem : EntitySystem
private bool TryHeal(EntityUid uid, EntityUid user, EntityUid target, HealingComponent component)
{
- if (_mobStateSystem.IsDead(target) || !TryComp(target, out var targetDamage) || component.CancelToken != null)
+ if (_mobStateSystem.IsDead(target) || !TryComp(target, out var targetDamage))
return false;
if (targetDamage.TotalDamage == 0)
return false;
- if (component.DamageContainerID is not null && !component.DamageContainerID.Equals(targetDamage.DamageContainerID))
+ if (component.DamageContainerID is not null &&
+ !component.DamageContainerID.Equals(targetDamage.DamageContainerID))
return false;
if (user != target && !_interactionSystem.InRangeUnobstructed(user, target, popup: true))
@@ -114,7 +113,8 @@ public sealed class HealingSystem : EntitySystem
return false;
if (component.HealingBeginSound != null)
- _audio.PlayPvs(component.HealingBeginSound, uid, AudioHelpers.WithVariation(0.125f, _random).WithVolume(-5f));
+ _audio.PlayPvs(component.HealingBeginSound, uid,
+ AudioHelpers.WithVariation(0.125f, _random).WithVolume(-5f));
var isNotSelf = user != target;
@@ -122,27 +122,18 @@ public sealed class HealingSystem : EntitySystem
? component.Delay
: component.Delay * GetScaledHealingPenalty(user, component);
- component.CancelToken = new CancellationTokenSource();
-
- var healingData = new HealingData(component, stack);
-
- 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
- // not being able to heal your own ticking damage would be frustrating.
- BreakOnStun = true,
- NeedHand = true,
- // Juusstt in case damageble gets removed it avoids having to re-cancel the token. Won't need this when DoAfterEvent gets added.
- PostCheck = () => true
- };
-
- _doAfter.DoAfter(doAfterEventArgs, healingData);
+ var doAfterEventArgs =
+ new DoAfterArgs(user, delay, new HealingDoAfterEvent(), target, target: target, used: uid)
+ {
+ //Raise the event on the target if it's not self, otherwise raise it on self.
+ BreakOnUserMove = true,
+ BreakOnTargetMove = true,
+ // Didn't break on damage as they may be trying to prevent it and
+ // not being able to heal your own ticking damage would be frustrating.
+ NeedHand = true,
+ };
+ _doAfter.TryStartDoAfter(doAfterEventArgs);
return true;
}
@@ -155,7 +146,8 @@ public sealed class HealingSystem : EntitySystem
public float GetScaledHealingPenalty(EntityUid uid, HealingComponent component)
{
var output = component.Delay;
- if (!TryComp(uid, out var mobThreshold) || !TryComp(uid, out var damageable))
+ if (!TryComp(uid, out var mobThreshold) ||
+ !TryComp(uid, out var damageable))
return output;
if (!_mobThresholdSystem.TryGetThresholdForState(uid, MobState.Critical, out var amount, mobThreshold))
return 1;
@@ -165,10 +157,4 @@ public sealed class HealingSystem : EntitySystem
var modifier = percentDamage * (component.SelfHealPenaltyMultiplier - 1) + 1;
return Math.Max(modifier, 1);
}
-
- private record struct HealingData(HealingComponent HealingComponent, StackComponent Stack)
- {
- public HealingComponent HealingComponent = HealingComponent;
- public StackComponent Stack = Stack;
- }
}
diff --git a/Content.Server/Medical/HealthAnalyzerSystem.cs b/Content.Server/Medical/HealthAnalyzerSystem.cs
index 0ba0770036..67fa2ebac8 100644
--- a/Content.Server/Medical/HealthAnalyzerSystem.cs
+++ b/Content.Server/Medical/HealthAnalyzerSystem.cs
@@ -1,4 +1,3 @@
-using Content.Server.DoAfter;
using Content.Server.Medical.Components;
using Content.Server.Disease;
using Content.Server.Popups;
@@ -6,6 +5,7 @@ using Content.Shared.Damage;
using Content.Shared.DoAfter;
using Content.Shared.IdentityManagement;
using Content.Shared.Interaction;
+using Content.Shared.MedicalScanner;
using Content.Shared.Mobs.Components;
using Robust.Server.GameObjects;
using static Content.Shared.MedicalScanner.SharedHealthAnalyzerComponent;
@@ -16,7 +16,7 @@ namespace Content.Server.Medical
{
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly DiseaseSystem _disease = default!;
- [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
@@ -25,7 +25,7 @@ namespace Content.Server.Medical
base.Initialize();
SubscribeLocalEvent(HandleActivateInWorld);
SubscribeLocalEvent(OnAfterInteract);
- SubscribeLocalEvent(OnDoAfter);
+ SubscribeLocalEvent(OnDoAfter);
}
private void HandleActivateInWorld(EntityUid uid, HealthAnalyzerComponent healthAnalyzer, ActivateInWorldEvent args)
@@ -40,11 +40,10 @@ namespace Content.Server.Medical
_audio.PlayPvs(healthAnalyzer.ScanningBeginSound, uid);
- _doAfterSystem.DoAfter(new DoAfterEventArgs(args.User, healthAnalyzer.ScanDelay, target: args.Target, used:uid)
+ _doAfterSystem.TryStartDoAfter(new DoAfterArgs(args.User, healthAnalyzer.ScanDelay, new HealthAnalyzerDoAfterEvent(), uid, target: args.Target, used: uid)
{
BreakOnTargetMove = true,
BreakOnUserMove = true,
- BreakOnStun = true,
NeedHand = true
});
}
diff --git a/Content.Server/Medical/Stethoscope/StethoscopeSystem.cs b/Content.Server/Medical/Stethoscope/StethoscopeSystem.cs
index af9589d016..b89c463dff 100644
--- a/Content.Server/Medical/Stethoscope/StethoscopeSystem.cs
+++ b/Content.Server/Medical/Stethoscope/StethoscopeSystem.cs
@@ -1,5 +1,4 @@
using Content.Server.Body.Components;
-using Content.Server.DoAfter;
using Content.Server.Medical.Components;
using Content.Server.Popups;
using Content.Shared.Actions;
@@ -11,6 +10,7 @@ using Content.Shared.Verbs;
using Content.Shared.Mobs.Components;
using Content.Shared.Mobs.Systems;
using Content.Shared.DoAfter;
+using Content.Shared.Medical;
using Robust.Shared.Utility;
namespace Content.Server.Medical
@@ -18,7 +18,7 @@ namespace Content.Server.Medical
public sealed class StethoscopeSystem : EntitySystem
{
[Dependency] private readonly PopupSystem _popupSystem = default!;
- [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
public override void Initialize()
@@ -29,7 +29,7 @@ namespace Content.Server.Medical
SubscribeLocalEvent>(AddStethoscopeVerb);
SubscribeLocalEvent(OnGetActions);
SubscribeLocalEvent(OnStethoscopeAction);
- SubscribeLocalEvent(OnDoAfter);
+ SubscribeLocalEvent(OnDoAfter);
}
///
@@ -103,11 +103,10 @@ namespace Content.Server.Medical
// construct the doafter and start it
private void StartListening(EntityUid scope, EntityUid user, EntityUid target, StethoscopeComponent comp)
{
- _doAfterSystem.DoAfter(new DoAfterEventArgs(user, comp.Delay, target: target, used:scope)
+ _doAfterSystem.TryStartDoAfter(new DoAfterArgs(user, comp.Delay, new StethoscopeDoAfterEvent(), scope, target: target, used: scope)
{
BreakOnTargetMove = true,
BreakOnUserMove = true,
- BreakOnStun = true,
NeedHand = true
});
}
diff --git a/Content.Server/NPC/Systems/NPCSteeringSystem.Obstacles.cs b/Content.Server/NPC/Systems/NPCSteeringSystem.Obstacles.cs
index 06aa9f7ca9..526eaab55a 100644
--- a/Content.Server/NPC/Systems/NPCSteeringSystem.Obstacles.cs
+++ b/Content.Server/NPC/Systems/NPCSteeringSystem.Obstacles.cs
@@ -99,7 +99,8 @@ public sealed partial class NPCSteeringSystem
if (doorQuery.TryGetComponent(ent, out var door) && door.State != DoorState.Open)
{
// TODO: Use the verb.
- if (door.State != DoorState.Opening && !door.BeingPried)
+
+ if (door.State != DoorState.Opening)
_doors.TryPryDoor(ent, uid, uid, door, true);
return SteeringObstacleStatus.Continuing;
diff --git a/Content.Server/Nuke/NukeSystem.cs b/Content.Server/Nuke/NukeSystem.cs
index 47e10929a3..fa18297a64 100644
--- a/Content.Server/Nuke/NukeSystem.cs
+++ b/Content.Server/Nuke/NukeSystem.cs
@@ -2,7 +2,6 @@ using Content.Server.AlertLevel;
using Content.Server.Audio;
using Content.Server.Chat.Systems;
using Content.Server.Coordinates.Helpers;
-using Content.Server.DoAfter;
using Content.Server.Explosion.EntitySystems;
using Content.Server.Popups;
using Content.Server.Station.Systems;
@@ -28,7 +27,7 @@ namespace Content.Server.Nuke
[Dependency] private readonly StationSystem _stationSystem = default!;
[Dependency] private readonly ServerGlobalSoundSystem _soundSystem = default!;
[Dependency] private readonly ChatSystem _chatSystem = default!;
- [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly UserInterfaceSystem _ui = default!;
@@ -67,7 +66,7 @@ namespace Content.Server.Nuke
SubscribeLocalEvent(OnEnterButtonPressed);
// Doafter events
- SubscribeLocalEvent(OnDoAfter);
+ SubscribeLocalEvent(OnDoAfter);
}
private void OnInit(EntityUid uid, NukeComponent component, ComponentInit args)
@@ -559,16 +558,17 @@ namespace Content.Server.Nuke
private void DisarmBombDoafter(EntityUid uid, EntityUid user, NukeComponent nuke)
{
- var doafter = new DoAfterEventArgs(user, nuke.DisarmDoafterLength, target: uid)
+ var doafter = new DoAfterArgs(user, nuke.DisarmDoafterLength, new NukeDisarmDoAfterEvent(), uid, target: uid)
{
BreakOnDamage = true,
- BreakOnStun = true,
BreakOnTargetMove = true,
BreakOnUserMove = true,
NeedHand = true
};
- _doAfterSystem.DoAfter(doafter);
+ if (!_doAfterSystem.TryStartDoAfter(doafter))
+ return;
+
_popups.PopupEntity(Loc.GetString("nuke-component-doafter-warning"), user,
user, PopupType.LargeCaution);
}
diff --git a/Content.Server/Nutrition/Components/DrinkComponent.cs b/Content.Server/Nutrition/Components/DrinkComponent.cs
index 60784ac412..7bc1913fe2 100644
--- a/Content.Server/Nutrition/Components/DrinkComponent.cs
+++ b/Content.Server/Nutrition/Components/DrinkComponent.cs
@@ -1,4 +1,5 @@
using Content.Server.Nutrition.EntitySystems;
+using Content.Shared.DoAfter;
using Content.Shared.FixedPoint;
using JetBrains.Annotations;
using Robust.Shared.Audio;
@@ -34,19 +35,6 @@ namespace Content.Server.Nutrition.Components
[DataField("burstSound")]
public SoundSpecifier BurstSound = new SoundPathSpecifier("/Audio/Effects/flash_bang.ogg");
- ///
- /// Is this drink being forced on someone else?
- ///
- ///
- [DataField("forceDrink")]
- public bool ForceDrink;
-
- ///
- /// Is the entity currently drinking or trying to make someone else drink?
- ///
- [DataField("drinking")]
- public bool Drinking;
-
///
/// How long it takes to drink this yourself.
///
diff --git a/Content.Server/Nutrition/Components/FoodComponent.cs b/Content.Server/Nutrition/Components/FoodComponent.cs
index 7e9effdfda..eb76cbbf55 100644
--- a/Content.Server/Nutrition/Components/FoodComponent.cs
+++ b/Content.Server/Nutrition/Components/FoodComponent.cs
@@ -1,5 +1,6 @@
using Content.Server.Chemistry.EntitySystems;
using Content.Server.Nutrition.EntitySystems;
+using Content.Shared.DoAfter;
using Content.Shared.FixedPoint;
using Robust.Shared.Audio;
using Robust.Shared.Prototypes;
@@ -40,18 +41,6 @@ namespace Content.Server.Nutrition.Components
[DataField("eatMessage")]
public string EatMessage = "food-nom";
- ///
- /// Is this entity being forcefed?
- ///
- [DataField("forceFeed")]
- public bool ForceFeed;
-
- ///
- /// Is this entity eating or being fed?
- ///
- [DataField(("eating"))]
- public bool Eating;
-
///
/// How long it takes to eat the food personally.
///
diff --git a/Content.Server/Nutrition/EntitySystems/DrinkSystem.cs b/Content.Server/Nutrition/EntitySystems/DrinkSystem.cs
index 933efc268a..21ab837b48 100644
--- a/Content.Server/Nutrition/EntitySystems/DrinkSystem.cs
+++ b/Content.Server/Nutrition/EntitySystems/DrinkSystem.cs
@@ -2,7 +2,6 @@ using Content.Server.Body.Components;
using Content.Server.Body.Systems;
using Content.Server.Chemistry.Components.SolutionManager;
using Content.Server.Chemistry.EntitySystems;
-using Content.Server.DoAfter;
using Content.Server.Fluids.EntitySystems;
using Content.Server.Forensics;
using Content.Server.Nutrition.Components;
@@ -10,7 +9,6 @@ using Content.Server.Popups;
using Content.Shared.Administration.Logs;
using Content.Shared.Body.Components;
using Content.Shared.Chemistry;
-using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.Database;
using Content.Shared.DoAfter;
@@ -21,6 +19,7 @@ using Content.Shared.Interaction;
using Content.Shared.Interaction.Events;
using Content.Shared.Mobs.Components;
using Content.Shared.Mobs.Systems;
+using Content.Shared.Nutrition;
using Content.Shared.Nutrition.Components;
using Content.Shared.Throwing;
using Content.Shared.Verbs;
@@ -42,7 +41,7 @@ namespace Content.Server.Nutrition.EntitySystems
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly BodySystem _bodySystem = default!;
[Dependency] private readonly StomachSystem _stomachSystem = default!;
- [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
[Dependency] private readonly SpillableSystem _spillableSystem = default!;
@@ -55,6 +54,7 @@ namespace Content.Server.Nutrition.EntitySystems
{
base.Initialize();
+ // TODO add InteractNoHandEvent for entities like mice.
SubscribeLocalEvent(OnSolutionChange);
SubscribeLocalEvent(OnDrinkInit);
SubscribeLocalEvent(HandleLand);
@@ -63,7 +63,7 @@ namespace Content.Server.Nutrition.EntitySystems
SubscribeLocalEvent>(AddDrinkVerb);
SubscribeLocalEvent(OnExamined);
SubscribeLocalEvent(OnTransferAttempt);
- SubscribeLocalEvent>(OnDoAfter);
+ SubscribeLocalEvent(OnDoAfter);
}
public bool IsEmpty(EntityUid uid, DrinkComponent? component = null)
@@ -218,7 +218,7 @@ namespace Content.Server.Nutrition.EntitySystems
private bool TryDrink(EntityUid user, EntityUid target, DrinkComponent drink, EntityUid item)
{
- if (!EntityManager.HasComponent(target) || drink.Drinking)
+ if (!EntityManager.HasComponent(target))
return false;
if (!drink.Opened)
@@ -236,16 +236,18 @@ namespace Content.Server.Nutrition.EntitySystems
return true;
}
+ if (drinkSolution.Name == null)
+ return false;
+
if (_foodSystem.IsMouthBlocked(target, user))
return true;
if (!_interactionSystem.InRangeUnobstructed(user, item, popup: true))
return true;
- drink.Drinking = true;
- drink.ForceDrink = user != target;
+ var forceDrink = user != target;
- if (drink.ForceDrink)
+ if (forceDrink)
{
var userName = Identity.Entity(user, EntityManager);
@@ -263,53 +265,51 @@ namespace Content.Server.Nutrition.EntitySystems
var flavors = _flavorProfileSystem.GetLocalizedFlavorsMessage(user, drinkSolution);
- var drinkData = new DrinkData(drinkSolution, flavors);
-
- var doAfterEventArgs = new DoAfterEventArgs(user, drink.ForceDrink ? drink.ForceFeedDelay : drink.Delay,
- target: target, used: item)
+ var doAfterEventArgs = new DoAfterArgs(
+ user,
+ forceDrink ? drink.ForceFeedDelay : drink.Delay,
+ new ConsumeDoAfterEvent(drinkSolution.Name, flavors),
+ eventTarget: item,
+ target: target,
+ used: item)
{
- RaiseOnTarget = user != target,
- RaiseOnUser = false,
- BreakOnUserMove = drink.ForceDrink,
+ BreakOnUserMove = forceDrink,
BreakOnDamage = true,
- BreakOnStun = true,
- BreakOnTargetMove = drink.ForceDrink,
+ BreakOnTargetMove = forceDrink,
MovementThreshold = 0.01f,
DistanceThreshold = 1.0f,
- NeedHand = true
+ // Mice and the like can eat without hands.
+ // TODO maybe set this based on some CanEatWithoutHands event or component?
+ NeedHand = forceDrink,
};
- _doAfterSystem.DoAfter(doAfterEventArgs, drinkData);
-
+ _doAfterSystem.TryStartDoAfter(doAfterEventArgs);
return true;
}
///
/// Raised directed at a victim when someone has force fed them a drink.
///
- private void OnDoAfter(EntityUid uid, DrinkComponent component, DoAfterEvent args)
+ private void OnDoAfter(EntityUid uid, DrinkComponent component, ConsumeDoAfterEvent args)
{
- if (args.Cancelled)
- {
- component.ForceDrink = false;
- component.Drinking = false;
- return;
- }
-
- if (args.Handled || component.Deleted)
+ if (args.Handled || args.Cancelled || component.Deleted)
return;
if (!TryComp(args.Args.Target, out var body))
return;
- component.Drinking = false;
+ if (!_solutionContainerSystem.TryGetSolution(args.Used, args.Solution, out var solution))
+ return;
- var transferAmount = FixedPoint2.Min(component.TransferAmount, args.AdditionalData.DrinkSolution.Volume);
- var drained = _solutionContainerSystem.Drain(uid, args.AdditionalData.DrinkSolution, transferAmount);
+ var transferAmount = FixedPoint2.Min(component.TransferAmount, solution.Volume);
+ var drained = _solutionContainerSystem.Drain(uid, solution, transferAmount);
+ var forceDrink = args.User != args.Target;
+
+ //var forceDrink = args.Args.Target.Value != args.Args.User;
if (!_bodySystem.TryGetBodyOrganComponents(args.Args.Target.Value, out var stomachs, body))
{
- _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);
+ _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);
if (HasComp(args.Args.Target.Value))
{
@@ -318,7 +318,7 @@ namespace Content.Server.Nutrition.EntitySystems
return;
}
- _solutionContainerSystem.Refill(args.Args.Target.Value, args.AdditionalData.DrinkSolution, drained);
+ _solutionContainerSystem.Refill(args.Args.Target.Value, solution, drained);
args.Handled = true;
return;
}
@@ -330,21 +330,21 @@ 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 (component.ForceDrink)
+ if (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");
}
else
- _solutionContainerSystem.TryAddSolution(uid, args.AdditionalData.DrinkSolution, drained);
+ _solutionContainerSystem.TryAddSolution(uid, solution, drained);
args.Handled = true;
return;
}
- var flavors = args.AdditionalData.FlavorMessage;
+ var flavors = args.FlavorMessage;
- if (component.ForceDrink)
+ if (forceDrink)
{
var targetName = Identity.Entity(args.Args.Target.Value, EntityManager);
var userName = Identity.Entity(args.Args.User, EntityManager);
@@ -372,11 +372,9 @@ namespace Content.Server.Nutrition.EntitySystems
_audio.PlayPvs(_audio.GetSound(component.UseSound), args.Args.Target.Value, AudioParams.Default.WithVolume(-2f));
- _reaction.DoEntityReaction(args.Args.Target.Value, args.AdditionalData.DrinkSolution, ReactionMethod.Ingestion);
+ _reaction.DoEntityReaction(args.Args.Target.Value, solution, ReactionMethod.Ingestion);
//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;
var comp = EnsureComp(uid);
@@ -421,11 +419,5 @@ namespace Content.Server.Nutrition.EntitySystems
return remainingString;
}
-
- private record struct DrinkData(Solution DrinkSolution, string FlavorMessage)
- {
- public readonly Solution DrinkSolution = DrinkSolution;
- public readonly string FlavorMessage = FlavorMessage;
- }
}
}
diff --git a/Content.Server/Nutrition/EntitySystems/FoodSystem.cs b/Content.Server/Nutrition/EntitySystems/FoodSystem.cs
index f7f9358cee..30cd1c8ba6 100644
--- a/Content.Server/Nutrition/EntitySystems/FoodSystem.cs
+++ b/Content.Server/Nutrition/EntitySystems/FoodSystem.cs
@@ -1,14 +1,12 @@
using Content.Server.Body.Components;
using Content.Server.Body.Systems;
using Content.Server.Chemistry.EntitySystems;
-using Content.Server.DoAfter;
using Content.Server.Hands.Components;
using Content.Server.Nutrition.Components;
using Content.Server.Popups;
using Content.Shared.Administration.Logs;
using Content.Shared.Body.Components;
using Content.Shared.Chemistry;
-using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.Database;
using Content.Shared.DoAfter;
@@ -20,6 +18,7 @@ using Content.Shared.Interaction.Events;
using Content.Shared.Inventory;
using Content.Shared.Mobs.Components;
using Content.Shared.Mobs.Systems;
+using Content.Shared.Nutrition;
using Content.Shared.Verbs;
using Robust.Shared.Audio;
using Robust.Shared.Player;
@@ -39,7 +38,7 @@ namespace Content.Server.Nutrition.EntitySystems
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
[Dependency] private readonly UtensilSystem _utensilSystem = default!;
- [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
[Dependency] private readonly InventorySystem _inventorySystem = default!;
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
@@ -51,10 +50,11 @@ namespace Content.Server.Nutrition.EntitySystems
{
base.Initialize();
+ // TODO add InteractNoHandEvent for entities like mice.
SubscribeLocalEvent(OnUseFoodInHand);
SubscribeLocalEvent(OnFeedFood);
SubscribeLocalEvent>(AddEatVerb);
- SubscribeLocalEvent>(OnDoAfter);
+ SubscribeLocalEvent(OnDoAfter);
SubscribeLocalEvent(OnInventoryIngestAttempt);
}
@@ -66,7 +66,8 @@ namespace Content.Server.Nutrition.EntitySystems
if (ev.Handled)
return;
- ev.Handled = TryFeed(ev.User, ev.User, uid, foodComponent);
+ ev.Handled = true;
+ TryFeed(ev.User, ev.User, uid, foodComponent);
}
///
@@ -77,7 +78,8 @@ namespace Content.Server.Nutrition.EntitySystems
if (args.Handled || args.Target == null || !args.CanReach)
return;
- args.Handled = TryFeed(args.User, args.Target.Value, uid, foodComponent);
+ args.Handled = true;
+ TryFeed(args.User, args.Target.Value, uid, foodComponent);
}
public bool TryFeed(EntityUid user, EntityUid target, EntityUid food, FoodComponent foodComp)
@@ -87,10 +89,10 @@ namespace Content.Server.Nutrition.EntitySystems
return false;
// Target can't be fed or they're already eating
- if (!EntityManager.HasComponent(target) || foodComp.Eating)
+ if (!EntityManager.HasComponent(target))
return false;
- if (!_solutionContainerSystem.TryGetSolution(food, foodComp.SolutionName, out var foodSolution))
+ if (!_solutionContainerSystem.TryGetSolution(food, foodComp.SolutionName, out var foodSolution) || foodSolution.Name == null)
return false;
var flavors = _flavorProfileSystem.GetLocalizedFlavorsMessage(food, user, foodSolution);
@@ -105,16 +107,15 @@ namespace Content.Server.Nutrition.EntitySystems
if (IsMouthBlocked(target, user))
return false;
- if (!TryGetRequiredUtensils(user, foodComp, out var utensils))
- return false;
-
if (!_interactionSystem.InRangeUnobstructed(user, food, popup: true))
return true;
- foodComp.Eating = true;
- foodComp.ForceFeed = user != target;
+ if (!TryGetRequiredUtensils(user, foodComp, out _))
+ return true;
- if (foodComp.ForceFeed)
+ var forceFeed = user != target;
+
+ if (forceFeed)
{
var userName = Identity.Entity(user, EntityManager);
_popupSystem.PopupEntity(Loc.GetString("food-system-force-feed", ("user", userName)),
@@ -129,38 +130,31 @@ namespace Content.Server.Nutrition.EntitySystems
_adminLogger.Add(LogType.Ingestion, LogImpact.Low, $"{ToPrettyString(target):target} is eating {ToPrettyString(food):food} {SolutionContainerSystem.ToPrettyString(foodSolution)}");
}
- var foodData = new FoodData(foodSolution, flavors, utensils);
-
- var doAfterEventArgs = new DoAfterEventArgs(user, foodComp.ForceFeed ? foodComp.ForceFeedDelay : foodComp.Delay, target: target, used: food)
+ var doAfterEventArgs = new DoAfterArgs(
+ user,
+ forceFeed ? foodComp.ForceFeedDelay : foodComp.Delay,
+ new ConsumeDoAfterEvent(foodSolution.Name, flavors),
+ eventTarget: food,
+ target: target,
+ used: food)
{
- RaiseOnTarget = foodComp.ForceFeed,
- RaiseOnUser = false, //causes a crash if mice eat if true
- BreakOnUserMove = foodComp.ForceFeed,
+ BreakOnUserMove = forceFeed,
BreakOnDamage = true,
- BreakOnStun = true,
- BreakOnTargetMove = foodComp.ForceFeed,
+ BreakOnTargetMove = forceFeed,
MovementThreshold = 0.01f,
DistanceThreshold = 1.0f,
- NeedHand = true
+ // Mice and the like can eat without hands.
+ // TODO maybe set this based on some CanEatWithoutHands event or component?
+ NeedHand = forceFeed,
};
- _doAfterSystem.DoAfter(doAfterEventArgs, foodData);
-
+ _doAfterSystem.TryStartDoAfter(doAfterEventArgs);
return true;
-
}
- private void OnDoAfter(EntityUid uid, FoodComponent component, DoAfterEvent args)
+ private void OnDoAfter(EntityUid uid, FoodComponent component, ConsumeDoAfterEvent args)
{
- //Prevents the target from being force fed food but allows the user to chow down
- if (args.Cancelled)
- {
- component.Eating = false;
- component.ForceFeed = false;
- return;
- }
-
- if (args.Handled || component.Deleted || args.Args.Target == null)
+ if (args.Cancelled || args.Handled || component.Deleted || args.Args.Target == null)
return;
if (!TryComp(args.Args.Target.Value, out var body))
@@ -169,29 +163,36 @@ namespace Content.Server.Nutrition.EntitySystems
if (!_bodySystem.TryGetBodyOrganComponents(args.Args.Target.Value, out var stomachs, body))
return;
- component.Eating = false;
+ if (!_solutionContainerSystem.TryGetSolution(args.Used, args.Solution, out var solution))
+ return;
- var transferAmount = component.TransferAmount != null ? FixedPoint2.Min((FixedPoint2) component.TransferAmount, args.AdditionalData.FoodSolution.Volume) : args.AdditionalData.FoodSolution.Volume;
+ if (!TryGetRequiredUtensils(args.User, component, out var utensils))
+ return;
- var split = _solutionContainerSystem.SplitSolution(uid, args.AdditionalData.FoodSolution, transferAmount);
+ args.Handled = true;
+
+ var transferAmount = component.TransferAmount != null ? FixedPoint2.Min((FixedPoint2) component.TransferAmount, solution.Volume) : solution.Volume;
+
+ var split = _solutionContainerSystem.SplitSolution(uid, solution, transferAmount);
//TODO: Get the stomach UID somehow without nabbing owner
var firstStomach = stomachs.FirstOrNull(stomach => _stomachSystem.CanTransferSolution(stomach.Comp.Owner, split));
+ var forceFeed = args.User != args.Target;
+
// No stomach so just popup a message that they can't eat.
if (firstStomach == null)
{
- _solutionContainerSystem.TryAddSolution(uid, args.AdditionalData.FoodSolution, split);
- _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;
+ _solutionContainerSystem.TryAddSolution(uid, solution, 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);
return;
}
- _reaction.DoEntityReaction(args.Args.Target.Value, args.AdditionalData.FoodSolution, ReactionMethod.Ingestion);
+ _reaction.DoEntityReaction(args.Args.Target.Value, solution, ReactionMethod.Ingestion);
_stomachSystem.TryTransferSolution(firstStomach.Value.Comp.Owner, split, firstStomach.Value.Comp);
- var flavors = args.AdditionalData.FlavorMessage;
+ var flavors = args.FlavorMessage;
- if (component.ForceFeed)
+ if (forceFeed)
{
var targetName = Identity.Entity(args.Args.Target.Value, EntityManager);
var userName = Identity.Entity(args.Args.User, EntityManager);
@@ -202,7 +203,6 @@ namespace Content.Server.Nutrition.EntitySystems
// log successful force feed
_adminLogger.Add(LogType.ForceFeed, LogImpact.Medium, $"{ToPrettyString(uid):user} forced {ToPrettyString(args.Args.User):target} to eat {ToPrettyString(uid):food}");
- component.ForceFeed = false;
}
else
{
@@ -215,26 +215,19 @@ namespace Content.Server.Nutrition.EntitySystems
_audio.Play(component.UseSound, Filter.Pvs(args.Args.Target.Value), args.Args.Target.Value, true, AudioParams.Default.WithVolume(-1f));
// Try to break all used utensils
- //TODO: Replace utensil owner with actual UID
- foreach (var utensil in args.AdditionalData.Utensils)
+ foreach (var utensil in utensils)
{
- _utensilSystem.TryBreak(utensil.Owner, args.Args.User);
+ _utensilSystem.TryBreak(utensil, args.Args.User);
}
if (component.UsesRemaining > 0)
- {
- args.Handled = true;
return;
- }
-
if (string.IsNullOrEmpty(component.TrashPrototype))
EntityManager.QueueDeleteEntity(uid);
else
DeleteAndSpawnTrash(component, uid, args.Args.User);
-
- args.Handled = true;
}
private void DeleteAndSpawnTrash(FoodComponent component, EntityUid food, EntityUid? user = null)
@@ -329,9 +322,9 @@ namespace Content.Server.Nutrition.EntitySystems
}
private bool TryGetRequiredUtensils(EntityUid user, FoodComponent component,
- out List utensils, HandsComponent? hands = null)
+ out List utensils, HandsComponent? hands = null)
{
- utensils = new List();
+ utensils = new List();
if (component.Utensil != UtensilType.None)
return true;
@@ -352,7 +345,7 @@ namespace Content.Server.Nutrition.EntitySystems
{
// Add to used list
usedTypes |= utensil.Types;
- utensils.Add(utensil);
+ utensils.Add(item);
}
}
@@ -415,12 +408,5 @@ namespace Content.Server.Nutrition.EntitySystems
return attempt.Cancelled;
}
-
- private record struct FoodData(Solution FoodSolution, string FlavorMessage, List Utensils)
- {
- public readonly Solution FoodSolution = FoodSolution;
- public readonly string FlavorMessage = FlavorMessage;
- public readonly List Utensils = Utensils;
- }
}
}
diff --git a/Content.Server/Power/EntitySystems/ApcSystem.cs b/Content.Server/Power/EntitySystems/ApcSystem.cs
index 691ba32d8a..183422aa21 100644
--- a/Content.Server/Power/EntitySystems/ApcSystem.cs
+++ b/Content.Server/Power/EntitySystems/ApcSystem.cs
@@ -4,11 +4,13 @@ using Content.Server.Power.Components;
using Content.Shared.Access.Components;
using Content.Shared.Access.Systems;
using Content.Shared.APC;
+using Content.Shared.DoAfter;
using Content.Shared.Emag.Components;
using Content.Shared.Emag.Systems;
using Content.Shared.Examine;
using Content.Shared.Interaction;
using Content.Shared.Popups;
+using Content.Shared.Power;
using Content.Shared.Tools;
using Content.Shared.Tools.Components;
using JetBrains.Annotations;
@@ -28,6 +30,7 @@ namespace Content.Server.Power.EntitySystems
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly SharedToolSystem _toolSystem = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
+ [Dependency] private readonly SharedAudioSystem _audio = default!;
private const float ScrewTime = 2f;
@@ -43,7 +46,7 @@ namespace Content.Server.Power.EntitySystems
SubscribeLocalEvent(OnToggleMainBreaker);
SubscribeLocalEvent(OnEmagged);
- SubscribeLocalEvent(OnToolFinished);
+ SubscribeLocalEvent(OnToolFinished);
SubscribeLocalEvent(OnInteractUsing);
SubscribeLocalEvent(OnExamine);
@@ -220,27 +223,21 @@ namespace Content.Server.Power.EntitySystems
if (!EntityManager.TryGetComponent(args.Used, out ToolComponent? tool))
return;
- var toolEvData = new ToolEventData(new ApcToolFinishedEvent(uid), fuel: 0f);
-
- if (_toolSystem.UseTool(args.Used, args.User, uid, ScrewTime, new [] { "Screwing" }, toolEvData, toolComponent:tool))
+ if (_toolSystem.UseTool(args.Used, args.User, uid, ScrewTime, "Screwing", new ApcToolFinishedEvent(), toolComponent:tool))
args.Handled = true;
}
- private void OnToolFinished(ApcToolFinishedEvent args)
+ private void OnToolFinished(EntityUid uid, ApcComponent component, ApcToolFinishedEvent args)
{
- if (!EntityManager.TryGetComponent(args.Target, out ApcComponent? component))
+ if (!args.Cancelled)
return;
+
component.IsApcOpen = !component.IsApcOpen;
+ UpdatePanelAppearance(uid, apc: component);
- if (TryComp(args.Target, out AppearanceComponent? appearance))
- {
- UpdatePanelAppearance(args.Target, appearance);
- }
-
- if (component.IsApcOpen)
- SoundSystem.Play(component.ScrewdriverOpenSound.GetSound(), Filter.Pvs(args.Target), args.Target);
- else
- SoundSystem.Play(component.ScrewdriverCloseSound.GetSound(), Filter.Pvs(args.Target), args.Target);
+ // this will play on top of the normal screw driver tool sound.
+ var sound = component.IsApcOpen ? component.ScrewdriverOpenSound : component.ScrewdriverCloseSound;
+ _audio.PlayPvs(sound, uid);
}
private void UpdatePanelAppearance(EntityUid uid, AppearanceComponent? appearance = null, ApcComponent? apc = null)
@@ -251,16 +248,6 @@ namespace Content.Server.Power.EntitySystems
_appearance.SetData(uid, ApcVisuals.PanelState, GetPanelState(apc), appearance);
}
- private sealed class ApcToolFinishedEvent : EntityEventArgs
- {
- public EntityUid Target { get; }
-
- public ApcToolFinishedEvent(EntityUid target)
- {
- Target = target;
- }
- }
-
private void OnExamine(EntityUid uid, ApcComponent component, ExaminedEvent args)
{
args.PushMarkup(Loc.GetString(component.IsApcOpen
diff --git a/Content.Server/Power/EntitySystems/CableSystem.cs b/Content.Server/Power/EntitySystems/CableSystem.cs
index eead07f34d..8dd09fab35 100644
--- a/Content.Server/Power/EntitySystems/CableSystem.cs
+++ b/Content.Server/Power/EntitySystems/CableSystem.cs
@@ -3,6 +3,7 @@ using Content.Server.Electrocution;
using Content.Server.Power.Components;
using Content.Server.Stack;
using Content.Shared.Database;
+using Content.Shared.DoAfter;
using Content.Shared.Interaction;
using Content.Shared.Tools;
using Content.Shared.Tools.Components;
@@ -26,7 +27,7 @@ public sealed partial class CableSystem : EntitySystem
InitializeCablePlacer();
SubscribeLocalEvent(OnInteractUsing);
- SubscribeLocalEvent(OnCableCut);
+ SubscribeLocalEvent(OnCableCut);
// Shouldn't need re-anchoring.
SubscribeLocalEvent(OnAnchorChanged);
}
@@ -36,12 +37,14 @@ public sealed partial class CableSystem : EntitySystem
if (args.Handled)
return;
- var toolEvData = new ToolEventData(new CuttingFinishedEvent(args.User), targetEntity: uid);
- args.Handled = _toolSystem.UseTool(args.Used, args.User, uid, cable.CuttingDelay, new[] { cable.CuttingQuality }, toolEvData);
+ args.Handled = _toolSystem.UseTool(args.Used, args.User, uid, cable.CuttingDelay, cable.CuttingQuality, new CableCuttingFinishedEvent());
}
- private void OnCableCut(EntityUid uid, CableComponent cable, CuttingFinishedEvent args)
+ private void OnCableCut(EntityUid uid, CableComponent cable, DoAfterEvent args)
{
+ if (args.Cancelled)
+ return;
+
if (_electrocutionSystem.TryDoElectrifiedAct(uid, args.User))
return;
@@ -67,13 +70,3 @@ public sealed partial class CableSystem : EntitySystem
QueueDel(uid);
}
}
-
-public sealed class CuttingFinishedEvent : EntityEventArgs
-{
- public EntityUid User;
-
- public CuttingFinishedEvent(EntityUid user)
- {
- User = user;
- }
-}
diff --git a/Content.Server/RCD/Components/RCDComponent.cs b/Content.Server/RCD/Components/RCDComponent.cs
index 23c8009d56..5375ae71b7 100644
--- a/Content.Server/RCD/Components/RCDComponent.cs
+++ b/Content.Server/RCD/Components/RCDComponent.cs
@@ -39,7 +39,5 @@ namespace Content.Server.RCD.Components
///
[ViewVariables(VVAccess.ReadWrite)] [DataField("ammo")]
public int CurrentAmmo = DefaultAmmoCount;
-
- public CancellationTokenSource? CancelToken = null;
}
}
diff --git a/Content.Server/RCD/Systems/RCDSystem.cs b/Content.Server/RCD/Systems/RCDSystem.cs
index 38c4e0f36a..b1b674a0aa 100644
--- a/Content.Server/RCD/Systems/RCDSystem.cs
+++ b/Content.Server/RCD/Systems/RCDSystem.cs
@@ -1,6 +1,4 @@
-using System.Threading;
using Content.Server.Administration.Logs;
-using Content.Server.DoAfter;
using Content.Server.Popups;
using Content.Server.RCD.Components;
using Content.Shared.Database;
@@ -23,7 +21,7 @@ namespace Content.Server.RCD.Systems
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
- [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
[Dependency] private readonly PopupSystem _popup = default!;
[Dependency] private readonly TagSystem _tagSystem = default!;
@@ -59,14 +57,6 @@ namespace Content.Server.RCD.Systems
if (args.Handled || !args.CanReach)
return;
- if (rcd.CancelToken != null)
- {
- rcd.CancelToken?.Cancel();
- rcd.CancelToken = null;
- args.Handled = true;
- return;
- }
-
if (!args.ClickLocation.IsValid(EntityManager)) return;
var clickLocationMod = args.ClickLocation;
@@ -96,19 +86,15 @@ namespace Content.Server.RCD.Systems
var user = args.User;
//Using an RCD isn't instantaneous
- rcd.CancelToken = new CancellationTokenSource();
- var doAfterEventArgs = new DoAfterEventArgs(user, rcd.Delay, rcd.CancelToken.Token, args.Target)
+ var doAfterEventArgs = new DoAfterArgs(user, rcd.Delay, new AwaitedDoAfterEvent(), null, target: args.Target)
{
BreakOnDamage = true,
- BreakOnStun = true,
NeedHand = true,
ExtraCheck = () => IsRCDStillValid(rcd, args, mapGrid, tile, startingMode) //All of the sanity checks are here
};
var result = await _doAfterSystem.WaitDoAfter(doAfterEventArgs);
- rcd.CancelToken = null;
-
if (result == DoAfterStatus.Cancelled)
return;
diff --git a/Content.Server/Repairable/RepairableSystem.cs b/Content.Server/Repairable/RepairableSystem.cs
index bf7593185d..56f1eb0903 100644
--- a/Content.Server/Repairable/RepairableSystem.cs
+++ b/Content.Server/Repairable/RepairableSystem.cs
@@ -1,14 +1,16 @@
using Content.Server.Administration.Logs;
using Content.Shared.Damage;
using Content.Shared.Database;
+using Content.Shared.DoAfter;
using Content.Shared.Interaction;
using Content.Shared.Popups;
+using Content.Shared.Repairable;
using Content.Shared.Tools;
using Content.Shared.Tools.Components;
namespace Content.Server.Repairable
{
- public sealed class RepairableSystem : EntitySystem
+ public sealed class RepairableSystem : SharedRepairableSystem
{
[Dependency] private readonly SharedToolSystem _toolSystem = default!;
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
@@ -22,6 +24,9 @@ namespace Content.Server.Repairable
private void OnRepairFinished(EntityUid uid, RepairableComponent component, RepairFinishedEvent args)
{
+ if (args.Cancelled)
+ return;
+
if (!EntityManager.TryGetComponent(uid, out DamageableComponent? damageable) || damageable.TotalDamage == 0)
return;
@@ -38,15 +43,17 @@ namespace Content.Server.Repairable
_adminLogger.Add(LogType.Healed, $"{ToPrettyString(args.User):user} repaired {ToPrettyString(uid):target} back to full health");
}
-
uid.PopupMessage(args.User,
Loc.GetString("comp-repairable-repair",
("target", uid),
- ("tool", args.Used)));
+ ("tool", args.Used!)));
}
public async void Repair(EntityUid uid, RepairableComponent component, InteractUsingEvent args)
{
+ if (args.Handled)
+ return;
+
// Only try repair the target if it is damaged
if (!EntityManager.TryGetComponent(uid, out DamageableComponent? damageable) || damageable.TotalDamage == 0)
return;
@@ -57,25 +64,8 @@ namespace Content.Server.Repairable
if (args.User == args.Target)
delay *= component.SelfRepairPenalty;
- var toolEvData = new ToolEventData(new RepairFinishedEvent(args.User, args.Used), component.FuelCost, targetEntity:uid);
-
// Can the tool actually repair this, does it have enough fuel?
- if (!_toolSystem.UseTool(args.Used, args.User, uid, delay, component.QualityNeeded, toolEvData, component.FuelCost))
- return;
-
- args.Handled = true;
- }
- }
-
- public sealed class RepairFinishedEvent : EntityEventArgs
- {
- public EntityUid User;
- public EntityUid Used;
-
- public RepairFinishedEvent(EntityUid user, EntityUid used)
- {
- User = user;
- Used = used;
+ args.Handled = !_toolSystem.UseTool(args.Used, args.User, uid, delay, component.QualityNeeded, new RepairFinishedEvent(), component.FuelCost);
}
}
}
diff --git a/Content.Server/Resist/CanEscapeInventoryComponent.cs b/Content.Server/Resist/CanEscapeInventoryComponent.cs
index b67adfc203..6572eca330 100644
--- a/Content.Server/Resist/CanEscapeInventoryComponent.cs
+++ b/Content.Server/Resist/CanEscapeInventoryComponent.cs
@@ -1,4 +1,4 @@
-using System.Threading;
+using Content.Shared.DoAfter;
namespace Content.Server.Resist;
@@ -11,8 +11,8 @@ public sealed class CanEscapeInventoryComponent : Component
[DataField("baseResistTime")]
public float BaseResistTime = 5f;
- [DataField("isEscaping")]
- public bool IsEscaping;
+ public bool IsEscaping => DoAfter != null;
- public CancellationTokenSource? CancelToken;
+ [DataField("doAfter")]
+ public DoAfterId? DoAfter;
}
diff --git a/Content.Server/Resist/EscapeInventorySystem.cs b/Content.Server/Resist/EscapeInventorySystem.cs
index 6230b16fc6..43012d8b7e 100644
--- a/Content.Server/Resist/EscapeInventorySystem.cs
+++ b/Content.Server/Resist/EscapeInventorySystem.cs
@@ -1,5 +1,3 @@
-using System.Threading;
-using Content.Server.DoAfter;
using Content.Server.Contests;
using Robust.Shared.Containers;
using Content.Server.Popups;
@@ -10,12 +8,13 @@ using Content.Shared.ActionBlocker;
using Content.Shared.DoAfter;
using Content.Shared.Movement.Events;
using Content.Shared.Interaction.Events;
+using Content.Shared.Resist;
namespace Content.Server.Resist;
public sealed class EscapeInventorySystem : EntitySystem
{
- [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
[Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!;
@@ -32,7 +31,7 @@ public sealed class EscapeInventorySystem : EntitySystem
base.Initialize();
SubscribeLocalEvent(OnRelayMovement);
- SubscribeLocalEvent>(OnEscape);
+ SubscribeLocalEvent(OnEscape);
SubscribeLocalEvent(OnDropped);
}
@@ -69,50 +68,37 @@ public sealed class EscapeInventorySystem : EntitySystem
if (component.IsEscaping)
return;
- component.CancelToken = new CancellationTokenSource();
- component.IsEscaping = true;
- var escapeEvent = new EscapeInventoryEvent();
- var doAfterEventArgs = new DoAfterEventArgs(user, component.BaseResistTime * multiplier, cancelToken: component.CancelToken.Token, target:container)
+ var doAfterEventArgs = new DoAfterArgs(user, component.BaseResistTime * multiplier, new EscapeInventoryEvent(), user, target: container)
{
BreakOnTargetMove = false,
BreakOnUserMove = true,
BreakOnDamage = true,
- BreakOnStun = true,
NeedHand = false
};
+ if (!_doAfterSystem.TryStartDoAfter(doAfterEventArgs, out component.DoAfter))
+ return;
+
+ Dirty(component);
_popupSystem.PopupEntity(Loc.GetString("escape-inventory-component-start-resisting"), user, user);
_popupSystem.PopupEntity(Loc.GetString("escape-inventory-component-start-resisting-target"), container, container);
- _doAfterSystem.DoAfter(doAfterEventArgs, escapeEvent);
}
- private void OnEscape(EntityUid uid, CanEscapeInventoryComponent component, DoAfterEvent args)
+ private void OnEscape(EntityUid uid, CanEscapeInventoryComponent component, EscapeInventoryEvent args)
{
- if (args.Cancelled)
- {
- component.CancelToken = null;
- component.IsEscaping = false;
- return;
- }
+ component.DoAfter = null;
+ Dirty(component);
- if (args.Handled)
+ if (args.Handled || args.Cancelled)
return;
Transform(uid).AttachParentToContainerOrGrid(EntityManager);
-
- component.CancelToken = null;
- component.IsEscaping = false;
args.Handled = true;
}
private void OnDropped(EntityUid uid, CanEscapeInventoryComponent component, DroppedEvent args)
{
- component.CancelToken?.Cancel();
- component.CancelToken = null;
- }
-
- private sealed class EscapeInventoryEvent : EntityEventArgs
- {
-
+ if (component.DoAfter != null)
+ _doAfterSystem.Cancel(component.DoAfter);
}
}
diff --git a/Content.Server/Resist/ResistLockerComponent.cs b/Content.Server/Resist/ResistLockerComponent.cs
index 7cb2149100..52a4683abf 100644
--- a/Content.Server/Resist/ResistLockerComponent.cs
+++ b/Content.Server/Resist/ResistLockerComponent.cs
@@ -17,6 +17,4 @@ public sealed class ResistLockerComponent : Component
///
[ViewVariables]
public bool IsResisting = false;
-
- public CancellationTokenSource? CancelToken;
}
diff --git a/Content.Server/Resist/ResistLockerSystem.cs b/Content.Server/Resist/ResistLockerSystem.cs
index 78da7c012a..4b433073ca 100644
--- a/Content.Server/Resist/ResistLockerSystem.cs
+++ b/Content.Server/Resist/ResistLockerSystem.cs
@@ -1,5 +1,3 @@
-using System.Threading;
-using Content.Server.DoAfter;
using Content.Server.Popups;
using Content.Server.Storage.Components;
using Content.Server.Storage.EntitySystems;
@@ -7,13 +5,13 @@ using Content.Shared.DoAfter;
using Content.Shared.Lock;
using Content.Shared.Movement.Events;
using Content.Shared.Popups;
-using Robust.Shared.Containers;
+using Content.Shared.Resist;
namespace Content.Server.Resist;
public sealed class ResistLockerSystem : EntitySystem
{
- [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly LockSystem _lockSystem = default!;
[Dependency] private readonly EntityStorageSystem _entityStorage = default!;
@@ -22,8 +20,7 @@ public sealed class ResistLockerSystem : EntitySystem
{
base.Initialize();
SubscribeLocalEvent(OnRelayMovement);
- SubscribeLocalEvent>(OnDoAfter);
- SubscribeLocalEvent(OnRemoved);
+ SubscribeLocalEvent(OnDoAfter);
}
private void OnRelayMovement(EntityUid uid, ResistLockerComponent component, ref ContainerRelayMovementEntityEvent args)
@@ -45,34 +42,24 @@ public sealed class ResistLockerSystem : EntitySystem
if (!Resolve(target, ref storageComponent, ref resistLockerComponent))
return;
- resistLockerComponent.CancelToken = new CancellationTokenSource();
-
- var doAfterEventArgs = new DoAfterEventArgs(user, resistLockerComponent.ResistTime, cancelToken:resistLockerComponent.CancelToken.Token, target:target)
+ var doAfterEventArgs = new DoAfterArgs(user, resistLockerComponent.ResistTime, new ResistLockerDoAfterEvent(), target, target: target)
{
BreakOnTargetMove = false,
BreakOnUserMove = true,
BreakOnDamage = true,
- BreakOnStun = true,
NeedHand = false //No hands 'cause we be kickin'
};
resistLockerComponent.IsResisting = true;
_popupSystem.PopupEntity(Loc.GetString("resist-locker-component-start-resisting"), user, user, PopupType.Large);
- _doAfterSystem.DoAfter(doAfterEventArgs, new LockerDoAfterData());
+ _doAfterSystem.TryStartDoAfter(doAfterEventArgs);
}
- private void OnRemoved(EntityUid uid, ResistLockerComponent component, EntRemovedFromContainerMessage args)
- {
- component.CancelToken?.Cancel();
- component.CancelToken = null;
- }
-
- private void OnDoAfter(EntityUid uid, ResistLockerComponent component, DoAfterEvent args)
+ private void OnDoAfter(EntityUid uid, ResistLockerComponent component, DoAfterEvent args)
{
if (args.Cancelled)
{
component.IsResisting = false;
- component.CancelToken = null;
_popupSystem.PopupEntity(Loc.GetString("resist-locker-component-resist-interrupted"), args.Args.User, args.Args.User, PopupType.Medium);
return;
}
@@ -93,11 +80,6 @@ public sealed class ResistLockerSystem : EntitySystem
_entityStorage.TryOpenStorage(args.Args.User, uid);
}
- component.CancelToken = null;
args.Handled = true;
}
-
- private struct LockerDoAfterData
- {
- }
}
diff --git a/Content.Server/Revenant/EntitySystems/RevenantSystem.Abilities.cs b/Content.Server/Revenant/EntitySystems/RevenantSystem.Abilities.cs
index 7c3b1508e7..44313457f8 100644
--- a/Content.Server/Revenant/EntitySystems/RevenantSystem.Abilities.cs
+++ b/Content.Server/Revenant/EntitySystems/RevenantSystem.Abilities.cs
@@ -26,6 +26,7 @@ using Content.Shared.Mobs;
using Content.Shared.Mobs.Components;
using Content.Shared.Mobs.Systems;
using Content.Shared.Revenant.Components;
+using Content.Shared.Revenant.EntitySystems;
using Robust.Shared.Physics.Components;
using Robust.Shared.Utility;
@@ -46,8 +47,8 @@ public sealed partial class RevenantSystem
private void InitializeAbilities()
{
SubscribeLocalEvent(OnInteract);
- SubscribeLocalEvent>(OnSoulSearch);
- SubscribeLocalEvent>(OnHarvest);
+ SubscribeLocalEvent(OnSoulSearch);
+ SubscribeLocalEvent(OnHarvest);
SubscribeLocalEvent(OnDefileAction);
SubscribeLocalEvent(OnOverloadLightsAction);
@@ -84,17 +85,19 @@ public sealed partial class RevenantSystem
private void BeginSoulSearchDoAfter(EntityUid uid, EntityUid target, RevenantComponent revenant)
{
- _popup.PopupEntity(Loc.GetString("revenant-soul-searching", ("target", target)), uid, uid, PopupType.Medium);
- var soulSearchEvent = new SoulEvent();
- var searchDoAfter = new DoAfterEventArgs(uid, revenant.SoulSearchDuration, target:target)
+ var searchDoAfter = new DoAfterArgs(uid, revenant.SoulSearchDuration, new SoulEvent(), uid, target: target)
{
BreakOnUserMove = true,
DistanceThreshold = 2
};
- _doAfter.DoAfter(searchDoAfter, soulSearchEvent);
+
+ if (!_doAfter.TryStartDoAfter(searchDoAfter))
+ return;
+
+ _popup.PopupEntity(Loc.GetString("revenant-soul-searching", ("target", target)), uid, uid, PopupType.Medium);
}
- private void OnSoulSearch(EntityUid uid, RevenantComponent component, DoAfterEvent args)
+ private void OnSoulSearch(EntityUid uid, RevenantComponent component, SoulEvent args)
{
if (args.Handled || args.Cancelled)
return;
@@ -135,25 +138,25 @@ public sealed partial class RevenantSystem
return;
}
- var harvestEvent = new HarvestEvent();
-
- var doAfter = new DoAfterEventArgs(uid, revenant.HarvestDebuffs.X, target:target)
+ var doAfter = new DoAfterArgs(uid, revenant.HarvestDebuffs.X, new HarvestEvent(), uid, target: target)
{
DistanceThreshold = 2,
BreakOnUserMove = true,
- NeedHand = false
+ RequireCanInteract = false, // stuns itself
};
+ if (!_doAfter.TryStartDoAfter(doAfter))
+ return;
+
_appearance.SetData(uid, RevenantVisuals.Harvesting, true);
_popup.PopupEntity(Loc.GetString("revenant-soul-begin-harvest", ("target", target)),
target, PopupType.Large);
TryUseAbility(uid, revenant, 0, revenant.HarvestDebuffs);
- _doAfter.DoAfter(doAfter, harvestEvent);
}
- private void OnHarvest(EntityUid uid, RevenantComponent component, DoAfterEvent args)
+ private void OnHarvest(EntityUid uid, RevenantComponent component, HarvestEvent args)
{
if (args.Cancelled)
{
@@ -327,14 +330,4 @@ public sealed partial class RevenantSystem
_emag.DoEmagEffect(ent, ent); //it emags itself. spooky.
}
}
-
- private sealed class SoulEvent : EntityEventArgs
- {
-
- }
-
- private sealed class HarvestEvent : EntityEventArgs
- {
-
- }
}
diff --git a/Content.Server/Revenant/EntitySystems/RevenantSystem.cs b/Content.Server/Revenant/EntitySystems/RevenantSystem.cs
index b8d78f5803..968da8c269 100644
--- a/Content.Server/Revenant/EntitySystems/RevenantSystem.cs
+++ b/Content.Server/Revenant/EntitySystems/RevenantSystem.cs
@@ -3,7 +3,6 @@ using Content.Shared.Popups;
using Content.Shared.Alert;
using Content.Shared.Damage;
using Content.Shared.Interaction;
-using Content.Server.DoAfter;
using Content.Server.GameTicking;
using Content.Shared.Stunnable;
using Content.Shared.Revenant;
@@ -17,6 +16,7 @@ using Content.Shared.Actions.ActionTypes;
using Content.Shared.Tag;
using Content.Server.Store.Components;
using Content.Server.Store.Systems;
+using Content.Shared.DoAfter;
using Content.Shared.FixedPoint;
using Content.Shared.Maps;
using Content.Shared.Mobs.Systems;
@@ -32,7 +32,7 @@ public sealed partial class RevenantSystem : EntitySystem
[Dependency] private readonly ActionsSystem _action = default!;
[Dependency] private readonly AlertsSystem _alerts = default!;
[Dependency] private readonly DamageableSystem _damage = default!;
- [Dependency] private readonly DoAfterSystem _doAfter = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly EntityLookupSystem _lookup = default!;
[Dependency] private readonly MobStateSystem _mobState = default!;
[Dependency] private readonly PhysicsSystem _physics = default!;
diff --git a/Content.Server/Sticky/Systems/StickySystem.cs b/Content.Server/Sticky/Systems/StickySystem.cs
index 9437ebbd00..fb9c5fab37 100644
--- a/Content.Server/Sticky/Systems/StickySystem.cs
+++ b/Content.Server/Sticky/Systems/StickySystem.cs
@@ -1,22 +1,20 @@
-using Content.Server.DoAfter;
using Content.Server.Popups;
using Content.Server.Sticky.Components;
using Content.Server.Sticky.Events;
using Content.Shared.DoAfter;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Interaction;
+using Content.Shared.Sticky;
using Content.Shared.Sticky.Components;
using Content.Shared.Verbs;
-using Robust.Server.GameObjects;
using Robust.Shared.Containers;
-using Robust.Shared.Player;
using Robust.Shared.Utility;
namespace Content.Server.Sticky.Systems;
public sealed class StickySystem : EntitySystem
{
- [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
@@ -28,7 +26,7 @@ public sealed class StickySystem : EntitySystem
public override void Initialize()
{
base.Initialize();
- SubscribeLocalEvent(OnStickSuccessful);
+ SubscribeLocalEvent(OnStickFinished);
SubscribeLocalEvent(OnAfterInteract);
SubscribeLocalEvent>(AddUnstickVerb);
}
@@ -88,9 +86,8 @@ public sealed class StickySystem : EntitySystem
component.Stick = true;
// start sticking object to target
- _doAfterSystem.DoAfter(new DoAfterEventArgs(user, delay, target: target, used: uid)
+ _doAfterSystem.TryStartDoAfter(new DoAfterArgs(user, delay, new StickyDoAfterEvent(), uid, target: target, used: uid)
{
- BreakOnStun = true,
BreakOnTargetMove = true,
BreakOnUserMove = true,
NeedHand = true
@@ -105,14 +102,13 @@ public sealed class StickySystem : EntitySystem
return true;
}
- private void OnStickSuccessful(EntityUid uid, StickyComponent component, DoAfterEvent args)
+ private void OnStickFinished(EntityUid uid, StickyComponent component, DoAfterEvent args)
{
if (args.Handled || args.Cancelled || args.Args.Target == null)
return;
if (component.Stick)
StickToEntity(uid, args.Args.Target.Value, args.Args.User, component);
-
else
UnstickFromEntity(uid, args.Args.User, component);
@@ -137,9 +133,8 @@ public sealed class StickySystem : EntitySystem
component.Stick = false;
// start unsticking object
- _doAfterSystem.DoAfter(new DoAfterEventArgs(user, delay, target: uid)
+ _doAfterSystem.TryStartDoAfter(new DoAfterArgs(user, delay, new StickyDoAfterEvent(), uid, target: uid)
{
- BreakOnStun = true,
BreakOnTargetMove = true,
BreakOnUserMove = true,
NeedHand = true
diff --git a/Content.Server/Storage/EntitySystems/BluespaceLockerSystem.cs b/Content.Server/Storage/EntitySystems/BluespaceLockerSystem.cs
index 8c2e06cf48..5050b6dd01 100644
--- a/Content.Server/Storage/EntitySystems/BluespaceLockerSystem.cs
+++ b/Content.Server/Storage/EntitySystems/BluespaceLockerSystem.cs
@@ -1,5 +1,4 @@
using System.Linq;
-using Content.Server.DoAfter;
using Content.Server.Explosion.EntitySystems;
using Content.Server.Mind.Components;
using Content.Server.Resist;
@@ -11,6 +10,7 @@ using Content.Shared.Coordinates;
using Content.Shared.DoAfter;
using Content.Shared.Lock;
using Content.Shared.Storage.Components;
+using Content.Shared.Storage.EntitySystems;
using Robust.Shared.Random;
using Robust.Shared.Timing;
@@ -23,7 +23,7 @@ public sealed class BluespaceLockerSystem : EntitySystem
[Dependency] private readonly EntityStorageSystem _entityStorage = default!;
[Dependency] private readonly WeldableSystem _weldableSystem = default!;
[Dependency] private readonly LockSystem _lockSystem = default!;
- [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly ExplosionSystem _explosionSystem = default!;
public override void Initialize()
@@ -33,7 +33,7 @@ public sealed class BluespaceLockerSystem : EntitySystem
SubscribeLocalEvent(OnStartup);
SubscribeLocalEvent(PreOpen);
SubscribeLocalEvent(PostClose);
- SubscribeLocalEvent(OnDoAfter);
+ SubscribeLocalEvent(OnDoAfter);
}
private void OnStartup(EntityUid uid, BluespaceLockerComponent component, ComponentStartup args)
@@ -284,7 +284,7 @@ public sealed class BluespaceLockerSystem : EntitySystem
{
EnsureComp(uid);
- _doAfterSystem.DoAfter(new DoAfterEventArgs(uid, component.BehaviorProperties.Delay));
+ _doAfterSystem.TryStartDoAfter(new DoAfterArgs(uid, component.BehaviorProperties.Delay, new BluespaceLockerDoAfterEvent(), uid));
return;
}
diff --git a/Content.Server/Storage/EntitySystems/DumpableSystem.cs b/Content.Server/Storage/EntitySystems/DumpableSystem.cs
index a59e439bec..69a2742542 100644
--- a/Content.Server/Storage/EntitySystems/DumpableSystem.cs
+++ b/Content.Server/Storage/EntitySystems/DumpableSystem.cs
@@ -1,11 +1,10 @@
-using System.Threading;
using Content.Shared.Interaction;
using Content.Server.Storage.Components;
using Content.Shared.Storage.Components;
using Content.Shared.Verbs;
using Content.Server.Disposal.Unit.Components;
using Content.Server.Disposal.Unit.EntitySystems;
-using Content.Server.DoAfter;
+using Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Systems;
using Content.Shared.DoAfter;
using Content.Shared.Placeable;
using Content.Shared.Storage;
@@ -17,7 +16,7 @@ namespace Content.Server.Storage.EntitySystems
{
public sealed class DumpableSystem : EntitySystem
{
- [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly DisposalUnitSystem _disposalUnitSystem = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly SharedContainerSystem _container = default!;
@@ -28,16 +27,19 @@ namespace Content.Server.Storage.EntitySystems
SubscribeLocalEvent(OnAfterInteract, after: new[]{ typeof(StorageSystem) });
SubscribeLocalEvent>(AddDumpVerb);
SubscribeLocalEvent>(AddUtilityVerbs);
- SubscribeLocalEvent(OnDoAfter);
+ SubscribeLocalEvent(OnDoAfter);
}
private void OnAfterInteract(EntityUid uid, DumpableComponent component, AfterInteractEvent args)
{
- if (!args.CanReach)
+ if (!args.CanReach || args.Handled)
return;
- if (HasComp(args.Target) || HasComp(args.Target))
- StartDoAfter(uid, args.Target.Value, args.User, component);
+ if (!HasComp(args.Target) && !HasComp(args.Target))
+ return;
+
+ StartDoAfter(uid, args.Target.Value, args.User, component);
+ args.Handled = true;
}
private void AddDumpVerb(EntityUid uid, DumpableComponent dumpable, GetVerbsEvent args)
@@ -52,7 +54,7 @@ namespace Content.Server.Storage.EntitySystems
{
Act = () =>
{
- StartDoAfter(uid, null, args.User, dumpable);//Had multiplier of 0.6f
+ StartDoAfter(uid, args.Target, args.User, dumpable);//Had multiplier of 0.6f
},
Text = Loc.GetString("dump-verb-name"),
Icon = new SpriteSpecifier.Texture(new ResourcePath("/Textures/Interface/VerbIcons/drop.svg.192dpi.png")),
@@ -104,12 +106,10 @@ namespace Content.Server.Storage.EntitySystems
float delay = storage.StoredEntities.Count * (float) dumpable.DelayPerItem.TotalSeconds * dumpable.Multiplier;
- _doAfterSystem.DoAfter(new DoAfterEventArgs(userUid, delay, target: targetUid, used: storageUid)
+ _doAfterSystem.TryStartDoAfter(new DoAfterArgs(userUid, delay, new DumpableDoAfterEvent(), storageUid, target: targetUid, used: storageUid)
{
- RaiseOnTarget = false,
BreakOnTargetMove = true,
BreakOnUserMove = true,
- BreakOnStun = true,
NeedHand = true
});
}
diff --git a/Content.Server/Storage/EntitySystems/StorageSystem.cs b/Content.Server/Storage/EntitySystems/StorageSystem.cs
index c8adcec54b..b09e436dc1 100644
--- a/Content.Server/Storage/EntitySystems/StorageSystem.cs
+++ b/Content.Server/Storage/EntitySystems/StorageSystem.cs
@@ -12,8 +12,6 @@ using Robust.Shared.Containers;
using Robust.Shared.Random;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
-using System.Threading;
-using Content.Server.DoAfter;
using Content.Server.Interaction;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Item;
@@ -33,7 +31,6 @@ using Content.Shared.Containers.ItemSlots;
using Content.Shared.DoAfter;
using Content.Shared.Implants.Components;
using Content.Shared.Lock;
-using Content.Shared.Movement.Events;
using Content.Server.Ghost.Components;
using Content.Server.Administration.Managers;
using Content.Shared.Administration;
@@ -47,7 +44,7 @@ namespace Content.Server.Storage.EntitySystems
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly IAdminManager _admin = default!;
[Dependency] private readonly ContainerSystem _containerSystem = default!;
- [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly EntityLookupSystem _entityLookupSystem = default!;
[Dependency] private readonly EntityStorageSystem _entityStorage = default!;
[Dependency] private readonly InteractionSystem _interactionSystem = default!;
@@ -81,7 +78,7 @@ namespace Content.Server.Storage.EntitySystems
SubscribeLocalEvent(OnBoundUIClosed);
SubscribeLocalEvent(OnStorageItemRemoved);
- SubscribeLocalEvent>(OnDoAfter);
+ SubscribeLocalEvent(OnDoAfter);
SubscribeLocalEvent(OnStorageFillMapInit);
}
@@ -234,16 +231,14 @@ namespace Content.Server.Storage.EntitySystems
//If there's only one then let's be generous
if (validStorables.Count > 1)
{
- var storageData = new StorageData(validStorables);
- var doAfterArgs = new DoAfterEventArgs(args.User, 0.2f * validStorables.Count, target: uid)
+ var doAfterArgs = new DoAfterArgs(args.User, 0.2f * validStorables.Count, new AreaPickupDoAfterEvent(validStorables), uid, target: uid)
{
- BreakOnStun = true,
BreakOnDamage = true,
BreakOnUserMove = true,
NeedHand = true
};
- _doAfterSystem.DoAfter(doAfterArgs, storageData);
+ _doAfterSystem.TryStartDoAfter(doAfterArgs);
}
return;
@@ -278,7 +273,7 @@ namespace Content.Server.Storage.EntitySystems
}
}
- private void OnDoAfter(EntityUid uid, ServerStorageComponent component, DoAfterEvent args)
+ private void OnDoAfter(EntityUid uid, ServerStorageComponent component, AreaPickupDoAfterEvent args)
{
if (args.Handled || args.Cancelled)
return;
@@ -289,7 +284,7 @@ namespace Content.Server.Storage.EntitySystems
var xformQuery = GetEntityQuery();
xformQuery.TryGetComponent(uid, out var xform);
- foreach (var entity in args.AdditionalData.ValidStorables)
+ foreach (var entity in args.Entities)
{
// Check again, situation may have changed for some entities, but we'll still pick up any that are valid
if (_containerSystem.IsEntityInContainer(entity)
@@ -667,10 +662,5 @@ namespace Content.Server.Storage.EntitySystems
_popupSystem.PopupEntity(Loc.GetString(message), player, player);
}
-
- private record struct StorageData(List validStorables)
- {
- public List ValidStorables = validStorables;
- }
}
}
diff --git a/Content.Server/Strip/StrippableSystem.cs b/Content.Server/Strip/StrippableSystem.cs
index 282e197d83..b0c9322ba7 100644
--- a/Content.Server/Strip/StrippableSystem.cs
+++ b/Content.Server/Strip/StrippableSystem.cs
@@ -1,5 +1,4 @@
using System.Linq;
-using Content.Server.DoAfter;
using Content.Server.Ensnaring;
using Content.Server.Hands.Components;
using Content.Shared.CombatMode;
@@ -12,7 +11,6 @@ using Content.Shared.Popups;
using Content.Shared.Strip.Components;
using Content.Shared.Verbs;
using Robust.Server.GameObjects;
-using System.Threading;
using Content.Server.Administration.Logs;
using Content.Shared.Cuffs;
using Content.Shared.Cuffs.Components;
@@ -30,8 +28,8 @@ namespace Content.Server.Strip
[Dependency] private readonly SharedCuffableSystem _cuffable = default!;
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
[Dependency] private readonly InventorySystem _inventorySystem = default!;
- [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
- [Dependency] private readonly SharedPopupSystem _popupSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
+ [Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly EnsnareableSystem _ensnaring = default!;
[Dependency] private readonly UserInterfaceSystem _userInterfaceSystem = default!;
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
@@ -61,12 +59,12 @@ namespace Content.Server.Strip
if (!TryComp(entity, out var ensnaring))
continue;
- _ensnaring.TryFree(uid, entity, ensnaring, user);
+ _ensnaring.TryFree(uid, user, entity, ensnaring);
return;
}
}
- private void OnStripButtonPressed(EntityUid uid, StrippableComponent component, StrippingSlotButtonPressed args)
+ private void OnStripButtonPressed(EntityUid target, StrippableComponent component, StrippingSlotButtonPressed args)
{
if (args.Session.AttachedEntity is not {Valid: true} user ||
!TryComp(user, out var userHands))
@@ -74,19 +72,19 @@ namespace Content.Server.Strip
if (args.IsHand)
{
- StripHand(uid, user, args.Slot, component, userHands);
+ StripHand(target, user, args.Slot, component, userHands);
return;
}
- if (!TryComp(component.Owner, out var inventory))
+ if (!TryComp(target, out var inventory))
return;
- var hasEnt = _inventorySystem.TryGetSlotEntity(component.Owner, args.Slot, out _, inventory);
+ var hasEnt = _inventorySystem.TryGetSlotEntity(target, args.Slot, out var held, inventory);
if (userHands.ActiveHandEntity != null && !hasEnt)
- PlaceActiveHandItemInInventory(user, args.Slot, component);
+ PlaceActiveHandItemInInventory(user, target, userHands.ActiveHandEntity.Value, args.Slot, component);
else if (userHands.ActiveHandEntity == null && hasEnt)
- TakeItemFromInventory(user, args.Slot, component);
+ TakeItemFromInventory(user, target, held!.Value, args.Slot, component);
}
private void StripHand(EntityUid target, EntityUid user, string handId, StrippableComponent component, HandsComponent userHands)
@@ -104,10 +102,10 @@ namespace Content.Server.Strip
return;
}
- if (hand.IsEmpty && userHands.ActiveHandEntity != null)
- PlaceActiveHandItemInHands(user, handId, component);
- else if (!hand.IsEmpty && userHands.ActiveHandEntity == null)
- TakeItemFromHands(user, handId, component);
+ if (userHands.ActiveHandEntity != null && hand.HeldEntity == null)
+ PlaceActiveHandItemInHands(user, target, userHands.ActiveHandEntity.Value, handId, component);
+ else if (userHands.ActiveHandEntity == null && hand.HeldEntity != null)
+ TakeItemFromHands(user,target, hand.HeldEntity.Value, handId, component);
}
public override void StartOpeningStripper(EntityUid user, StrippableComponent component, bool openInCombat = false)
@@ -166,287 +164,291 @@ namespace Content.Server.Strip
if (args.Target == args.User)
return;
- if (!HasComp(args.User))
+ if (!TryComp(args.User, out var actor))
return;
- args.Handled = true;
StartOpeningStripper(args.User, component);
}
///
/// Places item in user's active hand to an inventory slot.
///
- private async void PlaceActiveHandItemInInventory(EntityUid user, string slot, StrippableComponent component)
+ private async void PlaceActiveHandItemInInventory(
+ EntityUid user,
+ EntityUid target,
+ EntityUid held,
+ string slot,
+ StrippableComponent component)
{
var userHands = Comp(user);
bool Check()
{
- if (userHands.ActiveHand?.HeldEntity is not { } held)
+ if (userHands.ActiveHandEntity != held)
+ return false;
+
+ if (!_handsSystem.CanDropHeld(user, userHands.ActiveHand!))
{
- user.PopupMessageCursor(Loc.GetString("strippable-component-not-holding-anything"));
+ _popup.PopupCursor(Loc.GetString("strippable-component-cannot-drop"), user);
return false;
}
- if (!_handsSystem.CanDropHeld(user, userHands.ActiveHand))
+ if (_inventorySystem.TryGetSlotEntity(target, slot, out _))
{
- user.PopupMessageCursor(Loc.GetString("strippable-component-cannot-drop"));
+ _popup.PopupCursor(Loc.GetString("strippable-component-item-slot-occupied",("owner", target)), user);
return false;
}
- if (!_inventorySystem.HasSlot(component.Owner, slot))
- return false;
-
- if (_inventorySystem.TryGetSlotEntity(component.Owner, slot, out _))
+ if (!_inventorySystem.CanEquip(user, target, held, slot, out _))
{
- user.PopupMessageCursor(Loc.GetString("strippable-component-item-slot-occupied",("owner", component.Owner)));
- return false;
- }
-
- if (!_inventorySystem.CanEquip(user, component.Owner, held, slot, out _))
- {
- user.PopupMessageCursor(Loc.GetString("strippable-component-cannot-equip-message",("owner", component.Owner)));
+ _popup.PopupCursor(Loc.GetString("strippable-component-cannot-equip-message",("owner", target)), user);
return false;
}
return true;
}
- if (!_inventorySystem.TryGetSlot(component.Owner, slot, out var slotDef))
+ if (!_inventorySystem.TryGetSlot(target, slot, out var slotDef))
{
- Logger.Error($"{ToPrettyString(user)} attempted to place an item in a non-existent inventory slot ({slot}) on {ToPrettyString(component.Owner)}");
+ Logger.Error($"{ToPrettyString(user)} attempted to place an item in a non-existent inventory slot ({slot}) on {ToPrettyString(target)}");
return;
}
- var (time, stealth) = GetStripTimeModifiers(user, component.Owner, slotDef.StripTime);
+ var userEv = new BeforeStripEvent(slotDef.StripTime);
+ RaiseLocalEvent(user, userEv);
+ var ev = new BeforeGettingStrippedEvent(userEv.Time, userEv.Stealth);
+ RaiseLocalEvent(target, ev);
- var doAfterArgs = new DoAfterEventArgs(user, time, CancellationToken.None, component.Owner)
+ var doAfterArgs = new DoAfterArgs(user, ev.Time, new AwaitedDoAfterEvent(), null, target: target, used: held)
{
ExtraCheck = Check,
- BreakOnStun = true,
+ AttemptFrequency = AttemptFrequency.EveryTick,
BreakOnDamage = true,
BreakOnTargetMove = true,
BreakOnUserMove = true,
NeedHand = true,
+ DuplicateCondition = DuplicateConditions.SameTool // Block any other DoAfters featuring this same entity.
};
- if (!stealth && Check() && userHands.ActiveHandEntity != null)
+ if (!ev.Stealth && Check() && userHands.ActiveHandEntity != null)
{
var message = Loc.GetString("strippable-component-alert-owner-insert",
("user", Identity.Entity(user, EntityManager)), ("item", userHands.ActiveHandEntity));
- _popupSystem.PopupEntity(message, component.Owner, component.Owner, PopupType.Large);
+ _popup.PopupEntity(message, target, target, PopupType.Large);
}
- var result = await _doAfterSystem.WaitDoAfter(doAfterArgs);
+ var result = await _doAfter.WaitDoAfter(doAfterArgs);
if (result != DoAfterStatus.Finished) return;
- if (userHands.ActiveHand?.HeldEntity is { } held
- && _handsSystem.TryDrop(user, userHands.ActiveHand, handsComp: userHands))
- {
- _inventorySystem.TryEquip(user, component.Owner, held, slot);
+ DebugTools.Assert(userHands.ActiveHand?.HeldEntity == held);
- _adminLogger.Add(LogType.Stripping, LogImpact.Medium, $"{ToPrettyString(user):user} has placed the item {ToPrettyString(held):item} in {ToPrettyString(component.Owner):target}'s {slot} slot");
+ if (_handsSystem.TryDrop(user, handsComp: userHands))
+ {
+ _inventorySystem.TryEquip(user, target, held, slot);
+
+ _adminLogger.Add(LogType.Stripping, LogImpact.Medium, $"{ToPrettyString(user):user} has placed the item {ToPrettyString(held):item} in {ToPrettyString(target):target}'s {slot} slot");
}
}
///
/// Places item in user's active hand in one of the entity's hands.
///
- private async void PlaceActiveHandItemInHands(EntityUid user, string handName, StrippableComponent component)
+ private async void PlaceActiveHandItemInHands(
+ EntityUid user,
+ EntityUid target,
+ EntityUid held,
+ string handName,
+ StrippableComponent component)
{
- var hands = Comp(component.Owner);
+ var hands = Comp(target);
var userHands = Comp(user);
bool Check()
{
- if (userHands.ActiveHandEntity == null)
- {
- user.PopupMessageCursor(Loc.GetString("strippable-component-not-holding-anything"));
+ if (userHands.ActiveHandEntity != held)
return false;
- }
if (!_handsSystem.CanDropHeld(user, userHands.ActiveHand!))
{
- user.PopupMessageCursor(Loc.GetString("strippable-component-cannot-drop"));
+ _popup.PopupCursor(Loc.GetString("strippable-component-cannot-drop"), user);
return false;
}
if (!hands.Hands.TryGetValue(handName, out var hand)
- || !_handsSystem.CanPickupToHand(component.Owner, userHands.ActiveHandEntity.Value, hand, checkActionBlocker: false, hands))
+ || !_handsSystem.CanPickupToHand(target, userHands.ActiveHandEntity.Value, hand, checkActionBlocker: false, hands))
{
- user.PopupMessageCursor(Loc.GetString("strippable-component-cannot-put-message",("owner", component.Owner)));
+ _popup.PopupCursor(Loc.GetString("strippable-component-cannot-put-message",("owner", target)), user);
return false;
}
return true;
}
- var (time, stealth) = GetStripTimeModifiers(user, component.Owner, component.HandStripDelay);
+ var userEv = new BeforeStripEvent(component.HandStripDelay);
+ RaiseLocalEvent(user, userEv);
+ var ev = new BeforeGettingStrippedEvent(userEv.Time, userEv.Stealth);
+ RaiseLocalEvent(target, ev);
- var doAfterArgs = new DoAfterEventArgs(user, time, CancellationToken.None, component.Owner)
+ var doAfterArgs = new DoAfterArgs(user, ev.Time, new AwaitedDoAfterEvent(), null, target: target, used: held)
{
ExtraCheck = Check,
- BreakOnStun = true,
+ AttemptFrequency = AttemptFrequency.EveryTick,
BreakOnDamage = true,
BreakOnTargetMove = true,
BreakOnUserMove = true,
NeedHand = true,
+ DuplicateCondition = DuplicateConditions.SameTool
};
- if (!stealth
- && Check()
- && userHands.Hands.TryGetValue(handName, out var handSlot)
- && handSlot.HeldEntity != null)
- {
- _popupSystem.PopupEntity(
- Loc.GetString("strippable-component-alert-owner-insert",
- ("user", Identity.Entity(user, EntityManager)),
- ("item", handSlot.HeldEntity)),
- component.Owner, component.Owner, PopupType.Large);
- }
-
- var result = await _doAfterSystem.WaitDoAfter(doAfterArgs);
+ var result = await _doAfter.WaitDoAfter(doAfterArgs);
if (result != DoAfterStatus.Finished) return;
- if (userHands.ActiveHandEntity is not { } held)
- return;
-
_handsSystem.TryDrop(user, checkActionBlocker: false, handsComp: userHands);
- _handsSystem.TryPickup(component.Owner, held, handName, checkActionBlocker: false, animateUser: true, animate: !stealth, handsComp: hands);
- _adminLogger.Add(LogType.Stripping, LogImpact.Medium, $"{ToPrettyString(user):user} has placed the item {ToPrettyString(held):item} in {ToPrettyString(component.Owner):target}'s hands");
+ _handsSystem.TryPickup(target, held, handName, checkActionBlocker: false, animateUser: true, handsComp: hands);
+ _adminLogger.Add(LogType.Stripping, LogImpact.Medium, $"{ToPrettyString(user):user} has placed the item {ToPrettyString(held):item} in {ToPrettyString(target):target}'s hands");
// hand update will trigger strippable update
}
///
/// Takes an item from the inventory and places it in the user's active hand.
///
- private async void TakeItemFromInventory(EntityUid user, string slot, StrippableComponent component)
+ private async void TakeItemFromInventory(
+ EntityUid user,
+ EntityUid target,
+ EntityUid item,
+ string slot,
+ StrippableComponent component)
{
bool Check()
{
- if (!_inventorySystem.HasSlot(component.Owner, slot))
- return false;
-
- if (!_inventorySystem.TryGetSlotEntity(component.Owner, slot, out _))
+ if (!_inventorySystem.TryGetSlotEntity(target, slot, out var ent) && ent == item)
{
- user.PopupMessageCursor(Loc.GetString("strippable-component-item-slot-free-message", ("owner", component.Owner)));
+ _popup.PopupCursor(Loc.GetString("strippable-component-item-slot-free-message", ("owner", target)), user);
return false;
}
- if (!_inventorySystem.CanUnequip(user, component.Owner, slot, out var reason))
+ if (!_inventorySystem.CanUnequip(user, target, slot, out var reason))
{
- user.PopupMessageCursor(reason);
+ _popup.PopupCursor(reason, user);
return false;
}
return true;
}
- if (!_inventorySystem.TryGetSlot(component.Owner, slot, out var slotDef))
+ if (!_inventorySystem.TryGetSlot(target, slot, out var slotDef))
{
- Logger.Error($"{ToPrettyString(user)} attempted to take an item from a non-existent inventory slot ({slot}) on {ToPrettyString(component.Owner)}");
+ Logger.Error($"{ToPrettyString(user)} attempted to take an item from a non-existent inventory slot ({slot}) on {ToPrettyString(target)}");
return;
}
- var (time, stealth) = GetStripTimeModifiers(user, component.Owner, slotDef.StripTime);
+ var userEv = new BeforeStripEvent(slotDef.StripTime);
+ RaiseLocalEvent(user, userEv);
+ var ev = new BeforeGettingStrippedEvent(userEv.Time, userEv.Stealth);
+ RaiseLocalEvent(target, ev);
- var doAfterArgs = new DoAfterEventArgs(user, time, CancellationToken.None, component.Owner)
+ var doAfterArgs = new DoAfterArgs(user, ev.Time, new AwaitedDoAfterEvent(), null, target: target, used: item)
{
ExtraCheck = Check,
- BreakOnStun = true,
+ AttemptFrequency = AttemptFrequency.EveryTick,
BreakOnDamage = true,
BreakOnTargetMove = true,
BreakOnUserMove = true,
+ NeedHand = true,
+ BreakOnHandChange = false, // allow simultaneously removing multiple items.
+ DuplicateCondition = DuplicateConditions.SameTool
};
- if (!stealth && Check())
+ if (!ev.Stealth && Check())
{
if (slotDef.StripHidden)
{
- _popupSystem.PopupEntity(Loc.GetString("strippable-component-alert-owner-hidden", ("slot", slot)), component.Owner,
- component.Owner, PopupType.Large);
+ _popup.PopupEntity(Loc.GetString("strippable-component-alert-owner-hidden", ("slot", slot)), target,
+ target, PopupType.Large);
}
else if (_inventorySystem.TryGetSlotEntity(component.Owner, slot, out var slotItem))
{
- _popupSystem.PopupEntity(Loc.GetString("strippable-component-alert-owner", ("user", Identity.Entity(user, EntityManager)), ("item", slotItem)), component.Owner,
- component.Owner, PopupType.Large);
+ _popup.PopupEntity(Loc.GetString("strippable-component-alert-owner", ("user", Identity.Entity(user, EntityManager)), ("item", slotItem)), target,
+ target, PopupType.Large);
}
}
- var result = await _doAfterSystem.WaitDoAfter(doAfterArgs);
+ var result = await _doAfter.WaitDoAfter(doAfterArgs);
if (result != DoAfterStatus.Finished) return;
- if (_inventorySystem.TryGetSlotEntity(component.Owner, slot, out var item) && _inventorySystem.TryUnequip(user, component.Owner, slot))
- {
- // Raise a dropped event, so that things like gas tank internals properly deactivate when stripping
- RaiseLocalEvent(item.Value, new DroppedEvent(user), true);
+ if (!_inventorySystem.TryUnequip(user, component.Owner, slot))
+ return;
+
+ // Raise a dropped event, so that things like gas tank internals properly deactivate when stripping
+ RaiseLocalEvent(item, new DroppedEvent(user), true);
+
+ _handsSystem.PickupOrDrop(user, item);
+ _adminLogger.Add(LogType.Stripping, LogImpact.Medium, $"{ToPrettyString(user):user} has stripped the item {ToPrettyString(item):item} from {ToPrettyString(target):target}");
- _handsSystem.PickupOrDrop(user, item.Value, animate: !stealth);
- _adminLogger.Add(LogType.Stripping, LogImpact.Medium, $"{ToPrettyString(user):user} has stripped the item {ToPrettyString(item.Value):item} from {ToPrettyString(component.Owner):target}");
- }
}
///
/// Takes an item from a hand and places it in the user's active hand.
///
- private async void TakeItemFromHands(EntityUid user, string handName, StrippableComponent component)
+ private async void TakeItemFromHands(EntityUid user, EntityUid target, EntityUid item, string handName, StrippableComponent component)
{
- var hands = Comp(component.Owner);
+ var hands = Comp(target);
var userHands = Comp(user);
bool Check()
{
- if (!hands.Hands.TryGetValue(handName, out var hand) || hand.HeldEntity == null)
+ if (!hands.Hands.TryGetValue(handName, out var hand) || hand.HeldEntity != item)
{
- user.PopupMessageCursor(Loc.GetString("strippable-component-item-slot-free-message",("owner", component.Owner)));
+ _popup.PopupCursor(Loc.GetString("strippable-component-item-slot-free-message",("owner", target)), user);
return false;
}
if (HasComp(hand.HeldEntity))
return false;
- if (!_handsSystem.CanDropHeld(component.Owner, hand, false))
+ if (!_handsSystem.CanDropHeld(target, hand, false))
{
- user.PopupMessageCursor(Loc.GetString("strippable-component-cannot-drop-message",("owner", component.Owner)));
+ _popup.PopupCursor(Loc.GetString("strippable-component-cannot-drop-message",("owner", target)), user);
return false;
}
return true;
}
- var (time, stealth) = GetStripTimeModifiers(user, component.Owner, component.HandStripDelay);
+ var userEv = new BeforeStripEvent(component.HandStripDelay);
+ RaiseLocalEvent(user, userEv);
+ var ev = new BeforeGettingStrippedEvent(userEv.Time, userEv.Stealth);
+ RaiseLocalEvent(target, ev);
- var doAfterArgs = new DoAfterEventArgs(user, time, CancellationToken.None, component.Owner)
+ var doAfterArgs = new DoAfterArgs(user, ev.Time, new AwaitedDoAfterEvent(), null, target: target, used: item)
{
ExtraCheck = Check,
- BreakOnStun = true,
+ AttemptFrequency = AttemptFrequency.EveryTick,
BreakOnDamage = true,
BreakOnTargetMove = true,
BreakOnUserMove = true,
+ NeedHand = true,
+ BreakOnHandChange = false, // allow simultaneously removing multiple items.
+ DuplicateCondition = DuplicateConditions.SameTool
};
- if (!stealth
- && Check()
- && hands.Hands.TryGetValue(handName, out var handSlot)
- && handSlot.HeldEntity != null)
+ if (Check() && hands.Hands.TryGetValue(handName, out var handSlot) && handSlot.HeldEntity != null)
{
- _popupSystem.PopupEntity(
+ _popup.PopupEntity(
Loc.GetString("strippable-component-alert-owner",
- ("user", Identity.Entity(user, EntityManager)),
- ("item", handSlot.HeldEntity)),
- component.Owner, component.Owner);
+ ("user", Identity.Entity(user, EntityManager)), ("item", item)),
+ component.Owner,
+ component.Owner);
}
- var result = await _doAfterSystem.WaitDoAfter(doAfterArgs);
+ var result = await _doAfter.WaitDoAfter(doAfterArgs);
if (result != DoAfterStatus.Finished) return;
- if (!hands.Hands.TryGetValue(handName, out var hand) || hand.HeldEntity is not { } held)
- return;
-
- _handsSystem.TryDrop(component.Owner, hand, checkActionBlocker: false, handsComp: hands);
- _handsSystem.PickupOrDrop(user, held, handsComp: userHands, animate: !stealth);
+ _handsSystem.TryDrop(target, item, checkActionBlocker: false, handsComp: hands);
+ _handsSystem.PickupOrDrop(user, item, handsComp: userHands);
// hand update will trigger strippable update
- _adminLogger.Add(LogType.Stripping, LogImpact.Medium, $"{ToPrettyString(user):user} has stripped the item {ToPrettyString(held):item} from {ToPrettyString(component.Owner):target}");
+ _adminLogger.Add(LogType.Stripping, LogImpact.Medium,
+ $"{ToPrettyString(user):user} has stripped the item {ToPrettyString(item):item} from {ToPrettyString(target):target}");
}
}
}
diff --git a/Content.Server/Teleportation/HandTeleporterSystem.cs b/Content.Server/Teleportation/HandTeleporterSystem.cs
index 98a2aff1a8..f3a3b986a0 100644
--- a/Content.Server/Teleportation/HandTeleporterSystem.cs
+++ b/Content.Server/Teleportation/HandTeleporterSystem.cs
@@ -1,5 +1,4 @@
using Content.Server.Administration.Logs;
-using Content.Server.DoAfter;
using Content.Shared.DoAfter;
using Content.Shared.Database;
using Content.Shared.Interaction.Events;
@@ -17,14 +16,14 @@ public sealed class HandTeleporterSystem : EntitySystem
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
[Dependency] private readonly LinkedEntitySystem _link = default!;
[Dependency] private readonly AudioSystem _audio = default!;
- [Dependency] private readonly DoAfterSystem _doafter = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doafter = default!;
///
public override void Initialize()
{
SubscribeLocalEvent(OnUseInHand);
- SubscribeLocalEvent(OnDoAfter);
+ SubscribeLocalEvent(OnDoAfter);
}
private void OnDoAfter(EntityUid uid, HandTeleporterComponent component, DoAfterEvent args)
@@ -56,15 +55,14 @@ public sealed class HandTeleporterSystem : EntitySystem
if (xform.ParentUid != xform.GridUid)
return;
- var doafterArgs = new DoAfterEventArgs(args.User, component.PortalCreationDelay, used: uid)
+ var doafterArgs = new DoAfterArgs(args.User, component.PortalCreationDelay, new TeleporterDoAfterEvent(), uid, used: uid)
{
BreakOnDamage = true,
- BreakOnStun = true,
BreakOnUserMove = true,
MovementThreshold = 0.5f,
};
- _doafter.DoAfter(doafterArgs);
+ _doafter.TryStartDoAfter(doafterArgs);
}
}
diff --git a/Content.Server/Toilet/ToiletSystem.cs b/Content.Server/Toilet/ToiletSystem.cs
index b98c5c9d38..03591433fb 100644
--- a/Content.Server/Toilet/ToiletSystem.cs
+++ b/Content.Server/Toilet/ToiletSystem.cs
@@ -6,6 +6,7 @@ using Content.Server.Storage.EntitySystems;
using Content.Shared.Body.Components;
using Content.Shared.Body.Part;
using Content.Shared.Buckle.Components;
+using Content.Shared.DoAfter;
using Content.Shared.Examine;
using Content.Shared.IdentityManagement;
using Content.Shared.Interaction;
@@ -39,8 +40,7 @@ namespace Content.Server.Toilet
SubscribeLocalEvent(OnInteractHand, new []{typeof(BuckleSystem)});
SubscribeLocalEvent(OnExamine);
SubscribeLocalEvent(OnSuicide);
- SubscribeLocalEvent(OnToiletPried);
- SubscribeLocalEvent(OnToiletInterrupt);
+ SubscribeLocalEvent(OnToiletPried);
}
private void OnSuicide(EntityUid uid, ToiletComponent component, SuicideEvent args)
@@ -94,29 +94,15 @@ namespace Content.Server.Toilet
return;
// are player trying place or lift of cistern lid?
- if (EntityManager.TryGetComponent(args.Used, out ToolComponent? tool)
- && tool.Qualities.Contains(component.PryingQuality))
+ if (_toolSystem.UseTool(args.Used, args.User, uid, component.PryLidTime, component.PryingQuality, new ToiletPryDoAfterEvent()))
{
- // check if someone is already prying this toilet
- if (component.IsPrying)
- return;
- component.IsPrying = true;
-
- var toolEvData = new ToolEventData(new ToiletPryFinished(uid));
-
- // try to pry toilet cistern
- if (!_toolSystem.UseTool(args.Used, args.User, uid, component.PryLidTime, new [] {component.PryingQuality}, toolEvData))
- {
- component.IsPrying = false;
- return;
- }
-
args.Handled = true;
}
// maybe player trying to hide something inside cistern?
else if (component.LidOpen)
{
- args.Handled = _secretStash.TryHideItem(uid, args.User, args.Used);
+ args.Handled = true;
+ _secretStash.TryHideItem(uid, args.User, args.Used);
}
}
@@ -160,22 +146,13 @@ namespace Content.Server.Toilet
}
}
- private void OnToiletInterrupt(ToiletPryInterrupted ev)
+ private void OnToiletPried(EntityUid uid, ToiletComponent toilet, ToiletPryDoAfterEvent args)
{
- if (!EntityManager.TryGetComponent(ev.Uid, out ToiletComponent? toilet))
+ if (args.Cancelled)
return;
- toilet.IsPrying = false;
- }
-
- private void OnToiletPried(ToiletPryFinished ev)
- {
- if (!EntityManager.TryGetComponent(ev.Uid, out ToiletComponent? toilet))
- return;
-
- toilet.IsPrying = false;
toilet.LidOpen = !toilet.LidOpen;
- UpdateSprite(ev.Uid, toilet);
+ UpdateSprite(uid, toilet);
}
public void ToggleToiletSeat(EntityUid uid, ToiletComponent? component = null)
@@ -197,24 +174,4 @@ namespace Content.Server.Toilet
_appearance.SetData(uid, ToiletVisuals.SeatUp, component.IsSeatUp, appearance);
}
}
-
- public sealed class ToiletPryFinished : EntityEventArgs
- {
- public EntityUid Uid;
-
- public ToiletPryFinished(EntityUid uid)
- {
- Uid = uid;
- }
- }
-
- public sealed class ToiletPryInterrupted : EntityEventArgs
- {
- public EntityUid Uid;
-
- public ToiletPryInterrupted(EntityUid uid)
- {
- Uid = uid;
- }
- }
}
diff --git a/Content.Server/Tools/Components/LatticeCuttingComponent.cs b/Content.Server/Tools/Components/LatticeCuttingComponent.cs
index b1e4e18fec..bbc782a5f1 100644
--- a/Content.Server/Tools/Components/LatticeCuttingComponent.cs
+++ b/Content.Server/Tools/Components/LatticeCuttingComponent.cs
@@ -6,9 +6,6 @@ namespace Content.Server.Tools.Components;
[RegisterComponent]
public sealed class LatticeCuttingComponent : Component
{
- [DataField("toolComponentNeeded")]
- public bool ToolComponentNeeded = true;
-
[DataField("qualityNeeded", customTypeSerializer:typeof(PrototypeIdSerializer))]
public string QualityNeeded = "Cutting";
diff --git a/Content.Server/Tools/Components/TilePryingComponent.cs b/Content.Server/Tools/Components/TilePryingComponent.cs
index 9dee4fc004..82566e3559 100644
--- a/Content.Server/Tools/Components/TilePryingComponent.cs
+++ b/Content.Server/Tools/Components/TilePryingComponent.cs
@@ -15,8 +15,5 @@ namespace Content.Server.Tools.Components
[DataField("delay")]
public float Delay = 1f;
-
- [DataField("cancelToken")]
- public CancellationTokenSource? CancelToken;
}
}
diff --git a/Content.Server/Tools/Components/WeldableComponent.cs b/Content.Server/Tools/Components/WeldableComponent.cs
index b59f493e23..46062692d3 100644
--- a/Content.Server/Tools/Components/WeldableComponent.cs
+++ b/Content.Server/Tools/Components/WeldableComponent.cs
@@ -47,15 +47,9 @@ public sealed class WeldableComponent : SharedWeldableComponent
[ViewVariables(VVAccess.ReadWrite)]
public string? WeldedExamineMessage = "weldable-component-examine-is-welded";
- ///
- /// Whether something is currently using a welder on this so DoAfter isn't spammed.
- ///
- [ViewVariables(VVAccess.ReadOnly)]
- public bool BeingWelded;
-
///
/// Is this entity currently welded shut?
///
- [ViewVariables(VVAccess.ReadOnly)]
+ [DataField("isWelded")]
public bool IsWelded;
}
diff --git a/Content.Server/Tools/Systems/WeldableSystem.cs b/Content.Server/Tools/Systems/WeldableSystem.cs
index 780cab4368..c04ab840ef 100644
--- a/Content.Server/Tools/Systems/WeldableSystem.cs
+++ b/Content.Server/Tools/Systems/WeldableSystem.cs
@@ -1,10 +1,12 @@
using Content.Server.Administration.Logs;
using Content.Server.Tools.Components;
using Content.Shared.Database;
+using Content.Shared.DoAfter;
using Content.Shared.Examine;
using Content.Shared.Interaction;
using Content.Shared.Tools;
using Content.Shared.Tools.Components;
+using Content.Shared.Tools.Systems;
using Robust.Shared.Physics;
using Robust.Shared.Physics.Systems;
@@ -22,7 +24,6 @@ public sealed class WeldableSystem : EntitySystem
base.Initialize();
SubscribeLocalEvent(OnInteractUsing);
SubscribeLocalEvent(OnWeldFinished);
- SubscribeLocalEvent(OnWeldCanceled);
SubscribeLocalEvent(OnWeldChanged);
SubscribeLocalEvent(OnExamine);
}
@@ -47,9 +48,7 @@ public sealed class WeldableSystem : EntitySystem
return false;
// Basic checks
- if (!component.Weldable || component.BeingWelded)
- return false;
- if (!_toolSystem.HasQuality(tool, component.WeldingQuality))
+ if (!component.Weldable)
return false;
// Other component systems
@@ -69,8 +68,8 @@ public sealed class WeldableSystem : EntitySystem
if (!CanWeld(uid, tool, user, component))
return false;
- var toolEvData = new ToolEventData(new WeldFinishedEvent(user, tool), cancelledEv: new WeldCancelledEvent(),targetEntity: uid);
- component.BeingWelded = _toolSystem.UseTool(tool, user, uid, component.WeldingTime.Seconds, new[] { component.WeldingQuality }, toolEvData, fuel: component.FuelConsumption);
+ if (!_toolSystem.UseTool(tool, user, uid, component.WeldingTime.Seconds, component.WeldingQuality, new WeldFinishedEvent(), fuel: component.FuelConsumption))
+ return false;
// Log attempt
_adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(user):user} is {(component.IsWelded ? "un" : "")}welding {ToPrettyString(uid):target} at {Transform(uid).Coordinates:targetlocation}");
@@ -80,10 +79,11 @@ public sealed class WeldableSystem : EntitySystem
private void OnWeldFinished(EntityUid uid, WeldableComponent component, WeldFinishedEvent args)
{
- component.BeingWelded = false;
+ if (args.Cancelled || args.Used == null)
+ return;
// Check if target is still valid
- if (!CanWeld(uid, args.Tool, args.User, component))
+ if (!CanWeld(uid, args.Used.Value, args.User, component))
return;
component.IsWelded = !component.IsWelded;
@@ -95,11 +95,6 @@ public sealed class WeldableSystem : EntitySystem
_adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(args.User):user} {(!component.IsWelded ? "un" : "")}welded {ToPrettyString(uid):target}");
}
- private void OnWeldCanceled(EntityUid uid, WeldableComponent component, WeldCancelledEvent args)
- {
- component.BeingWelded = false;
- }
-
private void OnWeldChanged(EntityUid uid, LayerChangeOnWeldComponent component, WeldableChangedEvent args)
{
if (!TryComp(uid, out var fixtures))
@@ -148,30 +143,6 @@ public sealed class WeldableSystem : EntitySystem
return;
component.WeldingTime = time;
}
-
- ///
- /// Raised after welding do_after has finished. It doesn't guarantee success,
- /// use to get updated status.
- ///
- private sealed class WeldFinishedEvent : EntityEventArgs
- {
- public readonly EntityUid User;
- public readonly EntityUid Tool;
-
- public WeldFinishedEvent(EntityUid user, EntityUid tool)
- {
- User = user;
- Tool = tool;
- }
- }
-
- ///
- /// Raised when entity welding has failed.
- ///
- private sealed class WeldCancelledEvent : EntityEventArgs
- {
-
- }
}
///
diff --git a/Content.Server/Tools/ToolSystem.LatticeCutting.cs b/Content.Server/Tools/ToolSystem.LatticeCutting.cs
index 4a62865561..c9d08eb29a 100644
--- a/Content.Server/Tools/ToolSystem.LatticeCutting.cs
+++ b/Content.Server/Tools/ToolSystem.LatticeCutting.cs
@@ -2,6 +2,7 @@
using Content.Server.Maps;
using Content.Server.Tools.Components;
using Content.Shared.Database;
+using Content.Shared.DoAfter;
using Content.Shared.Interaction;
using Content.Shared.Maps;
using Content.Shared.Tools.Components;
@@ -22,6 +23,9 @@ public sealed partial class ToolSystem
private void OnLatticeCutComplete(EntityUid uid, LatticeCuttingComponent component, LatticeCuttingCompleteEvent args)
{
+ if (args.Cancelled)
+ return;
+
var gridUid = args.Coordinates.GetGridUid(EntityManager);
if (gridUid == null)
return;
@@ -50,10 +54,6 @@ public sealed partial class ToolSystem
private bool TryCut(EntityUid toolEntity, EntityUid user, LatticeCuttingComponent component, EntityCoordinates clickLocation)
{
- ToolComponent? tool = null;
- if (component.ToolComponentNeeded && !TryComp(toolEntity, out tool))
- return false;
-
if (!_mapManager.TryGetGrid(clickLocation.GetGridUid(EntityManager), out var mapGrid))
return false;
@@ -71,24 +71,8 @@ public sealed partial class ToolSystem
|| tile.IsBlockedTurf(true))
return false;
- var toolEvData = new ToolEventData(new LatticeCuttingCompleteEvent(clickLocation, user), targetEntity: toolEntity);
-
- if (!UseTool(toolEntity, user, null, component.Delay, new[] {component.QualityNeeded}, toolEvData, toolComponent: tool))
- return false;
-
- return true;
- }
-
- private sealed class LatticeCuttingCompleteEvent : EntityEventArgs
- {
- public EntityCoordinates Coordinates;
- public EntityUid User;
-
- public LatticeCuttingCompleteEvent(EntityCoordinates coordinates, EntityUid user)
- {
- Coordinates = coordinates;
- User = user;
- }
+ var ev = new LatticeCuttingCompleteEvent(clickLocation);
+ return UseTool(toolEntity, user, toolEntity, component.Delay, component.QualityNeeded, ev);
}
}
diff --git a/Content.Server/Tools/ToolSystem.TilePrying.cs b/Content.Server/Tools/ToolSystem.TilePrying.cs
index ea257548d3..59c041010b 100644
--- a/Content.Server/Tools/ToolSystem.TilePrying.cs
+++ b/Content.Server/Tools/ToolSystem.TilePrying.cs
@@ -1,6 +1,7 @@
using System.Threading;
using Content.Server.Fluids.Components;
using Content.Server.Tools.Components;
+using Content.Shared.DoAfter;
using Content.Shared.Interaction;
using Content.Shared.Maps;
using Content.Shared.Tools.Components;
@@ -18,8 +19,7 @@ public sealed partial class ToolSystem
private void InitializeTilePrying()
{
SubscribeLocalEvent(OnTilePryingAfterInteract);
- SubscribeLocalEvent(OnTilePryComplete);
- SubscribeLocalEvent(OnTilePryCancelled);
+ SubscribeLocalEvent(OnTilePryComplete);
}
private void OnTilePryingAfterInteract(EntityUid uid, TilePryingComponent component, AfterInteractEvent args)
@@ -30,9 +30,11 @@ public sealed partial class ToolSystem
args.Handled = true;
}
- private void OnTilePryComplete(EntityUid uid, TilePryingComponent component, TilePryingCompleteEvent args)
+ private void OnTilePryComplete(EntityUid uid, TilePryingComponent component, TilePryingDoAfterEvent args)
{
- component.CancelToken = null;
+ if (args.Cancelled)
+ return;
+
var gridUid = args.Coordinates.GetGridUid(EntityManager);
if (!_mapManager.TryGetGrid(gridUid, out var grid))
{
@@ -44,14 +46,9 @@ public sealed partial class ToolSystem
_tile.PryTile(tile);
}
- private void OnTilePryCancelled(EntityUid uid, TilePryingComponent component, TilePryingCancelledEvent args)
- {
- component.CancelToken = null;
- }
-
private bool TryPryTile(EntityUid toolEntity, EntityUid user, TilePryingComponent component, EntityCoordinates clickLocation)
{
- if (!TryComp(toolEntity, out var tool) && component.ToolComponentNeeded || component.CancelToken != null)
+ if (!TryComp(toolEntity, out var tool) && component.ToolComponentNeeded)
return false;
if (!_mapManager.TryGetGrid(clickLocation.GetGridUid(EntityManager), out var mapGrid))
@@ -69,28 +66,8 @@ public sealed partial class ToolSystem
if (!tileDef.CanCrowbar)
return false;
- 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, cancelToken: component.CancelToken))
- return false;
-
- return true;
- }
-
- private sealed class TilePryingCompleteEvent : EntityEventArgs
- {
- public readonly EntityCoordinates Coordinates;
-
- public TilePryingCompleteEvent(EntityCoordinates coordinates)
- {
- Coordinates = coordinates;
- }
- }
-
- private sealed class TilePryingCancelledEvent : EntityEventArgs
- {
+ var ev = new TilePryingDoAfterEvent(clickLocation);
+ return UseTool(toolEntity, user, toolEntity, component.Delay, component.QualityNeeded, ev, toolComponent: tool);
}
}
diff --git a/Content.Server/Tools/ToolSystem.Welder.cs b/Content.Server/Tools/ToolSystem.Welder.cs
index d50d4c106f..43f43dc9d4 100644
--- a/Content.Server/Tools/ToolSystem.Welder.cs
+++ b/Content.Server/Tools/ToolSystem.Welder.cs
@@ -4,6 +4,7 @@ using Content.Server.Chemistry.Components.SolutionManager;
using Content.Server.Chemistry.EntitySystems;
using Content.Server.Tools.Components;
using Content.Shared.Database;
+using Content.Shared.DoAfter;
using Content.Shared.Examine;
using Content.Shared.FixedPoint;
using Content.Shared.Interaction;
@@ -15,6 +16,7 @@ using Content.Shared.Weapons.Melee.Events;
using Robust.Server.GameObjects;
using Robust.Shared.Audio;
using Robust.Shared.GameStates;
+using Robust.Shared.Utility;
namespace Content.Server.Tools
{
@@ -38,8 +40,8 @@ namespace Content.Server.Tools
SubscribeLocalEvent(OnWelderSolutionChange);
SubscribeLocalEvent(OnWelderActivate);
SubscribeLocalEvent(OnWelderAfterInteract);
- SubscribeLocalEvent(OnWelderToolUseAttempt);
- SubscribeLocalEvent(OnWelderToolUseFinishAttempt);
+ SubscribeLocalEvent>(OnWelderToolUseAttempt);
+ SubscribeLocalEvent(OnWelderDoAfter);
SubscribeLocalEvent(OnWelderShutdown);
SubscribeLocalEvent