From 8f6326c3e0b04af30171d2435962b89105d67f31 Mon Sep 17 00:00:00 2001 From: deltanedas <39013340+deltanedas@users.noreply.github.com> Date: Thu, 25 Jul 2024 03:54:51 +0000 Subject: [PATCH] prevent borgs unlocking eachother and robotics console (#27888) * prevent borgs from using locks * e * bru * a * blacklist borgs and robotics console * frogro * add IsAllowed to EntityWhitelistSystem * use IsAllowed * move thing to new LockingWhitelistSystem * :trollface: * review * use renamed CheckBoth in locking whitelist * remove unused stuff and add more to doc * Use target entity instead to remove self check * Rename to _whitelistSystem * Add deny lock toggle popup * Prevent duplicate checks and popups * Fix wrong entity in popup when toggling another borg * Make new event * Update comment to user for new event --------- Co-authored-by: deltanedas <@deltanedas:kde.org> Co-authored-by: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com> --- Content.Shared/Lock/LockComponent.cs | 7 +++++ Content.Shared/Lock/LockSystem.cs | 8 ++++-- .../Lock/LockingWhitelistComponent.cs | 18 ++++++++++++ Content.Shared/Lock/LockingWhitelistSystem.cs | 28 +++++++++++++++++++ .../Whitelist/EntityWhitelistSystem.cs | 17 +++++++++++ .../lock/locking-whitelist-component.ftl | 1 + .../Mobs/Cyborgs/base_borg_chassis.yml | 5 ++++ 7 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 Content.Shared/Lock/LockingWhitelistComponent.cs create mode 100644 Content.Shared/Lock/LockingWhitelistSystem.cs create mode 100644 Resources/Locale/en-US/lock/locking-whitelist-component.ftl diff --git a/Content.Shared/Lock/LockComponent.cs b/Content.Shared/Lock/LockComponent.cs index e3e2bc6df1..070d5801c1 100644 --- a/Content.Shared/Lock/LockComponent.cs +++ b/Content.Shared/Lock/LockComponent.cs @@ -86,6 +86,13 @@ public sealed partial class LockComponent : Component [ByRefEvent] public record struct LockToggleAttemptEvent(EntityUid User, bool Silent = false, bool Cancelled = false); +/// +/// Event raised on the user when a toggle is attempted. +/// Can be cancelled to prevent it. +/// +[ByRefEvent] +public record struct UserLockToggleAttemptEvent(EntityUid Target, bool Silent = false, bool Cancelled = false); + /// /// Event raised on a lock after it has been toggled. /// diff --git a/Content.Shared/Lock/LockSystem.cs b/Content.Shared/Lock/LockSystem.cs index 22a90aa0a6..8dde767224 100644 --- a/Content.Shared/Lock/LockSystem.cs +++ b/Content.Shared/Lock/LockSystem.cs @@ -232,7 +232,12 @@ public sealed class LockSystem : EntitySystem var ev = new LockToggleAttemptEvent(user, quiet); RaiseLocalEvent(uid, ref ev, true); - return !ev.Cancelled; + if (ev.Cancelled) + return false; + + var userEv = new UserLockToggleAttemptEvent(uid, quiet); + RaiseLocalEvent(user, ref userEv, true); + return !userEv.Cancelled; } // TODO: this should be a helper on AccessReaderSystem since so many systems copy paste it @@ -377,4 +382,3 @@ public sealed class LockSystem : EntitySystem _activatableUI.CloseAll(uid); } } - diff --git a/Content.Shared/Lock/LockingWhitelistComponent.cs b/Content.Shared/Lock/LockingWhitelistComponent.cs new file mode 100644 index 0000000000..4ac832e438 --- /dev/null +++ b/Content.Shared/Lock/LockingWhitelistComponent.cs @@ -0,0 +1,18 @@ +using Content.Shared.Whitelist; +using Robust.Shared.GameStates; + +namespace Content.Shared.Lock; + +/// +/// Adds whitelist and blacklist for this mob to lock things. +/// The whitelist and blacklist are checked against the object being locked, not the mob. +/// +[RegisterComponent, NetworkedComponent, Access(typeof(LockingWhitelistSystem))] +public sealed partial class LockingWhitelistComponent : Component +{ + [DataField] + public EntityWhitelist? Whitelist; + + [DataField] + public EntityWhitelist? Blacklist; +} diff --git a/Content.Shared/Lock/LockingWhitelistSystem.cs b/Content.Shared/Lock/LockingWhitelistSystem.cs new file mode 100644 index 0000000000..ba495fba90 --- /dev/null +++ b/Content.Shared/Lock/LockingWhitelistSystem.cs @@ -0,0 +1,28 @@ +using Content.Shared.Popups; +using Content.Shared.Whitelist; + +namespace Content.Shared.Lock; + +public sealed class LockingWhitelistSystem : EntitySystem +{ + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; + [Dependency] private readonly SharedPopupSystem _popupSystem = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnUserLockToggleAttempt); + } + + private void OnUserLockToggleAttempt(Entity ent, ref UserLockToggleAttemptEvent args) + { + if (_whitelistSystem.CheckBoth(args.Target, ent.Comp.Blacklist, ent.Comp.Whitelist)) + return; + + if (!args.Silent) + _popupSystem.PopupClient(Loc.GetString("locking-whitelist-component-lock-toggle-deny"), ent.Owner); + + args.Cancelled = true; + } +} diff --git a/Content.Shared/Whitelist/EntityWhitelistSystem.cs b/Content.Shared/Whitelist/EntityWhitelistSystem.cs index f311946cf9..57fdb523dd 100644 --- a/Content.Shared/Whitelist/EntityWhitelistSystem.cs +++ b/Content.Shared/Whitelist/EntityWhitelistSystem.cs @@ -23,6 +23,23 @@ public sealed class EntityWhitelistSystem : EntitySystem return uid != null && IsValid(list, uid.Value); } + /// + /// Checks whether a given entity is allowed by a whitelist and not blocked by a blacklist. + /// If a blacklist is provided and it matches then this returns false. + /// If a whitelist is provided and it does not match then this returns false. + /// If either list is null it does not get checked. + /// + public bool CheckBoth([NotNullWhen(true)] EntityUid? uid, EntityWhitelist? blacklist = null, EntityWhitelist? whitelist = null) + { + if (uid == null) + return false; + + if (blacklist != null && IsValid(blacklist, uid)) + return false; + + return whitelist == null || IsValid(whitelist, uid); + } + /// /// Checks whether a given entity satisfies a whitelist. /// diff --git a/Resources/Locale/en-US/lock/locking-whitelist-component.ftl b/Resources/Locale/en-US/lock/locking-whitelist-component.ftl new file mode 100644 index 0000000000..182814c2c5 --- /dev/null +++ b/Resources/Locale/en-US/lock/locking-whitelist-component.ftl @@ -0,0 +1 @@ +locking-whitelist-component-lock-toggle-deny = You can't toggle the lock. diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml index 2618207b7a..f9422acd72 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml @@ -99,6 +99,11 @@ doAfterDelay: 10 allowSelfRepair: false - type: BorgChassis + - type: LockingWhitelist + blacklist: + components: + - BorgChassis + - RoboticsConsole - type: WiresPanel - type: ActivatableUIRequiresPanel - type: NameIdentifier -- 2.52.0