Decompiled source of ValheimBuildCamera v1.15.0

BepInEx/plugins/ValheimBuildCamera/ValheimBuildCamera.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Valheim Build Camera")]
[assembly: AssemblyFileVersion("0.1.48.0")]
[assembly: AssemblyVersion("0.1.48.0")]
namespace ValheimBuildCamera;

[BepInPlugin("valheim.buildcamera", "Valheim Build Camera", "0.1.48")]
[BepInProcess("valheim.exe")]
[DefaultExecutionOrder(1000)]
public sealed class BuildCamera : BaseUnityPlugin
{
	[HarmonyPatch(typeof(Player), "Update")]
	private static class BeforePlayerUpdate
	{
		private static void Prefix(Player __instance)
		{
			BuildCamera 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)
		{
			BuildCamera 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)
		{
			BuildCamera 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)
			BuildCamera 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)
		{
			BuildCamera instance = Instance;
			if (Object.op_Implicit((Object)(object)instance))
			{
				return !instance.ControlsOwned(__instance);
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(Player), "TakeInput")]
	private static class ProtectToggleAndDialogs
	{
		[ThreadStatic]
		private static bool _insideTakeInputPostfix;

		private static void EvaluateInput(Player __instance, ref bool __result)
		{
			BuildCamera instance = Instance;
			if (Object.op_Implicit((Object)(object)instance) && instance.HooksEnabled && instance.IsLocal(__instance) && (instance._chordHeld || Time.unscaledTime < instance._suppressUntil || (instance._active && (instance.GridCapturing || UnifiedPopup.IsVisible() || IsGamePausedSafe()))))
			{
				__result = false;
			}
		}

		private static void Postfix(Player __instance, ref bool __result)
		{
			if (_insideTakeInputPostfix)
			{
				return;
			}
			_insideTakeInputPostfix = true;
			try
			{
				EvaluateInput(__instance, ref __result);
			}
			finally
			{
				_insideTakeInputPostfix = false;
			}
		}
	}

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

	[HarmonyPatch(typeof(Player), "CheckPlacementGhostVSPlayers")]
	private static class PlacementCollisionScope
	{
		private static void Prefix(Player __instance, out bool __state)
		{
			BuildCamera instance = Instance;
			__state = Object.op_Implicit((Object)(object)instance) && instance.Active && instance.IsLocal(__instance);
			if (__state)
			{
				CollisionQueries++;
			}
		}

		private static Exception Finalizer(Exception __exception, bool __state)
		{
			if (__state)
			{
				CollisionQueries = Math.Max(0, CollisionQueries - 1);
			}
			return __exception;
		}
	}

	[HarmonyPatch(typeof(Player), "PieceRayTest")]
	private static class ExtendFreeCameraPlacementRay
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			return RewriteGridAimRay(RewriteBuildRay(instructions));
		}
	}

	[HarmonyPatch(typeof(Player), "CopyPiece")]
	private static class ExtendFreeCameraCopyRay
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			return RewriteBuildRay(instructions);
		}
	}

	[HarmonyPatch(typeof(Player), "RemovePiece")]
	private static class ExtendFreeCameraRemoveRay
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			return RewriteBuildRay(instructions);
		}
	}

	[HarmonyPatch(typeof(Player), "UpdateWearNTearHover")]
	private static class ExtendFreeCameraRepairRay
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			return RewriteBuildRay(instructions);
		}
	}

	[HarmonyPatch(typeof(Character), "GetCharactersInRange")]
	private static class PreservePlacementCollisionCoverage
	{
		private static void Prefix(ref float radius)
		{
			BuildCamera instance = Instance;
			if (CollisionQueries > 0 && Object.op_Implicit((Object)(object)instance) && instance.Active)
			{
				radius = Mathf.Max(radius, Mathf.Max(60f, instance._appliedReach + 30f));
			}
		}
	}

	private struct GridMesh
	{
		internal Mesh Mesh;

		internal Matrix4x4 Local;

		internal MeshRenderer Renderer;

		internal List<Material> Materials;

		internal MaterialPropertyBlock Properties;
	}

	[HarmonyPatch(typeof(Player), "UpdatePlacement")]
	private static class GridNativeAction
	{
		private static bool Prefix(Player __instance)
		{
			BuildCamera instance = Instance;
			if (Object.op_Implicit((Object)(object)instance) && instance.Active && instance.IsLocal(__instance) && !instance._gridExecuting)
			{
				if (!instance.GridCapturing)
				{
					return !instance.GridBusy;
				}
				return false;
			}
			return true;
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			foreach (CodeInstruction instruction in instructions)
			{
				MethodInfo methodInfo = instruction.operand as MethodInfo;
				if (methodInfo != null && methodInfo.DeclaringType == typeof(ZInput))
				{
					string text = ((methodInfo.Name == "GetButtonDown") ? "GridButtonDown" : ((methodInfo.Name == "GetButton") ? "GridButton" : ((methodInfo.Name == "GetButtonUp") ? "GridButtonUp" : ((methodInfo.Name == "GetMouseScrollWheel") ? "GridScroll" : null))));
					if (text != null)
					{
						instruction.operand = typeof(BuildCamera).GetMethod(text, BindingFlags.Static | BindingFlags.NonPublic);
					}
				}
				yield return instruction;
			}
		}
	}

	[HarmonyPatch(typeof(Player), "UpdateBuildGuiInput")]
	private static class GridKeepSelection
	{
		private static bool Prefix(Player __instance)
		{
			BuildCamera instance = Instance;
			if (Object.op_Implicit((Object)(object)instance) && instance.IsLocal(__instance))
			{
				return !instance._gridExecuting;
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(Player), "TryPlacePiece")]
	private static class GridStartInsteadOfSingle
	{
		private static bool Prefix(Player __instance, Piece __0, ref bool __result)
		{
			BuildCamera instance = Instance;
			if (!Object.op_Implicit((Object)(object)instance) || !instance.Active || !instance.IsLocal(__instance) || !instance._gridEnabled || instance._gridExecuting)
			{
				return true;
			}
			instance.BeginGrid(__0);
			__result = false;
			return false;
		}

		private static void Postfix(Player __instance, bool __result)
		{
			BuildCamera instance = Instance;
			if (Object.op_Implicit((Object)(object)instance) && instance._gridExecuting && instance.IsLocal(__instance))
			{
				instance._gridPlaced = __result;
			}
		}
	}

	[HarmonyPatch(typeof(Player), "PieceRayTest")]
	private static class GridTargetRay
	{
		private static bool Prefix(Player __instance, ref Vector3 __0, ref Vector3 __1, ref Piece __2, ref Heightmap __3, ref Collider __4, ref bool __result)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: 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_0063: 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_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: 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_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: 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)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			BuildCamera instance = Instance;
			if (!Object.op_Implicit((Object)(object)instance) || !instance._gridExecuting || !instance.IsLocal(__instance))
			{
				return true;
			}
			__0 = instance._gridTarget;
			__1 = instance._gridNormal;
			__2 = null;
			__3 = null;
			__4 = null;
			Vector3 val = ((((Vector3)(ref instance._gridNormal)).sqrMagnitude > 0.5f) ? instance._gridNormal : Vector3.up);
			int mask = LayerMask.GetMask(new string[5] { "terrain", "piece", "Default", "static_solid", "Default_small" });
			float num = Mathf.Max(0.25f, Mathf.Max(instance._gridStepX, Mathf.Max(instance._gridStepY, instance._gridStepZ)) * 0.55f);
			RaycastHit val2 = default(RaycastHit);
			if (Physics.Raycast(instance._gridTarget + val * num, -val, ref val2, num * 2f, mask, (QueryTriggerInteraction)1))
			{
				__1 = ((RaycastHit)(ref val2)).normal;
				__2 = ((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent<Piece>();
				__3 = ((Component)((RaycastHit)(ref val2)).collider).GetComponent<Heightmap>();
			}
			if (Physics.Raycast(instance._gridTarget + Vector3.up * 0.1f, Vector3.down, ref val2, 0.2f, LayerMask.GetMask(new string[1] { "Water" }), (QueryTriggerInteraction)2))
			{
				__4 = ((RaycastHit)(ref val2)).collider;
			}
			__result = instance.GridInRange(instance._gridTarget, instance._gridPiece);
			return false;
		}

		private static void Postfix(Player __instance, Vector3 __1, bool __result)
		{
			//IL_003d: 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)
			BuildCamera instance = Instance;
			if (Object.op_Implicit((Object)(object)instance) && instance.Active && instance._gridEnabled && !instance._gridExecuting && !instance.GridBusy && instance.IsLocal(__instance) && __result)
			{
				instance._gridNormal = __1;
			}
		}
	}

	[HarmonyPatch(typeof(Player), "UpdatePlacementGhost")]
	private static class GridExactGhost
	{
		private static void Prefix(Player __instance, out int __state)
		{
			//IL_004b: 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)
			BuildCamera instance = Instance;
			__state = -1;
			if (Object.op_Implicit((Object)(object)instance))
			{
				instance.BeginGridAimScope(__instance, out __state);
			}
			if (Object.op_Implicit((Object)(object)instance) && instance._gridExecuting && instance.IsLocal(__instance) && Object.op_Implicit((Object)(object)instance._gridGhost))
			{
				instance._gridGhost.transform.SetPositionAndRotation(instance._gridTarget, instance._gridRotation);
			}
		}

		private static void Finalizer(int __state)
		{
			BuildCamera instance = Instance;
			if (Object.op_Implicit((Object)(object)instance))
			{
				instance.EndGridAimScope(__state);
			}
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			int positions = 0;
			int rotations = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				MethodInfo methodInfo = instruction.operand as MethodInfo;
				if (methodInfo != null && methodInfo.DeclaringType == typeof(Transform) && (methodInfo.Name == "set_position" || methodInfo.Name == "set_rotation"))
				{
					bool flag = methodInfo.Name == "set_position";
					instruction.opcode = OpCodes.Call;
					instruction.operand = typeof(BuildCamera).GetMethod(flag ? "GridGhostPosition" : "GridGhostRotation", BindingFlags.Static | BindingFlags.NonPublic);
					if (flag)
					{
						int num = positions + 1;
						positions = num;
					}
					else
					{
						int num = rotations + 1;
						rotations = num;
					}
				}
				yield return instruction;
			}
			if (positions < 2 || rotations < 2)
			{
				throw new InvalidOperationException("Unsupported grid ghost positioning layout.");
			}
		}
	}

	[HarmonyPatch(typeof(GameCamera), "UpdateMouseCapture")]
	private static class GridMenuCursor
	{
		private static void Postfix()
		{
			BuildCamera instance = Instance;
			if (Object.op_Implicit((Object)(object)instance) && instance.Active && instance._gridMenu)
			{
				instance.GridCursor();
			}
		}
	}

	[HarmonyPatch(typeof(InventoryGui), "Show", new Type[]
	{
		typeof(Container),
		typeof(int)
	})]
	private static class GridMenuInventoryGuard
	{
		private static bool Prefix()
		{
			BuildCamera instance = Instance;
			if (Object.op_Implicit((Object)(object)instance) && instance.Active)
			{
				return !instance.GridCapturing;
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(Menu), "Update")]
	private static class GridMenuEscapeGuard
	{
		private static bool Prefix()
		{
			BuildCamera instance = Instance;
			if (Object.op_Implicit((Object)(object)instance) && instance.Active && !Menu.IsVisible())
			{
				return !instance.GridCapturing;
			}
			return true;
		}
	}

	public const string PluginId = "valheim.buildcamera";

	public const string PluginVersion = "0.1.48";

	internal static BuildCamera Instance;

	internal static int CollisionQueries;

	private ConfigEntry<bool> _dismantleWarning;

	private DismantlePreview _dismantlePreview;

	private ConfigEntry<bool> _placementWarning;

	private float _nextCircletCheck;

	private bool _previewFailed;

	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;

	private ConfigEntry<KeyboardShortcut> _gridKey;

	private bool _gridEnabled;

	private bool _gridMenu;

	private bool _gridExecuting;

	private bool _gridPlaced;

	private int _gridWidth = 1;

	private int _gridHeight = 1;

	private int _gridInputFrame = -1;

	private int _gridNext;

	private int _gridTotal;

	private int _gridBuilt;

	private float _gridNextTime;

	private Piece _gridPiece;

	private Piece _gridPreviewPiece;

	private ItemData _gridTool;

	private Vector3 _gridOrigin;

	private Vector3 _gridTarget;

	private Vector3 _gridNormal = Vector3.up;

	private Quaternion _gridRotation;

	private float _gridStepX;

	private float _gridStepY;

	private float _gridStepZ;

	private int _gridLayoutMode;

	private int _gridWidthSign = 1;

	private Piece _gridLayoutPiece;

	private GridBasis _gridAutoBasis;

	private GridBasis _gridBasis;

	private Vector3 _gridAcross;

	private Vector3 _gridAlong;

	private Vector3 _gridQueueAcross;

	private Vector3 _gridQueueAlong;

	private readonly List<GridVector> _gridSnapGeometry = new List<GridVector>();

	private int _gridQueueWidth;

	private GameObject _gridGhost;

	private string _gridStatus = "Choose a building piece, then aim to preview.";

	private float _gridStatusUntil;

	private Material _gridMaterial;

	private readonly GridMenuInput _gridInput = new GridMenuInput();

	private readonly GridMenuInput _gridKeyboardInput = new GridMenuInput();

	private float _gridCaptureUntil;

	private bool _gridSuppressRemoveRelease;

	private CursorLockMode _gridSavedLock;

	private bool _gridSavedCursor;

	private readonly List<Transform> _gridSnapPoints = new List<Transform>();

	private readonly List<GridMesh> _gridMeshes = new List<GridMesh>();

	private readonly Collider[] _gridDuplicateHits = (Collider[])(object)new Collider[128];

	private static readonly FieldInfo GridGhostField = AccessTools.Field(typeof(Player), "m_placementGhost");

	private static readonly FieldInfo GridStatusField = AccessTools.Field(typeof(Player), "m_placementStatus");

	private static readonly FieldInfo GridLastUseField = AccessTools.Field(typeof(Player), "m_lastToolUseTime");

	private static readonly FieldInfo GridPressedField = AccessTools.Field(typeof(Player), "m_placePressedTime");

	private static readonly FieldInfo GridBlockRemoveField = AccessTools.Field(typeof(Player), "m_blockRemove");

	private static readonly FieldInfo GridRemovePressedField = AccessTools.Field(typeof(Player), "m_removePressedTime");

	private static readonly Action<Player, bool> GridUpdateGhost = AccessTools.MethodDelegate<Action<Player, bool>>(AccessTools.Method(typeof(Player), "UpdatePlacementGhost", new Type[1] { typeof(bool) }, (Type[])null), (object)null, true);

	private static readonly Action<Player, bool, float> GridUpdatePlacement = AccessTools.MethodDelegate<Action<Player, bool, float>>(AccessTools.Method(typeof(Player), "UpdatePlacement", new Type[2]
	{
		typeof(bool),
		typeof(float)
	}, (Type[])null), (object)null, true);

	private GameObject _gridCanvas;

	private GameObject _gridPanel;

	private GameObject _gridHint;

	private Canvas _gridUICanvas;

	private GameObject _gridPreviousSelection;

	private TMP_Text _gridWidthText;

	private TMP_Text _gridHeightText;

	private TMP_Text _gridHeightLabel;

	private TMP_Text _gridPanelStatus;

	private TMP_Text _gridHintTitle;

	private TMP_Text _gridHintText;

	private TMP_Text _gridHintStatus;

	private Button _gridAuto;

	private Button _gridWall;

	private Button _gridFloor;

	private readonly List<Button> _gridAdjustButtons = new List<Button>();

	private TMP_Text _gridFontTemplate;

	private Button _gridButtonTemplate;

	private HotkeyBar[] _gridToolbars;

	private Hud _gridHud;

	private float _gridToolbarScanAt;

	private float _gridHintUntil;

	private readonly Vector3[] _gridCorners = (Vector3[])(object)new Vector3[4];

	private readonly List<GridHudLayout.Box> _gridToolbarBounds = new List<GridHudLayout.Box>();

	private static readonly Color GridGold = new Color(0.89f, 0.77f, 0.53f);

	private static readonly Color GridInk = new Color(0.95f, 0.93f, 0.86f);

	private const float GridPanelWidth = 360f;

	private Quaternion _gridViewAdjustment = Quaternion.identity;

	private GridFocusMotion _gridFocusYaw;

	private GridFocusMotion _gridFocusPitch;

	private int _gridAimDepth;

	private int _gridFocusFrame = -1;

	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.FreeCameraRange(_radius.Value, 8f, _rangeMultiplier.Value);

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

	private bool GridBusy
	{
		get
		{
			if (Object.op_Implicit((Object)(object)_gridPiece))
			{
				return _gridNext < _gridTotal;
			}
			return false;
		}
	}

	private bool GridCapturing
	{
		get
		{
			if (!_gridMenu && _gridInputFrame != Time.frameCount && !(Time.unscaledTime < _gridCaptureUntil) && !GridChordHeld())
			{
				return false;
			}
			return true;
		}
	}

	private Quaternion GridViewRotation => _rotation;

	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_02e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ea: Expected O, but got Unknown
		if (Application.isBatchMode)
		{
			return;
		}
		Instance = this;
		_enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable the build camera on this client.");
		_toggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "ToggleKey", new KeyboardShortcut((KeyCode)287, Array.Empty<KeyCode>()), "Enter/leave build camera with a hammer or another building tool equipped.");
		_resetKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "ResetViewKey", new KeyboardShortcut((KeyCode)288, Array.Empty<KeyCode>()), "Reset the active camera to its initial angled view.");
		_reportKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "ReloadAndReportKey", new KeyboardShortcut((KeyCode)291, 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 building tool 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, "Small top-centre reminder while the build 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.");
		_placementWarning = ((BaseUnityPlugin)this).Config.Bind<bool>("Safety", "PlacementSupportPreview", true, "Show a small support estimate for the placement ghost while build camera is active.");
		_dismantleWarning = ((BaseUnityPlugin)this).Config.Bind<bool>("Safety", "DismantleCollapsePreview", true, "While build camera is active, aim at a removable piece to preview additional support collapses. Orange target, red affected pieces, estimated count. Read-only and bounded; unsupported or oversized scans show unavailable. Set false to disable.");
		_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. Default 25 x 8 = 200 metres around the stationary body.");
		_reach = FloatSetting("Building", "BuildReach", 25f, 5f, 25f, "Base reach from your character's eyes, multiplied by FreeCameraRangeMultiplier only while free camera is active. Default 25 x 8 = 200 metres. Normal player reach is restored on exit; native building rules still apply.");
		_rangeMultiplier = FloatSetting("Camera", "FreeCameraRangeMultiplier", 8f, 1f, 8f, "Multiply both base camera radius and active build reach, from 1 to 8. Default 8 gives a 200 metre radius with the default 25 metre base. Does not affect normal player building reach. World streaming distances are unchanged.");
		UpgradeTo200mRange();
		_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 keeps rotating pieces.");
		try
		{
			StickInput.Initialize(typeof(ZInput), delegate(string message)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)message);
			});
			ValidateHooks();
			ConfigureGrid();
			ClearBuildingView.Initialize((BaseUnityPlugin)(object)this);
			_harmony = new Harmony("valheim.buildcamera");
			Harmony harmony = _harmony;
			Assembly assembly = typeof(BuildCamera).Assembly;
			OcdCompatibility.Initialize((BaseUnityPlugin)(object)this, OcdBatchOwnsPlacement, OcdCancelBatch);
			harmony.PatchAll(assembly);
			_ready = true;
			RefreshIndicatorText();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Build Camera 0.1.48 loaded. F6 toggle; F7 reset; F10 report/reload.");
		}
		catch (Exception ex)
		{
			_ready = false;
			_failed = true;
			if (_harmony != null)
			{
				_harmony.UnpatchSelf();
			}
			((BaseUnityPlugin)this).Logger.LogError((object)("Build Camera 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_027f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0284: 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("F10 before reload");
					StopCamera("Configuration reload", message: false);
					ResetInput();
					((BaseUnityPlugin)this).Config.Reload();
					RefreshIndicatorText();
					_failed = false;
					Notify("Build 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();
			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();
				TickGridInput(flag2);
				if (_gridMenu)
				{
					ApplyPose();
					return;
				}
				if (_gridInputFrame == Time.frameCount)
				{
					ApplyPose();
					return;
				}
				if (ZInput.GetKeyDown((KeyCode)27, true))
				{
					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)
				{
					TickGridQueue();
				}
			}
		}
		catch (Exception error)
		{
			Fail(error);
		}
	}

	private void LateUpdate()
	{
		if (!_active)
		{
			return;
		}
		try
		{
			BuildCameraRumble.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;
			}
			UpdateDismantlePreview();
			UpdateGridPreview();
			UpdateGridCamera();
			ApplyPose();
			DrawGridPreview();
			UpdateGridUI();
			if (!_hidePlayer.Value)
			{
				RestoreRenderers();
			}
			else if (_hidePlayer.Value && Time.unscaledTime >= _nextRendererScan)
			{
				HideRenderers();
				_nextRendererScan = Time.unscaledTime + 0.25f;
			}
		}
		catch (Exception error)
		{
			Fail(error);
		}
	}

	private void UpdateDismantlePreview()
	{
		if (_previewFailed)
		{
			return;
		}
		if (_gridEnabled || _gridMenu || (!_dismantleWarning.Value && !_placementWarning.Value) || MenuBlocksCamera() || !Application.isFocused)
		{
			if (_dismantlePreview != null)
			{
				_dismantlePreview.Clear();
				_dismantlePreview.TickPlacement(_player, enabled: false);
			}
			return;
		}
		try
		{
			if (_dismantlePreview == null)
			{
				_dismantlePreview = new DismantlePreview();
			}
			if (_dismantleWarning.Value)
			{
				_dismantlePreview.Tick(_player, _camera, PlacementRayDistance(_player));
			}
			else
			{
				_dismantlePreview.Clear();
			}
			_dismantlePreview.TickPlacement(_player, _placementWarning.Value);
		}
		catch (Exception ex)
		{
			_previewFailed = true;
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Dismantle preview unavailable; camera remains active. " + ex));
		}
	}

	private void OnRenderObject()
	{
		if (Active && !MenuBlocksCamera() && _dismantlePreview != null)
		{
			_dismantlePreview.DrawWorld(_camera);
		}
	}

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

	private static bool IsBuildTool(ItemData item)
	{
		if (item != null && item.m_shared != null)
		{
			return (Object)(object)item.m_shared.m_buildPieces != (Object)null;
		}
		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_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_00ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0102: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		//IL_019d: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)local) || !HasBuildingTool(local))
		{
			Notify("Equip your hammer or another building tool 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 build camera.");
			return;
		}
		if (!Object.op_Implicit((Object)(object)GameCamera.instance) || GameCamera.InFreeFly())
		{
			Notify("Return to the normal game 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;
		ResetGrid();
		_active = true;
		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("Build 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 (((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_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_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: 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_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: 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_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ef: 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)
		ResetGridCamera();
		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_011e: Unknown result type (might be due to invalid IL or missing references)
		//IL_013b: 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_01c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: 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_00e3: 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_0383: Unknown result type (might be due to invalid IL or missing references)
		//IL_038e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0395: Unknown result type (might be due to invalid IL or missing references)
		//IL_039b: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a5: 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() && !ZInput.GetButton("JoyRotate") && !ZInput.GetButton("JoyRotateRight"))
		{
			float x = StickInput.RightStickX();
			float y = 0f - StickInput.RightStickY();
			if (_gridEnabled)
			{
				CameraMath.PrecisionStick(ref x, ref y);
			}
			val = new Vector2(x, y) * (_gridEnabled ? 88f : 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);
		bool flag = _gridEnabled && ZInput.IsGamepadActive();
		float x2 = StickInput.LeftStickX();
		float y2 = 0f - StickInput.LeftStickY();
		if (flag)
		{
			CameraMath.PrecisionStick(ref x2, ref y2);
		}
		float x3 = (ZInput.GetButton("Right") ? 1f : 0f) - (ZInput.GetButton("Left") ? 1f : 0f) + x2;
		float z = (ZInput.GetButton("Forward") ? 1f : 0f) - (ZInput.GetButton("Backward") ? 1f : 0f) + y2;
		float y3 = ((ZInput.GetButton("Jump") || ZInput.GetButton("JoyJump")) ? 1f : 0f) - ((ZInput.GetButton("Crouch") || ZInput.GetButton("JoyCrouch")) ? 1f : 0f);
		CameraMath.NormalizeInput(ref x3, ref y3, 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 (x3 != 0f || y3 != 0f || z != 0f)
		{
			MovementVector movementVector = CameraMath.ViewRelativeMovement(_yaw, flag ? 0f : _pitch, x3, y3, z);
			float x4 = movementVector.X;
			float y4 = movementVector.Y;
			float z2 = movementVector.Z;
			CameraMath.NormalizeInput(ref x4, ref y4, ref z2);
			_position += new Vector3(x4, y4, 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_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: 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;
		}
		BuildCameraRumble.Stop();
		Transform transform = ((Component)_gameCamera).transform;
		Quaternion gridViewRotation = GridViewRotation;
		Vector3 position = transform.position;
		if (((Vector3)(ref position)).Equals(_position))
		{
			Quaternion rotation = transform.rotation;
			if (((Quaternion)(ref rotation)).Equals(gridViewRotation))
			{
				goto IL_006f;
			}
		}
		transform.SetPositionAndRotation(_position, gridViewRotation);
		goto IL_006f;
		IL_006f:
		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_019e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
		ClearBuildingView.Stop();
		ResetGrid();
		_nextCircletCheck = 0f;
		if (_dismantlePreview != null)
		{
			_dismantlePreview.Dispose();
			_dismantlePreview = null;
		}
		if (_active)
		{
			BuildCameraRumble.Stop();
		}
		CircletCameraLight.Stop();
		_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("Build camera OFF: " + reason + ".");
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Build Camera 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)("Build Camera 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_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Invalid comparison between Unknown and I4
		ClearBuildingView.Draw(Active, MenuBlocksCamera());
		if (Active && !MenuBlocksCamera() && (int)Event.current.type == 7 && !_gridEnabled && !_gridMenu && _dismantlePreview != null)
		{
			_dismantlePreview.DrawUI(_camera);
		}
	}

	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 = "BUILD CAMERA  |  " + ((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)
	{
		ClearBuildingView.FocusChanged(focused);
		if (!focused)
		{
			ResetInput();
		}
	}

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

	private void OnDestroy()
	{
		OcdCompatibility.Shutdown();
		ClearBuildingView.Shutdown();
		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("Valheim Build Camera 0.1.48 - 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 + "; collision query depth=" + CollisionQueries);
			}
			stringBuilder.AppendLine("No debug fly, god mode, no-cost mode, workbench bypass, ward bypass or network hooks installed.");
			File.WriteAllText(Path.Combine(Paths.ConfigPath, "valheim.buildcamera.diagnostics.txt"), stringBuilder.ToString());
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not write build camera diagnostics: " + ex.Message));
		}
	}

	private static void ValidateHooks()
	{
		Require(typeof(Player), "Update", Type.EmptyTypes);
		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), "CheckPlacementGhostVSPlayers", Type.EmptyTypes);
		Require(typeof(Player), "PieceRayTest", new Type[6]
		{
			typeof(Vector3).MakeByRefType(),
			typeof(Vector3).MakeByRefType(),
			typeof(Piece).MakeByRefType(),
			typeof(Heightmap).MakeByRefType(),
			typeof(Collider).MakeByRefType(),
			typeof(bool)
		});
		Require(typeof(Player), "CopyPiece", Type.EmptyTypes);
		Require(typeof(Player), "RemovePiece", Type.EmptyTypes);
		Require(typeof(Player), "UpdateWearNTearHover", Type.EmptyTypes);
		Require(typeof(Character), "GetCharactersInRange", new Type[3]
		{
			typeof(Vector3),
			typeof(float),
			typeof(List<Character>)
		});
	}

	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 static float PlacementRayDistance(Player player)
	{
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		BuildCamera instance = Instance;
		if (!Object.op_Implicit((Object)(object)instance) || !instance.Active || !instance.IsLocal(player))
		{
			return 50f;
		}
		Piece selectedPiece = player.GetSelectedPiece();
		return CameraMath.BuildRayDistance(Vector3.Distance(instance._position, ((Character)player).m_eye.position), instance._appliedReach, Object.op_Implicit((Object)(object)selectedPiece) ? ((float)selectedPiece.m_extraPlacementDistance) : 0f);
	}

	private static IEnumerable<CodeInstruction> RewriteBuildRay(IEnumerable<CodeInstruction> instructions)
	{
		MethodInfo raycast = AccessTools.DeclaredMethod(typeof(Physics), "Raycast", new Type[5]
		{
			typeof(Vector3),
			typeof(Vector3),
			typeof(RaycastHit).MakeByRefType(),
			typeof(float),
			typeof(int)
		}, (Type[])null);
		return PlacementRayPatch.Rewrite(instructions, raycast, AccessTools.DeclaredMethod(typeof(BuildCamera), "PlacementRayDistance", (Type[])null, (Type[])null));
	}

	private static Vector3 GridPlacementForward(Transform target)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		return target.forward;
	}

	private static IEnumerable<CodeInstruction> RewriteGridAimRay(IEnumerable<CodeInstruction> instructions)
	{
		MethodInfo forward = typeof(Transform).GetProperty("forward", BindingFlags.Instance | BindingFlags.Public).GetGetMethod();
		MethodInfo replacement = typeof(BuildCamera).GetMethod("GridPlacementForward", BindingFlags.Static | BindingFlags.NonPublic);
		foreach (CodeInstruction instruction in instructions)
		{
			if (instruction.operand is MethodInfo methodInfo && methodInfo == forward)
			{
				instruction.opcode = OpCodes.Call;
				instruction.operand = replacement;
			}
			yield return instruction;
		}
	}

	private void ConfigureGrid()
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		_gridKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "GridOptionsKey", new KeyboardShortcut((KeyCode)290, Array.Empty<KeyCode>()), "Toggle live multi-build in the build camera. F9 / LB+Y: on/off. D-pad: width/height. LB+Up/Down: layout. Shift+F9: layout. Arrow keys: resize. Starts in single-piece mode.");
		if (GridGhostField == null || GridStatusField == null || GridLastUseField == null || GridPressedField == null || GridBlockRemoveField == null || GridRemovePressedField == null)
		{
			throw new MissingFieldException("Native grid placement fields are unavailable.");
		}
	}

	private static bool GridChordHeld()
	{
		Gamepad current = Gamepad.current;
		if (ZInput.GetButton("JoyLBumper") || (current != null && current.leftShoulder.isPressed))
		{
			if (!ZInput.GetButton("JoyButtonY"))
			{
				if (current != null)
				{
					return current.buttonNorth.isPressed;
				}
				return false;
			}
			return true;
		}
		return false;
	}

	private void SetGridMenu(bool open)
	{
		_gridMenu = false;
	}

	private void GridCursor()
	{
		if (_gridMenu)
		{
			ZCursor.LockState = (CursorLockMode)0;
			if (ZInput.IsGamepadActive())
			{
				ZCursor.Hide();
			}
			else
			{
				ZCursor.Show();
			}
		}
	}

	private void ConsumeGridShortcut()
	{
		if (Object.op_Implicit((Object)(object)_player))
		{
			GridBlockRemoveField.SetValue(_player, true);
			GridRemovePressedField.SetValue(_player, -9999f);
			GridPressedField.SetValue(_player, -9999f);
			_gridCaptureUntil = Time.unscaledTime + 0.2f;
			Gamepad current = Gamepad.current;
			_gridSuppressRemoveRelease |= ZInput.GetButton("JoyLBumper") || (current != null && current.leftShoulder.isPressed);
		}
	}

	private void SetGridEnabled(bool enabled)
	{
		GridPreviewMaterials.Clear();
		if (!enabled && _gridEnabled)
		{
			LeaveGridCamera();
		}
		SetGridMenu(open: false);
		if (GridBusy)
		{
			CancelGrid("Stopped. Placed pieces remain.");
		}
		_gridEnabled = enabled;
		if (enabled)
		{
			_gridWidth = (_gridHeight = 1);
			_gridStatusUntil = 0f;
			_gridPreviewPiece = null;
			UpdateGridPreview();
		}
		else
		{
			_gridHintUntil = Time.unscaledTime + 5f;
		}
		ConsumeGridShortcut();
		_gridInputFrame = Time.frameCount;
	}

	private void ResetGrid()
	{
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		ResetGridCamera();
		SetGridMenu(open: false);
		DestroyGridUI();
		_gridInput.Reset();
		_gridKeyboardInput.Reset();
		_gridCaptureUntil = 0f;
		_gridSuppressRemoveRelease = false;
		_gridEnabled = false;
		_gridExecuting = false;
		_gridNormal = Vector3.up;
		_gridWidth = (_gridHeight = 1);
		_gridLayoutMode = 0;
		_gridLayoutPiece = null;
		_gridWidthSign = 1;
		_gridHintUntil = Time.unscaledTime + 7f;
		_gridPiece = null;
		_gridTool = null;
		_gridPreviewPiece = null;
		_gridGhost = null;
		_gridNext = (_gridTotal = (_gridBuilt = 0));
		_gridMeshes.Clear();
		GridPreviewMaterials.Clear();
		_gridSnapPoints.Clear();
		if (Object.op_Implicit((Object)(object)_gridMaterial))
		{
			Object.Destroy((Object)(object)_gridMaterial);
		}
		_gridMaterial = null;
	}

	private void CancelGrid(string message)
	{
		_gridPiece = null;
		_gridTool = null;
		_gridTotal = 0;
		_gridStatus = message;
		_gridStatusUntil = Time.unscaledTime + 4f;
		GridPressedField.SetValue(_player, -9999f);
	}

	private void TickGridInput(bool modal)
	{
		//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d2: 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_01e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_0202: Unknown result type (might be due to invalid IL or missing references)
		//IL_0207: Unknown result type (might be due to invalid IL or missing references)
		//IL_020b: Unknown result type (might be due to invalid IL or missing references)
		OcdCompatibility.Ensure();
		ClearBuildingView.Tick(Active, modal);
		Gamepad current = Gamepad.current;
		GridMenuInput.State state = GridMenuInput.Sample((Func<string, bool>)ZInput.GetButton, current != null && current.leftShoulder.isPressed, current != null && current.buttonNorth.isPressed, current != null && current.buttonSouth.isPressed, current != null && current.buttonEast.isPressed, current != null && current.dpad.left.isPressed, current != null && current.dpad.right.isPressed, current != null && current.dpad.up.isPressed, current != null && current.dpad.down.isPressed, 0f, 0f, current != null && current.buttonWest.isPressed);
		GridMenuInput.Actions input = _gridInput.Poll(state, Time.unscaledTime);
		if (_gridSuppressRemoveRelease)
		{
			GridBlockRemoveField.SetValue(_player, true);
			GridRemovePressedField.SetValue(_player, -9999f);
			if (!state.Modifier)
			{
				_gridSuppressRemoveRelease = false;
				_gridCaptureUntil = Time.unscaledTime + 0.2f;
			}
		}
		GridMenuInput.Actions input2 = _gridKeyboardInput.Poll(new GridMenuInput.State
		{
			Left = ZInput.GetKey((KeyCode)276, true),
			Right = ZInput.GetKey((KeyCode)275, true),
			Up = ZInput.GetKey((KeyCode)273, true),
			Down = ZInput.GetKey((KeyCode)274, true)
		}, Time.unscaledTime);
		if (modal || !Application.isFocused)
		{
			if (_gridMenu)
			{
				SetGridMenu(open: false);
			}
			return;
		}
		KeyboardShortcut value = _gridKey.Value;
		bool flag = ZInput.GetKeyDown(((KeyboardShortcut)(ref value)).MainKey, true);
		value = _gridKey.Value;
		foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers)
		{
			flag &= ZInput.GetKey(modifier, true);
		}
		bool flag2 = ZInput.GetKey((KeyCode)304, true) || ZInput.GetKey((KeyCode)303, true);
		if (flag && flag2 && _gridEnabled)
		{
			AdjustGridRow(2, 1);
			return;
		}
		if (flag || input.Toggle)
		{
			SetGridEnabled(!_gridEnabled);
			return;
		}
		if (_gridEnabled && state.Modifier && (state.Up || state.Down))
		{
			ConsumeGridShortcut();
		}
		if (_gridMenu)
		{
			GridCursor();
			if (ZInput.GetKeyDown((KeyCode)27, true))
			{
				SetGridMenu(open: false);
				return;
			}
			if (state.Modifier || state.Accept || state.Back || state.Single || state.Left || state.Right || state.Up || state.Down || StickMoved(StickInput.LeftStickX) || StickMoved(StickInput.LeftStickY) || StickMoved(StickInput.RightStickX) || StickMoved(StickInput.RightStickY))
			{
				SetGridMenu(open: false);
			}
		}
		if (_gridEnabled && !GridBusy)
		{
			GridMenuInput.Resize(input, busy: false, ref _gridWidth, ref _gridHeight, ref _gridLayoutMode);
			GridMenuInput.Resize(input2, busy: false, ref _gridWidth, ref _gridHeight, ref _gridLayoutMode);
			AdjustGridRow(0, (ZInput.GetKeyDown((KeyCode)93, true) ? 1 : 0) - (ZInput.GetKeyDown((KeyCode)91, true) ? 1 : 0));
			AdjustGridRow(1, (ZInput.GetKeyDown((KeyCode)61, true) ? 1 : 0) - (ZInput.GetKeyDown((KeyCode)45, true) ? 1 : 0));
		}
	}

	private static bool StickMoved(Func<float> read)
	{
		if (read != null)
		{
			return Mathf.Abs(read()) > 0.2f;
		}
		return false;
	}

	private void AdjustGridRow(int row, int step)
	{
		if (!GridBusy)
		{
			if (row == 0)
			{
				_gridWidth = GridLayout.ClampCount(_gridWidth + step);
			}
			if (row == 1)
			{
				_gridHeight = GridLayout.ClampCount(_gridHeight + step);
			}
			if (row == 2 && step != 0)
			{
				_gridLayoutMode = (_gridLayoutMode + Math.Sign(step) + 3) % 3;
			}
		}
	}

	private void SetGridPlane(int mode)
	{
		if (!GridBusy)
		{
			_gridLayoutMode = Math.Max(0, Math.Min(2, mode));
		}
	}

	private void UpdateGridBasis()
	{
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: 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_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e3: 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_00ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0118: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: Unknown result type (might be due to invalid IL or missing references)
		//IL_0129: Unknown result type (might be due to invalid IL or missing references)
		_gridBasis = ((_gridLayoutMode == 1) ? GridOrientation.Wall(_gridStepX, _gridStepY, _gridStepZ) : ((_gridLayoutMode == 2) ? GridOrientation.Ground(_gridStepX, _gridStepZ) : _gridAutoBasis));
		_gridAcross = new Vector3(_gridBasis.Across.X, _gridBasis.Across.Y, _gridBasis.Across.Z);
		_gridAlong = new Vector3(_gridBasis.Along.X, _gridBasis.Along.Y, _gridBasis.Along.Z);
		if (Object.op_Implicit((Object)(object)_gridGhost))
		{
			Vector3 val = _gridGhost.transform.rotation * _gridAcross;
			_gridWidthSign = GridLayout.WidthSign(Vector3.Dot(((Vector3)(ref val)).normalized, _rotation * Vector3.right), _gridWidthSign);
			_gridAcross *= (float)_gridWidthSign;
		}
	}

	private bool GridPieceAllowed(Piece piece)
	{
		if (Object.op_Implicit((Object)(object)piece) && !piece.m_repairPiece && !piece.m_removePiece && !Object.op_Implicit((Object)(object)((Component)piece).GetComponent<TerrainModifier>()) && !Object.op_Implicit((Object)(object)((Component)piece).GetComponent<TerrainOp>()))
		{
			return !Object.op_Implicit((Object)(object)((Component)piece).GetComponent<Plant>());
		}
		return false;
	}

	private void UpdateGridPreview()
	{
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		//IL_0125: Unknown result type (might be due to invalid IL or missing references)
		//IL_0328: Unknown result type (might be due to invalid IL or missing references)
		//IL_035c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0361: Unknown result type (might be due to invalid IL or missing references)
		//IL_0366: Unknown result type (might be due to invalid IL or missing references)
		//IL_0368: Unknown result type (might be due to invalid IL or missing references)
		//IL_0370: Unknown result type (might be due to invalid IL or missing references)
		//IL_0375: Unknown result type (might be due to invalid IL or missing references)
		//IL_037a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0382: Unknown result type (might be due to invalid IL or missing references)
		//IL_0389: Unknown result type (might be due to invalid IL or missing references)
		//IL_0390: Unknown result type (might be due to invalid IL or missing references)
		//IL_022a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0233: Unknown result type (might be due to invalid IL or missing references)
		//IL_0238: Unknown result type (might be due to invalid IL or missing references)
		//IL_023d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0258: Unknown result type (might be due to invalid IL or missing references)
		//IL_025a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0276: Unknown result type (might be due to invalid IL or missing references)
		//IL_0280: Expected O, but got Unknown
		//IL_0289: 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_03ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_03dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_03fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0416: Unknown result type (might be due to invalid IL or missing references)
		//IL_0422: Unknown result type (might be due to invalid IL or missing references)
		//IL_0437: Unknown result type (might be due to invalid IL or missing references)
		//IL_044f: Unknown result type (might be due to invalid IL or missing references)
		//IL_045b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0470: Unknown result type (might be due to invalid IL or missing references)
		//IL_0487: Unknown result type (might be due to invalid IL or missing references)
		//IL_0492: Unknown result type (might be due to invalid IL or missing references)
		//IL_0497: Unknown result type (might be due to invalid IL or missing references)
		//IL_049c: Unknown result type (might be due to invalid IL or missing references)
		//IL_04cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_04e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0297: Unknown result type (might be due to invalid IL or missing references)
		//IL_029e: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02de: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
		if (!_gridEnabled || MenuBlocksCamera() || !Application.isFocused)
		{
			return;
		}
		Piece selectedPiece = _player.GetSelectedPiece();
		object? value = GridGhostField.GetValue(_player);
		GameObject val = (GameObject)((value is GameObject) ? value : null);
		if (!GridPieceAllowed(selectedPiece) || !Object.op_Implicit((Object)(object)val) || !val.activeInHierarchy)
		{
			_gridPreviewPiece = null;
			_gridGhost = val;
			return;
		}
		if (GridBusy)
		{
			Vector3 val2 = GridCellPosition(_gridNext, _gridQueueWidth, _gridOrigin, _gridRotation, _gridQueueAcross, _gridQueueAlong);
			val.transform.SetPositionAndRotation(val2, _gridRotation);
		}
		if ((Object)(object)_gridPreviewPiece == (Object)(object)selectedPiece && (Object)(object)_gridGhost == (Object)(object)val)
		{
			UpdateGridBasis();
			return;
		}
		if ((Object)(object)_gridLayoutPiece != (Object)(object)selectedPiece)
		{
			_gridLayoutPiece = selectedPiece;
			_gridLayoutMode = 0;
		}
		_gridPreviewPiece = selectedPiece;
		_gridGhost = val;
		_gridMeshes.Clear();
		GridPreviewMaterials.Clear();
		_gridSnapPoints.Clear();
		Bounds val3 = default(Bounds);
		bool flag = false;
		Matrix4x4 worldToLocalMatrix = val.transform.worldToLocalMatrix;
		HashSet<Renderer> hashSet = new HashSet<Renderer>();
		LODGroup[] componentsInChildren = val.GetComponentsInChildren<LODGroup>();
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			LOD[] lODs = componentsInChildren[i].GetLODs();
			if (lODs.Length == 0)
			{
				continue;
			}
			HashSet<Renderer> hashSet2 = new HashSet<Renderer>(lODs[0].renderers);
			for (int j = 1; j < lODs.Length; j++)
			{
				Renderer[] renderers = lODs[j].renderers;
				foreach (Renderer val4 in renderers)
				{
					if (Object.op_Implicit((Object)(object)val4) && !hashSet2.Contains(val4))
					{
						hashSet.Add(val4);
					}
				}
			}
		}
		MeshFilter[] componentsInChildren2 = val.GetComponentsInChildren<MeshFilter>();
		foreach (MeshFilter val5 in componentsInChildren2)
		{
			Mesh sharedMesh = val5.sharedMesh;
			MeshRenderer component = ((Component)val5).GetComponent<MeshRenderer>();
			if (!Object.op_Implicit((Object)(object)sharedMesh) || !Object.op_Implicit((Object)(object)component) || !((Renderer)component).enabled || hashSet.Contains((Renderer)(object)component))
			{
				continue;
			}
			Matrix4x4 local = worldToLocalMatrix * ((Component)val5).transform.localToWorldMatrix;
			_gridMeshes.Add(new GridMesh
			{
				Mesh = sharedMesh,
				Local = local,
				Renderer = component,
				Materials = new List<Material>(),
				Properties = new MaterialPropertyBlock()
			});
			Bounds bounds = sharedMesh.bounds;
			for (int l = 0; l < 8; l++)
			{
				Vector3 val6 = ((Bounds)(ref bounds)).center + Vector3.Scale(((Bounds)(ref bounds)).extents, new Vector3((float)(((l & 1) != 0) ? 1 : (-1)), (float)(((l & 2) != 0) ? 1 : (-1)), (float)(((l & 4) != 0) ? 1 : (-1))));
				Vector3 val7 = ((Matrix4x4)(ref local)).MultiplyPoint3x4(val6);
				if (!flag)
				{
					((Bounds)(ref val3))..ctor(val7, Vector3.zero);
					flag = true;
				}
				else
				{
					((Bounds)(ref val3)).Encapsulate(val7);
				}
			}
		}
		selectedPiece.GetSnapPoints(_gridSnapPoints);
		Bounds val8 = default(Bounds);
		bool flag2 = false;
		_gridSnapGeometry.Clear();
		foreach (Transform gridSnapPoint in _gridSnapPoints)
		{
			Vector3 val9 = ((Component)selectedPiece).transform.InverseTransformPoint(gridSnapPoint.position);
			Vector3 val10 = Vector3.Scale(val9, val.transform.lossyScale);
			_gridSnapGeometry.Add(new GridVector(val10.x, val10.y, val10.z));
			if (!flag2)
			{
				val8 = new Bounds(val9, Vector3.zero);
				flag2 = true;
			}
			else
			{
				((Bounds)(ref val8)).Encapsulate(val9);
			}
		}
		_gridStepX = GridLayout.Spacing(((Bounds)(ref val8)).size.x, ((Bounds)(ref val3)).size.x) * Mathf.Abs(val.transform.lossyScale.x);
		_gridStepY = GridLayout.Spacing(((Bounds)(ref val8)).size.y, ((Bounds)(ref val3)).size.y) * Mathf.Abs(val.transform.lossyScale.y);
		_gridStepZ = GridLayout.Spacing(((Bounds)(ref val8)).size.z, ((Bounds)(ref val3)).size.z) * Mathf.Abs(val.transform.lossyScale.z);
		Vector3 val11 = Vector3.Scale(((Bounds)(ref val3)).size, val.transform.lossyScale);
		_gridAutoBasis = GridOrientation.Resolve(((Object)((Component)selectedPiece).gameObject).name + " " + selectedPiece.m_name, _gridStepX, _gridStepY, _gridStepZ, Mathf.Abs(val11.x), Mathf.Abs(val11.y), Mathf.Abs(val11.z), _gridSnapGeometry, selectedPiece.m_groundOnly || selectedPiece.m_groundPiece || selectedPiece.m_waterPiece, selectedPiece.m_notOnFloor);
		UpdateGridBasis();
	}

	private Vector3 GridCellPosition(int index, int width, Vector3 origin, Quaternion rotation, Vector3 across, Vector3 along)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		GridLayout.Cell(index, width, out var column, out var row);
		return origin + rotation * ((float)column * across + (float)row * along);
	}

	private bool BeginGrid(Piece piece)
	{
		bool result = default(bool);
		try
		{
			result = BeginGridCore(piece);
			return result;
		}
		catch (Exception error)
		{
			if (!OcdCompatibility.Recover(error))
			{
				throw;
			}
		}
		return result;
	}

	private void TickGridQueue()
	{
		try
		{
			TickGridQueueCore();
		}
		catch (Exception error)
		{
			if (!OcdCompatibility.Recover(error))
			{
				throw;
			}
		}
	}

	private bool GridInRange(Vector3 point, Piece piece)
	{
		//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)
		if (Object.op_Implicit((Object)(object)piece))
		{
			return Vector3.Distance(((Character)_player).m_eye.position, point) < _player.m_maxPlaceDistance + (float)piece.m_extraPlacementDistance;
		}
		return false;
	}

	private bool GridDuplicate(Vector3 point, Quaternion rotation, Piece piece)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		int num = Physics.OverlapSphereNonAlloc(point, Mathf.Max(2f, Mathf.Max(_gridStepX, Mathf.Max(_gridStepY, _gridStepZ))), _gridDuplicateHits, LayerMask.GetMask(new string[1] { "piece" }), (QueryTriggerInteraction)1);
		if (num == _gridDuplicateHits.Length)
		{
			return true;
		}
		for (int i = 0; i < num; i++)
		{
			Piece componentInParent = ((Component)_gridDuplicateHits[i]).GetComponentInParent<Piece>();
			if (Object.op_Implicit((Object)(object)componentInParent) && (Object)(object)((Component)componentInParent).gameObject != (Object)(object)_gridGhost && componentInParent.m_name == piece.m_name)
			{
				Vector3 val = ((Component)componentInParent).transform.position - point;
				if (((Vector3)(ref val)).sqrMagnitude < 0.0025f && Quaternion.Angle(((Component)componentInParent).transform.rotation, rotation) < 1f)
				{
					return true;
				}
			}
		}
		return false;
	}

	private void DrawGridPreview()
	{
		//IL_0074: 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_0086: Expected O, but got Unknown
		//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cd: 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_01d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01df: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ea: 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_0211: Unknown result type (might be due to invalid IL or missing references)
		//IL_0212: Unknown result type (might be due to invalid IL or missing references)
		//IL_0213: Unknown result type (might be due to invalid IL or missing references)
		//IL_0215: Unknown result type (might be due to invalid IL or missing references)
		//IL_0217: Unknown result type (might be due to invalid IL or missing references)
		//IL_021c: Unknown result type (might be due to invalid IL or missing references)
		//IL_021f: Unknown result type (might be due to invalid IL or missing references)
		//IL_022e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0230: Unknown result type (might be due to invalid IL or missing references)
		//IL_023c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0241: Unknown result type (might be due to invalid IL or missing references)
		//IL_0246: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
		if (!_gridEnabled || !Object.op_Implicit((Object)(object)_gridPreviewPiece) || !Object.op_Implicit((Object)(object)_gridGhost) || !_gridGhost.activeInHierarchy || !Object.op_Implicit((Object)(object)_camera) || MenuBlocksCamera() || !Application.isFocused)
		{
			return;
		}
		if (!Object.op_Implicit((Object)(object)_gridMaterial))
		{
			Shader val = Shader.Find("Hidden/Internal-Colored");
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			_gridMaterial = new Material(val)
			{
				hideFlags = (HideFlags)61
			};
			_gridMaterial.SetInt("_SrcBlend", 5);
			_gridMaterial.SetInt("_DstBlend", 10);
			_gridMaterial.SetInt("_Cull", 2);
			_gridMaterial.SetInt("_ZWrite", 1);
			_gridMaterial.SetInt("_ZTest", 4);
			_gridMaterial.SetColor("_Color", new Color(1f, 0.2f, 0.15f, 1f));
		}
		foreach (GridMesh gridMesh in _gridMeshes)
		{
			if (Object.op_Implicit((Object)(object)gridMesh.Renderer))
			{
				GridPreviewMaterials.GetProperties((Renderer)(object)gridMesh.Renderer, gridMesh.Properties);
				GridPreviewMaterials.GetMaterials((Renderer)(object)gridMesh.Renderer, gridMesh.Materials);
			}
		}
		bool gridBusy = GridBusy;
		int width = (gridBusy ? _gridQueueWidth : _gridWidth);
		int num = (gridBusy ? _gridTotal : (_gridWidth * _gridHeight));
		Vector3 origin = (gridBusy ? _gridOrigin : _gridGhost.transform.position);
		Quaternion val2 = (gridBusy ? _gridRotation : _gridGhost.transform.rotation);
		Vector3 across = (gridBusy ? _gridQueueAcross : _gridAcross);
		Vector3 along = (gridBusy ? _gridQueueAlong : _gridAlong);
		for (int i = ((!gridBusy) ? 1 : (_gridNext + 1)); i < num; i++)
		{
			Vector3 val3 = GridCellPosition(i, width, origin, val2, across, along);
			bool flag = GridInRange(val3, _gridPreviewPiece);
			Matrix4x4 val4 = Matrix4x4.TRS(val3, val2, _gridGhost.transform.lossyScale);
			foreach (GridMesh gridMesh2 in _gridMeshes)
			{
				for (int j = 0; j < gridMesh2.Mesh.subMeshCount; j++)
				{
					Material val5 = ((flag && j < gridMesh2.Materials.Count && Object.op_Implicit((Object)(object)gridMesh2.Materials[j])) ? gridMesh2.Materials[j] : _gridMaterial);
					Graphics.DrawMesh(gridMesh2.Mesh, val4 * gridMesh2.Local, val5, _gridGhost.layer, _camera, j, flag ? gridMesh2.Properties : null, (ShadowCastingMode)0, false);
				}
			}
		}
	}

	private static bool GridButtonDown(string name)
	{
		BuildCamera instance = Instance;
		if (!Object.op_Implicit((Object)(object)instance) || !instance._gridExecuting)
		{
			return ZInput.GetButtonDown(name);
		}
		return name == "Attack";
	}

	private static bool GridButton(string name)
	{
		if (!Object.op_Implicit((Object)(object)Instance) || !Instance._gridExecuting)
		{
			return ZInput.GetButton(name);
		}
		return false;
	}

	private static bool GridButtonUp(string name)
	{
		if (!Object.op_Implicit((Object)(object)Instance) || !Instance._gridExecuting)
		{
			return ZInput.GetButtonUp(name);
		}
		return false;
	}

	private static float GridScroll()
	{
		if (!Object.op_Implicit((Object)(object)Instance) || !Instance._gridExecuting)
		{
			return ZInput.GetMouseScrollWheel();
		}
		return 0f;
	}

	private static bool GridOwnTransform(Transform target)
	{
		BuildCamera instance = Instance;
		if (Object.op_Implicit((Object)(object)instance) && instance._gridExecuting && Object.op_Implicit((Object)(object)instance._gridGhost))
		{
			return (Object)(object)target == (Object)(object)instance._gridGhost.transform;
		}
		return false;
	}

	private static void GridGhostPosition(Transform target, Vector3 value)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		target.position = (GridOwnTransform(target) ? Instance._gridTarget : value);
	}

	private static void GridGhostRotation(Transform target, Quaternion value)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		target.rotation = (GridOwnTransform(target) ? Instance._gridRotation : value);
	}

	private void GridUISelection(bool open)
	{
		EventSystem current = EventSystem.current;
		if (!Object.op_Implicit((Object)(object)current))
		{
			return;
		}
		if (open)
		{
			_gridPreviousSelection = current.currentSelectedGameObject;
			current.SetSelectedGameObject((GameObject)null);
			return;
		}
		GameObject currentSelectedGameObject = current.currentSelectedGameObject;
		if (!Object.op_Implicit((Object)(object)currentSelectedGameObject) || (Object.op_Implicit((Object)(object)_gridCanvas) && currentSelectedGameObject.transform.IsChildOf(_gridCanvas.transform)))
		{
			current.SetSelectedGameObject((Object.op_Implicit((Object)(object)_gridPreviousSelection) && _gridPreviousSelection.activeInHierarchy) ? _gridPreviousSelection : null);
		}
		_gridPreviousSelection = null;
	}

	private void DestroyGridUI()
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		Canvas.willRenderCanvases -= new WillRenderCanvases(LayoutGridUI);
		if (Object.op_Implicit((Object)(object)_gridCanvas))
		{
			_gridCanvas.SetActive(false);
			Object.Destroy((Object)(object)_gridCanvas);
		}
		_gridCanvas = (_gridPanel = (_gridHint = null));
		_gridToolbars = null;
		_gridHud = null;
		_gridAdjustButtons.Clear();
	}

	private bool EnsureGridUI()
	{
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Expected O, but got Unknown
		//IL_013e: Unknown result type (might be due to invalid IL or missing references)
		//IL_025a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0336: Unknown result type (might be due to invalid IL or missing references)
		//IL_036d: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_03cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e2: Expected O, but got Unknown
		if (Object.op_Implicit((Object)(object)_gridCanvas))
		{
			return true;
		}
		if (!Object.op_Implicit((Object)(object)InventoryGui.instance))
		{
			return false;
		}
		ref Button gridButtonTemplate = ref _gridButtonTemplate;
		object? value = AccessTools.Field(typeof(InventoryGui), "m_takeAllButton").GetValue(InventoryGui.instance);
		gridButtonTemplate = (Button)((value is Button) ? value : null);
		if (!Object.op_Implicit((Object)(object)_gridButtonTemplate))
		{
			return false;
		}
		_gridFontTemplate = ((Component)_gridButtonTemplate).GetComponentInChildren<TMP_Text>(true);
		if (!Object.op_Implicit((Object)(object)_gridFontTemplate))
		{
			return false;
		}
		_gridCanvas = new GameObject("Build camera live controls", new Type[3]
		{
			typeof(RectTransform),
			typeof(Canvas),
			typeof(GraphicRaycaster)
		});
		_gridUICanvas = _gridCanvas.GetComponent<Canvas>();
		_gridUICanvas.renderMode = (RenderMode)0;
		_gridUICanvas.sortingOrder = 32000;
		_gridPanel = GridPanel("Mouse adjustments", _gridCanvas.transform, 360f, 300f);
		((Graphic)_gridPanel.GetComponent<Image>()).raycastTarget = true;
		GridText(_gridPanel.transform, "Set preview size", 14f, 8f, 330f, 32f, 24, GridGold);
		GridCountControls(0, 48f, "Columns", out _gridWidthText);
		_gridHeightLabel = GridCountControls(1, 92f, "Rows", out _gridHeightText);
		_gridAuto = GridButton(_gridPanel.transform, "Auto", 14f, 138f, 104f, 36f, delegate
		{
			SetGridPlane(0);
		});
		_gridWall = GridButton(_gridPanel.transform, "Upright", 128f, 138f, 104f, 36f, delegate
		{
			SetGridPlane(1);
		});
		_gridFloor = GridButton(_gridPanel.transform, "Ground", 242f, 138f, 104f, 36f, delegate
		{
			SetGridPlane(2);
		});
		_gridPanelStatus = GridText(_gridPanel.transform, "", 14f, 180f, 332f, 72f, 20, GridInk);
		GridButton(_gridPanel.transform, "Resume", 14f, 256f, 160f, 32f, delegate
		{
			SetGridMenu(open: false);
		});
		GridButton(_gridPanel.transform, "Single piece", 186f, 256f, 160f, 32f, delegate
		{
			SetGridEnabled(enabled: false);
		});
		_gridHint = GridPanel("Live build hint", _gridCanvas.transform, 360f, 192f);
		((Graphic)_gridHint.GetComponent<Image>()).raycastTarget = false;
		_gridHintTitle = GridText(_gridHint.transform, "", 14f, 8f, 332f, 32f, 24, GridGold);
		_gridHintText = GridText(_gridHint.transform, "", 14f, 44f, 332f, 82f, 20, GridInk);
		_gridHintStatus = GridText(_gridHint.transform, "", 14f, 134f, 332f, 50f, 20, GridInk);
		TMP_Text gridHintText = _gridHintText;
		TMP_Text gridHintStatus = _gridHintStatus;
		TextAlignmentOptions alignment = (TextAlignmentOptions)257;
		gridHintStatus.alignment = (TextAlignmentOptions)257;
		gridHintText.alignment = alignment;
		Canvas.willRenderCanvases += new WillRenderCanvases(LayoutGridUI);
		return true;
	}

	private TMP_Text GridCountControls(int row, float y, string label, out TMP_Text value)
	{
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		TMP_Text result = GridText(_gridPanel.transform, label, 14f, y, 156f, 36f, 22, GridInk);
		_gridAdjustButtons.Add(GridButton(_gridPanel.transform, "−", 180f, y, 38f, 36f, delegate
		{
			AdjustGridRow(row, -1);
		}));
		value = GridText(_gridPanel.transform, "", 220f, y, 84f, 36f, 24, GridInk);
		value.alignment = (TextAlignmentOptions)514;
		_gridAdjustButtons.Add(GridButton(_gridPanel.transform, "+", 308f, y, 38f, 36f, delegate
		{
			AdjustGridRow(row, 1);
		}));
		return result;
	}

	private void LayoutGridUI()
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_010f: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02bd: Expected O, but got Unknown
		//IL_02c4: 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_0143: Expected O, but got Unknown
		//IL_036d: Unknown result type (might be due to invalid IL or missing references)
		//IL_037e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0388: Unknown result type (might be due to invalid IL or missing references)
		//IL_038d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0393: Unknown result type (might be due to invalid IL or missing references)
		//IL_017f: 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_0189: Unknown result type (might be due to invalid IL or missing references)
		//IL_0191: Unknown result type (might be due to invalid IL or missing references)
		//IL_0199: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c1: 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_01d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)_gridCanvas) || !_gridCanvas.activeInHierarchy)
		{
			return;
		}
		Rect safeArea = Screen.safeArea;
		float num = Mathf.Max(0.1f, Mathf.Min(((Rect)(ref safeArea)).width / 1920f, ((Rect)(ref safeArea)).height / 1080f));
		_gridUICanvas.scaleFactor = num;
		if (_gridToolbars == null || (Object)(object)_gridHud != (Object)(object)Hud.instance || Time.unscaledTime >= _gridToolbarScanAt)
		{
			_gridHud = Hud.instance;
			_gridToolbars = (HotkeyBar[])(Object.op_Implicit((Object)(object)_gridHud) ? ((Array)((Component)_gridHud).GetComponentsInChildren<HotkeyBar>(true)) : ((Array)new HotkeyBar[0]));
			_gridToolbarScanAt = Time.unscaledTime + 1f;
		}
		_gridToolbarBounds.Clear();
		HotkeyBar[] gridToolbars = _gridToolbars;
		foreach (HotkeyBar val in gridToolbars)
		{
			if (!Object.op_Implicit((Object)(object)val) || !((Behaviour)val).isActiveAndEnabled)
			{
				continue;
			}
			Canvas componentInParent = ((Component)val).GetComponentInParent<Canvas>();
			Camera val2 = ((Object.op_Implicit((Object)(object)componentInParent) && (int)componentInParent.renderMode != 0) ? componentInParent.worldCamera : null);
			foreach (Transform item in ((Component)val).transform)
			{
				Transform val3 = item;
				RectTransform val4 = (RectTransform)(object)((val3 is RectTransform) ? val3 : null);
				if (Object.op_Implicit((Object)(object)val4) && ((Component)val3).gameObject.activeInHierarchy)
				{
					val4.GetWorldCorners(_gridCorners);
					Vector2 val5 = RectTransformUtility.WorldToScreenPoint(val2, _gridCorners[0]);
					float num2 = val5.x;
					float num3 = val5.x;
					float num4 = val5.y;
					float num5 = val5.y;
					for (int j = 1; j < 4; j++)
					{
						Vector2 val6 = RectTransformUtility.WorldToScreenPoint(val2, _gridCorners[j]);
						num2 = Mathf.Min(num2, val6.x);
						num3 = Mathf.Max(num3, val6.x);
						num4 = Mathf.Min(num4, val6.y);
						num5 = Mathf.Max(num5, val6.y);
					}
					if (num3 > num2 && num5 > num4)
					{
						_gridToolbarBounds.Add(new GridHudLayout.Box(num2, num4, num3 - num2, num5 - num4));
					}
				}
			}
		}
		float num6 = (_gridMenu ? 300 : ((!_gridEnabled) ? 36 : (ZInput.IsGamepadActive() ? 192 : 252)));
		RectTransform val7 = (RectTransform)(_gridMenu ? _gridPanel : _gridHint).transform;
		val7.sizeDelta = new Vector2(360f, num6);
		GridHudLayout.Box result;
		bool flag = GridHudLayout.PlaceHint(new GridHudLayout.Box(((Rect)(ref safeArea)).x, ((Rect)(ref safeArea)).y, ((Rect)(ref safeArea)).width, ((Rect)(ref safeArea)).height), num, 360f, num6, _gridToolbarBounds, out result);
		_gridPanel.SetActive(_gridMenu && flag);
		_gridHi