173 lines
6.7 KiB
C#
173 lines
6.7 KiB
C#
using Sandbox.ModAPI.Ingame;
|
|
using SpaceEngineers.Game.ModAPI.Ingame;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using VRage.Game.ModAPI.Ingame.Utilities;
|
|
|
|
namespace IngameScript
|
|
{
|
|
public partial class Program : MyGridProgram, IConsoleProgram
|
|
{
|
|
public MyIni Ini { get; } = new MyIni();
|
|
public IConsole Console { get; private set; }
|
|
|
|
private MyCommandLine _cli = new MyCommandLine();
|
|
private Dictionary<string, AirZone> _zones = new Dictionary<string, AirZone>();
|
|
private List<IEnumerator<bool>> _jobs = new List<IEnumerator<bool>>();
|
|
private List<IMyTextSurface> _displays = new List<IMyTextSurface>();
|
|
private StringBuilder _displayBuffer = new StringBuilder();
|
|
private List<IMyGasTank> _oxygenTanks = new List<IMyGasTank>();
|
|
|
|
public Program()
|
|
{
|
|
Console = new MainConsole(this, "Air Pressure Monitor");
|
|
|
|
// 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(this, zone);
|
|
}
|
|
_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;
|
|
Console.UpdateTickCount();
|
|
}
|
|
|
|
public void Main(string argument, UpdateType updateSource)
|
|
{
|
|
Console.UpdateTickCount();
|
|
|
|
if (argument != "")
|
|
{
|
|
_cli.TryParse(argument);
|
|
if (_cli.Switch("reset") || _cli.Switch("trigger"))
|
|
{
|
|
List<string> zonesToControl;
|
|
if (_cli.ArgumentCount == 0) zonesToControl = _zones.Keys.ToList();
|
|
else zonesToControl = new List<string>();
|
|
for (int i = 0; i < _cli.ArgumentCount; i++)
|
|
{
|
|
string zone = _cli.Argument(i);
|
|
if (!_zones.ContainsKey(zone))
|
|
{
|
|
Console.Print($"Ignoring non-existent zone '{zone}'");
|
|
continue;
|
|
}
|
|
zonesToControl.Add(zone);
|
|
}
|
|
|
|
foreach (string zone in zonesToControl)
|
|
{
|
|
if (_cli.Switch("reset"))
|
|
{
|
|
Console.Print($"Resetting {zone}.");
|
|
_zones[zone].Reset();
|
|
}
|
|
if (_cli.Switch("trigger"))
|
|
{
|
|
Console.Print($"Manually triggering {zone}.");
|
|
_zones[zone].Triggered = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach (IEnumerator job in _jobs)
|
|
{
|
|
if (job.MoveNext()) continue;
|
|
Console.Print("WARNING: Monitoring job exited. Zone no longer being monitored.");
|
|
}
|
|
|
|
_updateDisplays();
|
|
}
|
|
|
|
// write diagnostics to any configured display screens
|
|
private void _updateDisplays()
|
|
{
|
|
if (_displays.Count == 0) return;
|
|
|
|
_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());
|
|
}
|
|
}
|
|
}
|