diff --git a/Content.Server/Construction/AnchorableSystem.cs b/Content.Server/Construction/AnchorableSystem.cs index 2760a9db15..1d8e98bd55 100644 --- a/Content.Server/Construction/AnchorableSystem.cs +++ b/Content.Server/Construction/AnchorableSystem.cs @@ -1,3 +1,4 @@ +using System.Threading; using System.Threading.Tasks; using Content.Server.Administration.Logs; using Content.Server.Coordinates.Helpers; @@ -17,13 +18,81 @@ namespace Content.Server.Construction [Dependency] private readonly ToolSystem _toolSystem = default!; [Dependency] private readonly PullingSystem _pullingSystem = default!; + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnAnchorComplete2); + SubscribeLocalEvent(OnAnchorCancelled2); + SubscribeLocalEvent(OnUnanchorComplete2); + SubscribeLocalEvent(OnUnanchorCancelled2); + } + + private void OnUnanchorCancelled2(EntityUid uid, AnchorableComponent component, TryUnanchorCancelledEvent args) + { + component.CancelToken = null; + } + + private void OnUnanchorComplete2(EntityUid uid, AnchorableComponent component, TryUnanchorCompletedEvent args) + { + component.CancelToken = null; + var xform = Transform(uid); + + RaiseLocalEvent(uid, new BeforeUnanchoredEvent(args.User, args.Using), false); + + xform.Anchored = false; + + RaiseLocalEvent(uid, new UserUnanchoredEvent(args.User, args.Using), false); + + _adminLogs.Add( + LogType.Action, + LogImpact.Low, + $"{EntityManager.ToPrettyString(args.User):user} unanchored {EntityManager.ToPrettyString(uid):anchored} using {EntityManager.ToPrettyString(args.Using):using}" + ); + } + + private void OnAnchorCancelled2(EntityUid uid, AnchorableComponent component, TryAnchorCancelledEvent args) + { + component.CancelToken = null; + } + + private void OnAnchorComplete2(EntityUid uid, AnchorableComponent component, TryAnchorCompletedEvent args) + { + component.CancelToken = null; + var xform = Transform(uid); + + // Snap rotation to cardinal (multiple of 90) + var rot = xform.LocalRotation; + xform.LocalRotation = Math.Round(rot / (Math.PI / 2)) * (Math.PI / 2); + + if (TryComp(uid, out var pullable) && pullable.Puller != null) + { + _pullingSystem.TryStopPull(pullable); + } + + if (component.Snap) + xform.Coordinates = xform.Coordinates.SnapToGrid(); + + RaiseLocalEvent(uid, new BeforeAnchoredEvent(args.User, args.Using), false); + + xform.Anchored = true; + + RaiseLocalEvent(uid, new UserAnchoredEvent(args.User, args.Using), false); + + _adminLogs.Add( + LogType.Action, + LogImpact.Low, + $"{EntityManager.ToPrettyString(args.User):user} anchored {EntityManager.ToPrettyString(uid):anchored} using {EntityManager.ToPrettyString(args.Using):using}" + ); + } + /// /// Checks if a tool can change the anchored status. /// /// true if it is valid, false otherwise - private async Task Valid(EntityUid uid, EntityUid userUid, EntityUid usingUid, bool anchoring, AnchorableComponent? anchorable = null, ToolComponent? usingTool = null) + private bool Valid(EntityUid uid, EntityUid userUid, EntityUid usingUid, bool anchoring, AnchorableComponent? anchorable = null, ToolComponent? usingTool = null) { - if (!Resolve(uid, ref anchorable)) + if (!Resolve(uid, ref anchorable) || + anchorable.CancelToken != null) return false; if (!Resolve(usingUid, ref usingTool)) @@ -41,111 +110,106 @@ namespace Content.Server.Construction if (attempt.Cancelled) return false; - return await _toolSystem.UseTool(usingUid, userUid, uid, 0f, anchorable.Delay + attempt.Delay, anchorable.Tool, toolComponent:usingTool); + return true; } /// /// Tries to anchor the entity. /// /// true if anchored, false otherwise - public async Task TryAnchor(EntityUid uid, EntityUid userUid, EntityUid usingUid, + private void TryAnchor(EntityUid uid, EntityUid userUid, EntityUid usingUid, AnchorableComponent? anchorable = null, TransformComponent? transform = null, SharedPullableComponent? pullable = null, ToolComponent? usingTool = null) { - if (!Resolve(uid, ref anchorable, ref transform)) - return false; + if (!Resolve(uid, ref anchorable, ref transform)) return; // Optional resolves. Resolve(uid, ref pullable, false); - if (!Resolve(usingUid, ref usingTool)) - return false; + if (!Resolve(usingUid, ref usingTool)) return; - if (!(await Valid(uid, userUid, usingUid, true, anchorable, usingTool))) - { - return false; - } + if (!Valid(uid, userUid, usingUid, true, anchorable, usingTool)) return; - // Snap rotation to cardinal (multiple of 90) - var rot = transform.LocalRotation; - transform.LocalRotation = Math.Round(rot / (Math.PI / 2)) * (Math.PI / 2); + anchorable.CancelToken = new CancellationTokenSource(); - if (pullable is { Puller: {} }) - { - _pullingSystem.TryStopPull(pullable); - } - - if (anchorable.Snap) - transform.Coordinates = transform.Coordinates.SnapToGrid(); - - RaiseLocalEvent(uid, new BeforeAnchoredEvent(userUid, usingUid), false); - - transform.Anchored = true; - - RaiseLocalEvent(uid, new UserAnchoredEvent(userUid, usingUid), false); - - _adminLogs.Add( - LogType.Action, - LogImpact.Low, - $"{EntityManager.ToPrettyString(userUid):user} anchored {EntityManager.ToPrettyString(uid):anchored} using {EntityManager.ToPrettyString(usingUid):using}" - ); - - return true; + _toolSystem.UseTool(usingUid, userUid, uid, 0f, anchorable.Delay, usingTool.Qualities, + new TryAnchorCompletedEvent(), new TryAnchorCancelledEvent(), uid, cancelToken: anchorable.CancelToken.Token); } /// /// Tries to unanchor the entity. /// /// true if unanchored, false otherwise - public async Task TryUnAnchor(EntityUid uid, EntityUid userUid, EntityUid usingUid, + private void TryUnAnchor(EntityUid uid, EntityUid userUid, EntityUid usingUid, AnchorableComponent? anchorable = null, TransformComponent? transform = null, ToolComponent? usingTool = null) { - if (!Resolve(uid, ref anchorable, ref transform)) - return false; + if (!Resolve(uid, ref anchorable, ref transform) || + anchorable.CancelToken != null) + return; - if (!Resolve(usingUid, ref usingTool)) - return false; + if (!Resolve(usingUid, ref usingTool)) return; - if (!(await Valid(uid, userUid, usingUid, false))) - { - return false; - } + if (!Valid(uid, userUid, usingUid, false)) return; - RaiseLocalEvent(uid, new BeforeUnanchoredEvent(userUid, usingUid), false); + anchorable.CancelToken = new CancellationTokenSource(); - transform.Anchored = false; - - RaiseLocalEvent(uid, new UserUnanchoredEvent(userUid, usingUid), false); - - _adminLogs.Add( - LogType.Action, - LogImpact.Low, - $"{EntityManager.ToPrettyString(userUid):user} unanchored {EntityManager.ToPrettyString(uid):anchored} using {EntityManager.ToPrettyString(usingUid):using}" - ); - - return true; + _toolSystem.UseTool(usingUid, userUid, uid, 0f, anchorable.Delay, usingTool.Qualities, + new TryUnanchorCompletedEvent(), new TryUnanchorCancelledEvent(), uid, cancelToken: anchorable.CancelToken.Token); } /// /// Tries to toggle the anchored status of this component's owner. /// /// true if toggled, false otherwise - public override async Task TryToggleAnchor(EntityUid uid, EntityUid userUid, EntityUid usingUid, + public override void TryToggleAnchor(EntityUid uid, EntityUid userUid, EntityUid usingUid, AnchorableComponent? anchorable = null, TransformComponent? transform = null, SharedPullableComponent? pullable = null, ToolComponent? usingTool = null) { if (!Resolve(uid, ref transform)) - return false; + return; + + if (transform.Anchored) + { + TryUnAnchor(uid, userUid, usingUid, anchorable, transform, usingTool); + } + else + { + TryAnchor(uid, userUid, usingUid, anchorable, transform, pullable, usingTool); + } + } + + private abstract class AnchorEvent : EntityEventArgs + { + public EntityUid User; + public EntityUid Using; + + public readonly TransformComponent Transform = default!; + } + + private sealed class TryUnanchorCompletedEvent : AnchorEvent + { + + } + + private sealed class TryUnanchorCancelledEvent : AnchorEvent + { + + } + + private sealed class TryAnchorCompletedEvent : AnchorEvent + { + + } + + private sealed class TryAnchorCancelledEvent : AnchorEvent + { - return transform.Anchored ? - await TryUnAnchor(uid, userUid, usingUid, anchorable, transform, usingTool) : - await TryAnchor(uid, userUid, usingUid, anchorable, transform, pullable, usingTool); } } } diff --git a/Content.Shared/Construction/Components/AnchorableComponent.cs b/Content.Shared/Construction/Components/AnchorableComponent.cs index c4e2512147..f7e6dbc90e 100644 --- a/Content.Shared/Construction/Components/AnchorableComponent.cs +++ b/Content.Shared/Construction/Components/AnchorableComponent.cs @@ -1,3 +1,4 @@ +using System.Threading; using Content.Shared.Construction.EntitySystems; using Content.Shared.Tools; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; @@ -19,7 +20,9 @@ namespace Content.Shared.Construction.Components /// [ViewVariables(VVAccess.ReadWrite)] [DataField("delay")] - public float Delay = 0.5f; + public float Delay = 1f; + + public CancellationTokenSource? CancelToken = null; } public abstract class BaseAnchoredAttemptEvent : CancellableEntityEventArgs diff --git a/Content.Shared/Construction/EntitySystems/SharedAnchorableSystem.cs b/Content.Shared/Construction/EntitySystems/SharedAnchorableSystem.cs index cb7d85ab2b..7d8c32a647 100644 --- a/Content.Shared/Construction/EntitySystems/SharedAnchorableSystem.cs +++ b/Content.Shared/Construction/EntitySystems/SharedAnchorableSystem.cs @@ -15,7 +15,7 @@ public abstract class SharedAnchorableSystem : EntitySystem SubscribeLocalEvent(OnInteractUsing, after: new[] { typeof(SharedConstructionSystem) }); } - private async void OnInteractUsing(EntityUid uid, AnchorableComponent anchorable, InteractUsingEvent args) + private void OnInteractUsing(EntityUid uid, AnchorableComponent anchorable, InteractUsingEvent args) { if (args.Handled) return; @@ -25,16 +25,16 @@ public abstract class SharedAnchorableSystem : EntitySystem return; args.Handled = true; - await TryToggleAnchor(uid, args.User, args.Used, anchorable, usingTool: usedTool); + TryToggleAnchor(uid, args.User, args.Used, anchorable, usingTool: usedTool); } - public virtual async Task TryToggleAnchor(EntityUid uid, EntityUid userUid, EntityUid usingUid, + public virtual void TryToggleAnchor(EntityUid uid, EntityUid userUid, EntityUid usingUid, AnchorableComponent? anchorable = null, TransformComponent? transform = null, SharedPullableComponent? pullable = null, ToolComponent? usingTool = null) { // Thanks tool system. - return false; + return; } }