Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of RunicPrecisionBuildTool v1.0.0
RunicPrecisionBuildTool.dll
Decompiled 11 hours agousing 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; } } }