Refactor doors and lights to be slightly less coupled to the Zones. This allows them to be shared by multiple zones.
This commit is contained in:
parent
4be70bdfdb
commit
8b740dde71
19
AirMonitor/AirDoor.cs
Normal file
19
AirMonitor/AirDoor.cs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
using Sandbox.ModAPI.Ingame;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace IngameScript
|
||||||
|
{
|
||||||
|
partial class Program
|
||||||
|
{
|
||||||
|
public class AirDoor
|
||||||
|
{
|
||||||
|
public bool Triggered { get; set; } = false;
|
||||||
|
public IMyDoor Door { get; private set; }
|
||||||
|
|
||||||
|
public AirDoor(Program program, IMyDoor door)
|
||||||
|
{
|
||||||
|
Door = door;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,13 +10,14 @@ namespace IngameScript
|
||||||
public class AirZone
|
public class AirZone
|
||||||
{
|
{
|
||||||
public string Name { get; private set; }
|
public string Name { get; private set; }
|
||||||
|
|
||||||
public bool Triggered
|
public bool Triggered
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
foreach (IMyAirVent vent in Vents)
|
foreach (IMyAirVent vent in Vents)
|
||||||
{
|
{
|
||||||
if (vent.GetOxygenLevel() < TriggerLevel) return true;
|
if (vent.GetOxygenLevel() < TriggerLevel || vent.Status == VentStatus.Depressurized) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -24,9 +25,10 @@ namespace IngameScript
|
||||||
public List<IMyAirVent> Vents { get; } = new List<IMyAirVent>();
|
public List<IMyAirVent> Vents { get; } = new List<IMyAirVent>();
|
||||||
|
|
||||||
private Program _program;
|
private Program _program;
|
||||||
private List<IMyDoor> _doors = new List<IMyDoor>();
|
|
||||||
private List<IMyTextSurface> _displays = new List<IMyTextSurface>();
|
// private List<IMyTextSurface> _displays = new List<IMyTextSurface>(); // TODO: add single-zone displays
|
||||||
private List<IMyLightingBlock> _lights = new List<IMyLightingBlock>();
|
private List<IMyLightingBlock> _lights = new List<IMyLightingBlock>();
|
||||||
|
private List<AirDoor> _doors = new List<AirDoor>();
|
||||||
private PrefixedConsole _console;
|
private PrefixedConsole _console;
|
||||||
private Sequencer _sequencer;
|
private Sequencer _sequencer;
|
||||||
|
|
||||||
|
@ -40,25 +42,27 @@ namespace IngameScript
|
||||||
_sequencer = new Sequencer(_program, Name);
|
_sequencer = new Sequencer(_program, Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void AddDoor(AirDoor door)
|
||||||
|
{
|
||||||
|
_doors.Add(door);
|
||||||
|
IMyDoor doorBlock = door.Door;
|
||||||
|
SequenceableDoor wrapped = SequenceableFactory.MakeSequenceable(
|
||||||
|
_program,
|
||||||
|
doorBlock as IMyDoor,
|
||||||
|
"airMonitor") as SequenceableDoor;
|
||||||
|
wrapped.Step = 0;
|
||||||
|
wrapped.DeployOpen = false;
|
||||||
|
wrapped.LockOpen = false;
|
||||||
|
wrapped.LockClosed = true;
|
||||||
|
_sequencer.AddBlock(wrapped);
|
||||||
|
}
|
||||||
|
|
||||||
public void AddBlock(IMyTerminalBlock block)
|
public void AddBlock(IMyTerminalBlock block)
|
||||||
{
|
{
|
||||||
if (block is IMyAirVent)
|
if (block is IMyAirVent)
|
||||||
{
|
{
|
||||||
Vents.Add(block as IMyAirVent);
|
Vents.Add(block as IMyAirVent);
|
||||||
}
|
}
|
||||||
else if (block is IMyDoor)
|
|
||||||
{
|
|
||||||
_doors.Add(block as IMyDoor);
|
|
||||||
SequenceableDoor wrapped = SequenceableFactory.MakeSequenceable(
|
|
||||||
_program,
|
|
||||||
block as IMyDoor,
|
|
||||||
"airMonitor") as SequenceableDoor;
|
|
||||||
wrapped.Step = 0;
|
|
||||||
wrapped.DeployOpen = false;
|
|
||||||
wrapped.LockOpen = false;
|
|
||||||
wrapped.LockClosed = true;
|
|
||||||
_sequencer.AddBlock(wrapped);
|
|
||||||
}
|
|
||||||
else if (block is IMyLightingBlock)
|
else if (block is IMyLightingBlock)
|
||||||
{
|
{
|
||||||
_lights.Add(block as IMyLightingBlock);
|
_lights.Add(block as IMyLightingBlock);
|
||||||
|
@ -78,54 +82,34 @@ namespace IngameScript
|
||||||
if (Triggered == true)
|
if (Triggered == true)
|
||||||
{
|
{
|
||||||
_console.Print($"Low pressure alarm triggered.");
|
_console.Print($"Low pressure alarm triggered.");
|
||||||
|
|
||||||
// close the doors
|
// close the doors
|
||||||
IEnumerator<bool> job = _sequencer.RunSequence(true);
|
IEnumerator<bool> job = _sequencer.RunSequence(true);
|
||||||
while (job.MoveNext())
|
while (job.MoveNext())
|
||||||
{
|
{
|
||||||
// It would be nice if the API had UpdateFrequency.Once10, e.g. "re-run in 10 ticks and then clear the flag"
|
// It would be nice if the API had UpdateFrequency.Once10, e.g. "re-run in 10 ticks and then clear the flag"
|
||||||
// We'll just monitor every tick instead.
|
// We'll just monitor every tick instead.
|
||||||
|
setTriggeredStates();
|
||||||
_program.Runtime.UpdateFrequency |= UpdateFrequency.Once;
|
_program.Runtime.UpdateFrequency |= UpdateFrequency.Once;
|
||||||
yield return true;
|
yield return true;
|
||||||
}
|
}
|
||||||
job.Dispose();
|
job.Dispose();
|
||||||
|
|
||||||
while (Triggered) { yield return true; }
|
while (Triggered)
|
||||||
|
|
||||||
// unlock the doors, but we'll leave them closed.
|
|
||||||
foreach (IMyDoor door in _doors) { door.Enabled = true; }
|
|
||||||
|
|
||||||
foreach (IMyLightingBlock light in _lights)
|
|
||||||
{
|
{
|
||||||
light.Enabled = true;
|
setTriggeredStates();
|
||||||
light.Color = Color.White;
|
yield return true;
|
||||||
}
|
}
|
||||||
|
_console.Print("Air pressure returned to safe levels.");
|
||||||
}
|
}
|
||||||
|
|
||||||
yield return true;
|
yield return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetLights()
|
private void setTriggeredStates()
|
||||||
{
|
{
|
||||||
bool warning = false;
|
foreach (IMyLightingBlock light in _lights) light.Color = Color.Red;
|
||||||
foreach (IMyAirVent vent in Vents)
|
foreach (AirDoor door in _doors) door.Triggered = true;
|
||||||
{
|
|
||||||
if (vent.GetOxygenLevel() < TriggerLevel)
|
|
||||||
{
|
|
||||||
warning = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach (IMyLightingBlock light in _lights)
|
|
||||||
{
|
|
||||||
if (warning)
|
|
||||||
{
|
|
||||||
light.Enabled = true;
|
|
||||||
light.Color = Color.Red;
|
|
||||||
}
|
|
||||||
else light.Color = Color.White;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using VRage.Game.ModAPI.Ingame.Utilities;
|
using VRage.Game.ModAPI.Ingame.Utilities;
|
||||||
|
using VRageMath;
|
||||||
|
|
||||||
namespace IngameScript
|
namespace IngameScript
|
||||||
{
|
{
|
||||||
|
@ -13,12 +14,17 @@ namespace IngameScript
|
||||||
public MyIni Ini { get; } = new MyIni();
|
public MyIni Ini { get; } = new MyIni();
|
||||||
public IConsole Console { get; private set; }
|
public IConsole Console { get; private set; }
|
||||||
|
|
||||||
private Dictionary<string, AirZone> _zones = new Dictionary<string, AirZone>();
|
|
||||||
private List<IEnumerator<bool>> _jobs = new List<IEnumerator<bool>>();
|
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<IMyTextSurface> _displays = new List<IMyTextSurface>();
|
private List<IMyTextSurface> _displays = new List<IMyTextSurface>();
|
||||||
private StringBuilder _displayBuffer = new StringBuilder();
|
|
||||||
private List<IMyGasTank> _oxygenTanks = new List<IMyGasTank>();
|
private List<IMyGasTank> _oxygenTanks = new List<IMyGasTank>();
|
||||||
|
|
||||||
|
private StringBuilder _displayBuffer = new StringBuilder();
|
||||||
|
|
||||||
public Program()
|
public Program()
|
||||||
{
|
{
|
||||||
Console = new MainConsole(this, "Air Pressure Monitor");
|
Console = new MainConsole(this, "Air Pressure Monitor");
|
||||||
|
@ -31,13 +37,34 @@ namespace IngameScript
|
||||||
Ini.TryParse(block.CustomData);
|
Ini.TryParse(block.CustomData);
|
||||||
string[] zones = new string[] { };
|
string[] zones = new string[] { };
|
||||||
|
|
||||||
if (block is IMyTextSurface)
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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}'");
|
Console.Print($"Adding monitoring display '{block.CustomName}'");
|
||||||
_displays.Add(block as IMyTextSurface);
|
_displays.Add(block as IMyTextSurface);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (Ini.Get("airMonitor", "display").ToString() != "")
|
else if (Ini.Get("airMonitor", "display").ToString() != "")
|
||||||
{
|
{
|
||||||
|
// TODO: behave differently if zone is defined
|
||||||
int displayIndex = Ini.Get("airMonitor", "display").ToInt32();
|
int displayIndex = Ini.Get("airMonitor", "display").ToInt32();
|
||||||
IMyTextSurfaceProvider provider = block as IMyTextSurfaceProvider;
|
IMyTextSurfaceProvider provider = block as IMyTextSurfaceProvider;
|
||||||
if (provider.SurfaceCount <= displayIndex)
|
if (provider.SurfaceCount <= displayIndex)
|
||||||
|
@ -49,29 +76,26 @@ namespace IngameScript
|
||||||
_displays.Add(provider.GetSurface(displayIndex));
|
_displays.Add(provider.GetSurface(displayIndex));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (block is IMyGasTank)
|
|
||||||
|
else if (block is IMyDoor)
|
||||||
{
|
{
|
||||||
_oxygenTanks.Add(block as IMyGasTank);
|
AirDoor door = new AirDoor(this, block as IMyDoor);
|
||||||
}
|
_doors.Add(door);
|
||||||
else if (Ini.Get("airMonitor", "zones").ToString() != "")
|
foreach (string zone in zones) _zones[zone].AddDoor(door);
|
||||||
{
|
|
||||||
zones = Ini.Get("airMonitor", "zones").ToString().Split(',');
|
|
||||||
}
|
|
||||||
else if (Ini.Get("airMonitor", "zone").ToString() != "")
|
|
||||||
{
|
|
||||||
zones = new string[] { Ini.Get("airMonitor", "zone").ToString() };
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Console.Print($"Failed to add block {block.CustomName}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (string zone in zones)
|
else if (block is IMyLightingBlock)
|
||||||
{
|
{
|
||||||
if (!_zones.ContainsKey(zone))
|
_lights.Add(block as IMyLightingBlock);
|
||||||
|
foreach (string zone in zones) _zones[zone].AddBlock(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (string zone in zones)
|
||||||
{
|
{
|
||||||
_zones[zone] = new AirZone(this, zone);
|
_zones[zone].AddBlock(block);
|
||||||
}
|
}
|
||||||
_zones[zone].AddBlock(block);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,6 +106,7 @@ namespace IngameScript
|
||||||
Console.Print(kvp.Key);
|
Console.Print(kvp.Key);
|
||||||
_jobs.Add(zone.Monitor());
|
_jobs.Add(zone.Monitor());
|
||||||
}
|
}
|
||||||
|
|
||||||
Runtime.UpdateFrequency = UpdateFrequency.Update100;
|
Runtime.UpdateFrequency = UpdateFrequency.Update100;
|
||||||
Console.UpdateTickCount();
|
Console.UpdateTickCount();
|
||||||
}
|
}
|
||||||
|
@ -90,20 +115,32 @@ namespace IngameScript
|
||||||
{
|
{
|
||||||
Console.UpdateTickCount();
|
Console.UpdateTickCount();
|
||||||
|
|
||||||
|
// 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)
|
foreach (IEnumerator job in _jobs)
|
||||||
{
|
{
|
||||||
if (job.MoveNext()) continue;
|
// Run the monitoring jobs, which will update the lights and door states
|
||||||
Console.Print("WARNING: Monitoring job exited. Zone no longer being monitored.");
|
if (!job.MoveNext()) Console.Print("WARNING: Monitoring job exited. Zone no longer being monitored.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Light indicators should be set/unset independent of the triggered states and actions.
|
// Unlock all safe doors, but leave them closed.
|
||||||
foreach (AirZone zone in _zones.Values) zone.SetLights();
|
// 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();
|
updateDisplays();
|
||||||
}
|
}
|
||||||
|
|
||||||
// write diagnostics to any configured display screens
|
// write diagnostics to any configured display screens
|
||||||
private void _updateDisplays()
|
private void updateDisplays()
|
||||||
{
|
{
|
||||||
if (_displays.Count == 0) return;
|
if (_displays.Count == 0) return;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user