From 15a772fb96a3ea5c4aaafe2e50fd22415cbf517a Mon Sep 17 00:00:00 2001 From: Mervill Date: Sun, 16 Oct 2022 03:21:54 -0700 Subject: [PATCH] Cleanup for ChargerComponent (#11907) --- .../Components/ActiveChargerComponent.cs | 10 ++ .../Power/Components/ChargerComponent.cs | 99 +----------- .../Power/EntitySystems/ChargerSystem.cs | 153 ++++++++++++++---- Content.Server/PowerCell/PowerCellSystem.cs | 6 +- .../Containers/ItemSlot/ItemSlotsSystem.cs | 2 +- .../Entities/Structures/Power/chargers.yml | 39 +++-- 6 files changed, 160 insertions(+), 149 deletions(-) create mode 100644 Content.Server/Power/Components/ActiveChargerComponent.cs diff --git a/Content.Server/Power/Components/ActiveChargerComponent.cs b/Content.Server/Power/Components/ActiveChargerComponent.cs new file mode 100644 index 0000000000..57f2f1a79c --- /dev/null +++ b/Content.Server/Power/Components/ActiveChargerComponent.cs @@ -0,0 +1,10 @@ +using Content.Shared.Containers.ItemSlots; +using Content.Shared.Power; + +namespace Content.Server.Power.Components +{ + [RegisterComponent] + public sealed class ActiveChargerComponent : Component + { + } +} diff --git a/Content.Server/Power/Components/ChargerComponent.cs b/Content.Server/Power/Components/ChargerComponent.cs index f9e7dbddb3..e2c7f0eae1 100644 --- a/Content.Server/Power/Components/ChargerComponent.cs +++ b/Content.Server/Power/Components/ChargerComponent.cs @@ -6,104 +6,15 @@ namespace Content.Server.Power.Components [RegisterComponent] public sealed class ChargerComponent : Component { - [Dependency] private readonly IEntityManager _entMan = default!; + [ViewVariables] + public CellChargerStatus Status; [ViewVariables] - public BatteryComponent? HeldBattery; - - [ViewVariables] - private CellChargerStatus _status; - [DataField("chargeRate")] public int ChargeRate = 20; - [DataField("chargerSlot", required: true)] - public ItemSlot ChargerSlot = new(); - - private CellChargerStatus GetStatus() - { - if (!_entMan.TryGetComponent(Owner, out var xform) || - !xform.Anchored || - _entMan.TryGetComponent(Owner, out ApcPowerReceiverComponent? receiver) && !receiver.Powered) - { - return CellChargerStatus.Off; - } - - if (!ChargerSlot.HasItem) - return CellChargerStatus.Empty; - - if (HeldBattery != null && Math.Abs(HeldBattery.MaxCharge - HeldBattery.CurrentCharge) < 0.01) - return CellChargerStatus.Charged; - - return CellChargerStatus.Charging; - } - - public void UpdateStatus() - { - // Not called UpdateAppearance just because it messes with the load - var status = GetStatus(); - if (_status == status || - !_entMan.TryGetComponent(Owner, out ApcPowerReceiverComponent? receiver)) - { - return; - } - - _status = status; - _entMan.TryGetComponent(Owner, out AppearanceComponent? appearance); - - switch (_status) - { - // Update load just in case - case CellChargerStatus.Off: - receiver.Load = 0; - appearance?.SetData(CellVisual.Light, CellChargerStatus.Off); - break; - case CellChargerStatus.Empty: - receiver.Load = 0; - appearance?.SetData(CellVisual.Light, CellChargerStatus.Empty); - break; - case CellChargerStatus.Charging: - receiver.Load = ChargeRate; - appearance?.SetData(CellVisual.Light, CellChargerStatus.Charging); - break; - case CellChargerStatus.Charged: - receiver.Load = 0; - appearance?.SetData(CellVisual.Light, CellChargerStatus.Charged); - break; - default: - throw new ArgumentOutOfRangeException(); - } - - appearance?.SetData(CellVisual.Occupied, ChargerSlot.HasItem); - } - - public void OnUpdate(float frameTime) //todo: make single system for this - { - if (_status == CellChargerStatus.Empty || _status == CellChargerStatus.Charged || !ChargerSlot.HasItem) - return; - - TransferPower(frameTime); - } - - private void TransferPower(float frameTime) - { - if (_entMan.TryGetComponent(Owner, out ApcPowerReceiverComponent? receiver) && - !receiver.Powered) - { - return; - } - - if (HeldBattery == null) - return; - - HeldBattery.CurrentCharge += ChargeRate * frameTime; - // Just so the sprite won't be set to 99.99999% visibility - if (HeldBattery.MaxCharge - HeldBattery.CurrentCharge < 0.01) - { - HeldBattery.CurrentCharge = HeldBattery.MaxCharge; - } - - UpdateStatus(); - } + [ViewVariables] + [DataField("slotId", required: true)] + public string SlotId = string.Empty; } } diff --git a/Content.Server/Power/EntitySystems/ChargerSystem.cs b/Content.Server/Power/EntitySystems/ChargerSystem.cs index 7b6bcbcb06..a7a6881aac 100644 --- a/Content.Server/Power/EntitySystems/ChargerSystem.cs +++ b/Content.Server/Power/EntitySystems/ChargerSystem.cs @@ -5,6 +5,7 @@ using Content.Shared.Examine; using Content.Shared.PowerCell.Components; using JetBrains.Annotations; using Robust.Shared.Containers; +using Content.Shared.Power; namespace Content.Server.Power.EntitySystems; @@ -13,11 +14,11 @@ internal sealed class ChargerSystem : EntitySystem { [Dependency] private readonly ItemSlotsSystem _itemSlotsSystem = default!; [Dependency] private readonly PowerCellSystem _cellSystem = default!; + [Dependency] private readonly SharedAppearanceSystem _sharedAppearanceSystem = default!; public override void Initialize() { - SubscribeLocalEvent(OnChargerInit); - SubscribeLocalEvent(OnChargerRemove); + SubscribeLocalEvent(OnStartup); SubscribeLocalEvent(OnPowerChanged); SubscribeLocalEvent(OnInserted); SubscribeLocalEvent(OnRemoved); @@ -25,6 +26,11 @@ internal sealed class ChargerSystem : EntitySystem SubscribeLocalEvent(OnChargerExamine); } + private void OnStartup(EntityUid uid, ChargerComponent component, ComponentStartup args) + { + UpdateStatus(uid, component); + } + private void OnChargerExamine(EntityUid uid, ChargerComponent component, ExaminedEvent args) { args.PushMarkup(Loc.GetString("charger-examine", ("color", "yellow"), ("chargeRate", component.ChargeRate))); @@ -32,24 +38,21 @@ internal sealed class ChargerSystem : EntitySystem public override void Update(float frameTime) { - foreach (var comp in EntityManager.EntityQuery()) + foreach (var (_, charger, slotComp) in EntityManager.EntityQuery()) { - comp.OnUpdate(frameTime); + if (!_itemSlotsSystem.TryGetSlot(charger.Owner, charger.SlotId, out ItemSlot? slot, slotComp)) + continue; + + if (charger.Status == CellChargerStatus.Empty || charger.Status == CellChargerStatus.Charged || !slot.HasItem) + continue; + + TransferPower(charger.Owner, charger, frameTime); } } - private void OnChargerInit(EntityUid uid, ChargerComponent component, ComponentInit args) - { - _itemSlotsSystem.AddItemSlot(uid, "charger-slot", component.ChargerSlot); - } - - private void OnChargerRemove(EntityUid uid, ChargerComponent component, ComponentRemove args) - { - _itemSlotsSystem.RemoveItemSlot(uid, component.ChargerSlot); - } - + private void OnPowerChanged(EntityUid uid, ChargerComponent component, ref PowerChangedEvent args) { - component.UpdateStatus(); + UpdateStatus(uid, component); } private void OnInserted(EntityUid uid, ChargerComponent component, EntInsertedIntoContainerMessage args) @@ -57,25 +60,18 @@ internal sealed class ChargerSystem : EntitySystem if (!component.Initialized) return; - if (args.Container.ID != component.ChargerSlot.ID) + if (args.Container.ID != component.SlotId) return; - - // try get a battery directly on the inserted entity - if (!TryComp(args.Entity, out component.HeldBattery)) - { - // or by checking for a power cell slot on the inserted entity - _cellSystem.TryGetBatteryFromSlot(args.Entity, out component.HeldBattery); - } - - component.UpdateStatus(); + + UpdateStatus(uid, component); } private void OnRemoved(EntityUid uid, ChargerComponent component, EntRemovedFromContainerMessage args) { - if (args.Container.ID != component.ChargerSlot.ID) + if (args.Container.ID != component.SlotId) return; - component.UpdateStatus(); + UpdateStatus(uid, component); } /// @@ -86,16 +82,113 @@ internal sealed class ChargerSystem : EntitySystem if (!component.Initialized) return; - if (args.Container.ID != component.ChargerSlot.ID) + if (args.Container.ID != component.SlotId) return; if (!TryComp(args.EntityUid, out PowerCellSlotComponent? cellSlot)) return; - - if (!_itemSlotsSystem.TryGetSlotById(args.EntityUid, cellSlot.CellSlotId, out ItemSlot? itemSlot)) + + if (!_itemSlotsSystem.TryGetSlot(args.EntityUid, cellSlot.CellSlotId, out ItemSlot? itemSlot)) return; if (!cellSlot.FitsInCharger || !itemSlot.HasItem) args.Cancel(); } + + private void UpdateStatus(EntityUid uid, ChargerComponent component) + { + var status = GetStatus(uid, component); + if (component.Status == status || !TryComp(uid, out ApcPowerReceiverComponent? receiver)) + return; + + if (!_itemSlotsSystem.TryGetSlot(uid, component.SlotId, out ItemSlot? slot)) + return; + + TryComp(uid, out AppearanceComponent? appearance); + + component.Status = status; + + if (component.Status == CellChargerStatus.Charging) + { + AddComp(uid); + } + else + { + RemComp(uid); + } + + switch (component.Status) + { + case CellChargerStatus.Off: + receiver.Load = 0; + _sharedAppearanceSystem.SetData(uid, CellVisual.Light, CellChargerStatus.Off, appearance); + break; + case CellChargerStatus.Empty: + receiver.Load = 0; + _sharedAppearanceSystem.SetData(uid, CellVisual.Light, CellChargerStatus.Empty, appearance); + break; + case CellChargerStatus.Charging: + receiver.Load = component.ChargeRate; + _sharedAppearanceSystem.SetData(uid, CellVisual.Light, CellChargerStatus.Charging, appearance); + break; + case CellChargerStatus.Charged: + receiver.Load = 0; + _sharedAppearanceSystem.SetData(uid, CellVisual.Light, CellChargerStatus.Charged, appearance); + break; + default: + throw new ArgumentOutOfRangeException(); + } + + _sharedAppearanceSystem.SetData(uid, CellVisual.Occupied, slot.HasItem, appearance); + } + + private CellChargerStatus GetStatus(EntityUid uid, ChargerComponent component) + { + if (!TryComp(uid, out TransformComponent? transformComponent)) + return CellChargerStatus.Off; + + if (!transformComponent.Anchored) + return CellChargerStatus.Off; + + if (!TryComp(uid, out ApcPowerReceiverComponent? apcPowerReceiverComponent)) + return CellChargerStatus.Off; + + if (!apcPowerReceiverComponent.Powered) + return CellChargerStatus.Off; + + if (!_itemSlotsSystem.TryGetSlot(uid, component.SlotId, out ItemSlot? slot)) + return CellChargerStatus.Off; + + if (!_cellSystem.TryGetBatteryFromSlot(uid, out BatteryComponent? heldBattery)) + return CellChargerStatus.Off; + + if (!slot.HasItem) + return CellChargerStatus.Empty; + + if (heldBattery != null && Math.Abs(heldBattery.MaxCharge - heldBattery.CurrentCharge) < 0.01) + return CellChargerStatus.Charged; + + return CellChargerStatus.Charging; + } + + private void TransferPower(EntityUid uid, ChargerComponent component, float frameTime) + { + if (!TryComp(uid, out ApcPowerReceiverComponent? receiverComponent)) + return; + + if (!receiverComponent.Powered) + return; + + if (!_cellSystem.TryGetBatteryFromSlot(uid, out BatteryComponent? heldBattery)) + return; + + heldBattery.CurrentCharge += component.ChargeRate * frameTime; + // Just so the sprite won't be set to 99.99999% visibility + if (heldBattery.MaxCharge - heldBattery.CurrentCharge < 0.01) + { + heldBattery.CurrentCharge = heldBattery.MaxCharge; + } + + UpdateStatus(uid, component); + } } diff --git a/Content.Server/PowerCell/PowerCellSystem.cs b/Content.Server/PowerCell/PowerCellSystem.cs index 7d7d13fffa..e291869cf7 100644 --- a/Content.Server/PowerCell/PowerCellSystem.cs +++ b/Content.Server/PowerCell/PowerCellSystem.cs @@ -39,7 +39,7 @@ public sealed class PowerCellSystem : SharedPowerCellSystem private void OnSlotMicrowaved(EntityUid uid, PowerCellSlotComponent component, BeingMicrowavedEvent args) { - if (_itemSlotsSystem.TryGetSlotById(uid, component.CellSlotId, out ItemSlot? slot)) + if (_itemSlotsSystem.TryGetSlot(uid, component.CellSlotId, out ItemSlot? slot)) { if (slot.Item == null) return; @@ -80,7 +80,7 @@ public sealed class PowerCellSystem : SharedPowerCellSystem // If this power cell is inside a cell-slot, inform that entity that the power has changed (for updating visuals n such). if (_containerSystem.TryGetContainingContainer(uid, out var container) && TryComp(container.Owner, out PowerCellSlotComponent? slot) - && _itemSlotsSystem.TryGetSlotById(container.Owner, slot.CellSlotId, out ItemSlot? itemSlot)) + && _itemSlotsSystem.TryGetSlot(container.Owner, slot.CellSlotId, out ItemSlot? itemSlot)) { if (itemSlot.Item == uid) RaiseLocalEvent(container.Owner, new PowerCellChangedEvent(false), false); @@ -108,7 +108,7 @@ public sealed class PowerCellSystem : SharedPowerCellSystem return false; } - if (_itemSlotsSystem.TryGetSlotById(uid, component.CellSlotId, out ItemSlot? slot)) + if (_itemSlotsSystem.TryGetSlot(uid, component.CellSlotId, out ItemSlot? slot)) { return TryComp(slot.Item, out battery); } diff --git a/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs b/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs index 2157e1edfd..0b1d1dcf76 100644 --- a/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs +++ b/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs @@ -126,7 +126,7 @@ namespace Content.Shared.Containers.ItemSlots Dirty(itemSlots); } - public bool TryGetSlotById(EntityUid uid, string slotId, [NotNullWhen(true)] out ItemSlot? itemSlot, ItemSlotsComponent? component = null) + public bool TryGetSlot(EntityUid uid, string slotId, [NotNullWhen(true)] out ItemSlot? itemSlot, ItemSlotsComponent? component = null) { itemSlot = null; diff --git a/Resources/Prototypes/Entities/Structures/Power/chargers.yml b/Resources/Prototypes/Entities/Structures/Power/chargers.yml index 44a9370b1d..0e40fba97a 100644 --- a/Resources/Prototypes/Entities/Structures/Power/chargers.yml +++ b/Resources/Prototypes/Entities/Structures/Power/chargers.yml @@ -12,12 +12,7 @@ drawdepth: SmallObjects snapCardinals: true - type: Charger - chargerSlot: - ejectOnInteract: true - name: Power cell # used for verbs: "Eject > Power cell " - whitelist: - components: - - PowerCell + slotId: charger_slot - type: ApcPowerReceiver - type: ExtensionCableReceiver - type: Appearance @@ -40,9 +35,16 @@ layer: - HighImpassable - type: ItemSlots + slots: + charger_slot: + ejectOnInteract: true + name: Power cell + whitelist: + components: + - PowerCell - type: ContainerContainer containers: - charger-slot: !type:ContainerSlot + charger_slot: !type:ContainerSlot - type: entity name: recharger @@ -52,13 +54,15 @@ - type: Sprite sprite: Structures/Power/recharger.rsi - type: Charger - chargerSlot: - ejectOnInteract: true - whitelist: - components: - - HitscanBatteryAmmoProvider - - ProjectileBatteryAmmoProvider - - Stunbaton + slotId: charger_slot + - type: ItemSlots + slots: + charger_slot: + whitelist: + components: + - HitscanBatteryAmmoProvider + - ProjectileBatteryAmmoProvider + - Stunbaton - type: entity name: wall recharger @@ -70,10 +74,3 @@ - type: WallMount - type: Charger chargeRate: 25 - chargerSlot: - ejectOnInteract: true - whitelist: - components: - - HitscanBatteryAmmoProvider - - ProjectileBatteryAmmoProvider - - Stunbaton