--- /dev/null
+using Content.Shared.Power.Components;
+
+namespace Content.Client.Power.Components;
+
+[RegisterComponent]
+public sealed partial class ApcPowerReceiverComponent : SharedApcPowerReceiverComponent
+{
+}
--- /dev/null
+using Content.Client.Power.Components;
+using Content.Shared.Power.Components;
+using Content.Shared.Power.EntitySystems;
+using Robust.Shared.GameStates;
+
+namespace Content.Client.Power.EntitySystems;
+
+public sealed class PowerReceiverSystem : SharedPowerReceiverSystem
+{
+ public override void Initialize()
+ {
+ base.Initialize();
+ SubscribeLocalEvent<ApcPowerReceiverComponent, ComponentHandleState>(OnHandleState);
+ }
+
+ private void OnHandleState(EntityUid uid, ApcPowerReceiverComponent component, ref ComponentHandleState args)
+ {
+ if (args.Current is not ApcPowerReceiverComponentState state)
+ return;
+
+ component.Powered = state.Powered;
+ }
+}
using Content.Server.Power.NodeGroups;
using Content.Server.Power.Pow3r;
+using Content.Shared.Power.Components;
namespace Content.Server.Power.Components
{
/// so that it can receive power from a <see cref="IApcNet"/>.
/// </summary>
[RegisterComponent]
- public sealed partial class ApcPowerReceiverComponent : Component
+ public sealed partial class ApcPowerReceiverComponent : SharedApcPowerReceiverComponent
{
- [ViewVariables]
- public bool Powered => (MathHelper.CloseToPercent(NetworkLoad.ReceivingPower, Load) || !NeedsPower) && !PowerDisabled;
-
/// <summary>
/// Amount of charge this needs from an APC per second to function.
/// </summary>
{
_needsPower = value;
// Reset this so next tick will do a power update.
- PoweredLastUpdate = null;
+ Recalculate = true;
}
}
set => NetworkLoad.Enabled = !value;
}
- public bool? PoweredLastUpdate;
+ // TODO Is this needed? It forces a PowerChangedEvent when NeedsPower is toggled even if it changes to the same state.
+ public bool Recalculate;
[ViewVariables]
public PowerState.Load NetworkLoad { get; } = new PowerState.Load
/// Does nothing on the client.
/// </summary>
[ByRefEvent]
- public readonly record struct PowerChangedEvent(bool Powered, float ReceivingPower)
- {
- public readonly bool Powered = Powered;
- public readonly float ReceivingPower = ReceivingPower;
- }
-
+ public readonly record struct PowerChangedEvent(bool Powered, float ReceivingPower);
}
[Dependency] private readonly AppearanceSystem _appearance = default!;
[Dependency] private readonly PowerNetConnectorSystem _powerNetConnector = default!;
[Dependency] private readonly IParallelManager _parMan = default!;
+ [Dependency] private readonly PowerReceiverSystem _powerReceiver = default!;
private readonly PowerState _powerState = new();
private readonly HashSet<PowerNet> _powerNetReconnectQueue = new();
var enumerator = AllEntityQuery<ApcPowerReceiverComponent>();
while (enumerator.MoveNext(out var uid, out var apcReceiver))
{
- var powered = apcReceiver.Powered;
- if (powered == apcReceiver.PoweredLastUpdate)
+ var powered = !apcReceiver.PowerDisabled
+ && (!apcReceiver.NeedsPower
+ || MathHelper.CloseToPercent(apcReceiver.NetworkLoad.ReceivingPower,
+ apcReceiver.Load));
+
+ // If new value is the same as the old, then exit
+ if (!apcReceiver.Recalculate && apcReceiver.Powered == powered)
continue;
- if (metaQuery.GetComponent(uid).EntityPaused)
+ var metadata = metaQuery.Comp(uid);
+ if (metadata.EntityPaused)
continue;
- apcReceiver.PoweredLastUpdate = powered;
- var ev = new PowerChangedEvent(apcReceiver.Powered, apcReceiver.NetworkLoad.ReceivingPower);
+ apcReceiver.Recalculate = false;
+ apcReceiver.Powered = powered;
+ Dirty(uid, apcReceiver, metadata);
+ var ev = new PowerChangedEvent(powered, apcReceiver.NetworkLoad.ReceivingPower);
RaiseLocalEvent(uid, ref ev);
- if (appearanceQuery.TryGetComponent(uid, out var appearance))
+ if (appearanceQuery.TryComp(uid, out var appearance))
_appearance.SetData(uid, PowerDeviceVisuals.Powered, powered, appearance);
}
}
using Content.Shared.Examine;
using Content.Shared.Hands.Components;
using Content.Shared.Power;
+using Content.Shared.Power.Components;
+using Content.Shared.Power.EntitySystems;
using Content.Shared.Verbs;
using Robust.Server.Audio;
using Robust.Server.GameObjects;
using Robust.Shared.Audio;
+using Robust.Shared.GameStates;
using Robust.Shared.Utility;
namespace Content.Server.Power.EntitySystems
{
- public sealed class PowerReceiverSystem : EntitySystem
+ public sealed class PowerReceiverSystem : SharedPowerReceiverSystem
{
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
[Dependency] private readonly IAdminManager _adminManager = default!;
SubscribeLocalEvent<ApcPowerReceiverComponent, GetVerbsEvent<Verb>>(OnGetVerbs);
SubscribeLocalEvent<PowerSwitchComponent, GetVerbsEvent<AlternativeVerb>>(AddSwitchPowerVerb);
+ SubscribeLocalEvent<ApcPowerReceiverComponent, ComponentGetState>(OnGetState);
+
_recQuery = GetEntityQuery<ApcPowerReceiverComponent>();
_provQuery = GetEntityQuery<ApcPowerProviderComponent>();
}
args.Verbs.Add(verb);
}
+ private void OnGetState(EntityUid uid, ApcPowerReceiverComponent component, ref ComponentGetState args)
+ {
+ args.State = new ApcPowerReceiverComponentState
+ {
+ Powered = component.Powered
+ };
+ }
+
private void ProviderChanged(Entity<ApcPowerReceiverComponent> receiver)
{
var comp = receiver.Comp;
comp.NetworkLoad.LinkedNetwork = default;
- var ev = new PowerChangedEvent(comp.Powered, comp.NetworkLoad.ReceivingPower);
-
- RaiseLocalEvent(receiver, ref ev);
- _appearance.SetData(receiver, PowerDeviceVisuals.Powered, comp.Powered);
}
/// <summary>
/// Otherwise, it returns 'true' because if something doesn't take power
/// it's effectively always powered.
/// </summary>
+ /// <returns>True when entity has no ApcPowerReceiverComponent or is Powered. False when not.</returns>
public bool IsPowered(EntityUid uid, ApcPowerReceiverComponent? receiver = null)
{
- if (!_recQuery.Resolve(uid, ref receiver, false))
- return true;
-
- return receiver.Powered;
+ return !_recQuery.Resolve(uid, ref receiver, false) || receiver.Powered;
}
/// <summary>
return !receiver.PowerDisabled; // i.e. PowerEnabled
}
+
+ public void SetLoad(ApcPowerReceiverComponent comp, float load)
+ {
+ comp.Load = load;
+ }
}
}
--- /dev/null
+using Robust.Shared.Serialization;
+
+namespace Content.Shared.Power.Components;
+
+[Serializable, NetSerializable]
+public sealed class ApcPowerReceiverComponentState : ComponentState
+{
+ public bool Powered;
+}
--- /dev/null
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Power.Components;
+
+[NetworkedComponent]
+public abstract partial class SharedApcPowerReceiverComponent : Component
+{
+ [ViewVariables]
+ public bool Powered;
+}
--- /dev/null
+namespace Content.Shared.Power.EntitySystems;
+
+public abstract class SharedPowerReceiverSystem : EntitySystem
+{
+
+}