Decompiled source of AutoCloseDoors v0.1.4

AutoCloseDoors.dll

Decompiled a day ago
using System;
using System.Collections;
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 UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("0.0.0.0")]
namespace Obelisk.AutoCloseDoors;

[BepInPlugin("obelisk.valheim.autoclosedoors", "AutoCloseDoors", "0.1.4")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class AutoCloseDoorsPlugin : BaseUnityPlugin
{
	public const string PluginGuid = "obelisk.valheim.autoclosedoors";

	public const string PluginName = "AutoCloseDoors";

	public const string PluginVersion = "0.1.4";

	private static ConfigEntry<bool> _enabled;

	private static ConfigEntry<bool> _enableInDungeons;

	private static ConfigEntry<bool> _blockMonsterDoorSensors;

	private static ConfigEntry<float> _playerRadius;

	private static ConfigEntry<int> _closeDelaySeconds;

	private Harmony _harmony;

	internal static bool IsEnabled => _enabled.Value;

	internal static bool EnableInDungeons => _enableInDungeons.Value;

	internal static bool BlockMonsterDoorSensors => _blockMonsterDoorSensors.Value;

	internal static float PlayerRadius => Mathf.Max(0f, _playerRadius.Value);

	internal static float CloseDelay => Mathf.Clamp(_closeDelaySeconds.Value, 2, 10);

	private void Awake()
	{
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Expected O, but got Unknown
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Expected O, but got Unknown
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Expected O, but got Unknown
		_enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable automatic closing for opened doors and gates.");
		_enableInDungeons = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enable in dungeons", false, "Enable automatic closing while the local player is inside dungeons/interiors.");
		_blockMonsterDoorSensors = ((BaseUnityPlugin)this).Config.Bind<bool>("Compatibility", "Block monster door sensors", true, "Prevents compatible door sensor mods from opening player doors for monsters.");
		_playerRadius = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Player radius", 3f, new ConfigDescription("Door will wait again while any player is inside this radius.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), Array.Empty<object>()));
		_closeDelaySeconds = ((BaseUnityPlugin)this).Config.Bind<int>("General", "Close delay seconds", 5, new ConfigDescription("Seconds before an opened door can close. Allowed range: 2-10.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(2, 10), Array.Empty<object>()));
		DoorAutoCloser.Initialize(this);
		DoorAutoCloser.CacheGameMethods();
		_harmony = new Harmony("obelisk.valheim.autoclosedoors");
		_harmony.PatchAll();
		DoorAutoCloser.PatchCompatibility(_harmony);
	}

	private void OnDestroy()
	{
		DoorAutoCloser.Reset();
		Harmony harmony = _harmony;
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
	}
}
[HarmonyPatch(typeof(Door), "RPC_UseDoor")]
internal static class DoorRpcUseDoorPatch
{
	private static void Postfix(Door __instance)
	{
		DoorAutoCloser.OnDoorStateChanged(__instance);
	}
}
internal static class DoorAutoCloser
{
	private const float LinkedDoorSearchRadius = 5f;

	private const float LinkedDoorMaxHeightDifference = 0.35f;

	private const float LinkedDoorMinDistance = 0.1f;

	private static readonly Dictionary<Door, float> OpenDoors = new Dictionary<Door, float>();

	private static readonly List<Door> DueDoors = new List<Door>();

	private static readonly List<Door> LinkedDoors = new List<Door>();

	private static readonly List<Piece> NearbyPieces = new List<Piece>();

	private static AutoCloseDoorsPlugin _plugin;

	private static Coroutine _checkRoutine;

	private static MethodInfo _playerInInteriorMethod;

	private static bool _compatibilityPatched;

	public static void Initialize(AutoCloseDoorsPlugin plugin)
	{
		_plugin = plugin;
	}

	public static void CacheGameMethods()
	{
		_playerInInteriorMethod = AccessTools.Method(typeof(Player), "InInterior", (Type[])null, (Type[])null);
	}

	public static void PatchCompatibility(Harmony harmony)
	{
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Expected O, but got Unknown
		if (!_compatibilityPatched && harmony != null)
		{
			Type type = AccessTools.TypeByName("MonsterDoorSensor");
			MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "OpenDoor", (Type[])null, (Type[])null));
			MethodInfo methodInfo2 = AccessTools.Method(typeof(MonsterDoorSensorOpenDoorPatch), "Prefix", (Type[])null, (Type[])null);
			if (!(methodInfo == null) && !(methodInfo2 == null))
			{
				harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				_compatibilityPatched = true;
			}
		}
	}

	public static void Reset()
	{
		if ((Object)(object)_plugin != (Object)null && _checkRoutine != null)
		{
			((MonoBehaviour)_plugin).StopCoroutine(_checkRoutine);
		}
		_checkRoutine = null;
		OpenDoors.Clear();
		DueDoors.Clear();
		LinkedDoors.Clear();
		NearbyPieces.Clear();
	}

	public static void OnDoorStateChanged(Door door)
	{
		if (!AutoCloseDoorsPlugin.IsEnabled || IsDungeonDisabled() || !IsOpen(door))
		{
			Forget(door);
		}
		else
		{
			Track(door, Time.time + AutoCloseDoorsPlugin.CloseDelay, restartRoutine: true);
		}
	}

	private static void Track(Door door, float nextCheckTime, bool restartRoutine)
	{
		OpenDoors[door] = nextCheckTime;
		if (restartRoutine)
		{
			RestartCheckRoutine();
		}
	}

	private static void Forget(Door door)
	{
		if (door != null)
		{
			OpenDoors.Remove(door);
		}
	}

	private static void RestartCheckRoutine()
	{
		if (!((Object)(object)_plugin == (Object)null))
		{
			if (_checkRoutine != null)
			{
				((MonoBehaviour)_plugin).StopCoroutine(_checkRoutine);
			}
			_checkRoutine = ((MonoBehaviour)_plugin).StartCoroutine(CheckOpenDoors());
		}
	}

	private static IEnumerator CheckOpenDoors()
	{
		while (OpenDoors.Count > 0)
		{
			if (!AutoCloseDoorsPlugin.IsEnabled)
			{
				OpenDoors.Clear();
				break;
			}
			if (IsDungeonDisabled())
			{
				OpenDoors.Clear();
				break;
			}
			float dueDoors = GetDueDoors(Time.time);
			if (DueDoors.Count == 0)
			{
				float num = Mathf.Max(0.1f, dueDoors - Time.time);
				yield return (object)new WaitForSeconds(num);
				continue;
			}
			for (int i = 0; i < DueDoors.Count; i++)
			{
				Door val = DueDoors[i];
				if (OpenDoors.ContainsKey(val))
				{
					CheckDoor(val);
				}
			}
			DueDoors.Clear();
		}
		_checkRoutine = null;
	}

	private static float GetDueDoors(float now)
	{
		DueDoors.Clear();
		float num = float.MaxValue;
		foreach (KeyValuePair<Door, float> openDoor in OpenDoors)
		{
			if (!IsOpen(openDoor.Key))
			{
				DueDoors.Add(openDoor.Key);
			}
			else if (openDoor.Value <= now)
			{
				DueDoors.Add(openDoor.Key);
			}
			else if (openDoor.Value < num)
			{
				num = openDoor.Value;
			}
		}
		return num;
	}

	private static void CheckDoor(Door door)
	{
		CollectLinkedOpenDoors(door);
		if (LinkedDoors.Count == 0)
		{
			Forget(door);
		}
		else if (IsAnyPlayerNear(LinkedDoors))
		{
			float nextCheckTime = Time.time + AutoCloseDoorsPlugin.CloseDelay;
			for (int i = 0; i < LinkedDoors.Count; i++)
			{
				Track(LinkedDoors[i], nextCheckTime, restartRoutine: false);
			}
		}
		else
		{
			for (int j = 0; j < LinkedDoors.Count; j++)
			{
				CloseDoor(LinkedDoors[j]);
				Forget(LinkedDoors[j]);
			}
		}
	}

	private static void CollectLinkedOpenDoors(Door door)
	{
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		LinkedDoors.Clear();
		NearbyPieces.Clear();
		if (!IsOpen(door))
		{
			return;
		}
		LinkedDoors.Add(door);
		Piece.GetAllPiecesInRadius(((Component)door).transform.position, 5f, NearbyPieces);
		for (int i = 0; i < NearbyPieces.Count; i++)
		{
			Piece val = NearbyPieces[i];
			if (!((Object)(object)val == (Object)null))
			{
				Door component = ((Component)val).GetComponent<Door>();
				if (!((Object)(object)component == (Object)null) && !((Object)(object)component == (Object)(object)door) && IsOpen(component) && IsLinkedDoor(door, component))
				{
					LinkedDoors.Add(component);
				}
			}
		}
	}

	private static bool IsLinkedDoor(Door door, Door otherDoor)
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: 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)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0100: Unknown result type (might be due to invalid IL or missing references)
		//IL_0116: Unknown result type (might be due to invalid IL or missing references)
		//IL_0118: Unknown result type (might be due to invalid IL or missing references)
		//IL_0126: Unknown result type (might be due to invalid IL or missing references)
		//IL_0128: Unknown result type (might be due to invalid IL or missing references)
		//IL_013e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0140: Unknown result type (might be due to invalid IL or missing references)
		//IL_014e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0150: Unknown result type (might be due to invalid IL or missing references)
		Transform transform = ((Component)door).transform;
		Transform transform2 = ((Component)otherDoor).transform;
		Vector3 position = transform.position;
		Vector3 position2 = transform2.position;
		if (Mathf.Abs(position.y - position2.y) > 0.35f)
		{
			return false;
		}
		Vector3 val = position2 - position;
		val.y = 0f;
		float magnitude = ((Vector3)(ref val)).magnitude;
		if (magnitude < 0.1f || magnitude > 5f)
		{
			return false;
		}
		Vector3 val2 = val / magnitude;
		Vector3 val3 = Horizontal(transform.right);
		Vector3 val4 = Horizontal(transform2.right);
		Vector3 val5 = Horizontal(transform.forward);
		Vector3 val6 = Horizontal(transform2.forward);
		if (val3 == Vector3.zero || val4 == Vector3.zero || val5 == Vector3.zero || val6 == Vector3.zero)
		{
			return false;
		}
		((Vector3)(ref val3)).Normalize();
		((Vector3)(ref val4)).Normalize();
		((Vector3)(ref val5)).Normalize();
		((Vector3)(ref val6)).Normalize();
		bool num = Mathf.Abs(Vector3.Dot(val2, val3)) >= 0.75f;
		bool flag = Vector3.Dot(val3, val4) <= -0.75f || Vector3.Dot(val5, val6) <= -0.75f;
		bool flag2 = Vector3.Dot(val3, val4) >= 0.75f && Vector3.Dot(val5, val6) >= 0.75f;
		if (num)
		{
			return flag || flag2;
		}
		return false;
	}

	private static bool IsAnyPlayerNear(List<Door> doors)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		float playerRadius = AutoCloseDoorsPlugin.PlayerRadius;
		for (int i = 0; i < doors.Count; i++)
		{
			if (Player.IsPlayerInRange(((Component)doors[i]).transform.position, playerRadius))
			{
				return true;
			}
		}
		return false;
	}

	private static void CloseDoor(Door door)
	{
		if (!IsOpen(door))
		{
			return;
		}
		ZNetView doorView = GetDoorView(door);
		if (!((Object)(object)doorView == (Object)null) && doorView.IsValid())
		{
			if (!doorView.IsOwner())
			{
				doorView.ClaimOwnership();
			}
			doorView.GetZDO().Set(ZDOVars.s_state, 0, false);
		}
	}

	private static bool IsOpen(Door door)
	{
		ZNetView doorView = GetDoorView(door);
		if ((Object)(object)doorView == (Object)null || !doorView.IsValid())
		{
			return false;
		}
		return doorView.GetZDO().GetInt(ZDOVars.s_state, 0) != 0;
	}

	private static ZNetView GetDoorView(Door door)
	{
		if (door == null)
		{
			return null;
		}
		return ((Component)door).GetComponent<ZNetView>();
	}

	private static bool IsDungeonDisabled()
	{
		if (AutoCloseDoorsPlugin.EnableInDungeons)
		{
			return false;
		}
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null || _playerInInteriorMethod == null)
		{
			return false;
		}
		return (bool)_playerInInteriorMethod.Invoke(localPlayer, null);
	}

	private static Vector3 Horizontal(Vector3 vector)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		vector.y = 0f;
		return vector;
	}
}
internal static class MonsterDoorSensorOpenDoorPatch
{
	public static bool Prefix()
	{
		return !AutoCloseDoorsPlugin.BlockMonsterDoorSensors;
	}
}