Move ApcPowerReceiverComponent Powered state to shared (#28206)
* Try syncing powered state to client For some reason the client is not receiving the ApcPowerReceiverComponentState, so it's not working. * Fix powered state not syncing to client The client PowerReceiverSystem was abstract, which prevented it from running initialize. * Flip check so that it runs bigger checks first PowerDisabled skips the others. NeedsPower skips the receiving check. * Disallow changing Powered manually * Move Powered update to PowerReceiverSystem * Move appearance to event subscription * Move metadata component to AllEntityQuery * Cleanup * Move Powered update back to PowerNetSystem It's easier to use the EntityQueries and it dosen't need to be updated anywhere else. * Put appearance updating back * Move IsPowered to shared * Simplify IsPowered * Cleanup * Remove duplicate PowerChangedEvent PowerChangedEvent on ProviderChanged doesn't seem to be needed PowerChangedEvent gets raised by in update if the power state changes after a new provider is connected
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
using Content.Shared.Power.Components;
|
||||
|
||||
namespace Content.Client.Power.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class ApcPowerReceiverComponent : SharedApcPowerReceiverComponent
|
||||
{
|
||||
}
|
||||
23
Content.Client/Power/EntitySystems/PowerReceiverSystem.cs
Normal file
23
Content.Client/Power/EntitySystems/PowerReceiverSystem.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using Content.Server.Power.NodeGroups;
|
||||
using Content.Server.Power.Pow3r;
|
||||
using Content.Shared.Power.Components;
|
||||
|
||||
namespace Content.Server.Power.Components
|
||||
{
|
||||
@@ -8,11 +9,8 @@ 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>
|
||||
@@ -33,7 +31,7 @@ namespace Content.Server.Power.Components
|
||||
{
|
||||
_needsPower = value;
|
||||
// Reset this so next tick will do a power update.
|
||||
PoweredLastUpdate = null;
|
||||
Recalculate = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +48,8 @@ namespace Content.Server.Power.Components
|
||||
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
|
||||
@@ -66,10 +65,5 @@ namespace Content.Server.Power.Components
|
||||
/// 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);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ namespace Content.Server.Power.EntitySystems
|
||||
[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();
|
||||
@@ -302,19 +303,27 @@ namespace Content.Server.Power.EntitySystems
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,15 +6,18 @@ using Content.Shared.Database;
|
||||
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!;
|
||||
@@ -38,6 +41,8 @@ namespace Content.Server.Power.EntitySystems
|
||||
SubscribeLocalEvent<ApcPowerReceiverComponent, GetVerbsEvent<Verb>>(OnGetVerbs);
|
||||
SubscribeLocalEvent<PowerSwitchComponent, GetVerbsEvent<AlternativeVerb>>(AddSwitchPowerVerb);
|
||||
|
||||
SubscribeLocalEvent<ApcPowerReceiverComponent, ComponentGetState>(OnGetState);
|
||||
|
||||
_recQuery = GetEntityQuery<ApcPowerReceiverComponent>();
|
||||
_provQuery = GetEntityQuery<ApcPowerProviderComponent>();
|
||||
}
|
||||
@@ -140,14 +145,18 @@ namespace Content.Server.Power.EntitySystems
|
||||
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>
|
||||
@@ -155,12 +164,10 @@ namespace Content.Server.Power.EntitySystems
|
||||
/// 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>
|
||||
@@ -192,5 +199,10 @@ namespace Content.Server.Power.EntitySystems
|
||||
|
||||
return !receiver.PowerDisabled; // i.e. PowerEnabled
|
||||
}
|
||||
|
||||
public void SetLoad(ApcPowerReceiverComponent comp, float load)
|
||||
{
|
||||
comp.Load = load;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.Power.Components;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class ApcPowerReceiverComponentState : ComponentState
|
||||
{
|
||||
public bool Powered;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared.Power.Components;
|
||||
|
||||
[NetworkedComponent]
|
||||
public abstract partial class SharedApcPowerReceiverComponent : Component
|
||||
{
|
||||
[ViewVariables]
|
||||
public bool Powered;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Content.Shared.Power.EntitySystems;
|
||||
|
||||
public abstract class SharedPowerReceiverSystem : EntitySystem
|
||||
{
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user