using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("PreciseRotation")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("PreciseRotation")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")] [assembly: AssemblyFileVersion("26.2.2")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("26.2.2.0")] namespace PreciseRotation; [BepInPlugin("com.github.johndowson.PreciseRotation", "PreciseRotation", "26.2.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] internal class PreciseRotation : BaseUnityPlugin { private struct Rotator { public enum Axis { X, Y, Z } public Axis CurrentAxis; public float DegreesPerStep; public int fineMult; public int stepsCoarse; public float x; public float y; public float z; public bool Precision; public Rotator(ConfigEntry stepsCoarse, ConfigEntry fineMult) { CurrentAxis = Axis.Y; x = (y = (z = 0f)); Precision = false; DegreesPerStep = 180f / (float)(stepsCoarse.Value * fineMult.Value); this.fineMult = fineMult.Value; this.stepsCoarse = stepsCoarse.Value; stepsCoarse.SettingChanged += recalculate; } private void recalculate(object _sender, EventArgs eventArgs) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) ConfigEntryBase changedSetting = ((SettingChangedEventArgs)eventArgs).ChangedSetting; string key = changedSetting.Definition.Key; if (key == "StepsCoarse") { stepsCoarse = (int)changedSetting.BoxedValue; } else { if (!(key == "StepsCoarse")) { return; } fineMult = (int)changedSetting.BoxedValue; } x = (y = (z = 0f)); DegreesPerStep = 180f / (float)(stepsCoarse * fineMult); } public void ResetCurrent() { switch (CurrentAxis) { case Axis.X: x = 0f; break; case Axis.Y: y = 0f; break; case Axis.Z: z = 0f; break; } } public void Rotate(int steps) { steps = (Precision ? steps : (steps * fineMult)); float num = DegreesPerStep * (float)steps; switch (CurrentAxis) { case Axis.X: x += num; break; case Axis.Y: y += num; break; case Axis.Z: z += num; break; } } public readonly Quaternion GetRotatation() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) return Quaternion.Euler(x, y, z); } public void NextAxis() { CurrentAxis = CurrentAxis switch { Axis.X => Axis.Y, Axis.Y => Axis.Z, Axis.Z => Axis.X, _ => throw new ArgumentOutOfRangeException(), }; } public void PrevAxis() { CurrentAxis = CurrentAxis switch { Axis.X => Axis.Z, Axis.Y => Axis.X, Axis.Z => Axis.Y, _ => throw new ArgumentOutOfRangeException(), }; } } [HarmonyPatch(typeof(Player))] public static class PieceRotation_Patch { [HarmonyPatch("UpdatePlacementGhost")] [HarmonyTranspiler] private static IEnumerable UpdatePlacementGhostPatch(IEnumerable instructions) { //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Expected O, but got Unknown List list = new List(instructions); for (int i = 0; i < list.Count; i++) { if (list[i].opcode == OpCodes.Ldc_R4 && list[i + 1].opcode == OpCodes.Ldarg_0 && list[i + 2].opcode == OpCodes.Ldfld && list[i + 3].opcode == OpCodes.Ldarg_0 && list[i + 4].opcode == OpCodes.Ldfld && list[i + 5].opcode == OpCodes.Conv_R4 && list[i + 6].opcode == OpCodes.Mul && list[i + 7].opcode == OpCodes.Ldc_R4 && list[i + 8].opcode == OpCodes.Call) { list[i].opcode = OpCodes.Ldarg_0; list[i + 1] = new CodeInstruction(OpCodes.Call, (object)SymbolExtensions.GetMethodInfo((Expression>)((Player player) => GetRotatation(player)))); for (int j = 2; j <= 8; j++) { list[i + j].opcode = OpCodes.Nop; } } } return list.AsEnumerable(); } [HarmonyPatch("UpdatePlacement")] [HarmonyPrefix] private static void RememberOldRotation(Player __instance, bool takeInput, float dt, ref int __state) { __state = __instance.m_placeRotation; } [HarmonyPatch("UpdatePlacement")] [HarmonyPostfix] private static void StoreRotationDifference(Player __instance, bool takeInput, float dt, ref int __state) { if (!((Object)(object)Player.m_localPlayer != (Object)(object)__instance)) { int steps = __instance.m_placeRotation - __state; rotator.Rotate(steps); } } } public const string PluginGUID = "com.github.johndowson.PreciseRotation"; public const string PluginName = "PreciseRotation"; public const string PluginVersion = "26.2.2"; private static readonly Harmony harmony = new Harmony("com.github.johndowson.PreciseRotation"); private ConfigEntry ToggleRotation; private ButtonConfig RotationModifier; private ButtonConfig RotationReset; private ButtonConfig NextAxis; private ButtonConfig PreviousAxis; public static CustomLocalization Localization = LocalizationManager.Instance.GetLocalization(); private static Rotator rotator; private static Sprite X; private static Sprite Y; private static Sprite Z; private ButtonConfig makeBinding(string name, string description, KeyCode keyboardDefault, GamepadButton gamepadDefault, bool blockOtherInputs = false) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0053: 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_0072: Expected O, but got Unknown return new ButtonConfig { Name = name, Config = ((BaseUnityPlugin)this).Config.Bind("Controls", name + "Keyboard", keyboardDefault, description), GamepadConfig = ((BaseUnityPlugin)this).Config.Bind("Controls", name + "Gamepad", gamepadDefault, description), HintToken = "$" + name + "Hint", BlockOtherInputs = blockOtherInputs }; } private void Awake() { X = AssetUtils.LoadSpriteFromFile("PreciseRotation/Assets/axis_x.png"); Y = AssetUtils.LoadSpriteFromFile("PreciseRotation/Assets/axis_y.png"); Z = AssetUtils.LoadSpriteFromFile("PreciseRotation/Assets/axis_z.png"); if (X == null) { X = AssetUtils.LoadSpriteFromFile("disregardthatisuck-PreciseRotation/PreciseRotation/Assets/axis_x.png"); } if (Y == null) { Y = AssetUtils.LoadSpriteFromFile("disregardthatisuck-PreciseRotation/PreciseRotation/Assets/axis_y.png"); } if (Z == null) { Z = AssetUtils.LoadSpriteFromFile("disregardthatisuck-PreciseRotation/PreciseRotation/Assets/axis_z.png"); } if (((IEnumerable)(object)new Sprite[3] { X, Y, Z }).Any((Sprite s) => s == null)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Could not load axis icons. Are you using a weird mod manager?"); } ToggleRotation = ((BaseUnityPlugin)this).Config.Bind("Controls", "ToggleRotation", false, "When `true` pressing RotationModifier button toggless precise mode on and off"); RotationModifier = makeBinding("RotationModifier", "Key to toggle precise rotation", (KeyCode)308, (GamepadButton)0); InputManager.Instance.AddButton("com.github.johndowson.PreciseRotation", RotationModifier); RotationReset = makeBinding("RotationReset", "Key reset rotation in current axis", (KeyCode)47, (GamepadButton)0); InputManager.Instance.AddButton("com.github.johndowson.PreciseRotation", RotationReset); NextAxis = makeBinding("NextAxis", "Key to switch to next rotation axis", (KeyCode)46, (GamepadButton)0, blockOtherInputs: true); InputManager.Instance.AddButton("com.github.johndowson.PreciseRotation", NextAxis); PreviousAxis = makeBinding("PreviousAxis", "Key to switch to next rotation axis", (KeyCode)44, (GamepadButton)0, blockOtherInputs: true); InputManager.Instance.AddButton("com.github.johndowson.PreciseRotation", PreviousAxis); ConfigEntry stepsCoarse = ((BaseUnityPlugin)this).Config.Bind("Rotation", "StepsCoarse", 16, "Base number of rotation steps per 180 degrees, Valheim's default is 16"); ConfigEntry fineMult = ((BaseUnityPlugin)this).Config.Bind("Rotation", "FineMultiplier", 2, "Multiply StepsCoarse by this number to get precise mode steps per 180"); rotator = new Rotator(stepsCoarse, fineMult); harmony.PatchAll(); Logger.LogInfo((object)"PreciseRotation has landed"); } private void Update() { if (ZInput.instance != null && (Object)(object)Player.m_localPlayer != (Object)null) { if (ToggleRotation.Value && ZInput.GetButtonDown(RotationModifier.Name)) { rotator.Precision = !rotator.Precision; ((Character)Player.m_localPlayer).Message((MessageType)1, "Precise Rotation " + (rotator.Precision ? "On" : "Off"), 0, (Sprite)null); } else { rotator.Precision = ZInput.GetButton(RotationModifier.Name); } if (ZInput.GetButtonDown(RotationReset.Name)) { rotator.ResetCurrent(); } bool flag = false; if (ZInput.GetButtonDown(NextAxis.Name)) { rotator.NextAxis(); flag = true; } if (ZInput.GetButtonDown(PreviousAxis.Name)) { rotator.PrevAxis(); flag = true; } if (flag) { Sprite val = (Sprite)(rotator.CurrentAxis switch { Rotator.Axis.X => X, Rotator.Axis.Y => Y, Rotator.Axis.Z => Z, _ => throw new ArgumentOutOfRangeException(), }); ((Character)Player.m_localPlayer).Message((MessageType)1, "Rotation Axis", 0, val); } } } public static Quaternion GetRotatation(Player player) { //IL_0030: 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) if ((Object)(object)player != (Object)(object)Player.m_localPlayer) { return Quaternion.Euler(0f, player.m_placeRotationDegrees * (float)player.m_placeRotation, 0f); } return rotator.GetRotatation(); } }