diff --git a/Content.Goobstation.Client/Security/Systems/ContrabandIconsSystem.cs b/Content.Goobstation.Client/Security/Systems/ContrabandIconsSystem.cs index 678056d49bf1..4fe4d54c6eaf 100644 --- a/Content.Goobstation.Client/Security/Systems/ContrabandIconsSystem.cs +++ b/Content.Goobstation.Client/Security/Systems/ContrabandIconsSystem.cs @@ -1,5 +1,84 @@ +using Content.Goobstation.Common.CCVar; +using Content.Goobstation.Common.Security.ContrabandIcons.Events; +using Content.Goobstation.Shared.Contraband; using Content.Goobstation.Shared.Security.ContrabandIcons; +using Content.Goobstation.Shared.Security.ContrabandIcons.Components; +using Content.Shared.Contraband; +using Content.Shared.Inventory; +using Content.Shared.Inventory.Events; +using Robust.Shared.Configuration; + namespace Content.Goobstation.Client.Security.Systems; -public sealed class ContrabandIconsSystem : SharedContrabandIconsSystem; +public sealed class ContrabandIconsSystem : SharedContrabandIconsSystem +{ + [Dependency] private readonly IConfigurationManager _configuration = default!; + [Dependency] private readonly SharedContrabandDetectorSystem _detectorSystem = default!; + + private bool _isEnabled = true; + private EntityQuery _contrabandQuery; + + public override void Initialize() + { + base.Initialize(); + _contrabandQuery = GetEntityQuery(); + + Subs.CVar(_configuration, GoobCVars.ContrabandIconsEnabled, value => _isEnabled = value); + + SubscribeLocalEvent(OnEquip); + SubscribeLocalEvent(OnUnequip); + + SubscribeLocalEvent(OnIdCardInserted); + SubscribeLocalEvent(OnIdCardRemoved); + SubscribeLocalEvent(OnComponentStartup); + } + + private void OnEquip(EntityUid uid, VisibleContrabandComponent comp, DidEquipEvent args) + { + if (!_isEnabled) + return; + if (args.SlotFlags == SlotFlags.IDCARD) + { + CheckAllContra(args.Equipee); + return; + } + if (args.SlotFlags == SlotFlags.POCKET) + return; + if (!_contrabandQuery.TryComp(args.Equipment, out var contra)) + return; + if (contra.Severity == "Minor") + return; + var hasPermission = _detectorSystem.CheckContrabandPermission(args.Equipment, args.Equipee, contra); + if ((contra.Severity == "Restricted" || contra.Severity == "GrandTheft") && hasPermission) + return; + comp.VisibleItems.Add(args.Equipment); + UpdateStatusIcon(comp, args.Equipee, ContrabandStatus.Contraband); + } + + private void OnUnequip(EntityUid uid, VisibleContrabandComponent comp, DidUnequipEvent args) + { + if (args.SlotFlags == SlotFlags.IDCARD) + { + CheckAllContra(args.Equipee); + return; + } + comp.VisibleItems.Remove(args.Equipment); + if (comp.VisibleItems.Count == 0) + UpdateStatusIcon(comp, args.Equipee, ContrabandStatus.None); + } + + private void OnIdCardInserted(IdCardInsertedEvent args) + { + CheckAllContra(args.TargetUid); + } + + private void OnIdCardRemoved(IdCardRemovedEvent args) + { + CheckAllContra(args.TargetUid); + } + private void OnComponentStartup(EntityUid uid, VisibleContrabandComponent component, ComponentStartup args) + { + CheckAllContra(uid); + } +} diff --git a/Content.Goobstation.Client/Security/Systems/ShowContrabandIconsSystem.cs b/Content.Goobstation.Client/Security/Systems/ShowContrabandIconsSystem.cs index 885f2944f933..7e54bdf19ff2 100644 --- a/Content.Goobstation.Client/Security/Systems/ShowContrabandIconsSystem.cs +++ b/Content.Goobstation.Client/Security/Systems/ShowContrabandIconsSystem.cs @@ -1,25 +1,27 @@ using Content.Client.Overlays; using Content.Shared.StatusIcon.Components; using Robust.Shared.Prototypes; -using ShowContrabandIconsComponent = Content.Goobstation.Shared.Security.ContrabandIcons.Components.ShowContrabandIconsComponent; -using VisibleContrabandComponent = Content.Goobstation.Shared.Security.ContrabandIcons.Components.VisibleContrabandComponent; +using Content.Goobstation.Shared.Security.ContrabandIcons.Components; +using Content.Goobstation.Common.CCVar; +using Robust.Shared.Configuration; namespace Content.Goobstation.Client.Security.Systems; public sealed class ShowContrabandIconsSystem : EquipmentHudSystem { [Dependency] private readonly IPrototypeManager _prototype = default!; - + [Dependency] private readonly IConfigurationManager _configuration = default!; + private bool _isEnabled = true; public override void Initialize() { base.Initialize(); - + Subs.CVar(_configuration, GoobCVars.ContrabandIconsEnabled, value => _isEnabled = value); SubscribeLocalEvent(OnGetStatusIconsEvent); } private void OnGetStatusIconsEvent(EntityUid uid, VisibleContrabandComponent component, ref GetStatusIconsEvent ev) { - if (!IsActive) + if (!IsActive || !_isEnabled) return; if (_prototype.TryIndex(component.StatusIcon, out var iconPrototype)) diff --git a/Content.Goobstation.Common/CCVar/CCVars.Goob.cs b/Content.Goobstation.Common/CCVar/CCVars.Goob.cs index c0a40736eb28..5c3fc3bee1c4 100644 --- a/Content.Goobstation.Common/CCVar/CCVars.Goob.cs +++ b/Content.Goobstation.Common/CCVar/CCVars.Goob.cs @@ -641,10 +641,11 @@ public sealed partial class GoobCVars public static readonly CVarDef BleedMultiplier = CVarDef.Create("medical.bloodloss_multiplier", 4.0f, CVar.SERVER); - #endregion + /// /// Enables or disables contraband icons. /// public static readonly CVarDef ContrabandIconsEnabled = - CVarDef.Create("contraband.icons_enabled", false, CVar.SERVER | CVar.REPLICATED); -} + CVarDef.Create("contraband.icons_enabled", true, CVar.SERVER | CVar.REPLICATED); + #endregion +} \ No newline at end of file diff --git a/Content.Goobstation.Common/Security/ContrabandIcons/Events/SharedContrabandIconsEvents.cs b/Content.Goobstation.Common/Security/ContrabandIcons/Events/SharedContrabandIconsEvents.cs new file mode 100644 index 000000000000..86a79bea570a --- /dev/null +++ b/Content.Goobstation.Common/Security/ContrabandIcons/Events/SharedContrabandIconsEvents.cs @@ -0,0 +1,11 @@ +namespace Content.Goobstation.Common.Security.ContrabandIcons.Events; + + + +/// The entity UID of the ID card that was inserted. +/// The entity UID of the Pda. +public record struct IdCardInsertedEvent(EntityUid IdCardUid, EntityUid TargetUid); + +/// The entity UID of the ID card that was removed. +/// The entity UID of the Pda. +public record struct IdCardRemovedEvent(EntityUid IdCardUid, EntityUid TargetUid); \ No newline at end of file diff --git a/Content.Goobstation.Server/Security/ContrabandIcons/ContrabandIconsSystem.cs b/Content.Goobstation.Server/Security/ContrabandIcons/ContrabandIconsSystem.cs index 5fad338ba3e8..b58a7971a657 100644 --- a/Content.Goobstation.Server/Security/ContrabandIcons/ContrabandIconsSystem.cs +++ b/Content.Goobstation.Server/Security/ContrabandIcons/ContrabandIconsSystem.cs @@ -1,21 +1,5 @@ using Content.Goobstation.Shared.Security.ContrabandIcons; -using Content.Goobstation.Shared.Security.ContrabandIcons.Components; -using Content.Shared._Goobstation.Security.ContrabandIcons; -using Content.Shared.Inventory; namespace Content.Goobstation.Server.Security.ContrabandIcons; -public sealed class ContrabandIconsSystem : SharedContrabandIconsSystem -{ - public override void Initialize() - { - base.Initialize(); - - SubscribeLocalEvent(OnMapInit); - } - - private void OnMapInit(EntityUid uid, VisibleContrabandComponent component, MapInitEvent args) - { - ContrabandDetect(uid, component, SlotFlags.WITHOUT_POCKET); - } -} +public sealed class ContrabandIconsSystem : SharedContrabandIconsSystem; diff --git a/Content.Goobstation.Shared/Security/ContrabandIcons/Components/VisibleContrabandComponent.cs b/Content.Goobstation.Shared/Security/ContrabandIcons/Components/VisibleContrabandComponent.cs index c188ae90a590..77b8f5c27f4b 100644 --- a/Content.Goobstation.Shared/Security/ContrabandIcons/Components/VisibleContrabandComponent.cs +++ b/Content.Goobstation.Shared/Security/ContrabandIcons/Components/VisibleContrabandComponent.cs @@ -1,4 +1,4 @@ -using Content.Shared._Goobstation.Security.ContrabandIcons.Prototypes; +using Content.Goobstation.Shared.Security.ContrabandIcons.Prototypes; using Robust.Shared.GameStates; using Robust.Shared.Prototypes; @@ -12,4 +12,13 @@ public sealed partial class VisibleContrabandComponent : Component /// [DataField, AutoNetworkedField] public ProtoId StatusIcon = "ContrabandIconNone"; + + [DataField] + public HashSet VisibleItems = new(); +} + +public enum ContrabandStatus : byte +{ + None, + Contraband } diff --git a/Content.Goobstation.Shared/Security/ContrabandIcons/Prototypes/ContrabandIcons.cs b/Content.Goobstation.Shared/Security/ContrabandIcons/Prototypes/ContrabandIcons.cs index 4a7d298314ad..6c4654a9dafa 100644 --- a/Content.Goobstation.Shared/Security/ContrabandIcons/Prototypes/ContrabandIcons.cs +++ b/Content.Goobstation.Shared/Security/ContrabandIcons/Prototypes/ContrabandIcons.cs @@ -2,7 +2,7 @@ using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Array; -namespace Content.Shared._Goobstation.Security.ContrabandIcons.Prototypes; +namespace Content.Goobstation.Shared.Security.ContrabandIcons.Prototypes; [Prototype("contrabandIcon")] public sealed partial class ContrabandIconPrototype : StatusIconPrototype, IInheritingPrototype diff --git a/Content.Goobstation.Shared/Security/ContrabandIcons/Prototypes/ContrabandStatus.cs b/Content.Goobstation.Shared/Security/ContrabandIcons/Prototypes/ContrabandStatus.cs deleted file mode 100644 index 572cac8beca4..000000000000 --- a/Content.Goobstation.Shared/Security/ContrabandIcons/Prototypes/ContrabandStatus.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Content.Goobstation.Shared.Security.ContrabandIcons.Prototypes; - -public enum ContrabandStatus : byte -{ - None, - Contraband -} diff --git a/Content.Goobstation.Shared/Security/ContrabandIcons/SharedContrabandIconsSystem.cs b/Content.Goobstation.Shared/Security/ContrabandIcons/SharedContrabandIconsSystem.cs index 5c39738879b0..8a4e5c795a21 100644 --- a/Content.Goobstation.Shared/Security/ContrabandIcons/SharedContrabandIconsSystem.cs +++ b/Content.Goobstation.Shared/Security/ContrabandIcons/SharedContrabandIconsSystem.cs @@ -1,74 +1,61 @@ -using Content.Goobstation.Common.CCVar; +using System.Linq; using Content.Goobstation.Shared.Contraband; using Content.Goobstation.Shared.Security.ContrabandIcons.Components; -using Content.Goobstation.Shared.Security.ContrabandIcons.Prototypes; -using Content.Shared.Hands; using Content.Shared.Inventory; -using Content.Shared.Inventory.Events; -using Content.Shared.Strip.Components; -using Robust.Shared.Configuration; +using Robust.Shared.Network; namespace Content.Goobstation.Shared.Security.ContrabandIcons; -/// -/// This handles... -/// public abstract class SharedContrabandIconsSystem : EntitySystem { [Dependency] private readonly SharedContrabandDetectorSystem _detectorSystem = default!; - [Dependency] private readonly IConfigurationManager _configuration = default!; - private bool _isEnabled = true; + [Dependency] private readonly InventorySystem _inventory = default!; + [Dependency] private readonly INetManager _net = default!; + private EntityQuery _visibleContrabandQuery; public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(OnEquip); - SubscribeLocalEvent(OnUnequip); - - SubscribeLocalEvent(OnEquipHands); - SubscribeLocalEvent(OnUnequipHands); - - Subs.CVar(_configuration, GoobCVars.ContrabandIconsEnabled, value => _isEnabled = value); + _visibleContrabandQuery = GetEntityQuery(); } - - protected void ContrabandDetect(EntityUid inventory, VisibleContrabandComponent component, SlotFlags slotFlags = SlotFlags.WITHOUT_POCKET) - { - if (!_isEnabled) - return; - if (HasComp(inventory)) - return; - var list = _detectorSystem.FindContraband(inventory, false, slotFlags); - var isDetected = list.Count > 0; - component.StatusIcon = StatusToIcon(isDetected ? ContrabandStatus.Contraband : ContrabandStatus.None); - Dirty(inventory, component); - } - private string StatusToIcon(ContrabandStatus status) { - return status switch - { - ContrabandStatus.None => "ContrabandIconNone", - ContrabandStatus.Contraband => "ContrabandIconContraband", - _ => "ContrabandIconNone" - }; + return status == ContrabandStatus.Contraband ? "ContrabandIconContraband" : "ContrabandIconNone"; } - private void OnEquip(EntityUid uid, VisibleContrabandComponent component, DidEquipEvent args) + protected void CheckAllContra(EntityUid uid) { - ContrabandDetect(uid, component, args.SlotFlags); - } + uid = GetHighestContainerOwner(uid); - private void OnUnequip(EntityUid uid, VisibleContrabandComponent component, DidUnequipEvent args) - { - ContrabandDetect(uid, component, args.SlotFlags); + if (!_visibleContrabandQuery.TryComp(uid, out var visible)) + return; + var contraband = _detectorSystem.FindContraband(uid, false, SlotFlags.WITHOUT_POCKET); + if (contraband == null) // this is stupid but it works + return; + + visible.VisibleItems = contraband.ToHashSet(); + var status = visible.VisibleItems.Count > 0 ? ContrabandStatus.Contraband : ContrabandStatus.None; + UpdateStatusIcon(visible, uid, status); } - private void OnUnequipHands(EntityUid uid, VisibleContrabandComponent component, DidUnequipHandEvent args) + protected void UpdateStatusIcon(VisibleContrabandComponent comp, EntityUid uid, ContrabandStatus status) { - ContrabandDetect(uid, component, SlotFlags.NONE); + var newStatus = StatusToIcon(status); + if (comp.StatusIcon == newStatus) + return; + + comp.StatusIcon = newStatus; + if (_net.IsServer) + Dirty(uid, comp); } - private void OnEquipHands(EntityUid uid, VisibleContrabandComponent component, DidEquipHandEvent args) + + private EntityUid GetHighestContainerOwner(EntityUid uid) { - ContrabandDetect(uid, component, SlotFlags.NONE); + while (_inventory.TryGetContainingEntity(uid, out var containerEntity)) + { + uid = containerEntity.Value; + } + + return uid; } -} +} \ No newline at end of file diff --git a/Content.Shared/Overlays/ShowCriminalRecordIconsComponent.cs b/Content.Shared/Overlays/ShowCriminalRecordIconsComponent.cs index 2a4f472aedd7..0444e6636cab 100644 --- a/Content.Shared/Overlays/ShowCriminalRecordIconsComponent.cs +++ b/Content.Shared/Overlays/ShowCriminalRecordIconsComponent.cs @@ -13,4 +13,4 @@ namespace Content.Shared.Overlays; /// This component allows you to see criminal record status of mobs. /// [RegisterComponent, NetworkedComponent] -public sealed partial class ShowCriminalRecordIconsComponent : Component { } \ No newline at end of file +public sealed partial class ShowCriminalRecordIconsComponent : Component; \ No newline at end of file diff --git a/Content.Shared/PDA/SharedPdaSystem.cs b/Content.Shared/PDA/SharedPdaSystem.cs index 6004762a8ac2..9be6dd83b09e 100644 --- a/Content.Shared/PDA/SharedPdaSystem.cs +++ b/Content.Shared/PDA/SharedPdaSystem.cs @@ -11,6 +11,7 @@ // // SPDX-License-Identifier: MIT +using Content.Goobstation.Common.Security.ContrabandIcons.Events; using Content.Shared.Access.Components; using Content.Shared.Containers.ItemSlots; using Robust.Shared.Containers; @@ -57,7 +58,7 @@ protected virtual void OnItemInserted(EntityUid uid, PdaComponent pda, EntInsert { if (args.Container.ID == PdaComponent.PdaIdSlotId) pda.ContainedId = args.Entity; - + RaiseLocalEvent(new IdCardInsertedEvent(args.Entity, args.Container.Owner)); //goob event UpdatePdaAppearance(uid, pda); } @@ -65,7 +66,7 @@ protected virtual void OnItemRemoved(EntityUid uid, PdaComponent pda, EntRemoved { if (args.Container.ID == pda.IdSlot.ID) pda.ContainedId = null; - + RaiseLocalEvent(new IdCardRemovedEvent(args.Entity, args.Container.Owner)); //goob event UpdatePdaAppearance(uid, pda); } diff --git a/Resources/Prototypes/Entities/Clothing/Ears/headsets_alt.yml b/Resources/Prototypes/Entities/Clothing/Ears/headsets_alt.yml index b138b83ad076..5d68b9d58829 100644 --- a/Resources/Prototypes/Entities/Clothing/Ears/headsets_alt.yml +++ b/Resources/Prototypes/Entities/Clothing/Ears/headsets_alt.yml @@ -130,7 +130,7 @@ sprite: Clothing/Ears/Headsets/cargo.rsi - type: entity - parent: [ClothingHeadsetAlt, BaseCommandContraband] # Goobstation + parent: [ClothingHeadsetAlt, BaseCentcommCommandContraband] # Goobstation id: ClothingHeadsetAltCentCom name: CentComm over-ear headset components: diff --git a/Resources/Prototypes/Entities/Objects/base_contraband.yml b/Resources/Prototypes/Entities/Objects/base_contraband.yml index 67fe932ccc6a..b74b209b34eb 100644 --- a/Resources/Prototypes/Entities/Objects/base_contraband.yml +++ b/Resources/Prototypes/Entities/Objects/base_contraband.yml @@ -186,7 +186,7 @@ abstract: true components: - type: Contraband - allowedDepartments: [ Security, Cargo ] + allowedDepartments: [ Security, Cargo, CentralCommand ] # Goob - blueshield gear - type: entity id: BaseMedicalScienceContraband diff --git a/Resources/Prototypes/_Goobstation/Entities/Objects/base_contraband.yml b/Resources/Prototypes/_Goobstation/Entities/Objects/base_contraband.yml index 8a9c003d84fb..76270cb7d80b 100644 --- a/Resources/Prototypes/_Goobstation/Entities/Objects/base_contraband.yml +++ b/Resources/Prototypes/_Goobstation/Entities/Objects/base_contraband.yml @@ -28,7 +28,7 @@ abstract: true components: - type: Contraband - allowedDepartments: [ Security, Engineering, Cargo ] + allowedDepartments: [ Security, Engineering, Cargo, CentralCommand ] # stupid fucking BSO - type: entity id: BaseSecurityZookeeperContraband # Tranq shells diff --git a/Resources/Prototypes/_Goobstation/StatusIcon/contraband_icons.yml b/Resources/Prototypes/_Goobstation/StatusIcon/contraband_icons.yml index 2c81db9b71a1..23548dc57e98 100644 --- a/Resources/Prototypes/_Goobstation/StatusIcon/contraband_icons.yml +++ b/Resources/Prototypes/_Goobstation/StatusIcon/contraband_icons.yml @@ -10,13 +10,12 @@ parent: ContrabandIcon id: ContrabandIconContraband icon: - sprite: /Textures/_Goobstation/Interface/Misc/security_icons.rsi + sprite: /Textures/_Goobstation/Interface/Misc/contraband_icons.rsi state: hud_contraband - + - type: contrabandIcon parent: ContrabandIcon id: ContrabandIconNone icon: - sprite: /Textures/_Goobstation/Interface/Misc/security_icons.rsi + sprite: /Textures/_Goobstation/Interface/Misc/contraband_icons.rsi state: hud_none - diff --git a/Resources/Textures/_Goobstation/Interface/Misc/security_icons.rsi/hud_contraband.png b/Resources/Textures/_Goobstation/Interface/Misc/contraband_icons.rsi/hud_contraband.png similarity index 100% rename from Resources/Textures/_Goobstation/Interface/Misc/security_icons.rsi/hud_contraband.png rename to Resources/Textures/_Goobstation/Interface/Misc/contraband_icons.rsi/hud_contraband.png diff --git a/Resources/Textures/_Goobstation/Interface/Misc/security_icons.rsi/hud_none.png b/Resources/Textures/_Goobstation/Interface/Misc/contraband_icons.rsi/hud_none.png similarity index 100% rename from Resources/Textures/_Goobstation/Interface/Misc/security_icons.rsi/hud_none.png rename to Resources/Textures/_Goobstation/Interface/Misc/contraband_icons.rsi/hud_none.png diff --git a/Resources/Textures/_Goobstation/Interface/Misc/contraband_icons.rsi/meta.json b/Resources/Textures/_Goobstation/Interface/Misc/contraband_icons.rsi/meta.json new file mode 100644 index 000000000000..e8c53d02d6a6 --- /dev/null +++ b/Resources/Textures/_Goobstation/Interface/Misc/contraband_icons.rsi/meta.json @@ -0,0 +1,18 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Contraband icon by Jvne, 'owe' on discord", + + "size": { + "x": 8, + "y": 8 + }, + "states": [ + { + "name": "hud_contraband" + }, + { + "name": "hud_none" + } + ] +} diff --git a/Resources/Textures/_Goobstation/Interface/Misc/security_icons.rsi/meta.json b/Resources/Textures/_Goobstation/Interface/Misc/security_icons.rsi/meta.json index 06988689e1e9..dc93e3e48137 100644 --- a/Resources/Textures/_Goobstation/Interface/Misc/security_icons.rsi/meta.json +++ b/Resources/Textures/_Goobstation/Interface/Misc/security_icons.rsi/meta.json @@ -14,12 +14,6 @@ [ [1.0,1.0] ] - }, - { - "name": "hud_contraband" - }, - { - "name": "hud_none" } ] }