74 lines
2.9 KiB
C#
74 lines
2.9 KiB
C#
// Represents a single set of blocks to run in order, waiting for each group's completion before
|
|
// moving on to the next one.
|
|
|
|
using Sandbox.ModAPI.Ingame;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace IngameScript
|
|
{
|
|
partial class Program
|
|
{
|
|
public class Sequencer
|
|
{
|
|
public bool Running { get; private set; }
|
|
public string Name { get; private set; }
|
|
|
|
private IConsole _console;
|
|
|
|
private SortedDictionary<int, List<ISequenceable>> _sequence = new SortedDictionary<int, List<ISequenceable>>();
|
|
|
|
public Sequencer(Program program, string name)
|
|
{
|
|
Name = name;
|
|
_console = new PrefixedConsole(program.Console, Name);
|
|
}
|
|
|
|
public void AddBlock(ISequenceable block)
|
|
{
|
|
if (!_sequence.ContainsKey(block.Step)) _sequence[block.Step] = new List<ISequenceable>();
|
|
_sequence[block.Step].Add(block);
|
|
}
|
|
|
|
// 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<bool> RunSequence(bool deploy = true)
|
|
{
|
|
if (Running)
|
|
{
|
|
_console.Print("Already running, ignoring invocation.");
|
|
yield break;
|
|
}
|
|
|
|
// 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<KeyValuePair<int, List<ISequenceable>>> steps = deploy ? _sequence : _sequence.Reverse();
|
|
foreach (KeyValuePair<int, List<ISequenceable>> kvp in steps)
|
|
{
|
|
List<ISequenceable> blocks = kvp.Value;
|
|
List<IEnumerator<bool>> subJobs = new List<IEnumerator<bool>>();
|
|
Running = true;
|
|
|
|
foreach (ISequenceable block in blocks)
|
|
{
|
|
// TODO: add some sort of handling for block.Running == true, maybe?
|
|
// It *should* be an impossible case, but...
|
|
subJobs.Add(block.Run(deploy));
|
|
}
|
|
|
|
while (Running)
|
|
{
|
|
Running = false;
|
|
foreach (IEnumerator<bool> subJob in subJobs)
|
|
{
|
|
if (subJob.MoveNext()) Running = true;
|
|
}
|
|
yield return true;
|
|
}
|
|
foreach (IEnumerator<bool> subJob in subJobs) subJob.Dispose(); // clean up after ourselves
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |