]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Move ApcPowerReceiverComponent Powered state to shared (#28206)
authorShadowCommander <10494922+ShadowCommander@users.noreply.github.com>
Thu, 30 May 2024 06:46:22 +0000 (23:46 -0700)
committerGitHub <noreply@github.com>
Thu, 30 May 2024 06:46:22 +0000 (16:46 +1000)
* 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

Content.Client/Power/Components/ApcPowerReceiverComponent.cs [new file with mode: 0644]
Content.Client/Power/EntitySystems/PowerReceiverSystem.cs [new file with mode: 0644]
Content.Server/Power/Components/ApcPowerReceiverComponent.cs
Content.Server/Power/EntitySystems/PowerNetSystem.cs
Content.Server/Power/EntitySystems/PowerReceiverSystem.cs
Content.Shared/Power/Components/ApcPowerReceiverComponentState.cs [new file with mode: 0644]
Content.Shared/Power/Components/SharedApcPowerReceiverComponent.cs [new file with mode: 0644]
Content.Shared/Power/EntitySystems/SharedPowerReceiverSystem.cs [new file with mode: 0644]

diff --git a/Content.Client/Power/Components/ApcPowerReceiverComponent.cs b/Content.Client/Power/Components/ApcPowerReceiverComponent.cs
new file mode 100644 (file)
index 0000000..fbebcb7
--- /dev/null
@@ -0,0 +1,8 @@
+using Content.Shared.Power.Components;
+
+namespace Content.Client.Power.Components;
+
+[RegisterComponent]
+public sealed partial class ApcPowerReceiverComponent : SharedApcPowerReceiverComponent
+{
+}
diff --git a/Content.Client/Power/EntitySystems/PowerReceiverSystem.cs b/Content.Client/Power/EntitySystems/PowerReceiverSystem.cs
new file mode 100644 (file)
index 0000000..4d56592
--- /dev/null
@@ -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;
+    }
+}
index b8340d0be4b1c98419697b27b2005d182d463714..9a68e2aabb894b5e77d24e93362f91ffad257656 100644 (file)
@@ -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);
 }
index 07ecc2eafb0e7142406dae8fe71452f568584a74..7bd057951c9b1f6f0d433242f3fba3392a85e166 100644 (file)
@@ -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);
             }
         }
index 048fda23553ad7b010718e223c10162e6419328f..51520f04644630574ce5ad772a87721015bc3be8 100644 (file)
@@ -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;
+        }
     }
 }
diff --git a/Content.Shared/Power/Components/ApcPowerReceiverComponentState.cs b/Content.Shared/Power/Components/ApcPowerReceiverComponentState.cs
new file mode 100644 (file)
index 0000000..9b18d6a
--- /dev/null
@@ -0,0 +1,9 @@
+using Robust.Shared.Serialization;
+
+namespace Content.Shared.Power.Components;
+
+[Serializable, NetSerializable]
+public sealed class ApcPowerReceiverComponentState : ComponentState
+{
+    public bool Powered;
+}
diff --git a/Content.Shared/Power/Components/SharedApcPowerReceiverComponent.cs b/Content.Shared/Power/Components/SharedApcPowerReceiverComponent.cs
new file mode 100644 (file)
index 0000000..d739933
--- /dev/null
@@ -0,0 +1,10 @@
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Power.Components;
+
+[NetworkedComponent]
+public abstract partial class SharedApcPowerReceiverComponent : Component
+{
+    [ViewVariables]
+    public bool Powered;
+}
diff --git a/Content.Shared/Power/EntitySystems/SharedPowerReceiverSystem.cs b/Content.Shared/Power/EntitySystems/SharedPowerReceiverSystem.cs
new file mode 100644 (file)
index 0000000..be2a9dc
--- /dev/null
@@ -0,0 +1,6 @@
+namespace Content.Shared.Power.EntitySystems;
+
+public abstract class SharedPowerReceiverSystem : EntitySystem
+{
+
+}