Decompiled source of RunicPrecisionBuildTool v1.0.0

RunicPrecisionBuildTool.dll

Decompiled 11 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace QuietBuildRotation
{
	[BepInPlugin("chazman.RunicPrecisionBuildTool", "Runic Precision Build Tool", "1.0.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Guid = "chazman.RunicPrecisionBuildTool";

		public const string Name = "Runic Precision Build Tool";

		public const string Version = "1.0.0";

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<KeyboardShortcut> PitchModifier;

		internal static ConfigEntry<KeyboardShortcut> RollModifier;

		internal static ConfigEntry<KeyboardShortcut> FineModifier;

		internal static ConfigEntry<KeyboardShortcut> ResetShortcut;

		internal static ConfigEntry<float> NormalStep;

		internal static ConfigEntry<float> FineStep;

		internal static ConfigEntry<float> MoveStep;

		internal static ConfigEntry<float> FineMoveStep;

		internal static ManualLogSource Log;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: 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_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Expected O, but got Unknown
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Expected O, but got Unknown
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Expected O, but got Unknown
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Expected O, but got Unknown
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable advanced rotation. Vanilla rotation is unchanged when disabled.");
			PitchModifier = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "Pitch", new KeyboardShortcut((KeyCode)308, Array.Empty<KeyCode>()), "Hold and scroll to pitch.");
			RollModifier = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "Roll", new KeyboardShortcut((KeyCode)308, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Hold and scroll to roll.");
			FineModifier = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "Fine", new KeyboardShortcut((KeyCode)118, Array.Empty<KeyCode>()), "Hold as well for fine rotation or movement. Ctrl is intentionally unused.");
			ResetShortcut = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "Reset", new KeyboardShortcut((KeyCode)114, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Reserved reset binding. Alt+R resets rotation, vanilla yaw, and translation.");
			NormalStep = ((BaseUnityPlugin)this).Config.Bind<float>("Rotation", "StepDegrees", 15f, new ConfigDescription("Normal pitch/roll step.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 90f), Array.Empty<object>()));
			FineStep = ((BaseUnityPlugin)this).Config.Bind<float>("Rotation", "FineStepDegrees", 1f, new ConfigDescription("Fine pitch/roll step.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 45f), Array.Empty<object>()));
			MoveStep = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "StepMeters", 0.25f, new ConfigDescription("Normal local-axis movement step.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 5f), Array.Empty<object>()));
			FineMoveStep = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "FineStepMeters", 0.05f, new ConfigDescription("Fine local-axis movement step.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.001f, 1f), Array.Empty<object>()));
			_harmony = new Harmony("chazman.RunicPrecisionBuildTool");
			_harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Runic Precision Build Tool v1.0.0 loaded. Alt+wheel pitches, Alt+Shift+wheel rolls, Alt+arrows/PageUp/PageDown moves, Alt+R resets.");
		}

		private void Update()
		{
			RotationController.PollKeyboard();
			AxisGuide.Update();
		}

		private void OnDestroy()
		{
			AxisGuide.Destroy();
			NativeBuildHints.Destroy();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	internal struct PlacementState
	{
		internal Quaternion Rotation;

		internal Vector3 WorldOffset;

		internal static PlacementState Identity => new PlacementState
		{
			Rotation = Quaternion.identity,
			WorldOffset = Vector3.zero
		};
	}
	internal static class RotationController
	{
		private static string _activePiece;

		private static PlacementState _state = PlacementState.Identity;

		private static int _rotationBeforeInput;

		private static bool _advancedInput;

		private static bool _guideVisible;

		private static bool _resetRequested;

		private static readonly FieldRef<Player, int> PlaceRotation = AccessTools.FieldRefAccess<Player, int>("m_placeRotation");

		private static readonly FieldRef<Player, GameObject> PlacementGhost = AccessTools.FieldRefAccess<Player, GameObject>("m_placementGhost");

		private static readonly FieldRef<Player, float> ScrollAmount = AccessTools.FieldRefAccess<Player, float>("m_scrollCurrAmount");

		private static readonly FieldRef<Player, int> ManualSnapPoint = AccessTools.FieldRefAccess<Player, int>("m_manualSnapPoint");

		private static readonly MethodInfo SetupPlacementGhost = AccessTools.Method(typeof(Player), "SetupPlacementGhost", (Type[])null, (Type[])null);

		private static readonly MethodInfo UpdatePlacementGhost = AccessTools.Method(typeof(Player), "UpdatePlacementGhost", (Type[])null, (Type[])null);

		internal static bool GuideVisible => _guideVisible;

		internal static GameObject CurrentGhost
		{
			get
			{
				Player localPlayer = Player.m_localPlayer;
				if (!Object.op_Implicit((Object)(object)localPlayer))
				{
					return null;
				}
				return PlacementGhost.Invoke(localPlayer);
			}
		}

		internal static void BeforePlacementInput(Player player)
		{
			//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_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			ExecutePendingReset(player);
			_rotationBeforeInput = PlaceRotation.Invoke(player);
			int advancedInput;
			if (CanOperate(player))
			{
				KeyboardShortcut value = Plugin.PitchModifier.Value;
				if (!((KeyboardShortcut)(ref value)).IsPressed())
				{
					value = Plugin.RollModifier.Value;
					advancedInput = (((KeyboardShortcut)(ref value)).IsPressed() ? 1 : 0);
				}
				else
				{
					advancedInput = 1;
				}
			}
			else
			{
				advancedInput = 0;
			}
			_advancedInput = (byte)advancedInput != 0;
		}

		internal static void AfterPlacementInput(Player player)
		{
			//IL_0068: 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_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: 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_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: 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)
			if (!CanOperate(player))
			{
				return;
			}
			GameObject val = PlacementGhost.Invoke(player);
			if (!Object.op_Implicit((Object)(object)val) || !val.activeInHierarchy)
			{
				return;
			}
			Piece component = val.GetComponent<Piece>();
			if (!Object.op_Implicit((Object)(object)component) || !component.m_canRotate)
			{
				return;
			}
			string name = ((Object)val).name;
			PlacementState state = GetState(name);
			if (_advancedInput)
			{
				PlaceRotation.Invoke(player) = _rotationBeforeInput;
				float y = Input.mouseScrollDelta.y;
				if (Mathf.Abs(y) > 0.01f)
				{
					float num = Mathf.Sign(y);
					KeyboardShortcut value = Plugin.FineModifier.Value;
					float num2 = (((KeyboardShortcut)(ref value)).IsPressed() ? Plugin.FineStep.Value : Plugin.NormalStep.Value);
					value = Plugin.RollModifier.Value;
					Vector3 val2 = (((KeyboardShortcut)(ref value)).IsPressed() ? Vector3.forward : Vector3.right);
					state.Rotation *= Quaternion.AngleAxis(num * num2, val2);
					((Quaternion)(ref state.Rotation)).Normalize();
					SaveState(name, state);
				}
			}
		}

		internal static void PollKeyboard()
		{
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_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_0109: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (!CanOperate(localPlayer))
			{
				return;
			}
			GameObject val = PlacementGhost.Invoke(localPlayer);
			if (!Object.op_Implicit((Object)(object)val) || !val.activeInHierarchy)
			{
				return;
			}
			GetState(((Object)val).name);
			if (Input.GetKeyDown((KeyCode)103))
			{
				_guideVisible = !_guideVisible;
				return;
			}
			bool flag = Input.GetKey((KeyCode)308) || Input.GetKey((KeyCode)307);
			if ((flag && Input.GetKeyDown((KeyCode)114)) || (Input.GetKey((KeyCode)114) && (Input.GetKeyDown((KeyCode)308) || Input.GetKeyDown((KeyCode)307))))
			{
				_resetRequested = true;
			}
			else if (flag)
			{
				KeyboardShortcut value = Plugin.FineModifier.Value;
				float num = (((KeyboardShortcut)(ref value)).IsPressed() ? Plugin.FineMoveStep.Value : Plugin.MoveStep.Value);
				Vector3 val2 = ReadWorldMovementStep();
				if (val2 != Vector3.zero)
				{
					ref Vector3 worldOffset = ref _state.WorldOffset;
					worldOffset += val2 * num;
				}
			}
		}

		private static void ExecutePendingReset(Player player)
		{
			if (_resetRequested && !((Object)(object)player != (Object)(object)Player.m_localPlayer))
			{
				_resetRequested = false;
				_state = PlacementState.Identity;
				_activePiece = null;
				PlaceRotation.Invoke(player) = 0;
				ScrollAmount.Invoke(player) = 0f;
				ManualSnapPoint.Invoke(player) = -1;
				SetupPlacementGhost.Invoke(player, null);
				UpdatePlacementGhost.Invoke(player, new object[1] { false });
			}
		}

		internal static Quaternion ComposePlacementRotation(float x, float y, float z)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: 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_0030: 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_002e: Unknown result type (might be due to invalid IL or missing references)
			Quaternion val = Quaternion.Euler(x, y, z);
			Player localPlayer = Player.m_localPlayer;
			if (!CanOperate(localPlayer))
			{
				return val;
			}
			GameObject val2 = PlacementGhost.Invoke(localPlayer);
			if (!Object.op_Implicit((Object)(object)val2))
			{
				return val;
			}
			return val * GetState(((Object)val2).name).Rotation;
		}

		internal static void ApplyTranslation(Player player)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			if (!CanOperate(player))
			{
				return;
			}
			GameObject val = PlacementGhost.Invoke(player);
			if (Object.op_Implicit((Object)(object)val) && val.activeInHierarchy)
			{
				PlacementState state = GetState(((Object)val).name);
				if (!(((Vector3)(ref state.WorldOffset)).sqrMagnitude < 1E-07f))
				{
					Transform transform = val.transform;
					transform.position += state.WorldOffset;
				}
			}
		}

		internal static bool HasPrecisionOffset(Player player)
		{
			if (!CanOperate(player))
			{
				return false;
			}
			GameObject val = PlacementGhost.Invoke(player);
			if (Object.op_Implicit((Object)(object)val))
			{
				PlacementState state = GetState(((Object)val).name);
				return ((Vector3)(ref state.WorldOffset)).sqrMagnitude > 1E-07f;
			}
			return false;
		}

		private static bool CanOperate(Player player)
		{
			if (Plugin.Enabled.Value && (Object)(object)player == (Object)(object)Player.m_localPlayer && !Console.IsVisible() && ((Object)(object)Chat.instance == (Object)null || !Chat.instance.HasFocus()) && (Object)(object)Hud.instance != (Object)null)
			{
				return !Hud.IsPieceSelectionVisible();
			}
			return false;
		}

		private static PlacementState GetState(string key)
		{
			if (_activePiece != key)
			{
				_activePiece = key;
				_state = PlacementState.Identity;
			}
			return _state;
		}

		private static void SaveState(string key, PlacementState state)
		{
			GetState(key);
			_state = state;
		}

		private static Vector3 ReadWorldMovementStep()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			if (Input.GetKeyDown((KeyCode)276))
			{
				return Vector3.left;
			}
			if (Input.GetKeyDown((KeyCode)275))
			{
				return Vector3.right;
			}
			if (Input.GetKeyDown((KeyCode)273))
			{
				return Vector3.up;
			}
			if (Input.GetKeyDown((KeyCode)274))
			{
				return Vector3.down;
			}
			if (Input.GetKeyDown((KeyCode)280))
			{
				return Vector3.forward;
			}
			if (Input.GetKeyDown((KeyCode)281))
			{
				return Vector3.back;
			}
			return Vector3.zero;
		}
	}
	internal static class NativeBuildHints
	{
		private static readonly List<GameObject> Entries = new List<GameObject>();

		internal static void Create(KeyHints hints)
		{
			Destroy();
			if (Object.op_Implicit((Object)(object)hints) && Object.op_Implicit((Object)(object)hints.m_buildHints))
			{
				UIInputHint component = hints.m_buildHints.GetComponent<UIInputHint>();
				object obj;
				if (component == null)
				{
					obj = null;
				}
				else
				{
					GameObject mouseKeyboardHint = component.m_mouseKeyboardHint;
					obj = ((mouseKeyboardHint != null) ? mouseKeyboardHint.transform : null);
				}
				Transform val = (Transform)obj;
				object obj2;
				if (val == null)
				{
					obj2 = null;
				}
				else
				{
					Transform obj3 = val.Find("Place");
					obj2 = ((obj3 != null) ? ((Component)obj3).gameObject : null);
				}
				GameObject val2 = (GameObject)obj2;
				if (!Object.op_Implicit((Object)(object)val2))
				{
					Plugin.Log.LogWarning((object)"Could not find Valheim's native Place key hint; precision hints were not added.");
					return;
				}
				Add(val2, val, "Alt+Wheel", "Pitch");
				Add(val2, val, "Alt+Shift+Wheel", "Roll");
				Add(val2, val, "Alt+Arrows", "Move X/Y");
				Add(val2, val, "Alt+PgUp/PgDn", "Move Z");
				Add(val2, val, "V", "Fine");
				Add(val2, val, "Alt+R", "Reset");
				Add(val2, val, "G", "Guides");
			}
		}

		internal static void Refresh()
		{
			bool guideVisible = RotationController.GuideVisible;
			foreach (GameObject entry in Entries)
			{
				if (Object.op_Implicit((Object)(object)entry) && entry.activeSelf != guideVisible)
				{
					entry.SetActive(guideVisible);
				}
			}
		}

		internal static void Destroy()
		{
			foreach (GameObject entry in Entries)
			{
				if (Object.op_Implicit((Object)(object)entry))
				{
					Object.Destroy((Object)(object)entry);
				}
			}
			Entries.Clear();
		}

		private static void Add(GameObject template, Transform parent, string key, string label)
		{
			GameObject val = Object.Instantiate<GameObject>(template, parent, false);
			((Object)val).name = "RunicPrecision_" + label.Replace(" ", string.Empty);
			Transform obj = val.transform.Find("key_bkg/Key");
			TextMeshProUGUI val2 = ((obj != null) ? ((Component)obj).GetComponent<TextMeshProUGUI>() : null);
			Transform obj2 = val.transform.Find("Text");
			TextMeshProUGUI val3 = ((obj2 != null) ? ((Component)obj2).GetComponent<TextMeshProUGUI>() : null);
			if (Object.op_Implicit((Object)(object)val2))
			{
				((TMP_Text)val2).text = key;
			}
			if (Object.op_Implicit((Object)(object)val3))
			{
				((TMP_Text)val3).text = label;
			}
			val.SetActive(false);
			Entries.Add(val);
		}
	}
	internal static class AxisGuide
	{
		private const int Segments = 72;

		private static readonly Color[] LocalColors = (Color[])(object)new Color[3]
		{
			new Color(1f, 0.15f, 0.12f, 0.95f),
			new Color(0.2f, 1f, 0.25f, 0.95f),
			new Color(0.2f, 0.55f, 1f, 0.95f)
		};

		private static readonly Color[] WorldColors = (Color[])(object)new Color[3]
		{
			new Color(1f, 0.25f, 0.22f, 0.28f),
			new Color(0.3f, 1f, 0.35f, 0.28f),
			new Color(0.3f, 0.65f, 1f, 0.28f)
		};

		private static GameObject _root;

		private static LineRenderer[] _rings;

		private static Material _material;

		internal static void Update()
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: 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_0097: 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_00be: 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_00d2: 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_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			GameObject currentGhost = RotationController.CurrentGhost;
			if (!RotationController.GuideVisible || !Object.op_Implicit((Object)(object)currentGhost) || !currentGhost.activeInHierarchy)
			{
				if (Object.op_Implicit((Object)(object)_root))
				{
					_root.SetActive(false);
				}
				return;
			}
			EnsureCreated();
			_root.SetActive(true);
			Bounds val = CalculateBounds(currentGhost);
			Vector3 center = ((Bounds)(ref val)).center;
			Vector3 extents = ((Bounds)(ref val)).extents;
			float num = Mathf.Clamp(((Vector3)(ref extents)).magnitude * 0.72f, 0.45f, 2.75f);
			float num2 = Mathf.Clamp(Vector3.Distance(center, Object.op_Implicit((Object)(object)Camera.main) ? ((Component)Camera.main).transform.position : center) * 0.0025f, 0.018f, 0.055f);
			Quaternion rotation = currentGhost.transform.rotation;
			for (int i = 0; i < 3; i++)
			{
				DrawRing(_rings[i], center, num, num2, i, rotation);
				DrawRing(_rings[i + 3], center, num * 1.08f, num2 * 0.65f, i, Quaternion.identity);
			}
		}

		internal static void Destroy()
		{
			if (Object.op_Implicit((Object)(object)_root))
			{
				Object.Destroy((Object)(object)_root);
			}
			if (Object.op_Implicit((Object)(object)_material))
			{
				Object.Destroy((Object)(object)_material);
			}
			_root = null;
			_rings = null;
			_material = null;
		}

		private static void EnsureCreated()
		{
			//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_0024: Expected O, but got Unknown
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: 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_00f3: 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)
			if (!Object.op_Implicit((Object)(object)_root))
			{
				_root = new GameObject("QuietBuildRotation_AxisGuide")
				{
					hideFlags = (HideFlags)61
				};
				_material = new Material(Shader.Find("Sprites/Default"))
				{
					hideFlags = (HideFlags)61
				};
				_rings = (LineRenderer[])(object)new LineRenderer[6];
				for (int i = 0; i < _rings.Length; i++)
				{
					GameObject val = new GameObject((i < 3) ? $"LocalAxis_{i}" : $"WorldAxis_{i - 3}")
					{
						hideFlags = (HideFlags)61
					};
					val.transform.SetParent(_root.transform, false);
					LineRenderer val2 = val.AddComponent<LineRenderer>();
					((Renderer)val2).sharedMaterial = _material;
					val2.useWorldSpace = true;
					val2.loop = true;
					val2.positionCount = 72;
					val2.numCornerVertices = 2;
					val2.numCapVertices = 2;
					Color startColor = (val2.endColor = ((i < 3) ? LocalColors[i] : WorldColors[i - 3]));
					val2.startColor = startColor;
					_rings[i] = val2;
				}
			}
		}

		private static Bounds CalculateBounds(GameObject ghost)
		{
			//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_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: 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)
			Renderer[] componentsInChildren = ghost.GetComponentsInChildren<Renderer>();
			if (componentsInChildren.Length == 0)
			{
				return new Bounds(ghost.transform.position, Vector3.one);
			}
			Bounds bounds = componentsInChildren[0].bounds;
			for (int i = 1; i < componentsInChildren.Length; i++)
			{
				((Bounds)(ref bounds)).Encapsulate(componentsInChildren[i].bounds);
			}
			return bounds;
		}

		private static void DrawRing(LineRenderer line, Vector3 center, float radius, float width, int axis, Quaternion orientation)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: 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_0049: Unknown result type (might be due to invalid IL or missing references)
			float startWidth = (line.endWidth = width);
			line.startWidth = startWidth;
			for (int i = 0; i < 72; i++)
			{
				float num2 = (float)i * MathF.PI * 2f / 72f;
				float num3 = Mathf.Cos(num2) * radius;
				float num4 = Mathf.Sin(num2) * radius;
				line.SetPosition(i, center + orientation * (Vector3)(axis switch
				{
					1 => new Vector3(num3, 0f, num4), 
					0 => new Vector3(0f, num3, num4), 
					_ => new Vector3(num3, num4, 0f), 
				}));
			}
		}
	}
	[HarmonyPatch(typeof(Player), "UpdatePlacement")]
	internal static class PlayerUpdatePlacementPatch
	{
		private static void Prefix(Player __instance)
		{
			RotationController.BeforePlacementInput(__instance);
		}

		private static void Postfix(Player __instance)
		{
			RotationController.AfterPlacementInput(__instance);
		}
	}
	[HarmonyPatch(typeof(KeyHints), "Awake")]
	internal static class KeyHintsAwakePatch
	{
		private static void Postfix(KeyHints __instance)
		{
			NativeBuildHints.Create(__instance);
		}
	}
	[HarmonyPatch(typeof(KeyHints), "UpdateHints")]
	internal static class KeyHintsUpdatePatch
	{
		private static void Postfix()
		{
			NativeBuildHints.Refresh();
		}
	}
	[HarmonyPatch(typeof(Player), "UpdatePlacementGhost")]
	internal static class PlayerUpdatePlacementGhostPatch
	{
		private static readonly MethodInfo QuaternionEuler = AccessTools.Method(typeof(Quaternion), "Euler", new Type[3]
		{
			typeof(float),
			typeof(float),
			typeof(float)
		}, (Type[])null);

		private static readonly MethodInfo ComposeRotation = AccessTools.Method(typeof(RotationController), "ComposePlacementRotation", (Type[])null, (Type[])null);

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			bool replaced = false;
			foreach (CodeInstruction instruction in instructions)
			{
				if (!replaced && instruction.opcode == OpCodes.Call && object.Equals(instruction.operand, QuaternionEuler))
				{
					instruction.operand = ComposeRotation;
					replaced = true;
				}
				yield return instruction;
			}
			if (!replaced)
			{
				Plugin.Log.LogError((object)"Could not locate Valheim's placement quaternion. Advanced rotation was not patched.");
			}
		}

		private static void Postfix(Player __instance)
		{
			RotationController.ApplyTranslation(__instance);
		}
	}
	[HarmonyPatch(typeof(Player), "TestGhostClipping")]
	internal static class PlayerTestGhostClippingPatch
	{
		private static bool Prefix(Player __instance, ref bool __result)
		{
			if (!RotationController.HasPrecisionOffset(__instance))
			{
				return true;
			}
			__result = false;
			return false;
		}
	}
}