Files
ss14-wl/Content.Shared/PowerCell/PowerCellSystem.cs
slarticodefast 3266c94eac Unify BatteryComponent and PredictedBatteryComponent (#41867)
* unify

* cleanup and merge conflicts

* floating points

---------

Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com>
2025-12-19 18:18:12 +00:00

155 lines
5.9 KiB
C#

using Content.Shared.Containers.ItemSlots;
using Content.Shared.PowerCell.Components;
using Content.Shared.Examine;
using Content.Shared.Popups;
using Content.Shared.Power;
using Content.Shared.Power.Components;
using Content.Shared.Power.EntitySystems;
using Robust.Shared.Containers;
using Robust.Shared.Timing;
namespace Content.Shared.PowerCell;
public sealed partial class PowerCellSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly ItemSlotsSystem _itemSlots = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SharedBatterySystem _battery = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
public override void Initialize()
{
base.Initialize();
InitializeRelay();
SubscribeLocalEvent<PowerCellSlotComponent, ContainerIsInsertingAttemptEvent>(OnCellSlotInsertAttempt);
SubscribeLocalEvent<PowerCellSlotComponent, EntInsertedIntoContainerMessage>(OnCellSlotInserted);
SubscribeLocalEvent<PowerCellSlotComponent, EntRemovedFromContainerMessage>(OnCellSlotRemoved);
SubscribeLocalEvent<PowerCellSlotComponent, ExaminedEvent>(OnCellSlotExamined);
SubscribeLocalEvent<PowerCellSlotComponent, BatteryStateChangedEvent>(OnCellSlotStateChanged);
SubscribeLocalEvent<PowerCellComponent, ExaminedEvent>(OnCellExamined);
SubscribeLocalEvent<PowerCellDrawComponent, RefreshChargeRateEvent>(OnDrawRefreshChargeRate);
SubscribeLocalEvent<PowerCellDrawComponent, ComponentStartup>(OnDrawStartup);
SubscribeLocalEvent<PowerCellDrawComponent, ComponentRemove>(OnDrawRemove);
}
private void OnCellSlotInsertAttempt(Entity<PowerCellSlotComponent> ent, ref ContainerIsInsertingAttemptEvent args)
{
if (!ent.Comp.Initialized)
return;
if (args.Container.ID != ent.Comp.CellSlotId)
return;
// TODO: Can't this just use the ItemSlot's whitelist?
if (!HasComp<PowerCellComponent>(args.EntityUid))
args.Cancel();
}
private void OnCellSlotInserted(Entity<PowerCellSlotComponent> ent, ref EntInsertedIntoContainerMessage args)
{
if (args.Container.ID != ent.Comp.CellSlotId)
return;
if (_timing.ApplyingState)
return; // The change in appearance data is already networked separately.
var ev = new PowerCellChangedEvent(false);
RaiseLocalEvent(ent, ref ev);
_battery.RefreshChargeRate(args.Entity);
// Only update the visuals if we actually use them.
if (!HasComp<BatteryVisualsComponent>(ent))
return;
// Set the data to that of the power cell
if (_appearance.TryGetData(args.Entity, BatteryVisuals.State, out BatteryState state))
_appearance.SetData(ent.Owner, BatteryVisuals.State, state);
// Set the data to that of the power cell
if (_appearance.TryGetData(args.Entity, BatteryVisuals.Charging, out BatteryChargingState charging))
_appearance.SetData(ent.Owner, BatteryVisuals.Charging, charging);
}
private void OnCellSlotRemoved(Entity<PowerCellSlotComponent> ent, ref EntRemovedFromContainerMessage args)
{
if (args.Container.ID != ent.Comp.CellSlotId)
return;
if (_timing.ApplyingState)
return; // The change in appearance data is already networked separately.
var ev = new PowerCellChangedEvent(true);
RaiseLocalEvent(ent, ref ev);
var emptyEv = new PowerCellSlotEmptyEvent();
RaiseLocalEvent(ent, ref emptyEv);
_battery.RefreshChargeRate(args.Entity);
// Only update the visuals if we actually use them.
if (!HasComp<BatteryVisualsComponent>(ent))
return;
// Set the appearance to empty.
_appearance.SetData(ent.Owner, BatteryVisuals.State, BatteryState.Empty);
_appearance.SetData(ent.Owner, BatteryVisuals.Charging, BatteryChargingState.Constant);
}
private void OnCellSlotStateChanged(Entity<PowerCellSlotComponent> ent, ref BatteryStateChangedEvent args)
{
if (args.NewState != BatteryState.Empty)
return;
// Inform the device that the battery is empty.
var ev = new PowerCellSlotEmptyEvent();
RaiseLocalEvent(ent, ref ev);
}
private void OnCellSlotExamined(Entity<PowerCellSlotComponent> ent, ref ExaminedEvent args)
{
if (TryGetBatteryFromSlot(ent.AsNullable(), out var battery))
OnBatteryExamined(battery.Value, ref args);
else
args.PushMarkup(Loc.GetString("power-cell-component-examine-details-no-battery"));
}
private void OnCellExamined(Entity<PowerCellComponent> ent, ref ExaminedEvent args)
{
if (TryComp<BatteryComponent>(ent, out var battery))
OnBatteryExamined((ent.Owner, battery), ref args);
}
private void OnBatteryExamined(Entity<BatteryComponent> ent, ref ExaminedEvent args)
{
var chargePercent = _battery.GetChargeLevel(ent.AsNullable()) * 100;
args.PushMarkup(Loc.GetString("power-cell-component-examine-details", ("currentCharge", $"{chargePercent:F0}")));
}
private void OnDrawRefreshChargeRate(Entity<PowerCellDrawComponent> ent, ref RefreshChargeRateEvent args)
{
if (ent.Comp.Enabled)
args.NewChargeRate -= ent.Comp.DrawRate;
}
private void OnDrawStartup(Entity<PowerCellDrawComponent> ent, ref ComponentStartup args)
{
if (ent.Comp.Enabled)
_battery.RefreshChargeRate(ent.Owner);
}
private void OnDrawRemove(Entity<PowerCellDrawComponent> ent, ref ComponentRemove args)
{
// We use ComponentRemove to make sure this component no longer subscribes to the refresh event.
if (ent.Comp.Enabled)
_battery.RefreshChargeRate(ent.Owner);
}
}