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 AutoDoors v1.0.13
AutoDoors.dll
Decompiled 2 days agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("AutoDoors")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("AutoDoors")] [assembly: AssemblyTitle("AutoDoors")] [assembly: AssemblyVersion("1.0.0.0")] [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 AutoDoors { [BepInPlugin("zenox.autodoors", "AutoDoors", "1.0.12")] public class AutoDoorsPlugin : BaseUnityPlugin { private class DoorTracking { public bool WasInRange; public bool OpenedByMod; public bool IsManual; public bool WasOpenLastTick; public float OutOfRangeTimer; public bool SuppressNextEffect; public List<Door> Partners; public float PartnersLastScanned = -999f; public float LastCloseSuppressLogTime = -999f; } [HarmonyPatch(typeof(Door), "UpdateState")] private static class Door_UpdateState_Patch { private static void Postfix(Door __instance) { if ((Object)(object)Instance != (Object)null) { Instance.RegisterDoor(__instance); } } } [HarmonyPatch(typeof(Door), "SetState")] private static class Door_SetState_MuteSound_Patch { private static readonly FieldInfo AnimatorField = AccessTools.Field(typeof(Door), "m_animator"); private static bool Prefix(Door __instance, int state) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown if ((Object)(object)Instance == (Object)null || !Instance.trackedDoors.TryGetValue(__instance, out var value) || !value.SuppressNextEffect) { return true; } value.SuppressNextEffect = false; Animator val = (Animator)AnimatorField.GetValue(__instance); if (val.GetInteger("state") != state) { val.SetInteger("state", state); } if ((Object)(object)__instance.m_openEnable != (Object)null) { __instance.m_openEnable.SetActive(state != 0); } return false; } } public const string PluginGUID = "zenox.autodoors"; public const string PluginName = "AutoDoors"; public const string PluginVersion = "1.0.12"; public static AutoDoorsPlugin Instance; public static ConfigEntry<bool> ModEnabled; public static ConfigEntry<float> RangeMultiplier; public static ConfigEntry<float> UpdateInterval; public static ConfigEntry<bool> IgnoreLockedDoors; public static ConfigEntry<float> CloseDelaySeconds; public static ConfigEntry<bool> RequireFacingDoor; public static ConfigEntry<float> FacingAngleThreshold; public static ConfigEntry<bool> MuteAutoDoorSound; public static ConfigEntry<bool> PairDoubleDoors; public static ConfigEntry<float> MaxPairDistance; private readonly Harmony harmony = new Harmony("zenox.autodoors"); private readonly Dictionary<Door, DoorTracking> trackedDoors = new Dictionary<Door, DoorTracking>(); private float timeSinceLastCheck; private readonly Dictionary<Door, (int state, bool inRange, bool facingOk)> tickData = new Dictionary<Door, (int, bool, bool)>(); private void Awake() { Instance = this; ModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable/disable automatic opening and closing of doors and gates."); RangeMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("General", "RangeMultiplier", 1f, "Multiplier applied to the player's normal interaction distance to decide how close you need to be for a door to open automatically."); UpdateInterval = ((BaseUnityPlugin)this).Config.Bind<float>("General", "UpdateInterval", 0.1f, "Minimum time in seconds between range checks. Lower = more responsive, higher = better performance."); IgnoreLockedDoors = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "IgnoreLockedDoors", true, "If true, doors that require a key are left alone (you still need to unlock them by hand)."); CloseDelaySeconds = ((BaseUnityPlugin)this).Config.Bind<float>("General", "CloseDelaySeconds", 0.5f, "Seconds to wait after leaving range before auto-closing a door. 0 = close immediately (original behavior)."); RequireFacingDoor = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "RequireFacingDoor", true, "If true, doors only auto-open when you're roughly walking/facing towards them - prevents every door in a hallway opening at once just from being in range."); FacingAngleThreshold = ((BaseUnityPlugin)this).Config.Bind<float>("General", "FacingAngleThreshold", 45f, "Half-angle in degrees from your camera/crosshair direction still counted as 'facing' the door. Only used if RequireFacingDoor is true. Lower = stricter (must look more directly at it)."); MuteAutoDoorSound = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "MuteAutoDoorSound", false, "If true, suppresses the door's open/close sound and particle effect when triggered automatically by this mod. Doors opened/closed by hand still play the normal sound."); PairDoubleDoors = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "PairDoubleDoors", true, "If true, two door pieces snapped close together (a double door) are treated as one unit: if either half would open, both open; both only close once neither half is in range/facing anymore."); MaxPairDistance = ((BaseUnityPlugin)this).Config.Bind<float>("General", "MaxPairDistance", 2.5f, "Max gap in meters between two door/gate pieces (measured between their own edges, not their pivots) to be treated as a double-door pair. Only used if PairDoubleDoors is true."); harmony.PatchAll(Assembly.GetExecutingAssembly()); ((BaseUnityPlugin)this).Logger.LogInfo((object)"AutoDoors v1.0.12 loaded."); } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } internal void RegisterDoor(Door door) { if (!trackedDoors.ContainsKey(door)) { trackedDoors[door] = new DoorTracking(); } } private void Update() { //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_02e7: Unknown result type (might be due to invalid IL or missing references) //IL_02ed: Unknown result type (might be due to invalid IL or missing references) //IL_02f2: Unknown result type (might be due to invalid IL or missing references) //IL_02f7: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Unknown result type (might be due to invalid IL or missing references) //IL_032d: Unknown result type (might be due to invalid IL or missing references) if (!ModEnabled.Value) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead()) { return; } timeSinceLastCheck += Time.deltaTime; if (timeSinceLastCheck < UpdateInterval.Value) { return; } timeSinceLastCheck = 0f; float num = localPlayer.m_maxInteractDistance * RangeMultiplier.Value; float radiusSq = num * num; Vector3 playerPos = ((Component)localPlayer).transform.position; List<Door> list = null; tickData.Clear(); foreach (KeyValuePair<Door, DoorTracking> trackedDoor in trackedDoors) { Door key = trackedDoor.Key; DoorTracking value = trackedDoor.Value; if ((Object)(object)key == (Object)null) { (list ?? (list = new List<Door>())).Add(key); continue; } ZNetView component = ((Component)key).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsValid()) { continue; } ZDO zDO = component.GetZDO(); int num2 = zDO.GetInt("state", 0); if (IgnoreLockedDoors.Value && (Object)(object)key.m_keyItem != (Object)null) { continue; } if (PairDoubleDoors.Value) { ScanForPartners(key, value); } bool flag = Vector3.SqrMagnitude(((Component)key).transform.position - playerPos) <= radiusSq; if (flag) { if (!value.WasInRange) { if (num2 != 0 && !value.OpenedByMod) { value.IsManual = true; } else { value.IsManual = false; } } else if (value.OpenedByMod && value.WasOpenLastTick && num2 == 0) { value.IsManual = true; value.OpenedByMod = false; } } else if (num2 == 0) { value.OpenedByMod = false; value.IsManual = false; } bool flag2 = value.Partners != null && value.Partners.Exists((Door p) => (Object)(object)p != (Object)null && Vector3.SqrMagnitude(((Component)p).transform.position - playerPos) <= radiusSq); if (flag || flag2) { value.OutOfRangeTimer = 0f; } else { value.OutOfRangeTimer += UpdateInterval.Value; } bool item = true; if (RequireFacingDoor.Value) { Vector3 val = ((Component)key).transform.position - playerPos; if (((Vector3)(ref val)).sqrMagnitude > 0.01f && (Object)(object)GameCamera.instance != (Object)null) { float num3 = Vector3.Dot(((Component)GameCamera.instance).transform.forward, ((Vector3)(ref val)).normalized); float num4 = Mathf.Cos(FacingAngleThreshold.Value * (MathF.PI / 180f)); item = num3 >= num4; } } tickData[key] = (num2, flag, item); value.WasOpenLastTick = num2 != 0; value.WasInRange = flag; } foreach (KeyValuePair<Door, (int, bool, bool)> tickDatum in tickData) { Door key2 = tickDatum.Key; (int, bool, bool) value2 = tickDatum.Value; int item2 = value2.Item1; bool item3 = value2.Item2; bool item4 = value2.Item3; DoorTracking doorTracking = trackedDoors[key2]; (int, bool, bool) value3; bool flag3 = doorTracking.Partners != null && doorTracking.Partners.Exists((Door p) => tickData.TryGetValue(p, out value3) && value3.Item2); if (item3 || flag3) { bool flag4 = item2 == 0 && item4; bool flag5 = doorTracking.Partners != null && doorTracking.Partners.Exists((Door p) => tickData.TryGetValue(p, out value3) && value3.Item1 == 0 && value3.Item2 && value3.Item3); if (!doorTracking.IsManual && item2 == 0 && (flag4 || flag5)) { if (MuteAutoDoorSound.Value) { doorTracking.SuppressNextEffect = true; } if (flag5 && !flag4) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("[AutoDoors] Door '" + ((Object)key2).name + "' opened because a paired partner door wants to open (this door's own facing/range check didn't pass).")); } key2.Interact((Humanoid)(object)localPlayer, false, false); doorTracking.OpenedByMod = true; } continue; } bool flag6 = doorTracking.Partners == null || doorTracking.Partners.TrueForAll((Door p) => !tickData.TryGetValue(p, out value3) || !value3.Item2); if (doorTracking.IsManual || !doorTracking.OpenedByMod || item2 == 0 || !(doorTracking.OutOfRangeTimer >= CloseDelaySeconds.Value)) { continue; } if (!flag6) { if (Time.time - doorTracking.LastCloseSuppressLogTime > 3f) { doorTracking.LastCloseSuppressLogTime = Time.time; ((BaseUnityPlugin)this).Logger.LogInfo((object)("[AutoDoors] Door '" + ((Object)key2).name + "' close suppressed - a paired partner door is still in range.")); } } else { if (MuteAutoDoorSound.Value) { doorTracking.SuppressNextEffect = true; } key2.Interact((Humanoid)(object)localPlayer, false, false); } } if (list == null) { return; } foreach (Door item5 in list) { trackedDoors.Remove(item5); } } private void ScanForPartners(Door door, DoorTracking tracking) { //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) if ((tracking.Partners != null && tracking.Partners.Count > 0) || Time.time - tracking.PartnersLastScanned < 5f) { return; } tracking.PartnersLastScanned = Time.time; float horizontalHalfWidth = GetHorizontalHalfWidth(door); List<Door> list = null; foreach (KeyValuePair<Door, DoorTracking> trackedDoor in trackedDoors) { Door key = trackedDoor.Key; if (!((Object)(object)key == (Object)null) && !((Object)(object)key == (Object)(object)door)) { float num = Vector3.Distance(((Component)key).transform.position, ((Component)door).transform.position); float num2 = num - horizontalHalfWidth - GetHorizontalHalfWidth(key); if (num2 <= MaxPairDistance.Value) { (list ?? (list = new List<Door>())).Add(key); } } } if (list != null) { tracking.Partners = list; ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[AutoDoors] Paired door '{((Object)door).name}' at {((Component)door).transform.position} with {list.Count} partner(s) (gap <= {MaxPairDistance.Value}m)."); } } private static float GetHorizontalHalfWidth(Door door) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) Collider componentInChildren = ((Component)door).GetComponentInChildren<Collider>(); if ((Object)(object)componentInChildren == (Object)null) { return 0f; } Bounds bounds = componentInChildren.bounds; Vector3 size = ((Bounds)(ref bounds)).size; return Mathf.Max(size.x, size.z) * 0.5f; } } }