Power Monitoring Console (#7849)
This commit is contained in:
@@ -138,6 +138,7 @@ namespace Content.Client.Entry
|
|||||||
"Flash",
|
"Flash",
|
||||||
"Docking",
|
"Docking",
|
||||||
"Telecrystal",
|
"Telecrystal",
|
||||||
|
"PowerMonitoringConsole",
|
||||||
"RCD",
|
"RCD",
|
||||||
"RCDAmmo",
|
"RCDAmmo",
|
||||||
"CursedEntityStorage",
|
"CursedEntityStorage",
|
||||||
|
|||||||
20
Content.Client/Power/PowerMonitoringWindow.xaml
Normal file
20
Content.Client/Power/PowerMonitoringWindow.xaml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<DefaultWindow
|
||||||
|
xmlns="https://spacestation14.io"
|
||||||
|
Title="{Loc 'power-monitoring-window-title'}">
|
||||||
|
<BoxContainer Orientation="Vertical" VerticalExpand="True">
|
||||||
|
<GridContainer Columns="2">
|
||||||
|
<!-- Grid is used here to align things. -->
|
||||||
|
<Label Text="{Loc 'power-monitoring-window-total-sources'}"/><Label Name="TotalSourcesNum" Text="?"/>
|
||||||
|
<Label Text="{Loc 'power-monitoring-window-total-loads'}"/><Label Name="TotalLoadsNum" Text="?"/>
|
||||||
|
</GridContainer>
|
||||||
|
<TabContainer Name="MasterTabContainer" VerticalExpand="True">
|
||||||
|
<ItemList Name="SourcesList" VerticalExpand="True">
|
||||||
|
</ItemList>
|
||||||
|
<BoxContainer Orientation="Vertical" VerticalExpand="True">
|
||||||
|
<CheckBox Margin="8 8" Name="ShowInactiveConsumersCheckBox" Text="{Loc 'power-monitoring-window-show-inactive-consumers'}" />
|
||||||
|
<ItemList Name="LoadsList" VerticalExpand="True">
|
||||||
|
</ItemList>
|
||||||
|
</BoxContainer>
|
||||||
|
</TabContainer>
|
||||||
|
</BoxContainer>
|
||||||
|
</DefaultWindow>
|
||||||
85
Content.Client/Power/PowerMonitoringWindow.xaml.cs
Normal file
85
Content.Client/Power/PowerMonitoringWindow.xaml.cs
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using Content.Client.Computer;
|
||||||
|
using Content.Client.IoC;
|
||||||
|
using Content.Shared.Power;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using Robust.Client.AutoGenerated;
|
||||||
|
using Robust.Client.GameObjects;
|
||||||
|
using Robust.Client.Graphics;
|
||||||
|
using Robust.Client.UserInterface;
|
||||||
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
using Robust.Client.UserInterface.CustomControls;
|
||||||
|
using Robust.Client.UserInterface.XAML;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Localization;
|
||||||
|
using Robust.Shared.Maths;
|
||||||
|
using Robust.Shared.Timing;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Client.Power;
|
||||||
|
|
||||||
|
[GenerateTypedNameReferences]
|
||||||
|
public sealed partial class PowerMonitoringWindow : DefaultWindow, IComputerWindow<PowerMonitoringConsoleBoundInterfaceState>
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
|
|
||||||
|
public PowerMonitoringWindow()
|
||||||
|
{
|
||||||
|
RobustXamlLoader.Load(this);
|
||||||
|
SetSize = MinSize = (300, 450);
|
||||||
|
IoCManager.InjectDependencies(this);
|
||||||
|
MasterTabContainer.SetTabTitle(0, Loc.GetString("power-monitoring-window-tab-sources"));
|
||||||
|
MasterTabContainer.SetTabTitle(1, Loc.GetString("power-monitoring-window-tab-loads"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateState(PowerMonitoringConsoleBoundInterfaceState scc)
|
||||||
|
{
|
||||||
|
UpdateList(TotalSourcesNum, scc.TotalSources, SourcesList, scc.Sources);
|
||||||
|
var loads = scc.Loads;
|
||||||
|
if (!ShowInactiveConsumersCheckBox.Pressed)
|
||||||
|
{
|
||||||
|
// Not showing inactive consumers, so hiding them.
|
||||||
|
// This means filtering out loads that are not either:
|
||||||
|
// + Batteries (always important)
|
||||||
|
// + Meaningful (size above 0)
|
||||||
|
loads = loads.Where(a => a.IsBattery || (a.Size > 0.0f)).ToArray();
|
||||||
|
}
|
||||||
|
UpdateList(TotalLoadsNum, scc.TotalLoads, LoadsList, loads);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateList(Label number, double numberVal, ItemList list, PowerMonitoringConsoleEntry[] listVal)
|
||||||
|
{
|
||||||
|
number.Text = Loc.GetString("power-monitoring-window-value", ("value", numberVal));
|
||||||
|
// This magic is important to prevent scrolling issues.
|
||||||
|
while (list.Count > listVal.Length)
|
||||||
|
{
|
||||||
|
list.RemoveAt(list.Count - 1);
|
||||||
|
}
|
||||||
|
while (list.Count < listVal.Length)
|
||||||
|
{
|
||||||
|
list.AddItem("YOU SHOULD NEVER SEE THIS (REALLY!)", null, false);
|
||||||
|
}
|
||||||
|
// Now overwrite the items properly...
|
||||||
|
for (var i = 0; i < listVal.Length; i++)
|
||||||
|
{
|
||||||
|
var ent = listVal[i];
|
||||||
|
_prototypeManager.TryIndex(ent.IconEntityPrototypeId, out EntityPrototype? entityPrototype);
|
||||||
|
IRsiStateLike? iconState = null;
|
||||||
|
if (entityPrototype != null)
|
||||||
|
iconState = SpriteComponent.GetPrototypeIcon(entityPrototype, StaticIoC.ResC);
|
||||||
|
var icon = iconState?.GetFrame(RSI.State.Direction.South, 0);
|
||||||
|
var item = list[i];
|
||||||
|
item.Text = $"{ent.NameLocalized} {Loc.GetString("power-monitoring-window-value", ("value", ent.Size))}";
|
||||||
|
item.Icon = icon;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[UsedImplicitly]
|
||||||
|
public sealed class PowerMonitoringConsoleBoundUserInterface : ComputerBoundUserInterface<PowerMonitoringWindow, PowerMonitoringConsoleBoundInterfaceState>
|
||||||
|
{
|
||||||
|
public PowerMonitoringConsoleBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey) {}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Content.Server.Power.NodeGroups;
|
||||||
|
using Content.Server.Utility;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.ViewVariables;
|
||||||
|
|
||||||
|
namespace Content.Server.Power.Components;
|
||||||
|
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed class PowerMonitoringConsoleComponent : Component
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
using Content.Shared.Popups;
|
||||||
|
using Content.Shared.Power;
|
||||||
|
using Content.Server.NodeContainer;
|
||||||
|
using Content.Server.NodeContainer.Nodes;
|
||||||
|
using Content.Server.Power.Components;
|
||||||
|
using Content.Server.Power.NodeGroups;
|
||||||
|
using Content.Server.UserInterface;
|
||||||
|
using Content.Server.WireHacking;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
|
|
||||||
|
namespace Content.Server.Power.EntitySystems;
|
||||||
|
|
||||||
|
[UsedImplicitly]
|
||||||
|
internal sealed class PowerMonitoringConsoleSystem : EntitySystem
|
||||||
|
{
|
||||||
|
private float _updateTimer = 0.0f;
|
||||||
|
private const float UpdateTime = 1.0f;
|
||||||
|
|
||||||
|
[Dependency]
|
||||||
|
private UserInterfaceSystem _userInterfaceSystem = default!;
|
||||||
|
|
||||||
|
public override void Update(float frameTime)
|
||||||
|
{
|
||||||
|
_updateTimer += frameTime;
|
||||||
|
if (_updateTimer >= UpdateTime)
|
||||||
|
{
|
||||||
|
_updateTimer -= UpdateTime;
|
||||||
|
foreach (var component in EntityQuery<PowerMonitoringConsoleComponent>())
|
||||||
|
{
|
||||||
|
UpdateUIState(component.Owner, component);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateUIState(EntityUid target, PowerMonitoringConsoleComponent? pmcComp = null, NodeContainerComponent? ncComp = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(target, ref pmcComp))
|
||||||
|
return;
|
||||||
|
if (!Resolve(target, ref ncComp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var totalSources = 0.0d;
|
||||||
|
var totalLoads = 0.0d;
|
||||||
|
var sources = new List<PowerMonitoringConsoleEntry>();
|
||||||
|
var loads = new List<PowerMonitoringConsoleEntry>();
|
||||||
|
PowerMonitoringConsoleEntry LoadOrSource(Component comp, double rate, bool isBattery)
|
||||||
|
{
|
||||||
|
var md = MetaData(comp.Owner);
|
||||||
|
var prototype = md.EntityPrototype?.ID ?? "";
|
||||||
|
return new PowerMonitoringConsoleEntry(md.EntityName, prototype, rate, isBattery);
|
||||||
|
}
|
||||||
|
// Right, so, here's what needs to be considered here.
|
||||||
|
var netQ = ncComp.GetNode<Node>("hv").NodeGroup as PowerNet;
|
||||||
|
if (netQ != null)
|
||||||
|
{
|
||||||
|
var net = netQ!;
|
||||||
|
foreach (PowerConsumerComponent pcc in net.Consumers)
|
||||||
|
{
|
||||||
|
loads.Add(LoadOrSource(pcc, pcc.DrawRate, false));
|
||||||
|
totalLoads += pcc.DrawRate;
|
||||||
|
}
|
||||||
|
foreach (BatteryChargerComponent pcc in net.Chargers)
|
||||||
|
{
|
||||||
|
if (!TryComp(pcc.Owner, out PowerNetworkBatteryComponent? batteryComp))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var rate = batteryComp.NetworkBattery.CurrentReceiving;
|
||||||
|
loads.Add(LoadOrSource(pcc, rate, true));
|
||||||
|
totalLoads += rate;
|
||||||
|
}
|
||||||
|
foreach (PowerSupplierComponent pcc in net.Suppliers)
|
||||||
|
{
|
||||||
|
sources.Add(LoadOrSource(pcc, pcc.MaxSupply, false));
|
||||||
|
totalSources += pcc.MaxSupply;
|
||||||
|
}
|
||||||
|
foreach (BatteryDischargerComponent pcc in net.Dischargers)
|
||||||
|
{
|
||||||
|
if (!TryComp(pcc.Owner, out PowerNetworkBatteryComponent? batteryComp))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var rate = batteryComp.NetworkBattery.CurrentSupply;
|
||||||
|
sources.Add(LoadOrSource(pcc, rate, true));
|
||||||
|
totalSources += rate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Sort
|
||||||
|
loads.Sort(CompareLoadOrSources);
|
||||||
|
sources.Sort(CompareLoadOrSources);
|
||||||
|
// Actually set state.
|
||||||
|
var state = new PowerMonitoringConsoleBoundInterfaceState(totalSources, totalLoads, sources.ToArray(), loads.ToArray());
|
||||||
|
_userInterfaceSystem.GetUiOrNull(target, PowerMonitoringConsoleUiKey.Key)?.SetState(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int CompareLoadOrSources(PowerMonitoringConsoleEntry x, PowerMonitoringConsoleEntry y)
|
||||||
|
{
|
||||||
|
return -x.Size.CompareTo(y.Size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Maths;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
|
namespace Content.Shared.Power;
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class PowerMonitoringConsoleBoundInterfaceState : BoundUserInterfaceState
|
||||||
|
{
|
||||||
|
public double TotalSources;
|
||||||
|
public double TotalLoads;
|
||||||
|
public PowerMonitoringConsoleEntry[] Sources;
|
||||||
|
public PowerMonitoringConsoleEntry[] Loads;
|
||||||
|
public PowerMonitoringConsoleBoundInterfaceState(double totalSources, double totalLoads, PowerMonitoringConsoleEntry[] sources, PowerMonitoringConsoleEntry[] loads)
|
||||||
|
{
|
||||||
|
TotalSources = totalSources;
|
||||||
|
TotalLoads = totalLoads;
|
||||||
|
Sources = sources;
|
||||||
|
Loads = loads;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class PowerMonitoringConsoleEntry
|
||||||
|
{
|
||||||
|
public string NameLocalized;
|
||||||
|
public string IconEntityPrototypeId;
|
||||||
|
public double Size;
|
||||||
|
public bool IsBattery;
|
||||||
|
public PowerMonitoringConsoleEntry(string nl, string ipi, double size, bool isBattery)
|
||||||
|
{
|
||||||
|
NameLocalized = nl;
|
||||||
|
IconEntityPrototypeId = ipi;
|
||||||
|
Size = size;
|
||||||
|
IsBattery = isBattery;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public enum PowerMonitoringConsoleUiKey
|
||||||
|
{
|
||||||
|
Key
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
power-monitoring-window-title = Power Monitoring Console
|
||||||
|
power-monitoring-window-tab-sources = Sources
|
||||||
|
power-monitoring-window-tab-loads = Loads
|
||||||
|
power-monitoring-window-total-sources = Total Sources:
|
||||||
|
power-monitoring-window-total-loads = Total Loads:
|
||||||
|
power-monitoring-window-value = { POWERWATTS($value) }
|
||||||
|
power-monitoring-window-show-inactive-consumers = Show Inactive Consumers
|
||||||
|
|
||||||
@@ -66,6 +66,14 @@
|
|||||||
- type: ComputerBoard
|
- type: ComputerBoard
|
||||||
prototype: ComputerSupplyRequest
|
prototype: ComputerSupplyRequest
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: BaseComputerCircuitboard
|
||||||
|
id: PowerMonitoringComputerCircuitboard
|
||||||
|
name: power monitoring computer board
|
||||||
|
components:
|
||||||
|
- type: ComputerBoard
|
||||||
|
prototype: ComputerPowerMonitoring
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseComputerCircuitboard
|
parent: BaseComputerCircuitboard
|
||||||
id: ResearchComputerCircuitboard
|
id: ResearchComputerCircuitboard
|
||||||
|
|||||||
@@ -75,6 +75,19 @@
|
|||||||
color: "#c9c042"
|
color: "#c9c042"
|
||||||
- type: Computer
|
- type: Computer
|
||||||
board: PowerComputerCircuitboard
|
board: PowerComputerCircuitboard
|
||||||
|
- type: PowerMonitoringConsole
|
||||||
|
- type: NodeContainer
|
||||||
|
examinable: true
|
||||||
|
nodes:
|
||||||
|
hv:
|
||||||
|
!type:CableDeviceNode
|
||||||
|
nodeGroupID: HVPower
|
||||||
|
- type: ActivatableUI
|
||||||
|
key: enum.PowerMonitoringConsoleUiKey.Key
|
||||||
|
- type: UserInterface
|
||||||
|
interfaces:
|
||||||
|
- key: enum.PowerMonitoringConsoleUiKey.Key
|
||||||
|
type: PowerMonitoringConsoleBoundUserInterface
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ComputerBase
|
parent: ComputerBase
|
||||||
|
|||||||
Reference in New Issue
Block a user