Decompiled source of ClearSightCamera v1.1.0

ClearSightCamera.dll

Decompiled 3 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
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("ClearSightCamera")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Azumatt")]
[assembly: AssemblyProduct("ClearSightCamera")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("4358610B-F3F4-4843-B7AF-98B7BC60DCDE")]
[assembly: AssemblyFileVersion("1.1.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 ClearSightCamera
{
	internal static class CameraClearController
	{
		private sealed class RendererFadeData
		{
			public Renderer Renderer;

			public Material[] OriginalShared = Array.Empty<Material>();

			public Material[] GhostMats = Array.Empty<Material>();
		}

		private static readonly List<Renderer> _hiddenRenderers = new List<Renderer>();

		private static readonly HashSet<Renderer> _hiddenRendererSet = new HashSet<Renderer>();

		private static readonly Dictionary<Renderer, bool> _originalEnabled = new Dictionary<Renderer, bool>();

		private static readonly Dictionary<Renderer, bool> _originalForceOff = new Dictionary<Renderer, bool>();

		private static readonly Dictionary<Renderer, RendererFadeData> _fadeData = new Dictionary<Renderer, RendererFadeData>();

		private static int _geometryMask;

		private static int GeometryMask
		{
			get
			{
				if (_geometryMask != 0)
				{
					return _geometryMask;
				}
				_geometryMask = LayerMask.GetMask(new string[4] { "Default", "static_solid", "piece", "piece_nonsolid" });
				return _geometryMask;
			}
		}

		public static void OnAfterCameraUpdate(GameCamera cam)
		{
			if (!Object.op_Implicit((Object)(object)cam) || !Object.op_Implicit((Object)(object)cam.m_camera))
			{
				return;
			}
			if (cam.m_freeFly)
			{
				RestoreVisuals();
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer))
			{
				RestoreVisuals();
				return;
			}
			RestoreVisuals();
			if (ClearSightCameraPlugin.CullingEnabled)
			{
				ApplyCulling(cam, localPlayer);
			}
		}

		private static Vector3 GetCameraTargetPosition(Player player)
		{
			//IL_0013: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)((Character)player).m_eye))
			{
				return ((Character)player).m_eye.position;
			}
			if (Object.op_Implicit((Object)(object)((Character)player).m_head))
			{
				return ((Character)player).m_head.position;
			}
			return ((Component)player).transform.position + Vector3.up * 1.6f;
		}

		private static bool TryGetCullRoot(Collider col, out Transform root)
		{
			root = null;
			GameObject val = (Object.op_Implicit((Object)(object)col.attachedRigidbody) ? ((Component)col.attachedRigidbody).gameObject : ((Component)col).gameObject);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return false;
			}
			Player localPlayer = Player.m_localPlayer;
			if (Object.op_Implicit((Object)(object)localPlayer) && (Object)(object)val.GetComponentInParent<Player>() == (Object)(object)localPlayer)
			{
				return false;
			}
			Piece componentInParent = val.GetComponentInParent<Piece>();
			if (Object.op_Implicit((Object)(object)componentInParent))
			{
				root = ((Component)componentInParent).transform;
				return true;
			}
			root = val.transform;
			return true;
		}

		private static void ApplyCulling(GameCamera cam, Player player)
		{
			//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_001d: 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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: 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_00b2: Unknown result type (might be due to invalid IL or missing references)
			Camera camera = cam.m_camera;
			if (!Object.op_Implicit((Object)(object)camera))
			{
				return;
			}
			Vector3 position = ((Component)camera).transform.position;
			Vector3 cameraTargetPosition = GetCameraTargetPosition(player);
			Vector3 val = cameraTargetPosition - position;
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (magnitude < 0.1f)
			{
				return;
			}
			float num = Mathf.Min(magnitude, ClearSightCameraPlugin.CullMaxDistanceCfg.Value);
			Vector3 val2 = val / magnitude;
			float num2 = Mathf.Max(0.05f, ClearSightCameraPlugin.CullRadiusCfg.Value);
			RaycastHit[] array = Physics.SphereCastAll(position, num2, val2, num, GeometryMask, (QueryTriggerInteraction)2);
			if (array.Length == 0)
			{
				return;
			}
			RaycastHit[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				RaycastHit val3 = array2[i];
				Collider collider = ((RaycastHit)(ref val3)).collider;
				if (Object.op_Implicit((Object)(object)collider) && ShouldCullCollider(camera, cameraTargetPosition, collider, out Component root))
				{
					CullUnderRoot(root);
				}
			}
		}

		private static bool IsObstructingPlayer(Camera cam, Vector3 playerEyePos, Collider col)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = ((Component)cam).transform.position;
			Vector3 val = playerEyePos - position;
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (magnitude < 0.1f)
			{
				return false;
			}
			Vector3 val2 = val / magnitude;
			Vector3 val3 = SafeClosestPoint(col, playerEyePos);
			float num = Vector3.Dot(val3 - position, val2);
			float num2 = magnitude;
			if (num <= 0f || num >= num2 + 0.05f)
			{
				return false;
			}
			Vector3 val4 = cam.WorldToViewportPoint(playerEyePos);
			Vector3 val5 = cam.WorldToViewportPoint(val3);
			if (val5.z <= 0f)
			{
				return false;
			}
			Vector2 val6 = new Vector2(val4.x, val4.y);
			Vector2 val7 = default(Vector2);
			((Vector2)(ref val7))..ctor(val5.x, val5.y);
			Vector2 val8 = val6 - val7;
			float sqrMagnitude = ((Vector2)(ref val8)).sqrMagnitude;
			float value = ClearSightCameraPlugin.CullRadiusCfg.Value;
			return sqrMagnitude <= value * value;
		}

		private static Vector3 SafeClosestPoint(Collider col, Vector3 targetWorldPos)
		{
			//IL_0008: 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)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)col))
			{
				return targetWorldPos;
			}
			if (!(col is BoxCollider) && !(col is SphereCollider) && !(col is CapsuleCollider))
			{
				MeshCollider val = (MeshCollider)(object)((col is MeshCollider) ? col : null);
				if (val != null && val.convex)
				{
					return ((Collider)val).ClosestPoint(targetWorldPos);
				}
				Bounds bounds = col.bounds;
				return ((Bounds)(ref bounds)).ClosestPoint(targetWorldPos);
			}
			return col.ClosestPoint(targetWorldPos);
		}

		private static bool ShouldCullCollider(Camera cam, Vector3 playerEyePos, Collider col, out Component root)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			root = null;
			GameObject val = (Object.op_Implicit((Object)(object)col.attachedRigidbody) ? ((Component)col.attachedRigidbody).gameObject : ((Component)col).gameObject);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return false;
			}
			if (Object.op_Implicit((Object)(object)val.GetComponentInParent<Player>()))
			{
				return false;
			}
			if (Object.op_Implicit((Object)(object)val.GetComponentInParent<Character>()))
			{
				return false;
			}
			if (Object.op_Implicit((Object)(object)val.GetComponentInParent<ItemDrop>()))
			{
				return false;
			}
			if (!IsObstructingPlayer(cam, playerEyePos, col))
			{
				return false;
			}
			Piece componentInParent = val.GetComponentInParent<Piece>();
			if (Object.op_Implicit((Object)(object)componentInParent))
			{
				root = (Component)(object)componentInParent;
				return true;
			}
			root = (Component)(object)val.transform;
			return true;
		}

		private static bool HasComponentInHierarchy<T>(GameObject go) where T : Component
		{
			if (!((Object)(object)go.GetComponentInParent<T>() != (Object)null))
			{
				return (Object)(object)go.GetComponentInChildren<T>(true) != (Object)null;
			}
			return true;
		}

		private static bool HasHoverOrInteractInHierarchy(GameObject go)
		{
			MonoBehaviour[] componentsInParent = go.GetComponentsInParent<MonoBehaviour>(true);
			foreach (MonoBehaviour val in componentsInParent)
			{
				if ((val is Hoverable || val is Interactable) ? true : false)
				{
					return true;
				}
			}
			MonoBehaviour[] componentsInChildren = go.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val2 in componentsInChildren)
			{
				if ((val2 is Hoverable || val2 is Interactable) ? true : false)
				{
					return true;
				}
			}
			return false;
		}

		private static void CullUnderRoot(Component root)
		{
			if (Object.op_Implicit((Object)(object)root))
			{
				GameObject gameObject = root.gameObject;
				ClearSightCameraPlugin.ClearSightCameraLogger.LogDebug((object)("CULL UNDER ROOT [HoverFix] Hit " + ((Object)gameObject).name + ", " + $"occluder={(Object)(object)gameObject.GetComponentInParent<ClearSightOccluderTag>() != (Object)null}, " + $"hasHover={gameObject.GetComponentInParent<Hoverable>() != null}, " + $"hasInteract={gameObject.GetComponentInParent<Interactable>() != null}"));
				if (Object.op_Implicit((Object)(object)gameObject) && !Object.op_Implicit((Object)(object)gameObject.GetComponent<ClearSightOccluderTag>()))
				{
					gameObject.AddComponent<ClearSightOccluderTag>();
				}
				if (ClearSightCameraPlugin.UseTransparency && (Object)(object)ClearSightTransparentTemplateProvider.Template != (Object)null)
				{
					FadeRenderersUnder(root, ClearSightCameraPlugin.FadeAlpha);
				}
				else
				{
					HideRenderersUnder(root);
				}
			}
		}

		private static void HideRenderersUnder(Component root)
		{
			Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if (Object.op_Implicit((Object)(object)val) && !_hiddenRendererSet.Contains(val) && (val.enabled || _originalEnabled.ContainsKey(val)))
				{
					if (!_originalEnabled.ContainsKey(val))
					{
						_originalEnabled[val] = val.enabled;
						_originalForceOff[val] = val.forceRenderingOff;
					}
					val.forceRenderingOff = true;
					_hiddenRendererSet.Add(val);
					_hiddenRenderers.Add(val);
				}
			}
		}

		private static void FadeRenderersUnder(Component root, float targetAlpha)
		{
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: 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)
			Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true);
			targetAlpha = Mathf.Clamp01(targetAlpha);
			Renderer[] array = componentsInChildren;
			foreach (Renderer val in array)
			{
				if (!Object.op_Implicit((Object)(object)val))
				{
					continue;
				}
				if (!_fadeData.TryGetValue(val, out RendererFadeData value))
				{
					value = new RendererFadeData
					{
						Renderer = val,
						OriginalShared = val.sharedMaterials,
						GhostMats = BuildGhostMaterials(val.sharedMaterials)
					};
					_fadeData.Add(val, value);
				}
				if (value.GhostMats == null || value.GhostMats.Length == 0)
				{
					continue;
				}
				val.sharedMaterials = value.GhostMats;
				Material[] ghostMats = value.GhostMats;
				foreach (Material val2 in ghostMats)
				{
					if (Object.op_Implicit((Object)(object)val2) && val2.HasProperty("_Color"))
					{
						Color color = val2.color;
						color.a = targetAlpha;
						val2.color = color;
					}
				}
			}
		}

		private static Material[] BuildGhostMaterials(Material[] originals)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Expected O, but got Unknown
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			if (originals == null || originals.Length == 0)
			{
				return Array.Empty<Material>();
			}
			Material template = ClearSightTransparentTemplateProvider.Template;
			if (!Object.op_Implicit((Object)(object)template))
			{
				return Array.Empty<Material>();
			}
			Material[] array = (Material[])(object)new Material[originals.Length];
			for (int i = 0; i < originals.Length; i++)
			{
				Material val = originals[i];
				if (Object.op_Implicit((Object)(object)val))
				{
					Material val2 = new Material(template)
					{
						name = ((Object)val).name + " (ClearSightGhost)",
						mainTexture = val.mainTexture,
						mainTextureScale = val.mainTextureScale,
						mainTextureOffset = val.mainTextureOffset
					};
					if (val.HasProperty("_Color") && val2.HasProperty("_Color"))
					{
						Color color = val.color;
						color.a = ClearSightCameraPlugin.FadeAlpha;
						val2.color = color;
					}
					else if (val2.HasProperty("_Color"))
					{
						Color color2 = val2.color;
						color2.a = ClearSightCameraPlugin.FadeAlpha;
						val2.color = color2;
					}
					array[i] = val2;
				}
			}
			return array;
		}

		private static void RestoreVisuals()
		{
			if (_fadeData.Count > 0)
			{
				foreach (KeyValuePair<Renderer, RendererFadeData> fadeDatum in _fadeData)
				{
					RendererFadeData value = fadeDatum.Value;
					if (Object.op_Implicit((Object)(object)value.Renderer) && value.OriginalShared != null && value.OriginalShared.Length != 0)
					{
						value.Renderer.sharedMaterials = value.OriginalShared;
					}
				}
			}
			if (_hiddenRenderers.Count <= 0)
			{
				return;
			}
			for (int i = 0; i < _hiddenRenderers.Count; i++)
			{
				Renderer val = _hiddenRenderers[i];
				if (Object.op_Implicit((Object)(object)val))
				{
					if (_originalEnabled.TryGetValue(val, out var value2))
					{
						val.enabled = value2;
					}
					if (_originalForceOff.TryGetValue(val, out var value3))
					{
						val.forceRenderingOff = value3;
					}
					else
					{
						val.forceRenderingOff = false;
					}
				}
			}
			_hiddenRenderers.Clear();
			_hiddenRendererSet.Clear();
			_originalEnabled.Clear();
			_originalForceOff.Clear();
		}
	}
	internal static class ClearSightHoverResolver
	{
		internal static bool TryResolveHoverBehindOccluder(Player player, out GameObject bestHover, out Character bestChar)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: 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_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Expected O, but got Unknown
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			bestHover = null;
			bestChar = null;
			GameCamera instance = GameCamera.instance;
			if (!Object.op_Implicit((Object)(object)instance) || !Object.op_Implicit((Object)(object)instance.m_camera))
			{
				return false;
			}
			Camera camera = instance.m_camera;
			Vector3 position = ((Component)camera).transform.position;
			Vector3 forward = ((Component)camera).transform.forward;
			int interactMask = player.m_interactMask;
			RaycastHit[] array = Physics.RaycastAll(position, forward, 50f, interactMask, (QueryTriggerInteraction)2);
			if (array == null || array.Length == 0)
			{
				return false;
			}
			Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance));
			RaycastHit[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				RaycastHit val = array2[i];
				Collider collider = ((RaycastHit)(ref val)).collider;
				if (!Object.op_Implicit((Object)(object)collider))
				{
					continue;
				}
				GameObject val2 = (Object.op_Implicit((Object)(object)collider.attachedRigidbody) ? ((Component)collider.attachedRigidbody).gameObject : ((Component)collider).gameObject);
				if (!Object.op_Implicit((Object)(object)val2))
				{
					continue;
				}
				bool flag = (Object)(object)val2.GetComponentInParent<ClearSightOccluderTag>() != (Object)null;
				Hoverable componentInParent = val2.GetComponentInParent<Hoverable>();
				Interactable componentInParent2 = val2.GetComponentInParent<Interactable>();
				Character componentInParent3 = val2.GetComponentInParent<Character>();
				ClearSightCameraPlugin.ClearSightCameraLogger.LogDebug((object)("TryResolveHoverBehindOccluder[HoverFix] Hit " + ((Object)val2).name + ", " + $"occluder={flag}, hasHover={componentInParent != null}, hasInteract={componentInParent2 != null}"));
				if ((Object)(object)val2.GetComponentInParent<Player>() == (Object)(object)player || (flag && (Object)(object)componentInParent3 == (Object)null && componentInParent == null && componentInParent2 == null))
				{
					continue;
				}
				if (Object.op_Implicit((Object)(object)componentInParent3) && (Object)(object)componentInParent3 != (Object)(object)player)
				{
					bestHover = ((Component)componentInParent3).gameObject;
					bestChar = componentInParent3;
					break;
				}
				if (componentInParent != null || componentInParent2 != null)
				{
					? val3 = (Component)componentInParent;
					if ((int)val3 == 0)
					{
						val3 = (Component)componentInParent2;
					}
					Component val4 = (Component)val3;
					if (Object.op_Implicit((Object)(object)val4))
					{
						bestChar = (bestHover = val4.gameObject).GetComponentInParent<Character>();
						break;
					}
				}
				Piece componentInParent4 = val2.GetComponentInParent<Piece>();
				if (Object.op_Implicit((Object)(object)componentInParent4))
				{
					bestHover = ((Component)componentInParent4).gameObject;
					bestChar = ((Component)componentInParent4).GetComponentInParent<Character>();
					break;
				}
			}
			return (Object)(object)bestHover != (Object)null;
		}
	}
	[HarmonyPatch(typeof(Player), "UpdateHover")]
	internal static class Player_UpdateHover_ClearSightPatch
	{
		private static void Postfix(Player __instance)
		{
			if (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || !ClearSightCameraPlugin.CullingEnabled || !Object.op_Implicit((Object)(object)__instance.m_hovering))
			{
				return;
			}
			GameObject hovering = __instance.m_hovering;
			if (Object.op_Implicit((Object)(object)hovering.GetComponentInParent<ClearSightOccluderTag>()) && hovering.GetComponentInParent<Hoverable>() == null && hovering.GetComponentInParent<Interactable>() == null)
			{
				if (!ClearSightHoverResolver.TryResolveHoverBehindOccluder(__instance, out GameObject bestHover, out Character bestChar))
				{
					__instance.m_hovering = null;
					__instance.m_hoveringCreature = null;
				}
				else
				{
					__instance.m_hovering = bestHover;
					__instance.m_hoveringCreature = bestChar;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Player), "RemovePiece")]
	internal static class Player_RemovePiece_ClearSightPatch
	{
		private static void Prefix(Player __instance)
		{
			if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && ClearSightCameraPlugin.CullingEnabled && Object.op_Implicit((Object)(object)__instance.m_hovering) && Object.op_Implicit((Object)(object)__instance.m_hovering.GetComponentInParent<ClearSightOccluderTag>()))
			{
				if (!ClearSightHoverResolver.TryResolveHoverBehindOccluder(__instance, out GameObject bestHover, out Character bestChar))
				{
					__instance.m_hovering = null;
					__instance.m_hoveringCreature = null;
				}
				else
				{
					__instance.m_hovering = bestHover;
					__instance.m_hoveringCreature = bestChar;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Player), "Interact")]
	internal static class Player_Interact_ClearSightPatch
	{
		private static void Prefix(Player __instance, ref GameObject go, bool hold, bool alt)
		{
			if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && ClearSightCameraPlugin.CullingEnabled && Object.op_Implicit((Object)(object)go) && Object.op_Implicit((Object)(object)go.GetComponentInParent<ClearSightOccluderTag>()) && go.GetComponentInParent<Hoverable>() == null && go.GetComponentInParent<Interactable>() == null && ClearSightHoverResolver.TryResolveHoverBehindOccluder(__instance, out GameObject bestHover, out Character bestChar))
			{
				ClearSightCameraPlugin.ClearSightCameraLogger.LogDebug((object)("Player.Interact redirect: " + ((Object)go).name + " (occluder) → " + ((Object)bestHover).name));
				go = bestHover;
				__instance.m_hovering = bestHover;
				__instance.m_hoveringCreature = bestChar;
			}
		}
	}
	public sealed class ClearSightOccluderTag : MonoBehaviour
	{
	}
	internal static class ClearSightTransparentTemplateProvider
	{
		private static bool _initialized;

		private static Material _template;

		internal static Material Template
		{
			get
			{
				if (!_initialized)
				{
					InitializeLazy();
				}
				return _template;
			}
		}

		internal static void BootstrapFromFejdStartup(FejdStartup fejd)
		{
			if (_initialized || !Object.op_Implicit((Object)(object)fejd) || !Object.op_Implicit((Object)(object)fejd.m_objectDBPrefab))
			{
				return;
			}
			try
			{
				ZNetScene component = fejd.m_objectDBPrefab.GetComponent<ZNetScene>();
				if (Object.op_Implicit((Object)(object)component) && TryInitFromArmorLeather(component))
				{
					_initialized = true;
				}
			}
			catch (Exception arg)
			{
				ClearSightCameraPlugin.ClearSightCameraLogger.LogDebug((object)$"FejdStartup bootstrap failed: {arg}");
			}
		}

		private static void InitializeLazy()
		{
			if (!_initialized)
			{
				_initialized = true;
				if (!((Object)(object)_template != (Object)null) && !TryInitFromAnyStandardMaterial() && !TryInitFromAnyTransparentMaterial())
				{
					ClearSightCameraPlugin.ClearSightCameraLogger.LogWarning((object)"Could not find any suitable transparent template. Transparent culling will fall back to Hidden mode.");
				}
			}
		}

		private static bool TryInitFromArmorLeather(ZNetScene scene)
		{
			if (!Object.op_Implicit((Object)(object)scene))
			{
				return false;
			}
			string[] array = new string[4] { "ArmorLeather", "ArmorLeatherChest", "ArmorLeatherLegs", "ArmorLeatherHelmet" };
			foreach (string prefabName in array)
			{
				GameObject val = ((IEnumerable<GameObject>)scene.m_prefabs).FirstOrDefault((Func<GameObject, bool>)((GameObject x) => Object.op_Implicit((Object)(object)x) && ((Object)x).name == prefabName));
				if (Object.op_Implicit((Object)(object)val) && TryBuildTemplateFromRenderers(val.GetComponentsInChildren<Renderer>(true)))
				{
					return true;
				}
			}
			return false;
		}

		private static bool TryInitFromAnyStandardMaterial()
		{
			try
			{
				Material[] array = Resources.FindObjectsOfTypeAll<Material>();
				foreach (Material val in array)
				{
					if (Object.op_Implicit((Object)(object)val) && !((Object)(object)val.shader == (Object)null) && ((Object)val.shader).name.Contains("Standard") && TryBuildTemplateFromMaterial(val, "Standard material '" + ((Object)val).name + "'"))
					{
						return true;
					}
				}
			}
			catch (Exception arg)
			{
				ClearSightCameraPlugin.ClearSightCameraLogger.LogDebug((object)$"Standard material scan failed: {arg}");
			}
			return false;
		}

		private static bool TryInitFromAnyTransparentMaterial()
		{
			try
			{
				foreach (Material item in from m in Resources.FindObjectsOfTypeAll<Material>()
					orderby m.renderQueue
					select m)
				{
					if (Object.op_Implicit((Object)(object)item) && item.HasProperty("_Color") && item.HasProperty("_MainTex") && item.renderQueue >= 3000 && TryBuildTemplateFromMaterial(item, "transparent material '" + ((Object)item).name + "'"))
					{
						return true;
					}
				}
			}
			catch (Exception arg)
			{
				ClearSightCameraPlugin.ClearSightCameraLogger.LogDebug((object)$"Transparent material scan failed: {arg}");
			}
			return false;
		}

		private static bool TryBuildTemplateFromRenderers(IEnumerable<Renderer> renderers)
		{
			foreach (Renderer renderer in renderers)
			{
				if (!Object.op_Implicit((Object)(object)renderer))
				{
					continue;
				}
				Material[] sharedMaterials = renderer.sharedMaterials;
				if (sharedMaterials == null)
				{
					continue;
				}
				Material[] array = sharedMaterials;
				foreach (Material val in array)
				{
					if (Object.op_Implicit((Object)(object)val) && !((Object)(object)val.shader == (Object)null) && ((Object)val.shader).name.Contains("Standard") && TryBuildTemplateFromMaterial(val, "ArmorLeather material '" + ((Object)val).name + "'"))
					{
						return true;
					}
				}
			}
			return false;
		}

		private static bool TryBuildTemplateFromMaterial(Material source, string reason)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			if (!Object.op_Implicit((Object)(object)source) || (Object)(object)source.shader == (Object)null)
			{
				return false;
			}
			Material val = new Material(source)
			{
				name = "ClearSight_TransparentTemplate"
			};
			if (val.HasProperty("_Mode") && val.HasProperty("_SrcBlend") && val.HasProperty("_DstBlend") && val.HasProperty("_ZWrite"))
			{
				val.SetFloat("_Mode", 2f);
				val.SetInt("_SrcBlend", 5);
				val.SetInt("_DstBlend", 10);
				val.SetInt("_ZWrite", 0);
				val.DisableKeyword("_ALPHATEST_ON");
				val.EnableKeyword("_ALPHABLEND_ON");
				val.DisableKeyword("_ALPHAPREMULTIPLY_ON");
			}
			val.renderQueue = 3000;
			_template = val;
			ClearSightCameraPlugin.ClearSightCameraLogger.LogInfo((object)("Using " + reason + " (shader '" + ((Object)source.shader).name + "') as transparent template."));
			return true;
		}
	}
	[HarmonyPatch(typeof(FejdStartup), "Awake")]
	internal static class FejdStartup_Awake_ClearSightBootstrap
	{
		private static void Postfix(FejdStartup __instance)
		{
			ClearSightTransparentTemplateProvider.BootstrapFromFejdStartup(__instance);
		}
	}
	[HarmonyPatch(typeof(Piece), "GetAllComfortPiecesInRadius")]
	internal static class Piece_GetAllComfortPiecesInRadius_SanitizePatch
	{
		private static void Prefix()
		{
			try
			{
				List<Piece> s_allPieces = Piece.s_allPieces;
				if (s_allPieces == null)
				{
					return;
				}
				for (int num = s_allPieces.Count - 1; num >= 0; num--)
				{
					if (!Object.op_Implicit((Object)(object)s_allPieces[num]))
					{
						s_allPieces.RemoveAt(num);
					}
				}
			}
			catch (Exception arg)
			{
				ClearSightCameraPlugin.ClearSightCameraLogger.LogError((object)$"Failed to sanitize Piece.m_allPieces: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(GameCamera), "LateUpdate")]
	internal static class GameCamera_LateUpdate_ClearSightPatch
	{
		private static void Postfix(GameCamera __instance)
		{
			CameraClearController.OnAfterCameraUpdate(__instance);
		}
	}
	[HarmonyPatch(typeof(GameCamera), "CollideRay2")]
	internal static class GameCamera_CollideRay2_ClearSightPatch
	{
		private static bool Prefix(GameCamera __instance, Vector3 eyePos, Vector3 offsetedEyePos, ref Vector3 end)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			if (!ClearSightCameraPlugin.NoClipEnabled)
			{
				return true;
			}
			int mask = LayerMask.GetMask(new string[1] { "terrain" });
			float num = Vector3.Distance(eyePos, end);
			if (num <= 0.01f)
			{
				return false;
			}
			Vector3 val = end - offsetedEyePos;
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			if (((Vector3)(ref normalized)).sqrMagnitude < 1E-06f)
			{
				return false;
			}
			float num2 = num;
			bool flag = false;
			float raycastWidth = __instance.m_raycastWidth;
			RaycastHit val2 = default(RaycastHit);
			if (Physics.SphereCast(offsetedEyePos, raycastWidth, normalized, ref val2, num, mask))
			{
				num2 = ((RaycastHit)(ref val2)).distance;
				flag = true;
			}
			if (Physics.SphereCast(eyePos, raycastWidth, normalized, ref val2, num, mask))
			{
				if (((RaycastHit)(ref val2)).distance < num2)
				{
					num2 = ((RaycastHit)(ref val2)).distance;
				}
				flag = true;
			}
			if (flag)
			{
				float num3 = Utils.LerpStep(0.5f, 2f, num2);
				val = end - eyePos;
				Vector3 val3 = eyePos + ((Vector3)(ref val)).normalized * num2;
				val = end - offsetedEyePos;
				Vector3 val4 = offsetedEyePos + ((Vector3)(ref val)).normalized * num2;
				end = Vector3.Lerp(val3, val4, num3);
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(GameCamera), "Awake")]
	internal static class GameCamera_Awake_ClearSightPatch
	{
		private static void Postfix(GameCamera __instance)
		{
			float value = ClearSightCameraPlugin.MaxDistanceCfg.Value;
			if (!(value <= 0f))
			{
				if (value > __instance.m_maxDistance)
				{
					__instance.m_maxDistance = value;
				}
				if (value > __instance.m_maxDistanceBoat)
				{
					__instance.m_maxDistanceBoat = value;
				}
			}
		}
	}
	[BepInPlugin("Azumatt.ClearSightCamera", "ClearSightCamera", "1.1.0")]
	public class ClearSightCameraPlugin : BaseUnityPlugin
	{
		public enum Toggle
		{
			On = 1,
			Off = 0
		}

		public enum CullingVisualMode
		{
			Hidden,
			Transparent
		}

		internal const string ModName = "ClearSightCamera";

		internal const string ModVersion = "1.1.0";

		internal const string Author = "Azumatt";

		private const string ModGUID = "Azumatt.ClearSightCamera";

		private static readonly string ConfigFileName = "Azumatt.ClearSightCamera.cfg";

		private static readonly string ConfigFileFullPath;

		internal static readonly ManualLogSource ClearSightCameraLogger;

		private readonly Harmony _harmony = new Harmony("Azumatt.ClearSightCamera");

		private FileSystemWatcher _watcher;

		private readonly object _reloadLock = new object();

		private DateTime _lastConfigReloadTime;

		private const long RELOAD_DELAY = 10000000L;

		internal static ClearSightCameraPlugin Instance;

		internal static bool CullingEnabled;

		internal static bool NoClipEnabled;

		internal static ConfigEntry<KeyboardShortcut> ToggleCullKey;

		internal static ConfigEntry<KeyboardShortcut> ToggleNoClipKey;

		internal static ConfigEntry<Toggle> CullingEnabledCfg;

		internal static ConfigEntry<Toggle> NoClipEnabledCfg;

		internal static ConfigEntry<float> MaxDistanceCfg;

		internal static ConfigEntry<float> GroundPaddingCfg;

		internal static ConfigEntry<float> CullRadiusCfg;

		internal static ConfigEntry<float> CullMaxDistanceCfg;

		internal static ConfigEntry<CullingVisualMode> CullingVisualModeCfg;

		internal static ConfigEntry<float> CullingFadeAlphaCfg;

		internal static bool UseTransparency
		{
			get
			{
				ConfigEntry<CullingVisualMode> cullingVisualModeCfg = CullingVisualModeCfg;
				if (cullingVisualModeCfg != null)
				{
					return cullingVisualModeCfg.Value == CullingVisualMode.Transparent;
				}
				return false;
			}
		}

		internal static float FadeAlpha => Mathf.Clamp01(CullingFadeAlphaCfg?.Value ?? 0.25f);

		public void Awake()
		{
			Instance = this;
			bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet;
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = false;
			CreateConfigEntries();
			CullingEnabled = CullingEnabledCfg.Value.IsOn();
			NoClipEnabled = NoClipEnabledCfg.Value.IsOn();
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			_harmony.PatchAll(executingAssembly);
			SetupWatcher();
			((BaseUnityPlugin)this).Config.Save();
			if (saveOnConfigSet)
			{
				((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnConfigSet;
			}
		}

		private void Update()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: 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_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			KeyboardShortcut value = ToggleCullKey.Value;
			if ((int)((KeyboardShortcut)(ref value)).MainKey != 0 && ToggleCullKey.Value.IsKeyDown())
			{
				CullingEnabled = !CullingEnabled;
				CullingEnabledCfg.Value = CullingEnabled.ToToggle();
				ShowMessage("Camera culling: " + (CullingEnabled ? "ON" : "OFF"));
			}
			value = ToggleNoClipKey.Value;
			if ((int)((KeyboardShortcut)(ref value)).MainKey != 0 && ToggleNoClipKey.Value.IsKeyDown())
			{
				NoClipEnabled = !NoClipEnabled;
				NoClipEnabledCfg.Value = NoClipEnabled.ToToggle();
				ShowMessage("Camera no-clip: " + (NoClipEnabled ? "ON" : "OFF"));
			}
		}

		internal static void ShowMessage(string msg)
		{
			if (Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, msg, 0, (Sprite)null);
			}
			else
			{
				ClearSightCameraLogger.LogInfo((object)msg);
			}
		}

		private void OnDestroy()
		{
			SaveWithRespectToConfigSet();
			_watcher?.Dispose();
		}

		private void CreateConfigEntries()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			ToggleCullKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("1 - Hotkeys", "Toggle Culling Key", new KeyboardShortcut((KeyCode)288, Array.Empty<KeyCode>()), "Toggle camera occluder culling (roof/wall hiding) on/off.");
			ToggleNoClipKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("1 - Hotkeys", "Toggle No-Clip Key", new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()), "Toggle camera no-clip (ignore walls, respect ground) on/off.");
			CullingEnabledCfg = ((BaseUnityPlugin)this).Config.Bind<Toggle>("2 - Culling", "Culling Enabled", Toggle.On, "If true, the mod will attempt to hide occluding pieces between camera and player.");
			CullingVisualModeCfg = ((BaseUnityPlugin)this).Config.Bind<CullingVisualMode>("2 - Culling", "Culling Visual Mode", CullingVisualMode.Transparent, "How to visually treat occluding pieces between camera and player.\nHidden = fully disable renderers.\nTransparent = keep them visible but fade to the configured alpha.");
			CullingFadeAlphaCfg = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Culling", "Culling Fade Alpha", 0.25f, "Alpha value (0–1) used when Culling Visual Mode is Transparent.");
			CullRadiusCfg = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Culling", "Cull Sphere Radius", 1f, "Radius of the spherecast between camera and player used to find occluding pieces.");
			CullMaxDistanceCfg = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Culling", "Cull Max Distance", 15f, "Maximum distance from the camera along the ray to look for occluders.");
			NoClipEnabledCfg = ((BaseUnityPlugin)this).Config.Bind<Toggle>("3 - NoClip", "NoClip Enabled", Toggle.On, "If true, the mod will override camera collision and allow the camera to stay zoomed out, still respecting terrain.");
			MaxDistanceCfg = ((BaseUnityPlugin)this).Config.Bind<float>("3 - NoClip", "Forced Max Distance", 12f, "Target camera distance when no-clip is active. The vanilla max distance is around ~6 in most cases.");
			GroundPaddingCfg = ((BaseUnityPlugin)this).Config.Bind<float>("3 - NoClip", "Ground Padding", 0.5f, "Minimum distance above terrain to keep the camera when no-clip is active.");
		}

		private void SetupWatcher()
		{
			_watcher = new FileSystemWatcher(Paths.ConfigPath, ConfigFileName);
			_watcher.Changed += ReadConfigValues;
			_watcher.Created += ReadConfigValues;
			_watcher.Renamed += ReadConfigValues;
			_watcher.IncludeSubdirectories = true;
			_watcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
			_watcher.EnableRaisingEvents = true;
		}

		private void ReadConfigValues(object sender, FileSystemEventArgs e)
		{
			DateTime now = DateTime.Now;
			if (now.Ticks - _lastConfigReloadTime.Ticks < 10000000)
			{
				return;
			}
			lock (_reloadLock)
			{
				if (!File.Exists(ConfigFileFullPath))
				{
					ClearSightCameraLogger.LogWarning((object)"Config file does not exist. Skipping reload.");
					return;
				}
				try
				{
					ClearSightCameraLogger.LogDebug((object)"Reloading configuration...");
					SaveWithRespectToConfigSet(reload: true);
					CullingEnabled = CullingEnabledCfg.Value.IsOn();
					NoClipEnabled = NoClipEnabledCfg.Value.IsOn();
					ClearSightCameraLogger.LogInfo((object)"Configuration reload complete.");
				}
				catch (Exception ex)
				{
					ClearSightCameraLogger.LogError((object)("Error reloading configuration: " + ex.Message));
				}
			}
			_lastConfigReloadTime = now;
		}

		private void SaveWithRespectToConfigSet(bool reload = false)
		{
			bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet;
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = false;
			if (reload)
			{
				((BaseUnityPlugin)this).Config.Reload();
			}
			((BaseUnityPlugin)this).Config.Save();
			if (saveOnConfigSet)
			{
				((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnConfigSet;
			}
		}

		static ClearSightCameraPlugin()
		{
			string configPath = Paths.ConfigPath;
			char directorySeparatorChar = Path.DirectorySeparatorChar;
			ConfigFileFullPath = configPath + directorySeparatorChar + ConfigFileName;
			ClearSightCameraLogger = Logger.CreateLogSource("ClearSightCamera");
			Instance = null;
			ToggleCullKey = null;
			ToggleNoClipKey = null;
			CullingEnabledCfg = null;
			NoClipEnabledCfg = null;
			MaxDistanceCfg = null;
			GroundPaddingCfg = null;
			CullRadiusCfg = null;
			CullMaxDistanceCfg = null;
			CullingVisualModeCfg = null;
			CullingFadeAlphaCfg = null;
		}
	}
	public static class KeyboardExtensions
	{
		public static bool IsKeyDown(this KeyboardShortcut shortcut)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			if ((int)((KeyboardShortcut)(ref shortcut)).MainKey != 0 && Input.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey))
			{
				return ((KeyboardShortcut)(ref shortcut)).Modifiers.All((Func<KeyCode, bool>)Input.GetKey);
			}
			return false;
		}

		public static bool IsKeyHeld(this KeyboardShortcut shortcut)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			if ((int)((KeyboardShortcut)(ref shortcut)).MainKey != 0 && Input.GetKey(((KeyboardShortcut)(ref shortcut)).MainKey))
			{
				return ((KeyboardShortcut)(ref shortcut)).Modifiers.All((Func<KeyCode, bool>)Input.GetKey);
			}
			return false;
		}
	}
	public static class ToggleExtensions
	{
		public static bool IsOn(this ClearSightCameraPlugin.Toggle value)
		{
			return value == ClearSightCameraPlugin.Toggle.On;
		}

		public static bool IsOff(this ClearSightCameraPlugin.Toggle value)
		{
			return value == ClearSightCameraPlugin.Toggle.Off;
		}

		public static ClearSightCameraPlugin.Toggle ToToggle(this bool value)
		{
			if (!value)
			{
				return ClearSightCameraPlugin.Toggle.Off;
			}
			return ClearSightCameraPlugin.Toggle.On;
		}
	}
}