using Sandbox.ModAPI.Ingame; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using VRage.Game.ModAPI.Ingame.Utilities; using VRageMath; namespace IngameScript { public partial class Program : MyGridProgram, IConsoleProgram { public MyIni Ini { get; } = new MyIni(); public IConsole Console { get; private set; } private FailoverManager _failover; private List> _jobs = new List>(); private Dictionary _zones = new Dictionary(); private List _doors = new List(); private List _lights = new List(); private List _displays = new List(); private List _oxygenTanks = new List(); private StringBuilder _displayBuffer = new StringBuilder(); public Program() { Console = new MainConsole(this, "Air Pressure Monitor"); _failover = new FailoverManager(this, Console, Ini); List surfaces = new List(); // Find all tagged objects and build out zones List blocks = new List(); GridTerminalSystem.GetBlocksOfType(blocks, blockFilter); foreach (IMyTerminalBlock block in blocks) { Ini.TryParse(block.CustomData); string[] zones = new string[] { }; if (Ini.Get("airMonitor", "zones").ToString() != "") { zones = Ini.Get("airMonitor", "zones").ToString().Split(','); } foreach (string zone in zones) { if (!_zones.ContainsKey(zone)) _zones[zone] = new AirZone(this, zone); } if (block is IMyGasTank) { _oxygenTanks.Add(block as IMyGasTank); } else if (block is IMyTextSurface) { // TODO: behave differently if zone is defined Console.Print($"Adding monitoring display '{block.CustomName}'"); surfaces.Add(block as IMyTextSurface); } else if (Ini.Get("airMonitor", "display").ToString() != "") { // TODO: behave differently if zone is defined 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 { surfaces.Add(provider.GetSurface(displayIndex)); } } else if (block is IMyDoor) { AirDoor door = new AirDoor(block as IMyDoor); _doors.Add(door); foreach (string zone in zones) _zones[zone].AddDoor(door); } else if (block is IMyLightingBlock) { _lights.Add(block as IMyLightingBlock); foreach (string zone in zones) _zones[zone].AddBlock(block); } else { foreach (string zone in zones) { _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()); } foreach (IMyTextSurface surface in surfaces) { _displays.Add(new AirMonitorDisplay(surface, _zones.Values.ToList())); } Runtime.UpdateFrequency = UpdateFrequency.Update100; Console.UpdateTickCount(); } public void Main(string argument, UpdateType updateSource) { Console.UpdateTickCount(); if (_failover.ActiveCheck() == FailoverState.Standby) return; // Light indicators should be set/unset independent of the triggered states and actions. foreach (IMyLightingBlock light in _lights) light.Color = Color.White; foreach (AirDoor door in _doors) door.Triggered = false; foreach (IEnumerator job in _jobs) { // Run the monitoring jobs, which will update the lights and door states if (!job.MoveNext()) Console.Print("WARNING: Monitoring job exited. Zone no longer being monitored."); } // Unlock all safe doors, but leave them closed. // Note that this will make it difficult to manually lock/disable these doors. foreach (AirDoor door in _doors) { if (door.Door.Enabled == false && !door.Triggered) { Console.Print($"DEBUG: {door.Door.CustomName} re-enabled"); door.Door.Enabled = true; } } updateDisplays(); } private void updateDisplays() { foreach (AirMonitorDisplay display in _displays) { display.Draw(); } } private bool blockFilter(IMyTerminalBlock block) { return block.IsSameConstructAs(this.Me) && MyIni.HasSection(block.CustomData, "airMonitor"); } } }