CSharp · Console
using System;
using System.Collections.Generic;
using System.Threading;
namespace ConsoleApplication1
{
public class Program
{
public static void Main(string[] args)
{
var l = new Looper();
l.Loop();
}
}
public class Looper
{
public Looper()
{
for (var i = 0; i < 5; i++)
{
var e = new Entity
{
CurrentScript = new BlahScript()
};
Entities.Add(e);
}
}
private List<Entity> Entities { get; } = new List<Entity>();
public void Loop()
{
while (true)
{
foreach (var e in Entities)
{
var script = e.CurrentScript;
if (script.IsReadyToContinue)
{
script.Run();
}
}
Console.WriteLine("Tick");
if (Entities.TrueForAll(x => x.CurrentScript.IsFinished)) break;
Thread.Sleep(500);
}
Console.WriteLine("\nEnd of loop.");
}
}
internal class Entity
{
public IScript CurrentScript { get; set; }
public IContinueTrigger CurrentActionTrigger { get; set; }
}
#region Script
internal interface IScript
{
bool IsReadyToContinue { get; }
bool IsFinished { get; }
void Run();
}
internal abstract class AbstractScript : IScript
{
private readonly IEnumerator<IContinueTrigger> _scriptSteps;
private IContinueTrigger _trigger;
protected AbstractScript()
{
_scriptSteps = RunInner();
}
public void Run()
{
var e = _scriptSteps;
var hasMore = e.MoveNext();
if (!hasMore)
{
IsFinished = true;
_trigger = null;
return;
}
_trigger = e.Current;
}
public bool IsReadyToContinue => _trigger?.IsReady ?? true;
public bool IsFinished { get; private set; }
public abstract IEnumerator<IContinueTrigger> RunInner();
protected IContinueTrigger SleepOne()
{
return new ContinueImmediatelyTrigger();
}
protected IContinueTrigger Sleep(TimeSpan ts)
{
return new ContinueAfterElapsedTimeTrigger(ts);
}
}
internal class BlahScript : AbstractScript
{
public override IEnumerator<IContinueTrigger> RunInner()
{
Console.WriteLine("Hi there!");
yield return SleepOne();
Console.WriteLine("Let's talk in a few seconds...");
yield return Sleep(TimeSpan.FromSeconds(3));
Console.WriteLine("Scratch that, I have to go. :(");
}
}
#endregion
#region Continue triggers
internal interface IContinueTrigger
{
bool IsReady { get; }
}
internal class ContinueImmediatelyTrigger : IContinueTrigger
{
public bool IsReady => true;
}
internal class ContinueAfterElapsedTimeTrigger : IContinueTrigger
{
private readonly DateTime _timeToRun;
public ContinueAfterElapsedTimeTrigger(TimeSpan ts)
{
_timeToRun = DateTime.Now.Add(ts);
}
public bool IsReady => DateTime.Now >= _timeToRun;
}
#endregion
}