From 15c8aaca6686166fe10559b27fb4bd1775496b6b Mon Sep 17 00:00:00 2001 From: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com> Date: Fri, 14 Jan 2022 03:21:30 +1300 Subject: [PATCH] ECS cable (#6141) --- .../Power/Components/CableComponent.cs | 49 ++++---------- .../Power/EntitySystems/CableSystem.cs | 66 +++++++++++++++++++ 2 files changed, 78 insertions(+), 37 deletions(-) create mode 100644 Content.Server/Power/EntitySystems/CableSystem.cs diff --git a/Content.Server/Power/Components/CableComponent.cs b/Content.Server/Power/Components/CableComponent.cs index 3260c81a1a..4691c04b75 100644 --- a/Content.Server/Power/Components/CableComponent.cs +++ b/Content.Server/Power/Components/CableComponent.cs @@ -1,14 +1,10 @@ -using System.Threading.Tasks; -using Content.Server.Electrocution; -using Content.Server.Stack; -using Content.Server.Tools; -using Content.Shared.Interaction; +using Content.Server.Power.EntitySystems; using Content.Shared.Tools; +using Robust.Shared.Analyzers; using Robust.Shared.GameObjects; -using Robust.Shared.IoC; +using Robust.Shared.Prototypes; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; -using Robust.Shared.ViewVariables; namespace Content.Server.Power.Components { @@ -16,46 +12,25 @@ namespace Content.Server.Power.Components /// Allows the attached entity to be destroyed by a cutting tool, dropping a piece of cable. /// [RegisterComponent] - public class CableComponent : Component, IInteractUsing + [Friend(typeof(CableSystem))] + [ComponentProtoName("Cable")] + public class CableComponent : Component { - [Dependency] private readonly IEntityManager _entMan = default!; - - public override string Name => "Cable"; - - [ViewVariables] - [DataField("cableDroppedOnCutPrototype")] - private string? _cableDroppedOnCutPrototype = "CableHVStack1"; + [DataField("cableDroppedOnCutPrototype", customTypeSerializer: typeof(PrototypeIdSerializer))] + public readonly string CableDroppedOnCutPrototype = "CableHVStack1"; [DataField("cuttingQuality", customTypeSerializer:typeof(PrototypeIdSerializer))] - private string _cuttingQuality = "Cutting"; + public string CuttingQuality = "Cutting"; /// /// Checked by to determine if there is /// already a cable of a type on a tile. /// - [ViewVariables] - public CableType CableType => _cableType; [DataField("cableType")] - private CableType _cableType = CableType.HighVoltage; + public CableType CableType = CableType.HighVoltage; - async Task IInteractUsing.InteractUsing(InteractUsingEventArgs eventArgs) - { - if (_cableDroppedOnCutPrototype == null) - return false; - - if (!await EntitySystem.Get().UseTool(eventArgs.Using, eventArgs.User, Owner, 0f, 0.25f, _cuttingQuality)) return false; - - if (EntitySystem.Get().TryDoElectrifiedAct(Owner, eventArgs.User)) return false; - - _entMan.DeleteEntity(Owner); - var droppedEnt = _entMan.SpawnEntity(_cableDroppedOnCutPrototype, eventArgs.ClickLocation); - - // TODO: Literally just use a prototype that has a single thing in the stack, it's not that complicated... - if (_entMan.TryGetComponent(droppedEnt, out var stack)) - EntitySystem.Get().SetCount(droppedEnt, 1, stack); - - return true; - } + [DataField("cuttingDelay")] + public float CuttingDelay = 0.25f; } public enum CableType diff --git a/Content.Server/Power/EntitySystems/CableSystem.cs b/Content.Server/Power/EntitySystems/CableSystem.cs new file mode 100644 index 0000000000..f397a49c44 --- /dev/null +++ b/Content.Server/Power/EntitySystems/CableSystem.cs @@ -0,0 +1,66 @@ +using Content.Server.Electrocution; +using Content.Server.Power.Components; +using Content.Server.Tools; +using Content.Shared.Interaction; +using Robust.Shared.GameObjects; +using Robust.Shared.IoC; + +namespace Content.Server.Power.EntitySystems; + +public class CableSystem : EntitySystem +{ + [Dependency] private readonly ToolSystem _toolSystem = default!; + [Dependency] private readonly ElectrocutionSystem _electrocutionSystem = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnInteractUsing); + SubscribeLocalEvent(OnCableCut); + SubscribeLocalEvent(OnAnchorChanged); + } + + private void OnInteractUsing(EntityUid uid, CableComponent cable, InteractUsingEvent args) + { + if (args.Handled) + return; + + var ev = new CuttingFinishedEvent(uid, args.User); + _toolSystem.UseTool(args.Used, args.User, uid, 0, cable.CuttingDelay, new[] { cable.CuttingQuality }, doAfterCompleteEvent: ev); + args.Handled = true; + } + + private void OnCableCut(EntityUid uid, CableComponent cable, CuttingFinishedEvent args) + { + if (_electrocutionSystem.TryDoElectrifiedAct(uid, args.User)) + return; + + Spawn(cable.CableDroppedOnCutPrototype, Transform(uid).Coordinates); + Del(uid); + } + + private void OnAnchorChanged(EntityUid uid, CableComponent cable, ref AnchorStateChangedEvent args) + { + if (args.Anchored) + return; // huh? it wasn't anchored? + + // This entity should not be un-anchorable. But this can happen if the grid-tile is deleted (RCD, explosion, + // etc). In that case: behave as if the cable had been cut. + Spawn(cable.CableDroppedOnCutPrototype, Transform(uid).Coordinates); + Del(uid); + } +} + +// TODO: if #5887 gets merged, just use a directed event instead of broadcast-with-target +public class CuttingFinishedEvent : EntityEventArgs +{ + public EntityUid Target; + public EntityUid User; + + public CuttingFinishedEvent(EntityUid target, EntityUid user) + { + Target = target; + User = user; + } +}