Predict gas valves (#33836)

* Predict gas valves

* wawawewa

* Fix imports before I get yelled at

* soff
This commit is contained in:
metalgearsloth
2025-05-15 04:06:37 +10:00
committed by GitHub
parent 9a6dbb27cd
commit c09aa6039c
7 changed files with 137 additions and 104 deletions

View File

@@ -0,0 +1,8 @@
using Content.Shared.Atmos.Piping.Binary.Systems;
namespace Content.Client.Atmos.Piping.Binary.Systems;
public sealed class GasValveSystem : SharedGasValveSystem
{
}

View File

@@ -1,20 +0,0 @@
using Robust.Shared.Audio;
namespace Content.Server.Atmos.Piping.Binary.Components
{
[RegisterComponent]
public sealed partial class GasValveComponent : Component
{
[DataField("open")]
public bool Open { get; set; } = true;
[DataField("inlet")]
public string InletName { get; set; } = "inlet";
[DataField("outlet")]
public string OutletName { get; set; } = "outlet";
[DataField("valveSound")]
public SoundSpecifier ValveSound { get; private set; } = new SoundCollectionSpecifier("valveSqueak");
}
}

View File

@@ -1,93 +1,34 @@
using Content.Server.Atmos.Piping.Binary.Components;
using Content.Server.NodeContainer;
using Content.Server.NodeContainer.EntitySystems; using Content.Server.NodeContainer.EntitySystems;
using Content.Server.NodeContainer.Nodes; using Content.Server.NodeContainer.Nodes;
using Content.Shared.Atmos.Piping; using Content.Shared.Atmos.Piping.Binary.Components;
using Content.Shared.Atmos.Piping.Binary.Systems;
using Content.Shared.Audio; using Content.Shared.Audio;
using Content.Shared.Examine;
using Content.Shared.Interaction;
using JetBrains.Annotations;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Player;
namespace Content.Server.Atmos.Piping.Binary.EntitySystems namespace Content.Server.Atmos.Piping.Binary.EntitySystems;
public sealed class GasValveSystem : SharedGasValveSystem
{ {
[UsedImplicitly] [Dependency] private readonly SharedAmbientSoundSystem _ambientSoundSystem = default!;
public sealed class GasValveSystem : EntitySystem [Dependency] private readonly NodeContainerSystem _nodeContainer = default!;
public override void Set(EntityUid uid, GasValveComponent component, bool value)
{ {
[Dependency] private readonly SharedAmbientSoundSystem _ambientSoundSystem = default!; base.Set(uid, component, value);
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly NodeContainerSystem _nodeContainer = default!;
public override void Initialize() if (_nodeContainer.TryGetNodes(uid, component.InletName, component.OutletName, out PipeNode? inlet, out PipeNode? outlet))
{ {
base.Initialize(); if (component.Open)
SubscribeLocalEvent<GasValveComponent, ComponentStartup>(OnStartup);
SubscribeLocalEvent<GasValveComponent, ActivateInWorldEvent>(OnActivate);
SubscribeLocalEvent<GasValveComponent, ExaminedEvent>(OnExamined);
}
private void OnExamined(Entity<GasValveComponent> ent, ref ExaminedEvent args)
{
var valve = ent.Comp;
if (!Comp<TransformComponent>(ent).Anchored || !args.IsInDetailsRange) // Not anchored? Out of range? No status.
return;
if (Loc.TryGetString("gas-valve-system-examined", out var str,
("statusColor", valve.Open ? "green" : "orange"),
("open", valve.Open)))
{ {
args.PushMarkup(str); inlet.AddAlwaysReachable(outlet);
outlet.AddAlwaysReachable(inlet);
_ambientSoundSystem.SetAmbience(uid, true);
} }
} else
private void OnStartup(EntityUid uid, GasValveComponent component, ComponentStartup args)
{
// We call set in startup so it sets the appearance, node state, etc.
Set(uid, component, component.Open);
}
private void OnActivate(EntityUid uid, GasValveComponent component, ActivateInWorldEvent args)
{
if (args.Handled || !args.Complex)
return;
Toggle(uid, component);
_audio.PlayPvs(component.ValveSound, uid, AudioParams.Default.WithVariation(0.25f));
args.Handled = true;
}
public void Set(EntityUid uid, GasValveComponent component, bool value)
{
component.Open = value;
if (_nodeContainer.TryGetNodes(uid, component.InletName, component.OutletName, out PipeNode? inlet, out PipeNode? outlet))
{ {
if (TryComp<AppearanceComponent>(uid, out var appearance)) inlet.RemoveAlwaysReachable(outlet);
{ outlet.RemoveAlwaysReachable(inlet);
_appearance.SetData(uid, FilterVisuals.Enabled, component.Open, appearance); _ambientSoundSystem.SetAmbience(uid, false);
}
if (component.Open)
{
inlet.AddAlwaysReachable(outlet);
outlet.AddAlwaysReachable(inlet);
_ambientSoundSystem.SetAmbience(uid, true);
}
else
{
inlet.RemoveAlwaysReachable(outlet);
outlet.RemoveAlwaysReachable(inlet);
_ambientSoundSystem.SetAmbience(uid, false);
}
} }
} }
public void Toggle(EntityUid uid, GasValveComponent component)
{
Set(uid, component, !component.Open);
}
} }
} }

View File

@@ -1,5 +1,6 @@
using Content.Server.Atmos.Piping.Binary.Components; using Content.Server.Atmos.Piping.Binary.Components;
using Content.Server.DeviceLinking.Systems; using Content.Server.DeviceLinking.Systems;
using Content.Shared.Atmos.Piping.Binary.Components;
using Content.Shared.DeviceLinking.Events; using Content.Shared.DeviceLinking.Events;
namespace Content.Server.Atmos.Piping.Binary.EntitySystems; namespace Content.Server.Atmos.Piping.Binary.EntitySystems;

View File

@@ -11,7 +11,7 @@ namespace Content.Server.Atmos.Piping.Unary.Components
{ {
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
public bool Enabled { get; set; } = true; public bool Enabled = true;
/// <summary> /// <summary>
/// Target volume to transfer. If <see cref="WideNet"/> is enabled, actual transfer rate will be much higher. /// Target volume to transfer. If <see cref="WideNet"/> is enabled, actual transfer rate will be much higher.
@@ -25,15 +25,14 @@ namespace Content.Server.Atmos.Piping.Unary.Components
private float _transferRate = 50; private float _transferRate = 50;
[ViewVariables(VVAccess.ReadWrite)] [DataField]
[DataField("maxTransferRate")]
public float MaxTransferRate = Atmospherics.MaxTransferRate; public float MaxTransferRate = Atmospherics.MaxTransferRate;
[DataField("maxPressure")] [DataField]
[GuidebookData] [GuidebookData]
public float MaxPressure { get; set; } = GasVolumePumpComponent.DefaultHigherThreshold; public float MaxPressure = GasVolumePumpComponent.DefaultHigherThreshold;
[DataField("inlet")] [DataField("inlet")]
public string InletName { get; set; } = "pipe"; public string InletName = "pipe";
} }
} }

View File

@@ -0,0 +1,36 @@
using Content.Shared.Atmos.Piping.Binary.Systems;
using Robust.Shared.Audio;
using Robust.Shared.GameStates;
namespace Content.Shared.Atmos.Piping.Binary.Components;
/// <summary>
/// Component for manual atmospherics pumps that can open or close to let gas through.
/// </summary>
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(SharedGasValveSystem))]
public sealed partial class GasValveComponent : Component
{
/// <summary>
/// Whether the valve is currently open and letting gas through.
/// </summary>
[DataField, AutoNetworkedField, ViewVariables(VVAccess.ReadOnly)]
public bool Open = true;
/// <summary>
/// Inlet for the nodecontainer.
/// </summary>
[DataField("inlet")]
public string InletName = "inlet";
/// <summary>
/// Outlet for the nodecontainer.
/// </summary>
[DataField("outlet")]
public string OutletName = "outlet";
/// <summary>
/// Sound when <see cref="Open"/> is toggled.
/// </summary>
[DataField]
public SoundSpecifier ValveSound = new SoundCollectionSpecifier("valveSqueak");
}

View File

@@ -0,0 +1,68 @@
using Content.Shared.Atmos.Piping.Binary.Components;
using Content.Shared.Examine;
using Content.Shared.Interaction;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
namespace Content.Shared.Atmos.Piping.Binary.Systems;
public abstract class SharedGasValveSystem : EntitySystem
{
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<GasValveComponent, ComponentStartup>(OnStartup);
SubscribeLocalEvent<GasValveComponent, ActivateInWorldEvent>(OnActivate);
SubscribeLocalEvent<GasValveComponent, ExaminedEvent>(OnExamined);
}
private void OnStartup(Entity<GasValveComponent> ent, ref ComponentStartup args)
{
// We call set in startup so it sets the appearance, node state, etc.
Set(ent.Owner, ent.Comp, ent.Comp.Open);
}
public virtual void Set(EntityUid uid, GasValveComponent component, bool value)
{
component.Open = value;
Dirty(uid, component);
if (TryComp<AppearanceComponent>(uid, out var appearance))
{
_appearance.SetData(uid, FilterVisuals.Enabled, component.Open, appearance);
}
}
public void Toggle(EntityUid uid, GasValveComponent component)
{
Set(uid, component, !component.Open);
}
private void OnActivate(Entity<GasValveComponent> ent, ref ActivateInWorldEvent args)
{
if (args.Handled || !args.Complex)
return;
Toggle(ent.Owner, ent.Comp);
_audio.PlayPredicted(ent.Comp.ValveSound, ent.Owner, args.User, AudioParams.Default.WithVariation(0.25f));
args.Handled = true;
}
private void OnExamined(Entity<GasValveComponent> ent, ref ExaminedEvent args)
{
var valve = ent.Comp;
if (!Transform(ent).Anchored)
return;
if (Loc.TryGetString("gas-valve-system-examined", out var str,
("statusColor", valve.Open ? "green" : "orange"),
("open", valve.Open)))
{
args.PushMarkup(str);
}
}
}