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