Decompiled source of ValheimPickaxeCamera EasyPicking v1.3.0

BepInEx/plugins/FreePickaxeCam/FreePickaxeCam.dll

Decompiled 5 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Free Pickaxe Cam")]
[assembly: AssemblyFileVersion("0.1.2.0")]
[assembly: AssemblyVersion("0.1.2.0")]
namespace PickaxeCam;

[BepInPlugin("valheim.pickaxecam", "Free Pickaxe Cam", "0.1.2")]
[BepInProcess("valheim.exe")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[DefaultExecutionOrder(1000)]
public sealed class PickaxeCamera : BaseUnityPlugin
{
	[HarmonyPatch(typeof(InventoryGui), "Show", new Type[]
	{
		typeof(Container),
		typeof(int)
	})]
	private static class KeepInventoryClosedInPickaxeCamera
	{
		private static bool Prefix()
		{
			PickaxeCamera instance = Instance;
			if (Object.op_Implicit((Object)(object)instance))
			{
				return !instance.Active;
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(Player), "Update")]
	private static class BeforePlayerUpdate
	{
		private static void Prefix(Player __instance)
		{
			PickaxeCamera instance = Instance;
			if (Object.op_Implicit((Object)(object)instance) && instance.IsLocal(__instance))
			{
				instance.Tick();
			}
		}
	}

	[HarmonyPatch(typeof(GameCamera), "LateUpdate")]
	private static class DetachedCameraLateUpdate
	{
		private static void Postfix(GameCamera __instance)
		{
			PickaxeCamera instance = Instance;
			if (!Object.op_Implicit((Object)(object)instance) || !instance.Active || (Object)(object)__instance != (Object)(object)instance._gameCamera)
			{
				return;
			}
			try
			{
				instance.ApplyPose();
			}
			catch (Exception error)
			{
				instance.Fail(error);
			}
		}
	}

	[HarmonyPatch(typeof(GameCamera), "UpdateCamera")]
	private static class DetachedCamera
	{
		private static bool Prefix(GameCamera __instance)
		{
			PickaxeCamera instance = Instance;
			if (!Object.op_Implicit((Object)(object)instance) || !instance.Active || (Object)(object)__instance != (Object)(object)instance._gameCamera)
			{
				return true;
			}
			try
			{
				instance.ApplyPose();
				return false;
			}
			catch (Exception error)
			{
				instance.Fail(error);
				return true;
			}
		}
	}

	[HarmonyPatch(typeof(Player), "SetControls")]
	private static class KeepBodyStill
	{
		private static void Prefix(Player __instance, ref Vector3 movedir, ref bool attack, ref bool attackHold, ref bool secondaryAttack, ref bool secondaryAttackHold, ref bool block, ref bool blockHold, ref bool jump, ref bool crouch, ref bool run, ref bool autoRun, ref bool dodge)
		{
			//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)
			PickaxeCamera instance = Instance;
			if (Object.op_Implicit((Object)(object)instance) && instance.ControlsOwned(__instance))
			{
				movedir = Vector3.zero;
				attack = (attackHold = (secondaryAttack = (secondaryAttackHold = (block = (blockHold = false)))));
				jump = (crouch = (run = (autoRun = (dodge = false))));
				__instance.m_autoRun = false;
				if (instance._active)
				{
					((Character)__instance).StopMovement();
				}
			}
		}
	}

	[HarmonyPatch(typeof(Player), "SetMouseLook")]
	private static class KeepBodyLook
	{
		private static bool Prefix(Player __instance)
		{
			PickaxeCamera instance = Instance;
			if (Object.op_Implicit((Object)(object)instance))
			{
				return !instance.ControlsOwned(__instance);
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(Player), "TakeInput")]
	private static class ProtectToggleAndDialogs
	{
		private static void Postfix(Player __instance, ref bool __result)
		{
			PickaxeCamera instance = Instance;
			if (Object.op_Implicit((Object)(object)instance) && instance.HooksEnabled && instance.IsLocal(__instance) && (instance._active || instance._chordHeld || Time.unscaledTime < instance._suppressUntil))
			{
				__result = false;
			}
		}
	}

	[HarmonyPatch(typeof(Player), "StartGuardianPower")]
	private static class ProtectGuardianPowerChord
	{
		private static bool Prefix(Player __instance)
		{
			PickaxeCamera instance = Instance;
			if (!Object.op_Implicit((Object)(object)instance) || !instance.HooksEnabled || !instance.IsLocal(__instance))
			{
				return true;
			}
			if (!instance._active)
			{
				return !instance._chordHeld;
			}
			return false;
		}
	}

	private static PropertyInfo _otherActive;

	private static object _otherPlugin;

	private GameObject _miningTarget;

	private bool _miningBusy;

	private bool _mineArmed;

	private string _miningStatus = "Aim at a stone or ore deposit";

	private float _miningStatusUntil;

	private LineRenderer _miningOutline;

	private Material _miningMaterial;

	private GUIStyle _miningTitle;

	private GUIStyle _miningText;

	private static readonly int[] BoxOrder = new int[16]
	{
		0, 1, 2, 3, 0, 4, 5, 1, 5, 6,
		2, 6, 7, 3, 7, 4
	};

	public const string PluginId = "valheim.pickaxecam";

	public const string PluginVersion = "0.1.2";

	internal static PickaxeCamera Instance;

	private float _nextCircletCheck;

	private ConfigEntry<bool> _enabled;

	private ConfigEntry<bool> _controllerToggle;

	private ConfigEntry<bool> _hidePlayer;

	private ConfigEntry<bool> _showIndicator;

	private ConfigEntry<bool> _exitOnDamage;

	private ConfigEntry<KeyboardShortcut> _toggleKey;

	private ConfigEntry<KeyboardShortcut> _resetKey;

	private ConfigEntry<KeyboardShortcut> _reportKey;

	private ConfigEntry<float> _speed;

	private ConfigEntry<float> _fastMultiplier;

	private ConfigEntry<float> _radius;

	private ConfigEntry<float> _reach;

	private ConfigEntry<float> _rangeMultiplier;

	private ConfigEntry<float> _startPitch;

	private ConfigEntry<float> _startFov;

	private Harmony _harmony;

	private bool _ready;

	private bool _active;

	private bool _failed;

	private bool _chordHeld;

	private Player _player;

	private GameCamera _gameCamera;

	private Camera _camera;

	private Camera _skyCamera;

	private Vector3 _position;

	private Vector3 _bodyOrigin;

	private Vector3 _savedCameraPosition;

	private Quaternion _savedCameraRotation;

	private Quaternion _rotation;

	private float _yaw;

	private float _pitch;

	private float _fov;

	private float _savedFov;

	private float _savedSkyFov;

	private float _savedNearClip;

	private float _savedReach;

	private float _appliedReach;

	private float _suppressUntil;

	private float _nextRendererScan;

	private float _activeNearClip;

	private int _tickFrame = -1;

	private string _lastExit = "Not activated yet";

	private readonly CameraToggleInput _toggleInput = new CameraToggleInput();

	private string _indicatorText;

	internal bool HooksEnabled
	{
		get
		{
			if (_ready && !_failed)
			{
				return ((Behaviour)this).isActiveAndEnabled;
			}
			return false;
		}
	}

	internal bool Active
	{
		get
		{
			if (HooksEnabled)
			{
				return _active;
			}
			return false;
		}
	}

	private float EffectiveCameraRadius => CameraMath.PickaxeCameraRange(_radius.Value, 8f, _rangeMultiplier.Value);

	private float EffectiveBuildReach => CameraMath.PickaxeCameraRange(_reach.Value, 5f, _rangeMultiplier.Value);

	private void InstallBuildCameraCompatibility()
	{
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Expected O, but got Unknown
		//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Expected O, but got Unknown
		if (Chainloader.PluginInfos.TryGetValue("valheim.buildcamera", out var value))
		{
			_otherPlugin = value.Instance;
			Type type = ((object)value.Instance).GetType();
			_otherActive = AccessTools.Property(type, "Active");
			MethodInfo methodInfo = AccessTools.Method(type, "IsBuildTool", new Type[1] { typeof(ItemData) }, (Type[])null);
			if (methodInfo != null)
			{
				_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(PickaxeCamera), "ExcludePickaxeFromOtherCamera", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Build camera compatibility gate unavailable; use separate keyboard toggles.");
			}
			MethodInfo methodInfo2 = AccessTools.Method(type, "StartCamera", new Type[1] { typeof(Player) }, (Type[])null);
			if (methodInfo2 != null)
			{
				_harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(PickaxeCamera), "ReservePickaxeKeyboardActivation", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
		}
	}

	private static void ExcludePickaxeFromOtherCamera(ItemData __0, ref bool __result)
	{
		if (Object.op_Implicit((Object)(object)Instance) && Instance.HooksEnabled && Instance._enabled.Value && IsBuildTool(__0))
		{
			__result = false;
		}
	}

	private static bool ReservePickaxeKeyboardActivation(Player __0)
	{
		if (Object.op_Implicit((Object)(object)Instance) && Instance.HooksEnabled && Instance._enabled.Value && Object.op_Implicit((Object)(object)__0) && Instance.IsLocal(__0))
		{
			return !HasBuildingTool(__0);
		}
		return true;
	}

	private static bool OtherBuildCameraActive()
	{
		if (_otherPlugin != null && _otherActive != null)
		{
			return (bool)_otherActive.GetValue(_otherPlugin, null);
		}
		return false;
	}

	private static void ValidateHooks()
	{
		Require(typeof(Player), "Update", Type.EmptyTypes);
		Require(typeof(ParticleMist), "Update", Type.EmptyTypes);
		Require(typeof(InventoryGui), "Show", new Type[2]
		{
			typeof(Container),
			typeof(int)
		});
		Require(typeof(Player), "SetControls", new Type[12]
		{
			typeof(Vector3),
			typeof(bool),
			typeof(bool),
			typeof(bool),
			typeof(bool),
			typeof(bool),
			typeof(bool),
			typeof(bool),
			typeof(bool),
			typeof(bool),
			typeof(bool),
			typeof(bool)
		});
		Require(typeof(Player), "SetMouseLook", new Type[1] { typeof(Vector2) });
		Require(typeof(Player), "TakeInput", Type.EmptyTypes);
		Require(typeof(Player), "StartGuardianPower", Type.EmptyTypes);
		Require(typeof(GameCamera), "UpdateCamera", new Type[1] { typeof(float) });
		Require(typeof(GameCamera), "LateUpdate", Type.EmptyTypes);
		Require(typeof(Player), "UpdatePlacement", new Type[2]
		{
			typeof(bool),
			typeof(float)
		});
	}

	private static void Require(Type type, string name, Type[] arguments)
	{
		if (AccessTools.DeclaredMethod(type, name, arguments, (Type[])null) == null)
		{
			throw new MissingMethodException(type.FullName, name);
		}
	}

	private void ConfigureTerrain()
	{
		MiningOperation.Validate();
	}

	private void StartTerrain()
	{
		_mineArmed = false;
		_miningTarget = null;
		_miningStatus = "Aim at a stone or ore deposit";
	}

	private void StopTerrain()
	{
		_miningTarget = null;
		if (Object.op_Implicit((Object)(object)_miningOutline))
		{
			Object.Destroy((Object)(object)((Component)_miningOutline).gameObject);
		}
		if (Object.op_Implicit((Object)(object)_miningMaterial))
		{
			Object.Destroy((Object)(object)_miningMaterial);
		}
		_miningOutline = null;
		_miningMaterial = null;
	}

	private void HideBrush()
	{
		if (Object.op_Implicit((Object)(object)_miningOutline))
		{
			((Renderer)_miningOutline).enabled = false;
		}
	}

	private void TickTerrain()
	{
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_0131: Unknown result type (might be due to invalid IL or missing references)
		Gamepad current = Gamepad.current;
		bool flag = ((ZInput.IsGamepadActive() && current != null) ? current.rightTrigger.isPressed : ZInput.GetMouseButton(0));
		if (!flag)
		{
			_mineArmed = true;
		}
		_miningTarget = null;
		RaycastHit val = default(RaycastHit);
		if (Physics.Raycast(((Component)_camera).transform.position, ((Component)_camera).transform.forward, ref val, EffectiveCameraRadius * 2f + 20f, LayerMask.GetMask(new string[7] { "Default", "static_solid", "Default_small", "piece", "piece_nonsolid", "terrain", "vehicle" }), (QueryTriggerInteraction)1))
		{
			ZNetView componentInParent = ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<ZNetView>();
			if (Object.op_Implicit((Object)(object)componentInParent) && componentInParent.IsValid() && MiningOperation.IsDeposit(((Component)componentInParent).gameObject))
			{
				_miningTarget = ((Component)componentInParent).gameObject;
			}
		}
		bool flag2 = Object.op_Implicit((Object)(object)_miningTarget) && MiningOperation.Allowed(_miningTarget, _player, EffectiveBuildReach);
		if (Object.op_Implicit((Object)(object)_miningTarget))
		{
			DrawMiningOutline(MiningOperation.Bounds(_miningTarget), flag2);
		}
		else
		{
			HideBrush();
		}
		if (!_miningBusy && Time.unscaledTime >= _miningStatusUntil)
		{
			_miningStatus = ((!Object.op_Implicit((Object)(object)_miningTarget)) ? "Aim at a stone or ore deposit" : ((!flag2) ? "Out of reach or protected by a ward" : "Ready — one click mines this whole deposit"));
		}
		if (!flag || !_mineArmed)
		{
			return;
		}
		_mineArmed = false;
		if (!_miningBusy && flag2)
		{
			_miningBusy = true;
			_miningStatus = "Mining deposit…";
			((MonoBehaviour)this).StartCoroutine(MiningOperation.Mine(_player, _miningTarget, EffectiveBuildReach, delegate(string message)
			{
				_miningStatus = message;
				_miningStatusUntil = Time.unscaledTime + 4f;
			}, delegate
			{
				_miningBusy = false;
			}));
		}
	}

	private void DrawMiningOutline(Bounds bounds, bool allowed)
	{
		//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)
		//IL_00b6: 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_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f9: 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_0106: Unknown result type (might be due to invalid IL or missing references)
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_011e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: Unknown result type (might be due to invalid IL or missing references)
		//IL_012a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_013c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0142: Unknown result type (might be due to invalid IL or missing references)
		//IL_0148: 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_0153: Unknown result type (might be due to invalid IL or missing references)
		//IL_015a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0160: Unknown result type (might be due to invalid IL or missing references)
		//IL_0166: Unknown result type (might be due to invalid IL or missing references)
		//IL_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0171: Unknown result type (might be due to invalid IL or missing references)
		//IL_0178: Unknown result type (might be due to invalid IL or missing references)
		//IL_017e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0184: Unknown result type (might be due to invalid IL or missing references)
		//IL_018a: Unknown result type (might be due to invalid IL or missing references)
		//IL_018f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0196: Unknown result type (might be due to invalid IL or missing references)
		//IL_019c: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d6: 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_0030: Expected O, but got Unknown
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_021b: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)_miningOutline))
		{
			Shader val = Shader.Find("Sprites/Default");
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			_miningMaterial = new Material(val);
			_miningOutline = new GameObject("PickaxeCam_DepositOutline").AddComponent<LineRenderer>();
			((Renderer)_miningOutline).sharedMaterial = _miningMaterial;
			_miningOutline.useWorldSpace = true;
			_miningOutline.positionCount = BoxOrder.Length;
			LineRenderer miningOutline = _miningOutline;
			float startWidth = (_miningOutline.endWidth = 0.045f);
			miningOutline.startWidth = startWidth;
			((Renderer)_miningOutline).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)_miningOutline).receiveShadows = false;
		}
		Vector3 min = ((Bounds)(ref bounds)).min;
		Vector3 max = ((Bounds)(ref bounds)).max;
		Vector3[] array = (Vector3[])(object)new Vector3[8]
		{
			new Vector3(min.x, min.y, min.z),
			new Vector3(max.x, min.y, min.z),
			new Vector3(max.x, min.y, max.z),
			new Vector3(min.x, min.y, max.z),
			new Vector3(min.x, max.y, min.z),
			new Vector3(max.x, max.y, min.z),
			new Vector3(max.x, max.y, max.z),
			new Vector3(min.x, max.y, max.z)
		};
		LineRenderer miningOutline2 = _miningOutline;
		Color startColor = (_miningOutline.endColor = (allowed ? new Color(0.35f, 1f, 0.65f, 0.9f) : new Color(1f, 0.3f, 0.2f, 0.9f)));
		miningOutline2.startColor = startColor;
		for (int i = 0; i < BoxOrder.Length; i++)
		{
			_miningOutline.SetPosition(i, array[BoxOrder[i]]);
		}
		((Renderer)_miningOutline).enabled = true;
	}

	private void DrawTerrainHud()
	{
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: 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_003d: Expected O, but got Unknown
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: 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_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Expected O, but got Unknown
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_010e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0113: Unknown result type (might be due to invalid IL or missing references)
		//IL_0119: Unknown result type (might be due to invalid IL or missing references)
		//IL_011e: Unknown result type (might be due to invalid IL or missing references)
		//IL_012f: Unknown result type (might be due to invalid IL or missing references)
		//IL_013e: Expected O, but got Unknown
		//IL_0153: Unknown result type (might be due to invalid IL or missing references)
		//IL_0173: Unknown result type (might be due to invalid IL or missing references)
		//IL_0182: 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_01c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_020d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0234: Unknown result type (might be due to invalid IL or missing references)
		if (_showIndicator.Value)
		{
			if (_miningTitle == null)
			{
				_miningTitle = new GUIStyle(GUI.skin.label)
				{
					fontSize = 26,
					fontStyle = (FontStyle)1
				};
				_miningTitle.normal.textColor = new Color(1f, 0.8f, 0.4f);
				_miningText = new GUIStyle(GUI.skin.label)
				{
					fontSize = 22,
					wordWrap = true
				};
				_miningText.normal.textColor = Color.white;
			}
			bool flag = ZInput.IsGamepadActive();
			string text = MiningOperation.Name(_miningTarget) + "\n\n" + _miningStatus + "\n\n" + (flag ? "Press RT once: mine whole deposit\nLeft stick: fly · Right stick: look\nJump / Crouch: up / down\nBoth stick clicks: exit · Start: menu" : "Click left mouse: mine whole deposit\nWASD: fly · Mouse: look\nJump / Crouch: up / down\nF6: exit · F11: reset view · Esc: menu") + "\n\nLoot fills available weight and slots.\nOverflow drops beside your character.";
			float num = Mathf.Clamp((float)Screen.height / 1080f, 0.7f, 2.5f);
			Matrix4x4 matrix = GUI.matrix;
			Color color = GUI.color;
			GUI.matrix = Matrix4x4.Scale(Vector3.one * num);
			float num2 = _miningText.CalcHeight(new GUIContent(text), 510f);
			GUI.color = new Color(0.06f, 0.075f, 0.09f, 0.95f);
			GUI.DrawTexture(new Rect(20f, 155f, 540f, num2 + 70f), (Texture)(object)Texture2D.whiteTexture);
			GUI.color = Color.white;
			GUI.Label(new Rect(34f, 166f, 512f, 38f), "FREE PICKAXE CAM", _miningTitle);
			GUI.Label(new Rect(34f, 208f, 510f, num2), text, _miningText);
			float num3 = (float)Screen.width / num * 0.5f;
			float num4 = (float)Screen.height / num * 0.5f;
			GUI.DrawTexture(new Rect(num3 - 7f, num4 - 1f, 14f, 2f), (Texture)(object)Texture2D.whiteTexture);
			GUI.DrawTexture(new Rect(num3 - 1f, num4 - 7f, 2f, 14f), (Texture)(object)Texture2D.whiteTexture);
			GUI.color = color;
			GUI.matrix = matrix;
		}
	}

	internal bool IsLocal(Player player)
	{
		if (Object.op_Implicit((Object)(object)player))
		{
			return (Object)(object)player == (Object)(object)Player.m_localPlayer;
		}
		return false;
	}

	internal bool ControlsOwned(Player player)
	{
		if (HooksEnabled && IsLocal(player))
		{
			if (!_active && !_chordHeld)
			{
				return Time.unscaledTime < _suppressUntil;
			}
			return true;
		}
		return false;
	}

	private void Awake()
	{
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: 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_028c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0296: Expected O, but got Unknown
		if (Application.isBatchMode)
		{
			return;
		}
		Instance = this;
		_enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable the pickaxe camera on this client.");
		_toggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "ToggleKey", new KeyboardShortcut((KeyCode)287, Array.Empty<KeyCode>()), "Enter/leave pickaxe camera with a pickaxe equipped.");
		_resetKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "ResetViewKey", new KeyboardShortcut((KeyCode)292, Array.Empty<KeyCode>()), "Reset the active camera to its initial angled view.");
		_reportKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "ReloadAndReportKey", new KeyboardShortcut((KeyCode)293, Array.Empty<KeyCode>()), "Write camera diagnostics, exit camera mode, and reload configuration. Separate from Larger HUD's F8.");
		_controllerToggle = ((BaseUnityPlugin)this).Config.Bind<bool>("Controls", "ControllerStickToggle", true, "Press both stick buttons together to enter/leave. A pickaxe is needed to enter, but not to leave. Release both before toggling again.");
		_hidePlayer = ((BaseUnityPlugin)this).Config.Bind<bool>("View", "HideLocalPlayer", true, "Hide your character's renderers on your own screen while active. Your body remains in the world.");
		_showIndicator = ((BaseUnityPlugin)this).Config.Bind<bool>("View", "ShowIndicator", true, "Show the top-left mining controls and status while the pickaxe camera is active.");
		_exitOnDamage = ((BaseUnityPlugin)this).Config.Bind<bool>("Safety", "ExitOnDamage", true, "Exit immediately when the physical player takes damage. Set false only if you deliberately want environmental damage to be tolerated; death still exits.");
		_speed = FloatSetting("Camera", "MoveSpeed", 6f, 1f, 15f, "Camera movement in metres per second.");
		_fastMultiplier = FloatSetting("Camera", "FastMultiplier", 2f, 1f, 3f, "Hold your Run control for faster camera movement.");
		_radius = FloatSetting("Camera", "CameraRadius", 25f, 8f, 25f, "Base camera radius in metres, multiplied by FreeCameraRangeMultiplier. Free Pickaxe Cam doubles the result: default 25 x 2 x 2 = 100 metres around the stationary body. Existing base settings are retained.");
		_reach = FloatSetting("Mining", "MiningReach", 25f, 5f, 25f, "Mining reach from the stationary player, multiplied by FreeCameraRangeMultiplier and then doubled by Free Pickaxe Cam (100m by default). Targeted deposits must be within this distance.");
		_rangeMultiplier = FloatSetting("Camera", "FreeCameraRangeMultiplier", 2f, 1f, 2f, "Multiply both base camera radius and active build reach. The default multiplier is 2. Set 1 for a smaller working area. Does not affect normal player building reach.");
		_startPitch = FloatSetting("View", "StartingPitch", 50f, 20f, 75f, "Downward angle when entering/resetting the camera. Mouse/right stick can adjust it afterward.");
		_startFov = FloatSetting("View", "FieldOfView", 45f, 25f, 75f, "Starting perspective field of view. Page Up/Down zoom while active; mouse wheel changes brush size.");
		try
		{
			StickInput.Initialize(typeof(ZInput), delegate(string message)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)message);
			});
			ValidateHooks();
			_harmony = new Harmony("valheim.pickaxecam");
			_harmony.PatchAll(typeof(PickaxeCamera).Assembly);
			InstallBuildCameraCompatibility();
			ConfigureTerrain();
			_ready = true;
			RefreshIndicatorText();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Free Pickaxe Cam 0.1.2 loaded. F6 toggle; F11 reset; F12 report/reload.");
		}
		catch (Exception ex)
		{
			_ready = false;
			_failed = true;
			if (_harmony != null)
			{
				_harmony.UnpatchSelf();
			}
			((BaseUnityPlugin)this).Logger.LogError((object)("Free Pickaxe Cam could not install its game hooks and remains inactive. " + ex));
		}
		WriteDiagnostics("Startup");
	}

	private ConfigEntry<float> FloatSetting(string section, string key, float value, float min, float max, string text)
	{
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Expected O, but got Unknown
		return ((BaseUnityPlugin)this).Config.Bind<float>(section, key, value, new ConfigDescription(text, (AcceptableValueBase)(object)new AcceptableValueRange<float>(min, max), Array.Empty<object>()));
	}

	private void Update()
	{
		Tick();
	}

	internal void Tick()
	{
		//IL_0036: 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_00ff: 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_028e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0293: Unknown result type (might be due to invalid IL or missing references)
		if (!_ready || !((Behaviour)this).isActiveAndEnabled || _tickFrame == Time.frameCount)
		{
			return;
		}
		_tickFrame = Time.frameCount;
		try
		{
			KeyboardShortcut value;
			if (Application.isFocused)
			{
				value = _reportKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					WriteDiagnostics("F12 before reload");
					StopCamera("Configuration reload", message: false);
					ResetInput();
					((BaseUnityPlugin)this).Config.Reload();
					RefreshIndicatorText();
					_failed = false;
					Notify("Pickaxe camera settings reloaded; diagnostic report saved.");
					return;
				}
			}
			if (_failed)
			{
				return;
			}
			if (!_enabled.Value)
			{
				StopCamera("Disabled in configuration", message: false);
				ResetInput();
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer) || ZInput.instance == null)
			{
				StopCamera("Player/input changed", message: false);
				ResetInput();
				return;
			}
			if (!Application.isFocused)
			{
				ResetInput();
				return;
			}
			value = _toggleKey.Value;
			bool flag = (((KeyboardShortcut)(ref value)).IsDown() || ZInput.GetKeyDown((KeyCode)287, true)) && (_active || HasBuildingTool(localPlayer));
			bool left = false;
			bool right = false;
			if (_controllerToggle.Value)
			{
				ReadControllerSticks(out left, out right);
			}
			if (!_active && !flag && !_toggleInput.HasPendingKeyboard && !left && !right)
			{
				_toggleInput.Step(Time.frameCount, keyDown: false, keyboardAllowed: false, left: false, right: false, controllerAllowed: false, Time.unscaledDeltaTime);
				_chordHeld = false;
				return;
			}
			bool flag2 = MenuBlocksCamera();
			bool flag3 = CameraMath.ControllerToggleEligible(_controllerToggle.Value, localPlayerPresent: true, flag2, _active, _active || HasBuildingTool(localPlayer));
			_chordHeld = flag3 && left && right;
			if (_toggleInput.Step(Time.frameCount, flag, _active || !flag2, left, right, flag3, Time.unscaledDeltaTime))
			{
				if (_active)
				{
					StopCamera("Toggled off", message: true);
				}
				else if (!flag2)
				{
					StartCamera(localPlayer);
				}
			}
			else
			{
				if (!_active)
				{
					return;
				}
				string text = InvalidActiveReason();
				if (text != null)
				{
					StopCamera(text, message: true);
					return;
				}
				KeepBodyAtAnchor();
				if (Menu.IsVisible() || ZInput.GetKeyDown((KeyCode)27, true) || ZInput.GetButtonDown("JoyMenu") || ZInput.GetButtonDown("JoyStart"))
				{
					StopCamera("Escape", message: true);
					return;
				}
				value = _resetKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown() && !flag2)
				{
					ResetView();
					_suppressUntil = Time.unscaledTime + 0.2f;
				}
				if (!flag2 && !_chordHeld && Time.unscaledTime >= _suppressUntil)
				{
					MoveCamera();
				}
				ApplyPose();
				if (!flag2 && !_chordHeld && Time.unscaledTime >= _suppressUntil)
				{
					TickTerrain();
				}
				else
				{
					HideBrush();
				}
			}
		}
		catch (Exception error)
		{
			Fail(error);
		}
	}

	private void LateUpdate()
	{
		if (!_active)
		{
			return;
		}
		try
		{
			PickaxeCameraRumble.Stop();
			string text = InvalidActiveReason();
			if (text != null)
			{
				StopCamera(text, message: true);
				return;
			}
			KeepBodyAtAnchor();
			ApplyPose();
			if (Time.unscaledTime >= _nextCircletCheck)
			{
				CircletCameraLight.Update(_player, _camera);
				_nextCircletCheck = Time.unscaledTime + 0.25f;
			}
			if (!_hidePlayer.Value)
			{
				RestoreRenderers();
			}
			else if (_hidePlayer.Value && Time.unscaledTime >= _nextRendererScan)
			{
				HideRenderers();
				_nextRendererScan = Time.unscaledTime + 0.25f;
			}
		}
		catch (Exception error)
		{
			Fail(error);
		}
	}

	private static bool HasBuildingTool(Player player)
	{
		return IsBuildTool(((Humanoid)player).RightItem);
	}

	private static bool IsBuildTool(ItemData item)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Invalid comparison between Unknown and I4
		if (item != null && item.m_shared != null)
		{
			return (int)item.m_shared.m_skillType == 12;
		}
		return false;
	}

	private static void ReadControllerSticks(out bool left, out bool right)
	{
		left = ZInput.GetButton("JoyLStick");
		right = ZInput.GetButton("JoyRStick");
		try
		{
			Gamepad current = Gamepad.current;
			if (current != null)
			{
				left |= current.leftStickButton.isPressed;
				right |= current.rightStickButton.isPressed;
			}
		}
		catch (Exception)
		{
		}
	}

	internal static bool MenuBlocksCamera()
	{
		try
		{
			return (Object.op_Implicit((Object)(object)Chat.instance) && Chat.instance.HasFocus()) || Console.IsVisible() || TextInput.IsVisible() || InventoryGui.IsVisible() || Menu.IsVisible() || StoreGui.IsVisible() || Minimap.IsOpen() || (Object.op_Implicit((Object)(object)TextViewer.instance) && TextViewer.instance.IsVisible()) || UnifiedPopup.IsVisible() || Hud.IsPieceSelectionVisible() || Hud.InRadial() || PlayerCustomizaton.IsBarberGuiVisible() || IsGamePausedSafe();
		}
		catch (NullReferenceException)
		{
			return true;
		}
	}

	private static bool IsGamePausedSafe()
	{
		if ((Object)(object)ZNet.instance == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null)
		{
			return false;
		}
		try
		{
			return Game.IsPaused();
		}
		catch (NullReferenceException)
		{
			return false;
		}
	}

	private void StartCamera(Player local)
	{
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ed: 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_0103: Unknown result type (might be due to invalid IL or missing references)
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_0119: Unknown result type (might be due to invalid IL or missing references)
		//IL_01af: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)local) || !HasBuildingTool(local))
		{
			Notify("Equip your pickaxe first.");
			return;
		}
		if (((Character)local).IsDead() || ((Character)local).InCutscene() || ((Character)local).IsTeleporting() || ((Character)local).IsAttached() || local.GetDoodadController() != null || !((Character)local).IsOnGround() || ((Character)local).IsSwimming())
		{
			Notify("Stand on solid ground to enter the pickaxe camera.");
			return;
		}
		if (!Object.op_Implicit((Object)(object)GameCamera.instance) || GameCamera.InFreeFly())
		{
			Notify("Return to the normal game camera first.");
			return;
		}
		if (OtherBuildCameraActive())
		{
			Notify("Exit the hammer build camera first.");
			return;
		}
		_gameCamera = GameCamera.instance;
		_camera = ((Component)_gameCamera).GetComponent<Camera>();
		if (!Object.op_Implicit((Object)(object)_camera))
		{
			Notify("The game camera is not ready yet.");
			_gameCamera = null;
			return;
		}
		_skyCamera = _gameCamera.m_skyCamera;
		_player = local;
		_bodyOrigin = ((Component)local).transform.position;
		_savedCameraPosition = ((Component)_gameCamera).transform.position;
		_savedCameraRotation = ((Component)_gameCamera).transform.rotation;
		_savedFov = _camera.fieldOfView;
		_savedNearClip = _camera.nearClipPlane;
		_activeNearClip = Mathf.Min(_savedNearClip, 0.1f);
		_savedSkyFov = (Object.op_Implicit((Object)(object)_skyCamera) ? _skyCamera.fieldOfView : _savedFov);
		_savedReach = local.m_maxPlaceDistance;
		_appliedReach = EffectiveBuildReach;
		_active = true;
		StartTerrain();
		local.m_autoRun = false;
		((Character)local).StopMovement();
		local.SetControls(Vector3.zero, false, false, false, false, false, false, false, false, false, false, false);
		local.m_maxPlaceDistance = _appliedReach;
		((Character)local).m_onDamaged = (Action<float, Character>)Delegate.Combine(((Character)local).m_onDamaged, new Action<float, Character>(OnPlayerDamaged));
		ResetView();
		if (_hidePlayer.Value)
		{
			HideRenderers();
		}
		_suppressUntil = Time.unscaledTime + 0.2f;
		_nextRendererScan = Time.unscaledTime + 0.25f;
		ApplyPose();
		Notify("Pickaxe camera ON. Jump: up; Crouch: down. F6 or press both stick clicks: exit.");
		WriteDiagnostics("Activated");
	}

	private void KeepBodyAtAnchor()
	{
		//IL_0019: 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_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: 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)
		if (Object.op_Implicit((Object)(object)_player))
		{
			Vector3 val = ((Component)_player).transform.position - _bodyOrigin;
			if (((Vector3)(ref val)).sqrMagnitude > 0.0001f)
			{
				((Component)_player).transform.position = _bodyOrigin;
				Physics.SyncTransforms();
			}
			((Character)_player).StopMovement();
		}
	}

	private string InvalidActiveReason()
	{
		if (!Object.op_Implicit((Object)(object)_player) || (Object)(object)_player != (Object)(object)Player.m_localPlayer)
		{
			return "Player changed";
		}
		if (!Object.op_Implicit((Object)(object)_gameCamera) || (Object)(object)GameCamera.instance != (Object)(object)_gameCamera || !Object.op_Implicit((Object)(object)_camera))
		{
			return "Camera changed";
		}
		if (!HasBuildingTool(_player))
		{
			return "Pickaxe unequipped";
		}
		if (((Character)_player).IsDead())
		{
			return "Player died";
		}
		if (((Character)_player).InCutscene() || ((Character)_player).IsTeleporting() || ((Character)_player).IsAttached() || _player.GetDoodadController() != null)
		{
			return "Player changed activity";
		}
		return null;
	}

	private void OnPlayerDamaged(float damage, Character attacker)
	{
		if (_active && _exitOnDamage.Value && damage > 0f)
		{
			StopCamera("You took damage", message: true);
		}
	}

	private void ResetView()
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: 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_007f: 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_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: 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)
		//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_00c7: 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_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		Quaternion rotation = ((Character)_player).m_eye.rotation;
		_yaw = ((Quaternion)(ref rotation)).eulerAngles.y;
		_pitch = CameraMath.Clamp(_startPitch.Value, 50f, 20f, 75f);
		_fov = CameraMath.Clamp(_startFov.Value, 45f, 25f, 75f);
		_rotation = Quaternion.Euler(_pitch, _yaw, 0f);
		Vector3 val = ((Component)_player).transform.position + Quaternion.Euler(0f, _yaw, 0f) * Vector3.forward * 5f + Vector3.up;
		_position = val - _rotation * Vector3.forward * 12f;
		ClampCameraPosition();
	}

	private void MoveCamera()
	{
		//IL_001a: 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_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ec: 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_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: 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_003f: 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_0176: Unknown result type (might be due to invalid IL or missing references)
		//IL_017b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0300: Unknown result type (might be due to invalid IL or missing references)
		//IL_030b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0312: Unknown result type (might be due to invalid IL or missing references)
		//IL_0318: Unknown result type (might be due to invalid IL or missing references)
		//IL_031d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0322: Unknown result type (might be due to invalid IL or missing references)
		float num = CameraMath.Clamp(Time.unscaledDeltaTime, 0f, 0f, 0.05f);
		Vector2 val = Vector2.zero;
		if (ZInput.IsMouseActive())
		{
			val = ZInput.GetMouseDelta() * (ZInput.IsGamepadMouseActive() ? PlayerController.m_switchMouseSens : PlayerController.m_mouseSens);
			if (PlayerController.m_invertMouse)
			{
				val.y *= -1f;
			}
		}
		else if (ZInput.IsGamepadActive())
		{
			val = new Vector2(StickInput.RightStickX(), 0f - StickInput.RightStickY()) * 110f * num * PlayerController.m_gamepadSens;
			if (PlayerController.m_invertCameraX)
			{
				val.x *= -1f;
			}
			if (PlayerController.m_invertCameraY)
			{
				val.y *= -1f;
			}
		}
		_yaw = Mathf.Repeat(_yaw + val.x, 360f);
		_pitch = Mathf.Clamp(_pitch - val.y, -80f, 85f);
		if (ZInput.GetKey((KeyCode)280, true))
		{
			_fov -= 25f * num;
		}
		if (ZInput.GetKey((KeyCode)281, true))
		{
			_fov += 25f * num;
		}
		_fov = Mathf.Clamp(_fov, 25f, 75f);
		_rotation = Quaternion.Euler(_pitch, _yaw, 0f);
		float x = (ZInput.GetButton("Right") ? 1f : 0f) - (ZInput.GetButton("Left") ? 1f : 0f) + StickInput.LeftStickX();
		float z = (ZInput.GetButton("Forward") ? 1f : 0f) - (ZInput.GetButton("Backward") ? 1f : 0f) - StickInput.LeftStickY();
		float y = ((ZInput.GetButton("Jump") || ZInput.GetButton("JoyJump")) ? 1f : 0f) - ((ZInput.GetButton("Crouch") || ZInput.GetButton("JoyCrouch")) ? 1f : 0f);
		CameraMath.NormalizeInput(ref x, ref y, ref z);
		float num2 = CameraMath.Clamp(_speed.Value, 6f, 1f, 15f);
		if (ZInput.GetButton("Run") || ZInput.GetButton("JoyRun"))
		{
			num2 *= CameraMath.Clamp(_fastMultiplier.Value, 2f, 1f, 3f);
		}
		if (x != 0f || y != 0f || z != 0f)
		{
			MovementVector movementVector = CameraMath.ViewRelativeMovement(_yaw, _pitch, x, y, z);
			float x2 = movementVector.X;
			float y2 = movementVector.Y;
			float z2 = movementVector.Z;
			CameraMath.NormalizeInput(ref x2, ref y2, ref z2);
			_position += new Vector3(x2, y2, z2) * num2 * num;
			ClampCameraPosition();
		}
	}

	private void ClampCameraPosition()
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//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_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: 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_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: 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_0051: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = _bodyOrigin + Vector3.up;
		Vector3 val2 = _position - val;
		float x = val2.x;
		float y = val2.y;
		float z = val2.z;
		CameraMath.ClampToSphere(ref x, ref y, ref z, EffectiveCameraRadius);
		_position = val + new Vector3(x, y, z);
	}

	internal void ApplyPose()
	{
		//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_003e: 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_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: 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)
		if (!_active || !Object.op_Implicit((Object)(object)_camera) || !Object.op_Implicit((Object)(object)_gameCamera))
		{
			return;
		}
		PickaxeCameraRumble.Stop();
		Transform transform = ((Component)_gameCamera).transform;
		Vector3 position = transform.position;
		if (((Vector3)(ref position)).Equals(_position))
		{
			Quaternion rotation = transform.rotation;
			if (((Quaternion)(ref rotation)).Equals(_rotation))
			{
				goto IL_0072;
			}
		}
		transform.SetPositionAndRotation(_position, _rotation);
		goto IL_0072;
		IL_0072:
		if (_camera.fieldOfView != _fov)
		{
			_camera.fieldOfView = _fov;
		}
		if (_camera.nearClipPlane != _activeNearClip)
		{
			_camera.nearClipPlane = _activeNearClip;
		}
		if (Object.op_Implicit((Object)(object)_skyCamera) && _skyCamera.fieldOfView != _fov)
		{
			_skyCamera.fieldOfView = _fov;
		}
	}

	private void HideRenderers()
	{
		LocalPlayerVisuals.Hide(_player, _camera);
	}

	private void StopCamera(string reason, bool message)
	{
		//IL_0184: Unknown result type (might be due to invalid IL or missing references)
		//IL_018a: Unknown result type (might be due to invalid IL or missing references)
		//IL_018f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0194: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01db: Unknown result type (might be due to invalid IL or missing references)
		_nextCircletCheck = 0f;
		StopTerrain();
		if (_active)
		{
			PickaxeCameraRumble.Stop();
		}
		CircletCameraLight.Stop();
		FeatherCapeMist.Clear();
		_toggleInput.CancelPending();
		if (!_active)
		{
			return;
		}
		_active = false;
		_lastExit = reason;
		try
		{
			if (Object.op_Implicit((Object)(object)_player))
			{
				Player player = _player;
				((Character)player).m_onDamaged = (Action<float, Character>)Delegate.Remove(((Character)player).m_onDamaged, new Action<float, Character>(OnPlayerDamaged));
				if (Mathf.Approximately(_player.m_maxPlaceDistance, _appliedReach))
				{
					_player.m_maxPlaceDistance = _savedReach;
				}
			}
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Build reach cleanup: " + ex.Message));
		}
		RestoreRenderers();
		try
		{
			if (Object.op_Implicit((Object)(object)_camera))
			{
				_camera.fieldOfView = _savedFov;
				_camera.nearClipPlane = _savedNearClip;
			}
			if (Object.op_Implicit((Object)(object)_skyCamera))
			{
				_skyCamera.fieldOfView = _savedSkyFov;
			}
			if (Object.op_Implicit((Object)(object)_player) && (Object)(object)_player == (Object)(object)Player.m_localPlayer && !((Character)_player).IsTeleporting() && !((Character)_player).InCutscene() && !((Character)_player).IsAttached() && _player.GetDoodadController() == null)
			{
				Vector3 val = ((Component)_player).transform.position - _bodyOrigin;
				if (((Vector3)(ref val)).sqrMagnitude < 1f && Object.op_Implicit((Object)(object)_gameCamera) && (Object)(object)_gameCamera == (Object)(object)GameCamera.instance && !GameCamera.InFreeFly())
				{
					((Component)_gameCamera).transform.SetPositionAndRotation(_savedCameraPosition, _savedCameraRotation);
				}
			}
		}
		catch (Exception ex2)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Camera cleanup: " + ex2.Message));
		}
		_player = null;
		_gameCamera = null;
		_camera = null;
		_skyCamera = null;
		float suppressUntil;
		switch (reason)
		{
		default:
			suppressUntil = 0f;
			break;
		case "Toggled off":
		case "Escape":
		case "Configuration reload":
			suppressUntil = Time.unscaledTime + 0.2f;
			break;
		}
		_suppressUntil = suppressUntil;
		if (message)
		{
			Notify("Pickaxe camera OFF: " + reason + ".");
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Free Pickaxe Cam stopped: " + reason));
	}

	private void RestoreRenderers()
	{
		LocalPlayerVisuals.Restore();
	}

	internal void Fail(Exception error)
	{
		StopCamera("Stopped after an error", message: false);
		_failed = true;
		ResetInput();
		((BaseUnityPlugin)this).Logger.LogError((object)("Free Pickaxe Cam stopped and restored its local changes. " + error));
		WriteDiagnostics("Error: " + error.GetType().Name + ": " + error.Message);
	}

	private static void Notify(string text)
	{
		if (Object.op_Implicit((Object)(object)MessageHud.instance))
		{
			MessageHud.instance.ShowMessage((MessageType)1, text, 0, (Sprite)null, false, true);
		}
	}

	private void OnGUI()
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Invalid comparison between Unknown and I4
		if ((int)Event.current.type == 7 && Active && !MenuBlocksCamera())
		{
			DrawTerrainHud();
		}
	}

	private void RefreshIndicatorText()
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		_indicatorText = "PICKAXE CAM  |  " + ((object)_toggleKey.Value/*cast due to .constrained prefix*/).ToString() + (_controllerToggle.Value ? " / press both stick clicks to exit" : " to exit");
	}

	private void ResetInput()
	{
		_toggleInput.Reset(waitForRelease: true);
		_chordHeld = false;
		_suppressUntil = 0f;
	}

	private void OnApplicationFocus(bool focused)
	{
		if (!focused)
		{
			StopCamera("Focus lost", message: false);
			ResetInput();
		}
	}

	private void OnDisable()
	{
		StopCamera("Plugin disabled", message: false);
		ResetInput();
	}

	private void OnDestroy()
	{
		StopCamera("Plugin unloaded", message: false);
		ResetInput();
		if (_harmony != null)
		{
			_harmony.UnpatchSelf();
		}
		if ((Object)(object)Instance == (Object)(object)this)
		{
			Instance = null;
		}
	}

	private void WriteDiagnostics(string reason)
	{
		//IL_0226: Unknown result type (might be due to invalid IL or missing references)
		//IL_022c: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("Free Pickaxe Cam 0.1.2 - client diagnostics");
			stringBuilder.AppendLine("Reason: " + reason);
			stringBuilder.AppendLine("No player names, server addresses, chat, item descriptions or world coordinates included.");
			stringBuilder.AppendLine("Unity=" + Application.unityVersion + "; screen=" + Screen.width + "x" + Screen.height);
			stringBuilder.AppendLine("Ready=" + _ready + "; failed=" + _failed + "; active=" + _active + "; last exit=" + _lastExit);
			stringBuilder.AppendLine("Effective camera radius=" + EffectiveCameraRadius + "; configured free-camera reach=" + EffectiveBuildReach + "; range multiplier=" + _rangeMultiplier.Value);
			stringBuilder.AppendLine("Game assembly=" + typeof(Player).Assembly.GetName().Version?.ToString() + "; Harmony=" + typeof(Harmony).Assembly.GetName().Version);
			if (Object.op_Implicit((Object)(object)_player))
			{
				stringBuilder.AppendLine("Building tool=" + HasBuildingTool(_player) + "; grounded=" + ((Character)_player).IsOnGround() + "; menu paused=" + MenuBlocksCamera());
				stringBuilder.AppendLine("Camera distance from body=" + Vector3.Distance(_position, _bodyOrigin).ToString("F2", CultureInfo.InvariantCulture));
				stringBuilder.AppendLine("Pitch=" + _pitch + "; FOV=" + _fov + "; temporary reach=" + _player.m_maxPlaceDistance + "; original reach=" + _savedReach);
				stringBuilder.AppendLine("Tracked local renderers=" + LocalPlayerVisuals.RendererCount);
			}
			stringBuilder.AppendLine("Mining uses native deposit damage and native drops; inventory transfer respects weight and slot capacity.");
			File.WriteAllText(Path.Combine(Paths.ConfigPath, "valheim.pickaxecam.diagnostics.txt"), stringBuilder.ToString());
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not write pickaxe camera diagnostics: " + ex.Message));
		}
	}
}
internal struct MovementVector
{
	internal float X;

	internal float Y;

	internal float Z;

	internal MovementVector(float x, float y, float z)
	{
		X = x;
		Y = y;
		Z = z;
	}
}
internal static class CameraMath
{
	internal static float FreeCameraRange(float baseMetres, float minimumBase, float multiplier)
	{
		return Clamp(baseMetres, 25f, minimumBase, 25f) * Clamp(multiplier, 2f, 1f, 2f);
	}

	internal static float PickaxeCameraRange(float baseMetres, float minimumBase, float multiplier)
	{
		return FreeCameraRange(baseMetres, minimumBase, multiplier) * 2f;
	}

	internal static float BuildRayDistance(float cameraEyeDistance, float appliedReach, float pieceExtraDistance)
	{
		return Math.Max(50f, cameraEyeDistance + appliedReach + Math.Max(0f, pieceExtraDistance) + 1f);
	}

	internal static MovementVector ViewRelativeMovement(float yawDegrees, float pitchDegrees, float strafe, float vertical, float forward)
	{
		double num = (double)yawDegrees * Math.PI / 180.0;
		double num2 = (double)pitchDegrees * Math.PI / 180.0;
		float num3 = (float)Math.Sin(num);
		float num4 = (float)Math.Cos(num);
		float num5 = (float)Math.Cos(num2);
		float num6 = (float)Math.Sin(num2);
		float num7 = num4;
		float num8 = 0f - num3;
		float num9 = num3 * num5;
		float num10 = 0f - num6;
		float num11 = num4 * num5;
		return new MovementVector(num7 * strafe + num9 * forward, vertical + num10 * forward, num8 * strafe + num11 * forward);
	}

	internal static float Clamp(float value, float fallback, float min, float max)
	{
		if (!float.IsNaN(value) && !float.IsInfinity(value))
		{
			return Math.Max(min, Math.Min(max, value));
		}
		return fallback;
	}

	internal static void NormalizeInput(ref float x, ref float y, ref float z)
	{
		float num = x * x + y * y + z * z;
		if (!(num <= 1f))
		{
			float num2 = (float)Math.Sqrt(num);
			x /= num2;
			y /= num2;
			z /= num2;
		}
	}

	internal static void ClampToSphere(ref float x, ref float y, ref float z, float radius)
	{
		float num = x * x + y * y + z * z;
		if (!(num <= radius * radius) && !(num < 1E-10f))
		{
			float num2 = (float)Math.Sqrt(num);
			float num3 = radius / num2;
			x *= num3;
			y *= num3;
			z *= num3;
		}
	}

	internal static bool ControllerToggleEligible(bool enabled, bool localPlayerPresent, bool modal, bool active, bool hasBuildingTool)
	{
		if (enabled && localPlayerPresent && !modal)
		{
			return active || hasBuildingTool;
		}
		return false;
	}
}
internal sealed class HoldToggle
{
	private float _held;

	private bool _fired;

	internal bool Step(bool pressed, float dt)
	{
		if (!pressed)
		{
			_held = 0f;
			_fired = false;
			return false;
		}
		_held += CameraMath.Clamp(dt, 0f, 0f, 0.1f);
		if (_fired || _held < 0.5f)
		{
			return false;
		}
		_fired = true;
		return true;
	}

	internal void Reset()
	{
		_held = 0f;
		_fired = false;
	}
}
internal sealed class ButtonChordToggle
{
	private float _window;

	private float _bothHeld;

	private bool _fired;

	internal bool Step(bool left, bool right, float dt)
	{
		dt = CameraMath.Clamp(dt, 0f, 0f, 0.1f);
		if (!left && !right)
		{
			Reset();
			return false;
		}
		_window = Math.Min(2f, _window + dt);
		if (left && right)
		{
			_bothHeld = Math.Min(1f, _bothHeld + dt);
			if (!_fired && (_window <= 0.35f || _bothHeld >= 0.25f))
			{
				_fired = true;
				return true;
			}
		}
		else
		{
			_bothHeld = 0f;
		}
		return false;
	}

	internal void Reset()
	{
		_window = 0f;
		_bothHeld = 0f;
		_fired = false;
	}
}
internal sealed class CameraToggleInput
{
	private readonly ButtonChordToggle _chord = new ButtonChordToggle();

	private int _keyboardFrame = -1;

	private bool _waitForRelease;

	internal bool HasPendingKeyboard => _keyboardFrame >= 0;

	internal bool Step(int frame, bool keyDown, bool keyboardAllowed, bool left, bool right, bool controllerAllowed, float dt)
	{
		if (_waitForRelease)
		{
			if (keyDown || left || right)
			{
				return false;
			}
			_waitForRelease = false;
		}
		bool num = _chord.Step(left, right, dt);
		if (!keyboardAllowed)
		{
			CancelPending();
		}
		bool flag = HasPendingKeyboard && frame > _keyboardFrame;
		if ((num && controllerAllowed) || flag)
		{
			CancelPending();
			return true;
		}
		if (keyDown && keyboardAllowed)
		{
			_keyboardFrame = frame;
		}
		return false;
	}

	internal void CancelPending()
	{
		_keyboardFrame = -1;
	}

	internal void Reset(bool waitForRelease)
	{
		CancelPending();
		_chord.Reset();
		_waitForRelease = waitForRelease;
	}
}
internal static class CircletCameraLight
{
	private static Light _light;

	private static Type _playerType;

	private static Type _itemType;

	private static FieldInfo _inventory;

	private static FieldInfo _prefab;

	private static FieldInfo _equipped;

	private static MethodInfo _getItems;

	private static bool _warned;

	private static FieldInfo FindField(Type type, string name)
	{
		while (type != null)
		{
			FieldInfo field = type.GetField(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null)
			{
				return field;
			}
			type = type.BaseType;
		}
		throw new MissingFieldException(name);
	}

	internal static bool IsCirclet(string prefabName)
	{
		if (prefabName == null)
		{
			return false;
		}
		prefabName = prefabName.Trim();
		if (prefabName.EndsWith("(Clone)", StringComparison.Ordinal))
		{
			prefabName = prefabName.Substring(0, prefabName.Length - "(Clone)".Length).TrimEnd();
		}
		return string.Equals(prefabName, "HelmetDverger", StringComparison.Ordinal);
	}

	private static bool Equipped(object player)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Expected O, but got Unknown
		if (player == null || !(player is Object) || !Object.op_Implicit((Object)player))
		{
			return false;
		}
		Type type = player.GetType();
		if (_playerType != type)
		{
			_inventory = FindField(type, "m_inventory");
			_getItems = null;
			_playerType = type;
		}
		object value = _inventory.GetValue(player);
		if (value == null)
		{
			return false;
		}
		if (_getItems == null)
		{
			_getItems = value.GetType().GetMethod("GetAllItems", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
			if (_getItems == null)
			{
				throw new MissingMethodException("Inventory.GetAllItems");
			}
		}
		foreach (object item in (IEnumerable)_getItems.Invoke(value, null))
		{
			if (item == null)
			{
				continue;
			}
			if (_itemType != item.GetType())
			{
				_prefab = FindField(item.GetType(), "m_dropPrefab");
				_equipped = FindField(item.GetType(), "m_equipped");
				_itemType = item.GetType();
			}
			if ((bool)_equipped.GetValue(item))
			{
				object? value2 = _prefab.GetValue(item);
				GameObject val = (GameObject)((value2 is GameObject) ? value2 : null);
				if (Object.op_Implicit((Object)(object)val) && IsCirclet(((Object)val).name))
				{
					return true;
				}
			}
		}
		return false;
	}

	internal static void Update(object player, Camera camera)
	{
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: 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_0042: 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_00d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_0153: Unknown result type (might be due to invalid IL or missing references)
		//IL_0167: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (!Object.op_Implicit((Object)(object)camera) || !Equipped(player))
			{
				Stop();
				return;
			}
			if (!Object.op_Implicit((Object)(object)_light))
			{
				GameObject val = new GameObject("PickaxeCamera_CircletLight")
				{
					hideFlags = (HideFlags)52
				};
				val.SetActive(false);
				_light = val.AddComponent<Light>();
				_light.type = (LightType)0;
				_light.range = 35f;
				_light.spotAngle = 100f;
				_light.intensity = 1.5f;
				_light.color = new Color(1f, 0.95f, 0.85f);
				_light.shadows = (LightShadows)2;
				_light.renderMode = (LightRenderMode)1;
				((Component)_light).transform.SetParent(((Component)camera).transform, false);
				((Component)_light).transform.localPosition = Vector3.zero;
				((Component)_light).transform.localRotation = Quaternion.identity;
				_light.cullingMask = camera.cullingMask;
				val.SetActive(true);
				Debug.Log((object)"Free Pickaxe Cam circlet light: camera spotlight activated (local only).");
			}
			if ((Object)(object)((Component)_light).transform.parent != (Object)(object)((Component)camera).transform)
			{
				((Component)_light).transform.SetParent(((Component)camera).transform, false);
				((Component)_light).transform.localPosition = Vector3.zero;
				((Component)_light).transform.localRotation = Quaternion.identity;
			}
			_light.cullingMask = camera.cullingMask;
		}
		catch (Exception ex)
		{
			Stop();
			if (!_warned)
			{
				_warned = true;
				Debug.LogWarning((object)("Free Pickaxe Cam circlet light unavailable: " + ex.Message));
			}
		}
	}

	internal static void Stop()
	{
		if (Object.op_Implicit((Object)(object)_light))
		{
			((Behaviour)_light).enabled = false;
			Object.Destroy((Object)(object)((Component)_light).gameObject);
		}
		_light = null;
	}
}
internal static class FeatherCapeMist
{
	[HarmonyPatch(typeof(ParticleMist), "Update")]
	private static class ParticleMistUpdate
	{
		private static bool Prefix(ParticleMist __instance)
		{
			try
			{
				if ((!Object.op_Implicit((Object)(object)PickaxeCamera.Instance) || !PickaxeCamera.Instance.Active) && !hidden)
				{
					return true;
				}
				if (mistParticleField == null)
				{
					mistParticleField = FindField(typeof(ParticleMist), "m_ps");
				}
				object? value = mistParticleField.GetValue(__instance);
				object? obj = ((value is ParticleSystem) ? value : null);
				if ((Object)obj != (Object)(object)mistParticles && hidden)
				{
					SetHidden(value: false);
				}
				mistParticles = (ParticleSystem)obj;
				if (ShouldHide())
				{
					SetHidden(value: true);
				}
				else if (hidden)
				{
					SetHidden(value: false);
					mistParticles = null;
				}
				return true;
			}
			catch (Exception ex)
			{
				if (hidden)
				{
					SetHidden(value: false);
				}
				if (!warned)
				{
					warned = true;
					Debug.LogWarning((object)("Free Pickaxe Cam feather-cape mist control unavailable: " + ex.Message));
				}
				return true;
			}
		}
	}

	private static FieldInfo inventoryField;

	private static FieldInfo prefabField;

	private static FieldInfo equippedField;

	private static FieldInfo mistParticleField;

	private static MethodInfo getItems;

	private static Type playerType;

	private static Type itemType;

	private static ParticleSystem mistParticles;

	private static bool hidden;

	private static Renderer mistRenderer;

	private static bool previousForceOff;

	private static bool warned;

	private static Player cachedPlayer;

	private static float nextEquipmentCheck;

	private static bool cachedEquipped;

	private static FieldInfo FindField(Type type, string name)
	{
		while (type != null)
		{
			FieldInfo field = type.GetField(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null)
			{
				return field;
			}
			type = type.BaseType;
		}
		throw new MissingFieldException(name);
	}

	private static bool Equipped(object player)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Expected O, but got Unknown
		if (player == null || !(player is Object) || !Object.op_Implicit((Object)player))
		{
			return false;
		}
		Type type = player.GetType();
		if (playerType != type)
		{
			inventoryField = FindField(type, "m_inventory");
			getItems = null;
			playerType = type;
		}
		object value = inventoryField.GetValue(player);
		if (value == null)
		{
			return false;
		}
		if (getItems == null)
		{
			getItems = value.GetType().GetMethod("GetAllItems", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
		}
		if (getItems == null)
		{
			return false;
		}
		foreach (object item in (IEnumerable)getItems.Invoke(value, null))
		{
			if (item == null)
			{
				continue;
			}
			if (itemType != item.GetType())
			{
				prefabField = FindField(item.GetType(), "m_dropPrefab");
				equippedField = FindField(item.GetType(), "m_equipped");
				itemType = item.GetType();
			}
			if ((bool)equippedField.GetValue(item))
			{
				object? value2 = prefabField.GetValue(item);
				GameObject val = (GameObject)((value2 is GameObject) ? value2 : null);
				if (Object.op_Implicit((Object)(object)val) && string.Equals(((Object)val).name.Trim().Replace("(Clone)", "").Trim(), "CapeFeather", StringComparison.Ordinal))
				{
					return true;
				}
			}
		}
		return false;
	}

	private static void SetHidden(bool value)
	{
		if (!Object.op_Implicit((Object)(object)mistParticles) && value)
		{
			return;
		}
		if (value && !hidden)
		{
			mistRenderer = (Renderer)(object)((Component)mistParticles).GetComponent<ParticleSystemRenderer>();
			if (!Object.op_Implicit((Object)(object)mistRenderer))
			{
				return;
			}
			previousForceOff = mistRenderer.forceRenderingOff;
		}
		if (Object.op_Implicit((Object)(object)mistRenderer))
		{
			mistRenderer.forceRenderingOff = value || previousForceOff;
		}
		hidden = value;
	}

	private static bool ShouldHide()
	{
		if (!Object.op_Implicit((Object)(object)PickaxeCamera.Instance) || !PickaxeCamera.Instance.Active || !Object.op_Implicit((Object)(object)Player.m_localPlayer))
		{
			return false;
		}
		if ((Object)(object)cachedPlayer != (Object)(object)Player.m_localPlayer || Time.unscaledTime >= nextEquipmentCheck)
		{
			cachedPlayer = Player.m_localPlayer;
			cachedEquipped = Equipped(cachedPlayer);
			nextEquipmentCheck = Time.unscaledTime + 0.25f;
		}
		return cachedEquipped;
	}

	internal static void Clear()
	{
		if (hidden)
		{
			SetHidden(value: false);
		}
		mistParticles = null;
		hidden = false;
		cachedPlayer = null;
		nextEquipmentCheck = 0f;
		cachedEquipped = false;
	}
}
internal static class HotbarInputGuard
{
	[HarmonyPatch(typeof(HotkeyBar), "Update")]
	private static class GuardHotbarInput
	{
		[HarmonyPriority(800)]
		private static void Prefix(out bool __state)
		{
			Enter(out __state);
		}

		private static void Finalizer(bool __state)
		{
			Leave(__state);
		}
	}

	[HarmonyPatch(typeof(ZInput), "GetButtonDown", new Type[] { typeof(string) })]
	private static class GuardNativeInput
	{
		[HarmonyPriority(0)]
		private static bool Prefix(ref bool __result)
		{
			return ReadInput(ref __result);
		}
	}

	[ThreadStatic]
	private static int hotbarInputDepth;

	internal static void Enter(out bool entered)
	{
		PickaxeCamera instance = PickaxeCamera.Instance;
		entered = Object.op_Implicit((Object)(object)instance) && instance.ControlsOwned(Player.m_localPlayer);
		if (entered)
		{
			hotbarInputDepth++;
		}
	}

	internal static void Leave(bool entered)
	{
		if (entered && hotbarInputDepth > 0)
		{
			hotbarInputDepth--;
		}
	}

	internal static bool ReadInput(ref bool result)
	{
		if (hotbarInputDepth == 0)
		{
			return true;
		}
		result = false;
		return false;
	}
}
internal static class LocalPlayerVisuals
{
	private static readonly Dictionary<Renderer, bool> Renderers = new Dictionary<Renderer, bool>();

	private static readonly Dictionary<Light, bool> Lights = new Dictionary<Light, bool>();

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

	private static readonly HashSet<Light> SeenLights = new HashSet<Light>();

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

	private static readonly List<Light> LightScan = new List<Light>();

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

	private static readonly List<Light> RetiredLights = new List<Light>();

	private static Component _owner;

	private static bool _warned;

	private static readonly Dictionary<Type, FieldInfo> EffectFields = new Dictionary<Type, FieldInfo>();

	internal static int RendererCount => Renderers.Count;

	private static void Scan(GameObject root, Camera camera)
	{
		if (!Object.op_Implicit((Object)(object)root))
		{
			return;
		}
		RendererScan.Clear();
		LightScan.Clear();
		root.GetComponentsInChildren<Renderer>(true, RendererScan);
		root.GetComponentsInChildren<Light>(true, LightScan);
		foreach (Renderer item in RendererScan)
		{
			if (Object.op_Implicit((Object)(object)item) && (!Object.op_Implicit((Object)(object)camera) || !((Component)item).transform.IsChildOf(((Component)camera).transform)))
			{
				SeenRenderers.Add(item);
				if (!Renderers.ContainsKey(item))
				{
					Renderers.Add(item, item.forceRenderingOff);
				}
				item.forceRenderingOff = true;
			}
		}
		foreach (Light item2 in LightScan)
		{
			if (Object.op_Implicit((Object)(object)item2) && (!Object.op_Implicit((Object)(object)camera) || !((Component)item2).transform.IsChildOf(((Component)camera).transform)))
			{
				SeenLights.Add(item2);
				if (!Lights.ContainsKey(item2))
				{
					Lights.Add(item2, ((Behaviour)item2).enabled);
				}
				((Behaviour)item2).enabled = false;
			}
		}
	}

	internal static void Hide(object player, Camera camera)
	{
		Component val = (Component)((player is Component) ? player : null);
		if (!Object.op_Implicit((Object)(object)val))
		{
			Restore();
			return;
		}
		if ((Object)(object)_owner != (Object)(object)val)
		{
			Restore();
			_owner = val;
		}
		SeenRenderers.Clear();
		SeenLights.Clear();
		Scan(val.gameObject, camera);
		try
		{
			MethodInfo method = ((object)val).GetType().GetMethod("GetSEMan", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
			if (method != null)
			{
				object obj = method.Invoke(val, null);
				if (obj != null)
				{
					MethodInfo method2 = obj.GetType().GetMethod("GetStatusEffects", Type.EmptyTypes);
					if (method2 != null)
					{
						foreach (object item in (IEnumerable)method2.Invoke(obj, null))
						{
							if (item == null)
							{
								continue;
							}
							Type type = item.GetType();
							if (!EffectFields.TryGetValue(type, out var value))
							{
								Type type2 = type;
								while (type2 != null && value == null)
								{
									value = type2.GetField("m_startEffectInstances", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
									type2 = type2.BaseType;
								}
								EffectFields.Add(type, value);
							}
							IEnumerable enumerable = ((value == null) ? null : (value.GetValue(item) as IEnumerable));
							if (enumerable == null)
							{
								continue;
							}
							foreach (object item2 in enumerable)
							{
								Scan((GameObject)((item2 is GameObject) ? item2 : null), camera);
							}
						}
					}
				}
			}
		}
		catch (Exception ex)
		{
			if (!_warned)
			{
				_warned = true;
				Debug.LogWarning((object)("Free Pickaxe Cam effect visibility: " + ex.Message));
			}
		}
		RetiredRenderers.Clear();
		RetiredLights.Clear();
		foreach (KeyValuePair<Renderer, bool> renderer in Renderers)
		{
			if (!Object.op_Implicit((Object)(object)renderer.Key) || !SeenRenderers.Contains(renderer.Key))
			{
				if (Object.op_Implicit((Object)(object)renderer.Key))
				{
					renderer.Key.forceRenderingOff = renderer.Value;
				}
				RetiredRenderers.Add(renderer.Key);
			}
		}
		foreach (KeyValuePair<Light, bool> light in Lights)
		{
			if (!Object.op_Implicit((Object)(object)light.Key) || !SeenLights.Contains(light.Key))
			{
				if (Object.op_Implicit((Object)(object)light.Key))
				{
					((Behaviour)light.Key).enabled = light.Value;
				}
				RetiredLights.Add(light.Key);
			}
		}
		foreach (Renderer retiredRenderer in RetiredRenderers)
		{
			Renderers.Remove(retiredRenderer);
		}
		foreach (Light retiredLight in RetiredLights)
		{
			Lights.Remove(retiredLight);
		}
	}

	internal static void Restore()
	{
		foreach (KeyValuePair<Renderer, bool> renderer in Renderers)
		{
			if (Object.op_Implicit((Object)(object)renderer.Key))
			{
				renderer.Key.forceRenderingOff = renderer.Value;
			}
		}
		foreach (KeyValuePair<Light, bool> light in Lights)
		{
			if (Object.op_Implicit((Object)(object)light.Key))
			{
				((Behaviour)light.Key).enabled = light.Value;
			}
		}
		Renderers.Clear();
		Lights.Clear();
		SeenRenderers.Clear();
		SeenLights.Clear();
		RendererScan.Clear();
		LightScan.Clear();
		RetiredRenderers.Clear();
		RetiredLights.Clear();
		_owner = null;
	}
}
internal static class MiningOperation
{
	private static readonly FieldInfo OldAreas = AccessTools.Field(typeof(MineRock), "m_hitAreas");

	private static readonly FieldInfo Areas = AccessTools.Field(typeof(MineRock5), "m_hitAreas");

	private static readonly MethodInfo OldHit = AccessTools.Method(typeof(MineRock), "RPC_Hit", (Type[])null, (Type[])null);

	private static readonly MethodInfo Hit = AccessTools.Method(typeof(MineRock5), "RPC_Damage", (Type[])null, (Type[])null);

	internal static void Validate()
	{
		if (OldAreas == null || Areas == null || OldHit == null || Hit == null || AccessTools.Method(typeof(ItemDrop), "Save", Type.EmptyTypes, (Type[])null) == null)
		{
			throw new MissingMethodException("Native mining or loot API unavailable");
		}
	}

	internal static bool IsDeposit(GameObject root)
	{
		if (!Object.op_Implicit((Object)(object)root) || Object.op_Implicit((Object)(object)root.GetComponentInParent<Character>()) || Object.op_Implicit((Object)(object)root.GetComponent<Piece>()) || Object.op_Implicit((Object)(object)root.GetComponent<WearNTear>()) || Object.op_Implicit((Object)(object)root.GetComponent<ItemDrop>()) || Object.op_Implicit((Object)(object)root.GetComponent<Container>()) || Object.op_Implicit((Object)(object)root.GetComponent<TreeBase>()) || Object.op_Implicit((Object)(object)root.GetComponent<TreeLog>()))
		{
			return false;
		}
		if (Object.op_Implicit((Object)(object)root.GetComponent<MineRock>()) || Object.op_Implicit((Object)(object)root.GetComponent<MineRock5>()))
		{
			return true;
		}
		if (Object.op_Implicit((Object)(object)root.GetComponent<Destructible>()))
		{
			return MiningPolicy.MineralName(((Object)root).name);
		}
		return false;
	}

	internal static string Name(GameObject root)
	{
		if (!Object.op_Implicit((Object)(object)root))
		{
			return "Aim at a stone or ore deposit";
		}
		MineRock component = root.GetComponent<MineRock>();
		if (Object.op_Implicit((Object)(object)component))
		{
			return Localization.instance.Localize(component.m_name);
		}
		MineRock5 component2 = root.GetComponent<MineRock5>();
		if (Object.op_Implicit((Object)(object)component2))
		{
			return Localization.instance.Localize(component2.m_name);
		}
		return ((Object)root).name.Replace("(Clone)", "");
	}

	internal static Bounds Bounds(GameObject root)
	{
		//IL_0008: 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_0062: 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_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		Bounds bounds = default(Bounds);
		((Bounds)(ref bounds))..ctor(root.transform.position, Vector3.zero);
		bool flag = true;
		Collider[] componentsInChildren = root.GetComponentsInChildren<Collider>();
		foreach (Collider val in componentsInChildren)
		{
			if (val.enabled && !val.isTrigger)
			{
				if (flag)
				{
					bounds = val.bounds;
					flag = false;
				}
				else
				{
					((Bounds)(ref bounds)).Encapsulate(val.bounds);
				}
			}
		}
		return bounds;
	}

	internal static bool Allowed(GameObject root, Player player, float reach)
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: 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_002c: 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_0040: 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)
		if (!IsDeposit(root) || !Object.op_Implicit((Object)(object)player))
		{
			return false;
		}
		Bounds val = Bounds(root);
		if (Vector3.Distance(((Component)player).transform.position, ((Bounds)(ref val)).ClosestPoint(((Component)player).transform.position)) <= reach)
		{
			Vector3 center = ((Bounds)(ref val)).center;
			Vector3 extents = ((Bounds)(ref val)).extents;
			return PrivateArea.CheckAccess(center, ((Vector3)(ref extents)).magnitude, false, false);
		}
		return false;
	}

	private static HitData Damage(Player player, Vector3 point, Collider collider)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: 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_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: 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_0029: 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_0041: Expected O, but got Unknown
		HitData val = new HitData
		{
			m_point = point,
			m_dir = Vector3.down,
			m_hitCollider = collider,
			m_toolTier = short.MaxValue,
			m_damage = 
			{
				m_damage = 1E+09f
			}
		};
		val.SetAttacker((Character)(object)player);
		return val;
	}

	internal static IEnumerator Mine(Player player, GameObject root, float reach, Action<string> status, Action done)
	{
		Queue<GameObject> queue = new Queue<GameObject>();
		queue.Enqueue(root);
		HashSet<int> visited = new HashSet<int>();
		MiningReturns.Overflow = 0;
		MiningReturns.Collected = 0;
		bool failed = false;
		try
		{
			while (true)
			{
				if (queue.Count > 0 && Object.op_Implicit((Object)(object)player) && (Object)(object)player == (Object)(object)Player.m_localPlayer && !((Character)player).IsDead())
				{
					GameObject target = queue.Dequeue();
					if (!Object.op_Implicit((Object)(object)target) || !visited.Add(((Object)target).GetInstanceID()) || !IsDeposit(target))
					{
						continue;
					}
					yield return null;
					if (!Object.op_Implicit((Object)(object)target))
					{
						continue;
					}
					if (!Allowed(target, player, reach))
					{
						failed = true;
						status("Deposit is out of reach or protected");
					}
					else
					{
						ZNetView view = target.GetComponent<ZNetView>();
						if (!Object.op_Implicit((Object)(object)view) || !view.IsValid())
						{
							failed = true;
							status("Deposit is not ready");
						}
						else
						{
							float deadline = Time.unscaledTime + 2f;
							if (!view.IsOwner())
							{
								view.ClaimOwnership();
							}
							while (Object.op_Implicit((Object)(object)view) && view.IsValid() && !view.IsOwner() && Time.unscaledTime < deadline)
							{
								status("Waiting for deposit ownership");
								yield return null;
							}
							if (!Object.op_Implicit((Object)(object)view) || !view.IsValid())
							{
								continue;
							}
							if (!view.IsOwner())
							{
								failed = true;
								status("Could not acquire deposit — click to retry");
							}
							else
							{
								MineRock old = target.GetComponent<MineRock>();
								MineRock5 rock = target.GetComponent<MineRock5>();
								IList areas = (Object.op_Implicit((Object)(object)old) ? (OldAreas.GetValue(old) as IList) : (Object.op_Implicit((Object)(object)rock) ? (Areas.GetValue(rock) as IList) : null));
								if ((Object.op_Implicit((Object)(object)old) || Object.op_Implicit((Object)(object)rock)) && areas == null)
								{
									failed = true;
									status("Deposit is still loading — click to retry");
								}
								else
								{
									int count = areas?.Count ?? 1;
									int num;
									for (int i = 0; i < count; num = i + 1, i = num)
									{
										if (!Object.op_Implicit((Object)(object)player) || (Object)(object)player != (Object)(object)Player.m_localPlayer || ((Character)player).IsDead())
										{
											yield break;
										}
										if (!Object.op_Implicit((Object)(object)target) || !Object.op_Implicit((Object)(object)view) || !view.IsValid())
										{
											break;
										}
										if (!view.IsOwner())
										{
											failed = true;
											status("Ownership changed — click remaining deposit to retry");
											break;
										}
										Collider val = null;
										if (areas != null)
										{
											val = (Collider)(Object.op_Implicit((Object)(object)old) ? /*isinst with value type is only supported in some contexts*/: /*isinst with value type is only supported in some contexts*/);
											if (!Object.op_Implicit((Object)(object)val) || !((Component)val).gameObject.activeInHierarchy || !val.enabled)
											{
												continue;
											}
										}
										int index = i;
										Vector3 point;
										if (!Object.op_Implicit((Object)(object)val))
										{
											point = target.transform.position;
										}
										else
										{
											Bounds bounds = val.bounds;
											point = ((Bounds)(ref bounds)).center;
										}
										HitData hit = Damage(player, point, val);
										string text = null;
										try
										{
											MiningReturns.Run(player, queue, delegate
											{
												if (Object.op_Implicit((Object)(object)old))
												{
													OldHit.Invoke(old, new object[3] { 0L, hit, index });
												}
												else if (Object.op_Implicit((Object)(object)rock))
												{
													Hit.Invoke(rock, new object[3] { 0L, hit, index });
												}
												else
												{
													target.GetComponent<Destructible>().Destroy(hit);
												}
											});
										}
										catch (Exception ex)
										{
											Debug.LogError((object)("[Free Pickaxe Cam] Mining stopped: " + ex));
											text = "Mining stopped — native drops kept; see log";
										}
										if (text != null)
										{
											failed = true;
											status(text);
											break;
										}
										if ((i + 1) % 8 == 0)
										{
											status("Mining deposit… " + MiningReturns.Collected + " collected");
											yield return null;
										}
									}
									if (!failed)
									{
										continue;
									}
								}
							}
						}
					}
				}
				if (!failed)
				{
					status("Collected " + MiningReturns.Collected + " · " + MiningReturns.Overflow + " dropped beside you");
				}
				break;
			}
		}
		finally
		{
			done();
		}
	}
}
internal static class MiningPolicy
{
	internal static bool FitsWeight(float current, float maximum, float item)
	{
		if (!float.IsNaN(current) && !float.IsNaN(maximum) && !float.IsNaN(item) && !float.IsInfinity(current) && !float.IsInfinity(maximum) && !float.IsInfinity(item) && item >= 0f)
		{
			return (double)current + (double)item <= (double)maximum;
		}
		return false;
	}

	internal static bool MineralName(string name)
	{
		if (string.IsNullOrEmpty(name))
		{
			return false;
		}
		string text = name.ToLowerInvariant();
		if (!text.StartsWith("rock") && !text.StartsWith("minerock") && !text.StartsWith("copperdeposit") && !text.StartsWith("silvervein") && !text.StartsWith("tindeposit") && !text.StartsWith("obsidian") && !text.StartsWith("mudpile") && !text.StartsWith("flametal") && !text.StartsWith("giant_brain") && !text.StartsWith("giant_ribs"))
		{
			return text.StartsWith("giant_skull");
		}
		return true;
	}
}
internal static class MiningReturns
{
	private sealed class Scope
	{
		internal Player Player;

		internal Queue<GameObject> Fragments;

		internal readonly HashSet<ItemDrop> Drops = new HashSet<ItemDrop>();
	}

	[HarmonyPatch(typeof(ItemDrop), "OnCreateNew", new Type[]
	{
		typeof(ItemDrop),
		typeof(bool)
	})]
	private static class CaptureDrop
	{
		private static void Postfix(ItemDrop item)
		{
			if (current != null && Object.op_Implicit((Object)(object)item))
			{
				current.Drops.Add(item);
			}
		}
	}

	[HarmonyPatch(typeof(ZNetView), "Awake")]
	private static class CaptureFragments
	{
		private static void Postfix(ZNetView __instance)
		{
			if (current != null && Object.op_Implicit((Object)(object)__instance) && MiningOperation.IsDeposit(((Component)__instance).gameObject))
			{
				current.Fragments.Enqueue(((Component)__instance).gameObject);
			}
		}
	}

	private static Scope current;

	private static readonly MethodInfo Save = AccessTools.Method(typeof(ItemDrop), "Save", Type.EmptyTypes, (Type[])null);

	internal static int Collected;

	internal static int Overflow;

	internal static void Run(Player player, Queue<GameObject> fragments, Action native)
	{
		Scope scope = current;
		Scope scope2 = (current = new Scope
		{
			Player = player,
			Fragments = fragments
		});
		try
		{
			native();
		}
		finally
		{
			current = scope;
			Collect(scope2);
		}
	}

	private static void Collect(Scope scope)
	{
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_013a: Unknown result type (might be due to invalid IL or missing references)
		//IL_013f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: Unknown result type (might be due to invalid IL or missing references)
		//IL_018b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0166: Unknown result type (might be due to invalid IL or missing references)
		//IL_016f: Unknown result type (might be due to invalid IL or missing references)
		//IL_017b: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)scope.Player) || (Object)(object)scope.Player != (Object)(object)Player.m_localPlayer)
		{
			return;
		}
		foreach (ItemDrop drop in scope.Drops)
		{
			if (!Object.op_Implicit((Object)(object)drop))
			{
				continue;
			}
			ZNetView component = ((Component)drop).GetComponent<ZNetView>();
			if (!Object.op_Implicit((Object)(object)component) || !component.IsValid() || !component.IsOwner())
			{
				continue;
			}
			try
			{
				Inventory inventory = ((Humanoid)scope.Player).GetInventory();
				while (drop.m_itemData.m_stack > 0)
				{
					ItemData val2 = drop.m_itemData.Clone();
					val2.m_stack = 1;
					if (!MiningPolicy.FitsWeight(inventory.GetTotalWeight(), scope.Player.GetMaxCarryWeight(), val2.GetWeight(-1)) || !inventory.CanAddItem(val2, 1) || !inventory.AddItem(val2))
					{
						break;
					}
					ItemData itemData = drop.m_itemData;
					itemData.m_stack--;
					Collected++;
				}
				if (drop.m_itemData.m_stack == 0)
				{
					component.Destroy();
					continue;
				}
				Overflow += drop.m_itemData.m_stack;
				Vector3 position = ((Component)scope.Player).transform.position + Vector3.up * 0.8f;
				((Component)drop).transform.position = position;
				Rigidbody component2 = ((Component)drop).GetComponent<Rigidbody>();
				if (Object.op_Implicit((Object)(object)component2))
				{
					component2.position = position;
					component2.linearVelocity = Vector3.zero;
					component2.angularVelocity = Vector3.zero;
				}
				component.GetZDO().SetPosition(position);
				Save.Invoke(drop, null);
			}
			catch (Exception ex)
			{
				try
				{
					if (Object.op_Implicit((Object)(object)drop) && component.IsValid() && component.IsOwner())
					{
						Save.Invoke(drop, null);
					}
				}
				catch
				{
				}
				Debug.LogError((object)("[Free Pickaxe Cam] Remaining native loot retained: " + ex));
			}
		}
	}
}
internal static class PickaxeCameraRumble
{
	[HarmonyPatch(typeof(ZInput), "InternalSetGamepadRumble")]
	private static class SuppressFreeCameraRumble
	{
		private static bool Prefix()
		{
			if (Object.op_Implicit((Object)(object)PickaxeCamera.Instance))
			{
				return !PickaxeCamera.Instance.Active;
			}
			return true;
		}
	}

	private static readonly FieldRef<GameCamera, float> Shake = AccessTools.FieldRefAccess<GameCamera, float>("m_shakeIntensity");

	internal static void Stop()
	{
		if (Object.op_Implicit((Object)(object)GameCamera.instance))
		{
			Shake.Invoke(GameCamera.instance) = 0f;
		}
		ZInput.StopGamepadRumble();
	}
}
internal static class StickInput
{
	internal static Func<float> RightStickX;

	internal static Func<float> RightStickY;

	internal static Func<float> LeftStickX;

	internal static Func<float> LeftStickY;

	internal static void Initialize(Type inputType, Action<string> warning)
	{
		RightStickX = Bind(inputType, "GetJoyRightStickX", warning);
		RightStickY = Bind(inputType, "GetJoyRightStickY", warning);
		LeftStickX = Bind(inputType, "GetJoyLeftStickX", warning);
		LeftStickY = Bind(inputType, "GetJoyLeftStickY", warning);
	}

	internal static Func<float> Bind(Type type, string name, Action<string> warning)
	{
		MethodInfo method = type.GetMethod(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
		if (method != null && method.ReturnType == typeof(float))
		{
			return (Func<float>)Delegate.CreateDelegate(typeof(Func<float>), method);
		}
		method = type.GetMethod(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(bool) }, null);
		if (method != null && method.ReturnType == typeof(float))
		{
			Func<bool, float> call = (Func<bool, float>)Delegate.CreateDelegate(typeof(Func<bool, float>), method);
			ParameterInfo parameterInfo = method.GetParameters()[0];
			bool value = parameterInfo.HasDefaultValue && parameterInfo.DefaultValue is bool && (bool)parameterInfo.DefaultValue;
			return () => call(value);
		}
		MethodInfo[] methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		foreach (MethodInfo candidate in methods)
		{
			if (candidate.Name != name || candidate.ReturnType != typeof(float))
			{
				continue;
			}
			ParameterInfo[] parameters = candidate.GetParameters();
			if (parameters.Length == 0)
			{
				continue;
			}
			object[] arguments = new object[parameters.Length];
			bool flag = true;
			for (int num2 = 0; num2 < parameters.Length; num2++)
			{
				if (!parameters[num2].HasDefaultValue || parameters[num2].ParameterType.IsByRef)
				{
					flag = false;
					break;
				}
				arguments[num2] = parameters[num2].DefaultValue;
			}
			if (flag)
			{
				return () => (float)candidate.Invoke(null, arguments);
			}
		}
		warning("Free Pickaxe Cam: unsupported controller axis " + name + ". This axis is disabled; keyboard/mouse remain available.");
		return () => 0f;
	}
}