space_engineers/MechanicalDoor/Program.cs
2025-02-07 21:06:24 -05:00

149 lines
4.6 KiB
C#

using Sandbox.ModAPI.Ingame;
using System.Collections.Generic;
using VRage.Game.ModAPI.Ingame.Utilities;
namespace IngameScript
{
public partial class Program : MyGridProgram
{
private MyCommandLine _cli;
private List<IEnumerator<bool>> _jobs;
private Dictionary<string, Door> _doors;
private int _tickCount;
public Program()
{
_tickCount = 0;
_cli = new MyCommandLine();
_jobs = new List<IEnumerator<bool>>();
_doors = new Dictionary<string, Door>();
List<IMyMotorStator> allHinges = new List<IMyMotorStator>();
GridTerminalSystem.GetBlocksOfType(allHinges);
foreach (IMyMotorStator hinge in allHinges)
{
if (hinge.CustomName.StartsWith("Door"))
{
string doorName = hinge.CustomName.Split(' ')[0];
if (!_doors.ContainsKey(doorName))
{
_doors[doorName] = new Door(this);
}
_doors[doorName].AddHinge(hinge);
}
}
Echo($"Found {_doors.Keys.Count} doors.");
}
public void Main(string argument, UpdateType updateSource)
{
Echo($"index: {_tickCount++}");
if (updateSource == UpdateType.Trigger || updateSource == UpdateType.Terminal)
{
// Create a new job
_cli.TryParse(argument);
List<Door> doorsToControl = new List<Door>();
if (_cli.ArgumentCount == 0)
{
Echo("No arguments passed. Controlling all doors.");
foreach (Door door in _doors.Values)
{
if (!door.Locked)
{
continue;
}
doorsToControl.Add(door);
}
}
for (int i = 0; i < _cli.ArgumentCount; i++)
{
string key = "Door" + _cli.Argument(i);
if (!_doors.ContainsKey(key))
{
Echo($"Door with identifier {key} not found. Skipping.");
continue;
}
if (!_doors[key].Locked)
{
Echo($"Door {key} already moving. Skipping.");
continue;
}
doorsToControl.Add(_doors[key]);
}
if (doorsToControl.Count == 0)
{
Echo("No doors found. Not creating new job.");
}
else
{
Echo("Creating new job.");
if (_cli.Switch("close")) _jobs.Add(closeDoors(doorsToControl));
else _jobs.Add(openDoors(doorsToControl));
Runtime.UpdateFrequency = UpdateFrequency.Update1;
}
}
// Process running jobs
for (int i = 0; i < _jobs.Count; i++)
{
if (!_jobs[i].MoveNext())
{
_jobs[i].Dispose();
_jobs.Remove(_jobs[i]);
i--;
Echo("Operation Complete.");
}
}
if (_jobs.Count == 0)
{
Runtime.UpdateFrequency = UpdateFrequency.None;
}
}
private IEnumerator<bool> openDoors(List<Door> doorsToControl)
{
Echo("Opening doors.");
foreach (Door door in doorsToControl)
{
door.OpenDoor();
}
return actuateDoors(doorsToControl);
}
private IEnumerator<bool> closeDoors(List<Door> doorsToControl)
{
Echo("Closing doors.");
foreach (Door door in doorsToControl)
{
door.CloseDoor();
}
return actuateDoors(doorsToControl);
}
private IEnumerator<bool> actuateDoors(List<Door> doorsToControl)
{
while (true)
{
Echo("Actuating doors.");
bool done = true; // assume we've finished, then falsify it below
foreach (Door door in doorsToControl)
{
if (!door.Actuate())
{
done = false;
}
}
if (done) yield break;
yield return true;
}
}
}
}