Decompiled source of DeftHands v1.1.0

DeftHands/DeftHands.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.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using DeftHands.Compat;
using DeftHands.Configuration;
using DeftHands.Runtime;
using DeftHands.Utils;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Deft Hands")]
[assembly: AssemblyDescription("Deft Hands - intuitive mouse-drag item rotation for Sailwind, with weighted inertia. https://github.com/KeeviDev/SailwindDeftHands.git")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Keevi")]
[assembly: AssemblyProduct("Deft Hands")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("205f0518-759a-486d-82a9-cea6097352f3")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.1.0.0")]
namespace DeftHands
{
	[BepInPlugin("com.keevi.defthands", "Deft Hands", "1.1.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PLUGIN_GUID = "com.keevi.defthands";

		public const string PLUGIN_NAME = "Deft Hands";

		public const string PLUGIN_VERSION = "1.1.0";

		internal static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			try
			{
				ModConfig.Bind(((BaseUnityPlugin)this).Config);
				LogSettings();
				ApplyHarmonyPatches();
			}
			catch (Exception arg)
			{
				Log.LogError((object)string.Format("{0} failed to load and will not activate: {1}", "Deft Hands", arg));
				return;
			}
			Log.LogInfo((object)string.Format("{0} v{1} loaded.", "Deft Hands", "1.1.0"));
		}

		private void LogSettings()
		{
			Log.LogInfo((object)"Configuration:");
			foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in ((BaseUnityPlugin)this).Config)
			{
				Log.LogInfo((object)$"  {item.Key.Key}: {item.Value.BoxedValue}");
			}
		}

		private static void ApplyHarmonyPatches()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			Harmony val = new Harmony("com.keevi.defthands");
			val.PatchAll(Assembly.GetExecutingAssembly());
			foreach (MethodBase patchedMethod in val.GetPatchedMethods())
			{
				Log.LogInfo((object)$"Patched {patchedMethod.DeclaringType}.{patchedMethod.Name}");
			}
		}
	}
}
namespace DeftHands.Utils
{
	internal static class ReflectionUtils
	{
		public static Type FindType(string fullName)
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				Type type;
				try
				{
					type = assembly.GetType(fullName);
				}
				catch
				{
					continue;
				}
				if (type != null)
				{
					return type;
				}
			}
			return null;
		}
	}
	internal static class PickupableItemUtils
	{
		public static bool HasCustomOnScroll(PickupableItem item)
		{
			MethodInfo method = ((object)item).GetType().GetMethod("OnScroll", BindingFlags.Instance | BindingFlags.Public);
			if (method == null)
			{
				return false;
			}
			return method.DeclaringType != typeof(PickupableItem);
		}
	}
}
namespace DeftHands.Compat
{
	internal static class NandTweaksCompat
	{
		private const string PluginTypeName = "NANDTweaks.Plugin";

		private const BindingFlags FieldFlags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		private static bool initialized;

		private static FieldInfo rotateKeyField;

		private static FieldInfo pushKeyField;

		public static bool IsRotateKeyPressed()
		{
			EnsureInitialized();
			return IsShortcutPressed(rotateKeyField);
		}

		public static bool IsPushKeyPressed()
		{
			EnsureInitialized();
			return IsShortcutPressed(pushKeyField);
		}

		public static bool IsAnyKeyPressed()
		{
			if (!IsRotateKeyPressed())
			{
				return IsPushKeyPressed();
			}
			return true;
		}

		private static void EnsureInitialized()
		{
			if (!initialized)
			{
				initialized = true;
				Type type = ReflectionUtils.FindType("NANDTweaks.Plugin");
				if (!(type == null))
				{
					rotateKeyField = type.GetField("rotateItemKey", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
					pushKeyField = type.GetField("pushItemKey", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				}
			}
		}

		private static bool IsShortcutPressed(FieldInfo configEntryField)
		{
			//IL_001e: 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)
			if (configEntryField == null)
			{
				return false;
			}
			if (!(configEntryField.GetValue(null) is ConfigEntry<KeyboardShortcut> val))
			{
				return false;
			}
			KeyboardShortcut value = val.Value;
			return ((KeyboardShortcut)(ref value)).IsPressed();
		}
	}
	internal static class HooksHangMoreCompat
	{
		private const string AddOnsTypeName = "HooksHangMore.PickupableItemAddOns";

		private const float MinOffset = -90f;

		private const float MaxOffset = 90f;

		private static bool initialized;

		private static Type addOnsType;

		private static FieldInfo offsetField;

		public static void AddHookSwing(PickupableItem item, float delta)
		{
			EnsureInitialized();
			if (!(offsetField == null))
			{
				Component component = ((Component)item).GetComponent(addOnsType);
				if (!((Object)(object)component == (Object)null))
				{
					float num = (float)offsetField.GetValue(component);
					offsetField.SetValue(component, Mathf.Clamp(num + delta, -90f, 90f));
				}
			}
		}

		private static void EnsureInitialized()
		{
			if (!initialized)
			{
				initialized = true;
				addOnsType = ReflectionUtils.FindType("HooksHangMore.PickupableItemAddOns");
				if (!(addOnsType == null))
				{
					offsetField = addOnsType.GetField("heldRotationYOffset", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
			}
		}
	}
}
namespace DeftHands.Patches
{
	internal static class HeldItemTracker
	{
		public static void SetCurrentItem(PickupableItem item)
		{
			RotationHandler.GetInstance().SetCurrentItem(item);
			PushPullHandler.GetInstance().SetCurrentItem(item);
		}
	}
	[HarmonyPatch(typeof(GoPointer), "PickUpItem")]
	public static class PickUpItemPatch
	{
		public static void Postfix(PickupableItem item)
		{
			if ((Object)(object)item != (Object)null)
			{
				HeldItemTracker.SetCurrentItem(item);
			}
		}
	}
	[HarmonyPatch(typeof(GoPointer), "DropItem")]
	public static class DropItemPatch
	{
		public static void Prefix()
		{
			HeldItemTracker.SetCurrentItem(null);
		}
	}
	[HarmonyPatch(typeof(PickupableItem), "OnScroll")]
	public static class ScrollWheelPatch
	{
		private const float ScrollInputPerDistance = 40f;

		public static bool Prefix(float input, PickupableItem __instance)
		{
			if (PickupableItemUtils.HasCustomOnScroll(__instance))
			{
				return true;
			}
			if (ModConfig.PushPullScrollEnabled.Value && !NandTweaksCompat.IsAnyKeyPressed())
			{
				PushPullHandler.GetInstance().Nudge(input / 40f);
				return false;
			}
			if (RotationHandler.GetInstance().IsRotating)
			{
				return false;
			}
			return ModConfig.LegacyRotationEnabled.Value;
		}
	}
	internal static class AltInteractionBlocker
	{
		private static bool isPressSuppressed;

		public static bool FilterDown(bool isDown)
		{
			if (isDown)
			{
				isPressSuppressed = RotationHandler.GetInstance().IsRotating;
			}
			if (isDown)
			{
				return !isPressSuppressed;
			}
			return false;
		}

		public static bool FilterHeld(bool isHeld)
		{
			if (!isHeld)
			{
				isPressSuppressed = false;
				return false;
			}
			if (!isPressSuppressed)
			{
				return !RotationHandler.GetInstance().IsRotating;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(GoPointer), "AltButtonDown")]
	public static class AltButtonDownPatch
	{
		public static void Postfix(ref bool __result)
		{
			__result = AltInteractionBlocker.FilterDown(__result);
		}
	}
	[HarmonyPatch(typeof(GoPointer), "AltButtonHeld")]
	public static class AltButtonHeldPatch
	{
		public static void Postfix(ref bool __result)
		{
			__result = AltInteractionBlocker.FilterHeld(__result);
		}
	}
	[HarmonyPatch(typeof(GoPointer), "LateUpdate")]
	public static class LegacyRotationBlockPatch
	{
		private static bool shouldBlockRotation;

		[HarmonyPrefix]
		private static void Prefix(GoPointer __instance)
		{
			shouldBlockRotation = ShouldBlockRotation(__instance.GetHeldItem());
		}

		private static bool ShouldBlockRotation(PickupableItem heldItem)
		{
			if (ModConfig.LegacyRotationEnabled.Value || (Object)(object)heldItem == (Object)null)
			{
				return false;
			}
			if (PickupableItemUtils.HasCustomOnScroll(heldItem) || NandTweaksCompat.IsPushKeyPressed())
			{
				return false;
			}
			if (!GameInput.GetKey((InputName)11) && !NandTweaksCompat.IsRotateKeyPressed())
			{
				return !ModConfig.PushPullScrollEnabled.Value;
			}
			return true;
		}

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(typeof(LegacyRotationBlockPatch), "MaskScrollValue", (Type[])null, (Type[])null);
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			bool flag = false;
			for (int i = 1; i < list.Count; i++)
			{
				if (CodeInstructionExtensions.LoadsConstant(list[i], 0.0) && CodeInstructionExtensions.IsLdloc(list[i - 1], (LocalBuilder)null))
				{
					list.Insert(i, new CodeInstruction(OpCodes.Call, (object)methodInfo));
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				Plugin.Log.LogError((object)"Could not find the scroll check to patch in GoPointer.LateUpdate - the game may have updated. Legacy Rotation Control will not be able to block scroll-wheel rotation.");
			}
			return list;
		}

		private static float MaskScrollValue(float original)
		{
			if (!shouldBlockRotation)
			{
				return original;
			}
			return 0f;
		}
	}
	[HarmonyPatch(typeof(MouseLook), "Update")]
	public static class DisableCameraRotationPatch
	{
		public static bool Prefix()
		{
			return !RotationHandler.GetInstance().IsRotating;
		}
	}
	[HarmonyPatch(typeof(MouseLook), "Update")]
	public static class MouseLookRotateHUnblockPatch
	{
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(typeof(GameInput), "GetKey", new Type[1] { typeof(InputName) }, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(MouseLookRotateHUnblockPatch), "MaskRotateHCheck", (Type[])null, (Type[])null);
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			bool flag = false;
			for (int i = 0; i < list.Count; i++)
			{
				if (CodeInstructionExtensions.Calls(list[i], methodInfo))
				{
					list.Insert(i + 1, new CodeInstruction(OpCodes.Call, (object)methodInfo2));
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				Plugin.Log.LogError((object)"Could not find the RotateH check to patch in MouseLook.Update - the game may have updated. The camera will keep ignoring input while Q is held even with Legacy Rotation Control off.");
			}
			return list;
		}

		private static bool MaskRotateHCheck(bool original)
		{
			return ModConfig.LegacyRotationEnabled.Value && original;
		}
	}
}
namespace DeftHands.Runtime
{
	public class RotationHandler : MonoBehaviour
	{
		private const float QuadrantZeroDeadzoneDegrees = 2f;

		private const float WeightEffectThreshold = 0f;

		private const float WeightEffectCap = 900f;

		private const float WeightCurvePower = 0.4f;

		private const float StandardSmoothTime = 0.25f;

		private const float LightSmoothTime = 0.1f;

		private const float SingleAxisSpeedMultiplier = 2f;

		private const float MinAppliedInput = 0.001f;

		private static readonly FieldInfo BigItemLocalRotField = AccessTools.Field(typeof(GoPointer), "bigItemLocalRot");

		private static RotationHandler instance;

		private PickupableItem currentItem;

		private float smoothedX;

		private float smoothedY;

		private float dampVelocityX;

		private float dampVelocityY;

		private float quadrantRawOffset;

		private float lastAppliedQuadrantOffset;

		public bool IsRotating
		{
			get
			{
				if (ModConfig.MouseRotationEnabled.Value && ModInput.IsRotationActivationKeyHeld() && (Object)(object)currentItem != (Object)null)
				{
					return (Object)(object)currentItem.held != (Object)null;
				}
				return false;
			}
		}

		public static RotationHandler GetInstance()
		{
			//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_0027: Expected O, but got Unknown
			if ((Object)(object)instance == (Object)null)
			{
				GameObject val = new GameObject("DeftHands_RotationHandler");
				instance = val.AddComponent<RotationHandler>();
				Object.DontDestroyOnLoad((Object)val);
			}
			return instance;
		}

		public void SetCurrentItem(PickupableItem item)
		{
			currentItem = item;
			ResetWeightState();
			lastAppliedQuadrantOffset = (quadrantRawOffset = (((Object)(object)item != (Object)null) ? item.heldRotationOffset : 0f));
		}

		private void Update()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: 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_003c: 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_0028: Unknown result type (might be due to invalid IL or missing references)
			if (!IsRotating)
			{
				ResetWeightState();
				return;
			}
			Vector2 val = ReadMouseInput();
			if (!(Mathf.Abs(val.x) < 0.001f) || !(Mathf.Abs(val.y) < 0.001f))
			{
				RotateHeldItem(val.x, val.y);
			}
		}

		private Vector2 ReadMouseInput()
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			float axis = Input.GetAxis("Mouse X");
			float axis2 = Input.GetAxis("Mouse Y");
			if (!ModConfig.RotationInertiaEnabled.Value)
			{
				ResetWeightState();
				return new Vector2(axis, axis2);
			}
			float num = GetHeaviness() * GetPresetSmoothTime();
			smoothedX = Mathf.SmoothDamp(smoothedX, axis, ref dampVelocityX, num);
			smoothedY = Mathf.SmoothDamp(smoothedY, axis2, ref dampVelocityY, num);
			return new Vector2(smoothedX, smoothedY);
		}

		private void ResetWeightState()
		{
			smoothedX = 0f;
			smoothedY = 0f;
			dampVelocityX = 0f;
			dampVelocityY = 0f;
		}

		private static float GetPresetSmoothTime()
		{
			if (ModConfig.WeightPreset.Value != RotationWeightPreset.Light)
			{
				return 0.25f;
			}
			return 0.1f;
		}

		private float GetHeaviness()
		{
			PickupableItem obj = currentItem;
			ShipItem val = (ShipItem)(object)((obj is ShipItem) ? obj : null);
			if (val == null)
			{
				return 0f;
			}
			return Mathf.Pow(Mathf.InverseLerp(0f, 900f, val.mass), 0.4f);
		}

		private void RotateHeldItem(float horizontalInput, float verticalInput)
		{
			if (PickupableItemUtils.HasCustomOnScroll(currentItem))
			{
				return;
			}
			Camera main = Camera.main;
			if (!((Object)(object)main == (Object)null))
			{
				float value = ModConfig.RotationSensitivity.Value;
				float num = value * 2f;
				float num2 = ApplyInversion(verticalInput, ModConfig.InvertVertical);
				float num3 = ApplyInversion(horizontalInput, ModConfig.InvertRoll);
				HooksHangMoreCompat.AddHookSwing(currentItem, (0f - num3) * num);
				if (currentItem.big)
				{
					RotateBigItem(currentItem, main, horizontalInput, num2, value);
					return;
				}
				if (currentItem is ShipItemQuadrant)
				{
					RotateQuadrant(num2 * num);
					return;
				}
				PickupableItem obj = currentItem;
				obj.heldRotationOffset += num2 * num;
			}
		}

		private static void RotateBigItem(PickupableItem item, Camera mainCamera, float horizontalInput, float tiltInput, float sensitivity)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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_005f: Unknown result type (might be due to invalid IL or missing references)
			bool num = ModConfig.UseAlternativeRotationAxis.Value ^ ModInput.IsAxisSwapKeyHeld();
			Vector3 val = (num ? ((Component)mainCamera).transform.up : ((Component)mainCamera).transform.forward);
			ConfigEntry<bool> invert = (num ? ModConfig.InvertTurn : ModConfig.InvertRoll);
			((Component)item).transform.Rotate(val, (0f - ApplyInversion(horizontalInput, invert)) * sensitivity, (Space)0);
			((Component)item).transform.Rotate(((Component)mainCamera).transform.right, tiltInput * sensitivity, (Space)0);
			StoreBigItemRotation(item);
		}

		private static float ApplyInversion(float input, ConfigEntry<bool> invert)
		{
			if (!invert.Value)
			{
				return input;
			}
			return 0f - input;
		}

		private static void StoreBigItemRotation(PickupableItem item)
		{
			//IL_0019: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			if (!(BigItemLocalRotField == null))
			{
				Quaternion rotation = ((Component)item.held).transform.rotation;
				BigItemLocalRotField.SetValue(item.held, Quaternion.Inverse(rotation) * ((Component)item).transform.rotation);
				item.heldRotationOffset = 0f;
			}
		}

		private void RotateQuadrant(float angle)
		{
			if (!Mathf.Approximately(currentItem.heldRotationOffset, lastAppliedQuadrantOffset))
			{
				quadrantRawOffset = currentItem.heldRotationOffset;
			}
			quadrantRawOffset += angle;
			lastAppliedQuadrantOffset = ApplyDeadzone(quadrantRawOffset, 2f);
			currentItem.heldRotationOffset = lastAppliedQuadrantOffset;
		}

		private static float ApplyDeadzone(float raw, float zone)
		{
			if (!(Mathf.Abs(raw) <= zone))
			{
				return raw;
			}
			return 0f;
		}
	}
	public class PushPullHandler : MonoBehaviour
	{
		private const float SmoothTime = 0.12f;

		private const float SettleThreshold = 0.0005f;

		private const float MinHoldDistance = 0.5f;

		private const float MaxHoldDistance = 2f;

		private const float MinBigItemDistance = 1f;

		private const float MaxBigItemDistance = 3f;

		private static readonly FieldInfo BigItemLocalPosField = AccessTools.Field(typeof(GoPointer), "bigItemLocalPos");

		private static readonly FieldInfo DecolLocalPosField = AccessTools.Field(typeof(GoPointer), "decolLocalPos");

		private static PushPullHandler instance;

		private PickupableItem currentItem;

		private float requestedOffset;

		private float appliedOffset;

		private float smoothVelocity;

		public static PushPullHandler GetInstance()
		{
			//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_0027: Expected O, but got Unknown
			if ((Object)(object)instance == (Object)null)
			{
				GameObject val = new GameObject("DeftHands_PushPullHandler");
				instance = val.AddComponent<PushPullHandler>();
				Object.DontDestroyOnLoad((Object)val);
			}
			return instance;
		}

		public void SetCurrentItem(PickupableItem item)
		{
			currentItem = item;
			ResetSmoothing();
		}

		public void Nudge(float delta)
		{
			if (!((Object)(object)currentItem == (Object)null))
			{
				requestedOffset += delta;
			}
		}

		private void Update()
		{
			if ((Object)(object)currentItem == (Object)null || (Object)(object)currentItem.held == (Object)null)
			{
				ResetSmoothing();
			}
			else if (requestedOffset != appliedOffset)
			{
				float num = ((Mathf.Abs(requestedOffset - appliedOffset) < 0.0005f) ? requestedOffset : Mathf.SmoothDamp(appliedOffset, requestedOffset, ref smoothVelocity, 0.12f));
				bool num2 = MoveHeldItem(num - appliedOffset);
				appliedOffset = num;
				if (!num2 || appliedOffset == requestedOffset)
				{
					ResetSmoothing();
				}
			}
		}

		private void ResetSmoothing()
		{
			requestedOffset = 0f;
			appliedOffset = 0f;
			smoothVelocity = 0f;
		}

		private bool MoveHeldItem(float step)
		{
			float num = currentItem.holdDistance + step;
			currentItem.holdDistance = ClampTowardRange(currentItem.holdDistance, num, 0.5f, 2f);
			bool result = currentItem.holdDistance == num;
			if (currentItem.big && BigItemLocalPosField != null && DecolLocalPosField != null)
			{
				result = MoveBigItemFields(step);
			}
			return result;
		}

		private bool MoveBigItemFields(float step)
		{
			bool result = AddToLocalZ(BigItemLocalPosField, step);
			AddToLocalZ(DecolLocalPosField, step);
			return result;
		}

		private bool AddToLocalZ(FieldInfo localPosField, float step)
		{
			//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_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: 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)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = (Vector3)localPosField.GetValue(currentItem.held);
			float num = val.z + step;
			val.z = ClampTowardRange(val.z, num, 1f, 3f);
			localPosField.SetValue(currentItem.held, val);
			return val.z == num;
		}

		private static float ClampTowardRange(float current, float requested, float min, float max)
		{
			return Mathf.Clamp(requested, Mathf.Min(current, min), Mathf.Max(current, max));
		}
	}
}
namespace DeftHands.Configuration
{
	internal static class ModConfig
	{
		private const string HeldItemControlSection = "Held Item Control";

		private const string AxisInversionSection = "Axis Inversion";

		private const string WeightSimulationSection = "Weight Simulation";

		public static ConfigEntry<bool> MouseRotationEnabled { get; private set; }

		public static ConfigEntry<bool> PushPullScrollEnabled { get; private set; }

		public static ConfigEntry<bool> LegacyRotationEnabled { get; private set; }

		public static ConfigEntry<KeyboardShortcut> RotationActivationKey { get; private set; }

		public static ConfigEntry<float> RotationSensitivity { get; private set; }

		public static ConfigEntry<bool> UseAlternativeRotationAxis { get; private set; }

		public static ConfigEntry<KeyboardShortcut> AxisSwapKey { get; private set; }

		public static ConfigEntry<bool> InvertVertical { get; private set; }

		public static ConfigEntry<bool> InvertRoll { get; private set; }

		public static ConfigEntry<bool> InvertTurn { get; private set; }

		public static ConfigEntry<bool> RotationInertiaEnabled { get; private set; }

		public static ConfigEntry<RotationWeightPreset> WeightPreset { get; private set; }

		public static void Bind(ConfigFile config)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected O, but got Unknown
			//IL_0087: 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_00a1: Expected O, but got Unknown
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Expected O, but got Unknown
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Expected O, but got Unknown
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Expected O, but got Unknown
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Expected O, but got Unknown
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Expected O, but got Unknown
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Expected O, but got Unknown
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Expected O, but got Unknown
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Expected O, but got Unknown
			MouseRotationEnabled = config.Bind<bool>("Held Item Control", "Mouse rotation control", true, new ConfigDescription("Rotate held items with mouse movement while holding the Rotation Activation Key below.", (AcceptableValueBase)null, Array.Empty<object>()));
			PushPullScrollEnabled = config.Bind<bool>("Held Item Control", "Push/pull on scroll wheel", true, new ConfigDescription("Scroll the mouse wheel (without holding a modifier key) to move the held item closer or farther, instead of rotating it around its main axis.", (AcceptableValueBase)null, Array.Empty<object>()));
			LegacyRotationEnabled = config.Bind<bool>("Held Item Control", "Legacy rotation control", true, new ConfigDescription("Enable the game's original scroll-wheel rotation (plain scroll, plus the Q axis), and NANDTweaks' third axis if you have that mod installed. Turn this off to rotate items with the mouse-drag method only.", (AcceptableValueBase)null, Array.Empty<object>()));
			RotationActivationKey = config.Bind<KeyboardShortcut>("Held Item Control", "Rotation activation key", new KeyboardShortcut((KeyCode)308, Array.Empty<KeyCode>()), new ConfigDescription("The key or mouse button you hold down while moving the mouse to rotate the held item.", (AcceptableValueBase)null, Array.Empty<object>()));
			RotationSensitivity = config.Bind<float>("Held Item Control", "Rotation sensitivity", 2f, new ConfigDescription("How fast items rotate with mouse movement.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 10f), Array.Empty<object>()));
			UseAlternativeRotationAxis = config.Bind<bool>("Held Item Control", "Alternative rotation axis", false, new ConfigDescription("Changes which axis left/right mouse movement rotates the item around. By default, it rolls the item around the direction you're looking. Turn this on to instead yaw it around the vertical axis.", (AcceptableValueBase)null, Array.Empty<object>()));
			AxisSwapKey = config.Bind<KeyboardShortcut>("Held Item Control", "Axis swap key", new KeyboardShortcut((KeyCode)324, Array.Empty<KeyCode>()), new ConfigDescription("While held together with the Rotation Activation Key, temporarily swaps which axis left/right mouse movement rotates big items around, overriding Alternative Rotation Axis for as long as it's held.", (AcceptableValueBase)null, Array.Empty<object>()));
			InvertVertical = config.Bind<bool>("Axis Inversion", "Invert vertical", false, new ConfigDescription("Reverses which way up/down mouse movement tilts the held item.", (AcceptableValueBase)null, Array.Empty<object>()));
			InvertRoll = config.Bind<bool>("Axis Inversion", "Invert roll", false, new ConfigDescription("Reverses which way left/right mouse movement rolls items.", (AcceptableValueBase)null, Array.Empty<object>()));
			InvertTurn = config.Bind<bool>("Axis Inversion", "Invert turn", false, new ConfigDescription("Reverses which way left/right mouse movement turns items around the vertical axis (Alternative Rotation Axis, or while holding the Axis Swap Key).", (AcceptableValueBase)null, Array.Empty<object>()));
			RotationInertiaEnabled = config.Bind<bool>("Weight Simulation", "Rotation inertia", true, new ConfigDescription("Makes held items feel like they have weight when you rotate them: heavier items take a moment to speed up, and keep drifting briefly after you stop moving the mouse. Turn off for instant, 1:1 mouse response.", (AcceptableValueBase)null, Array.Empty<object>()));
			WeightPreset = config.Bind<RotationWeightPreset>("Weight Simulation", "Weight preset", RotationWeightPreset.Standard, new ConfigDescription("How strongly items feel weighted while rotating. Standard is the full effect; Light is a much subtler version.", (AcceptableValueBase)null, Array.Empty<object>()));
			KeepPushPullDependentOnMouseRotation();
		}

		private static void KeepPushPullDependentOnMouseRotation()
		{
			DisablePushPullWithoutMouseRotation();
			MouseRotationEnabled.SettingChanged += delegate
			{
				DisablePushPullWithoutMouseRotation();
			};
			PushPullScrollEnabled.SettingChanged += delegate
			{
				if (PushPullScrollEnabled.Value && !MouseRotationEnabled.Value)
				{
					MouseRotationEnabled.Value = true;
				}
			};
		}

		private static void DisablePushPullWithoutMouseRotation()
		{
			if (!MouseRotationEnabled.Value && PushPullScrollEnabled.Value)
			{
				PushPullScrollEnabled.Value = false;
			}
		}
	}
	internal static class ModInput
	{
		public static bool IsRotationActivationKeyHeld()
		{
			return IsMainKeyHeld(ModConfig.RotationActivationKey);
		}

		public static bool IsAxisSwapKeyHeld()
		{
			return IsMainKeyHeld(ModConfig.AxisSwapKey);
		}

		private static bool IsMainKeyHeld(ConfigEntry<KeyboardShortcut> shortcut)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			KeyboardShortcut value = shortcut.Value;
			return Input.GetKey(((KeyboardShortcut)(ref value)).MainKey);
		}
	}
	public enum RotationWeightPreset
	{
		Standard,
		Light
	}
}