space_engineers/AirMonitor/Program.cs

161 lines
5.8 KiB
C#

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<IEnumerator<bool>> _jobs = new List<IEnumerator<bool>>();
private Dictionary<string, AirZone> _zones = new Dictionary<string, AirZone>();
private List<AirDoor> _doors = new List<AirDoor>();
private List<IMyLightingBlock> _lights = new List<IMyLightingBlock>();
private List<AirMonitorDisplay> _displays = new List<AirMonitorDisplay>();
private List<IMyGasTank> _oxygenTanks = new List<IMyGasTank>();
private StringBuilder _displayBuffer = new StringBuilder();
public Program()
{
Console = new MainConsole(this, "Air Pressure Monitor");
_failover = new FailoverManager(this, Console, Ini);
List<IMyTextSurface> surfaces = new List<IMyTextSurface>();
// Find all tagged objects and build out zones
List<IMyTerminalBlock> blocks = new List<IMyTerminalBlock>();
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<string, AirZone> 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");
}
}
}