From fe6590bbe6e68ebd38c4a99e0cda0178a6ea4e2c Mon Sep 17 00:00:00 2001 From: Vera Aguilera Puerto <6766154+Zumorica@users.noreply.github.com> Date: Tue, 9 Nov 2021 08:08:30 +0100 Subject: [PATCH] Makes Anchorable ECS. (#5222) --- .../AtmosUnsafeUnanchorSystem.cs | 5 +- .../Construction/AnchorableSystem.cs | 151 +++++++++++++++++ .../Components/AnchorableComponent.cs | 154 ++---------------- 3 files changed, 171 insertions(+), 139 deletions(-) create mode 100644 Content.Server/Construction/AnchorableSystem.cs diff --git a/Content.Server/Atmos/Piping/EntitySystems/AtmosUnsafeUnanchorSystem.cs b/Content.Server/Atmos/Piping/EntitySystems/AtmosUnsafeUnanchorSystem.cs index 47dd0acbcc..68005e9ff4 100644 --- a/Content.Server/Atmos/Piping/EntitySystems/AtmosUnsafeUnanchorSystem.cs +++ b/Content.Server/Atmos/Piping/EntitySystems/AtmosUnsafeUnanchorSystem.cs @@ -3,12 +3,14 @@ using Content.Server.Atmos.Piping.Components; using Content.Server.Construction.Components; using Content.Server.NodeContainer; using Content.Server.NodeContainer.Nodes; +using Content.Server.Popups; using Content.Shared.Atmos; using Content.Shared.Popups; using JetBrains.Annotations; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Localization; +using Robust.Shared.Player; namespace Content.Server.Atmos.Piping.EntitySystems { @@ -16,6 +18,7 @@ namespace Content.Server.Atmos.Piping.EntitySystems public class AtmosUnsafeUnanchorSystem : EntitySystem { [Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!; + [Dependency] private readonly PopupSystem _popupSystem = default!; public override void Initialize() { @@ -38,7 +41,7 @@ namespace Content.Server.Atmos.Piping.EntitySystems if ((pipe.Air.Pressure - environment.Pressure) > 2 * Atmospherics.OneAtmosphere) { args.Delay += 1.5f; - args.User?.PopupMessageCursor(Loc.GetString("comp-atmos-unsafe-unanchor-warning")); + _popupSystem.PopupCursor(Loc.GetString("comp-atmos-unsafe-unanchor-warning"), Filter.Entities(args.User)); return; // Show the warning only once. } } diff --git a/Content.Server/Construction/AnchorableSystem.cs b/Content.Server/Construction/AnchorableSystem.cs new file mode 100644 index 0000000000..d9109071f2 --- /dev/null +++ b/Content.Server/Construction/AnchorableSystem.cs @@ -0,0 +1,151 @@ +using System; +using System.Threading.Tasks; +using Content.Server.Construction.Components; +using Content.Server.Coordinates.Helpers; +using Content.Server.Pulling; +using Content.Server.Tools; +using Content.Server.Tools.Components; +using Content.Shared.Interaction; +using Content.Shared.Pulling.Components; +using Robust.Shared.GameObjects; +using Robust.Shared.IoC; + +namespace Content.Server.Construction +{ + public class AnchorableSystem : EntitySystem + { + [Dependency] private readonly ToolSystem _toolSystem = default!; + [Dependency] private readonly PullingSystem _pullingSystem = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnInteractUsing, after:new []{typeof(ConstructionSystem)}); + } + + private async void OnInteractUsing(EntityUid uid, AnchorableComponent anchorable, InteractUsingEvent args) + { + args.Handled = await TryToggleAnchor(uid, args.User.Uid, args.Used.Uid, anchorable); + } + + /// + /// 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) + { + if (!Resolve(uid, ref anchorable)) + return false; + + if (!Resolve(usingUid, ref usingTool)) + return false; + + BaseAnchoredAttemptEvent attempt = + anchoring ? new AnchorAttemptEvent(userUid, usingUid) : new UnanchorAttemptEvent(userUid, usingUid); + + // Need to cast the event or it will be raised as BaseAnchoredAttemptEvent. + if (anchoring) + RaiseLocalEvent(uid, (AnchorAttemptEvent) attempt, false); + else + RaiseLocalEvent(uid, (UnanchorAttemptEvent) attempt, false); + + if (attempt.Cancelled) + return false; + + return await _toolSystem.UseTool(usingUid, userUid, uid, 0f, 0.5f + attempt.Delay, anchorable.Tool, toolComponent:usingTool); + } + + /// + /// Tries to anchor the entity. + /// + /// true if anchored, false otherwise + public async Task 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; + + // Optional resolves. + Resolve(uid, ref pullable); + + if (!Resolve(usingUid, ref usingTool)) + return false; + + if (!(await Valid(uid, userUid, usingUid, true, anchorable, usingTool))) + { + return false; + } + + // Snap rotation to cardinal (multiple of 90) + var rot = transform.LocalRotation; + transform.LocalRotation = Math.Round(rot / (Math.PI / 2)) * (Math.PI / 2); + + 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 AnchoredEvent(userUid, usingUid), false); + + return true; + } + + /// + /// Tries to unanchor the entity. + /// + /// true if unanchored, false otherwise + public async Task 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(usingUid, ref usingTool)) + return false; + + if (!(await Valid(uid, userUid, usingUid, false))) + { + return false; + } + + RaiseLocalEvent(uid, new BeforeUnanchoredEvent(userUid, usingUid), false); + + transform.Anchored = false; + + RaiseLocalEvent(uid, new UnanchoredEvent(userUid, usingUid), false); + + return true; + } + + /// + /// Tries to toggle the anchored status of this component's owner. + /// + /// true if toggled, false otherwise + public async Task 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 transform.Anchored ? + await TryUnAnchor(uid, userUid, usingUid, anchorable, transform, usingTool) : + await TryAnchor(uid, userUid, usingUid, anchorable, transform, pullable, usingTool); + } + } +} diff --git a/Content.Server/Construction/Components/AnchorableComponent.cs b/Content.Server/Construction/Components/AnchorableComponent.cs index 351c4b7676..5c6fd84d92 100644 --- a/Content.Server/Construction/Components/AnchorableComponent.cs +++ b/Content.Server/Construction/Components/AnchorableComponent.cs @@ -1,15 +1,7 @@ -using System; -using System.Threading.Tasks; -using Content.Server.Coordinates.Helpers; -using Content.Server.Pulling; -using Content.Server.Tools; -using Content.Server.Tools.Components; using Content.Shared.Interaction; using Content.Shared.Tools; -using Content.Shared.Tools.Components; -using Content.Shared.Pulling.Components; +using Robust.Shared.Analyzers; using Robust.Shared.GameObjects; -using Robust.Shared.Physics; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; using Robust.Shared.ViewVariables; @@ -17,137 +9,23 @@ using Robust.Shared.ViewVariables; namespace Content.Server.Construction.Components { // TODO: Move this component's logic to an EntitySystem. - [RegisterComponent] - public class AnchorableComponent : Component, IInteractUsing + [RegisterComponent, Friend(typeof(AnchorableSystem))] + public class AnchorableComponent : Component { public override string Name => "Anchorable"; - [ViewVariables] [DataField("tool", customTypeSerializer:typeof(PrototypeIdSerializer))] public string Tool { get; private set; } = "Anchoring"; - [ViewVariables] - int IInteractUsing.Priority => 1; - - [ViewVariables(VVAccess.ReadWrite)] [DataField("snap")] + [ViewVariables(VVAccess.ReadWrite)] public bool Snap { get; private set; } = true; - - /// - /// Checks if a tool can change the anchored status. - /// - /// The user doing the action - /// The tool being used - /// True if we're anchoring, and false if we're unanchoring. - /// true if it is valid, false otherwise - private async Task Valid(IEntity user, IEntity utilizing, bool anchoring) - { - if (!Owner.HasComponent()) - { - return false; - } - - if (!utilizing.TryGetComponent(out ToolComponent? tool)) - return false; - - BaseAnchoredAttemptEvent attempt = - anchoring ? new AnchorAttemptEvent(user, utilizing) : new UnanchorAttemptEvent(user, utilizing); - - // Need to cast the event or it will be raised as BaseAnchoredAttemptEvent. - if (anchoring) - Owner.EntityManager.EventBus.RaiseLocalEvent(Owner.Uid, (AnchorAttemptEvent) attempt, false); - else - Owner.EntityManager.EventBus.RaiseLocalEvent(Owner.Uid, (UnanchorAttemptEvent) attempt, false); - - if (attempt.Cancelled) - return false; - - return await EntitySystem.Get().UseTool(utilizing.Uid, user.Uid, Owner.Uid, 0f, 0.5f + attempt.Delay, Tool, toolComponent:tool); - } - - /// - /// Tries to anchor the owner of this component. - /// - /// The entity doing the anchoring - /// The tool being used - /// true if anchored, false otherwise - public async Task TryAnchor(IEntity user, IEntity utilizing) - { - if (!(await Valid(user, utilizing, true))) - { - return false; - } - - // Snap rotation to cardinal (multiple of 90) - var rot = Owner.Transform.LocalRotation; - Owner.Transform.LocalRotation = Math.Round(rot / (Math.PI / 2)) * (Math.PI / 2); - - if (Owner.TryGetComponent(out SharedPullableComponent? pullableComponent)) - { - if (pullableComponent.Puller != null) - { - EntitySystem.Get().TryStopPull(pullableComponent); - } - } - - if (Snap) - Owner.SnapToGrid(Owner.EntityManager); - - Owner.EntityManager.EventBus.RaiseLocalEvent(Owner.Uid, new BeforeAnchoredEvent(user, utilizing), false); - - Owner.Transform.Anchored = true; - - Owner.EntityManager.EventBus.RaiseLocalEvent(Owner.Uid, new AnchoredEvent(user, utilizing), false); - - return true; - } - - /// - /// Tries to unanchor the owner of this component. - /// - /// The entity doing the unanchoring - /// The tool being used, if any - /// Whether or not to ignore valid tool checks - /// true if unanchored, false otherwise - public async Task TryUnAnchor(IEntity user, IEntity utilizing) - { - if (!(await Valid(user, utilizing, false))) - { - return false; - } - - Owner.EntityManager.EventBus.RaiseLocalEvent(Owner.Uid, new BeforeUnanchoredEvent(user, utilizing), false); - - Owner.Transform.Anchored = false; - - Owner.EntityManager.EventBus.RaiseLocalEvent(Owner.Uid, new UnanchoredEvent(user, utilizing), false); - - return true; - } - - /// - /// Tries to toggle the anchored status of this component's owner. - /// - /// The entity doing the unanchoring - /// The tool being used - /// true if toggled, false otherwise - public async Task TryToggleAnchor(IEntity user, IEntity utilizing) - { - return Owner.Transform.Anchored ? - await TryUnAnchor(user, utilizing) : - await TryAnchor(user, utilizing); - } - - async Task IInteractUsing.InteractUsing(InteractUsingEventArgs eventArgs) - { - return await TryToggleAnchor(eventArgs.User, eventArgs.Using); - } } public abstract class BaseAnchoredAttemptEvent : CancellableEntityEventArgs { - public IEntity User { get; } - public IEntity Tool { get; } + public EntityUid User { get; } + public EntityUid Tool { get; } /// /// Extra delay to add to the do_after. @@ -156,7 +34,7 @@ namespace Content.Server.Construction.Components /// public float Delay { get; set; } = 0f; - protected BaseAnchoredAttemptEvent(IEntity user, IEntity tool) + protected BaseAnchoredAttemptEvent(EntityUid user, EntityUid tool) { User = user; Tool = tool; @@ -165,20 +43,20 @@ namespace Content.Server.Construction.Components public class AnchorAttemptEvent : BaseAnchoredAttemptEvent { - public AnchorAttemptEvent(IEntity user, IEntity tool) : base(user, tool) { } + public AnchorAttemptEvent(EntityUid user, EntityUid tool) : base(user, tool) { } } public class UnanchorAttemptEvent : BaseAnchoredAttemptEvent { - public UnanchorAttemptEvent(IEntity user, IEntity tool) : base(user, tool) { } + public UnanchorAttemptEvent(EntityUid user, EntityUid tool) : base(user, tool) { } } public abstract class BaseAnchoredEvent : EntityEventArgs { - public IEntity User { get; } - public IEntity Tool { get; } + public EntityUid User { get; } + public EntityUid Tool { get; } - protected BaseAnchoredEvent(IEntity user, IEntity tool) + protected BaseAnchoredEvent(EntityUid user, EntityUid tool) { User = user; Tool = tool; @@ -190,12 +68,12 @@ namespace Content.Server.Construction.Components /// public class BeforeAnchoredEvent : BaseAnchoredEvent { - public BeforeAnchoredEvent(IEntity user, IEntity tool) : base(user, tool) { } + public BeforeAnchoredEvent(EntityUid user, EntityUid tool) : base(user, tool) { } } public class AnchoredEvent : BaseAnchoredEvent { - public AnchoredEvent(IEntity user, IEntity tool) : base(user, tool) { } + public AnchoredEvent(EntityUid user, EntityUid tool) : base(user, tool) { } } /// @@ -203,11 +81,11 @@ namespace Content.Server.Construction.Components /// public class BeforeUnanchoredEvent : BaseAnchoredEvent { - public BeforeUnanchoredEvent(IEntity user, IEntity tool) : base(user, tool) { } + public BeforeUnanchoredEvent(EntityUid user, EntityUid tool) : base(user, tool) { } } public class UnanchoredEvent : BaseAnchoredEvent { - public UnanchoredEvent(IEntity user, IEntity tool) : base(user, tool) { } + public UnanchoredEvent(EntityUid user, EntityUid tool) : base(user, tool) { } } }