From 1eb81427d38ffd063f823df01853f5e8a1584a0d Mon Sep 17 00:00:00 2001 From: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com> Date: Mon, 29 Apr 2024 15:24:10 +1200 Subject: [PATCH] Stop admin verb pop-in (#27450) --- .../Administration/Systems/AdminVerbSystem.cs | 23 ++++++++++++++++ .../Verbs/UI/VerbMenuUIController.cs | 25 ++++++++++-------- Content.Client/Verbs/VerbSystem.cs | 16 ++++-------- Content.Shared/Verbs/SharedVerbSystem.cs | 26 ++++++++++++------- Content.Shared/Verbs/VerbEvents.cs | 10 ++++++- Resources/Locale/en-US/verbs/verb-system.ftl | 1 - 6 files changed, 68 insertions(+), 33 deletions(-) diff --git a/Content.Client/Administration/Systems/AdminVerbSystem.cs b/Content.Client/Administration/Systems/AdminVerbSystem.cs index e0f84bc4f0..dced59bbf2 100644 --- a/Content.Client/Administration/Systems/AdminVerbSystem.cs +++ b/Content.Client/Administration/Systems/AdminVerbSystem.cs @@ -1,3 +1,6 @@ +using Content.Shared.Administration; +using Content.Shared.Administration.Managers; +using Content.Shared.Mind.Components; using Content.Shared.Verbs; using Robust.Client.Console; using Robust.Shared.Utility; @@ -11,10 +14,12 @@ namespace Content.Client.Administration.Systems { [Dependency] private readonly IClientConGroupController _clientConGroupController = default!; [Dependency] private readonly IClientConsoleHost _clientConsoleHost = default!; + [Dependency] private readonly ISharedAdminManager _admin = default!; public override void Initialize() { SubscribeLocalEvent>(AddAdminVerbs); + } private void AddAdminVerbs(GetVerbsEvent args) @@ -33,6 +38,24 @@ namespace Content.Client.Administration.Systems }; args.Verbs.Add(verb); } + + if (!_admin.IsAdmin(args.User)) + return; + + if (_admin.HasAdminFlag(args.User, AdminFlags.Admin)) + args.ExtraCategories.Add(VerbCategory.Admin); + + if (_admin.HasAdminFlag(args.User, AdminFlags.Fun) && HasComp(args.Target)) + args.ExtraCategories.Add(VerbCategory.Antag); + + if (_admin.HasAdminFlag(args.User, AdminFlags.Debug)) + args.ExtraCategories.Add(VerbCategory.Debug); + + if (_admin.HasAdminFlag(args.User, AdminFlags.Fun)) + args.ExtraCategories.Add(VerbCategory.Smite); + + if (_admin.HasAdminFlag(args.User, AdminFlags.Admin)) + args.ExtraCategories.Add(VerbCategory.Tricks); } } } diff --git a/Content.Client/Verbs/UI/VerbMenuUIController.cs b/Content.Client/Verbs/UI/VerbMenuUIController.cs index 21eb6becd6..c3fc8c8356 100644 --- a/Content.Client/Verbs/UI/VerbMenuUIController.cs +++ b/Content.Client/Verbs/UI/VerbMenuUIController.cs @@ -31,6 +31,7 @@ namespace Content.Client.Verbs.UI public NetEntity CurrentTarget; public SortedSet CurrentVerbs = new(); + public List ExtraCategories = new(); /// /// Separate from , since we can open a verb menu as a submenu @@ -91,19 +92,12 @@ namespace Content.Client.Verbs.UI menu.MenuBody.DisposeAllChildren(); CurrentTarget = target; - CurrentVerbs = _verbSystem.GetVerbs(target, user, Verb.VerbTypes, force); + CurrentVerbs = _verbSystem.GetVerbs(target, user, Verb.VerbTypes, out ExtraCategories, force); OpenMenu = menu; // Fill in client-side verbs. FillVerbPopup(menu); - // Add indicator that some verbs may be missing. - // I long for the day when verbs will all be predicted and this becomes unnecessary. - if (!target.IsClientSide()) - { - _context.AddElement(menu, new ContextMenuElement(Loc.GetString("verb-system-waiting-on-server-text"))); - } - // if popup isn't null (ie we are opening out of an entity menu element), // assume that that is going to handle opening the submenu properly if (popup != null) @@ -128,11 +122,19 @@ namespace Content.Client.Verbs.UI var element = new VerbMenuElement(verb); _context.AddElement(popup, element); } - else if (listedCategories.Add(verb.Category.Text)) AddVerbCategory(verb.Category, popup); } + if (ExtraCategories != null) + { + foreach (var category in ExtraCategories) + { + if (listedCategories.Add(category.Text)) + AddVerbCategory(category, popup); + } + } + popup.InvalidateMeasure(); } @@ -153,10 +155,11 @@ namespace Content.Client.Verbs.UI } } - if (verbsInCategory.Count == 0) + if (verbsInCategory.Count == 0 && !ExtraCategories.Contains(category)) return; - var element = new VerbMenuElement(category, verbsInCategory[0].TextStyleClass); + var style = verbsInCategory.FirstOrDefault()?.TextStyleClass ?? Verb.DefaultTextStyleClass; + var element = new VerbMenuElement(category, style); _context.AddElement(popup, element); // Create the pop-up that appears when hovering over this element diff --git a/Content.Client/Verbs/VerbSystem.cs b/Content.Client/Verbs/VerbSystem.cs index 77f46a3fc9..49a3785eb2 100644 --- a/Content.Client/Verbs/VerbSystem.cs +++ b/Content.Client/Verbs/VerbSystem.cs @@ -165,29 +165,23 @@ namespace Content.Client.Verbs return true; } - /// - /// Asks the server to send back a list of server-side verbs, for the given verb type. - /// - public SortedSet GetVerbs(EntityUid target, EntityUid user, Type type, bool force = false) - { - return GetVerbs(GetNetEntity(target), user, new List() { type }, force); - } - /// /// Ask the server to send back a list of server-side verbs, and for now return an incomplete list of verbs /// (only those defined locally). /// - public SortedSet GetVerbs(NetEntity target, EntityUid user, List verbTypes, - bool force = false) + public SortedSet GetVerbs(NetEntity target, EntityUid user, List verbTypes, out List extraCategories, bool force = false) { if (!target.IsClientSide()) RaiseNetworkEvent(new RequestServerVerbsEvent(target, verbTypes, adminRequest: force)); // Some admin menu interactions will try get verbs for entities that have not yet been sent to the player. if (!TryGetEntity(target, out var local)) + { + extraCategories = new(); return new(); + } - return GetLocalVerbs(local.Value, user, verbTypes, force); + return GetLocalVerbs(local.Value, user, verbTypes, out extraCategories, force); } diff --git a/Content.Shared/Verbs/SharedVerbSystem.cs b/Content.Shared/Verbs/SharedVerbSystem.cs index 9dda910f3f..60714aea8f 100644 --- a/Content.Shared/Verbs/SharedVerbSystem.cs +++ b/Content.Shared/Verbs/SharedVerbSystem.cs @@ -55,13 +55,21 @@ namespace Content.Shared.Verbs return GetLocalVerbs(target, user, new List() { type }, force); } + /// + public SortedSet GetLocalVerbs(EntityUid target, EntityUid user, List types, bool force = false) + { + return GetLocalVerbs(target, user, types, out _, force); + } + /// /// Raises a number of events in order to get all verbs of the given type(s) defined in local systems. This /// does not request verbs from the server. /// - public SortedSet GetLocalVerbs(EntityUid target, EntityUid user, List types, bool force = false) + public SortedSet GetLocalVerbs(EntityUid target, EntityUid user, List types, + out List extraCategories, bool force = false) { SortedSet verbs = new(); + extraCategories = new(); // accessibility checks bool canAccess = false; @@ -108,7 +116,7 @@ namespace Content.Shared.Verbs // TODO: fix this garbage and use proper generics or reflection or something else, not this. if (types.Contains(typeof(InteractionVerb))) { - var verbEvent = new GetVerbsEvent(user, target, @using, hands, canInteract, canAccess); + var verbEvent = new GetVerbsEvent(user, target, @using, hands, canInteract, canAccess, extraCategories); RaiseLocalEvent(target, verbEvent, true); verbs.UnionWith(verbEvent.Verbs); } @@ -117,35 +125,35 @@ namespace Content.Shared.Verbs && @using != null && @using != target) { - var verbEvent = new GetVerbsEvent(user, target, @using, hands, canInteract, canAccess); + var verbEvent = new GetVerbsEvent(user, target, @using, hands, canInteract, canAccess, extraCategories); RaiseLocalEvent(@using.Value, verbEvent, true); // directed at used, not at target verbs.UnionWith(verbEvent.Verbs); } if (types.Contains(typeof(InnateVerb))) { - var verbEvent = new GetVerbsEvent(user, target, @using, hands, canInteract, canAccess); + var verbEvent = new GetVerbsEvent(user, target, @using, hands, canInteract, canAccess, extraCategories); RaiseLocalEvent(user, verbEvent, true); verbs.UnionWith(verbEvent.Verbs); } if (types.Contains(typeof(AlternativeVerb))) { - var verbEvent = new GetVerbsEvent(user, target, @using, hands, canInteract, canAccess); + var verbEvent = new GetVerbsEvent(user, target, @using, hands, canInteract, canAccess, extraCategories); RaiseLocalEvent(target, verbEvent, true); verbs.UnionWith(verbEvent.Verbs); } if (types.Contains(typeof(ActivationVerb))) { - var verbEvent = new GetVerbsEvent(user, target, @using, hands, canInteract, canAccess); + var verbEvent = new GetVerbsEvent(user, target, @using, hands, canInteract, canAccess, extraCategories); RaiseLocalEvent(target, verbEvent, true); verbs.UnionWith(verbEvent.Verbs); } if (types.Contains(typeof(ExamineVerb))) { - var verbEvent = new GetVerbsEvent(user, target, @using, hands, canInteract, canAccess); + var verbEvent = new GetVerbsEvent(user, target, @using, hands, canInteract, canAccess, extraCategories); RaiseLocalEvent(target, verbEvent, true); verbs.UnionWith(verbEvent.Verbs); } @@ -153,7 +161,7 @@ namespace Content.Shared.Verbs // generic verbs if (types.Contains(typeof(Verb))) { - var verbEvent = new GetVerbsEvent(user, target, @using, hands, canInteract, canAccess); + var verbEvent = new GetVerbsEvent(user, target, @using, hands, canInteract, canAccess, extraCategories); RaiseLocalEvent(target, verbEvent, true); verbs.UnionWith(verbEvent.Verbs); } @@ -161,7 +169,7 @@ namespace Content.Shared.Verbs if (types.Contains(typeof(EquipmentVerb))) { var access = canAccess || _interactionSystem.CanAccessEquipment(user, target); - var verbEvent = new GetVerbsEvent(user, target, @using, hands, canInteract, access); + var verbEvent = new GetVerbsEvent(user, target, @using, hands, canInteract, access, extraCategories); RaiseLocalEvent(target, verbEvent); verbs.UnionWith(verbEvent.Verbs); } diff --git a/Content.Shared/Verbs/VerbEvents.cs b/Content.Shared/Verbs/VerbEvents.cs index 9a09d5d7a1..6b3fd327c9 100644 --- a/Content.Shared/Verbs/VerbEvents.cs +++ b/Content.Shared/Verbs/VerbEvents.cs @@ -77,6 +77,13 @@ namespace Content.Shared.Verbs /// public readonly SortedSet Verbs = new(); + /// + /// Additional verb categories to show in the pop-up menu, even if there are no verbs currently associated + /// with that category. This is mainly useful to prevent verb menu pop-in. E.g., admins will get admin/debug + /// related verbs on entities, even though most of those verbs are all defined server-side. + /// + public readonly List ExtraCategories; + /// /// Can the user physically access the target? /// @@ -123,7 +130,7 @@ namespace Content.Shared.Verbs /// public readonly EntityUid? Using; - public GetVerbsEvent(EntityUid user, EntityUid target, EntityUid? @using, HandsComponent? hands, bool canInteract, bool canAccess) + public GetVerbsEvent(EntityUid user, EntityUid target, EntityUid? @using, HandsComponent? hands, bool canInteract, bool canAccess, List extraCategories) { User = user; Target = target; @@ -131,6 +138,7 @@ namespace Content.Shared.Verbs Hands = hands; CanAccess = canAccess; CanInteract = canInteract; + ExtraCategories = extraCategories; } } } diff --git a/Resources/Locale/en-US/verbs/verb-system.ftl b/Resources/Locale/en-US/verbs/verb-system.ftl index c626e41ce1..64104f796e 100644 --- a/Resources/Locale/en-US/verbs/verb-system.ftl +++ b/Resources/Locale/en-US/verbs/verb-system.ftl @@ -1,4 +1,3 @@ -verb-system-waiting-on-server-text = Waiting on Server... verb-system-null-server-response = Entity not in view. You should not see this.