Predict some power PowerReceiver stuff (#33834)

* Predict some power PowerReceiver stuff

Need it for some atmos device prediction.

* Also this
This commit is contained in:
metalgearsloth
2025-03-10 13:00:49 +11:00
committed by GitHub
parent 6689cae5a1
commit 75a7407e33
9 changed files with 96 additions and 61 deletions

View File

@@ -27,6 +27,8 @@ public sealed class PowerReceiverSystem : SharedPowerReceiverSystem
return; return;
component.Powered = state.Powered; component.Powered = state.Powered;
component.NeedsPower = state.NeedsPower;
component.PowerDisabled = state.PowerDisabled;
} }
public override bool ResolveApc(EntityUid entity, [NotNullWhen(true)] ref SharedApcPowerReceiverComponent? component) public override bool ResolveApc(EntityUid entity, [NotNullWhen(true)] ref SharedApcPowerReceiverComponent? component)

View File

@@ -24,7 +24,7 @@ namespace Content.Server.Power.Components
/// When false, causes this to appear powered even if not receiving power from an Apc. /// When false, causes this to appear powered even if not receiving power from an Apc.
/// </summary> /// </summary>
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
public bool NeedsPower public override bool NeedsPower
{ {
get => _needsPower; get => _needsPower;
set set
@@ -41,9 +41,9 @@ namespace Content.Server.Power.Components
/// <summary> /// <summary>
/// When true, causes this to never appear powered. /// When true, causes this to never appear powered.
/// </summary> /// </summary>
[ViewVariables(VVAccess.ReadWrite)]
[DataField("powerDisabled")] [DataField("powerDisabled")]
public bool PowerDisabled { public override bool PowerDisabled
{
get => !NetworkLoad.Enabled; get => !NetworkLoad.Enabled;
set => NetworkLoad.Enabled = !value; set => NetworkLoad.Enabled = !value;
} }

View File

@@ -1,18 +1,12 @@
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using Content.Server.Administration.Logs;
using Content.Server.Administration.Managers; using Content.Server.Administration.Managers;
using Content.Server.Power.Components; using Content.Server.Power.Components;
using Content.Shared.Administration; using Content.Shared.Administration;
using Content.Shared.Database;
using Content.Shared.Examine; using Content.Shared.Examine;
using Content.Shared.Hands.Components; using Content.Shared.Hands.Components;
using Content.Shared.Power;
using Content.Shared.Power.Components; using Content.Shared.Power.Components;
using Content.Shared.Power.EntitySystems; using Content.Shared.Power.EntitySystems;
using Content.Shared.Verbs; using Content.Shared.Verbs;
using Robust.Server.Audio;
using Robust.Server.GameObjects;
using Robust.Shared.Audio;
using Robust.Shared.GameStates; using Robust.Shared.GameStates;
using Robust.Shared.Utility; using Robust.Shared.Utility;
@@ -20,9 +14,8 @@ namespace Content.Server.Power.EntitySystems
{ {
public sealed class PowerReceiverSystem : SharedPowerReceiverSystem public sealed class PowerReceiverSystem : SharedPowerReceiverSystem
{ {
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
[Dependency] private readonly IAdminManager _adminManager = default!; [Dependency] private readonly IAdminManager _adminManager = default!;
[Dependency] private readonly AudioSystem _audio = default!;
private EntityQuery<ApcPowerReceiverComponent> _recQuery; private EntityQuery<ApcPowerReceiverComponent> _recQuery;
private EntityQuery<ApcPowerProviderComponent> _provQuery; private EntityQuery<ApcPowerProviderComponent> _provQuery;
@@ -63,7 +56,10 @@ namespace Content.Server.Power.EntitySystems
Text = Loc.GetString("verb-debug-toggle-need-power"), Text = Loc.GetString("verb-debug-toggle-need-power"),
Category = VerbCategory.Debug, Category = VerbCategory.Debug,
Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/smite.svg.192dpi.png")), // "smite" is a lightning bolt Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/smite.svg.192dpi.png")), // "smite" is a lightning bolt
Act = () => component.NeedsPower = !component.NeedsPower Act = () =>
{
SetNeedsPower(uid, !component.NeedsPower, component);
}
}); });
} }
@@ -143,7 +139,9 @@ namespace Content.Server.Power.EntitySystems
{ {
args.State = new ApcPowerReceiverComponentState args.State = new ApcPowerReceiverComponentState
{ {
Powered = component.Powered Powered = component.Powered,
NeedsPower = component.NeedsPower,
PowerDisabled = component.PowerDisabled,
}; };
} }
@@ -164,36 +162,6 @@ namespace Content.Server.Power.EntitySystems
return !_recQuery.Resolve(uid, ref receiver, false) || receiver.Powered; return !_recQuery.Resolve(uid, ref receiver, false) || receiver.Powered;
} }
/// <summary>
/// Turn this machine on or off.
/// Returns true if we turned it on, false if we turned it off.
/// </summary>
public bool TogglePower(EntityUid uid, bool playSwitchSound = true, ApcPowerReceiverComponent? receiver = null, EntityUid? user = null)
{
if (!_recQuery.Resolve(uid, ref receiver, false))
return true;
// it'll save a lot of confusion if 'always powered' means 'always powered'
if (!receiver.NeedsPower)
{
receiver.PowerDisabled = false;
return true;
}
receiver.PowerDisabled = !receiver.PowerDisabled;
if (user != null)
_adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(user.Value):player} hit power button on {ToPrettyString(uid)}, it's now {(!receiver.PowerDisabled ? "on" : "off")}");
if (playSwitchSound)
{
_audio.PlayPvs(new SoundPathSpecifier("/Audio/Machines/machine_switch.ogg"), uid,
AudioParams.Default.WithVolume(-2f));
}
return !receiver.PowerDisabled; // i.e. PowerEnabled
}
public void SetLoad(ApcPowerReceiverComponent comp, float load) public void SetLoad(ApcPowerReceiverComponent comp, float load)
{ {
comp.Load = load; comp.Load = load;

View File

@@ -11,6 +11,7 @@ using Content.Shared.Atmos;
using Content.Shared.DeviceNetwork; using Content.Shared.DeviceNetwork;
using Content.Shared.Examine; using Content.Shared.Examine;
using Content.Shared.Power; using Content.Shared.Power;
using Content.Shared.Power.EntitySystems;
using Content.Shared.Power.Generation.Teg; using Content.Shared.Power.Generation.Teg;
using Content.Shared.Rounding; using Content.Shared.Rounding;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
@@ -66,11 +67,12 @@ public sealed class TegSystem : EntitySystem
/// </summary> /// </summary>
public const string DeviceNetworkCommandSyncData = "teg_sync_data"; public const string DeviceNetworkCommandSyncData = "teg_sync_data";
[Dependency] private readonly AmbientSoundSystem _ambientSound = default!;
[Dependency] private readonly AppearanceSystem _appearance = default!;
[Dependency] private readonly AtmosphereSystem _atmosphere = default!; [Dependency] private readonly AtmosphereSystem _atmosphere = default!;
[Dependency] private readonly DeviceNetworkSystem _deviceNetwork = default!; [Dependency] private readonly DeviceNetworkSystem _deviceNetwork = default!;
[Dependency] private readonly AppearanceSystem _appearance = default!;
[Dependency] private readonly PointLightSystem _pointLight = default!; [Dependency] private readonly PointLightSystem _pointLight = default!;
[Dependency] private readonly AmbientSoundSystem _ambientSound = default!; [Dependency] private readonly SharedPowerReceiverSystem _receiver = default!;
private EntityQuery<NodeContainerComponent> _nodeContainerQuery; private EntityQuery<NodeContainerComponent> _nodeContainerQuery;
@@ -241,8 +243,7 @@ public sealed class TegSystem : EntitySystem
var powerReceiver = Comp<ApcPowerReceiverComponent>(uid); var powerReceiver = Comp<ApcPowerReceiverComponent>(uid);
powerReceiver.PowerDisabled = !group.IsFullyBuilt; _receiver.SetPowerDisabled(uid, !group.IsFullyBuilt, powerReceiver);
UpdateAppearance(uid, component, powerReceiver, group); UpdateAppearance(uid, component, powerReceiver, group);
} }

View File

@@ -1,6 +1,7 @@
using Content.Server.Electrocution; using Content.Server.Electrocution;
using Content.Shared.Electrocution; using Content.Shared.Electrocution;
using Content.Server.Power.Components; using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems;
using Content.Server.Wires; using Content.Server.Wires;
using Content.Shared.Power; using Content.Shared.Power;
using Content.Shared.Wires; using Content.Shared.Wires;
@@ -61,15 +62,17 @@ public sealed partial class PowerWireAction : BaseWireAction
return; return;
} }
var receiverSys = EntityManager.System<PowerReceiverSystem>();
if (pulsed) if (pulsed)
{ {
power.PowerDisabled = true; receiverSys.SetPowerDisabled(owner, true, power);
return; return;
} }
if (AllWiresCut(owner)) if (AllWiresCut(owner))
{ {
power.PowerDisabled = true; receiverSys.SetPowerDisabled(owner, true, power);
} }
else else
{ {
@@ -79,7 +82,7 @@ public sealed partial class PowerWireAction : BaseWireAction
return; return;
} }
power.PowerDisabled = false; receiverSys.SetPowerDisabled(owner, false, power);
} }
} }

View File

@@ -12,6 +12,7 @@ using Content.Shared.Paper;
using Content.Shared.Placeable; using Content.Shared.Placeable;
using Content.Shared.Popups; using Content.Shared.Popups;
using Content.Shared.Power; using Content.Shared.Power;
using Content.Shared.Power.EntitySystems;
using Content.Shared.Research.Components; using Content.Shared.Research.Components;
using Content.Shared.Xenoarchaeology.Equipment; using Content.Shared.Xenoarchaeology.Equipment;
using Content.Shared.Xenoarchaeology.XenoArtifacts; using Content.Shared.Xenoarchaeology.XenoArtifacts;
@@ -33,15 +34,16 @@ public sealed class ArtifactAnalyzerSystem : EntitySystem
{ {
[Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly IPrototypeManager _prototype = default!; [Dependency] private readonly IPrototypeManager _prototype = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedAmbientSoundSystem _ambientSound = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly UserInterfaceSystem _ui = default!;
[Dependency] private readonly ArtifactSystem _artifact = default!; [Dependency] private readonly ArtifactSystem _artifact = default!;
[Dependency] private readonly MetaDataSystem _metaSystem = default!;
[Dependency] private readonly PaperSystem _paper = default!; [Dependency] private readonly PaperSystem _paper = default!;
[Dependency] private readonly ResearchSystem _research = default!; [Dependency] private readonly ResearchSystem _research = default!;
[Dependency] private readonly MetaDataSystem _metaSystem = default!; [Dependency] private readonly SharedAmbientSoundSystem _ambientSound = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly SharedPowerReceiverSystem _receiver = default!;
[Dependency] private readonly TraversalDistorterSystem _traversalDistorter = default!; [Dependency] private readonly TraversalDistorterSystem _traversalDistorter = default!;
[Dependency] private readonly UserInterfaceSystem _ui = default!;
/// <inheritdoc/> /// <inheritdoc/>
public override void Initialize() public override void Initialize()
@@ -492,17 +494,13 @@ public sealed class ArtifactAnalyzerSystem : EntitySystem
private void OnAnalyzeStart(EntityUid uid, ActiveArtifactAnalyzerComponent component, ComponentStartup args) private void OnAnalyzeStart(EntityUid uid, ActiveArtifactAnalyzerComponent component, ComponentStartup args)
{ {
if (TryComp<ApcPowerReceiverComponent>(uid, out var powa)) _receiver.SetNeedsPower(uid, true);
powa.NeedsPower = true;
_ambientSound.SetAmbience(uid, true); _ambientSound.SetAmbience(uid, true);
} }
private void OnAnalyzeEnd(EntityUid uid, ActiveArtifactAnalyzerComponent component, ComponentShutdown args) private void OnAnalyzeEnd(EntityUid uid, ActiveArtifactAnalyzerComponent component, ComponentShutdown args)
{ {
if (TryComp<ApcPowerReceiverComponent>(uid, out var powa)) _receiver.SetNeedsPower(uid, false);
powa.NeedsPower = false;
_ambientSound.SetAmbience(uid, false); _ambientSound.SetAmbience(uid, false);
} }

View File

@@ -6,4 +6,6 @@ namespace Content.Shared.Power.Components;
public sealed class ApcPowerReceiverComponentState : ComponentState public sealed class ApcPowerReceiverComponentState : ComponentState
{ {
public bool Powered; public bool Powered;
public bool NeedsPower;
public bool PowerDisabled;
} }

View File

@@ -7,4 +7,10 @@ public abstract partial class SharedApcPowerReceiverComponent : Component
{ {
[ViewVariables] [ViewVariables]
public bool Powered; public bool Powered;
[ViewVariables]
public virtual bool NeedsPower { get; set; }
[ViewVariables]
public virtual bool PowerDisabled { get; set; }
} }

View File

@@ -1,12 +1,67 @@
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using Content.Shared.Administration.Logs;
using Content.Shared.Database;
using Content.Shared.Power.Components; using Content.Shared.Power.Components;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
namespace Content.Shared.Power.EntitySystems; namespace Content.Shared.Power.EntitySystems;
public abstract class SharedPowerReceiverSystem : EntitySystem public abstract class SharedPowerReceiverSystem : EntitySystem
{ {
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
public abstract bool ResolveApc(EntityUid entity, [NotNullWhen(true)] ref SharedApcPowerReceiverComponent? component); public abstract bool ResolveApc(EntityUid entity, [NotNullWhen(true)] ref SharedApcPowerReceiverComponent? component);
public void SetNeedsPower(EntityUid uid, bool value, SharedApcPowerReceiverComponent? receiver = null)
{
if (!ResolveApc(uid, ref receiver) || receiver.NeedsPower == value)
return;
receiver.NeedsPower = value;
Dirty(uid, receiver);
}
public void SetPowerDisabled(EntityUid uid, bool value, SharedApcPowerReceiverComponent? receiver = null)
{
if (!ResolveApc(uid, ref receiver) || receiver.PowerDisabled == value)
return;
receiver.PowerDisabled = value;
Dirty(uid, receiver);
}
/// <summary>
/// Turn this machine on or off.
/// Returns true if we turned it on, false if we turned it off.
/// </summary>
public bool TogglePower(EntityUid uid, bool playSwitchSound = true, SharedApcPowerReceiverComponent? receiver = null, EntityUid? user = null)
{
if (!ResolveApc(uid, ref receiver))
return true;
// it'll save a lot of confusion if 'always powered' means 'always powered'
if (!receiver.NeedsPower)
{
SetPowerDisabled(uid, false, receiver);
return true;
}
SetPowerDisabled(uid, !receiver.PowerDisabled, receiver);
if (user != null)
_adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(user.Value):player} hit power button on {ToPrettyString(uid)}, it's now {(!receiver.PowerDisabled ? "on" : "off")}");
if (playSwitchSound)
{
_audio.PlayPredicted(new SoundPathSpecifier("/Audio/Machines/machine_switch.ogg"), uid, user: user,
AudioParams.Default.WithVolume(-2f));
}
return !receiver.PowerDisabled; // i.e. PowerEnabled
}
/// <summary> /// <summary>
/// Checks if entity is APC-powered device, and if it have power. /// Checks if entity is APC-powered device, and if it have power.
/// </summary> /// </summary>