Skip to content

Commit

Permalink
WorkingMonitoringConsole
Browse files Browse the repository at this point in the history
  • Loading branch information
Alwayswannahunt committed Aug 17, 2024
1 parent a063398 commit 4acb236
Show file tree
Hide file tree
Showing 21 changed files with 430 additions and 127 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt
using Content.Shared.SS220.SuperMatter.Ui;

namespace Content.Client.SS220.SuperMatter.Observer;

[RegisterComponent]
public sealed partial class SuperMatterObserverComponent : Component
public sealed partial class SuperMatterObserverComponent : SharedSuperMatterObserverComponent
{
[ViewVariables(VVAccess.ReadOnly)]
public Dictionary<int, string> Names = new();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt
namespace Content.Client.SS220.SuperMatter.Observer;

/// <summary> We use this component to mark entities which can receiver </summary>
[RegisterComponent]
public sealed partial class SuperMatterObserverReceiverComponent() : Component { }
109 changes: 93 additions & 16 deletions Content.Client/SS220/SuperMatter/Observer/SuperMatterObserverSystem.cs
Original file line number Diff line number Diff line change
@@ -1,64 +1,141 @@
// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt
using Content.Client.Power.Components;
using Content.Shared.Mobs;
using Robust.Client.GameObjects;
using Content.Shared.SS220.SuperMatter.Ui;
using System.Linq;
using Content.Client.SS220.SuperMatter.Ui;
using Robust.Shared.Timing;

namespace Content.Client.SS220.SuperMatter.Observer;

public sealed class SuperMatterObserverSystem : EntitySystem
{
[Dependency] private readonly UserInterfaceSystem _userInterface = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly EntityLookupSystem _entityLookup = default!;
// 120 like 2 minutes with update rate 1 sec
public const int MAX_CACHED_AMOUNT = 120;
private List<Entity<SuperMatterObserverComponent>> _observerComps = new();
private const float UpdateDelay = 1f;
private HashSet<Entity<SuperMatterObserverComponent>> _observerEntities = new();
private List<EntityUid> _smReceiverUIOwnersToInit = new();
private TimeSpan _nextUpdateTime = default!;
private HashSet<Entity<SuperMatterObserverReceiverComponent>> _receivers = new();
public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<SuperMatterObserverComponent, ComponentInit>(OnComponentInit);
SubscribeLocalEvent<SuperMatterObserverComponent, ComponentRemove>(OnComponentRemove);

SubscribeLocalEvent<SuperMatterObserverReceiverComponent, BoundUIOpenedEvent>(OnReceiverBoundUIOpened);
SubscribeLocalEvent<SuperMatterObserverReceiverComponent, BoundUIClosedEvent>(OnReceiverBoundUIClosed);
SubscribeNetworkEvent<SuperMatterStateUpdate>(OnCrystalUpdate);
}
public override void FrameUpdate(float frameTime)
{
base.FrameUpdate(frameTime);

if (_gameTiming.CurTime > _nextUpdateTime)
{
// kinda simulate servers and clients working
_nextUpdateTime += TimeSpan.FromSeconds(UpdateDelay);
foreach (var smReceiverOwner in new List<EntityUid>(_smReceiverUIOwnersToInit))
{
if (!HasComp<TransformComponent>(smReceiverOwner)
|| Transform(smReceiverOwner).GridUid == null)
continue;

_entityLookup.GetChildEntities(Transform(smReceiverOwner).GridUid!.Value, _observerEntities);
foreach (var (observerUid, _) in _observerEntities)
{
if (TryComp<ApcPowerReceiverComponent>(observerUid, out var powerReceiver)
&& powerReceiver.Powered)
{
if (!_userInterface.HasUi(smReceiverOwner, SuperMatterObserverUiKey.Key))
return;
if (TrySendToUIState(smReceiverOwner,
new SuperMatterObserverInitState(new List<Entity<SuperMatterObserverComponent>>(_observerEntities))))
_smReceiverUIOwnersToInit.Remove(smReceiverOwner);
break;
}
}
_observerEntities.Clear();
}
}
}

private void OnCrystalUpdate(SuperMatterStateUpdate args)
{
// store values to simulate real working data observer&collectors manufacture
foreach (var observerEnt in _observerComps)
if (args.SMGridId == null)
return;
_entityLookup.GetChildEntities(EntityManager.GetEntity(args.SMGridId.Value), _observerEntities);
foreach (var observerEnt in _observerEntities)
{
// To make possible many SMs on different grids
var (observerUid, observerComp) = observerEnt;
if (!HasComp<TransformComponent>(observerUid))
continue;
if (Transform(observerUid).GridUid != EntityManager.GetEntity(args.SMGridId))
continue;
// still it will store without power, cause, you know... caching =)
observerComp.Names[args.Id] = args.Name;
observerComp.DelaminationStatuses[args.Id] = args.Delaminate;
if (!observerComp.Integrities.ContainsKey(args.Id))
{
observerComp.Integrities[args.Id] = new();
observerComp.Pressures[args.Id] = new();
observerComp.Temperatures[args.Id] = new();
observerComp.Matters[args.Id] = new();
observerComp.InternalEnergy[args.Id] = new();
}
AddToCacheList(observerComp.Integrities[args.Id], args.Integrity);
AddToCacheList(observerComp.Pressures[args.Id], args.Pressure);
AddToCacheList(observerComp.Temperatures[args.Id], args.Temperature);
AddToCacheList(observerComp.Matters[args.Id], args.Matter);
AddToCacheList(observerComp.InternalEnergy[args.Id], args.InternalEnergy);
// check if power is On on console
// here dispatches events to sprites of SM itself
// RaiseLocalEvent(GetIntegrityState changed then change sprite)
// check if console has power
if (!(TryComp<ApcPowerReceiverComponent>(observerUid, out var powerReceiver)
&& powerReceiver.Powered))
continue;
// Send updateStates for opened UIs and panels

// think of the same way as with _observerEntities, but will have problems if SMObserver will be on other maps etc
_entityLookup.GetEntitiesOnMap(Transform(observerUid).MapID, _receivers);
// logic
foreach (var receiver in _receivers)
TrySendToUIState(receiver.Owner, new SuperMatterObserverUpdateState(args.Id, args.Name, args.Integrity, args.Pressure,
args.Temperature, args.Matter, args.InternalEnergy, args.Delaminate));
_receivers.Clear();
// RaiseLocalEvent(SMpanels -> accept information)
}
_observerEntities.Clear();
}
private void OnComponentInit(Entity<SuperMatterObserverComponent> entity, ref ComponentInit args)
private void OnReceiverBoundUIOpened(Entity<SuperMatterObserverReceiverComponent> entity, ref BoundUIOpenedEvent args)
{
// very aware of client crashes
_observerComps.Add(entity);
_observerComps = _observerComps.Distinct().ToList();
if (!_userInterface.HasUi(entity, args.UiKey))
return;
_smReceiverUIOwnersToInit.Add(entity.Owner);

}
private void OnComponentRemove(Entity<SuperMatterObserverComponent> entity, ref ComponentRemove args)
private void OnReceiverBoundUIClosed(Entity<SuperMatterObserverReceiverComponent> entity, ref BoundUIClosedEvent args)
{
// very aware of client crashes
_observerComps = _observerComps.Distinct().ToList();
_observerComps.Remove(entity);
if (!_userInterface.HasUi(entity, args.UiKey))
return;
// Lest hope it wont duplicate
_smReceiverUIOwnersToInit.Remove(entity.Owner);
}
private void AddToCacheList<T>(List<T> listToAdd, T value)
{
if (listToAdd.Count == MAX_CACHED_AMOUNT)
listToAdd.RemoveAt(0);
listToAdd.Add(value);
}
private bool TrySendToUIState(EntityUid uid, BoundUserInterfaceState state)
{
if (!_userInterface.TryGetOpenUi(uid, SuperMatterObserverUiKey.Key, out var bui))
{
return false;
}
((SuperMatterObserverBUI)bui).DirectUpdateState(state);
return true;
}
}
43 changes: 28 additions & 15 deletions Content.Client/SS220/SuperMatter/Ui/SuperMatterObserverBUI.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt
using Content.Shared.SS220.SuperMatter.Ui;
using Robust.Client.UserInterface;

namespace Content.Client.SS220.SuperMatter.Ui;

public sealed class SuperMatterObserverBUI : BoundUserInterface
Expand All @@ -10,23 +13,33 @@ public SuperMatterObserverBUI(EntityUid owner, Enum uiKey) : base(owner, uiKey)
protected override void Open()
{
base.Open();
_menu = this.CreateWindow<SuperMatterObserverMenu>();

_menu = new SuperMatterObserverMenu();
_menu.OnClose += Close;
_menu.OpenCentered();
}
protected override void UpdateState(BoundUserInterfaceState state)
{
base.UpdateState(state);

_menu?.UpdateState();
_menu.OnServerButtonPressed += (args, observerComp) =>
{
if (!args.Button.Pressed)
_menu.Observer = null;
else
_menu.Observer = observerComp;
_menu.CrystalKey = null;
_menu.LoadCrystal();
};
_menu.OnCrystalButtonPressed += (_, crystalKey) =>
{
_menu.CrystalKey = crystalKey;
_menu.LoadCachedData();
};
}
protected override void Dispose(bool disposing)
public void DirectUpdateState(BoundUserInterfaceState state)
{
base.Dispose(disposing);
if (!disposing)
return;
_menu?.Close();
_menu?.Dispose();
switch (state)
{
case SuperMatterObserverInitState msg:
_menu?.LoadState(msg.ObserverEntity);
break;
case SuperMatterObserverUpdateState msg:
_menu?.UpdateState(msg);
break;
}
}
}
22 changes: 17 additions & 5 deletions Content.Client/SS220/SuperMatter/Ui/SuperMatterObserverMenu.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,23 @@
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
Title="{Loc 'supermatter-observer-title'}"
Resizable="False"
MinSize="512 576"
SetSize="512 576"
MinSize="512 608"
SetSize="512 608"
RectClipContent="False">
<BoxContainer Orientation="Vertical">
<plot:PlotSequencedView Name="PlotValueOverTime" MinHeight="256" MouseFilter="Stop" Margin="8 8" />
<plot:Pseudo3DColoredView Name="ColorState" MinHeight="256" MouseFilter="Stop" Margin="8 8" />
<BoxContainer Name="ContentHolderContainer" Orientation="Vertical">
<BoxContainer Name="ServerNavigationBar" HorizontalExpand="True" MinHeight="16" Margin="1 1 3 0">
<!-- Here goes all avaible "Servers" with SM data -->
</BoxContainer>
<BoxContainer Name="CrystalNavigationBar" HorizontalExpand="True" MinHeight="16" Margin="1 1 3 0">
<!-- Here goes all avaible "Servers" with SM data -->
</BoxContainer>
<BoxContainer Name="UpperDataContainer" MinHeight="256" Orientation="Vertical" Margin="8 8">
<plot:PlotSequencedView Name="PlotValueOverTime" MinHeight="256" MouseFilter="Stop"/>
<!-- Here go numberic Data -->
</BoxContainer>
<BoxContainer Name="LowerDataContainer" MinHeight="256" Orientation="Vertical" Margin="8 8">
<plot:Pseudo3DColoredView Name="ColorState" MinHeight="256" MouseFilter="Stop"/>
<!-- Here go data about gasses ratio near SM and their amount as label? or just in text -->
</BoxContainer>
</BoxContainer>
</controls:FancyWindow>
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,102 @@
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Timing;
using Robust.Client.UserInterface.Controls;
using Content.Shared.SS220.SuperMatter.Ui;
using Content.Client.SS220.UserInterface.PlotFigure;
using Content.Client.SS220.SuperMatter.Observer;
using System.Numerics;
using System.Linq;

namespace Content.Client.SS220.SuperMatter.Ui;

// For optimization make cache value in ServerSystem and then subscribe from client if it needs it;
[GenerateTypedNameReferences]
public sealed partial class SuperMatterObserverMenu : FancyWindow
{

public event Action<BaseButton.ButtonEventArgs, SuperMatterObserverComponent>? OnServerButtonPressed;
public event Action<BaseButton.ButtonEventArgs, int>? OnCrystalButtonPressed;
public SuperMatterObserverComponent? Observer;
public int? CrystalKey;
public const int MAX_DATA_LENGTH = 180;
private int counter = 0;
private float conterAbobaX = 0f;
private float conterAbobaY = 0f;
public SuperMatterObserverMenu()
{
IoCManager.InjectDependencies(this);
RobustXamlLoader.Load(this);
PlotValueOverTime.SetXLabel("t, с");
PlotValueOverTime.SetYLabel("u, эрг");
ColorState.MakeMeshgrid((100, 100, 25), (1000, 100, 400));
PlotValueOverTime.SetLabels("time elapsed, s", " Integrity", " Crystal Integrity ");
ColorState.MakeMeshgrid((1, 100, 25), (1, 100, 100));
ColorState.EvalFunctionOnMeshgrid(GetIntegrityDamageMap);
ColorState.SetLabels("Matter, a.u.", "Internal energy, a.u.", " Safe operation ");
}
public void UpdateState()
public void LoadState(List<Entity<SuperMatterObserverComponent>> observerEntities)
{
ServerNavigationBar.RemoveAllChildren();
foreach (var (observerUid, observerComp) in observerEntities)
{
var serverButton = new ServerButton
{
Text = observerUid.ToString(),
ObserverComponent = observerComp,
ToggleMode = true,
StyleClasses = { "OpenBoth" }
};

serverButton.OnPressed += args => OnServerButtonPressed?.Invoke(args, serverButton.ObserverComponent);
ServerNavigationBar.AddChild(serverButton);
}
}
public void LoadCrystal()
{
CrystalNavigationBar.RemoveAllChildren();
if (Observer == null)
return;
foreach (var (crystalKey, name) in Observer.Names)
{
var crystalButton = new CrystalButton
{
Text = name,
CrystalKey = crystalKey,
ToggleMode = true,
StyleClasses = { "OpenBoth" }
};

crystalButton.OnPressed += args => OnCrystalButtonPressed?.Invoke(args, crystalButton.CrystalKey);
CrystalNavigationBar.AddChild(crystalButton);
}
}
public void LoadCachedData()
{
if (Observer == null
|| CrystalKey == null)
return;
PlotValueOverTime.LoadPlot2DTimePoints(new PlotPoints2D(MAX_DATA_LENGTH, Observer.Integrities[CrystalKey.Value],
-1f, -1f * Observer.Integrities[CrystalKey.Value].Count));
ColorState.LoadMovingPoint(new Vector2(Observer.Matters[CrystalKey.Value].Last().Value, Observer.InternalEnergy[CrystalKey.Value].Last().Value),
new Vector2(Observer.Matters[CrystalKey.Value].Last().Derv, Observer.InternalEnergy[CrystalKey.Value].Last().Derv));
}
protected override void FrameUpdate(FrameEventArgs args)
public void UpdateState(SuperMatterObserverUpdateState msg)
{
base.FrameUpdate(args);
PlotValueOverTime.AddPointToPlot(new Vector2(counter++, counter++));
ColorState.LoadMovingPoint(new Vector2(conterAbobaX+=5, conterAbobaY+=80), new Vector2(5,80));
if (Observer == null
|| CrystalKey == null)
return;
PlotValueOverTime.AddPointToPlot(new Vector2(PlotValueOverTime.GetLastAddedPointX() + 1, msg.Integrity));
ColorState.LoadMovingPoint(new Vector2(msg.Matter.Value, msg.InternalEnergy.Value), new Vector2(msg.Matter.Derivative, msg.InternalEnergy.Derivative));
}
private float GetIntegrityDamageMap(float matter, float internalEnergy)
{
return SuperMatterFunctions.EnergyToMatterDamageFactorFunction(
internalEnergy - SuperMatterFunctions.SafeInternalEnergyToMatterFunction(matter));
internalEnergy - SuperMatterFunctions.SafeInternalEnergyToMatterFunction(matter / SuperMatterFunctions.MatterNondimensionalization));
}
private sealed class ServerButton : Button
{
public SuperMatterObserverComponent? ObserverComponent;
}
private sealed class CrystalButton : Button
{
public int CrystalKey;
}
}
Loading

0 comments on commit 4acb236

Please sign in to comment.