diff --git a/Space Engineers/acd-firqmod.cs b/Space Engineers/acd-firqmod.cs new file mode 100644 index 0000000..0851af3 --- /dev/null +++ b/Space Engineers/acd-firqmod.cs @@ -0,0 +1,105 @@ +/* + * README + * ----------- + * + * The AutoCloseDoor-script will monitor and after a (configurade) deley automatically clos eht door for you. + * It will only monitor doors within the same 'construct' (same "mechanical group", not Connectors) + * + * Tag a door with [ACD] (including brackets) in its name to have the AutoCloseDoor-script watch it and automatically close if after 3 seconds. + * + * You can also tag it with [ACD 10] to auto-close after 10 seconds (you can write whatever delay you want) + * + * ----------- + * + * This version has been slightly modified by Firq. All credit goes to the original author Ninlin (https://steamcommunity.com/sharedfiles/filedetails/?id=2371860127) + */ + +public Program() { + Runtime.UpdateFrequency = UpdateFrequency.Update100; +} + +const int DefaultTimeout = 3; +const string TAG = "[ACD"; +readonly int TAGlen = TAG.Length; + +private Dictionary < string, OpenDoor > openDoors = new Dictionary < string, OpenDoor > (); + +public void Main(string argument, UpdateType updateSource) { + int iDetectedDoors = 0; + int iOpenDoors = 0; + int iClosedDoors = 0; + + var doors = new List < IMyDoor > (); + GridTerminalSystem.GetBlocksOfType < IMyDoor > (doors, (IMyDoor d) => (d.CustomName.Contains(TAG) && d.IsSameConstructAs(Me))); + foreach(var door in doors) { + iDetectedDoors++; + if (door.Status == DoorStatus.Open) + iOpenDoors += handleOpenDoor(door); + } + + int iCloseFailed = 0; + + var now = DateTime.UtcNow; + List < string > removeNames = null; + foreach(var opendoor in openDoors) { + if (opendoor.Value.Expired) { + var d = GridTerminalSystem.GetBlockWithId(opendoor.Value.ID) as IMyDoor; + if (d != null) { + iClosedDoors++; + d.CloseDoor(); + if (removeNames == null) + removeNames = new List < string > (); + removeNames.Add(opendoor.Key); + } else + iCloseFailed++; + } + } + if (removeNames != null) + foreach(var name in removeNames) + openDoors.Remove(name); + + var msg = string.Format("\n\nAutoCloseDoors\n----------------------------\nCurrent Time: {0}\nGuarding {1} {2}", + now.ToLocalTime().ToLongTimeString(), iDetectedDoors, (iDetectedDoors == 1 ? "door" : "doors")); + if (iOpenDoors > 0) + msg += string.Format("\n{0} {1} currently open", iOpenDoors, (iOpenDoors == 1 ? "door is" : "doors are")); + if (iClosedDoors > 0) + msg += string.Format("\n{0} {1} closed", iClosedDoors, (iClosedDoors == 1 ? "door was" : "doors were")); + if (iCloseFailed > 0) + msg += string.Format("\n{0} {1} failed to close", iCloseFailed, (iCloseFailed == 1 ? "door" : "doors")); + var screen = Me.GetSurface(0); + screen.ContentType = ContentType.TEXT_AND_IMAGE; + screen.Alignment = TextAlignment.CENTER; + screen.WriteText(msg, false); + + Echo(msg); +} + +private class OpenDoor { + public long ID; + public DateTime Timeout; + + public OpenDoor(IMyDoor door, int timeout) { + if (timeout <= 0) + timeout = DefaultTimeout; + ID = door.GetId(); + Timeout = DateTime.UtcNow.AddSeconds(timeout); + } + + public bool Expired => Timeout < DateTime.UtcNow; +} + +private int handleOpenDoor(IMyDoor door) { + string tag = door.CustomName.Substring(door.CustomName.IndexOf(TAG) + TAGlen); + int end = tag.IndexOf(']'); + if (end < 0) { + return 0; + } + tag = tag.Substring(0, end); + int timeout; + int.TryParse(tag, out timeout); + if (!openDoors.ContainsKey(door.Name)) { + openDoors.Add(door.Name, new OpenDoor(door, timeout)); + return 1; + } + return 1; +} \ No newline at end of file