Convert mechanical door script to use MDK2.
This commit is contained in:
parent
f0f7aa9030
commit
13e1f9d63c
32
.gitignore
vendored
Normal file
32
.gitignore
vendored
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
*.swp
|
||||||
|
*.*~
|
||||||
|
project.lock.json
|
||||||
|
.DS_Store
|
||||||
|
*.pyc
|
||||||
|
nupkg/
|
||||||
|
|
||||||
|
# Visual Studio Code
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
build/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Oo]ut/
|
||||||
|
msbuild.log
|
||||||
|
msbuild.err
|
||||||
|
msbuild.wrn
|
57
MechanicalDoor/Door.cs
Normal file
57
MechanicalDoor/Door.cs
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
using Sandbox.ModAPI.Ingame;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace IngameScript
|
||||||
|
{
|
||||||
|
public class Door
|
||||||
|
{
|
||||||
|
public Door()
|
||||||
|
{
|
||||||
|
Hinges = new List<DoorHinge>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a hinge to the door
|
||||||
|
public void AddHinge(IMyMotorStator hinge)
|
||||||
|
{
|
||||||
|
Hinges.Add(new DoorHinge(hinge));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OpenDoor()
|
||||||
|
{
|
||||||
|
foreach (DoorHinge hinge in Hinges)
|
||||||
|
{
|
||||||
|
hinge.OpenDoorHinge();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CloseDoor()
|
||||||
|
{
|
||||||
|
foreach (DoorHinge hinge in Hinges)
|
||||||
|
{
|
||||||
|
hinge.CloseDoorHinge();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process the door's movement. This will return true when the door is done moving.
|
||||||
|
public bool Actuate()
|
||||||
|
{
|
||||||
|
bool done = true;
|
||||||
|
foreach (DoorHinge hinge in Hinges)
|
||||||
|
{
|
||||||
|
if (!hinge.Actuate()) done = false;
|
||||||
|
}
|
||||||
|
return done;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Locked()
|
||||||
|
{
|
||||||
|
foreach (DoorHinge hinge in Hinges)
|
||||||
|
{
|
||||||
|
if (!hinge.Locked()) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<DoorHinge> Hinges;
|
||||||
|
}
|
||||||
|
}
|
84
MechanicalDoor/DoorHinge.cs
Normal file
84
MechanicalDoor/DoorHinge.cs
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
using Sandbox.ModAPI.Ingame;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace IngameScript
|
||||||
|
{
|
||||||
|
public class DoorHinge
|
||||||
|
{
|
||||||
|
public DoorHinge(IMyMotorStator hinge)
|
||||||
|
{
|
||||||
|
Hinge = hinge;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For these two functions, IMyMotorStator.Angle reports radians, but
|
||||||
|
// IMyMotorStator.RotateToAngle() expects degrees...
|
||||||
|
public void OpenDoorHinge()
|
||||||
|
{
|
||||||
|
Hinge.RotorLock = false;
|
||||||
|
TargetAngle = DegToRad(OpenAngle);
|
||||||
|
Hinge.RotateToAngle(MyRotationDirection.AUTO, OpenAngle, Velocity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CloseDoorHinge()
|
||||||
|
{
|
||||||
|
Hinge.RotorLock = false;
|
||||||
|
TargetAngle = DegToRad(ClosedAngle);
|
||||||
|
Hinge.RotateToAngle(MyRotationDirection.AUTO, ClosedAngle, Velocity);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process the hinge's movement.
|
||||||
|
// It will return true when the panel has finished moving.
|
||||||
|
// TODO: Add a mechanism to determine when a door gets stuck or can't reach the target angle.
|
||||||
|
public bool Actuate()
|
||||||
|
{
|
||||||
|
if (Math.Abs(Hinge.Angle - TargetAngle) < 0.1 && Hinge.Angle == LastAngle)
|
||||||
|
{
|
||||||
|
Hinge.RotorLock = true;
|
||||||
|
}
|
||||||
|
LastAngle = Hinge.Angle;
|
||||||
|
return Locked();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Locked()
|
||||||
|
{
|
||||||
|
return Hinge.RotorLock;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IMyMotorStator Hinge { get; set; }
|
||||||
|
private float TargetAngle { get; set; }
|
||||||
|
private float LastAngle { get; set; }
|
||||||
|
private float OpenAngle { get; set; } = 90F;
|
||||||
|
private float ClosedAngle { get; set; } = 0F;
|
||||||
|
private float Velocity { get; set; } = 5F;
|
||||||
|
|
||||||
|
private void ParseConfig()
|
||||||
|
{
|
||||||
|
string[] lines = Hinge.CustomData.Split('\n');
|
||||||
|
foreach (string line in lines)
|
||||||
|
{
|
||||||
|
string[] tokens = line.Split('=');
|
||||||
|
if (tokens.Length != 2) continue;
|
||||||
|
switch (tokens[0])
|
||||||
|
{
|
||||||
|
case "OpenAngle":
|
||||||
|
OpenAngle = float.Parse(tokens[1]);
|
||||||
|
break;
|
||||||
|
case "ClosedAngle":
|
||||||
|
ClosedAngle = float.Parse(tokens[1]);
|
||||||
|
break;
|
||||||
|
case "Velocity":
|
||||||
|
Velocity = float.Parse(tokens[1]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: a utility class or function would be lovely...
|
||||||
|
// In general, the encapsulation feels a little screwy here.
|
||||||
|
private float DegToRad(float degrees)
|
||||||
|
{
|
||||||
|
return degrees * ((float)Math.PI / 180F);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
27
MechanicalDoor/MechanicalDoor.csproj
Normal file
27
MechanicalDoor/MechanicalDoor.csproj
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netframework48</TargetFramework>
|
||||||
|
<RootNamespace>IngameScript</RootNamespace>
|
||||||
|
<LangVersion>6</LangVersion>
|
||||||
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
|
<Configurations>Release;Debug</Configurations>
|
||||||
|
<Platforms>x64</Platforms>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Mal.Mdk2.PbAnalyzers" Version="2.1.11">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Mal.Mdk2.PbPackager" Version="2.1.1">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Mal.Mdk2.References" Version="2.2.4" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Remove="Instructions.readme" />
|
||||||
|
<AdditionalFiles Include="Instructions.readme" />
|
||||||
|
<AdditionalFiles Include="thumb.png" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="../Mixins/JobDispatcher/JobDispatcher.projitems" Label="JobDispatcher" />
|
||||||
|
</Project>
|
22
MechanicalDoor/MechanicalDoor.mdk.ini
Normal file
22
MechanicalDoor/MechanicalDoor.mdk.ini
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
; This file is project specific and should be checked in to source control.
|
||||||
|
|
||||||
|
[mdk]
|
||||||
|
; This is a programmable block script project.
|
||||||
|
; You should not change this.
|
||||||
|
type=programmableblock
|
||||||
|
|
||||||
|
; Toggle trace (on|off) (verbose output)
|
||||||
|
trace=off
|
||||||
|
|
||||||
|
; What type of minification to use (none|trim|stripcomments|lite|full)
|
||||||
|
; none: No minification
|
||||||
|
; trim: Removes unused types (NOT members).
|
||||||
|
; stripcomments: trim + removes comments.
|
||||||
|
; lite: stripcomments + removes leading/trailing whitespace.
|
||||||
|
; full: lite + renames identifiers to shorter names.
|
||||||
|
minify=none
|
||||||
|
|
||||||
|
; A list of files and folder to ignore when creating the script.
|
||||||
|
; This is a comma separated list of glob patterns.
|
||||||
|
; See https://code.visualstudio.com/docs/editor/glob-patterns
|
||||||
|
ignores=obj/**/*,MDK/**/*,**/*.debug.cs
|
7
MechanicalDoor/MechanicalDoor.mdk.local.ini
Normal file
7
MechanicalDoor/MechanicalDoor.mdk.local.ini
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
; This file is _local_ to your machine and should not be checked in to source control.
|
||||||
|
|
||||||
|
[mdk]
|
||||||
|
; Where to output the script to (auto|specific path)
|
||||||
|
output=auto
|
||||||
|
; Override the default binary path (auto|specific path)
|
||||||
|
binarypath=auto
|
165
MechanicalDoor/Program.cs
Normal file
165
MechanicalDoor/Program.cs
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
using Sandbox.Game.EntityComponents;
|
||||||
|
using Sandbox.ModAPI.Ingame;
|
||||||
|
using Sandbox.ModAPI.Interfaces;
|
||||||
|
using SpaceEngineers.Game.ModAPI.Ingame;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using VRage;
|
||||||
|
using VRage.Collections;
|
||||||
|
using VRage.Game;
|
||||||
|
using VRage.Game.Components;
|
||||||
|
using VRage.Game.GUI.TextPanel;
|
||||||
|
using VRage.Game.ModAPI.Ingame;
|
||||||
|
using VRage.Game.ModAPI.Ingame.Utilities;
|
||||||
|
using VRage.Game.ObjectBuilders.Definitions;
|
||||||
|
using VRageMath;
|
||||||
|
|
||||||
|
namespace IngameScript
|
||||||
|
{
|
||||||
|
public partial class Program : MyGridProgram
|
||||||
|
{
|
||||||
|
MyCommandLine cli;
|
||||||
|
List<IEnumerator<bool>> jobs;
|
||||||
|
Dictionary<string, Door> doors;
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
20
MechanicalDoor/instructions.readme
Normal file
20
MechanicalDoor/instructions.readme
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
Script for controlling "mechanical" doors, aka custom doors using hinges.
|
||||||
|
|
||||||
|
Future features:
|
||||||
|
* Rotor and piston support.
|
||||||
|
* "Multi-stage doors", e.g. actuate a hinge, then a piston.
|
||||||
|
|
||||||
|
Currently this operates on hinges whose names start with "DoorX", where X is an arbitrary identifier.
|
||||||
|
Usage:
|
||||||
|
Script argument should be a space-separated list of identifiers and either
|
||||||
|
`-open` (default behavior) or `-close`.
|
||||||
|
Failing to pass any identifiers will cause the action to happen to all doors on the grid.
|
||||||
|
|
||||||
|
By default "open" is assumed to be 90 degrees and "closed" is assumed to be 0 degrees.
|
||||||
|
However, each hinge can have this behavior configured via custom data. A sample config
|
||||||
|
(with the default values):
|
||||||
|
|
||||||
|
OpenAngle=90
|
||||||
|
ClosedAngle=0
|
||||||
|
Velocity=5
|
||||||
|
|
BIN
MechanicalDoor/thumb.png
Normal file
BIN
MechanicalDoor/thumb.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 389 KiB |
|
@ -1,246 +0,0 @@
|
||||||
// Script for controlling "mechanical" doors, aka custom doors using hinges.
|
|
||||||
//
|
|
||||||
// Future features:
|
|
||||||
// * Rotor and piston support.
|
|
||||||
// * "Multi-stage doors", e.g. actuate a hinge, then a piston.
|
|
||||||
//
|
|
||||||
// Currently this operates on hinges whose names start with "DoorX", where X is an arbitrary identifier.
|
|
||||||
// Usage:
|
|
||||||
// Script argument should be a space-separated list of identifiers and either
|
|
||||||
// `-open` (default behavior) or `-close`.
|
|
||||||
// Failing to pass any identifiers will cause the action to happen to all doors on the grid.
|
|
||||||
//
|
|
||||||
// By default "open" is assumed to be 90 degrees and "closed" is assumed to be 0 degrees.
|
|
||||||
// However, each hinge can have this behavior configured via custom data. A sample config
|
|
||||||
// (with the default values):
|
|
||||||
//
|
|
||||||
// OpenAngle=90
|
|
||||||
// ClosedAngle=0
|
|
||||||
// Velocity=5
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
MyCommandLine cli;
|
|
||||||
List<IEnumerator<bool>> jobs;
|
|
||||||
Dictionary<string, Door> doors;
|
|
||||||
int tickCount;
|
|
||||||
|
|
||||||
public class DoorHinge {
|
|
||||||
public DoorHinge(Program p, IMyMotorStator hinge) {
|
|
||||||
P = p;
|
|
||||||
Hinge = hinge;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For these two functions, IMyMotorStator.Angle reports radians, but
|
|
||||||
// IMyMotorStator.RotateToAngle() expects degrees...
|
|
||||||
public void OpenDoorHinge() {
|
|
||||||
Hinge.RotorLock = false;
|
|
||||||
TargetAngle = DegToRad(OpenAngle);
|
|
||||||
Hinge.RotateToAngle(MyRotationDirection.AUTO, OpenAngle, Velocity);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CloseDoorHinge() {
|
|
||||||
Hinge.RotorLock = false;
|
|
||||||
TargetAngle = DegToRad(ClosedAngle);
|
|
||||||
Hinge.RotateToAngle(MyRotationDirection.AUTO, ClosedAngle, Velocity);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process the hinge's movement.
|
|
||||||
// It will return true when the panel has finished moving.
|
|
||||||
// TODO: Add a mechanism to determine when a door gets stuck or can't reach the target angle.
|
|
||||||
public bool Actuate() {
|
|
||||||
if (Math.Abs(Hinge.Angle - TargetAngle) < 0.1 && Hinge.Angle == LastAngle) {
|
|
||||||
Hinge.RotorLock = true;
|
|
||||||
}
|
|
||||||
LastAngle = Hinge.Angle;
|
|
||||||
return Locked();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Locked() {
|
|
||||||
return Hinge.RotorLock;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Program P; // for access to Echo, etc.
|
|
||||||
private IMyMotorStator Hinge { get; set; }
|
|
||||||
private float TargetAngle { get; set; }
|
|
||||||
private float LastAngle {get; set; }
|
|
||||||
private float OpenAngle { get; set; } = 90F;
|
|
||||||
private float ClosedAngle { get; set; } = 0F;
|
|
||||||
private float Velocity { get; set; } = 5F;
|
|
||||||
|
|
||||||
private void ParseConfig() {
|
|
||||||
string[] lines = Hinge.CustomData.Split('\n');
|
|
||||||
foreach (string line in lines) {
|
|
||||||
string[] tokens = line.Split('=');
|
|
||||||
if (tokens.Length != 2) continue;
|
|
||||||
switch(tokens[0]) {
|
|
||||||
case "OpenAngle":
|
|
||||||
OpenAngle = float.Parse(tokens[1]);
|
|
||||||
break;
|
|
||||||
case "ClosedAngle":
|
|
||||||
ClosedAngle = float.Parse(tokens[1]);
|
|
||||||
break;
|
|
||||||
case "Velocity":
|
|
||||||
Velocity = float.Parse(tokens[1]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: a utility class or function would be lovely...
|
|
||||||
// In general, the encapsulation feels a little screwy here.
|
|
||||||
private float DegToRad(float degrees) {
|
|
||||||
return degrees * ((float)Math.PI / 180F);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Door {
|
|
||||||
public Door(Program p) {
|
|
||||||
P = p;
|
|
||||||
Hinges = new List<DoorHinge>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a hinge to the door
|
|
||||||
public void AddHinge(IMyMotorStator hinge) {
|
|
||||||
Hinges.Add(new DoorHinge(P, hinge));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OpenDoor() {
|
|
||||||
foreach (DoorHinge hinge in Hinges) {
|
|
||||||
hinge.OpenDoorHinge();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CloseDoor() {
|
|
||||||
foreach (DoorHinge hinge in Hinges) {
|
|
||||||
hinge.CloseDoorHinge();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process the door's movement. This will return true when the door is done moving.
|
|
||||||
public bool Actuate() {
|
|
||||||
bool done = true;
|
|
||||||
foreach (DoorHinge hinge in Hinges) {
|
|
||||||
if (!hinge.Actuate()) done = false;
|
|
||||||
}
|
|
||||||
return done;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Locked() {
|
|
||||||
foreach (DoorHinge hinge in Hinges) {
|
|
||||||
if (!hinge.Locked()) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<DoorHinge> Hinges;
|
|
||||||
private Program P;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user