diff --git a/MechanicalDoor/Program.cs b/MechanicalDoor/Program.cs index c36f841..b30785c 100644 --- a/MechanicalDoor/Program.cs +++ b/MechanicalDoor/Program.cs @@ -24,21 +24,20 @@ namespace IngameScript _doors = new Dictionary(); List doorBlocks = new List(); - GridTerminalSystem.GetBlocksOfType(doorBlocks, block => block.CustomName.Contains("!Door")); + GridTerminalSystem.GetBlocksOfType(doorBlocks, block => MyIni.HasSection(block.CustomData, "mechDoor")); foreach (IMyTerminalBlock block in doorBlocks) { - string doorName = Utils.ExtractTag(block, "!Door"); - - // Create the door if this is a new tag + _ini.TryParse(block.CustomData); + string doorName = _ini.Get("mechDoor", "id").ToString(); + // Create the door if this is a new id if (!_doors.ContainsKey(doorName)) { _doors[doorName] = new Sequencer(doorName, new PrefixedConsole(_console, doorName)); } // Add the part; the Door object handles typing and sequencing. - int defaultStep = 1; - if (block is IMyShipMergeBlock) defaultStep = 0; - ISequenceable wrapped = SequenceableFactory.MakeSequenceable(block, _ini, defaultStep); + ISequenceable wrapped = SequenceableFactory.MakeSequenceable(block, _ini, "mechDoor"); + if (!(block is IMyShipMergeBlock)) wrapped.Step = 1; if (wrapped == null) { _console.Print($"Tried to add incompatible block '{block.CustomName}'"); continue; } _doors[doorName].AddBlock(wrapped); } @@ -68,7 +67,7 @@ namespace IngameScript for (int i = 0; i < _cli.ArgumentCount; i++) { - string key = "Door" + _cli.Argument(i); + string key = _cli.Argument(i); if (!_doors.ContainsKey(key)) { _console.Print($"Door '{key}' not found. Skipping."); @@ -89,10 +88,10 @@ namespace IngameScript else { _console.Print("Creating new job(s)."); - bool close = _cli.Switch("close"); + bool deploy = _cli.Switch("deploy") || _cli.Switch("open"); foreach (Sequencer door in doorsToControl) { - _jobs.Add(door.RunSequence(close)); + _jobs.Add(door.RunSequence(deploy)); } Runtime.UpdateFrequency |= UpdateFrequency.Update1; } @@ -101,13 +100,12 @@ namespace IngameScript // Process running jobs for (int i = 0; i < _jobs.Count; i++) { - if (!_jobs[i].MoveNext()) - { - _jobs[i].Dispose(); - _jobs.Remove(_jobs[i]); - i--; - _console.Print("Operation Complete."); - } + if (_jobs[i].MoveNext()) continue; + + _jobs[i].Dispose(); + _jobs.Remove(_jobs[i]); + i--; + _console.Print("Operation Complete."); } if (_jobs.Count == 0) diff --git a/Mixins/Sequencer/ISequenceable.cs b/Mixins/Sequencer/ISequenceable.cs index defd8cc..bfe2212 100644 --- a/Mixins/Sequencer/ISequenceable.cs +++ b/Mixins/Sequencer/ISequenceable.cs @@ -1,3 +1,5 @@ +using System.Collections.Generic; + namespace IngameScript { partial class Program @@ -5,10 +7,8 @@ namespace IngameScript public interface ISequenceable { bool Running { get; } - int Step { get; } - void Start(bool reverse = true); - bool Check(); - void Finish(); + int Step { get; set; } + IEnumerator Run(bool deploy); } } } \ No newline at end of file diff --git a/Mixins/Sequencer/SequenceableFactory.cs b/Mixins/Sequencer/SequenceableFactory.cs index 330447e..59e9bd3 100644 --- a/Mixins/Sequencer/SequenceableFactory.cs +++ b/Mixins/Sequencer/SequenceableFactory.cs @@ -13,11 +13,11 @@ namespace IngameScript public static ISequenceable MakeSequenceable( IMyTerminalBlock block, MyIni ini, - int step = 0) + string sectionName = "sequence") { if (block is IMyMotorStator) { - return new SequenceableRotor(block as IMyMotorStator, ini, step); + return new SequenceableRotor(block as IMyMotorStator, ini, sectionName); } if (block is IMyPistonBase) { diff --git a/Mixins/Sequencer/SequenceableRotor.cs b/Mixins/Sequencer/SequenceableRotor.cs index da82cf1..f60cf1d 100644 --- a/Mixins/Sequencer/SequenceableRotor.cs +++ b/Mixins/Sequencer/SequenceableRotor.cs @@ -1,5 +1,6 @@ using Sandbox.ModAPI.Ingame; using System; +using System.Collections.Generic; using VRage.Game.ModAPI.Ingame.Utilities; namespace IngameScript @@ -9,55 +10,71 @@ namespace IngameScript public class SequenceableRotor : ISequenceable { public bool Running { get; private set; } = false; - public int Step { get; private set; } - - private float _targetAngle; - private float _lastAngle; + public int Step { get; set; } private float _velocity; - private float _openAngle; - private float _closedAngle; + private float _deployAngle; + private float _stowAngle; private IMyMotorStator _rotor; + private MyRotationDirection _deployDirection; + private MyRotationDirection _stowDirection; public SequenceableRotor( IMyMotorStator rotor, MyIni ini, - int defaultStep = 0) + string sectionName) { _rotor = rotor; ini.TryParse(rotor.CustomData); - _openAngle = ini.Get("sequencer", "openAngle").ToSingle(90F); - _closedAngle = ini.Get("sequencer", "closedAngle").ToSingle(0F); - _velocity = ini.Get("sequencer", "velocity").ToSingle(5F); - Step = ini.Get("sequencer", "step").ToInt32(defaultStep); - } - - public void Start(bool reverse) - { - float degAngle = reverse ? _closedAngle : _openAngle; - _targetAngle = degToRad(degAngle); - _rotor.RotorLock = false; - _rotor.RotateToAngle(MyRotationDirection.AUTO, degAngle, _velocity); - Running = true; - } - - public bool Check() - { - if (Math.Abs(_rotor.Angle - _targetAngle) < 0.1 && _rotor.Angle == _lastAngle) + _deployAngle = ini.Get(sectionName, "deployAngle").ToSingle(90F); + _stowAngle = ini.Get(sectionName, "stowAngle").ToSingle(0F); + _velocity = ini.Get(sectionName, "velocity").ToSingle(5F); + switch (ini.Get(sectionName, "deployDirection").ToString("auto")) { - return false; + case "auto": + _deployDirection = MyRotationDirection.AUTO; + _stowDirection = MyRotationDirection.AUTO; + break; + case "cw": + _deployDirection = MyRotationDirection.CW; + _stowDirection = MyRotationDirection.CCW; + break; + case "ccw": + _deployDirection = MyRotationDirection.CCW; + _stowDirection = MyRotationDirection.CW; + break; } - _lastAngle = _rotor.Angle; - return true; + Step = ini.Get(sectionName, "step").ToInt32(0); } - public void Finish() + public IEnumerator Run(bool deploy = true) { + float _targetAngle = setup(deploy); + + float _lastAngle = _rotor.Angle; + while (Math.Abs(_rotor.Angle - _targetAngle) > 0.1 || _rotor.Angle != _lastAngle) + { + _lastAngle = _rotor.Angle; + yield return true; + } + _rotor.RotorLock = true; Running = false; } + private float setup(bool deploy = true) + { + float degAngle = deploy ? _deployAngle : _stowAngle; + MyRotationDirection dir = deploy ? _deployDirection : _stowDirection; + + _rotor.RotorLock = false; + _rotor.RotateToAngle(dir, degAngle, _velocity); + Running = true; + + return degToRad(degAngle); + } + private float degToRad(float degrees) { return degrees * ((float)Math.PI / 180F); diff --git a/Mixins/Sequencer/Sequencer.cs b/Mixins/Sequencer/Sequencer.cs index 3f4168f..19d0e1b 100644 --- a/Mixins/Sequencer/Sequencer.cs +++ b/Mixins/Sequencer/Sequencer.cs @@ -34,7 +34,7 @@ namespace IngameScript // To activate the Sequencer, call this once, then call `MoveNext()` once per tick // on the returned object until it returns false. // (then be sure to call `Dispose() on that object`) - public IEnumerator RunSequence(bool reverse = false) + public IEnumerator RunSequence(bool deploy = true) { if (Running) { @@ -44,36 +44,30 @@ namespace IngameScript // This is a bit convoluted, but we're extracting the iterator for use in the foreach directly. // This allows us to iterate in reverse when reversing/"closing" the sequence. - IEnumerable>> steps = reverse ? _sequence.Reverse() : _sequence; + IEnumerable>> steps = deploy ? _sequence : _sequence.Reverse(); foreach (KeyValuePair> kvp in steps) { List blocks = kvp.Value; + List> subJobs = new List>(); Running = true; foreach (ISequenceable block in blocks) { - // TODO: add some sort of handling for block.Running == true - block.Start(reverse); + // TODO: add some sort of handling for block.Running == true, maybe? + // It *should* be an impossible case, but... + subJobs.Add(block.Run(deploy)); } - yield return true; while (Running) { Running = false; - foreach (ISequenceable block in blocks) + foreach (IEnumerator subJob in subJobs) { - if (block.Check()) Running = true; + if (subJob.MoveNext()) Running = true; } yield return true; } - - foreach (ISequenceable block in blocks) - { - block.Finish(); - } } - - yield break; } } }