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.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("26.2.0.0")]
namespace PreciseRotation;
[BepInPlugin("com.github.johndowson.PreciseRotation", "PreciseRotation", "26.2.0")]
[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 float x;
public float y;
public float z;
public bool Precision;
public Rotator(int stepsCoarse, int fineMult)
{
CurrentAxis = Axis.Y;
x = (y = (z = 0f));
Precision = false;
DegreesPerStep = 180f / (float)(stepsCoarse * fineMult);
this.fineMult = fineMult;
}
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(),
};
}
}
[HarmonyPatch(typeof(Player))]
public static class PieceRotation_Patch
{
[HarmonyPatch("UpdatePlacementGhost")]
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> UpdatePlacementGhostPatch(IEnumerable<CodeInstruction> instructions)
{
//IL_0173: Unknown result type (might be due to invalid IL or missing references)
//IL_017d: Expected O, but got Unknown
List<CodeInstruction> list = new List<CodeInstruction>(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<Player, Quaternion>((Expression<Func<Player, Quaternion>>)((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.0";
private static readonly Harmony harmony = new Harmony("com.github.johndowson.PreciseRotation");
private ConfigEntry<int> RotationStepsCoarse;
private ConfigEntry<int> RotationStepsFineMultiplier;
private ConfigEntry<bool> ToggleRotation;
private ConfigEntry<KeyCode> RotationModifierKeyboard;
private ConfigEntry<GamepadButton> RotationModifierGamepad;
private ButtonConfig RotationModifier;
private ConfigEntry<KeyCode> NextAxisKeyboard;
private ConfigEntry<GamepadButton> NextAxisGamepad;
private ButtonConfig NextAxis;
public static CustomLocalization Localization = LocalizationManager.Instance.GetLocalization();
private static Rotator rotator;
private static Sprite X;
private static Sprite Y;
private static Sprite Z;
private void Awake()
{
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
//IL_009a: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
//IL_00d4: Expected O, but got Unknown
//IL_012d: Unknown result type (might be due to invalid IL or missing references)
//IL_0132: Unknown result type (might be due to invalid IL or missing references)
//IL_013d: Unknown result type (might be due to invalid IL or missing references)
//IL_0149: Unknown result type (might be due to invalid IL or missing references)
//IL_0155: Unknown result type (might be due to invalid IL or missing references)
//IL_0160: Unknown result type (might be due to invalid IL or missing references)
//IL_016c: Expected O, but got Unknown
X = AssetUtils.LoadSpriteFromFile("PreciseRotation/Assets/axis_x.png");
Y = AssetUtils.LoadSpriteFromFile("PreciseRotation/Assets/axis_y.png");
Z = AssetUtils.LoadSpriteFromFile("PreciseRotation/Assets/axis_z.png");
ToggleRotation = ((BaseUnityPlugin)this).Config.Bind<bool>("Controls", "ToggleRotation", false, "Key to toggle precise rotation");
RotationModifierKeyboard = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "RotationModifierKeyboard", (KeyCode)308, "Key to toggle precise rotation");
RotationModifierGamepad = ((BaseUnityPlugin)this).Config.Bind<GamepadButton>("Controls", "RotationModifierGamepad", (GamepadButton)0, "Key to toggle precise rotation");
RotationModifier = new ButtonConfig
{
Name = "RotationModifier",
Config = RotationModifierKeyboard,
GamepadConfig = RotationModifierGamepad,
HintToken = "$RotationModifierHint",
BlockOtherInputs = false
};
InputManager.Instance.AddButton("com.github.johndowson.PreciseRotation", RotationModifier);
NextAxisKeyboard = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "NextAxisKeyboard", (KeyCode)46, "Key to toggle rotation axis");
NextAxisGamepad = ((BaseUnityPlugin)this).Config.Bind<GamepadButton>("Controls", "NextAxisGamepad", (GamepadButton)0, "Key to toggle rotation axis");
NextAxis = new ButtonConfig
{
Name = "NextAxis",
Config = NextAxisKeyboard,
GamepadConfig = NextAxisGamepad,
HintToken = "$NextAxisHint",
BlockOtherInputs = true
};
InputManager.Instance.AddButton("com.github.johndowson.PreciseRotation", NextAxis);
RotationStepsCoarse = ((BaseUnityPlugin)this).Config.Bind<int>("Rotation", "StepsCoarse", 16, "Base number of rotation steps per 180 degrees, Valheim's default is 16");
RotationStepsFineMultiplier = ((BaseUnityPlugin)this).Config.Bind<int>("Rotation", "FineMultiplier", 2, "Multiply StepsCoarse by this number to get precise mode steps per 180");
rotator = new Rotator(RotationStepsCoarse.Value, RotationStepsFineMultiplier.Value);
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);
}
Logger.LogFatal((object)$"Prec: {rotator.Precision};");
if (ZInput.GetButtonDown(NextAxis.Name))
{
rotator.NextAxis();
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();
}
}