Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of AutoCloseDoors v1.0.3
Landoria.AutoCloseDoors.dll
Decompiled 8 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Threading; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Landoria.AutoCloseDoors")] [assembly: AssemblyDescription("Automatically closes player-built doors when no player is nearby.")] [assembly: AssemblyCompany("Landoria")] [assembly: AssemblyProduct("Landoria.AutoCloseDoors")] [assembly: AssemblyCopyright("Copyright © 2026 Landoria")] [assembly: ComVisible(false)] [assembly: Guid("92DF0504-5C40-43E7-AC8C-9F36792D6FED")] [assembly: AssemblyFileVersion("1.0.3")] [assembly: AssemblyInformationalVersion("1.0.3")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.3.39085")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Landoria.AutoCloseDoors { internal static class ConfigWatcher { private const int ReloadDelayMilliseconds = 250; private const int MaximumReloadAttempts = 5; private static ConfigFile config; private static string configPath; private static ManualLogSource logger; private static FileSystemWatcher watcher; private static long lastChangeTicks; private static int reloadPending; private static int reloadAttempts; private static long ignoredWriteTicks; private static string displayName; private static Action restoreDefaults; private static Action applyConfiguration; internal static void Initialize(ConfigFile configFile, ManualLogSource logSource, string configurationDisplayName, Action restoreDefaultsAction, Action applyConfigurationAction = null) { Dispose(); config = configFile; logger = logSource; displayName = configurationDisplayName; restoreDefaults = restoreDefaultsAction; applyConfiguration = applyConfigurationAction; configPath = Path.GetFullPath(config.ConfigFilePath); watcher = new FileSystemWatcher(Path.GetDirectoryName(configPath), Path.GetFileName(configPath)); watcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite | NotifyFilters.CreationTime; watcher.Changed += OnChanged; watcher.Created += OnChanged; watcher.Deleted += OnChanged; watcher.Renamed += OnRenamed; watcher.EnableRaisingEvents = true; } internal static void IgnoreCurrentFileVersion() { if (string.IsNullOrEmpty(configPath) || !File.Exists(configPath)) { return; } try { Interlocked.Exchange(ref ignoredWriteTicks, File.GetLastWriteTimeUtc(configPath).Ticks); Interlocked.Exchange(ref reloadPending, 0); } catch (IOException) { ManualLogSource obj = logger; if (obj != null) { obj.LogDebug((object)"Could not mark the internal configuration write."); } } } internal static void Update() { if (Volatile.Read(in reloadPending) == 0 || !ReloadDelayElapsed()) { return; } Interlocked.Exchange(ref reloadPending, 0); try { bool flag = !File.Exists(configPath); if (flag) { restoreDefaults?.Invoke(); } else { config.Reload(); } applyConfiguration?.Invoke(); reloadAttempts = 0; logger.LogInfo((object)(flag ? "Recreated the deleted configuration with default values." : "Reloaded configuration after a file change.")); ShowReloadMessage(flag); } catch (Exception exception) { RetryReload(exception); } } internal static void Dispose() { if (watcher != null) { watcher.EnableRaisingEvents = false; watcher.Dispose(); watcher = null; } Interlocked.Exchange(ref reloadPending, 0); Interlocked.Exchange(ref ignoredWriteTicks, 0L); reloadAttempts = 0; displayName = null; restoreDefaults = null; applyConfiguration = null; } private static void OnChanged(object sender, FileSystemEventArgs eventArgs) { QueueReload(); } private static void OnRenamed(object sender, RenamedEventArgs eventArgs) { QueueReload(); } private static void QueueReload() { if (!IsIgnoredWrite()) { Interlocked.Exchange(ref lastChangeTicks, DateTime.UtcNow.Ticks); Interlocked.Exchange(ref reloadPending, 1); reloadAttempts = 0; } } private static bool IsIgnoredWrite() { try { long num = (File.Exists(configPath) ? File.GetLastWriteTimeUtc(configPath).Ticks : 0); return num != 0L && num == Interlocked.Read(in ignoredWriteTicks); } catch (IOException) { return false; } } private static bool ReloadDelayElapsed() { return DateTime.UtcNow.Ticks - Interlocked.Read(in lastChangeTicks) >= 2500000; } private static void RetryReload(Exception exception) { reloadAttempts++; logger.LogWarning((object)("Configuration reload failed: " + exception.Message)); if (reloadAttempts < 5) { Interlocked.Exchange(ref lastChangeTicks, DateTime.UtcNow.Ticks); Interlocked.Exchange(ref reloadPending, 1); } } private static void ShowReloadMessage(bool recreated) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)1, recreated ? (displayName + " configuration restored to defaults.") : (displayName + " configuration reloaded."), 0, (Sprite)null, false); } } } internal static class DoorChoice { internal static bool IsTarget(Door door) { if ((Object)(object)door == (Object)null || (Object)(object)door.m_keyItem != (Object)null || door.m_canNotBeClosed) { return false; } Piece component = ((Component)door).GetComponent<Piece>(); if ((Object)(object)component != (Object)null) { return component.IsPlacedByPlayer(); } return false; } internal static bool CanClose(Door door) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (IsTarget(door) && (Object)(object)Player.m_localPlayer != (Object)null) { if (door.m_checkGuardStone) { return PrivateArea.CheckAccess(((Component)door).transform.position, 0f, false, false); } return true; } return false; } internal static bool IsEnabled(Door door) { Player localPlayer = Player.m_localPlayer; string text = Key(door, "Enabled"); string key = Key(door, "Disabled"); if ((Object)(object)localPlayer != (Object)null && text != null) { if (localPlayer.m_customData.ContainsKey(text)) { return true; } if (localPlayer.m_customData.ContainsKey(key)) { return false; } } return Plugin.Settings?.EnabledByDefault ?? true; } internal static void Toggle(Door door) { Player localPlayer = Player.m_localPlayer; string text = Key(door, "Enabled"); string text2 = Key(door, "Disabled"); if ((Object)(object)localPlayer == (Object)null || text == null) { return; } bool flag = !IsEnabled(door); localPlayer.m_customData.Remove(text); localPlayer.m_customData.Remove(text2); localPlayer.m_customData[flag ? text : text2] = "1"; if (flag) { ZNetView component = ((Component)door).GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null && component.IsValid() && component.GetZDO().GetInt(ZDOVars.s_state, 0) != 0) { DoorProximity.Track(door); } } else { DoorProximity.Cancel(door); } string text3 = (flag ? "enabled" : "disabled"); ((Character)localPlayer).Message((MessageType)2, "Auto-close " + text3, 0, (Sprite)null, false); } private static string Key(Door door, string choice) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) ZNetView component = ((Component)door).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsValid() || (Object)(object)ZNet.instance == (Object)null) { return null; } ZDOID uid = component.GetZDO().m_uid; return "Landoria.AutoCloseDoors." + choice + ":" + ZNet.instance.GetWorldUID() + ":" + ((ZDOID)(ref uid)).UserID + ":" + ((ZDOID)(ref uid)).ID; } } [HarmonyPatch] internal static class DoorPatches { [HarmonyPatch(typeof(Door), "GetHoverText")] [HarmonyPostfix] private static void Hover(Door __instance, ref string __result) { if (DoorChoice.CanClose(__instance) && !string.IsNullOrEmpty(__result)) { string text = (DoorChoice.IsEnabled(__instance) ? "on" : "off"); string text2 = Localization.instance.Localize("$KEY_Use"); __result = __result + "\n[<color=yellow><b>" + Plugin.Settings.ToggleModifierName + " + " + text2 + "</b></color>] Auto-close: " + text; } } [HarmonyPatch(typeof(Door), "Interact")] [HarmonyPrefix] private static bool Interact(Door __instance, Humanoid character, bool hold, bool alt, ref bool __result, out bool? __state) { //IL_0079: Unknown result type (might be due to invalid IL or missing references) __state = false; if (DoorChoice.IsTarget(__instance) && !hold && (Object)(object)character == (Object)(object)Player.m_localPlayer) { ZNetView component = ((Component)__instance).GetComponent<ZNetView>(); __state = (Object)(object)component != (Object)null && component.IsValid() && component.GetZDO().GetInt(ZDOVars.s_state, 0) == 0; } if (!DoorChoice.IsTarget(__instance) || hold || Plugin.Settings == null || !Input.GetKey(Plugin.Settings.ToggleModifier) || (Object)(object)character != (Object)(object)Player.m_localPlayer) { return true; } if (!DoorChoice.CanClose(__instance)) { return true; } DoorChoice.Toggle(__instance); __state = null; __result = true; return false; } [HarmonyPatch(typeof(Door), "Interact")] [HarmonyPostfix] private static void AfterInteract(Door __instance, Humanoid character, bool hold, bool alt, bool __result, bool? __state) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) if (!(!__state.HasValue || !DoorChoice.IsTarget(__instance) || hold) && __result && !((Object)(object)character != (Object)(object)Player.m_localPlayer) && (!__instance.m_checkGuardStone || PrivateArea.CheckAccess(((Component)__instance).transform.position, 0f, false, false))) { if (__state.Value && DoorChoice.IsEnabled(__instance)) { DoorProximity.Track(__instance); } else { DoorProximity.Cancel(__instance); } } } } internal static class DoorProximity { private const float OpenRequestTimeout = 2f; private static readonly Dictionary<Door, float> Tracked = new Dictionary<Door, float>(); private static readonly List<Door> Finished = new List<Door>(); internal static void Track(Door door) { Tracked[door] = Time.time; } internal static void Cancel(Door door) { Tracked.Remove(door); } internal static void Update() { //IL_00c3: Unknown result type (might be due to invalid IL or missing references) Finished.Clear(); float num = Mathf.Max(0f, Plugin.Settings.CloseDistanceMeters); foreach (KeyValuePair<Door, float> item in Tracked) { Door key = item.Key; if ((Object)(object)key == (Object)null || !DoorChoice.IsEnabled(key)) { Finished.Add(key); continue; } ZNetView component = ((Component)key).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsValid()) { Finished.Add(key); } else if (component.GetZDO().GetInt(ZDOVars.s_state, 0) == 0) { if (Time.time - item.Value >= 2f) { Finished.Add(key); } } else if (!Player.IsPlayerInRange(((Component)key).transform.position, num) && DoorChoice.CanClose(key)) { component.InvokeRPC("UseDoor", new object[1] { false }); Finished.Add(key); } } foreach (Door item2 in Finished) { Tracked.Remove(item2); } } internal static void Clear() { Tracked.Clear(); Finished.Clear(); } } internal enum ToggleModifierOption { LeftAlt, LeftShift, LeftControl } internal sealed class ModConfig { private readonly ConfigFile config; private readonly ConfigEntry<bool> enabledByDefault; private readonly ConfigEntry<float> closeDistance; private readonly ConfigEntry<ToggleModifierOption> toggleModifier; internal bool EnabledByDefault => enabledByDefault.Value; internal float CloseDistanceMeters => closeDistance.Value; internal KeyCode ToggleModifier { get { if (toggleModifier.Value != ToggleModifierOption.LeftShift) { if (toggleModifier.Value == ToggleModifierOption.LeftControl) { return (KeyCode)306; } return (KeyCode)308; } return (KeyCode)304; } } internal string ToggleModifierName { get { if (toggleModifier.Value != ToggleModifierOption.LeftShift) { if (toggleModifier.Value != ToggleModifierOption.LeftControl) { return "Alt"; } return "Ctrl"; } return "Shift"; } } internal ModConfig(ConfigFile configFile) { config = configFile; enabledByDefault = config.Bind<bool>("General", "EnabledByDefault", true, "Whether supported doors close automatically unless changed with the modifier and use key."); closeDistance = config.Bind<float>("General", "CloseDistanceMeters", 5f, "Distance players must leave before an enabled door closes automatically."); toggleModifier = config.Bind<ToggleModifierOption>("General", "ToggleModifier", ToggleModifierOption.LeftAlt, "Modifier used with the door interaction key to toggle auto-close."); } internal void RestoreDefaults() { enabledByDefault.Value = true; closeDistance.Value = 5f; toggleModifier.Value = ToggleModifierOption.LeftAlt; config.Save(); ConfigWatcher.IgnoreCurrentFileVersion(); } } [BepInPlugin("Landoria.AutoCloseDoors", "AutoClose Doors", "1.0.3")] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "Landoria.AutoCloseDoors"; public const string PluginName = "AutoClose Doors"; public const string PluginVersion = "1.0.3"; internal static ModConfig Settings; private Harmony harmony; private void Awake() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown Settings = new ModConfig(((BaseUnityPlugin)this).Config); harmony = new Harmony("Landoria.AutoCloseDoors"); harmony.PatchAll(); ConfigWatcher.Initialize(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger, "AutoClose Doors", Settings.RestoreDefaults); } private void Update() { ConfigWatcher.Update(); DoorProximity.Update(); } private void OnDestroy() { ConfigWatcher.Dispose(); Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } DoorProximity.Clear(); Settings = null; } } }