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 Enabled; internal static ConfigEntry PitchModifier; internal static ConfigEntry RollModifier; internal static ConfigEntry FineModifier; internal static ConfigEntry ResetShortcut; internal static ConfigEntry NormalStep; internal static ConfigEntry FineStep; internal static ConfigEntry MoveStep; internal static ConfigEntry 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("General", "Enabled", true, "Enable advanced rotation. Vanilla rotation is unchanged when disabled."); PitchModifier = ((BaseUnityPlugin)this).Config.Bind("Controls", "Pitch", new KeyboardShortcut((KeyCode)308, Array.Empty()), "Hold and scroll to pitch."); RollModifier = ((BaseUnityPlugin)this).Config.Bind("Controls", "Roll", new KeyboardShortcut((KeyCode)308, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Hold and scroll to roll."); FineModifier = ((BaseUnityPlugin)this).Config.Bind("Controls", "Fine", new KeyboardShortcut((KeyCode)118, Array.Empty()), "Hold as well for fine rotation or movement. Ctrl is intentionally unused."); ResetShortcut = ((BaseUnityPlugin)this).Config.Bind("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("Rotation", "StepDegrees", 15f, new ConfigDescription("Normal pitch/roll step.", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 90f), Array.Empty())); FineStep = ((BaseUnityPlugin)this).Config.Bind("Rotation", "FineStepDegrees", 1f, new ConfigDescription("Fine pitch/roll step.", (AcceptableValueBase)(object)new AcceptableValueRange(0.01f, 45f), Array.Empty())); MoveStep = ((BaseUnityPlugin)this).Config.Bind("Movement", "StepMeters", 0.25f, new ConfigDescription("Normal local-axis movement step.", (AcceptableValueBase)(object)new AcceptableValueRange(0.01f, 5f), Array.Empty())); FineMoveStep = ((BaseUnityPlugin)this).Config.Bind("Movement", "FineStepMeters", 0.05f, new ConfigDescription("Fine local-axis movement step.", (AcceptableValueBase)(object)new AcceptableValueRange(0.001f, 1f), Array.Empty())); _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 PlaceRotation = AccessTools.FieldRefAccess("m_placeRotation"); private static readonly FieldRef PlacementGhost = AccessTools.FieldRefAccess("m_placementGhost"); private static readonly FieldRef ScrollAmount = AccessTools.FieldRefAccess("m_scrollCurrAmount"); private static readonly FieldRef ManualSnapPoint = AccessTools.FieldRefAccess("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(); 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 Entries = new List(); 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(); 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(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() : null); Transform obj2 = val.transform.Find("Text"); TextMeshProUGUI val3 = ((obj2 != null) ? ((Component)obj2).GetComponent() : 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(); ((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(); 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 Transpiler(IEnumerable 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; } } }