diff --git a/Content.Server/Power/Components/ApcComponent.cs b/Content.Server/Power/Components/ApcComponent.cs index 8f74146b45..bee8defc43 100644 --- a/Content.Server/Power/Components/ApcComponent.cs +++ b/Content.Server/Power/Components/ApcComponent.cs @@ -11,12 +11,9 @@ public sealed partial class ApcComponent : BaseApcNetComponent [DataField("onReceiveMessageSound")] public SoundSpecifier OnReceiveMessageSound = new SoundPathSpecifier("/Audio/Machines/machine_switch.ogg"); - [DataField("lastChargeState")] public ApcChargeState LastChargeState; - [DataField("lastChargeStateTime", customTypeSerializer: typeof(TimeOffsetSerializer))] - public TimeSpan LastChargeStateTime; + public TimeSpan? LastChargeStateTime; - [DataField("lastExternalState")] public ApcExternalPowerState LastExternalState; /// @@ -24,7 +21,6 @@ public sealed partial class ApcComponent : BaseApcNetComponent /// Done after every to show the latest load. /// If charge state changes it will be instantly updated. /// - [DataField("lastUiUpdate", customTypeSerializer: typeof(TimeOffsetSerializer))] public TimeSpan LastUiUpdate; [DataField("enabled")] @@ -33,6 +29,11 @@ public sealed partial class ApcComponent : BaseApcNetComponent [DataField("hasAccess")] public bool HasAccess = false; + /// + /// APC state needs to always be updated after first processing tick. + /// + public bool NeedStateUpdate; + public const float HighPowerThreshold = 0.9f; public static TimeSpan VisualsChangeDelay = TimeSpan.FromSeconds(1); diff --git a/Content.Server/Power/EntitySystems/ApcSystem.cs b/Content.Server/Power/EntitySystems/ApcSystem.cs index d88edd85cb..52c19c302c 100644 --- a/Content.Server/Power/EntitySystems/ApcSystem.cs +++ b/Content.Server/Power/EntitySystems/ApcSystem.cs @@ -32,7 +32,7 @@ public sealed class ApcSystem : EntitySystem UpdatesAfter.Add(typeof(PowerNetSystem)); SubscribeLocalEvent(OnBoundUiOpen); - SubscribeLocalEvent(OnApcInit); + SubscribeLocalEvent(OnApcStartup); SubscribeLocalEvent(OnBatteryChargeChanged); SubscribeLocalEvent(OnToggleMainBreaker); SubscribeLocalEvent(OnEmagged); @@ -50,6 +50,11 @@ public sealed class ApcSystem : EntitySystem apc.LastUiUpdate = _gameTiming.CurTime; UpdateUIState(uid, apc, battery); } + + if (apc.NeedStateUpdate) + { + UpdateApcState(uid, apc, battery); + } } } @@ -59,9 +64,11 @@ public sealed class ApcSystem : EntitySystem UpdateApcState(uid, component); } - private void OnApcInit(EntityUid uid, ApcComponent component, MapInitEvent args) + private static void OnApcStartup(EntityUid uid, ApcComponent component, ComponentStartup args) { - UpdateApcState(uid, component); + // We cannot update immediately, as various network/battery state is not valid yet. + // Defer until the next tick. + component.NeedStateUpdate = true; } //Update the HasAccess var for UI to read @@ -119,15 +126,18 @@ public sealed class ApcSystem : EntitySystem if (!Resolve(uid, ref apc, ref battery, false)) return; - var newState = CalcChargeState(uid, battery.NetworkBattery); - if (newState != apc.LastChargeState && apc.LastChargeStateTime + ApcComponent.VisualsChangeDelay < _gameTiming.CurTime) + if (apc.LastChargeStateTime == null || apc.LastChargeStateTime + ApcComponent.VisualsChangeDelay < _gameTiming.CurTime) { - apc.LastChargeState = newState; - apc.LastChargeStateTime = _gameTiming.CurTime; - - if (TryComp(uid, out AppearanceComponent? appearance)) + var newState = CalcChargeState(uid, battery.NetworkBattery); + if (newState != apc.LastChargeState) { - _appearance.SetData(uid, ApcVisuals.ChargeState, newState, appearance); + apc.LastChargeState = newState; + apc.LastChargeStateTime = _gameTiming.CurTime; + + if (TryComp(uid, out AppearanceComponent? appearance)) + { + _appearance.SetData(uid, ApcVisuals.ChargeState, newState, appearance); + } } } @@ -137,6 +147,8 @@ public sealed class ApcSystem : EntitySystem apc.LastExternalState = extPowerState; UpdateUIState(uid, apc, battery); } + + apc.NeedStateUpdate = false; } public void UpdateUIState(EntityUid uid,