From b9ead9dd6cea8959ccd219cdbebbec740cfc8dc8 Mon Sep 17 00:00:00 2001 From: Whatstone <166147148+whatston3@users.noreply.github.com> Date: Wed, 12 Aug 2026 03:25:52 +0000 Subject: [PATCH] Bugfix: SharedForensicsSystem: correct entity in Resolve, cleanup (#45263) * SharedForensicsSystem: cleanup * you too * IS * test scamboni * Shared: the burden * branch is cursed * allem private * suggestion, file rename --- .../Cloning/CloningSystem.Subscriptions.cs | 2 +- .../Nutrition/EntitySystems/SmokingSystem.cs | 2 +- .../Systems/ChangelingClonerSystem.cs | 2 +- .../Chemistry/EntitySystems/InjectorSystem.cs | 2 +- .../Forensics/Systems/ForensicPadSystem.cs | 2 +- ...dForensicsSystem.cs => ForensicsSystem.cs} | 55 +++++++++++-------- .../Systems/SharedForensicScannerSystem.cs | 2 +- .../Implants/SharedImplanterSystem.cs | 2 +- Content.Shared/Medical/VomitSystem.cs | 2 +- .../EntitySystems/IngestionSystem.cs | 2 +- .../Systems/DnaScrambleOnTriggerSystem.cs | 2 +- 11 files changed, 41 insertions(+), 34 deletions(-) rename Content.Shared/Forensics/Systems/{SharedForensicsSystem.cs => ForensicsSystem.cs} (87%) diff --git a/Content.Server/Cloning/CloningSystem.Subscriptions.cs b/Content.Server/Cloning/CloningSystem.Subscriptions.cs index b385814114..5f73649759 100644 --- a/Content.Server/Cloning/CloningSystem.Subscriptions.cs +++ b/Content.Server/Cloning/CloningSystem.Subscriptions.cs @@ -42,7 +42,7 @@ public sealed partial class CloningSystem [Dependency] private SharedChameleonClothingSystem _chameleonClothing = default!; [Dependency] private PullingSystem _pulling = default!; [Dependency] private BloodstreamSystem _bloodstream = default!; - [Dependency] private SharedForensicsSystem _forensics = default!; + [Dependency] private ForensicsSystem _forensics = default!; public override void Initialize() { diff --git a/Content.Server/Nutrition/EntitySystems/SmokingSystem.cs b/Content.Server/Nutrition/EntitySystems/SmokingSystem.cs index ca81e9e222..ec1e8389a4 100644 --- a/Content.Server/Nutrition/EntitySystems/SmokingSystem.cs +++ b/Content.Server/Nutrition/EntitySystems/SmokingSystem.cs @@ -34,7 +34,7 @@ namespace Content.Server.Nutrition.EntitySystems [Dependency] private SharedItemSystem _items = default!; [Dependency] private SharedContainerSystem _container = default!; [Dependency] private SharedAppearanceSystem _appearance = default!; - [Dependency] private SharedForensicsSystem _forensics = default!; + [Dependency] private ForensicsSystem _forensics = default!; private const float UpdateTimer = 3f; diff --git a/Content.Shared/Changeling/Systems/ChangelingClonerSystem.cs b/Content.Shared/Changeling/Systems/ChangelingClonerSystem.cs index dd13f5948b..bbc8f2e656 100644 --- a/Content.Shared/Changeling/Systems/ChangelingClonerSystem.cs +++ b/Content.Shared/Changeling/Systems/ChangelingClonerSystem.cs @@ -27,7 +27,7 @@ public sealed partial class ChangelingClonerSystem : EntitySystem [Dependency] private SharedCloningSystem _cloning = default!; [Dependency] private SharedAppearanceSystem _appearance = default!; [Dependency] private SharedChangelingIdentitySystem _changelingIdentity = default!; - [Dependency] private SharedForensicsSystem _forensics = default!; + [Dependency] private ForensicsSystem _forensics = default!; [Dependency] private SharedVisualBodySystem _visualBody = default!; public override void Initialize() diff --git a/Content.Shared/Chemistry/EntitySystems/InjectorSystem.cs b/Content.Shared/Chemistry/EntitySystems/InjectorSystem.cs index 5b990ac893..ad209ce5d8 100644 --- a/Content.Shared/Chemistry/EntitySystems/InjectorSystem.cs +++ b/Content.Shared/Chemistry/EntitySystems/InjectorSystem.cs @@ -33,7 +33,7 @@ public sealed partial class InjectorSystem : EntitySystem { [Dependency] private ISharedAdminLogManager _adminLogger = default!; [Dependency] private SharedAudioSystem _audio = default!; - [Dependency] private SharedForensicsSystem _forensics = default!; + [Dependency] private ForensicsSystem _forensics = default!; [Dependency] private SharedDoAfterSystem _doAfter = default!; [Dependency] private OpenableSystem _openable = default!; [Dependency] private SharedPopupSystem _popup = default!; diff --git a/Content.Shared/Forensics/Systems/ForensicPadSystem.cs b/Content.Shared/Forensics/Systems/ForensicPadSystem.cs index 00daebb17a..d7b58de4e8 100644 --- a/Content.Shared/Forensics/Systems/ForensicPadSystem.cs +++ b/Content.Shared/Forensics/Systems/ForensicPadSystem.cs @@ -15,7 +15,7 @@ public sealed partial class ForensicPadSystem : EntitySystem { [Dependency] private SharedDoAfterSystem _doAfterSystem = default!; [Dependency] private SharedPopupSystem _popupSystem = default!; - [Dependency] private SharedForensicsSystem _forensics = default!; + [Dependency] private ForensicsSystem _forensics = default!; [Dependency] private LabelSystem _label = default!; [SubscribeLocalEvent] diff --git a/Content.Shared/Forensics/Systems/SharedForensicsSystem.cs b/Content.Shared/Forensics/Systems/ForensicsSystem.cs similarity index 87% rename from Content.Shared/Forensics/Systems/SharedForensicsSystem.cs rename to Content.Shared/Forensics/Systems/ForensicsSystem.cs index c63fd264a7..fe82e9d331 100644 --- a/Content.Shared/Forensics/Systems/SharedForensicsSystem.cs +++ b/Content.Shared/Forensics/Systems/ForensicsSystem.cs @@ -9,18 +9,21 @@ using Content.Shared.Hands.Components; using Content.Shared.Interaction; using Content.Shared.Interaction.Events; using Content.Shared.Inventory; -using Content.Shared.Popups; -using Content.Shared.Verbs; using Content.Shared.Gibbing; using Content.Shared.IdentityManagement; using Content.Shared.Nutrition.EntitySystems; +using Content.Shared.Popups; +using Content.Shared.Verbs; using Content.Shared.Weapons.Melee.Events; using Robust.Shared.Random; using Robust.Shared.Utility; namespace Content.Shared.Forensics.Systems; -public sealed partial class SharedForensicsSystem : EntitySystem +/// +/// A system for storing forensics data on entities, and transferring them between entities when interacting. +/// +public sealed partial class ForensicsSystem : EntitySystem { [Dependency] private IRobustRandom _random = default!; [Dependency] private InventorySystem _inventory = default!; @@ -28,6 +31,14 @@ public sealed partial class SharedForensicsSystem : EntitySystem [Dependency] private SharedPopupSystem _popupSystem = default!; [Dependency] private SharedSolutionContainerSystem _solutionContainerSystem = default!; + [Dependency] private EntityQuery _dnaQuery = default!; + [Dependency] private EntityQuery _fiberQuery = default!; + [Dependency] private EntityQuery _fingerprintQuery = default!; + [Dependency] private EntityQuery _forensicsQuery = default!; + [Dependency] private EntityQuery _ignoresFingerprintsQuery = default!; + [Dependency] private EntityQuery _inventoryQuery = default!; + [Dependency] private EntityQuery _residueQuery = default!; + [SubscribeLocalEvent] private void OnSolutionChanged(Entity ent, ref SolutionChangedEvent ev) { @@ -76,7 +87,7 @@ public sealed partial class SharedForensicsSystem : EntitySystem { var dna = Loc.GetString("forensics-dna-unknown"); - if (TryComp(ent, out DnaComponent? dnaComp) && dnaComp.DNA != null) + if (_dnaQuery.TryComp(ent, out var dnaComp) && dnaComp.DNA != null) dna = dnaComp.DNA; foreach (var part in args.Giblets) @@ -98,7 +109,7 @@ public sealed partial class SharedForensicsSystem : EntitySystem foreach (var hitEntity in args.HitEntities) { - if (TryComp(hitEntity, out var hitEntityComp) && hitEntityComp.DNA != null) + if (_dnaQuery.TryComp(hitEntity, out var hitEntityComp) && hitEntityComp.DNA != null) weapon.Comp.DNAs.Add(hitEntityComp.DNA); } Dirty(weapon); @@ -116,10 +127,8 @@ public sealed partial class SharedForensicsSystem : EntitySystem /// public void CopyForensicsFrom(Entity src, EntityUid target) { - if (!Resolve(target, ref src.Comp, false)) - { + if (!Resolve(src, ref src.Comp, false)) return; - } var targetComp = EnsureComp(target); foreach (var dna in src.Comp.DNAs) @@ -162,10 +171,8 @@ public sealed partial class SharedForensicsSystem : EntitySystem { foreach (var data in reagent.Reagent.EnsureReagentData()) { - if (data is DnaData) - { - list.Add(((DnaData) data).DNA); - } + if (data is DnaData dnaData) + list.Add(dnaData.DNA); } } return list; @@ -213,7 +220,7 @@ public sealed partial class SharedForensicsSystem : EntitySystem /// True if the target can be cleaned and has some sort of DNA or fingerprints / fibers and false otherwise. public bool TryStartCleaning(Entity cleanForensicsEntity, EntityUid user, EntityUid target) { - if (!TryComp(target, out var forensicsComp)) + if (!_forensicsQuery.TryComp(target, out var forensicsComp)) { _popupSystem.PopupEntity(Loc.GetString("forensics-cleaning-cannot-clean", ("target", Identity.Entity(target, EntityManager))), user, user, PopupType.MediumCaution); return false; @@ -253,7 +260,7 @@ public sealed partial class SharedForensicsSystem : EntitySystem if (args.Handled || args.Cancelled || args.Args.Target == null) return; - if (!TryComp(args.Target, out var targetComp)) + if (!_forensicsQuery.TryComp(args.Target, out var targetComp)) return; targetComp.Fibers = []; @@ -263,10 +270,10 @@ public sealed partial class SharedForensicsSystem : EntitySystem targetComp.DNAs = []; // leave behind evidence it was cleaned - if (TryComp(args.Used, out var fiber)) + if (_fiberQuery.TryComp(args.Used, out var fiber)) targetComp.Fibers.Add(string.IsNullOrEmpty(fiber.FiberColor) ? Loc.GetString("forensic-fibers", ("material", fiber.FiberMaterial)) : Loc.GetString("forensic-fibers-colored", ("color", fiber.FiberColor), ("material", fiber.FiberMaterial))); - if (TryComp(args.Used, out var residue)) + if (_residueQuery.TryComp(args.Used, out var residue)) targetComp.Residues.Add(string.IsNullOrEmpty(residue.ResidueColor) ? Loc.GetString("forensic-residue", ("adjective", residue.ResidueAdjective)) : Loc.GetString("forensic-residue-colored", ("color", residue.ResidueColor), ("adjective", residue.ResidueAdjective))); Dirty(args.Target.Value, targetComp); @@ -282,29 +289,29 @@ public sealed partial class SharedForensicsSystem : EntitySystem public string GenerateDNA() { var letters = new[] { "A", "C", "G", "T" }; - var DNA = string.Empty; + var dna = string.Empty; for (var i = 0; i < 16; i++) { - DNA += letters[_random.Next(letters.Length)]; + dna += letters[_random.Next(letters.Length)]; } - return DNA; + return dna; } private void ApplyEvidence(EntityUid user, EntityUid target) { - if (HasComp(target)) + if (_ignoresFingerprintsQuery.HasComp(target)) return; var component = EnsureComp(target); if (_inventory.TryGetSlotEntity(user, "gloves", out var gloves)) { - if (TryComp(gloves, out var fiber) && !string.IsNullOrEmpty(fiber.FiberMaterial)) + if (_fiberQuery.TryComp(gloves, out var fiber) && !string.IsNullOrEmpty(fiber.FiberMaterial)) component.Fibers.Add(string.IsNullOrEmpty(fiber.FiberColor) ? Loc.GetString("forensic-fibers", ("material", fiber.FiberMaterial)) : Loc.GetString("forensic-fibers-colored", ("color", fiber.FiberColor), ("material", fiber.FiberMaterial))); } - if (TryComp(user, out var fingerprint) && CanAccessFingerprint(user, out _)) + if (_fingerprintQuery.TryComp(user, out var fingerprint) && CanAccessFingerprint(user, out _)) component.Fingerprints.Add(fingerprint.Fingerprint ?? ""); Dirty(target, component); @@ -341,7 +348,7 @@ public sealed partial class SharedForensicsSystem : EntitySystem /// If this DNA be cleaned off of the recipient. e.g. cleaning a knife vs cleaning a puddle of blood public void TransferDna(EntityUid recipient, EntityUid donor, bool canDnaBeCleaned = true) { - if (!TryComp(donor, out var donorComp) || donorComp.DNA == null) + if (!_dnaQuery.TryComp(donor, out var donorComp) || donorComp.DNA == null) return; EnsureComp(recipient, out var recipientComp); @@ -361,7 +368,7 @@ public sealed partial class SharedForensicsSystem : EntitySystem var ev = new TryAccessFingerprintEvent(); RaiseLocalEvent(target, ev); - if (!ev.Cancelled && TryComp(target, out var inv)) + if (!ev.Cancelled && _inventoryQuery.TryComp(target, out var inv)) _inventory.RelayEvent((target, inv), ev); blocker = ev.Blocker; diff --git a/Content.Shared/Forensics/Systems/SharedForensicScannerSystem.cs b/Content.Shared/Forensics/Systems/SharedForensicScannerSystem.cs index 5be60c0c3d..5869cb0555 100644 --- a/Content.Shared/Forensics/Systems/SharedForensicScannerSystem.cs +++ b/Content.Shared/Forensics/Systems/SharedForensicScannerSystem.cs @@ -28,7 +28,7 @@ public sealed partial class SharedForensicScannerSystem : EntitySystem [Dependency] private SharedHandsSystem _handsSystem = default!; [Dependency] private SharedAudioSystem _audioSystem = default!; [Dependency] private MetaDataSystem _metaData = default!; - [Dependency] private SharedForensicsSystem _forensicsSystem = default!; + [Dependency] private ForensicsSystem _forensicsSystem = default!; [Dependency] private TagSystem _tag = default!; private static readonly ProtoId DNASolutionScannableTag = "DNASolutionScannable"; diff --git a/Content.Shared/Implants/SharedImplanterSystem.cs b/Content.Shared/Implants/SharedImplanterSystem.cs index 3a1a2d616e..0cbb5236be 100644 --- a/Content.Shared/Implants/SharedImplanterSystem.cs +++ b/Content.Shared/Implants/SharedImplanterSystem.cs @@ -34,7 +34,7 @@ public abstract partial class SharedImplanterSystem : EntitySystem [Dependency] private SharedContainerSystem _container = default!; [Dependency] private SharedDoAfterSystem _doAfter = default!; [Dependency] private SharedPopupSystem _popup = default!; - [Dependency] private SharedForensicsSystem _forensics = default!; + [Dependency] private ForensicsSystem _forensics = default!; [Dependency] private SharedUserInterfaceSystem _ui = default!; [Dependency] private EntityQuery _implantCompQuery; diff --git a/Content.Shared/Medical/VomitSystem.cs b/Content.Shared/Medical/VomitSystem.cs index 70bf6d629f..dacdfac646 100644 --- a/Content.Shared/Medical/VomitSystem.cs +++ b/Content.Shared/Medical/VomitSystem.cs @@ -27,7 +27,7 @@ public sealed partial class VomitSystem : EntitySystem [Dependency] private MovementModStatusSystem _movementMod = default!; [Dependency] private SharedAudioSystem _audio = default!; [Dependency] private BloodstreamSystem _bloodstream = default!; - [Dependency] private SharedForensicsSystem _forensics = default!; + [Dependency] private ForensicsSystem _forensics = default!; [Dependency] private SharedPopupSystem _popup = default!; [Dependency] private SharedPuddleSystem _puddle = default!; [Dependency] private SatiationSystem _satiation = default!; diff --git a/Content.Shared/Nutrition/EntitySystems/IngestionSystem.cs b/Content.Shared/Nutrition/EntitySystems/IngestionSystem.cs index b4a10f8011..30425740a9 100644 --- a/Content.Shared/Nutrition/EntitySystems/IngestionSystem.cs +++ b/Content.Shared/Nutrition/EntitySystems/IngestionSystem.cs @@ -56,7 +56,7 @@ public sealed partial class IngestionSystem : EntitySystem [Dependency] private SharedPopupSystem _popup = default!; [Dependency] private SharedSolutionContainerSystem _solutionContainer = default!; [Dependency] private SharedTransformSystem _transform = default!; - [Dependency] private SharedForensicsSystem _forensics = default!; + [Dependency] private ForensicsSystem _forensics = default!; // Body Component Dependencies [Dependency] private BodySystem _body = default!; diff --git a/Content.Shared/Trigger/Systems/DnaScrambleOnTriggerSystem.cs b/Content.Shared/Trigger/Systems/DnaScrambleOnTriggerSystem.cs index 8c149dd143..086a6c8049 100644 --- a/Content.Shared/Trigger/Systems/DnaScrambleOnTriggerSystem.cs +++ b/Content.Shared/Trigger/Systems/DnaScrambleOnTriggerSystem.cs @@ -16,7 +16,7 @@ public sealed partial class DnaScrambleOnTriggerSystem : XOnTriggerSystem