Configure Mechanical Door to use CustomData for configuration. Also refactor Sequenceables to use the yield enumerator pattern.
This commit is contained in:
parent
8c55176aed
commit
c8babebaef
|
@ -24,21 +24,20 @@ namespace IngameScript
|
||||||
_doors = new Dictionary<string, Sequencer>();
|
_doors = new Dictionary<string, Sequencer>();
|
||||||
|
|
||||||
List<IMyTerminalBlock> doorBlocks = new List<IMyTerminalBlock>();
|
List<IMyTerminalBlock> doorBlocks = new List<IMyTerminalBlock>();
|
||||||
GridTerminalSystem.GetBlocksOfType<IMyTerminalBlock>(doorBlocks, block => block.CustomName.Contains("!Door"));
|
GridTerminalSystem.GetBlocksOfType(doorBlocks, block => MyIni.HasSection(block.CustomData, "mechDoor"));
|
||||||
foreach (IMyTerminalBlock block in doorBlocks)
|
foreach (IMyTerminalBlock block in doorBlocks)
|
||||||
{
|
{
|
||||||
string doorName = Utils.ExtractTag(block, "!Door");
|
_ini.TryParse(block.CustomData);
|
||||||
|
string doorName = _ini.Get("mechDoor", "id").ToString();
|
||||||
// Create the door if this is a new tag
|
// Create the door if this is a new id
|
||||||
if (!_doors.ContainsKey(doorName))
|
if (!_doors.ContainsKey(doorName))
|
||||||
{
|
{
|
||||||
_doors[doorName] = new Sequencer(doorName, new PrefixedConsole(_console, doorName));
|
_doors[doorName] = new Sequencer(doorName, new PrefixedConsole(_console, doorName));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the part; the Door object handles typing and sequencing.
|
// Add the part; the Door object handles typing and sequencing.
|
||||||
int defaultStep = 1;
|
ISequenceable wrapped = SequenceableFactory.MakeSequenceable(block, _ini, "mechDoor");
|
||||||
if (block is IMyShipMergeBlock) defaultStep = 0;
|
if (!(block is IMyShipMergeBlock)) wrapped.Step = 1;
|
||||||
ISequenceable wrapped = SequenceableFactory.MakeSequenceable(block, _ini, defaultStep);
|
|
||||||
if (wrapped == null) { _console.Print($"Tried to add incompatible block '{block.CustomName}'"); continue; }
|
if (wrapped == null) { _console.Print($"Tried to add incompatible block '{block.CustomName}'"); continue; }
|
||||||
_doors[doorName].AddBlock(wrapped);
|
_doors[doorName].AddBlock(wrapped);
|
||||||
}
|
}
|
||||||
|
@ -68,7 +67,7 @@ namespace IngameScript
|
||||||
|
|
||||||
for (int i = 0; i < _cli.ArgumentCount; i++)
|
for (int i = 0; i < _cli.ArgumentCount; i++)
|
||||||
{
|
{
|
||||||
string key = "Door" + _cli.Argument(i);
|
string key = _cli.Argument(i);
|
||||||
if (!_doors.ContainsKey(key))
|
if (!_doors.ContainsKey(key))
|
||||||
{
|
{
|
||||||
_console.Print($"Door '{key}' not found. Skipping.");
|
_console.Print($"Door '{key}' not found. Skipping.");
|
||||||
|
@ -89,10 +88,10 @@ namespace IngameScript
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_console.Print("Creating new job(s).");
|
_console.Print("Creating new job(s).");
|
||||||
bool close = _cli.Switch("close");
|
bool deploy = _cli.Switch("deploy") || _cli.Switch("open");
|
||||||
foreach (Sequencer door in doorsToControl)
|
foreach (Sequencer door in doorsToControl)
|
||||||
{
|
{
|
||||||
_jobs.Add(door.RunSequence(close));
|
_jobs.Add(door.RunSequence(deploy));
|
||||||
}
|
}
|
||||||
Runtime.UpdateFrequency |= UpdateFrequency.Update1;
|
Runtime.UpdateFrequency |= UpdateFrequency.Update1;
|
||||||
}
|
}
|
||||||
|
@ -101,13 +100,12 @@ namespace IngameScript
|
||||||
// Process running jobs
|
// Process running jobs
|
||||||
for (int i = 0; i < _jobs.Count; i++)
|
for (int i = 0; i < _jobs.Count; i++)
|
||||||
{
|
{
|
||||||
if (!_jobs[i].MoveNext())
|
if (_jobs[i].MoveNext()) continue;
|
||||||
{
|
|
||||||
_jobs[i].Dispose();
|
_jobs[i].Dispose();
|
||||||
_jobs.Remove(_jobs[i]);
|
_jobs.Remove(_jobs[i]);
|
||||||
i--;
|
i--;
|
||||||
_console.Print("Operation Complete.");
|
_console.Print("Operation Complete.");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_jobs.Count == 0)
|
if (_jobs.Count == 0)
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace IngameScript
|
namespace IngameScript
|
||||||
{
|
{
|
||||||
partial class Program
|
partial class Program
|
||||||
|
@ -5,10 +7,8 @@ namespace IngameScript
|
||||||
public interface ISequenceable
|
public interface ISequenceable
|
||||||
{
|
{
|
||||||
bool Running { get; }
|
bool Running { get; }
|
||||||
int Step { get; }
|
int Step { get; set; }
|
||||||
void Start(bool reverse = true);
|
IEnumerator<bool> Run(bool deploy);
|
||||||
bool Check();
|
|
||||||
void Finish();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -13,11 +13,11 @@ namespace IngameScript
|
||||||
public static ISequenceable MakeSequenceable(
|
public static ISequenceable MakeSequenceable(
|
||||||
IMyTerminalBlock block,
|
IMyTerminalBlock block,
|
||||||
MyIni ini,
|
MyIni ini,
|
||||||
int step = 0)
|
string sectionName = "sequence")
|
||||||
{
|
{
|
||||||
if (block is IMyMotorStator)
|
if (block is IMyMotorStator)
|
||||||
{
|
{
|
||||||
return new SequenceableRotor(block as IMyMotorStator, ini, step);
|
return new SequenceableRotor(block as IMyMotorStator, ini, sectionName);
|
||||||
}
|
}
|
||||||
if (block is IMyPistonBase)
|
if (block is IMyPistonBase)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using Sandbox.ModAPI.Ingame;
|
using Sandbox.ModAPI.Ingame;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using VRage.Game.ModAPI.Ingame.Utilities;
|
using VRage.Game.ModAPI.Ingame.Utilities;
|
||||||
|
|
||||||
namespace IngameScript
|
namespace IngameScript
|
||||||
|
@ -9,55 +10,71 @@ namespace IngameScript
|
||||||
public class SequenceableRotor : ISequenceable
|
public class SequenceableRotor : ISequenceable
|
||||||
{
|
{
|
||||||
public bool Running { get; private set; } = false;
|
public bool Running { get; private set; } = false;
|
||||||
public int Step { get; private set; }
|
public int Step { get; set; }
|
||||||
|
|
||||||
private float _targetAngle;
|
|
||||||
private float _lastAngle;
|
|
||||||
|
|
||||||
private float _velocity;
|
private float _velocity;
|
||||||
private float _openAngle;
|
private float _deployAngle;
|
||||||
private float _closedAngle;
|
private float _stowAngle;
|
||||||
private IMyMotorStator _rotor;
|
private IMyMotorStator _rotor;
|
||||||
|
private MyRotationDirection _deployDirection;
|
||||||
|
private MyRotationDirection _stowDirection;
|
||||||
|
|
||||||
public SequenceableRotor(
|
public SequenceableRotor(
|
||||||
IMyMotorStator rotor,
|
IMyMotorStator rotor,
|
||||||
MyIni ini,
|
MyIni ini,
|
||||||
int defaultStep = 0)
|
string sectionName)
|
||||||
{
|
{
|
||||||
_rotor = rotor;
|
_rotor = rotor;
|
||||||
|
|
||||||
ini.TryParse(rotor.CustomData);
|
ini.TryParse(rotor.CustomData);
|
||||||
_openAngle = ini.Get("sequencer", "openAngle").ToSingle(90F);
|
_deployAngle = ini.Get(sectionName, "deployAngle").ToSingle(90F);
|
||||||
_closedAngle = ini.Get("sequencer", "closedAngle").ToSingle(0F);
|
_stowAngle = ini.Get(sectionName, "stowAngle").ToSingle(0F);
|
||||||
_velocity = ini.Get("sequencer", "velocity").ToSingle(5F);
|
_velocity = ini.Get(sectionName, "velocity").ToSingle(5F);
|
||||||
Step = ini.Get("sequencer", "step").ToInt32(defaultStep);
|
switch (ini.Get(sectionName, "deployDirection").ToString("auto"))
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
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;
|
Step = ini.Get(sectionName, "step").ToInt32(0);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Finish()
|
public IEnumerator<bool> 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;
|
_rotor.RotorLock = true;
|
||||||
Running = false;
|
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)
|
private float degToRad(float degrees)
|
||||||
{
|
{
|
||||||
return degrees * ((float)Math.PI / 180F);
|
return degrees * ((float)Math.PI / 180F);
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace IngameScript
|
||||||
// To activate the Sequencer, call this once, then call `MoveNext()` once per tick
|
// To activate the Sequencer, call this once, then call `MoveNext()` once per tick
|
||||||
// on the returned object until it returns false.
|
// on the returned object until it returns false.
|
||||||
// (then be sure to call `Dispose() on that object`)
|
// (then be sure to call `Dispose() on that object`)
|
||||||
public IEnumerator<bool> RunSequence(bool reverse = false)
|
public IEnumerator<bool> RunSequence(bool deploy = true)
|
||||||
{
|
{
|
||||||
if (Running)
|
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 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.
|
// This allows us to iterate in reverse when reversing/"closing" the sequence.
|
||||||
IEnumerable<KeyValuePair<int, List<ISequenceable>>> steps = reverse ? _sequence.Reverse() : _sequence;
|
IEnumerable<KeyValuePair<int, List<ISequenceable>>> steps = deploy ? _sequence : _sequence.Reverse();
|
||||||
foreach (KeyValuePair<int, List<ISequenceable>> kvp in steps)
|
foreach (KeyValuePair<int, List<ISequenceable>> kvp in steps)
|
||||||
{
|
{
|
||||||
List<ISequenceable> blocks = kvp.Value;
|
List<ISequenceable> blocks = kvp.Value;
|
||||||
|
List<IEnumerator<bool>> subJobs = new List<IEnumerator<bool>>();
|
||||||
Running = true;
|
Running = true;
|
||||||
|
|
||||||
foreach (ISequenceable block in blocks)
|
foreach (ISequenceable block in blocks)
|
||||||
{
|
{
|
||||||
// TODO: add some sort of handling for block.Running == true
|
// TODO: add some sort of handling for block.Running == true, maybe?
|
||||||
block.Start(reverse);
|
// It *should* be an impossible case, but...
|
||||||
|
subJobs.Add(block.Run(deploy));
|
||||||
}
|
}
|
||||||
yield return true;
|
|
||||||
|
|
||||||
while (Running)
|
while (Running)
|
||||||
{
|
{
|
||||||
Running = false;
|
Running = false;
|
||||||
foreach (ISequenceable block in blocks)
|
foreach (IEnumerator<bool> subJob in subJobs)
|
||||||
{
|
{
|
||||||
if (block.Check()) Running = true;
|
if (subJob.MoveNext()) Running = true;
|
||||||
}
|
}
|
||||||
yield return true;
|
yield return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (ISequenceable block in blocks)
|
|
||||||
{
|
|
||||||
block.Finish();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
yield break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user