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