using Content.Server.Forensics; using Content.Server.Speech.EntitySystems; using Content.Shared.Cloning.Events; using Content.Shared.FixedPoint; using Content.Shared.Inventory; using Content.Shared.Labels.Components; using Content.Shared.Labels.EntitySystems; using Content.Shared.Movement.Components; using Content.Shared.Movement.Systems; using Content.Shared.Paper; using Content.Shared.Stacks; using Content.Shared.Speech.Components; using Content.Shared.Storage; using Content.Shared.Store; using Content.Shared.Store.Components; using Robust.Shared.Prototypes; namespace Content.Server.Cloning; /// /// The part of item cloning responsible for copying over important components. /// /// /// 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. /// public sealed partial class CloningSystem { [Dependency] private readonly SharedStackSystem _stack = default!; [Dependency] private readonly LabelSystem _label = default!; [Dependency] private readonly ForensicsSystem _forensics = default!; [Dependency] private readonly PaperSystem _paper = default!; [Dependency] private readonly VocalSystem _vocal = default!; [Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifier = default!; public override void Initialize() { base.Initialize(); // These are used for . // 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(OnCloneItemStack); SubscribeLocalEvent(OnCloneItemLabel); SubscribeLocalEvent(OnCloneItemPaper); SubscribeLocalEvent(OnCloneItemForensics); SubscribeLocalEvent(OnCloneItemStore); // 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(OnCloneVocal); SubscribeLocalEvent(OnCloneStorage); SubscribeLocalEvent(OnCloneInventory); SubscribeLocalEvent(OnCloneInventory); } private void OnCloneItemStack(Entity ent, ref CloningItemEvent args) { // if the clone is a stack as well, adjust the count of the copy if (TryComp(args.CloneUid, out var cloneStackComp)) _stack.SetCount((args.CloneUid, cloneStackComp), ent.Comp.Count); } private void OnCloneItemLabel(Entity ent, ref CloningItemEvent args) { // copy the label _label.Label(args.CloneUid, ent.Comp.CurrentLabel); } private void OnCloneItemPaper(Entity ent, ref CloningItemEvent args) { // copy the text and any stamps if (TryComp(args.CloneUid, out var clonePaperComp)) { _paper.SetContent((args.CloneUid, clonePaperComp), ent.Comp.Content); _paper.CopyStamps(ent.AsNullable(), (args.CloneUid, clonePaperComp)); } } private void OnCloneItemForensics(Entity ent, ref CloningItemEvent args) { // copy any forensics to the cloned item _forensics.CopyForensicsFrom(ent.Comp, args.CloneUid); } private void OnCloneItemStore(Entity 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(args.CloneUid, out var cloneStoreComp)) { cloneStoreComp.Balance = new Dictionary, FixedPoint2>(ent.Comp.Balance); } } private void OnCloneVocal(Entity 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 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 ent, ref CloningEvent args) { if (!args.Settings.EventComponents.Contains(Factory.GetRegistration(ent.Comp.GetType()).Name)) return; _inventory.CopyComponent(ent.AsNullable(), args.CloneUid); } private void OnCloneInventory(Entity ent, ref CloningEvent args) { if (!args.Settings.EventComponents.Contains(Factory.GetRegistration(ent.Comp.GetType()).Name)) return; _movementSpeedModifier.CopyComponent(ent.AsNullable(), args.CloneUid); } }