Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of AutoCloseDoors v1.1.0
Mods/AutoCloseDoors.dll
Decompiled a day agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using AutoCloseDoors; using HarmonyLib; using Il2CppFishNet.Object; using Il2CppScheduleOne.Doors; using MelonLoader; using MelonLoader.Utils; using Microsoft.CodeAnalysis; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(/*Could not decode attribute arguments.*/)] [assembly: MelonInfo(typeof(Mod), "Auto Close Doors", "1.1.0", "Primal", null)] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: AssemblyVersion("0.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : System.Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(/*Could not decode attribute arguments.*/)] internal sealed class RefSafetyRulesAttribute : System.Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace AutoCloseDoors { public sealed class Mod : MelonMod { [field: CompilerGenerated] internal static Settings Config { [CompilerGenerated] get; [CompilerGenerated] private set; } = new Settings(); public override void OnInitializeMelon() { string text = Path.Combine(MelonEnvironment.UserDataDirectory, "AutoCloseDoors.cfg"); Config = Settings.Load(text, delegate(string message) { MelonLogger.Warning(message); }); ((MelonBase)this).LoggerInstance.Msg(Config.Enabled ? $"Doors left open for {Config.CloseDelaySeconds} seconds will close. Multiplayer: run on the host." : "Automatic door closing is disabled."); ((MelonBase)this).LoggerInstance.Msg("Configuration (restart the game after editing): " + text); } } [HarmonyPatch(typeof(DoorController), "Update")] internal static class DoorUpdatePatch { private static bool failed; private static void Postfix(DoorController __instance) { if (failed || !Mod.Config.Enabled) { return; } try { if (((NetworkBehaviour)__instance).IsServerInitialized && __instance.IsOpen && __instance.timeInCurrentState >= Mod.Config.CloseDelaySeconds) { __instance.SetIsOpen_Server(false, (EDoorSide)0, false); } } catch (System.Exception ex) { failed = true; MelonLogger.Error("Auto Close Doors disabled after an error: " + (object)ex); } } } internal sealed class Settings { internal const string DefaultFile = "# Auto Close Doors configuration\n# Keep this file in the game's UserData folder.\n# Restart the game after making changes. Multiplayer: the host controls doors.\n\n# true = auto close enabled; false = disabled\nEnabled = true\n\n# Seconds doors remain open. Must be greater than 0; decimals use a dot.\nCloseDelaySeconds = 5\n"; [field: CompilerGenerated] internal bool Enabled { [CompilerGenerated] get; [CompilerGenerated] private set; } = true; [field: CompilerGenerated] internal float CloseDelaySeconds { [CompilerGenerated] get; [CompilerGenerated] private set; } = 5f; internal static Settings Load(string path, Action<string> warn) { Settings settings = new Settings(); try { if (!File.Exists(path)) { Directory.CreateDirectory(Path.GetDirectoryName(Path.GetFullPath(path))); File.WriteAllText(path, "# Auto Close Doors configuration\n# Keep this file in the game's UserData folder.\n# Restart the game after making changes. Multiplayer: the host controls doors.\n\n# true = auto close enabled; false = disabled\nEnabled = true\n\n# Seconds doors remain open. Must be greater than 0; decimals use a dot.\nCloseDelaySeconds = 5\n"); return settings; } int num = 0; System.Collections.Generic.IEnumerator<string> enumerator = File.ReadLines(path).GetEnumerator(); try { bool enabled = default(bool); float num3 = default(float); while (((System.Collections.IEnumerator)enumerator).MoveNext()) { string current = enumerator.Current; num++; string text = current.Split(new char[2] { '#', ';' }, 2)[0].Trim(); if (text.Length == 0) { continue; } int num2 = text.IndexOf('='); if (num2 < 1) { warn.Invoke($"AutoCloseDoors.cfg line {num}: expected key = value."); continue; } string text2 = text.Substring(0, num2).Trim(); string text3 = text.Substring(num2 + 1).Trim(); if (text2.Equals("Enabled", (StringComparison)5)) { if (bool.TryParse(text3, ref enabled)) { settings.Enabled = enabled; continue; } settings.Enabled = true; warn.Invoke("AutoCloseDoors.cfg: Enabled must be true or false; using true."); } else if (text2.Equals("CloseDelaySeconds", (StringComparison)5)) { if (float.TryParse(text3, (NumberStyles)167, (IFormatProvider)(object)CultureInfo.InvariantCulture, ref num3) && !float.IsNaN(num3) && !float.IsInfinity(num3) && num3 > 0f) { settings.CloseDelaySeconds = num3; continue; } settings.CloseDelaySeconds = 5f; warn.Invoke("AutoCloseDoors.cfg: CloseDelaySeconds must be a finite number greater than 0; using 5."); } else { warn.Invoke($"AutoCloseDoors.cfg line {num}: unknown setting '{text2}'."); } } } finally { ((System.IDisposable)enumerator)?.Dispose(); } return settings; } catch (System.Exception ex) when (ex is IOException || ex is UnauthorizedAccessException) { warn.Invoke("Could not read or create AutoCloseDoors.cfg; using defaults. " + ex.Message); return new Settings(); } } } }