From c6c319f7e485460ebf547fd5a8bbaab9e72ac20a Mon Sep 17 00:00:00 2001 From: Nemanja <98561806+EmoGarbage404@users.noreply.github.com> Date: Sat, 11 Feb 2023 20:12:29 -0500 Subject: [PATCH] move lockcomponent to shared (#13722) * move lockcomponent to shared * ajcm review --- .../Unary/EntitySystems/GasCanisterSystem.cs | 6 +- .../Buckle/Systems/BuckleSystem.Buckle.cs | 6 +- Content.Server/Cabinet/ItemCabinetSystem.cs | 1 + .../CardboardBox/CardboardBoxSystem.cs | 5 +- .../Construction/Conditions/Locked.cs | 2 +- Content.Server/Foldable/FoldableSystem.cs | 13 +- Content.Server/Ghost/GhostSystem.cs | 6 +- Content.Server/Lock/LockComponent.cs | 30 --- Content.Server/Lock/LockSystem.cs | 206 --------------- Content.Server/Lock/LockToggledEvent.cs | 12 - Content.Server/Morgue/CrematoriumSystem.cs | 8 +- .../EntityStorageLayingDownOverrideSystem.cs | 9 +- Content.Server/Resist/ResistLockerSystem.cs | 4 +- .../Systems/DeployableBarrierSystem.cs | 5 +- .../EntitySystems/EmitterSystem.cs | 1 + .../Components/EntityStorageComponent.cs | 33 --- .../EntitySystems/BluespaceLockerSystem.cs | 7 +- .../CursedEntityStorageSystem.cs | 5 +- .../EntitySystems/EntityStorageSystem.cs | 28 +- .../Storage/EntitySystems/StorageSystem.cs | 1 + Content.Shared/Lock/LockComponent.cs | 57 ++++ Content.Shared/Lock/LockSystem.cs | 243 ++++++++++++++++++ .../Storage/Components/SharedEntityStorage.cs | 25 ++ 23 files changed, 381 insertions(+), 332 deletions(-) delete mode 100644 Content.Server/Lock/LockComponent.cs delete mode 100644 Content.Server/Lock/LockSystem.cs delete mode 100644 Content.Server/Lock/LockToggledEvent.cs create mode 100644 Content.Shared/Lock/LockComponent.cs create mode 100644 Content.Shared/Lock/LockSystem.cs create mode 100644 Content.Shared/Storage/Components/SharedEntityStorage.cs diff --git a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCanisterSystem.cs b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCanisterSystem.cs index 99c59fea14..9a1bf537f5 100644 --- a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCanisterSystem.cs +++ b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCanisterSystem.cs @@ -4,21 +4,19 @@ using Content.Server.Atmos.EntitySystems; using Content.Server.Atmos.Piping.Components; using Content.Server.Atmos.Piping.Unary.Components; using Content.Server.Cargo.Systems; -using Content.Server.Lock; using Content.Server.NodeContainer; using Content.Server.NodeContainer.NodeGroups; using Content.Server.NodeContainer.Nodes; using Content.Server.Popups; -using Content.Server.Storage.Components; using Content.Shared.Atmos; using Content.Shared.Atmos.Piping.Binary.Components; using Content.Shared.Database; using Content.Shared.Hands.EntitySystems; using Content.Shared.Interaction; +using Content.Shared.Lock; using JetBrains.Annotations; using Robust.Server.GameObjects; using Robust.Shared.Containers; -using Robust.Shared.Player; namespace Content.Server.Atmos.Piping.Unary.EntitySystems { @@ -324,7 +322,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems args.GasMixtures = new Dictionary { {Name(uid), component.Air} }; } - private void OnLockToggled(EntityUid uid, GasCanisterComponent component, LockToggledEvent args) + private void OnLockToggled(EntityUid uid, GasCanisterComponent component, ref LockToggledEvent args) { _appearanceSystem.SetData(uid, GasCanisterVisuals.Locked, args.Locked); } diff --git a/Content.Server/Buckle/Systems/BuckleSystem.Buckle.cs b/Content.Server/Buckle/Systems/BuckleSystem.Buckle.cs index 3e1135b1f5..4ab9439f94 100644 --- a/Content.Server/Buckle/Systems/BuckleSystem.Buckle.cs +++ b/Content.Server/Buckle/Systems/BuckleSystem.Buckle.cs @@ -1,6 +1,5 @@ using System.Diagnostics.CodeAnalysis; using Content.Server.Administration.Logs; -using Content.Server.Storage.Components; using Content.Shared.Alert; using Content.Shared.Bed.Sleep; using Content.Shared.Buckle.Components; @@ -11,6 +10,7 @@ using Content.Shared.IdentityManagement; using Content.Shared.Interaction; using Content.Shared.Mobs.Components; using Content.Shared.Pulling.Components; +using Content.Shared.Storage.Components; using Content.Shared.Stunnable; using Content.Shared.Vehicle.Components; using Content.Shared.Verbs; @@ -98,10 +98,10 @@ public sealed partial class BuckleSystem TryUnbuckle(uid, buckle.Owner, true, buckle); } - private void OnEntityStorageInsertAttempt(EntityUid uid, BuckleComponent comp, InsertIntoEntityStorageAttemptEvent args) + private void OnEntityStorageInsertAttempt(EntityUid uid, BuckleComponent comp, ref InsertIntoEntityStorageAttemptEvent args) { if (comp.Buckled) - args.Cancel(); + args.Cancelled = true; } private void OnBuckleCanDrop(EntityUid uid, BuckleComponent component, CanDropEvent args) diff --git a/Content.Server/Cabinet/ItemCabinetSystem.cs b/Content.Server/Cabinet/ItemCabinetSystem.cs index 4a7a22e289..439c6e7da5 100644 --- a/Content.Server/Cabinet/ItemCabinetSystem.cs +++ b/Content.Server/Cabinet/ItemCabinetSystem.cs @@ -3,6 +3,7 @@ using Content.Shared.Audio; using Content.Shared.Cabinet; using Content.Shared.Containers.ItemSlots; using Content.Shared.Interaction; +using Content.Shared.Lock; using Content.Shared.Verbs; using Robust.Server.GameObjects; using Robust.Shared.Audio; diff --git a/Content.Server/CardboardBox/CardboardBoxSystem.cs b/Content.Server/CardboardBox/CardboardBoxSystem.cs index b482ef9826..2cfdf126a1 100644 --- a/Content.Server/CardboardBox/CardboardBoxSystem.cs +++ b/Content.Server/CardboardBox/CardboardBoxSystem.cs @@ -8,6 +8,7 @@ using Content.Shared.Movement.Components; using Content.Shared.Movement.Systems; using Content.Shared.Stealth; using Content.Shared.Stealth.Components; +using Content.Shared.Storage.Components; using Robust.Server.GameObjects; using Robust.Shared.Containers; using Robust.Shared.Player; @@ -44,7 +45,7 @@ public sealed class CardboardBoxSystem : SharedCardboardBoxSystem _storage.OpenStorage(uid); } - private void AfterStorageOpen(EntityUid uid, CardboardBoxComponent component, StorageAfterOpenEvent args) + private void AfterStorageOpen(EntityUid uid, CardboardBoxComponent component, ref StorageAfterOpenEvent args) { //Remove the mover after the box is opened and play the effect if it hasn't been played yet. if (component.Mover != null) @@ -64,7 +65,7 @@ public sealed class CardboardBoxSystem : SharedCardboardBoxSystem _stealth.SetEnabled(uid, false); } - private void AfterStorageClosed(EntityUid uid, CardboardBoxComponent component, StorageAfterCloseEvent args) + private void AfterStorageClosed(EntityUid uid, CardboardBoxComponent component, ref StorageAfterCloseEvent args) { // If this box has a stealth/chameleon effect, enable the stealth effect. if (TryComp(uid, out StealthComponent? stealth)) diff --git a/Content.Server/Construction/Conditions/Locked.cs b/Content.Server/Construction/Conditions/Locked.cs index f8128378c2..2b8abd335c 100644 --- a/Content.Server/Construction/Conditions/Locked.cs +++ b/Content.Server/Construction/Conditions/Locked.cs @@ -1,6 +1,6 @@ -using Content.Server.Storage.Components; using Content.Shared.Construction; using Content.Shared.Examine; +using Content.Shared.Lock; using JetBrains.Annotations; namespace Content.Server.Construction.Conditions diff --git a/Content.Server/Foldable/FoldableSystem.cs b/Content.Server/Foldable/FoldableSystem.cs index 4b66d2aba0..deea2b7c08 100644 --- a/Content.Server/Foldable/FoldableSystem.cs +++ b/Content.Server/Foldable/FoldableSystem.cs @@ -3,6 +3,7 @@ using Content.Server.Buckle.Systems; using Content.Server.Storage.Components; using Content.Shared.Buckle.Components; using Content.Shared.Foldable; +using Content.Shared.Storage.Components; using Content.Shared.Verbs; using JetBrains.Annotations; using Robust.Shared.Containers; @@ -12,8 +13,8 @@ namespace Content.Server.Foldable [UsedImplicitly] public sealed class FoldableSystem : SharedFoldableSystem { - [Dependency] private BuckleSystem _buckle = default!; - [Dependency] private SharedContainerSystem _container = default!; + [Dependency] private readonly BuckleSystem _buckle = default!; + [Dependency] private readonly SharedContainerSystem _container = default!; public override void Initialize() { @@ -25,10 +26,10 @@ namespace Content.Server.Foldable } - private void OnFoldableOpenAttempt(EntityUid uid, FoldableComponent component, StorageOpenAttemptEvent args) + private void OnFoldableOpenAttempt(EntityUid uid, FoldableComponent component, ref StorageOpenAttemptEvent args) { if (component.IsFolded) - args.Cancel(); + args.Cancelled = true; } public bool TryToggleFold(FoldableComponent comp) @@ -89,12 +90,12 @@ namespace Content.Server.Foldable _buckle.StrapSetEnabled(component.Owner, !component.IsFolded); } - public void OnStoreThisAttempt(EntityUid uid, FoldableComponent comp, StoreMobInItemContainerAttemptEvent args) + public void OnStoreThisAttempt(EntityUid uid, FoldableComponent comp, ref StoreMobInItemContainerAttemptEvent args) { args.Handled = true; if (comp.IsFolded) - args.Cancel(); + args.Cancelled = true; } #region Verb diff --git a/Content.Server/Ghost/GhostSystem.cs b/Content.Server/Ghost/GhostSystem.cs index 8d0dbeae2f..5213ec83c0 100644 --- a/Content.Server/Ghost/GhostSystem.cs +++ b/Content.Server/Ghost/GhostSystem.cs @@ -4,7 +4,6 @@ using Content.Server.Ghost.Components; using Content.Server.Mind; using Content.Server.Mind.Components; using Content.Server.Players; -using Content.Server.Storage.Components; using Content.Server.Visible; using Content.Server.Warps; using Content.Shared.Actions; @@ -15,6 +14,7 @@ using Content.Shared.Ghost; using Content.Shared.Mobs.Components; using Content.Shared.Mobs.Systems; using Content.Shared.Movement.Events; +using Content.Shared.Storage.Components; using JetBrains.Annotations; using Robust.Server.GameObjects; using Robust.Server.Player; @@ -270,9 +270,9 @@ namespace Content.Server.Ghost } } - private void OnEntityStorageInsertAttempt(EntityUid uid, GhostComponent comp, InsertIntoEntityStorageAttemptEvent args) + private void OnEntityStorageInsertAttempt(EntityUid uid, GhostComponent comp, ref InsertIntoEntityStorageAttemptEvent args) { - args.Cancel(); + args.Cancelled = true; } /// diff --git a/Content.Server/Lock/LockComponent.cs b/Content.Server/Lock/LockComponent.cs deleted file mode 100644 index 0585986091..0000000000 --- a/Content.Server/Lock/LockComponent.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Robust.Shared.Audio; - -namespace Content.Server.Storage.Components -{ - /// - /// Allows locking/unlocking, with access determined by AccessReader - /// - [RegisterComponent] - public sealed class LockComponent : Component - { - [ViewVariables(VVAccess.ReadWrite)] [DataField("locked")] public bool Locked { get; set; } = true; - [ViewVariables(VVAccess.ReadWrite)] [DataField("lockOnClick")] public bool LockOnClick { get; set; } = false; - [ViewVariables(VVAccess.ReadWrite)] [DataField("unlockingSound")] public SoundSpecifier UnlockSound { get; set; } = new SoundPathSpecifier("/Audio/Machines/door_lock_off.ogg"); - [ViewVariables(VVAccess.ReadWrite)] [DataField("lockingSound")] public SoundSpecifier LockSound { get; set; } = new SoundPathSpecifier("/Audio/Machines/door_lock_on.ogg"); - } -} -[ByRefEvent] -public struct LockToggleAttemptEvent -{ - public bool Silent = false; - public bool Cancelled = false; - public EntityUid User; - - public LockToggleAttemptEvent(EntityUid user, bool silent = false) - { - User = user; - Silent = silent; - } -} -public sealed class LockToggleAttemptArgs : EventArgs { } diff --git a/Content.Server/Lock/LockSystem.cs b/Content.Server/Lock/LockSystem.cs deleted file mode 100644 index c31e0ce8f3..0000000000 --- a/Content.Server/Lock/LockSystem.cs +++ /dev/null @@ -1,206 +0,0 @@ -using Content.Server.Storage.Components; -using Content.Shared.Emag.Systems; -using Content.Shared.Access.Components; -using Content.Shared.Access.Systems; -using Content.Shared.Examine; -using Content.Shared.Hands.Components; -using Content.Shared.Interaction; -using Content.Shared.Popups; -using Content.Shared.Storage; -using Content.Shared.Verbs; -using JetBrains.Annotations; -using Robust.Shared.Audio; -using Robust.Shared.Player; - -namespace Content.Server.Lock -{ - /// - /// Handles (un)locking and examining of Lock components - /// - [UsedImplicitly] - public sealed class LockSystem : EntitySystem - { - [Dependency] private readonly AccessReaderSystem _accessReader = default!; - [Dependency] private readonly SharedPopupSystem _sharedPopupSystem = default!; - [Dependency] private readonly SharedAppearanceSystem _appearanceSystem = default!; - [Dependency] private readonly SharedAudioSystem _audio = default!; - - /// - public override void Initialize() - { - base.Initialize(); - SubscribeLocalEvent(OnStartup); - SubscribeLocalEvent(OnActivated); - SubscribeLocalEvent(OnStorageOpenAttempt); - SubscribeLocalEvent(OnExamined); - SubscribeLocalEvent>(AddToggleLockVerb); - SubscribeLocalEvent(OnEmagged); - } - - private void OnStartup(EntityUid uid, LockComponent lockComp, ComponentStartup args) - { - if (EntityManager.TryGetComponent(lockComp.Owner, out AppearanceComponent? appearance)) - { - _appearanceSystem.SetData(uid, StorageVisuals.CanLock, true, appearance); - } - } - - private void OnActivated(EntityUid uid, LockComponent lockComp, ActivateInWorldEvent args) - { - if (args.Handled) - return; - - // Only attempt an unlock by default on Activate - if (lockComp.Locked) - { - TryUnlock(uid, args.User, lockComp); - args.Handled = true; - } - else if (lockComp.LockOnClick) - { - TryLock(uid, args.User, lockComp); - args.Handled = true; - } - } - - private void OnStorageOpenAttempt(EntityUid uid, LockComponent component, StorageOpenAttemptEvent args) - { - if (component.Locked) - { - if (!args.Silent) - _sharedPopupSystem.PopupEntity(Loc.GetString("entity-storage-component-locked-message"), uid); - - args.Cancel(); - } - } - - private void OnExamined(EntityUid uid, LockComponent lockComp, ExaminedEvent args) - { - args.PushText(Loc.GetString(lockComp.Locked - ? "lock-comp-on-examined-is-locked" - : "lock-comp-on-examined-is-unlocked", - ("entityName", EntityManager.GetComponent(lockComp.Owner).EntityName))); - } - - public bool TryLock(EntityUid uid, EntityUid user, LockComponent? lockComp = null) - { - if (!Resolve(uid, ref lockComp)) - return false; - - if (!CanToggleLock(uid, user, quiet: false)) - return false; - - if (!HasUserAccess(uid, user, quiet: false)) - return false; - - _sharedPopupSystem.PopupEntity(Loc.GetString("lock-comp-do-lock-success", ("entityName", EntityManager.GetComponent(uid).EntityName)), uid, user); - lockComp.Locked = true; - - _audio.PlayPvs(_audio.GetSound(lockComp.LockSound), uid, AudioParams.Default.WithVolume(-5)); - - if (EntityManager.TryGetComponent(uid, out AppearanceComponent? appearanceComp)) - { - _appearanceSystem.SetData(uid, StorageVisuals.Locked, true, appearanceComp); - } - - RaiseLocalEvent(lockComp.Owner, new LockToggledEvent(true), true); - - return true; - } - - public void Unlock(EntityUid uid, EntityUid? user, LockComponent? lockComp = null) - { - if (!Resolve(uid, ref lockComp)) - return; - - if (user is { Valid: true }) - { - _sharedPopupSystem.PopupEntity(Loc.GetString("lock-comp-do-unlock-success", ("entityName", EntityManager.GetComponent(uid).EntityName)), uid, user.Value); - } - - lockComp.Locked = false; - - _audio.PlayPvs(_audio.GetSound(lockComp.UnlockSound), uid, AudioParams.Default.WithVolume(-5)); - - if (EntityManager.TryGetComponent(lockComp.Owner, out AppearanceComponent? appearanceComp)) - { - _appearanceSystem.SetData(uid, StorageVisuals.Locked, false, appearanceComp); - } - - RaiseLocalEvent(lockComp.Owner, new LockToggledEvent(false), true); - } - - public bool TryUnlock(EntityUid uid, EntityUid user, LockComponent? lockComp = null) - { - if (!Resolve(uid, ref lockComp)) - return false; - - if (!CanToggleLock(uid, user, quiet: false)) - return false; - - if (!HasUserAccess(uid, user, quiet: false)) - return false; - - Unlock(uid, user, lockComp); - return true; - } - - /// - /// Before locking the entity, check whether it's a locker. If is, prevent it from being locked from the inside or while it is open. - /// - public bool CanToggleLock(EntityUid uid, EntityUid user, bool quiet = true) - { - if (!HasComp(user)) - return false; - - var ev = new LockToggleAttemptEvent(user, quiet); - RaiseLocalEvent(uid, ref ev, true); - return !ev.Cancelled; - } - - private bool HasUserAccess(EntityUid uid, EntityUid user, AccessReaderComponent? reader = null, bool quiet = true) - { - // Not having an AccessComponent means you get free access. woo! - if (!Resolve(uid, ref reader)) - return true; - - if (!_accessReader.IsAllowed(user, reader)) - { - if (!quiet) - _sharedPopupSystem.PopupEntity(Loc.GetString("lock-comp-has-user-access-fail"), uid, user); - return false; - } - - return true; - } - - private void AddToggleLockVerb(EntityUid uid, LockComponent component, GetVerbsEvent args) - { - if (!args.CanAccess || !args.CanInteract || !CanToggleLock(uid, args.User)) - return; - - AlternativeVerb verb = new(); - verb.Act = component.Locked ? - () => TryUnlock(uid, args.User, component) : - () => TryLock(uid, args.User, component); - verb.Text = Loc.GetString(component.Locked ? "toggle-lock-verb-unlock" : "toggle-lock-verb-lock"); - verb.IconTexture = component.Locked ? "/Textures/Interface/VerbIcons/unlock.svg.192dpi.png" : "/Textures/Interface/VerbIcons/lock.svg.192dpi.png"; - args.Verbs.Add(verb); - } - - private void OnEmagged(EntityUid uid, LockComponent component, ref GotEmaggedEvent args) - { - if (component.Locked) - { - _audio.PlayPvs(_audio.GetSound(component.UnlockSound), uid, AudioParams.Default.WithVolume(-5)); - - if (EntityManager.TryGetComponent(component.Owner, out AppearanceComponent? appearanceComp)) - { - _appearanceSystem.SetData(uid, StorageVisuals.Locked, false, appearanceComp); - } - EntityManager.RemoveComponent(uid); //Literally destroys the lock as a tell it was emagged - args.Handled = true; - } - } - } -} diff --git a/Content.Server/Lock/LockToggledEvent.cs b/Content.Server/Lock/LockToggledEvent.cs deleted file mode 100644 index e37f139b45..0000000000 --- a/Content.Server/Lock/LockToggledEvent.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Content.Server.Lock -{ - public sealed class LockToggledEvent : EntityEventArgs - { - public readonly bool Locked; - - public LockToggledEvent(bool locked) - { - Locked = locked; - } - } -} diff --git a/Content.Server/Morgue/CrematoriumSystem.cs b/Content.Server/Morgue/CrematoriumSystem.cs index 4ffadd0a98..ef1f8c9a2a 100644 --- a/Content.Server/Morgue/CrematoriumSystem.cs +++ b/Content.Server/Morgue/CrematoriumSystem.cs @@ -14,6 +14,7 @@ using Content.Shared.Examine; using Content.Shared.Standing; using Content.Shared.Storage; using Content.Shared.IdentityManagement; +using Content.Shared.Storage.Components; namespace Content.Server.Morgue; @@ -42,8 +43,9 @@ public sealed class CrematoriumSystem : EntitySystem return; if (_appearance.TryGetData(uid, CrematoriumVisuals.Burning, out var isBurning, appearance) && isBurning) + { args.PushMarkup(Loc.GetString("crematorium-entity-storage-component-on-examine-details-is-burning", ("owner", uid))); - + } if (_appearance.TryGetData(uid, StorageVisuals.HasContents, out var hasContents, appearance) && hasContents) { args.PushMarkup(Loc.GetString("crematorium-entity-storage-component-on-examine-details-has-contents")); @@ -54,9 +56,9 @@ public sealed class CrematoriumSystem : EntitySystem } } - private void OnAttemptOpen(EntityUid uid, ActiveCrematoriumComponent component, StorageOpenAttemptEvent args) + private void OnAttemptOpen(EntityUid uid, ActiveCrematoriumComponent component, ref StorageOpenAttemptEvent args) { - args.Cancel(); + args.Cancelled = true; } private void AddCremateVerb(EntityUid uid, CrematoriumComponent component, GetVerbsEvent args) diff --git a/Content.Server/Morgue/EntityStorageLayingDownOverrideSystem.cs b/Content.Server/Morgue/EntityStorageLayingDownOverrideSystem.cs index 18e0d8e958..3bafc0ea8c 100644 --- a/Content.Server/Morgue/EntityStorageLayingDownOverrideSystem.cs +++ b/Content.Server/Morgue/EntityStorageLayingDownOverrideSystem.cs @@ -1,15 +1,13 @@ -using Content.Server.Body.Systems; using Content.Server.Morgue.Components; -using Content.Server.Storage.Components; using Content.Shared.Body.Components; using Content.Shared.Standing; +using Content.Shared.Storage.Components; namespace Content.Server.Morgue; public sealed class EntityStorageLayingDownOverrideSystem : EntitySystem { [Dependency] private readonly StandingStateSystem _standing = default!; - [Dependency] private readonly BodySystem _body = default!; public override void Initialize() { @@ -18,11 +16,12 @@ public sealed class EntityStorageLayingDownOverrideSystem : EntitySystem SubscribeLocalEvent(OnBeforeClose); } - private void OnBeforeClose(EntityUid uid, EntityStorageLayingDownOverrideComponent component, - StorageBeforeCloseEvent args) + private void OnBeforeClose(EntityUid uid, EntityStorageLayingDownOverrideComponent component, ref StorageBeforeCloseEvent args) { foreach (var ent in args.Contents) + { if (HasComp(ent) && !_standing.IsDown(ent)) args.Contents.Remove(ent); + } } } diff --git a/Content.Server/Resist/ResistLockerSystem.cs b/Content.Server/Resist/ResistLockerSystem.cs index 0222cfef66..7230b496dc 100644 --- a/Content.Server/Resist/ResistLockerSystem.cs +++ b/Content.Server/Resist/ResistLockerSystem.cs @@ -1,12 +1,10 @@ -using Content.Shared.Movement; using Content.Server.Storage.Components; using Content.Server.DoAfter; -using Content.Server.Lock; -using Robust.Shared.Player; using Robust.Shared.Containers; using Content.Server.Popups; using Content.Shared.Movement.Events; using Content.Server.Storage.EntitySystems; +using Content.Shared.Lock; using Content.Shared.Popups; namespace Content.Server.Resist; diff --git a/Content.Server/Security/Systems/DeployableBarrierSystem.cs b/Content.Server/Security/Systems/DeployableBarrierSystem.cs index b5aa9a70aa..db8465a619 100644 --- a/Content.Server/Security/Systems/DeployableBarrierSystem.cs +++ b/Content.Server/Security/Systems/DeployableBarrierSystem.cs @@ -1,5 +1,4 @@ -using Content.Server.Lock; -using Content.Server.Storage.Components; +using Content.Shared.Lock; using Content.Shared.Security; using Robust.Server.GameObjects; @@ -24,7 +23,7 @@ namespace Content.Server.Security.Systems ToggleBarrierDeploy(uid, component, lockComponent.Locked); } - private void OnLockToggled(EntityUid uid, DeployableBarrierComponent component, LockToggledEvent args) + private void OnLockToggled(EntityUid uid, DeployableBarrierComponent component, ref LockToggledEvent args) { ToggleBarrierDeploy(uid, component, args.Locked); } diff --git a/Content.Server/Singularity/EntitySystems/EmitterSystem.cs b/Content.Server/Singularity/EntitySystems/EmitterSystem.cs index eb8b0ef981..10dd6f74ce 100644 --- a/Content.Server/Singularity/EntitySystems/EmitterSystem.cs +++ b/Content.Server/Singularity/EntitySystems/EmitterSystem.cs @@ -9,6 +9,7 @@ using Content.Server.Weapons.Ranged.Systems; using Content.Shared.Database; using Content.Shared.Examine; using Content.Shared.Interaction; +using Content.Shared.Lock; using Content.Shared.Popups; using Content.Shared.Projectiles; using Content.Shared.Singularity.Components; diff --git a/Content.Server/Storage/Components/EntityStorageComponent.cs b/Content.Server/Storage/Components/EntityStorageComponent.cs index 8173cbb6bf..705ad00ab9 100644 --- a/Content.Server/Storage/Components/EntityStorageComponent.cs +++ b/Content.Server/Storage/Components/EntityStorageComponent.cs @@ -99,36 +99,3 @@ public sealed class EntityStorageComponent : Component, IGasMixtureHolder [ViewVariables(VVAccess.ReadWrite)] public GasMixture Air { get; set; } = new (GasMixVolume); } - -public sealed class InsertIntoEntityStorageAttemptEvent : CancellableEntityEventArgs { } -public sealed class StoreMobInItemContainerAttemptEvent : CancellableEntityEventArgs -{ - public bool Handled = false; -} -public sealed class StorageOpenAttemptEvent : CancellableEntityEventArgs -{ - public bool Silent = false; - - public StorageOpenAttemptEvent (bool silent = false) - { - Silent = silent; - } -} -public sealed class StorageBeforeOpenEvent : EventArgs { } -public sealed class StorageAfterOpenEvent : EventArgs { } -public sealed class StorageCloseAttemptEvent : CancellableEntityEventArgs { } -public sealed class StorageBeforeCloseEvent : EventArgs -{ - public HashSet Contents; - - /// - /// Entities that will get inserted, regardless of any insertion or whitelist checks. - /// - public HashSet BypassChecks = new(); - - public StorageBeforeCloseEvent(HashSet contents) - { - Contents = contents; - } -} -public sealed class StorageAfterCloseEvent : EventArgs { } diff --git a/Content.Server/Storage/EntitySystems/BluespaceLockerSystem.cs b/Content.Server/Storage/EntitySystems/BluespaceLockerSystem.cs index af0e6e2692..fe368eb186 100644 --- a/Content.Server/Storage/EntitySystems/BluespaceLockerSystem.cs +++ b/Content.Server/Storage/EntitySystems/BluespaceLockerSystem.cs @@ -2,7 +2,6 @@ using System.Threading; using Content.Server.DoAfter; using Content.Server.Explosion.EntitySystems; -using Content.Server.Lock; using Content.Server.Mind.Components; using Content.Server.Resist; using Content.Server.Station.Components; @@ -10,6 +9,8 @@ using Content.Server.Storage.Components; using Content.Server.Tools.Systems; using Content.Shared.Access.Components; using Content.Shared.Coordinates; +using Content.Shared.Lock; +using Content.Shared.Storage.Components; using Robust.Shared.Random; using Robust.Shared.Timing; @@ -58,7 +59,7 @@ public sealed class BluespaceLockerSystem : EntitySystem Spawn(effectSourceComponent.BehaviorProperties.BluespaceEffectPrototype, effectTargetUid.ToCoordinates()); } - private void PreOpen(EntityUid uid, BluespaceLockerComponent component, StorageBeforeOpenEvent args) + private void PreOpen(EntityUid uid, BluespaceLockerComponent component, ref StorageBeforeOpenEvent args) { EntityStorageComponent? entityStorageComponent = null; int transportedEntities = 0; @@ -259,7 +260,7 @@ public sealed class BluespaceLockerSystem : EntitySystem } } - private void PostClose(EntityUid uid, BluespaceLockerComponent component, StorageAfterCloseEvent args) + private void PostClose(EntityUid uid, BluespaceLockerComponent component, ref StorageAfterCloseEvent args) { PostClose(uid, component); } diff --git a/Content.Server/Storage/EntitySystems/CursedEntityStorageSystem.cs b/Content.Server/Storage/EntitySystems/CursedEntityStorageSystem.cs index d9c5c14520..1492a3f481 100644 --- a/Content.Server/Storage/EntitySystems/CursedEntityStorageSystem.cs +++ b/Content.Server/Storage/EntitySystems/CursedEntityStorageSystem.cs @@ -1,11 +1,10 @@ using Content.Server.Storage.Components; using Content.Shared.Audio; -using Content.Shared.Interaction; -using Robust.Server.Containers; using Robust.Shared.Audio; using Robust.Shared.Player; using Robust.Shared.Random; using System.Linq; +using Content.Shared.Storage.Components; namespace Content.Server.Storage.EntitySystems; @@ -21,7 +20,7 @@ public sealed class CursedEntityStorageSystem : EntitySystem SubscribeLocalEvent(OnClose); } - private void OnClose(EntityUid uid, CursedEntityStorageComponent component, StorageAfterCloseEvent args) + private void OnClose(EntityUid uid, CursedEntityStorageComponent component, ref StorageAfterCloseEvent args) { if (!TryComp(uid, out var storage)) return; diff --git a/Content.Server/Storage/EntitySystems/EntityStorageSystem.cs b/Content.Server/Storage/EntitySystems/EntityStorageSystem.cs index 7deb015cc9..3d2bb019cc 100644 --- a/Content.Server/Storage/EntitySystems/EntityStorageSystem.cs +++ b/Content.Server/Storage/EntitySystems/EntityStorageSystem.cs @@ -10,8 +10,10 @@ using Content.Shared.Destructible; using Content.Shared.Hands.Components; using Content.Shared.Interaction; using Content.Shared.Item; +using Content.Shared.Lock; using Content.Shared.Placeable; using Content.Shared.Storage; +using Content.Shared.Storage.Components; using Content.Shared.Wall; using Content.Shared.Whitelist; using Robust.Server.Containers; @@ -20,7 +22,6 @@ using Robust.Shared.Map; using Robust.Shared.Physics; using Robust.Shared.Physics.Components; using Robust.Shared.Physics.Systems; -using Robust.Shared.Player; namespace Content.Server.Storage.EntitySystems; @@ -167,13 +168,15 @@ public sealed class EntityStorageSystem : EntitySystem if (!Resolve(uid, ref component)) return; - RaiseLocalEvent(uid, new StorageBeforeOpenEvent()); + var beforeev = new StorageBeforeOpenEvent(); + RaiseLocalEvent(uid, ref beforeev); component.Open = true; EmptyContents(uid, component); ModifyComponents(uid, component); - _audio.PlayPvs(component.OpenSound, component.Owner); + _audio.PlayPvs(component.OpenSound, uid); ReleaseGas(uid, component); - RaiseLocalEvent(uid, new StorageAfterOpenEvent()); + var afterev = new StorageAfterOpenEvent(); + RaiseLocalEvent(uid, ref afterev); } public void CloseStorage(EntityUid uid, EntityStorageComponent? component = null) @@ -186,8 +189,8 @@ public sealed class EntityStorageSystem : EntitySystem var entities = _lookup.GetEntitiesInRange(targetCoordinates, component.EnteringRange, LookupFlags.Approximate | LookupFlags.Dynamic | LookupFlags.Sundries); - var ev = new StorageBeforeCloseEvent(entities); - RaiseLocalEvent(uid, ev); + var ev = new StorageBeforeCloseEvent(entities, new()); + RaiseLocalEvent(uid, ref ev); var count = 0; foreach (var entity in ev.Contents) { @@ -207,9 +210,10 @@ public sealed class EntityStorageSystem : EntitySystem TakeGas(uid, component); ModifyComponents(uid, component); - _audio.PlayPvs(component.CloseSound, component.Owner); + _audio.PlayPvs(component.CloseSound, uid); component.LastInternalOpenAttempt = default; - RaiseLocalEvent(uid, new StorageAfterCloseEvent()); + var afterev = new StorageAfterCloseEvent(); + RaiseLocalEvent(uid, ref afterev); } public bool Insert(EntityUid toInsert, EntityUid container, EntityStorageComponent? component = null) @@ -302,7 +306,7 @@ public sealed class EntityStorageSystem : EntitySystem } var ev = new StorageOpenAttemptEvent(silent); - RaiseLocalEvent(target, ev, true); + RaiseLocalEvent(target, ref ev, true); return !ev.Cancelled; } @@ -310,7 +314,7 @@ public sealed class EntityStorageSystem : EntitySystem public bool CanClose(EntityUid target, bool silent = false) { var ev = new StorageCloseAttemptEvent(); - RaiseLocalEvent(target, ev, silent); + RaiseLocalEvent(target, ref ev, silent); return !ev.Cancelled; } @@ -347,7 +351,7 @@ public sealed class EntityStorageSystem : EntitySystem // 6. if this is an item, then mobs must only be eaten if some other component prevents // pick-up interactions while a mob is inside (e.g. foldable) var attemptEvent = new InsertIntoEntityStorageAttemptEvent(); - RaiseLocalEvent(toInsert, attemptEvent); + RaiseLocalEvent(toInsert, ref attemptEvent); if (attemptEvent.Cancelled) return false; @@ -367,7 +371,7 @@ public sealed class EntityStorageSystem : EntitySystem else { var storeEv = new StoreMobInItemContainerAttemptEvent(); - RaiseLocalEvent(container, storeEv); + RaiseLocalEvent(container, ref storeEv); allowedToEat = storeEv.Handled && !storeEv.Cancelled; } } diff --git a/Content.Server/Storage/EntitySystems/StorageSystem.cs b/Content.Server/Storage/EntitySystems/StorageSystem.cs index 04d500412b..7cc632247a 100644 --- a/Content.Server/Storage/EntitySystems/StorageSystem.cs +++ b/Content.Server/Storage/EntitySystems/StorageSystem.cs @@ -31,6 +31,7 @@ using Content.Shared.ActionBlocker; using Content.Shared.CombatMode; using Content.Shared.Containers.ItemSlots; using Content.Shared.Implants.Components; +using Content.Shared.Lock; using Content.Shared.Movement.Events; namespace Content.Server.Storage.EntitySystems diff --git a/Content.Shared/Lock/LockComponent.cs b/Content.Shared/Lock/LockComponent.cs new file mode 100644 index 0000000000..d8c0963830 --- /dev/null +++ b/Content.Shared/Lock/LockComponent.cs @@ -0,0 +1,57 @@ +using Robust.Shared.Audio; +using Robust.Shared.GameStates; +using Robust.Shared.Serialization; + +namespace Content.Shared.Lock; + +/// +/// Allows locking/unlocking, with access determined by AccessReader +/// +[RegisterComponent, NetworkedComponent] +[Access(typeof(LockSystem))] +public sealed class LockComponent : Component +{ + /// + /// Whether or not the lock is locked. + /// + [DataField("locked"), ViewVariables(VVAccess.ReadWrite)] + public bool Locked = true; + + /// + /// Whether or not the lock is toggled by simply clicking. + /// + [DataField("lockOnClick"), ViewVariables(VVAccess.ReadWrite)] + public bool LockOnClick; + + /// + /// The sound played when unlocked. + /// + [DataField("unlockingSound"), ViewVariables(VVAccess.ReadWrite)] + public SoundSpecifier UnlockSound = new SoundPathSpecifier("/Audio/Machines/door_lock_off.ogg"); + + /// + /// The sound played when locked. + /// + [DataField("lockingSound"), ViewVariables(VVAccess.ReadWrite)] + public SoundSpecifier LockSound = new SoundPathSpecifier("/Audio/Machines/door_lock_on.ogg"); +} + +[Serializable, NetSerializable] +public sealed class LockComponentState : ComponentState +{ + public bool Locked; + + public bool LockOnClick; + + public LockComponentState(bool locked, bool lockOnClick) + { + Locked = locked; + LockOnClick = lockOnClick; + } +} + +[ByRefEvent] +public record struct LockToggleAttemptEvent(EntityUid User, bool Silent = false, bool Cancelled = false); + +[ByRefEvent] +public readonly record struct LockToggledEvent(bool Locked); diff --git a/Content.Shared/Lock/LockSystem.cs b/Content.Shared/Lock/LockSystem.cs new file mode 100644 index 0000000000..b8ae9fdd07 --- /dev/null +++ b/Content.Shared/Lock/LockSystem.cs @@ -0,0 +1,243 @@ +using Content.Shared.Emag.Systems; +using Content.Shared.Access.Components; +using Content.Shared.Access.Systems; +using Content.Shared.Examine; +using Content.Shared.Hands.Components; +using Content.Shared.IdentityManagement; +using Content.Shared.Interaction; +using Content.Shared.Popups; +using Content.Shared.Storage; +using Content.Shared.Storage.Components; +using Content.Shared.Verbs; +using JetBrains.Annotations; +using Robust.Shared.Audio; +using Robust.Shared.GameStates; +using Robust.Shared.Network; +using Robust.Shared.Timing; + +namespace Content.Shared.Lock; + +/// +/// Handles (un)locking and examining of Lock components +/// +[UsedImplicitly] +public sealed class LockSystem : EntitySystem +{ + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly INetManager _net = default!; + [Dependency] private readonly AccessReaderSystem _accessReader = default!; + [Dependency] private readonly SharedAppearanceSystem _appearanceSystem = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly SharedPopupSystem _sharedPopupSystem = default!; + + /// + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnGetState); + SubscribeLocalEvent(OnHandleState); + SubscribeLocalEvent(OnStartup); + SubscribeLocalEvent(OnActivated); + SubscribeLocalEvent(OnStorageOpenAttempt); + SubscribeLocalEvent(OnExamined); + SubscribeLocalEvent>(AddToggleLockVerb); + SubscribeLocalEvent(OnEmagged); + } + + private void OnGetState(EntityUid uid, LockComponent component, ref ComponentGetState args) + { + args.State = new LockComponentState(component.Locked, component.LockOnClick); + } + + private void OnHandleState(EntityUid uid, LockComponent component, ref ComponentHandleState args) + { + if (args.Current is not LockComponentState state) + return; + component.Locked = state.Locked; + component.LockOnClick = state.LockOnClick; + } + + private void OnStartup(EntityUid uid, LockComponent lockComp, ComponentStartup args) + { + _appearanceSystem.SetData(uid, StorageVisuals.CanLock, true); + } + + private void OnActivated(EntityUid uid, LockComponent lockComp, ActivateInWorldEvent args) + { + if (args.Handled) + return; + + // Only attempt an unlock by default on Activate + if (lockComp.Locked) + { + TryUnlock(uid, args.User, lockComp); + args.Handled = true; + } + else if (lockComp.LockOnClick) + { + TryLock(uid, args.User, lockComp); + args.Handled = true; + } + } + + private void OnStorageOpenAttempt(EntityUid uid, LockComponent component, ref StorageOpenAttemptEvent args) + { + if (!component.Locked) + return; + if (!args.Silent) + _sharedPopupSystem.PopupEntity(Loc.GetString("entity-storage-component-locked-message"), uid); + + args.Cancelled = true; + } + + private void OnExamined(EntityUid uid, LockComponent lockComp, ExaminedEvent args) + { + args.PushText(Loc.GetString(lockComp.Locked + ? "lock-comp-on-examined-is-locked" + : "lock-comp-on-examined-is-unlocked", + ("entityName", Identity.Name(uid, EntityManager)))); + } + + /// + /// Attmempts to lock a given entity + /// + /// The entity with the lock + /// The person trying to lock it + /// + /// If locking was successful + public bool TryLock(EntityUid uid, EntityUid user, LockComponent? lockComp = null) + { + if (!Resolve(uid, ref lockComp)) + return false; + + if (!CanToggleLock(uid, user, quiet: false)) + return false; + + if (!HasUserAccess(uid, user, quiet: false)) + return false; + + if (_net.IsClient && _timing.IsFirstTimePredicted) + { + _sharedPopupSystem.PopupEntity(Loc.GetString("lock-comp-do-lock-success", + ("entityName", Identity.Name(uid, EntityManager))), uid, user); + _audio.PlayPvs(_audio.GetSound(lockComp.LockSound), uid, AudioParams.Default.WithVolume(-5)); + } + + lockComp.Locked = true; + _appearanceSystem.SetData(uid, StorageVisuals.Locked, true); + Dirty(lockComp); + + RaiseLocalEvent(uid, new LockToggledEvent(true), true); + return true; + } + + /// + /// Forces a given entity to be unlocked + /// + /// The entity with the lock + /// The person unlocking it. Can be null + /// + public void Unlock(EntityUid uid, EntityUid? user, LockComponent? lockComp = null) + { + if (!Resolve(uid, ref lockComp)) + return; + + if (_net.IsClient && _timing.IsFirstTimePredicted) + { + if (user is { Valid: true }) + { + _sharedPopupSystem.PopupEntity(Loc.GetString("lock-comp-do-unlock-success", + ("entityName", Identity.Name(uid, EntityManager))), uid, user.Value); + } + _audio.PlayPvs(_audio.GetSound(lockComp.UnlockSound), uid, AudioParams.Default.WithVolume(-5)); + } + + lockComp.Locked = false; + _appearanceSystem.SetData(uid, StorageVisuals.Locked, false); + Dirty(lockComp); + + RaiseLocalEvent(uid, new LockToggledEvent(false), true); + } + + + /// + /// Attmempts to unlock a given entity + /// + /// The entity with the lock + /// The person trying to unlock it + /// + /// If locking was successful + public bool TryUnlock(EntityUid uid, EntityUid user, LockComponent? lockComp = null) + { + if (!Resolve(uid, ref lockComp)) + return false; + + if (!CanToggleLock(uid, user, quiet: false)) + return false; + + if (!HasUserAccess(uid, user, quiet: false)) + return false; + + Unlock(uid, user, lockComp); + return true; + } + + /// + /// Raises an event for other components to check whether or not + /// the entity can be locked in its current state. + /// + public bool CanToggleLock(EntityUid uid, EntityUid user, bool quiet = true) + { + if (!HasComp(user)) + return false; + + var ev = new LockToggleAttemptEvent(user, quiet); + RaiseLocalEvent(uid, ref ev, true); + return !ev.Cancelled; + } + + private bool HasUserAccess(EntityUid uid, EntityUid user, AccessReaderComponent? reader = null, bool quiet = true) + { + // Not having an AccessComponent means you get free access. woo! + if (!Resolve(uid, ref reader)) + return true; + + if (_accessReader.IsAllowed(user, reader)) + return true; + + if (!quiet && _net.IsClient && _timing.IsFirstTimePredicted) + _sharedPopupSystem.PopupEntity(Loc.GetString("lock-comp-has-user-access-fail"), uid, user); + return false; + } + + private void AddToggleLockVerb(EntityUid uid, LockComponent component, GetVerbsEvent args) + { + if (!args.CanAccess || !args.CanInteract || !CanToggleLock(uid, args.User)) + return; + + AlternativeVerb verb = new() + { + Act = component.Locked ? + () => TryUnlock(uid, args.User, component) : + () => TryLock(uid, args.User, component), + Text = Loc.GetString(component.Locked ? "toggle-lock-verb-unlock" : "toggle-lock-verb-lock"), + IconTexture = component.Locked ? "/Textures/Interface/VerbIcons/unlock.svg.192dpi.png" : "/Textures/Interface/VerbIcons/lock.svg.192dpi.png" + }; + args.Verbs.Add(verb); + } + + private void OnEmagged(EntityUid uid, LockComponent component, ref GotEmaggedEvent args) + { + if (!component.Locked) + return; + if (_net.IsClient && _timing.IsFirstTimePredicted) + { + _audio.PlayPvs(_audio.GetSound(component.UnlockSound), uid, AudioParams.Default.WithVolume(-5)); + } + _appearanceSystem.SetData(uid, StorageVisuals.Locked, false); + RemComp(uid); //Literally destroys the lock as a tell it was emagged + args.Handled = true; + } +} + diff --git a/Content.Shared/Storage/Components/SharedEntityStorage.cs b/Content.Shared/Storage/Components/SharedEntityStorage.cs new file mode 100644 index 0000000000..a3399e2926 --- /dev/null +++ b/Content.Shared/Storage/Components/SharedEntityStorage.cs @@ -0,0 +1,25 @@ +namespace Content.Shared.Storage.Components; + +[ByRefEvent] +public record struct InsertIntoEntityStorageAttemptEvent(bool Cancelled = false); + +[ByRefEvent] +public record struct StoreMobInItemContainerAttemptEvent(bool Handled, bool Cancelled = false); + +[ByRefEvent] +public record struct StorageOpenAttemptEvent(bool Silent, bool Cancelled = false); + +[ByRefEvent] +public readonly record struct StorageBeforeOpenEvent; + +[ByRefEvent] +public readonly record struct StorageAfterOpenEvent; + +[ByRefEvent] +public record struct StorageCloseAttemptEvent(bool Cancelled = false); + +[ByRefEvent] +public readonly record struct StorageBeforeCloseEvent(HashSet Contents, HashSet BypassChecks); + +[ByRefEvent] +public readonly record struct StorageAfterCloseEvent; -- 2.52.0