CatStation/Content.Server/Cloning/CloningSystem.Subscriptions.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

166 lines
7.5 KiB
C#

using Content.Shared.Body.Components;
using Content.Shared.Body.Systems;
using Content.Server.Speech.EntitySystems;
using Content.Shared.Cloning.Events;
using Content.Shared.Clothing.Components;
using Content.Shared.Clothing.EntitySystems;
using Content.Shared.FixedPoint;
using Content.Shared.Forensics.Components;
using Content.Shared.Forensics.Systems;
using Content.Shared.Inventory;
using Content.Shared.Labels.Components;
using Content.Shared.Labels.EntitySystems;
using Content.Shared.Movement.Components;
using Content.Shared.Movement.Pulling.Components;
using Content.Shared.Movement.Pulling.Systems;
using Content.Shared.Movement.Systems;
using Content.Shared.Paper;
using Content.Shared.Speech.Components;
using Content.Shared.Speech.EntitySystems;
using Content.Shared.Stacks;
using Content.Shared.Storage;
using Content.Shared.Store;
using Content.Shared.Store.Components;
using Robust.Shared.Prototypes;
namespace Content.Server.Cloning;
/// <summary>
/// The part of item cloning responsible for copying over important components.
/// </summary>
/// <remarks>
/// These are all not part of their corresponding systems because we don't want systems every system to depend on a CloningSystem namespace import, which is still heavily coupled to med code.
/// TODO: Create a more generic "CopyEntity" method/event (probably in RT) that doesn't have this problem and then move all these subscriptions.
/// </remarks>
public sealed partial class CloningSystem
{
[Dependency] private SharedStackSystem _stack = default!;
[Dependency] private LabelSystem _label = default!;
[Dependency] private PaperSystem _paper = default!;
[Dependency] private VocalSystem _vocal = default!;
[Dependency] private MovementSpeedModifierSystem _movementSpeedModifier = default!;
[Dependency] private SharedChameleonClothingSystem _chameleonClothing = default!;
[Dependency] private PullingSystem _pulling = default!;
[Dependency] private BloodstreamSystem _bloodstream = default!;
[Dependency] private SharedForensicsSystem _forensics = default!;
public override void Initialize()
{
base.Initialize();
// These are used for <see cref="CopyItem"/>.
// Anything not copied over here gets reverted to the values the item had in its prototype.
// This method of copying items is of course not perfect as we cannot clone every single component, which would be pretty much impossible with our ECS.
// We only consider the most important components so the paradox clone gets similar equipment.
// This method of using subscriptions was chosen to make it easy for forks to add their own custom components that need to be copied.
SubscribeLocalEvent<StackComponent, CloningItemEvent>(OnCloneItemStack);
SubscribeLocalEvent<LabelComponent, CloningItemEvent>(OnCloneItemLabel);
SubscribeLocalEvent<PaperComponent, CloningItemEvent>(OnCloneItemPaper);
SubscribeLocalEvent<ForensicsComponent, CloningItemEvent>(OnCloneItemForensics);
SubscribeLocalEvent<StoreComponent, CloningItemEvent>(OnCloneItemStore);
SubscribeLocalEvent<ChameleonClothingComponent, CloningItemEvent>(OnCloneItemChameleon);
// These are for cloning components that cannot be cloned using CopyComp.
// Put them into CloningSettingsPrototype.EventComponents to have them be applied to the clone.
SubscribeLocalEvent<VocalComponent, CloningEvent>(OnCloneVocal);
SubscribeLocalEvent<StorageComponent, CloningEvent>(OnCloneStorage);
SubscribeLocalEvent<InventoryComponent, CloningEvent>(OnCloneInventory);
SubscribeLocalEvent<MovementSpeedModifierComponent, CloningEvent>(OnCloneMovementSpeedModifier);
SubscribeLocalEvent<PullerComponent, CloningEvent>(OnClonePuller);
SubscribeLocalEvent<BloodstreamComponent, CloningEvent>(OnCloneBloodstream);
}
private void OnCloneItemStack(Entity<StackComponent> ent, ref CloningItemEvent args)
{
// if the clone is a stack as well, adjust the count of the copy
if (TryComp<StackComponent>(args.CloneUid, out var cloneStackComp))
_stack.SetCount((args.CloneUid, cloneStackComp), ent.Comp.Count);
}
private void OnCloneItemLabel(Entity<LabelComponent> ent, ref CloningItemEvent args)
{
// copy the label
_label.Label(args.CloneUid, ent.Comp.CurrentLabel);
}
private void OnCloneItemPaper(Entity<PaperComponent> ent, ref CloningItemEvent args)
{
// copy the text and any stamps
if (TryComp<PaperComponent>(args.CloneUid, out var clonePaperComp))
{
_paper.SetContent((args.CloneUid, clonePaperComp), ent.Comp.Content);
_paper.CopyStamps(ent.AsNullable(), (args.CloneUid, clonePaperComp));
}
}
private void OnCloneItemForensics(Entity<ForensicsComponent> ent, ref CloningItemEvent args)
{
// copy any forensics to the cloned item
_forensics.CopyForensicsFrom(ent.AsNullable(), args.CloneUid);
}
private void OnCloneItemStore(Entity<StoreComponent> ent, ref CloningItemEvent args)
{
// copy the current amount of currency in the store
// at the moment this takes care of uplink implants and the portable nukie uplinks
// turning a copied pda into an uplink will need some refactoring first
if (TryComp<StoreComponent>(args.CloneUid, out var cloneStoreComp))
{
cloneStoreComp.Balance = new Dictionary<ProtoId<CurrencyPrototype>, FixedPoint2>(ent.Comp.Balance);
}
}
private void OnCloneItemChameleon(Entity<ChameleonClothingComponent> ent, ref CloningItemEvent args)
{
// copy the prototype the original is mimicing
_chameleonClothing.SetSelectedPrototype(args.CloneUid, ent.Comp.Default);
}
private void OnCloneVocal(Entity<VocalComponent> ent, ref CloningEvent args)
{
if (!args.Settings.EventComponents.Contains(Factory.GetRegistration(ent.Comp.GetType()).Name))
return;
_vocal.CopyComponent(ent.AsNullable(), args.CloneUid);
}
private void OnCloneStorage(Entity<StorageComponent> ent, ref CloningEvent args)
{
if (!args.Settings.EventComponents.Contains(Factory.GetRegistration(ent.Comp.GetType()).Name))
return;
_storage.CopyComponent(ent.AsNullable(), args.CloneUid);
}
private void OnCloneInventory(Entity<InventoryComponent> ent, ref CloningEvent args)
{
if (!args.Settings.EventComponents.Contains(Factory.GetRegistration(ent.Comp.GetType()).Name))
return;
_inventory.CopyComponent(ent.AsNullable(), args.CloneUid);
}
private void OnCloneMovementSpeedModifier(Entity<MovementSpeedModifierComponent> ent, ref CloningEvent args)
{
if (!args.Settings.EventComponents.Contains(Factory.GetRegistration(ent.Comp.GetType()).Name))
return;
_movementSpeedModifier.CopyComponent(ent.AsNullable(), args.CloneUid);
}
private void OnClonePuller(Entity<PullerComponent> ent, ref CloningEvent args)
{
if (!args.Settings.EventComponents.Contains(Factory.GetRegistration(ent.Comp.GetType()).Name))
return;
_pulling.CopyPullerComponent(ent.AsNullable(), args.CloneUid);
}
private void OnCloneBloodstream(Entity<BloodstreamComponent> ent, ref CloningEvent args)
{
if (!args.Settings.EventComponents.Contains(Factory.GetRegistration(ent.Comp.GetType()).Name))
return;
_bloodstream.CopyComponent(ent.AsNullable(), args.CloneUid);
}
}