space_engineers/AirMonitor/Program.cs

169 lines
6.3 KiB
C#

using Sandbox.Game.EntityComponents;
using Sandbox.ModAPI.Ingame;
using Sandbox.ModAPI.Interfaces;
using SpaceEngineers.Game.ModAPI.Ingame;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Text;
using VRage;
using VRage.Collections;
using VRage.Game;
using VRage.Game.Components;
using VRage.Game.GUI.TextPanel;
using VRage.Game.ModAPI.Ingame;
using VRage.Game.ModAPI.Ingame.Utilities;
using VRage.Game.ObjectBuilders.Definitions;
using VRageMath;
namespace IngameScript
{
public partial class Program : MyGridProgram
{
private MyIni _ini;
private Console _console;
private MyCommandLine _cli;
private int _totalTicks = 0;
private Dictionary<string, AirZone> _zones;
private List<IEnumerator<bool>> _jobs;
private List<IMyTextSurface> _displays;
private StringBuilder _displayBuffer;
private List<IMyGasTank> _oxygenTanks;
public Program()
{
_cli = new MyCommandLine();
_ini = new MyIni();
_console = new Console(this, _ini);
_zones = new Dictionary<string, AirZone>();
_jobs = new List<IEnumerator<bool>>();
_displays = new List<IMyTextSurface>();
_displayBuffer = new StringBuilder();
_oxygenTanks = new List<IMyGasTank>();
// Find all tagged objects and build out zones
List<IMyTerminalBlock> blocks = new List<IMyTerminalBlock>();
GridTerminalSystem.GetBlocksOfType(blocks, block => MyIni.HasSection(block.CustomData, "airMonitor"));
foreach (IMyTerminalBlock block in blocks)
{
_ini.TryParse(block.CustomData);
string[] zones = new string[] { };
// TODO: how do we display text on e.g. decorative console blocks?
// They have configurable screens but the docs say they don't implement this.
// Meanwhile *every* functional block seems to implement IMyTextSurfaceProvider...
// It'd probably be safe to just check SurfaceCount... experiment with this later
if (block is IMyTextSurface)
{
_console.Print($"Adding monitoring display '{block.CustomName}'");
_displays.Add(block as IMyTextSurface);
}
if (_ini.Get("airMonitor", "display").ToString() != "")
{
int displayIndex = _ini.Get("airMonitor", "display").ToInt32();
IMyTextSurfaceProvider provider = block as IMyTextSurfaceProvider;
if (provider.SurfaceCount <= displayIndex)
{
_console.Print($"Invalid display index '{displayIndex}' in block '{block.CustomName}'");
}
else
{
_displays.Add(provider.GetSurface(displayIndex));
}
}
if (block is IMyGasTank)
{
_oxygenTanks.Add(block as IMyGasTank);
}
if (_ini.Get("airMonitor", "zones").ToString() != "")
{
zones = _ini.Get("airMonitor", "zones").ToString().Split(',');
}
else if (_ini.Get("airMonitor", "zone").ToString() != "")
{
zones = new string[] { _ini.Get("airMonitor", "zone").ToString() };
}
foreach (string zone in zones)
{
if (!_zones.ContainsKey(zone))
{
_zones[zone] = new AirZone(zone, _ini, _console);
}
_zones[zone].AddBlock(block);
}
}
_console.Print($"Found {_zones.Count} zones:");
foreach (KeyValuePair<string, AirZone> kvp in _zones)
{
AirZone zone = kvp.Value;
_console.Print(kvp.Key);
_jobs.Add(zone.Monitor());
}
Runtime.UpdateFrequency |= UpdateFrequency.Update100;
}
public void Main(string argument, UpdateType updateSource)
{
_console.PrintLower($"Air Monitor\nTotal Ticks: {++_totalTicks}");
if (argument != "")
{
_cli.TryParse(argument);
if (_cli.Switch("reset"))
{
for (int i = 0; i < _cli.ArgumentCount; i++)
{
string zone = _cli.Argument(i);
_console.Print($"Resetting {zone}.");
if (_zones.ContainsKey(zone))
{
_zones[zone].Reset();
}
}
}
}
// write diagnostics
if (_displays.Count != 0)
{
_displayBuffer.Clear();
_displayBuffer.Append("AIR PRESSURE REPORT\n\n");
foreach (AirZone zone in _zones.Values)
{
_displayBuffer.Append(zone.Name);
_displayBuffer.Append(": ");
_displayBuffer.Append(zone.Triggered ? "ALARM TRIPPED " : "NOMINAL ");
foreach (IMyAirVent vent in zone.Vents)
{
_displayBuffer.Append((int)(vent.GetOxygenLevel() * 100F));
_displayBuffer.Append("% ");
}
_displayBuffer.Append("\n");
}
_displayBuffer.Append("\n");
_displayBuffer.Append("OXYGEN TANK LEVELS\n");
foreach (IMyGasTank tank in _oxygenTanks)
{
_displayBuffer.Append((int)(tank.FilledRatio * 100));
_displayBuffer.Append("% ");
}
foreach (IMyTextSurface display in _displays) display.WriteText(_displayBuffer.ToString());
}
foreach (IEnumerator job in _jobs)
{
if (job.MoveNext()) continue;
_console.Print("WARNING: Monitoring job exited. Zone no longer being monitored.");
}
}
}
}