Predict gasthermomachines (#33837)
* Predict gasthermomachines * despawn * smellby
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
using Content.Client.Atmos.UI;
|
||||
using Content.Shared.Atmos.Piping.Unary.Components;
|
||||
using Content.Shared.Atmos.Piping.Unary.Systems;
|
||||
|
||||
namespace Content.Client.Atmos.Piping.Unary.Systems;
|
||||
|
||||
public sealed class GasThermoMachineSystem : SharedGasThermoMachineSystem
|
||||
{
|
||||
[Dependency] private readonly SharedUserInterfaceSystem _ui = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<GasThermoMachineComponent, AfterAutoHandleStateEvent>(OnGasAfterState);
|
||||
}
|
||||
|
||||
private void OnGasAfterState(Entity<GasThermoMachineComponent> ent, ref AfterAutoHandleStateEvent args)
|
||||
{
|
||||
DirtyUI(ent.Owner, ent.Comp);
|
||||
}
|
||||
|
||||
protected override void DirtyUI(EntityUid uid, GasThermoMachineComponent? thermoMachine, UserInterfaceComponent? ui = null)
|
||||
{
|
||||
if (_ui.TryGetOpenUi<GasThermomachineBoundUserInterface>(uid, ThermomachineUiKey.Key, out var bui))
|
||||
{
|
||||
bui.Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Client.Power.EntitySystems;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Atmos.Piping.Unary.Components;
|
||||
using Content.Shared.Atmos.Piping.Unary.Systems;
|
||||
using Content.Shared.Power.Components;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.UserInterface;
|
||||
@@ -36,6 +39,8 @@ namespace Content.Client.Atmos.UI
|
||||
|
||||
_window.ToggleStatusButton.OnPressed += _ => OnToggleStatusButtonPressed();
|
||||
_window.TemperatureSpinbox.OnValueChanged += _ => OnTemperatureChanged(_window.TemperatureSpinbox.Value);
|
||||
_window.Entity = Owner;
|
||||
Update();
|
||||
}
|
||||
|
||||
private void OnToggleStatusButtonPressed()
|
||||
@@ -43,7 +48,7 @@ namespace Content.Client.Atmos.UI
|
||||
if (_window is null) return;
|
||||
|
||||
_window.SetActive(!_window.Active);
|
||||
SendMessage(new GasThermomachineToggleMessage());
|
||||
SendPredictedMessage(new GasThermomachineToggleMessage());
|
||||
}
|
||||
|
||||
private void OnTemperatureChanged(float value)
|
||||
@@ -60,25 +65,32 @@ namespace Content.Client.Atmos.UI
|
||||
return;
|
||||
}
|
||||
|
||||
SendMessage(new GasThermomachineChangeTemperatureMessage(actual));
|
||||
SendPredictedMessage(new GasThermomachineChangeTemperatureMessage(actual));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the UI state based on server-sent info
|
||||
/// </summary>
|
||||
/// <param name="state"></param>
|
||||
protected override void UpdateState(BoundUserInterfaceState state)
|
||||
public override void Update()
|
||||
{
|
||||
base.UpdateState(state);
|
||||
if (_window == null || state is not GasThermomachineBoundUserInterfaceState cast)
|
||||
if (_window == null || !EntMan.TryGetComponent(Owner, out GasThermoMachineComponent? thermo))
|
||||
return;
|
||||
|
||||
_minTemp = cast.MinTemperature;
|
||||
_maxTemp = cast.MaxTemperature;
|
||||
_isHeater = cast.IsHeater;
|
||||
var system = EntMan.System<SharedGasThermoMachineSystem>();
|
||||
_minTemp = thermo.MinTemperature;
|
||||
_maxTemp = thermo.MaxTemperature;
|
||||
_isHeater = system.IsHeater(thermo);
|
||||
|
||||
_window.SetTemperature(thermo.TargetTemperature);
|
||||
|
||||
var receiverSys = EntMan.System<PowerReceiverSystem>();
|
||||
SharedApcPowerReceiverComponent? receiver = null;
|
||||
|
||||
receiverSys.ResolveApc(Owner, ref receiver);
|
||||
|
||||
// Also set in frameupdates.
|
||||
if (receiver != null)
|
||||
{
|
||||
_window.SetActive(!receiver.PowerDisabled);
|
||||
}
|
||||
|
||||
_window.SetTemperature(cast.Temperature);
|
||||
_window.SetActive(cast.Enabled);
|
||||
_window.Title = _isHeater switch
|
||||
{
|
||||
false => Loc.GetString("comp-gas-thermomachine-ui-title-freezer"),
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<DefaultWindow xmlns="https://spacestation14.io"
|
||||
<controls:FancyWindow xmlns="https://spacestation14.io"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
MinSize="300 120" Title="{Loc comp-gas-thermomachine-ui-title-freezer}">
|
||||
<BoxContainer Name="VboxContainer" Orientation="Vertical" Margin="5 5 5 5" SeparationOverride="10">
|
||||
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
|
||||
@@ -11,4 +12,4 @@
|
||||
<Label Text="{Loc comp-gas-thermomachine-ui-temperature}"/>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</DefaultWindow>
|
||||
</controls:FancyWindow>
|
||||
|
||||
@@ -1,19 +1,26 @@
|
||||
using Content.Client.Power.Components;
|
||||
using Content.Client.UserInterface.Controls;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Client.Atmos.UI;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class GasThermomachineWindow : DefaultWindow
|
||||
public sealed partial class GasThermomachineWindow : FancyWindow
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entManager = default!;
|
||||
|
||||
public bool Active = true;
|
||||
|
||||
public FloatSpinBox TemperatureSpinbox;
|
||||
|
||||
public EntityUid Entity;
|
||||
|
||||
public GasThermomachineWindow()
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
RobustXamlLoader.Load(this);
|
||||
|
||||
SpinboxHBox.AddChild(
|
||||
@@ -27,12 +34,10 @@ public sealed partial class GasThermomachineWindow : DefaultWindow
|
||||
if (active)
|
||||
{
|
||||
ToggleStatusButton.Text = Loc.GetString("comp-gas-thermomachine-ui-status-enabled");
|
||||
ToggleStatusButton.Pressed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ToggleStatusButton.Text = Loc.GetString("comp-gas-thermomachine-ui-status-disabled");
|
||||
ToggleStatusButton.Pressed = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,4 +45,14 @@ public sealed partial class GasThermomachineWindow : DefaultWindow
|
||||
{
|
||||
TemperatureSpinbox.Value = temperature;
|
||||
}
|
||||
|
||||
protected override void FrameUpdate(FrameEventArgs args)
|
||||
{
|
||||
base.FrameUpdate(args);
|
||||
|
||||
if (_entManager.TryGetComponent(Entity, out ApcPowerReceiverComponent? receiver))
|
||||
{
|
||||
SetActive(!receiver.PowerDisabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
5
Content.Client/NodeContainer/NodeContainerSystem.cs
Normal file
5
Content.Client/NodeContainer/NodeContainerSystem.cs
Normal file
@@ -0,0 +1,5 @@
|
||||
using Content.Shared.NodeContainer;
|
||||
|
||||
namespace Content.Client.NodeContainer;
|
||||
|
||||
public sealed class NodeContainerSystem : SharedNodeContainerSystem;
|
||||
@@ -1,8 +1,19 @@
|
||||
using Content.Client.Power.Components;
|
||||
using Content.Shared.Power.Components;
|
||||
using Content.Shared.Power.EntitySystems;
|
||||
|
||||
namespace Content.Client.Power.EntitySystems;
|
||||
|
||||
public sealed class PowerNetSystem : SharedPowerNetSystem
|
||||
{
|
||||
public override bool IsPoweredCalculate(SharedApcPowerReceiverComponent comp)
|
||||
{
|
||||
return IsPoweredCalculate((ApcPowerReceiverComponent)comp);
|
||||
}
|
||||
|
||||
private bool IsPoweredCalculate(ApcPowerReceiverComponent comp)
|
||||
{
|
||||
return !comp.PowerDisabled
|
||||
&& !comp.NeedsPower;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,11 +9,8 @@ using Content.Server.Power.Components;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Atmos.Piping.Unary.Components;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Server.GameObjects;
|
||||
using Content.Server.Power.EntitySystems;
|
||||
using Content.Shared.UserInterface;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.Atmos.Piping.Unary.Systems;
|
||||
using Content.Shared.DeviceNetwork;
|
||||
using Content.Shared.DeviceNetwork.Events;
|
||||
using Content.Shared.Examine;
|
||||
@@ -22,36 +19,23 @@ using Content.Shared.DeviceNetwork.Components;
|
||||
namespace Content.Server.Atmos.Piping.Unary.EntitySystems
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public sealed class GasThermoMachineSystem : EntitySystem
|
||||
public sealed class GasThermoMachineSystem : SharedGasThermoMachineSystem
|
||||
{
|
||||
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
||||
[Dependency] private readonly UserInterfaceSystem _userInterfaceSystem = default!;
|
||||
[Dependency] private readonly PowerReceiverSystem _power = default!;
|
||||
[Dependency] private readonly NodeContainerSystem _nodeContainer = default!;
|
||||
[Dependency] private readonly DeviceNetworkSystem _deviceNetwork = default!;
|
||||
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<GasThermoMachineComponent, AtmosDeviceUpdateEvent>(OnThermoMachineUpdated);
|
||||
SubscribeLocalEvent<GasThermoMachineComponent, ExaminedEvent>(OnExamined);
|
||||
|
||||
// UI events
|
||||
SubscribeLocalEvent<GasThermoMachineComponent, BeforeActivatableUIOpenEvent>(OnBeforeOpened);
|
||||
SubscribeLocalEvent<GasThermoMachineComponent, GasThermomachineToggleMessage>(OnToggleMessage);
|
||||
SubscribeLocalEvent<GasThermoMachineComponent, GasThermomachineChangeTemperatureMessage>(OnChangeTemperature);
|
||||
|
||||
// Device network
|
||||
SubscribeLocalEvent<GasThermoMachineComponent, DeviceNetworkPacketEvent>(OnPacketRecv);
|
||||
}
|
||||
|
||||
private void OnBeforeOpened(Entity<GasThermoMachineComponent> ent, ref BeforeActivatableUIOpenEvent args)
|
||||
{
|
||||
DirtyUI(ent, ent.Comp);
|
||||
}
|
||||
|
||||
private void OnThermoMachineUpdated(EntityUid uid, GasThermoMachineComponent thermoMachine, ref AtmosDeviceUpdateEvent args)
|
||||
{
|
||||
thermoMachine.LastEnergyDelta = 0f;
|
||||
@@ -135,56 +119,6 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsHeater(GasThermoMachineComponent comp)
|
||||
{
|
||||
return comp.Cp >= 0;
|
||||
}
|
||||
|
||||
private void OnToggleMessage(EntityUid uid, GasThermoMachineComponent thermoMachine, GasThermomachineToggleMessage args)
|
||||
{
|
||||
var powerState = _power.TogglePower(uid);
|
||||
_adminLogger.Add(LogType.AtmosPowerChanged, $"{ToPrettyString(args.Actor)} turned {(powerState ? "On" : "Off")} {ToPrettyString(uid)}");
|
||||
DirtyUI(uid, thermoMachine);
|
||||
}
|
||||
|
||||
private void OnChangeTemperature(EntityUid uid, GasThermoMachineComponent thermoMachine, GasThermomachineChangeTemperatureMessage args)
|
||||
{
|
||||
if (IsHeater(thermoMachine))
|
||||
thermoMachine.TargetTemperature = MathF.Min(args.Temperature, thermoMachine.MaxTemperature);
|
||||
else
|
||||
thermoMachine.TargetTemperature = MathF.Max(args.Temperature, thermoMachine.MinTemperature);
|
||||
thermoMachine.TargetTemperature = MathF.Max(thermoMachine.TargetTemperature, Atmospherics.TCMB);
|
||||
_adminLogger.Add(LogType.AtmosTemperatureChanged, $"{ToPrettyString(args.Actor)} set temperature on {ToPrettyString(uid)} to {thermoMachine.TargetTemperature}");
|
||||
DirtyUI(uid, thermoMachine);
|
||||
}
|
||||
|
||||
private void DirtyUI(EntityUid uid, GasThermoMachineComponent? thermoMachine, UserInterfaceComponent? ui=null)
|
||||
{
|
||||
if (!Resolve(uid, ref thermoMachine, ref ui, false))
|
||||
return;
|
||||
|
||||
ApcPowerReceiverComponent? powerReceiver = null;
|
||||
if (!Resolve(uid, ref powerReceiver))
|
||||
return;
|
||||
|
||||
_userInterfaceSystem.SetUiState(uid, ThermomachineUiKey.Key,
|
||||
new GasThermomachineBoundUserInterfaceState(thermoMachine.MinTemperature, thermoMachine.MaxTemperature, thermoMachine.TargetTemperature, !powerReceiver.PowerDisabled, IsHeater(thermoMachine)));
|
||||
}
|
||||
|
||||
private void OnExamined(EntityUid uid, GasThermoMachineComponent thermoMachine, ExaminedEvent args)
|
||||
{
|
||||
if (!args.IsInDetailsRange)
|
||||
return;
|
||||
|
||||
if (Loc.TryGetString("gas-thermomachine-system-examined", out var str,
|
||||
("machineName", !IsHeater(thermoMachine) ? "freezer" : "heater"),
|
||||
("tempColor", !IsHeater(thermoMachine) ? "deepskyblue" : "red"),
|
||||
("temp", Math.Round(thermoMachine.TargetTemperature,2))
|
||||
))
|
||||
|
||||
args.PushMarkup(str);
|
||||
}
|
||||
|
||||
private void OnPacketRecv(EntityUid uid, GasThermoMachineComponent component, DeviceNetworkPacketEvent args)
|
||||
{
|
||||
if (!TryComp(uid, out DeviceNetworkComponent? netConn)
|
||||
|
||||
@@ -5,6 +5,7 @@ using Content.Server.Popups;
|
||||
using Content.Server.Power.Components;
|
||||
using Content.Server.Power.EntitySystems;
|
||||
using Content.Shared.Atmos.Piping.Portable.Components;
|
||||
using Content.Shared.Atmos.Piping.Unary.Components;
|
||||
using Content.Shared.Atmos.Visuals;
|
||||
using Content.Shared.Power;
|
||||
using Content.Shared.UserInterface;
|
||||
@@ -41,6 +42,7 @@ public sealed class SpaceHeaterSystem : EntitySystem
|
||||
{
|
||||
if (!TryComp<GasThermoMachineComponent>(uid, out var thermoMachine))
|
||||
return;
|
||||
|
||||
thermoMachine.Cp = spaceHeater.HeatingCp;
|
||||
thermoMachine.HeatCapacity = spaceHeater.PowerConsumption;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Content.Server.NodeContainer.EntitySystems
|
||||
/// </summary>
|
||||
/// <seealso cref="NodeGroupSystem"/>
|
||||
[UsedImplicitly]
|
||||
public sealed class NodeContainerSystem : EntitySystem
|
||||
public sealed class NodeContainerSystem : SharedNodeContainerSystem
|
||||
{
|
||||
[Dependency] private readonly NodeGroupSystem _nodeGroupSystem = default!;
|
||||
private EntityQuery<NodeContainerComponent> _query;
|
||||
|
||||
@@ -31,7 +31,6 @@ namespace Content.Server.Power.EntitySystems
|
||||
private readonly HashSet<ApcNet> _apcNetReconnectQueue = new();
|
||||
|
||||
private EntityQuery<ApcPowerReceiverBatteryComponent> _apcBatteryQuery;
|
||||
private EntityQuery<AppearanceComponent> _appearanceQuery;
|
||||
private EntityQuery<BatteryComponent> _batteryQuery;
|
||||
|
||||
private BatteryRampPegSolver _solver = new();
|
||||
@@ -41,7 +40,6 @@ namespace Content.Server.Power.EntitySystems
|
||||
base.Initialize();
|
||||
|
||||
_apcBatteryQuery = GetEntityQuery<ApcPowerReceiverBatteryComponent>();
|
||||
_appearanceQuery = GetEntityQuery<AppearanceComponent>();
|
||||
_batteryQuery = GetEntityQuery<BatteryComponent>();
|
||||
|
||||
UpdatesAfter.Add(typeof(NodeGroupSystem));
|
||||
@@ -317,15 +315,25 @@ namespace Content.Server.Power.EntitySystems
|
||||
_powerNetReconnectQueue.Clear();
|
||||
}
|
||||
|
||||
private bool IsPoweredCalculate(ApcPowerReceiverComponent comp)
|
||||
{
|
||||
return !comp.PowerDisabled
|
||||
&& (!comp.NeedsPower
|
||||
|| MathHelper.CloseToPercent(comp.NetworkLoad.ReceivingPower,
|
||||
comp.Load));
|
||||
}
|
||||
|
||||
public override bool IsPoweredCalculate(SharedApcPowerReceiverComponent comp)
|
||||
{
|
||||
return IsPoweredCalculate((ApcPowerReceiverComponent)comp);
|
||||
}
|
||||
|
||||
private void UpdateApcPowerReceiver(float frameTime)
|
||||
{
|
||||
var enumerator = AllEntityQuery<ApcPowerReceiverComponent>();
|
||||
while (enumerator.MoveNext(out var uid, out var apcReceiver))
|
||||
{
|
||||
var powered = !apcReceiver.PowerDisabled
|
||||
&& (!apcReceiver.NeedsPower
|
||||
|| MathHelper.CloseToPercent(apcReceiver.NetworkLoad.ReceivingPower,
|
||||
apcReceiver.Load));
|
||||
var powered = IsPoweredCalculate(apcReceiver);
|
||||
|
||||
MetaDataComponent? metadata = null;
|
||||
|
||||
@@ -381,9 +389,6 @@ namespace Content.Server.Power.EntitySystems
|
||||
|
||||
var ev = new PowerChangedEvent(powered, apcReceiver.NetworkLoad.ReceivingPower);
|
||||
RaiseLocalEvent(uid, ref ev);
|
||||
|
||||
if (_appearanceQuery.TryComp(uid, out var appearance))
|
||||
_appearance.SetData(uid, PowerDeviceVisuals.Powered, powered, appearance);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Guidebook;
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Server.Atmos.Piping.Unary.Components
|
||||
namespace Content.Shared.Atmos.Piping.Unary.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true)]
|
||||
public sealed partial class GasThermoMachineComponent : Component
|
||||
{
|
||||
[DataField("inlet")]
|
||||
@@ -13,11 +14,11 @@ namespace Content.Server.Atmos.Piping.Unary.Components
|
||||
/// Current electrical power consumption, in watts. Increasing power increases the ability of the
|
||||
/// thermomachine to heat or cool air.
|
||||
/// </summary>
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField]
|
||||
[GuidebookData]
|
||||
public float HeatCapacity = 5000;
|
||||
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField, AutoNetworkedField]
|
||||
public float TargetTemperature = Atmospherics.T20C;
|
||||
|
||||
/// <summary>
|
||||
@@ -39,42 +40,41 @@ namespace Content.Server.Atmos.Piping.Unary.Components
|
||||
/// Positive for heaters, negative for freezers.
|
||||
/// </summary>
|
||||
[DataField("coefficientOfPerformance")]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public float Cp = 0.9f; // output power / input power, positive is heat
|
||||
|
||||
/// <summary>
|
||||
/// Current minimum temperature
|
||||
/// Ignored if heater.
|
||||
/// </summary>
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
[GuidebookData]
|
||||
[DataField, AutoNetworkedField]
|
||||
[GuidebookData]
|
||||
public float MinTemperature = 73.15f;
|
||||
|
||||
/// <summary>
|
||||
/// Current maximum temperature
|
||||
/// Ignored if freezer.
|
||||
/// </summary>
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
[GuidebookData]
|
||||
[DataField, AutoNetworkedField]
|
||||
[GuidebookData]
|
||||
public float MaxTemperature = 593.15f;
|
||||
|
||||
/// <summary>
|
||||
/// Last amount of energy added/removed from the attached pipe network
|
||||
/// </summary>
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField]
|
||||
public float LastEnergyDelta;
|
||||
|
||||
/// <summary>
|
||||
/// An percentage of the energy change that is leaked into the surrounding environment rather than the inlet pipe.
|
||||
/// </summary>
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
[GuidebookData]
|
||||
public float EnergyLeakPercentage;
|
||||
[DataField]
|
||||
[GuidebookData]
|
||||
public float EnergyLeakPercentage;
|
||||
|
||||
/// <summary>
|
||||
/// If true, heat is exclusively exchanged with the local atmosphere instead of the inlet pipe air
|
||||
/// </summary>
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
public bool Atmospheric = false;
|
||||
[DataField]
|
||||
public bool Atmospheric;
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ public sealed record GasThermoMachineData(float EnergyDelta);
|
||||
|
||||
[Serializable]
|
||||
[NetSerializable]
|
||||
public enum ThermomachineUiKey
|
||||
public enum ThermomachineUiKey : byte
|
||||
{
|
||||
Key
|
||||
}
|
||||
@@ -29,23 +29,3 @@ public sealed class GasThermomachineChangeTemperatureMessage : BoundUserInterfac
|
||||
Temperature = temperature;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
[NetSerializable]
|
||||
public sealed class GasThermomachineBoundUserInterfaceState : BoundUserInterfaceState
|
||||
{
|
||||
public float MinTemperature { get; }
|
||||
public float MaxTemperature { get; }
|
||||
public float Temperature { get; }
|
||||
public bool Enabled { get; }
|
||||
public bool IsHeater { get; }
|
||||
|
||||
public GasThermomachineBoundUserInterfaceState(float minTemperature, float maxTemperature, float temperature, bool enabled, bool isHeater)
|
||||
{
|
||||
MinTemperature = minTemperature;
|
||||
MaxTemperature = maxTemperature;
|
||||
Temperature = temperature;
|
||||
Enabled = enabled;
|
||||
IsHeater = isHeater;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.Atmos.Piping.Unary.Components;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Power.EntitySystems;
|
||||
|
||||
namespace Content.Shared.Atmos.Piping.Unary.Systems;
|
||||
|
||||
public abstract class SharedGasThermoMachineSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
|
||||
[Dependency] private readonly SharedPowerReceiverSystem _receiver = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<GasThermoMachineComponent, ExaminedEvent>(OnExamined);
|
||||
|
||||
SubscribeLocalEvent<GasThermoMachineComponent, GasThermomachineToggleMessage>(OnToggleMessage);
|
||||
SubscribeLocalEvent<GasThermoMachineComponent, GasThermomachineChangeTemperatureMessage>(OnChangeTemperature);
|
||||
}
|
||||
|
||||
private void OnExamined(EntityUid uid, GasThermoMachineComponent thermoMachine, ExaminedEvent args)
|
||||
{
|
||||
if (Loc.TryGetString("gas-thermomachine-system-examined",
|
||||
out var str,
|
||||
("machineName", !IsHeater(thermoMachine) ? "freezer" : "heater"),
|
||||
("tempColor", !IsHeater(thermoMachine) ? "deepskyblue" : "red"),
|
||||
("temp", Math.Round(thermoMachine.TargetTemperature, 2))
|
||||
))
|
||||
{
|
||||
args.PushMarkup(str);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsHeater(GasThermoMachineComponent comp)
|
||||
{
|
||||
return comp.Cp >= 0;
|
||||
}
|
||||
|
||||
private void OnToggleMessage(EntityUid uid, GasThermoMachineComponent thermoMachine, GasThermomachineToggleMessage args)
|
||||
{
|
||||
var powerState = _receiver.TogglePower(uid, user: args.Actor);
|
||||
_adminLogger.Add(LogType.AtmosPowerChanged, $"{ToPrettyString(args.Actor)} turned {(powerState ? "On" : "Off")} {ToPrettyString(uid)}");
|
||||
DirtyUI(uid, thermoMachine);
|
||||
}
|
||||
|
||||
private void OnChangeTemperature(EntityUid uid, GasThermoMachineComponent thermoMachine, GasThermomachineChangeTemperatureMessage args)
|
||||
{
|
||||
if (IsHeater(thermoMachine))
|
||||
thermoMachine.TargetTemperature = MathF.Min(args.Temperature, thermoMachine.MaxTemperature);
|
||||
else
|
||||
thermoMachine.TargetTemperature = MathF.Max(args.Temperature, thermoMachine.MinTemperature);
|
||||
thermoMachine.TargetTemperature = MathF.Max(thermoMachine.TargetTemperature, Atmospherics.TCMB);
|
||||
_adminLogger.Add(LogType.AtmosTemperatureChanged, $"{ToPrettyString(args.Actor)} set temperature on {ToPrettyString(uid)} to {thermoMachine.TargetTemperature}");
|
||||
Dirty(uid, thermoMachine);
|
||||
DirtyUI(uid, thermoMachine);
|
||||
}
|
||||
|
||||
protected virtual void DirtyUI(EntityUid uid, GasThermoMachineComponent? thermoMachine, UserInterfaceComponent? ui=null) {}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Content.Shared.NodeContainer;
|
||||
|
||||
public abstract class SharedNodeContainerSystem : EntitySystem
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,6 +1,21 @@
|
||||
using Content.Shared.Power.Components;
|
||||
|
||||
namespace Content.Shared.Power.EntitySystems;
|
||||
|
||||
public abstract class SharedPowerNetSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||
|
||||
public abstract bool IsPoweredCalculate(SharedApcPowerReceiverComponent comp);
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<AppearanceComponent, PowerChangedEvent>(OnPowerAppearance);
|
||||
}
|
||||
|
||||
private void OnPowerAppearance(Entity<AppearanceComponent> ent, ref PowerChangedEvent args)
|
||||
{
|
||||
_appearance.SetData(ent, PowerDeviceVisuals.Powered, args.Powered, ent.Comp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,13 +4,16 @@ using Content.Shared.Database;
|
||||
using Content.Shared.Power.Components;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Network;
|
||||
|
||||
namespace Content.Shared.Power.EntitySystems;
|
||||
|
||||
public abstract class SharedPowerReceiverSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly INetManager _netMan = default!;
|
||||
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] private readonly SharedPowerNetSystem _net = default!;
|
||||
|
||||
public abstract bool ResolveApc(EntityUid entity, [NotNullWhen(true)] ref SharedApcPowerReceiverComponent? component);
|
||||
|
||||
@@ -44,6 +47,15 @@ public abstract class SharedPowerReceiverSystem : EntitySystem
|
||||
// it'll save a lot of confusion if 'always powered' means 'always powered'
|
||||
if (!receiver.NeedsPower)
|
||||
{
|
||||
var powered = _net.IsPoweredCalculate(receiver);
|
||||
|
||||
// Server won't raise it here as it can raise the load event later with NeedsPower?
|
||||
// This is mostly here for clientside predictions.
|
||||
if (receiver.Powered != powered)
|
||||
{
|
||||
RaisePower((uid, receiver));
|
||||
}
|
||||
|
||||
SetPowerDisabled(uid, false, receiver);
|
||||
return true;
|
||||
}
|
||||
@@ -59,6 +71,19 @@ public abstract class SharedPowerReceiverSystem : EntitySystem
|
||||
AudioParams.Default.WithVolume(-2f));
|
||||
}
|
||||
|
||||
if (_netMan.IsClient && receiver.PowerDisabled)
|
||||
{
|
||||
var powered = _net.IsPoweredCalculate(receiver);
|
||||
|
||||
// Server won't raise it here as it can raise the load event later with NeedsPower?
|
||||
// This is mostly here for clientside predictions.
|
||||
if (receiver.Powered != powered)
|
||||
{
|
||||
receiver.Powered = powered;
|
||||
RaisePower((uid, receiver));
|
||||
}
|
||||
}
|
||||
|
||||
return !receiver.PowerDisabled; // i.e. PowerEnabled
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user