From fab331742ae9726a88ad41fb341d872ab5e3c93c Mon Sep 17 00:00:00 2001 From: Kara Date: Thu, 14 Jul 2022 04:45:31 -0700 Subject: [PATCH] Remove `IAfterInteract` (#9715) * remove gas analyzer iafterinteract * solution transfer + obsolete * cuffable * remove --- .../Atmos/Components/GasAnalyzerComponent.cs | 18 +---- .../Atmos/EntitySystems/GasAnalyzerSystem.cs | 29 ++++++++ .../Components/SolutionTransferComponent.cs | 74 +------------------ .../EntitySystems/SolutionTransferSystem.cs | 69 +++++++++++++++++ .../Cuffs/Components/HandcuffComponent.cs | 59 ++------------- Content.Server/Cuffs/CuffableSystem.cs | 54 ++++++++++++++ Content.Shared/Examine/ExamineSystemShared.cs | 28 ------- .../{IAfterInteract.cs => AfterInteract.cs} | 37 ---------- .../Helpers/SharedUnoccludedExtensions.cs | 32 -------- .../{IRangedInteract.cs => RangedInteract.cs} | 0 .../Popups/SharedPopupExtensions.cs | 4 + 11 files changed, 163 insertions(+), 241 deletions(-) rename Content.Shared/Interaction/{IAfterInteract.cs => AfterInteract.cs} (63%) rename Content.Shared/Interaction/{IRangedInteract.cs => RangedInteract.cs} (100%) diff --git a/Content.Server/Atmos/Components/GasAnalyzerComponent.cs b/Content.Server/Atmos/Components/GasAnalyzerComponent.cs index 8d1e1bcdb9..876a922d81 100644 --- a/Content.Server/Atmos/Components/GasAnalyzerComponent.cs +++ b/Content.Server/Atmos/Components/GasAnalyzerComponent.cs @@ -15,7 +15,7 @@ namespace Content.Server.Atmos.Components { [RegisterComponent] [ComponentReference(typeof(SharedGasAnalyzerComponent))] - public sealed class GasAnalyzerComponent : SharedGasAnalyzerComponent, IAfterInteract + public sealed class GasAnalyzerComponent : SharedGasAnalyzerComponent { [Dependency] private readonly IEntityManager _entities = default!; @@ -245,21 +245,5 @@ namespace Content.Server.Atmos.Components break; } } - - async Task IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs) - { - if (!eventArgs.CanReach) - { - eventArgs.User.PopupMessage(Loc.GetString("gas-analyzer-component-player-cannot-reach-message")); - return true; - } - - if (_entities.TryGetComponent(eventArgs.User, out ActorComponent? actor)) - { - OpenInterface(actor.PlayerSession, eventArgs.ClickLocation); - } - - return true; - } } } diff --git a/Content.Server/Atmos/EntitySystems/GasAnalyzerSystem.cs b/Content.Server/Atmos/EntitySystems/GasAnalyzerSystem.cs index 8ce8251f86..c7cf03c0d3 100644 --- a/Content.Server/Atmos/EntitySystems/GasAnalyzerSystem.cs +++ b/Content.Server/Atmos/EntitySystems/GasAnalyzerSystem.cs @@ -1,11 +1,24 @@ using Content.Server.Atmos.Components; +using Content.Server.Popups; +using Content.Shared.Interaction; using JetBrains.Annotations; +using Robust.Server.GameObjects; +using Robust.Shared.Player; namespace Content.Server.Atmos.EntitySystems { [UsedImplicitly] public sealed class GasAnalyzerSystem : EntitySystem { + [Dependency] private readonly PopupSystem _popup = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnAfterInteract); + } + public override void Update(float frameTime) { foreach (var analyzer in EntityManager.EntityQuery(true)) @@ -13,5 +26,21 @@ namespace Content.Server.Atmos.EntitySystems analyzer.Update(frameTime); } } + + private void OnAfterInteract(EntityUid uid, GasAnalyzerComponent component, AfterInteractEvent args) + { + if (!args.CanReach) + { + _popup.PopupEntity(Loc.GetString("gas-analyzer-component-player-cannot-reach-message"), args.User, Filter.Entities(args.User)); + return; + } + + if (TryComp(args.User, out ActorComponent? actor)) + { + component.OpenInterface(actor.PlayerSession, args.ClickLocation); + } + + args.Handled = true; + } } } diff --git a/Content.Server/Chemistry/Components/SolutionTransferComponent.cs b/Content.Server/Chemistry/Components/SolutionTransferComponent.cs index 4e07041cc0..46cf733637 100644 --- a/Content.Server/Chemistry/Components/SolutionTransferComponent.cs +++ b/Content.Server/Chemistry/Components/SolutionTransferComponent.cs @@ -14,15 +14,8 @@ namespace Content.Server.Chemistry.Components /// Gives click behavior for transferring to/from other reagent containers. /// [RegisterComponent] - public sealed class SolutionTransferComponent : Component, IAfterInteract + public sealed class SolutionTransferComponent : Component { - [Dependency] private readonly IEntityManager _entities = default!; - - // Behavior is as such: - // If it's a reagent tank, TAKE reagent. - // If it's anything else, GIVE reagent. - // Of course, only if possible. - /// /// The amount of solution to be transferred from this solution when clicking on other solutions with it. /// @@ -102,70 +95,5 @@ namespace Content.Server.Chemistry.Components MaximumTransferAmount.Int())); TransferAmount = amount; } - - async Task IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs) - { - if (!eventArgs.CanReach || eventArgs.Target == null) - return false; - - var target = eventArgs.Target!.Value; - var solutionsSys = EntitySystem.Get(); - var transferSystem = EntitySystem.Get(); - - //Special case for reagent tanks, because normally clicking another container will give solution, not take it. - if (CanReceive && !_entities.HasComponent(target) // target must not be refillable (e.g. Reagent Tanks) - && solutionsSys.TryGetDrainableSolution(target, out var targetDrain) // target must be drainable - && _entities.TryGetComponent(Owner, out RefillableSolutionComponent? refillComp) - && solutionsSys.TryGetRefillableSolution(Owner, out var ownerRefill, refillable: refillComp)) - - { - - var transferAmount = TransferAmount; // This is the player-configurable transfer amount of "Owner," not the target reagent tank. - - if (_entities.TryGetComponent(Owner, out RefillableSolutionComponent? refill) && refill.MaxRefill != null) // Owner is the entity receiving solution from target. - { - transferAmount = FixedPoint2.Min(transferAmount, (FixedPoint2) refill.MaxRefill); // if the receiver has a smaller transfer limit, use that instead - } - - var transferred = transferSystem.Transfer(eventArgs.User, target, targetDrain, Owner, ownerRefill, transferAmount); - if (transferred > 0) - { - var toTheBrim = ownerRefill.AvailableVolume == 0; - var msg = toTheBrim - ? "comp-solution-transfer-fill-fully" - : "comp-solution-transfer-fill-normal"; - - target.PopupMessage(eventArgs.User, - Loc.GetString(msg, ("owner", eventArgs.Target), ("amount", transferred), ("target", Owner))); - return true; - } - } - - // if target is refillable, and owner is drainable - if (CanSend && solutionsSys.TryGetRefillableSolution(target, out var targetRefill) - && solutionsSys.TryGetDrainableSolution(Owner, out var ownerDrain)) - { - var transferAmount = TransferAmount; - - if (_entities.TryGetComponent(target, out RefillableSolutionComponent? refill) && refill.MaxRefill != null) - { - transferAmount = FixedPoint2.Min(transferAmount, (FixedPoint2) refill.MaxRefill); - } - - var transferred = transferSystem.Transfer(eventArgs.User, Owner, ownerDrain, target, targetRefill, transferAmount); - - if (transferred > 0) - { - Owner.PopupMessage(eventArgs.User, - Loc.GetString("comp-solution-transfer-transfer-solution", - ("amount", transferred), - ("target", target))); - - return true; - } - } - - return false; - } } } diff --git a/Content.Server/Chemistry/EntitySystems/SolutionTransferSystem.cs b/Content.Server/Chemistry/EntitySystems/SolutionTransferSystem.cs index 2dc54ae99e..fff81125dd 100644 --- a/Content.Server/Chemistry/EntitySystems/SolutionTransferSystem.cs +++ b/Content.Server/Chemistry/EntitySystems/SolutionTransferSystem.cs @@ -1,9 +1,11 @@ using Content.Shared.Verbs; using Content.Server.Chemistry.Components; +using Content.Server.Chemistry.Components.SolutionManager; using JetBrains.Annotations; using Robust.Server.GameObjects; using Content.Shared.Chemistry.Components; using Content.Shared.FixedPoint; +using Content.Shared.Interaction; using Content.Shared.Popups; namespace Content.Server.Chemistry.EntitySystems @@ -11,6 +13,8 @@ namespace Content.Server.Chemistry.EntitySystems [UsedImplicitly] public sealed class SolutionTransferSystem : EntitySystem { + [Dependency] private readonly SolutionContainerSystem _solutionContainer = default!; + /// /// Default transfer amounts for the set-transfer verb. /// @@ -21,6 +25,7 @@ namespace Content.Server.Chemistry.EntitySystems base.Initialize(); SubscribeLocalEvent>(AddSetTransferVerbs); + SubscribeLocalEvent(OnAfterInteract); } private void AddSetTransferVerbs(EntityUid uid, SolutionTransferComponent component, GetVerbsEvent args) @@ -63,6 +68,70 @@ namespace Content.Server.Chemistry.EntitySystems } } + private void OnAfterInteract(EntityUid uid, SolutionTransferComponent component, AfterInteractEvent args) + { + if (!args.CanReach || args.Target == null) + return; + + var target = args.Target!.Value; + + //Special case for reagent tanks, because normally clicking another container will give solution, not take it. + if (component.CanReceive && !EntityManager.HasComponent(target) // target must not be refillable (e.g. Reagent Tanks) + && _solutionContainer.TryGetDrainableSolution(target, out var targetDrain) // target must be drainable + && EntityManager.TryGetComponent(uid, out RefillableSolutionComponent? refillComp) + && _solutionContainer.TryGetRefillableSolution(uid, out var ownerRefill, refillable: refillComp)) + + { + + var transferAmount = component.TransferAmount; // This is the player-configurable transfer amount of "uid," not the target reagent tank. + + if (EntityManager.TryGetComponent(uid, out RefillableSolutionComponent? refill) && refill.MaxRefill != null) // uid is the entity receiving solution from target. + { + transferAmount = FixedPoint2.Min(transferAmount, (FixedPoint2) refill.MaxRefill); // if the receiver has a smaller transfer limit, use that instead + } + + var transferred = Transfer(args.User, target, targetDrain, uid, ownerRefill, transferAmount); + if (transferred > 0) + { + var toTheBrim = ownerRefill.AvailableVolume == 0; + var msg = toTheBrim + ? "comp-solution-transfer-fill-fully" + : "comp-solution-transfer-fill-normal"; + + target.PopupMessage(args.User, + Loc.GetString(msg, ("owner", args.Target), ("amount", transferred), ("target", uid))); + + args.Handled = true; + return; + } + } + + // if target is refillable, and owner is drainable + if (component.CanSend && _solutionContainer.TryGetRefillableSolution(target, out var targetRefill) + && _solutionContainer.TryGetDrainableSolution(uid, out var ownerDrain)) + { + var transferAmount = component.TransferAmount; + + if (EntityManager.TryGetComponent(target, out RefillableSolutionComponent? refill) && refill.MaxRefill != null) + { + transferAmount = FixedPoint2.Min(transferAmount, (FixedPoint2) refill.MaxRefill); + } + + var transferred = Transfer(args.User, uid, ownerDrain, target, targetRefill, transferAmount); + + if (transferred > 0) + { + uid.PopupMessage(args.User, + Loc.GetString("comp-solution-transfer-transfer-solution", + ("amount", transferred), + ("target", target))); + + args.Handled = true; + return; + } + } + } + /// /// Transfer from a solution to another. /// diff --git a/Content.Server/Cuffs/Components/HandcuffComponent.cs b/Content.Server/Cuffs/Components/HandcuffComponent.cs index 59b0c6f90e..7d2877ba40 100644 --- a/Content.Server/Cuffs/Components/HandcuffComponent.cs +++ b/Content.Server/Cuffs/Components/HandcuffComponent.cs @@ -13,7 +13,7 @@ namespace Content.Server.Cuffs.Components { [RegisterComponent] [ComponentReference(typeof(SharedHandcuffComponent))] - public sealed class HandcuffComponent : SharedHandcuffComponent, IAfterInteract + public sealed class HandcuffComponent : SharedHandcuffComponent { [Dependency] private readonly IEntityManager _entities = default!; @@ -128,66 +128,17 @@ namespace Content.Server.Cuffs.Components /// /// Used to prevent DoAfter getting spammed. /// - private bool _cuffing; + public bool Cuffing; public override ComponentState GetComponentState() { return new HandcuffedComponentState(Broken ? BrokenState : string.Empty); } - async Task IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs) - { - if (_cuffing) return true; - - if (eventArgs.Target is not {Valid: true} target || - !_entities.TryGetComponent(eventArgs.Target.Value, out var cuffed)) - { - return false; - } - - if (Broken) - { - eventArgs.User.PopupMessage(Loc.GetString("handcuff-component-cuffs-broken-error")); - return true; - } - - if (!_entities.TryGetComponent(target, out var hands)) - { - eventArgs.User.PopupMessage(Loc.GetString("handcuff-component-target-has-no-hands-error",("targetName", eventArgs.Target))); - return true; - } - - if (cuffed.CuffedHandCount >= hands.Count) - { - eventArgs.User.PopupMessage(Loc.GetString("handcuff-component-target-has-no-free-hands-error",("targetName", eventArgs.Target))); - return true; - } - - if (!eventArgs.CanReach) - { - eventArgs.User.PopupMessage(Loc.GetString("handcuff-component-too-far-away-error")); - return true; - } - - if (eventArgs.Target == eventArgs.User) - { - eventArgs.User.PopupMessage(Loc.GetString("handcuff-component-target-self")); - } - else - { - eventArgs.User.PopupMessage(Loc.GetString("handcuff-component-start-cuffing-target-message",("targetName", eventArgs.Target))); - eventArgs.User.PopupMessage(target, Loc.GetString("handcuff-component-start-cuffing-by-other-message",("otherName", eventArgs.User))); - } - SoundSystem.Play(StartCuffSound.GetSound(), Filter.Pvs(Owner), Owner); - - TryUpdateCuff(eventArgs.User, target, cuffed); - return true; - } - /// /// Update the cuffed state of an entity /// - private async void TryUpdateCuff(EntityUid user, EntityUid target, CuffableComponent cuffs) + public async void TryUpdateCuff(EntityUid user, EntityUid target, CuffableComponent cuffs) { var cuffTime = CuffTime; @@ -205,11 +156,11 @@ namespace Content.Server.Cuffs.Components NeedHand = true }; - _cuffing = true; + Cuffing = true; var result = await EntitySystem.Get().WaitDoAfter(doAfterEventArgs); - _cuffing = false; + Cuffing = false; if (result != DoAfterStatus.Cancelled) { diff --git a/Content.Server/Cuffs/CuffableSystem.cs b/Content.Server/Cuffs/CuffableSystem.cs index 7df6eaed8f..6a42412e45 100644 --- a/Content.Server/Cuffs/CuffableSystem.cs +++ b/Content.Server/Cuffs/CuffableSystem.cs @@ -9,6 +9,8 @@ using Content.Shared.Verbs; using JetBrains.Annotations; using Robust.Shared.Player; using Content.Shared.Hands.EntitySystems; +using Content.Shared.Interaction; +using Robust.Shared.Audio; namespace Content.Server.Cuffs { @@ -25,6 +27,7 @@ namespace Content.Server.Cuffs SubscribeLocalEvent(OnHandCountChanged); SubscribeLocalEvent(OnUncuffAttempt); SubscribeLocalEvent>(AddUncuffVerb); + SubscribeLocalEvent(OnCuffAfterInteract); } private void AddUncuffVerb(EntityUid uid, CuffableComponent component, GetVerbsEvent args) @@ -46,6 +49,57 @@ namespace Content.Server.Cuffs args.Verbs.Add(verb); } + private void OnCuffAfterInteract(EntityUid uid, HandcuffComponent component, AfterInteractEvent args) + { + if (component.Cuffing) + return; + + if (args.Target is not {Valid: true} target || + !EntityManager.TryGetComponent(args.Target.Value, out var cuffed)) + { + return; + } + + if (component.Broken) + { + args.User.PopupMessage(Loc.GetString("handcuff-component-cuffs-broken-error")); + return; + } + + if (!EntityManager.TryGetComponent(target, out var hands)) + { + args.User.PopupMessage(Loc.GetString("handcuff-component-target-has-no-hands-error",("targetName", args.Target))); + return; + } + + if (cuffed.CuffedHandCount >= hands.Count) + { + args.User.PopupMessage(Loc.GetString("handcuff-component-target-has-no-free-hands-error",("targetName", args.Target))); + return; + } + + if (!args.CanReach) + { + args.User.PopupMessage(Loc.GetString("handcuff-component-too-far-away-error")); + return; + } + + if (args.Target == args.User) + { + args.User.PopupMessage(Loc.GetString("handcuff-component-target-self")); + } + else + { + args.User.PopupMessage(Loc.GetString("handcuff-component-start-cuffing-target-message",("targetName", args.Target))); + args.User.PopupMessage(target, Loc.GetString("handcuff-component-start-cuffing-by-other-message",("otherName", args.User))); + } + + SoundSystem.Play(component.StartCuffSound.GetSound(), Filter.Pvs(uid), uid); + + component.TryUpdateCuff(args.User, target, cuffed); + args.Handled = true; + } + private void OnUncuffAttempt(UncuffAttemptEvent args) { if (args.Cancelled) diff --git a/Content.Shared/Examine/ExamineSystemShared.cs b/Content.Shared/Examine/ExamineSystemShared.cs index a2d7a28c31..78d8662344 100644 --- a/Content.Shared/Examine/ExamineSystemShared.cs +++ b/Content.Shared/Examine/ExamineSystemShared.cs @@ -208,34 +208,6 @@ namespace Content.Shared.Examine return InRangeUnOccluded(originPos, other, range, predicate, ignoreInsideBlocker); } - public static bool InRangeUnOccluded(ITargetedInteractEventArgs args, float range, Ignored? predicate, bool ignoreInsideBlocker = true) - { - var entMan = IoCManager.Resolve(); - var originPos = entMan.GetComponent(args.User).MapPosition; - var otherPos = entMan.GetComponent(args.Target).MapPosition; - - return InRangeUnOccluded(originPos, otherPos, range, predicate, ignoreInsideBlocker); - } - - public static bool InRangeUnOccluded(DragDropEvent args, float range, Ignored? predicate, bool ignoreInsideBlocker = true) - { - var entMan = IoCManager.Resolve(); - var originPos = entMan.GetComponent(args.User).MapPosition; - var otherPos = args.DropLocation.ToMap(entMan); - - return InRangeUnOccluded(originPos, otherPos, range, predicate, ignoreInsideBlocker); - } - - public static bool InRangeUnOccluded(AfterInteractEventArgs args, float range, Ignored? predicate, bool ignoreInsideBlocker = true) - { - var entityManager = IoCManager.Resolve();; - var originPos = entityManager.GetComponent(args.User).MapPosition; - var target = args.Target; - var otherPos = (target != null ? entityManager.GetComponent(target.Value).MapPosition : args.ClickLocation.ToMap(entityManager)); - - return InRangeUnOccluded(originPos, otherPos, range, predicate, ignoreInsideBlocker); - } - public FormattedMessage GetExamineText(EntityUid entity, EntityUid? examiner) { var message = new FormattedMessage(); diff --git a/Content.Shared/Interaction/IAfterInteract.cs b/Content.Shared/Interaction/AfterInteract.cs similarity index 63% rename from Content.Shared/Interaction/IAfterInteract.cs rename to Content.Shared/Interaction/AfterInteract.cs index ba01d8d789..2f1f5c70a9 100644 --- a/Content.Shared/Interaction/IAfterInteract.cs +++ b/Content.Shared/Interaction/AfterInteract.cs @@ -5,43 +5,6 @@ using Robust.Shared.Map; namespace Content.Shared.Interaction { - /// - /// This interface gives components a behavior when their entity is in the active hand, when - /// clicking on another object and no interaction occurs, at any range. This includes - /// clicking on an object in the world as well as clicking on an object in inventory. - /// - [RequiresExplicitImplementation] - public interface IAfterInteract - { - /// - /// The interaction priority. Higher numbers get called first. - /// - /// Priority defaults to 0 - int Priority => 0; - - /// - /// Called when we interact with nothing, or when we interact with an entity out of range that has no behavior - /// - [Obsolete("Use AfterInteractMessage instead")] - Task AfterInteract(AfterInteractEventArgs eventArgs); - } - - public sealed class AfterInteractEventArgs : EventArgs - { - public EntityUid User { get; } - public EntityCoordinates ClickLocation { get; } - public EntityUid? Target { get; } - public bool CanReach { get; } - - public AfterInteractEventArgs(EntityUid user, EntityCoordinates clickLocation, EntityUid? target, bool canReach) - { - User = user; - ClickLocation = clickLocation; - Target = target; - CanReach = canReach; - } - } - [PublicAPI] public abstract class InteractEvent : HandledEntityEventArgs { diff --git a/Content.Shared/Interaction/Helpers/SharedUnoccludedExtensions.cs b/Content.Shared/Interaction/Helpers/SharedUnoccludedExtensions.cs index be610f3f44..0a13fc4f1b 100644 --- a/Content.Shared/Interaction/Helpers/SharedUnoccludedExtensions.cs +++ b/Content.Shared/Interaction/Helpers/SharedUnoccludedExtensions.cs @@ -343,37 +343,5 @@ namespace Content.Shared.Interaction.Helpers ignoreInsideBlocker); } #endregion - - #region EventArgs - public static bool InRangeUnOccluded( - this ITargetedInteractEventArgs args, - float range = InteractionRange, - Ignored? predicate = null, - bool ignoreInsideBlocker = true) - { - return ExamineSystemShared.InRangeUnOccluded(args, range, predicate, - ignoreInsideBlocker); - } - - public static bool InRangeUnOccluded( - this DragDropEvent args, - float range = InteractionRange, - Ignored? predicate = null, - bool ignoreInsideBlocker = true) - { - return ExamineSystemShared.InRangeUnOccluded(args, range, predicate, - ignoreInsideBlocker); - } - - public static bool InRangeUnOccluded( - this AfterInteractEventArgs args, - float range = InteractionRange, - Ignored? predicate = null, - bool ignoreInsideBlocker = true) - { - return ExamineSystemShared.InRangeUnOccluded(args, range, predicate, - ignoreInsideBlocker); - } - #endregion } } diff --git a/Content.Shared/Interaction/IRangedInteract.cs b/Content.Shared/Interaction/RangedInteract.cs similarity index 100% rename from Content.Shared/Interaction/IRangedInteract.cs rename to Content.Shared/Interaction/RangedInteract.cs diff --git a/Content.Shared/Popups/SharedPopupExtensions.cs b/Content.Shared/Popups/SharedPopupExtensions.cs index 8ab5473229..a3581cefeb 100644 --- a/Content.Shared/Popups/SharedPopupExtensions.cs +++ b/Content.Shared/Popups/SharedPopupExtensions.cs @@ -12,6 +12,7 @@ namespace Content.Shared.Popups /// The entity above which the message will appear. /// The entity that will see the message. /// The message to show. + [Obsolete("Use PopupSystem.PopupEntity instead.")] public static void PopupMessage(this EntityUid source, EntityUid viewer, string message) { var popupSystem = EntitySystem.Get(); @@ -24,6 +25,7 @@ namespace Content.Shared.Popups /// /// The entity that will see the message. /// The message to be seen. + [Obsolete("Use PopupSystem.PopupEntity instead.")] public static void PopupMessage(this EntityUid viewer, string message) { viewer.PopupMessage(viewer, message); @@ -35,6 +37,7 @@ namespace Content.Shared.Popups /// Location on a grid that the message floats up from. /// The client attached entity that the message is being sent to. /// Text contents of the message. + [Obsolete("Use PopupSystem.PopupCoordinates instead.")] public static void PopupMessage(this EntityCoordinates coordinates, EntityUid viewer, string message) { var popupSystem = EntitySystem.Get(); @@ -48,6 +51,7 @@ namespace Content.Shared.Popups /// The client attached entity that the message is being sent to. /// /// Text contents of the message. + [Obsolete("Use PopupSystem.PopupCursor instead.")] public static void PopupMessageCursor(this EntityUid viewer, string message) { var popupSystem = EntitySystem.Get();