using Robust.Server.GameObjects;
using Robust.Shared.Timing;
-namespace Content.Server.Power.SMES
+namespace Content.Server.Power.SMES;
+
+/// <summary>
+/// Handles the "user-facing" side of the actual SMES object.
+/// This is operations that are specific to the SMES, like UI and visuals.
+/// Logic is handled in <see cref="PowerSmesSystem"/>
+/// Code interfacing with the powernet is handled in <see cref="BatteryStorageComponent"/> and <see cref="BatteryDischargerComponent"/>.
+/// </summary>
+[RegisterComponent, Access(typeof(SmesSystem))]
+public sealed class SmesComponent : Component
{
- /// <summary>
- /// Handles the "user-facing" side of the actual SMES object.
- /// This is operations that are specific to the SMES, like UI and visuals.
- /// Code interfacing with the powernet is handled in <see cref="BatteryStorageComponent"/> and <see cref="BatteryDischargerComponent"/>.
- /// </summary>
- [RegisterComponent]
- public sealed class SmesComponent : Component
- {
- [Dependency] private readonly IEntityManager _entMan = default!;
- [Dependency] private readonly IGameTiming _gameTiming = default!;
-
- private int _lastChargeLevel;
-
- private TimeSpan _lastChargeLevelChange;
-
- private ChargeState _lastChargeState;
-
- private TimeSpan _lastChargeStateChange;
-
- private const int VisualsChangeDelay = 1;
-
- protected override void Initialize()
- {
- base.Initialize();
-
- Owner.EnsureComponentWarn<ServerAppearanceComponent>();
- }
-
- public void OnUpdate()
- {
- var newLevel = GetNewChargeLevel();
- if (newLevel != _lastChargeLevel && _lastChargeLevelChange + TimeSpan.FromSeconds(VisualsChangeDelay) < _gameTiming.CurTime)
- {
- _lastChargeLevel = newLevel;
- _lastChargeLevelChange = _gameTiming.CurTime;
-
- if (_entMan.TryGetComponent(Owner, out AppearanceComponent? appearance))
- {
- appearance.SetData(SmesVisuals.LastChargeLevel, newLevel);
- }
- }
-
- var newChargeState = GetNewChargeState();
- if (newChargeState != _lastChargeState && _lastChargeStateChange + TimeSpan.FromSeconds(VisualsChangeDelay) < _gameTiming.CurTime)
- {
- _lastChargeState = newChargeState;
- _lastChargeStateChange = _gameTiming.CurTime;
-
- if (_entMan.TryGetComponent(Owner, out AppearanceComponent? appearance))
- {
- appearance.SetData(SmesVisuals.LastChargeState, newChargeState);
- }
- }
- }
-
- private int GetNewChargeLevel()
- {
- if (!_entMan.TryGetComponent(Owner, out BatteryComponent? battery))
- {
- return 0;
- }
-
- return ContentHelpers.RoundToLevels(battery.CurrentCharge, battery.MaxCharge, 6);
- }
-
- private ChargeState GetNewChargeState()
- {
- var battery = _entMan.GetComponent<PowerNetworkBatteryComponent>(Owner);
- return (battery.CurrentSupply - battery.CurrentReceiving) switch
- {
- > 0 => ChargeState.Discharging,
- < 0 => ChargeState.Charging,
- _ => ChargeState.Still
- };
- }
- }
+ [ViewVariables]
+ public ChargeState LastChargeState;
+ [ViewVariables]
+ public TimeSpan LastChargeStateTime;
+ [ViewVariables]
+ public int LastChargeLevel;
+ [ViewVariables]
+ public TimeSpan LastChargeLevelTime;
+ [ViewVariables]
+ public TimeSpan VisualsChangeDelay = TimeSpan.FromSeconds(1);
}
--- /dev/null
+using Content.Server.Power.Components;
+using Content.Server.Power.EntitySystems;
+using Content.Shared.Power;
+using Content.Shared.Rounding;
+using Content.Shared.SMES;
+using JetBrains.Annotations;
+using Robust.Shared.Timing;
+
+namespace Content.Server.Power.SMES;
+
+[UsedImplicitly]
+internal sealed class SmesSystem : EntitySystem
+{
+ [Dependency] private readonly IGameTiming _gameTiming = default!;
+ [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ UpdatesAfter.Add(typeof(PowerNetSystem));
+
+ SubscribeLocalEvent<SmesComponent, MapInitEvent>(OnMapInit);
+ SubscribeLocalEvent<SmesComponent, ChargeChangedEvent>(OnBatteryChargeChanged);
+ }
+
+ private void OnMapInit(EntityUid uid, SmesComponent component, MapInitEvent args)
+ {
+ UpdateSmesState(uid, component);
+ }
+
+ private void OnBatteryChargeChanged(EntityUid uid, SmesComponent component, ref ChargeChangedEvent args)
+ {
+ UpdateSmesState(uid, component);
+ }
+
+ private void UpdateSmesState(EntityUid uid, SmesComponent smes)
+ {
+ var newLevel = CalcChargeLevel(uid);
+ if (newLevel != smes.LastChargeLevel && smes.LastChargeLevelTime + smes.VisualsChangeDelay < _gameTiming.CurTime)
+ {
+ smes.LastChargeLevel = newLevel;
+ smes.LastChargeLevelTime = _gameTiming.CurTime;
+
+ _appearance.SetData(uid, SmesVisuals.LastChargeLevel, newLevel);
+ }
+
+ var newChargeState = CalcChargeState(uid);
+ if (newChargeState != smes.LastChargeState && smes.LastChargeStateTime + smes.VisualsChangeDelay < _gameTiming.CurTime)
+ {
+ smes.LastChargeState = newChargeState;
+ smes.LastChargeStateTime = _gameTiming.CurTime;
+
+ _appearance.SetData(uid, SmesVisuals.LastChargeState, newChargeState);
+ }
+ }
+
+ private int CalcChargeLevel(EntityUid uid, BatteryComponent? battery = null)
+ {
+ if (!Resolve<BatteryComponent>(uid, ref battery))
+ return 0;
+
+ return ContentHelpers.RoundToLevels(battery.CurrentCharge, battery.MaxCharge, 6);
+ }
+
+ private ChargeState CalcChargeState(EntityUid uid, PowerNetworkBatteryComponent? netBattery = null)
+ {
+ if (!Resolve<PowerNetworkBatteryComponent>(uid, ref netBattery))
+ return ChargeState.Still;
+
+ return (netBattery.CurrentSupply - netBattery.CurrentReceiving) switch
+ {
+ > 0 => ChargeState.Discharging,
+ < 0 => ChargeState.Charging,
+ _ => ChargeState.Still
+ };
+ }
+}