CatStation/Content.Shared/Forensics/Systems/ForensicPadSystem.cs
Prole 502af6955d
Predict Forensics V2.0 (Ready for Review) (#40693)
* What sitting on code does to a branch + no mo owner v2

* Replacing ViewVariables with AutoNetworkedField + Missed One V2

* Removing Virtual Methods & Renaming ForensicsSystem to SharedForensicsSystem (Also made it abstract) V2

* IProduceWidgets Review Changes & some of my own V2

* Lil Cleanup V2

* Part 1 of Review Changes (Only thing left is the BUI stuff and the constructor) V2

* It now WORKS!!! (Still needs the BUI and constuctor changes, ill figure it out later)

* Test (Removal of ServerSide VomitSystem.cs)

* Ok...

* Moved System BloodstreamSystem.cs to SharedBloodstreamSystem.cs & deleted client BloodStreamSystem.cs to make SharedBloodstreamSystem.cs sealed. (No Unregistered errors)

* Prediction

* Fix?

* No mo log error?

* Revert "No mo log error?"

This reverts commit 50c15a3deab6af9dffd7baed45820bae5558e41f.

* Constructor going up

* No ForensicScannerBoundUserInterface.cs (It doesnt wanna scan anymore but it doesnt crash)

* For Conflicts

* Guh

* Yea

* Organization & no ErrorHell (maybe)

* Dirtying

* Dirtying take 2

* Revert "Dirtying take 2"

This reverts commit 5735012e21f43808db3ae010fce268eac24d0583.

* the dirties dont do much here

* For Conflict

* Readded

* Another Conflict Commit Fix

* Conflict Fix Thrice

* Empty Space

* Keep it simple

* Add it back in

* Move BloodstreamSystem stuff thats causing the error back to system. This'll prob fix the conflict

* Conflict fix?

* Trust the fix

* Looked at other prediction PR's, they had better code.

* To not mix up the system in client

* Removing Conflict

* For conflict

* For the conflic fix, will be removed later

* Scuffed Fix

* Removal & Adding the Decouple

* Took some HEAVY pointers from SirWarocks work. The Roadblock has been CLEARED, DOAFTERS WORK NOW!!

* Cleanup & Optimizing, mostly comps.

* More Optimization, most of this is just imported Warock Code, his QOL included. Did not want to remove SolutionDNA's tho, mostly due to a Log.Debug in OnPrint.

* Forgot that the Print Refreshes, more of Warocks work.

* Removing Loc.GetString

* All of BloodStream to Shared, hopefully no errors.

* Sketchy Dirty Removed

* Removed Timer.Spawn, added FrameUpdate cause anything else only updated when the window opened, & a bit of cleanup.

* No mo Mispredict

* GenerateDnaEvent Predicted

* Forgot the user

* I knew it was real, bloodstutter is REAL and now GONE.

* Cant dirty NewEntityBloodData due to potential stutter, so its safer to put it all back into server. again...

* Clearer

* Thank you leahcat, no more identity leak.

* Routine Maintenance

* sealing the class

* it checks for this now?!

* While im here, FileScope Namespaces & removing unused namespaces

* Update Attribute Type (SirWarock Import), it works and is much easier to read.

* Forever Fixing Conflicts

* Readonly Genocide & Partial Maxing

* LGTM, BloodstreamSystem moved to SharedBloodstreamSystem!

* Sohn

* If OG Github back push this commit

* One Billionth Commit Fix

* Removed client/server stuff

* Made implicit

* NewLine & comment on why AutoGenCompState is true

* Updatin the rest of the Popups to use Entity

* I think that's what they meant? It looks cleaner at least.

* Mass Attribute for LocalEvents that are safe to change.

* Putting it back as abstract

* maybe?

* Guhh, rolling back empty client/server of BloodStream

* Removed Client/Server BloodstreamSystems, changed access modifier from protected to private, & renamed SharedBloodstreamSystem to BloodstreamSystem

* From Protected to Private

* Removed comment & made it explicit on what changed to true

* Guh, hopefully thats all of it...

* Forgot

* Review

* Test Push

* Line 316 in SharedForensicsSystem was causing the errors, better to play it safe

* Review Changes

* Update Content.Shared/Forensics/Events.cs

Co-authored-by: Whatstone <166147148+whatston3@users.noreply.github.com>

* The only thing SolutionDNAs does is search and clears itself. I see no reason to keep it

* The print.disabled didnt properly disable when cleared. So ill just use the old if check

* Figured out the rest of the SubscribeLocalEvents and networking BloodData cause its fully in Shared

---------

Co-authored-by: Whatstone <166147148+whatston3@users.noreply.github.com>
2026-08-08 22:48:36 +00:00

118 lines
4.2 KiB
C#

using Content.Shared.DoAfter;
using Content.Shared.Examine;
using Content.Shared.Forensics.Components;
using Content.Shared.IdentityManagement;
using Content.Shared.Interaction;
using Content.Shared.Labels.EntitySystems;
using Content.Shared.Popups;
namespace Content.Shared.Forensics.Systems;
/// <summary>
/// Used to transfer fingerprints from entities to forensic pads.
/// </summary>
public sealed partial class ForensicPadSystem : EntitySystem
{
[Dependency] private SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private SharedPopupSystem _popupSystem = default!;
[Dependency] private SharedForensicsSystem _forensics = default!;
[Dependency] private LabelSystem _label = default!;
[SubscribeLocalEvent]
private void OnExamined(Entity<ForensicPadComponent> pad, ref ExaminedEvent args)
{
if (!args.IsInDetailsRange)
return;
if (!pad.Comp.Used)
{
args.PushMarkup(Loc.GetString("forensic-pad-unused"));
return;
}
args.PushMarkup(Loc.GetString("forensic-pad-sample", ("sample", pad.Comp.Sample)));
}
[SubscribeLocalEvent]
private void OnAfterInteract(Entity<ForensicPadComponent> pad, ref AfterInteractEvent args)
{
if (!args.CanReach || args.Target == null || HasComp<ForensicScannerComponent>(args.Target))
return;
args.Handled = true;
if (pad.Comp.Used)
{
_popupSystem.PopupEntity(Loc.GetString("forensic-pad-already-used"), args.Target.Value, args.User);
return;
}
if (!_forensics.CanAccessFingerprint(args.Target.Value, out var blocker))
{
var message = blocker is { } item
? Loc.GetString("forensic-pad-no-access-due", ("entity", Identity.Entity(item, EntityManager)))
: Loc.GetString("forensic-pad-no-access");
_popupSystem.PopupEntity(message, args.Target.Value, args.User);
return;
}
if (TryComp<FingerprintComponent>(args.Target, out var fingerprint) && fingerprint.Fingerprint != null)
{
var skipDelay = true;
if (args.User != args.Target)
{
var userMessage = Loc.GetString("forensic-pad-start-scan-user", ("target", Identity.Entity(args.Target.Value, EntityManager)));
var targetMessage = Loc.GetString("forensic-pad-start-scan-target", ("user", Identity.Entity(args.User, EntityManager)));
skipDelay = false;
_popupSystem.PopupEntity(userMessage, args.Target.Value, args.User);
_popupSystem.PopupEntity(targetMessage, args.Target.Value, args.Target.Value);
}
StartScan(pad, args.User, args.Target.Value, pad.Comp, fingerprint.Fingerprint, skipDelay);
return;
}
if (TryComp<FiberComponent>(args.Target, out var fiber))
{
var fiberString = string.IsNullOrEmpty(fiber.FiberColor)
? Loc.GetString("forensic-fibers", ("material", fiber.FiberMaterial))
: Loc.GetString("forensic-fibers-colored", ("color", fiber.FiberColor), ("material", fiber.FiberMaterial));
StartScan(pad, args.User, args.Target.Value, pad.Comp, fiberString, true);
}
}
private void StartScan(EntityUid used, EntityUid user, EntityUid target, ForensicPadComponent pad, string sample, bool skipDelay = false)
{
var ev = new ForensicPadDoAfterEvent(sample);
var delay = skipDelay ? TimeSpan.Zero : pad.ScanDelay;
var doAfterEventArgs = new DoAfterArgs(EntityManager, user, delay, ev, used, target: target, used: used)
{
NeedHand = true,
BreakOnMove = true,
};
_doAfterSystem.TryStartDoAfter(doAfterEventArgs);
}
[SubscribeLocalEvent]
private void OnDoAfter(Entity<ForensicPadComponent> pad, ref ForensicPadDoAfterEvent args)
{
if (args.Handled || args.Cancelled)
return;
if (args.Args.Target != null)
{
var label = Identity.Name(args.Args.Target.Value, EntityManager);
_label.Label(pad, label);
}
pad.Comp.Sample = args.Sample;
pad.Comp.Used = true;
args.Handled = true;
Dirty(pad);
}
}