diff --git a/Airlock/Airlock.cs b/Airlock/Airlock.cs index baad440..4c210ec 100644 --- a/Airlock/Airlock.cs +++ b/Airlock/Airlock.cs @@ -1,3 +1,13 @@ +// Airlock logic. +// +// We don't use a Sequencer for Airlocks for a number of reasons. Most notably: +// +// * One door in each cycle needs to be both closed and then opened. +// * The lights (and in the future, displays) need to emit signal information at several stages. +// +// We could add functionality to the Sequencer for these use cases, but right now we'll keep the logic separate, +// even though *for the most part* it follows the same "Enumerator that waits for various bits of state" logic. + using Sandbox.ModAPI.Ingame; using SpaceEngineers.Game.ModAPI.Ingame; using System.Collections.Generic; @@ -21,7 +31,7 @@ namespace IngameScript { get { - return innerDoor.Status == DoorStatus.Closed && outerDoor.Status == DoorStatus.Closed; + return _innerDoor.Status == DoorStatus.Closed && _outerDoor.Status == DoorStatus.Closed; } } @@ -30,21 +40,21 @@ namespace IngameScript { get { - return ((airVent.Depressurize && airVent.GetOxygenLevel() <= targetOxygenLevel) || - (!airVent.Depressurize && airVent.Status == VentStatus.Pressurized)); + return ((_airVent.Depressurize && _airVent.GetOxygenLevel() <= targetOxygenLevel) || + (!_airVent.Depressurize && _airVent.Status == VentStatus.Pressurized)); } } public bool OxygenBalanced { - get { return oxygenTank.FilledRatio > 0.25; } + get { return _oxygenTank.FilledRatio > 0.25; } } public bool Functional { get { - return (innerDoor != null && outerDoor != null && airVent != null && oxygenTank != null); + return (_innerDoor != null && _outerDoor != null && _airVent != null && _oxygenTank != null); } } @@ -54,20 +64,20 @@ namespace IngameScript { get { - return innerDoor.Status == DoorStatus.Open || outerDoor.Status == DoorStatus.Open; + return _innerDoor.Status == DoorStatus.Open || _outerDoor.Status == DoorStatus.Open; } } // Returns false if we are in a state where we can't or don't need to balance private bool balanceOxygen() { - if (innerDoor.Status == DoorStatus.Closed || outerDoor.Status == DoorStatus.Open || OxygenBalanced) { return false; } + if (_innerDoor.Status == DoorStatus.Closed || _outerDoor.Status == DoorStatus.Open || OxygenBalanced) { return false; } _console.Print($"{_name}: Balancing Oxygen Tank"); // Configure the vent to suck in Oxygen. - airVent.Depressurize = true; - airVent.Enabled = true; + _airVent.Depressurize = true; + _airVent.Enabled = true; return true; } @@ -76,64 +86,46 @@ namespace IngameScript private MyGridProgram _p; private float targetOxygenLevel = 0.0F; - private IMyDoor innerDoor; - private IMyDoor outerDoor; - private List lights; - private IMyGasTank oxygenTank; - private IMyAirVent airVent; - private IMyAirVent airSensor; + private IMyDoor _innerDoor; + private IMyDoor _outerDoor; + private List _lights; + private IMyGasTank _oxygenTank; + private IMyAirVent _airVent; + private IMyAirVent _airSensor; + // private List _displays; + private const int CooldownTicks = 120; + private const int SealTimeoutTicks = 30; public Airlock(MyGridProgram program, Console console, string name) { _p = program; _name = name; _console = console.CreatePrefixedConsole(_name); - lights = new List(); - - // Find the appropriate blocks given the airlock name - // initDoors(); - // initLights(); - // initVents(); - // initOxygen(); + _lights = new List(); + // _displays = new List(); } public void AddBlock(IMyTerminalBlock block) { - if (block is IMyDoor) - { - addDoor(block as IMyDoor); - return; - } - if (block is IMyLightingBlock) - { - lights.Add(block as IMyLightingBlock); - return; - } - if (block is IMyAirVent) - { - addVent(block as IMyAirVent); - return; - } - if (block is IMyGasTank) - { - addOxygenTank(block as IMyGasTank); - return; - } - - _console.Print($"Tried to add invalid block '{block.CustomName}'"); + if (block is IMyDoor) addDoor(block as IMyDoor); + else if (block is IMyLightingBlock) _lights.Add(block as IMyLightingBlock); + else if (block is IMyAirVent) addVent(block as IMyAirVent); + else if (block is IMyGasTank) addOxygenTank(block as IMyGasTank); + // else if (block is IMyTextSurfaceProvider) _displays.Add(((IMyTextSurfaceProvider)block).GetSurface(0)); + else _console.Print($"Tried to add invalid block '{block.CustomName}'"); } private void addDoor(IMyDoor door) { - if (door.CustomName.Contains("Inner") && innerDoor == null) + if (door.CustomName.Contains("Inner") && _innerDoor == null) { - innerDoor = door; + _innerDoor = door; return; } - if (door.CustomName.Contains("Outer") && outerDoor == null) + if (door.CustomName.Contains("Outer") && _outerDoor == null) { - outerDoor = door; + _outerDoor = door; return; } _console.Print($"Couldn't add door '{door.CustomName}'"); @@ -141,14 +133,14 @@ namespace IngameScript private void addVent(IMyAirVent vent) { - if (vent.CustomName.Contains("Main") && airVent == null) + if (vent.CustomName.Contains("Main") && _airVent == null) { - airVent = vent; + _airVent = vent; return; } - if (vent.CustomName.Contains("Reference") && airSensor == null) + if (vent.CustomName.Contains("Reference") && _airSensor == null) { - airSensor = vent; + _airSensor = vent; return; } _console.Print($"Couldn't add air vent '{vent.CustomName}'"); @@ -156,98 +148,14 @@ namespace IngameScript private void addOxygenTank(IMyGasTank tank) { - if (oxygenTank == null) + if (_oxygenTank == null) { - oxygenTank = tank; + _oxygenTank = tank; return; } _console.Print($"Couldn't add oxygen tank '{tank.CustomName}'"); } - // private void initDoors() - // { - // List onlyDoors = new List(); - // _p.GridTerminalSystem.GetBlocksOfType(onlyDoors); - // foreach (IMyDoor door in onlyDoors) - // { - // if (!door.CustomName.StartsWith(_name)) continue; - - // if (door.CustomName.Contains("Inner")) - // { - // innerDoor = door; - // } - // else if (door.CustomName.Contains("Outer")) - // { - // outerDoor = door; - // } - - // if (innerDoor != null && outerDoor != null) - // { - // return; - // } - // } - - // Functional = false; - // } - - // private void initVents() - // { - // List onlyFans = new List(); - // _p.GridTerminalSystem.GetBlocksOfType(onlyFans); - // foreach (IMyAirVent vent in onlyFans) - // { - // if (!vent.CustomName.StartsWith(_name)) continue; - - // if (vent.CustomName.StartsWith(_name)) - // { - // if (vent.CustomName.Contains("Main")) - // { - // airVent = vent; - // continue; - // } - // else if (vent.CustomName.Contains("Reference")) - // { - // airSensor = vent; - // continue; - // } - // } - - // // A global reference vent will be used if we don't have one specific to our airlock. - // // A specific vent found later will overwrite this assignment. - // if (vent.CustomName.StartsWith("Airlock Reference") && airSensor == null) - // { - // airSensor = vent; - // } - // } - - // if (airVent == null) Functional = false; - // } - - // private void initLights() - // { - // lights = new List(); - // List allLights = new List(); - // _p.GridTerminalSystem.GetBlocksOfType(allLights); - // foreach (IMyLightingBlock light in allLights) - // { - // if (!light.CustomName.StartsWith(_name)) continue; - // lights.Add(light); - // } - // } - - // private void initOxygen() - // { - // List allTanks = new List(); - // _p.GridTerminalSystem.GetBlocksOfType(allTanks); - // foreach (IMyGasTank tank in allTanks) - // { - // if (!tank.CustomName.StartsWith(_name)) continue; - // oxygenTank = tank; - // return; - // } - // Functional = false; - // } - public IEnumerator CycleAirlock() { Cycling = true; @@ -257,7 +165,14 @@ namespace IngameScript while (!DoorsClosed) { yield return true; } lockDoors(); - if (!airVent.CanPressurize) + int ticks = 0; + while (!_airVent.CanPressurize && ticks < SealTimeoutTicks) + { + ticks++; + yield return true; + } + + if (!_airVent.CanPressurize) { error("Airlock is not airtight."); Cycling = false; @@ -266,7 +181,7 @@ namespace IngameScript pressurizeDepressurize(); while (!PressureStabilized) { yield return true; } - airVent.Enabled = false; + _airVent.Enabled = false; openDoor(); while (!DoorOpened) { yield return true; } @@ -278,7 +193,7 @@ namespace IngameScript { while (!OxygenBalanced) { yield return true; } } - airVent.Enabled = false; + _airVent.Enabled = false; // Cooldown period int cooldown = 0; @@ -298,10 +213,10 @@ namespace IngameScript _console.Print("Closing Doors"); // close the doors - innerDoor.Enabled = true; - outerDoor.Enabled = true; - innerDoor.CloseDoor(); - outerDoor.CloseDoor(); + _innerDoor.Enabled = true; + _outerDoor.Enabled = true; + _innerDoor.CloseDoor(); + _outerDoor.CloseDoor(); } private void pressurizeDepressurize() @@ -309,14 +224,14 @@ namespace IngameScript _console.Print("Cycling"); // toggle the current state - airVent.Depressurize = !airVent.Depressurize; - airVent.Enabled = true; + _airVent.Depressurize = !_airVent.Depressurize; + _airVent.Enabled = true; // When depressurizing, check the external pressure and only depressurize to that value. // TODO: test this for floating point errors - if (airVent.Depressurize && airSensor != null) + if (_airVent.Depressurize && _airSensor != null) { - targetOxygenLevel = airSensor.GetOxygenLevel(); + targetOxygenLevel = _airSensor.GetOxygenLevel(); _console.Print($"Set depressurization target to {targetOxygenLevel}"); } } @@ -326,15 +241,15 @@ namespace IngameScript { _console.Print($"Opening Door"); - if (airVent.Status == VentStatus.Pressurized) + if (_airVent.Status == VentStatus.Pressurized) { - innerDoor.Enabled = true; - innerDoor.OpenDoor(); + _innerDoor.Enabled = true; + _innerDoor.OpenDoor(); } else { - outerDoor.Enabled = true; - outerDoor.OpenDoor(); + _outerDoor.Enabled = true; + _outerDoor.OpenDoor(); } } @@ -362,7 +277,7 @@ namespace IngameScript break; } - foreach (IMyLightingBlock light in lights) + foreach (IMyLightingBlock light in _lights) { light.Enabled = true; light.BlinkIntervalSeconds = blinkInterval; @@ -371,10 +286,16 @@ namespace IngameScript } } + // private void setDisplays(string text) { + // foreach (IMyTextSurface display in _displays) { + // display.WriteText(text); + // } + // } + private void lockDoors() { - innerDoor.Enabled = false; - outerDoor.Enabled = false; + _innerDoor.Enabled = false; + _outerDoor.Enabled = false; } private void error(string error) diff --git a/Airlock/Program.cs b/Airlock/Program.cs index e146fe6..ccd4fab 100644 --- a/Airlock/Program.cs +++ b/Airlock/Program.cs @@ -40,11 +40,12 @@ namespace IngameScript // keeping around for warnings. } _console.Print($"Found {_airlocks.Count} airlocks."); + _console.PrintLower($"Airlock Controller\nTotal Ticks: 0"); } public void Main(string argument, UpdateType updateSource) { - _console.PrintLower($"Total Ticks: {_tickCount++}"); + _console.PrintLower($"Airlock Controller\nTotal Ticks: {++_tickCount}"); if (updateSource == UpdateType.Trigger || updateSource == UpdateType.Terminal) { @@ -53,10 +54,8 @@ namespace IngameScript else { string airlockName = $"!Airlock{_cli.Argument(0)}"; - if (!_airlocks.ContainsKey(airlockName)) - { - _console.Print($"Invalid airlock ID {_cli.Argument(0)}"); - } + if (!_airlocks.ContainsKey(airlockName)) _console.Print($"Invalid airlock ID {_cli.Argument(0)}"); + else if (!_airlocks[airlockName].Functional) _console.Print($"Airlock '{airlockName}' is not functional."); else { _jobs.Add(_airlocks[airlockName].CycleAirlock());