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 _zones = new Dictionary(); private List> _jobs = new List>(); private List _displays = new List(); private StringBuilder _displayBuffer = new StringBuilder(); private List _oxygenTanks = new List(); public Program() { Console = new MainConsole(this, "Air Pressure Monitor"); // Find all tagged objects and build out zones List blocks = new List(); 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, this); } _zones[zone].AddBlock(block); } } Console.Print($"Found {_zones.Count} zones:"); foreach (KeyValuePair 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.UpdateTickCount(); if (argument != "") { _cli.TryParse(argument); if (_cli.Switch("reset")) { List zonesToReset; if (_cli.ArgumentCount == 0) zonesToReset = _zones.Keys.ToList(); else zonesToReset = new List(); for (int i = 0; i < _cli.ArgumentCount; i++) zonesToReset.Add(_cli.Argument(i)); foreach (string zone in zonesToReset) { { Console.Print($"Resetting {zone}."); if (_zones.ContainsKey(zone)) _zones[zone].Reset(); } } } } foreach (IEnumerator job in _jobs) { if (job.MoveNext()) continue; Console.Print("WARNING: Monitoring job exited. Zone no longer being monitored."); } } // 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()); } } }