Decompiled source of Item Stand Rotation v0.5.1

BepInEx/plugins/StandTurn/StandTurn.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.Utilities;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("StandTurn")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.5.1.0")]
[assembly: AssemblyInformationalVersion("0.5.1")]
[assembly: AssemblyProduct("StandTurn")]
[assembly: AssemblyTitle("StandTurn")]
[assembly: AssemblyVersion("0.5.1.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 StandTurn
{
	internal static class AngleMath
	{
		internal static float Normalize(float value)
		{
			if (float.IsNaN(value) || float.IsInfinity(value))
			{
				return 0f;
			}
			return (value % 360f + 360f) % 360f;
		}

		internal static float Scroll(float angle, float wheel, float step)
		{
			if (float.IsNaN(wheel) || float.IsInfinity(wheel) || wheel == 0f)
			{
				return Normalize(angle);
			}
			return Normalize(angle + (float)Math.Sign(wheel) * step);
		}
	}
	internal struct FacingRotation
	{
		internal float X;

		internal float Y;

		internal float Z;

		internal float W;

		internal static FacingRotation Identity => new FacingRotation(0f, 0f, 0f, 1f);

		internal FacingRotation(float x, float y, float z, float w)
		{
			X = x;
			Y = y;
			Z = z;
			W = w;
		}

		internal FacingRotation Normalized()
		{
			double num = Math.Sqrt((double)X * (double)X + (double)Y * (double)Y + (double)Z * (double)Z + (double)W * (double)W);
			if (double.IsNaN(num) || double.IsInfinity(num) || num < 1E-06)
			{
				return Identity;
			}
			return new FacingRotation((float)((double)X / num), (float)((double)Y / num), (float)((double)Z / num), (float)((double)W / num));
		}

		internal FacingRotation Turn(int axis, float degrees)
		{
			return Rotate(axis, degrees, fixedAxis: false);
		}

		internal FacingRotation TurnFixed(int axis, float degrees)
		{
			return Rotate(axis, degrees, fixedAxis: true);
		}

		private FacingRotation Rotate(int axis, float degrees, bool fixedAxis)
		{
			double num = (double)AngleMath.Normalize(degrees) * Math.PI / 360.0;
			float num2 = (float)Math.Sin(num);
			float w = (float)Math.Cos(num);
			FacingRotation facingRotation = new FacingRotation((axis == 0) ? num2 : 0f, (axis == 1) ? num2 : 0f, (axis == 2) ? num2 : 0f, w);
			FacingRotation facingRotation2 = Normalized();
			if (fixedAxis)
			{
				FacingRotation facingRotation3 = facingRotation2;
				facingRotation2 = facingRotation;
				facingRotation = facingRotation3;
			}
			return new FacingRotation(facingRotation2.W * facingRotation.X + facingRotation2.X * facingRotation.W + facingRotation2.Y * facingRotation.Z - facingRotation2.Z * facingRotation.Y, facingRotation2.W * facingRotation.Y - facingRotation2.X * facingRotation.Z + facingRotation2.Y * facingRotation.W + facingRotation2.Z * facingRotation.X, facingRotation2.W * facingRotation.Z + facingRotation2.X * facingRotation.Y - facingRotation2.Y * facingRotation.X + facingRotation2.Z * facingRotation.W, facingRotation2.W * facingRotation.W - facingRotation2.X * facingRotation.X - facingRotation2.Y * facingRotation.Y - facingRotation2.Z * facingRotation.Z).Normalized();
		}

		internal bool SameOrientation(FacingRotation other)
		{
			FacingRotation facingRotation = Normalized();
			FacingRotation facingRotation2 = other.Normalized();
			return Math.Abs((double)facingRotation.X * (double)facingRotation2.X + (double)facingRotation.Y * (double)facingRotation2.Y + (double)facingRotation.Z * (double)facingRotation2.Z + (double)facingRotation.W * (double)facingRotation2.W) > 0.9999999;
		}
	}
	internal static class GameAccess
	{
		internal static readonly FieldRef<ItemStand, ZNetView> View = AccessTools.FieldRefAccess<ItemStand, ZNetView>("m_nview");

		internal static readonly FieldRef<ItemStand, GameObject> Visual = AccessTools.FieldRefAccess<ItemStand, GameObject>("m_visualItem");

		internal static readonly FieldRef<ItemStand, ItemData> QueuedItem = AccessTools.FieldRefAccess<ItemStand, ItemData>("m_queuedItem");

		internal static readonly Func<ItemStand, ItemData, bool> CanAttach = AccessTools.MethodDelegate<Func<ItemStand, ItemData, bool>>(AccessTools.Method(typeof(ItemStand), "CanAttach", (Type[])null, (Type[])null), (object)null, true);

		internal static readonly Func<ItemStand, int> Orientation = AccessTools.MethodDelegate<Func<ItemStand, int>>(AccessTools.Method(typeof(ItemStand), "GetOrientation", (Type[])null, (Type[])null), (object)null, true);

		internal static readonly Action<ItemStand> UpdateAttach = AccessTools.MethodDelegate<Action<ItemStand>>(AccessTools.Method(typeof(ItemStand), "UpdateAttach", (Type[])null, (Type[])null), (object)null, true);

		internal static readonly Func<Player, bool> TakeInput = AccessTools.MethodDelegate<Func<Player, bool>>(AccessTools.Method(typeof(Player), "TakeInput", (Type[])null, (Type[])null), (object)null, true);

		internal static readonly FieldRef<Player, float> MaxDistance = AccessTools.FieldRefAccess<Player, float>("m_maxInteractDistance");

		private static readonly Type EquipmentVisualType = typeof(ItemStand).Assembly.GetType("IEquipmentVisual", throwOnError: true);

		internal static void SetupEquipment(GameObject model, int variant)
		{
			Component componentInChildren = model.GetComponentInChildren(EquipmentVisualType, true);
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				EquipmentVisualType.GetMethod("Setup").Invoke(componentInChildren, new object[1] { variant });
			}
		}

		internal static bool Valid(ItemStand stand)
		{
			if (Object.op_Implicit((Object)(object)stand) && Object.op_Implicit((Object)(object)View.Invoke(stand)))
			{
				return View.Invoke(stand).IsValid();
			}
			return false;
		}

		internal static bool Supported(ItemStand stand)
		{
			if (!Valid(stand) || Object.op_Implicit((Object)(object)stand.m_guardianPower) || !stand.m_canBeRemoved)
			{
				return false;
			}
			string text = ((Object)((Component)stand).gameObject).name.Replace("(Clone)", "").Trim();
			if (!(text == "itemstand"))
			{
				return text == "itemstandh";
			}
			return true;
		}

		internal static float ReadAngle(ItemStand stand)
		{
			return AngleMath.Normalize(View.Invoke(stand).GetZDO().GetFloat("StandTurn.Angle.v1", 0f));
		}

		internal static FacingRotation ReadFacing(ItemStand stand)
		{
			return ReadQuaternion(stand, "StandTurn.Facing.v1");
		}

		internal static FacingRotation ReadRotation(ItemStand stand)
		{
			return ReadQuaternion(stand, "StandTurn.Rotation.v1");
		}

		internal static Vector3 ReadOffset(ItemStand stand)
		{
			//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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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)
			Vector3 vec = View.Invoke(stand).GetZDO().GetVec3("StandTurn.Offset.v1", Vector3.zero);
			return new Vector3(PositionMath.Clean(vec.x), PositionMath.Clean(vec.y), PositionMath.Clean(vec.z));
		}

		private static FacingRotation ReadQuaternion(ItemStand stand, string key)
		{
			//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_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: 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_0029: 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)
			Quaternion quaternion = View.Invoke(stand).GetZDO().GetQuaternion(key, Quaternion.identity);
			return new FacingRotation(quaternion.x, quaternion.y, quaternion.z, quaternion.w).Normalized();
		}

		internal static Quaternion ToQuaternion(FacingRotation facing)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			FacingRotation facingRotation = facing.Normalized();
			return new Quaternion(facingRotation.X, facingRotation.Y, facingRotation.Z, facingRotation.W);
		}

		internal static Vector3 Axis(ItemStand stand, Transform parent)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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_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)
			Vector3 val = (((int)stand.m_orientationType == 2) ? Plugin.Instance.HorizontalAxis.Value : Plugin.Instance.VerticalAxis.Value);
			if (((Vector3)(ref val)).sqrMagnitude < 0.001f)
			{
				val = Vector3.up;
			}
			Vector3 val2 = parent.InverseTransformDirection(((Component)stand).transform.TransformDirection(((Vector3)(ref val)).normalized));
			return ((Vector3)(ref val2)).normalized;
		}

		internal static Quaternion RotationFrame(ItemStand stand, Transform parent)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: 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)
			//IL_000f: Invalid comparison between Unknown and I4
			//IL_0018: 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_001d: 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)
			//IL_0026: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: 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_0038: 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_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: 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_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: 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_0084: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = Axis(stand, parent);
			Vector3 val2 = (((int)stand.m_orientationType == 2) ? Vector3.forward : Vector3.up);
			Vector3 val3 = parent.InverseTransformDirection(((Component)stand).transform.TransformDirection(val2));
			val3 = Vector3.ProjectOnPlane(val3, val);
			if (((Vector3)(ref val3)).sqrMagnitude < 0.001f)
			{
				val3 = Vector3.ProjectOnPlane(parent.InverseTransformDirection(((Component)stand).transform.right), val);
			}
			if (((Vector3)(ref val3)).sqrMagnitude < 0.001f)
			{
				val3 = Vector3.ProjectOnPlane(parent.InverseTransformDirection(((Component)stand).transform.forward), val);
			}
			return Quaternion.LookRotation(Vector3.Cross(val, ((Vector3)(ref val3)).normalized), ((Vector3)(ref val3)).normalized);
		}

		internal static Vector3 DisplayAngles(ItemStand stand, Transform parent, Quaternion mounting, float angle, FacingRotation facing, FacingRotation standRotation)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: 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_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: 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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: 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)
			//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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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_003d: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			Quaternion val = Quaternion.Inverse(RotationFrame(stand, parent)) * mounting;
			Quaternion val2 = ToQuaternion(standRotation) * Quaternion.AngleAxis(angle, Vector3.right) * val * ToQuaternion(facing) * Quaternion.Inverse(val);
			return ((Quaternion)(ref val2)).eulerAngles;
		}

		internal static void Apply(Transform target, Vector3 position, Quaternion rotation, ItemStand stand, float angle, FacingRotation facing, FacingRotation standRotation, Vector3 offset)
		{
			//IL_0007: 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_0014: 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_001a: 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_0027: 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)
			//IL_002b: 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_0035: 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)
			//IL_0040: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: 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_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = Axis(stand, target.parent);
			Quaternion val2 = Quaternion.AngleAxis(AngleMath.Normalize(angle), val);
			Quaternion val3 = RotationFrame(stand, target.parent);
			Quaternion val4 = val3 * ToQuaternion(standRotation) * Quaternion.Inverse(val3);
			target.localPosition = val4 * (val2 * position);
			target.position += target.parent.TransformDirection(val3 * offset);
			target.localRotation = val4 * val2 * rotation * ToQuaternion(facing);
		}
	}
	internal static class InputCapture
	{
		internal struct Snapshot
		{
			internal bool Edit;

			internal bool Cancel;

			internal bool Confirm;

			internal bool Reset;

			internal bool Turn;

			internal bool CycleAxis;

			internal bool ToggleMode;

			internal bool Fine;

			internal bool OtherHeld;

			internal float Wheel;
		}

		[ThreadStatic]
		private static int ownReadDepth;

		private static readonly HashSet<InputControl> locomotion = new HashSet<InputControl>();

		internal static bool Blocking
		{
			get
			{
				if (ownReadDepth == 0)
				{
					return Plugin.BlockActions;
				}
				return false;
			}
		}

		internal static void RefreshBindings()
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//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)
			locomotion.Clear();
			if (ZInput.instance == null)
			{
				return;
			}
			string[] array = new string[6] { "Forward", "Backward", "Left", "Right", "Jump", "JoyJump" };
			foreach (string text in array)
			{
				ButtonDef buttonDef = ZInput.instance.GetButtonDef(text);
				if (((buttonDef != null) ? buttonDef.ButtonAction : null) == null)
				{
					continue;
				}
				Enumerator<InputControl> enumerator = buttonDef.ButtonAction.controls.GetEnumerator();
				try
				{
					while (enumerator.MoveNext())
					{
						InputControl current = enumerator.Current;
						locomotion.Add(current);
					}
				}
				finally
				{
					((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
				}
			}
		}

		internal static bool AllowsControl(InputControl control)
		{
			if (locomotion.Contains(control))
			{
				return true;
			}
			for (InputControl parent = control.parent; parent != null; parent = parent.parent)
			{
				if (parent is StickControl)
				{
					return true;
				}
			}
			return false;
		}

		internal static Snapshot Read(Key edit, Key turn, Key axis, Key mode)
		{
			//IL_0026: 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_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			ownReadDepth++;
			try
			{
				Keyboard current = Keyboard.current;
				Mouse current2 = Mouse.current;
				Snapshot result = new Snapshot
				{
					Edit = (current != null && ((ButtonControl)current[edit]).wasPressedThisFrame),
					Cancel = ((current != null && ((ButtonControl)current.escapeKey).wasPressedThisFrame) || (current2 != null && current2.rightButton.wasPressedThisFrame)),
					Confirm = (current2 != null && current2.leftButton.wasPressedThisFrame),
					Reset = (current != null && ((ButtonControl)current.rKey).wasPressedThisFrame),
					Turn = (current != null && ((ButtonControl)current[turn]).wasPressedThisFrame),
					CycleAxis = (current != null && ((ButtonControl)current[axis]).wasPressedThisFrame),
					ToggleMode = (current != null && ((ButtonControl)current[mode]).wasPressedThisFrame),
					Fine = (current != null && (((ButtonControl)current.leftShiftKey).isPressed || ((ButtonControl)current.rightShiftKey).isPressed)),
					Wheel = ((current2 == null) ? 0f : ((InputControl<Vector2>)(object)current2.scroll).ReadValue().y)
				};
				Enumerator<InputDevice> enumerator = InputSystem.devices.GetEnumerator();
				try
				{
					while (enumerator.MoveNext())
					{
						InputDevice current3 = enumerator.Current;
						if (!(current3 is Keyboard) && !(current3 is Mouse) && !(current3 is Gamepad))
						{
							continue;
						}
						Enumerator<InputControl> enumerator2 = current3.allControls.GetEnumerator();
						try
						{
							while (enumerator2.MoveNext())
							{
								InputControl current4 = enumerator2.Current;
								ButtonControl val = (ButtonControl)(object)((current4 is ButtonControl) ? current4 : null);
								if (val != null && !AllowsControl((InputControl)(object)val) && val.isPressed)
								{
									result.OtherHeld = true;
								}
							}
						}
						finally
						{
							((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose();
						}
					}
				}
				finally
				{
					((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
				}
				return result;
			}
			finally
			{
				ownReadDepth--;
			}
		}
	}
	[HarmonyPatch]
	internal static class RawButtonPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			string[] array = new string[3] { "isPressed", "wasPressedThisFrame", "wasReleasedThisFrame" };
			foreach (string text in array)
			{
				yield return AccessTools.PropertyGetter(typeof(ButtonControl), text);
			}
		}

		[HarmonyPriority(0)]
		private static void Postfix(ButtonControl __instance, ref bool __result)
		{
			if (InputCapture.Blocking && !InputCapture.AllowsControl((InputControl)(object)__instance))
			{
				__result = false;
			}
		}
	}
	[HarmonyPatch]
	internal static class ShortcutInputPatch
	{
		internal static IEnumerable<MethodBase> Targets()
		{
			string[] array = new string[3] { "IsDown", "IsPressed", "IsUp" };
			foreach (string text in array)
			{
				yield return AccessTools.Method(typeof(KeyboardShortcut), text, (Type[])null, (Type[])null);
			}
			List<Type> list = new List<Type>
			{
				typeof(ZInput),
				typeof(Input)
			};
			Type[] types = typeof(BaseUnityPlugin).Assembly.GetTypes();
			foreach (Type type in types)
			{
				if (!type.IsInterface && !type.IsAbstract && typeof(IInputSystem).IsAssignableFrom(type))
				{
					list.Add(type);
				}
			}
			foreach (Type type2 in list)
			{
				MethodInfo[] methods = type2.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
				foreach (MethodInfo methodInfo in methods)
				{
					if (methodInfo.ReturnType == typeof(bool) && methodInfo.GetMethodBody() != null && (methodInfo.Name == "GetKey" || methodInfo.Name == "GetKeyDown" || methodInfo.Name == "GetKeyUp" || methodInfo.Name == "GetMouseButton" || methodInfo.Name == "GetMouseButtonDown" || methodInfo.Name == "GetMouseButtonUp" || (type2 == typeof(Input) && (methodInfo.Name == "GetButton" || methodInfo.Name == "GetButtonDown" || methodInfo.Name == "GetButtonUp"))))
					{
						yield return methodInfo;
					}
				}
			}
		}

		private static IEnumerable<MethodBase> TargetMethods()
		{
			return Targets();
		}

		[HarmonyPriority(800)]
		private static bool Prefix(ref bool __result)
		{
			if (!InputCapture.Blocking)
			{
				return true;
			}
			__result = false;
			return false;
		}

		[HarmonyPriority(0)]
		private static void Postfix(ref bool __result)
		{
			if (InputCapture.Blocking)
			{
				__result = false;
			}
		}
	}
	[HarmonyPatch]
	internal static class ButtonDefinitionPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			string[] array = new string[3] { "Held", "Pressed", "Released" };
			foreach (string text in array)
			{
				yield return AccessTools.PropertyGetter(typeof(ButtonDef), text);
			}
		}

		[HarmonyPriority(0)]
		private static void Postfix(ButtonDef __instance, ref bool __result)
		{
			if (Plugin.BlockActions && !InputPolicy.AllowsAction(__instance.Name))
			{
				__result = false;
			}
		}
	}
	[HarmonyPatch]
	internal static class ActionTimerPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(ZInput), "GetButtonPressedTimer", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(ZInput), "GetButtonLastPressedTimer", (Type[])null, (Type[])null);
		}

		[HarmonyPriority(0)]
		private static void Postfix(string name, MethodBase __originalMethod, ref float __result)
		{
			if (Plugin.BlockActions && !InputPolicy.AllowsAction(name))
			{
				__result = ((__originalMethod.Name == "GetButtonLastPressedTimer") ? float.MaxValue : 0f);
			}
		}
	}
	[HarmonyPatch]
	internal static class LegacyAxisPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(Input), "GetAxis", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(Input), "GetAxisRaw", (Type[])null, (Type[])null);
		}

		[HarmonyPriority(800)]
		private static bool Prefix(string __0, ref float __result)
		{
			if (!Plugin.BlockActions || InputPolicy.AllowsLegacyAxis(__0))
			{
				return true;
			}
			__result = 0f;
			return false;
		}

		[HarmonyPriority(0)]
		private static void Postfix(string __0, ref float __result)
		{
			if (Plugin.BlockActions && !InputPolicy.AllowsLegacyAxis(__0))
			{
				__result = 0f;
			}
		}
	}
	internal static class InputPolicy
	{
		internal static bool AllowsAction(string name)
		{
			switch (name)
			{
			case "Forward":
			case "Backward":
			case "Left":
			case "Right":
			case "Jump":
			case "JoyJump":
				return true;
			default:
				return false;
			}
		}

		internal static bool AllowsLegacyAxis(string name)
		{
			switch (name)
			{
			default:
				return name == "Mouse Y";
			case "Horizontal":
			case "Vertical":
			case "Mouse X":
				return true;
			}
		}
	}
	internal sealed class InputReleaseGate
	{
		private bool waiting;

		private int throughFrame = -1;

		internal bool Blocks(int frame)
		{
			if (!waiting)
			{
				return frame <= throughFrame;
			}
			return true;
		}

		internal void Finish(int frame)
		{
			waiting = true;
			throughFrame = frame + 1;
		}

		internal void Poll(bool held, int frame)
		{
			if (waiting && !held)
			{
				waiting = false;
				throughFrame = frame + 1;
			}
		}
	}
	[BepInPlugin("com.keeton.standturn", "Item Stand Rotation", "0.5.1")]
	[DefaultExecutionOrder(-10000)]
	public sealed class Plugin : BaseUnityPlugin
	{
		private sealed class Session
		{
			internal ItemStand Stand;

			internal ItemData Item;

			internal PreviewVisual Ghost;

			internal StandVisual Existing;

			internal int ItemHash;

			internal int Variant;

			internal int Quality;

			internal int Orientation;

			internal float Angle;

			internal float SavedAngle;

			internal float Deadline;

			internal FacingRotation Facing = FacingRotation.Identity;

			internal FacingRotation SavedFacing;

			internal FacingRotation Rotation = FacingRotation.Identity;

			internal FacingRotation SavedRotation;

			internal int Axis;

			internal Vector3 Offset;

			internal Vector3 SavedOffset;

			internal bool Editing;

			internal bool Waiting;

			internal bool Moving;
		}

		public const string Id = "com.keeton.standturn";

		public const string ModVersion = "0.5.1";

		internal const string AngleKey = "StandTurn.Angle.v1";

		internal const string FacingKey = "StandTurn.Facing.v1";

		internal const string RotationKey = "StandTurn.Rotation.v1";

		internal const string OffsetKey = "StandTurn.Offset.v1";

		internal static Plugin Instance;

		internal static bool AllowVanillaAttach;

		private Harmony harmony;

		private Session session;

		private readonly InputReleaseGate releaseGate = new InputReleaseGate();

		private ConfigEntry<float> step;

		private ConfigEntry<float> fineStep;

		private ConfigEntry<float> moveStep;

		private ConfigEntry<float> fineMoveStep;

		private ConfigEntry<Key> editKey;

		private ConfigEntry<Key> facingKey;

		private ConfigEntry<Key> axisKey;

		private ConfigEntry<Key> modeKey;

		internal ConfigEntry<Vector3> VerticalAxis;

		internal ConfigEntry<Vector3> HorizontalAxis;

		internal static bool Busy
		{
			get
			{
				if (Object.op_Implicit((Object)(object)Instance))
				{
					return Instance.session != null;
				}
				return false;
			}
		}

		internal static bool BlockActions
		{
			get
			{
				if (Object.op_Implicit((Object)(object)Instance))
				{
					if (!Busy)
					{
						return Instance.releaseGate.Blocks(Time.frameCount);
					}
					return true;
				}
				return false;
			}
		}

		private void Awake()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Expected O, but got Unknown
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Expected O, but got Unknown
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Expected O, but got Unknown
			Instance = this;
			step = ((BaseUnityPlugin)this).Config.Bind<float>("Controls", "RotationStep", 15f, new ConfigDescription("Degrees per wheel event.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 90f), Array.Empty<object>()));
			fineStep = ((BaseUnityPlugin)this).Config.Bind<float>("Controls", "FineRotationStep", 1f, new ConfigDescription("Degrees per wheel event while holding Shift.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 15f), Array.Empty<object>()));
			editKey = ((BaseUnityPlugin)this).Config.Bind<Key>("Controls", "EditKey", (Key)101, "Start editing the mounted item on the stand you are looking at.");
			facingKey = ((BaseUnityPlugin)this).Config.Bind<Key>("Controls", "FacingKey", (Key)20, "Turn 90 degrees around the selected stand axis during preview/edit. Press twice for 180 degrees.");
			axisKey = ((BaseUnityPlugin)this).Config.Bind<Key>("Controls", "FacingAxisKey", (Key)34, "Cycle stand-relative rotation axes X (wall rotation), Y (surface-up), Z (across surface). Starts on X.");
			modeKey = ((BaseUnityPlugin)this).Config.Bind<Key>("Controls", "MoveModeKey", (Key)21, "Toggle rotate/move mode during preview/edit.");
			moveStep = ((BaseUnityPlugin)this).Config.Bind<float>("Controls", "MoveStep", 0.05f, new ConfigDescription("Meters per wheel event in move mode.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.001f, 1f), Array.Empty<object>()));
			fineMoveStep = ((BaseUnityPlugin)this).Config.Bind<float>("Controls", "FineMoveStep", 0.01f, new ConfigDescription("Meters per wheel event with Shift in move mode.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.001f, 0.1f), Array.Empty<object>()));
			VerticalAxis = ((BaseUnityPlugin)this).Config.Bind<Vector3>("Axes", "VerticalStandNormal", Vector3.forward, "Surface normal in vertical stand ROOT local coordinates. Restart after changes. Default: 0,0,1.");
			HorizontalAxis = ((BaseUnityPlugin)this).Config.Bind<Vector3>("Axes", "HorizontalStandNormal", Vector3.up, "Surface normal in horizontal stand ROOT local coordinates. Restart after changes. Default: 0,1,0.");
			try
			{
				harmony = new Harmony("com.keeton.standturn");
				harmony.PatchAll(typeof(Plugin).Assembly);
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Item Stand Rotation 0.5.1 loaded. Game: " + Version.GetVersionString(false)));
			}
			catch (Exception ex)
			{
				Harmony obj = harmony;
				if (obj != null)
				{
					obj.UnpatchSelf();
				}
				((Behaviour)this).enabled = false;
				((BaseUnityPlugin)this).Logger.LogError((object)("StandTurn could not bind to this game version; disabled. " + ex));
			}
		}

		private void Update()
		{
			try
			{
				Tick();
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("StandTurn canceled an interaction: " + ex));
				Finish();
				Notify("StandTurn canceled. See BepInEx LogOutput.log.");
			}
		}

		private void Tick()
		{
			//IL_0006: 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_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0336: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c6: Unknown result type (might be due to invalid IL or missing references)
			InputCapture.Snapshot snapshot = InputCapture.Read(editKey.Value, facingKey.Value, axisKey.Value, modeKey.Value);
			releaseGate.Poll(snapshot.OtherHeld, Time.frameCount);
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer) || Keyboard.current == null || !GameAccess.TakeInput(localPlayer))
			{
				if (Busy)
				{
					Finish();
				}
				return;
			}
			if (session == null)
			{
				if (!BlockActions && snapshot.Edit)
				{
					GameObject hoverObject = ((Humanoid)localPlayer).GetHoverObject();
					ItemStand val = (Object.op_Implicit((Object)(object)hoverObject) ? hoverObject.GetComponentInParent<ItemStand>() : null);
					if (GameAccess.Supported(val) && val.HaveAttachment())
					{
						BeginEdit(val);
					}
				}
				return;
			}
			if (!Validate(session, localPlayer))
			{
				Finish();
				Notify("StandTurn canceled: stand, item, or access changed.");
				return;
			}
			if (snapshot.Cancel)
			{
				Finish();
				return;
			}
			if (session.Waiting)
			{
				if (Time.unscaledTime > session.Deadline)
				{
					Finish();
					Notify("StandTurn: ownership request timed out; nothing placed.");
				}
				else if (GameAccess.View.Invoke(session.Stand).IsOwner())
				{
					Commit();
				}
				return;
			}
			if (snapshot.ToggleMode)
			{
				session.Moving = !session.Moving;
			}
			if (snapshot.Reset)
			{
				if (session.Moving)
				{
					session.Offset = Vector3.zero;
				}
				else
				{
					session.Angle = 0f;
					session.Facing = FacingRotation.Identity;
					session.Rotation = FacingRotation.Identity;
				}
			}
			if (snapshot.CycleAxis)
			{
				session.Axis = (session.Axis + 1) % 3;
			}
			if (snapshot.Turn && !session.Moving)
			{
				session.Rotation = session.Rotation.TurnFixed(session.Axis, 90f);
			}
			float wheel = snapshot.Wheel;
			float num = (snapshot.Fine ? fineStep.Value : step.Value);
			if (session.Moving)
			{
				((Vector3)(ref session.Offset))[session.Axis] = PositionMath.Scroll(((Vector3)(ref session.Offset))[session.Axis], wheel, snapshot.Fine ? fineMoveStep.Value : moveStep.Value);
			}
			else if (!float.IsNaN(wheel) && !float.IsInfinity(wheel) && wheel != 0f)
			{
				session.Rotation = session.Rotation.TurnFixed(session.Axis, (float)Math.Sign(wheel) * num);
			}
			session.Ghost?.SetPose(session.Angle, session.Facing, session.Rotation, session.Offset);
			if (Object.op_Implicit((Object)(object)session.Existing))
			{
				session.Existing.PreviewAngle = session.Angle;
				session.Existing.PreviewFacing = session.Facing;
				session.Existing.PreviewRotation = session.Rotation;
				session.Existing.PreviewOffset = session.Offset;
				session.Existing.Refresh();
			}
			if (snapshot.Confirm)
			{
				session.Waiting = true;
				session.Deadline = Time.unscaledTime + 5f;
				ZNetView val2 = GameAccess.View.Invoke(session.Stand);
				if (val2.IsOwner())
				{
					Commit();
				}
				else
				{
					val2.InvokeRPC("RPC_RequestOwn", Array.Empty<object>());
				}
			}
		}

		internal bool BeginAttach(ItemStand stand, ItemData item)
		{
			Finish();
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer) || !GameAccess.TakeInput(localPlayer) || !CanReach(stand, localPlayer) || !GameAccess.CanAttach(stand, item))
			{
				return false;
			}
			if (GameAccess.QueuedItem.Invoke(stand) != null)
			{
				Notify("This stand is already attaching an item.");
				return false;
			}
			Session session = Snapshot(stand);
			session.Item = item;
			session.ItemHash = StringExtensionMethods.GetStableHashCode(((Object)item.m_dropPrefab).name);
			session.Ghost = new PreviewVisual(stand, item, session.Orientation);
			InputCapture.RefreshBindings();
			this.session = session;
			return true;
		}

		private void BeginEdit(ItemStand stand)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			if (CanReach(stand, Player.m_localPlayer) && Object.op_Implicit((Object)(object)GameAccess.Visual.Invoke(stand)))
			{
				Session session = Snapshot(stand);
				session.Editing = true;
				session.Angle = session.SavedAngle;
				session.Facing = session.SavedFacing;
				session.Rotation = session.SavedRotation;
				session.Offset = session.SavedOffset;
				session.Existing = ((Component)stand).GetComponent<StandVisual>() ?? ((Component)stand).gameObject.AddComponent<StandVisual>();
				session.Existing.Capture();
				session.Existing.PreviewAngle = session.Angle;
				session.Existing.PreviewFacing = session.Facing;
				session.Existing.PreviewRotation = session.Rotation;
				session.Existing.PreviewOffset = session.Offset;
				InputCapture.RefreshBindings();
				this.session = session;
			}
		}

		private static Session Snapshot(ItemStand stand)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			ZDO zDO = GameAccess.View.Invoke(stand).GetZDO();
			return new Session
			{
				Stand = stand,
				SavedAngle = GameAccess.ReadAngle(stand),
				Orientation = GameAccess.Orientation(stand),
				SavedFacing = GameAccess.ReadFacing(stand),
				SavedRotation = GameAccess.ReadRotation(stand),
				Axis = 0,
				SavedOffset = GameAccess.ReadOffset(stand),
				ItemHash = stand.GetAttachedItem(),
				Variant = zDO.GetInt(ZDOVars.s_variant, 0),
				Quality = zDO.GetInt(ZDOVars.s_quality, 1)
			};
		}

		private static bool CanReach(ItemStand stand, Player player)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			if (GameAccess.Valid(stand) && Object.op_Implicit((Object)(object)player) && Vector3.Distance(((Character)player).GetEyePoint(), ((Component)stand).transform.position) <= GameAccess.MaxDistance.Invoke(player))
			{
				return PrivateArea.CheckAccess(((Component)stand).transform.position, 0f, false, false);
			}
			return false;
		}

		private static bool Validate(Session s, Player player)
		{
			//IL_0085: 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_008e: Unknown result type (might be due to invalid IL or missing references)
			if (CanReach(s.Stand, player) && GameAccess.TakeInput(player) && GameAccess.Orientation(s.Stand) == s.Orientation && GameAccess.ReadAngle(s.Stand) == s.SavedAngle && GameAccess.ReadFacing(s.Stand).SameOrientation(s.SavedFacing) && GameAccess.ReadRotation(s.Stand).SameOrientation(s.SavedRotation))
			{
				Vector3 val = GameAccess.ReadOffset(s.Stand);
				if (((Vector3)(ref val)).Equals(s.SavedOffset))
				{
					if (!s.Editing)
					{
						if (!s.Stand.HaveAttachment() && ((Humanoid)player).GetInventory().ContainsItem(s.Item))
						{
							return GameAccess.CanAttach(s.Stand, s.Item);
						}
						return false;
					}
					ZDO zDO = GameAccess.View.Invoke(s.Stand).GetZDO();
					if (s.Stand.HaveAttachment() && s.Stand.GetAttachedItem() == s.ItemHash && zDO.GetInt(ZDOVars.s_variant, 0) == s.Variant)
					{
						return zDO.GetInt(ZDOVars.s_quality, 1) == s.Quality;
					}
					return false;
				}
			}
			return false;
		}

		private void Commit()
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			Session session = this.session;
			Player localPlayer = Player.m_localPlayer;
			if (!Validate(session, localPlayer) || !GameAccess.View.Invoke(session.Stand).IsOwner())
			{
				Finish();
				return;
			}
			ZDO zDO = GameAccess.View.Invoke(session.Stand).GetZDO();
			bool flag = false;
			try
			{
				zDO.Set("StandTurn.Angle.v1", AngleMath.Normalize(session.Angle));
				zDO.Set("StandTurn.Facing.v1", GameAccess.ToQuaternion(session.Facing));
				zDO.Set("StandTurn.Rotation.v1", GameAccess.ToQuaternion(session.Rotation));
				zDO.Set("StandTurn.Offset.v1", session.Offset);
				if (session.Editing)
				{
					flag = true;
				}
				else
				{
					AllowVanillaAttach = true;
					if (session.Stand.UseItem((Humanoid)(object)localPlayer, session.Item))
					{
						GameAccess.UpdateAttach(session.Stand);
					}
					flag = session.Stand.HaveAttachment() && session.Stand.GetAttachedItem() == session.ItemHash;
				}
			}
			finally
			{
				AllowVanillaAttach = false;
				if (!flag && GameAccess.Valid(session.Stand) && GameAccess.View.Invoke(session.Stand).IsOwner())
				{
					zDO.Set("StandTurn.Angle.v1", session.SavedAngle);
					zDO.Set("StandTurn.Facing.v1", GameAccess.ToQuaternion(session.SavedFacing));
					zDO.Set("StandTurn.Rotation.v1", GameAccess.ToQuaternion(session.SavedRotation));
					zDO.Set("StandTurn.Offset.v1", session.SavedOffset);
				}
				if (!session.Editing && GameAccess.Valid(session.Stand) && GameAccess.QueuedItem.Invoke(session.Stand) == session.Item)
				{
					((MonoBehaviour)session.Stand).CancelInvoke("UpdateAttach");
					GameAccess.QueuedItem.Invoke(session.Stand) = null;
				}
				Finish();
			}
			Notify(flag ? "Item Stand Rotation: placement saved." : "Item Stand Rotation: item could not be attached.");
		}

		private void Finish()
		{
			Session session = this.session;
			this.session = null;
			if (session != null)
			{
				session.Ghost?.Dispose();
				if (Object.op_Implicit((Object)(object)session.Existing))
				{
					session.Existing.PreviewAngle = null;
					session.Existing.PreviewFacing = null;
					session.Existing.PreviewRotation = null;
					session.Existing.PreviewOffset = null;
					session.Existing.Refresh();
				}
				releaseGate.Finish(Time.frameCount);
			}
		}

		internal void ReportPreviewError(Exception error)
		{
			Finish();
			((BaseUnityPlugin)this).Logger.LogError((object)("Could not create item preview: " + error));
			Notify("StandTurn: preview unavailable; item was not placed.");
		}

		private static void Notify(string text)
		{
			if (Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, text, 0, (Sprite)null, false);
			}
		}

		private void OnGUI()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			//IL_00d6: 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_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Invalid comparison between Unknown and I4
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f6: Expected O, but got Unknown
			//IL_0320: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			if (session != null)
			{
				GUIStyle val = new GUIStyle(GUI.skin.box)
				{
					fontSize = Mathf.RoundToInt(17f * Mathf.Clamp((float)Screen.height / 1080f, 0.8f, 1.5f)),
					alignment = (TextAnchor)4,
					wordWrap = true,
					richText = true
				};
				Vector3 val2 = (Object.op_Implicit((Object)(object)session.Existing) ? session.Existing.DisplayAngles(session.Angle, session.Facing, session.Rotation) : (session.Ghost?.DisplayAngles(session.Angle, session.Facing, session.Rotation) ?? Vector3.zero));
				string text = AxisCounter(0, val2.x) + "     " + AxisCounter(1, val2.y) + "     " + AxisCounter(2, val2.z);
				text = "Rotation: " + text + "\nPosition: " + PositionCounter(0) + "     " + PositionCounter(1) + "     " + PositionCounter(2);
				bool flag = (int)session.Stand.m_orientationType == 2;
				string text2 = ((!session.Moving) ? "X: wall rotation   Y: surface-up   Z: across surface" : (flag ? "X: up/down   Y: forward/back   Z: sideways" : "X: into/out of wall   Y: up/down   Z: sideways"));
				string text3 = (session.Waiting ? ("Item Stand Rotation • Waiting for stand ownership…\n" + text + "\nRight-click / Esc: cancel") : ("Item Stand Rotation • " + (session.Editing ? "Edit" : "Preview") + " • " + (session.Moving ? "MOVE" : "ROTATE") + "\n" + text + "\n" + string.Format("{0}\n{1}: rotate/move   {2}: X → Y → Z   Scroll: {3} selected axis   Shift: fine\n", text2, modeKey.Value, axisKey.Value, session.Moving ? "move" : "rotate") + (session.Moving ? "R: reset position" : $"{facingKey.Value}: +90° on selected axis   R: reset rotation") + "\nLeft-click: confirm   Right-click / Esc: cancel\nMovement, jump and look remain available; other controls are captured."));
				float num = Mathf.Min(800f, (float)Screen.width - 24f);
				float num2 = val.CalcHeight(new GUIContent(text3), num) + 12f;
				GUI.Box(new Rect(((float)Screen.width - num) / 2f, (float)Screen.height - 130f - num2, num, num2), text3, val);
			}
		}

		private string AxisCounter(int axis, float degrees)
		{
			float num = AngleMath.Normalize((float)Math.Round(degrees, 1));
			string text = string.Format("{0}: {1:0.#}°", "XYZ"[axis], num);
			if (axis != session.Axis || session.Moving)
			{
				return text;
			}
			return "<color=#FFFF00><b>" + text + "</b></color>";
		}

		private string PositionCounter(int axis)
		{
			float num = (float)Math.Round(((Vector3)(ref session.Offset))[axis], 3);
			string text = string.Format("{0}: {1:0.###} m", "XYZ"[axis], num);
			if (axis != session.Axis || !session.Moving)
			{
				return text;
			}
			return "<color=#FFFF00><b>" + text + "</b></color>";
		}

		private void OnDestroy()
		{
			Finish();
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			StandVisual[] array = Object.FindObjectsByType<StandVisual>((FindObjectsSortMode)0);
			for (int i = 0; i < array.Length; i++)
			{
				Object.Destroy((Object)(object)array[i]);
			}
			Instance = null;
		}

		private void OnApplicationFocus(bool focused)
		{
			if (!focused)
			{
				Finish();
			}
		}
	}
	[HarmonyPatch(typeof(ItemStand), "Awake")]
	internal static class StandAwakePatch
	{
		private static void Postfix(ItemStand __instance)
		{
			if (GameAccess.Supported(__instance) && !Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<StandVisual>()))
			{
				((Component)__instance).gameObject.AddComponent<StandVisual>();
			}
		}
	}
	[HarmonyPatch(typeof(ItemStand), "SetVisualItem")]
	internal static class StandVisualPatch
	{
		private static void Postfix(ItemStand __instance)
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			if (GameAccess.Supported(__instance) && !__instance.HaveAttachment() && GameAccess.View.Invoke(__instance).IsOwner())
			{
				GameAccess.View.Invoke(__instance).GetZDO().Set("StandTurn.Angle.v1", 0f);
				GameAccess.View.Invoke(__instance).GetZDO().Set("StandTurn.Facing.v1", Quaternion.identity);
				GameAccess.View.Invoke(__instance).GetZDO().Set("StandTurn.Rotation.v1", Quaternion.identity);
				GameAccess.View.Invoke(__instance).GetZDO().Set("StandTurn.Offset.v1", Vector3.zero);
			}
			StandVisual component = ((Component)__instance).GetComponent<StandVisual>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.Refresh();
			}
		}
	}
	[HarmonyPatch(typeof(ItemStand), "UseItem")]
	internal static class StandUsePatch
	{
		private static bool Prefix(ItemStand __instance, Humanoid user, ItemData item, ref bool __result)
		{
			if (Plugin.AllowVanillaAttach || !Object.op_Implicit((Object)(object)Plugin.Instance) || !((Behaviour)Plugin.Instance).enabled || (Object)(object)user != (Object)(object)Player.m_localPlayer || !GameAccess.Supported(__instance) || __instance.HaveAttachment())
			{
				return true;
			}
			__result = true;
			try
			{
				Plugin.Instance.BeginAttach(__instance, item);
			}
			catch (Exception error)
			{
				Plugin.Instance.ReportPreviewError(error);
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(ItemStand), "Interact")]
	internal static class StandInteractPatch
	{
		private static bool Prefix(ref bool __result)
		{
			if (!Plugin.Busy)
			{
				return true;
			}
			__result = false;
			return false;
		}
	}
	[HarmonyPatch(typeof(ItemStand), "GetHoverText")]
	internal static class StandHoverPatch
	{
		private static void Postfix(ItemStand __instance, ref string __result)
		{
			if (GameAccess.Supported(__instance) && !Plugin.Busy)
			{
				__result += (__instance.HaveAttachment() ? "\n[Item Stand Rotation] Edit: configured EditKey (F8 default)" : "\n[Item Stand Rotation] Use an item hotbar key to preview");
			}
		}
	}
	[HarmonyPatch(typeof(ZInput), "GetMouseScrollWheel")]
	internal static class ScrollPatch
	{
		private static void Postfix(ref float __result)
		{
			if (Plugin.BlockActions)
			{
				__result = 0f;
			}
		}
	}
	[HarmonyPatch(typeof(Player), "UseHotbarItem")]
	internal static class HotbarPatch
	{
		private static bool Prefix(Player __instance)
		{
			if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
			{
				return !Plugin.BlockActions;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Player), "SetControls")]
	internal static class ControlsPatch
	{
		private static void Prefix(Player __instance, ref bool attack, ref bool attackHold, ref bool secondaryAttack, ref bool secondaryAttackHold, ref bool block, ref bool blockHold, ref bool dodge, ref bool crouch, ref bool run, ref bool autoRun)
		{
			if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && Plugin.BlockActions)
			{
				attack = (attackHold = (secondaryAttack = (secondaryAttackHold = (block = (blockHold = (dodge = (crouch = (run = (autoRun = false)))))))));
				__instance.m_autoRun = false;
			}
		}
	}
	[HarmonyPatch]
	internal static class ActionButtonPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(ZInput), "GetButton", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(ZInput), "GetButtonDown", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(ZInput), "GetButtonUp", (Type[])null, (Type[])null);
		}

		[HarmonyPriority(0)]
		private static void Postfix(string name, ref bool __result)
		{
			if (Plugin.BlockActions && !InputPolicy.AllowsAction(name))
			{
				__result = false;
			}
		}
	}
	internal static class PositionMath
	{
		internal static float Clean(float value)
		{
			if (!float.IsNaN(value) && !float.IsInfinity(value))
			{
				return value;
			}
			return 0f;
		}

		internal static float Scroll(float current, float wheel, float step)
		{
			current = Clean(current);
			if (float.IsNaN(wheel) || float.IsInfinity(wheel) || wheel == 0f || step <= 0f || Clean(step) == 0f)
			{
				return current;
			}
			return Clean((float)Math.Round(current + (float)Math.Sign(wheel) * step, 4));
		}
	}
	internal sealed class PreviewVisual : IDisposable
	{
		private readonly GameObject staging;

		private GameObject model;

		private Material ghostMaterial;

		private Vector3 position;

		private Quaternion rotation;

		private readonly ItemStand stand;

		internal PreviewVisual(ItemStand target, ItemData item, int orientation)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			//IL_0282: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Unknown result type (might be due to invalid IL or missing references)
			//IL_029e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0303: Unknown result type (might be due to invalid IL or missing references)
			//IL_0452: Unknown result type (might be due to invalid IL or missing references)
			//IL_0328: Unknown result type (might be due to invalid IL or missing references)
			//IL_032d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0342: Unknown result type (might be due to invalid IL or missing references)
			//IL_0351: Expected O, but got Unknown
			stand = target;
			staging = new GameObject("StandTurn inactive preview staging");
			staging.SetActive(false);
			try
			{
				GameObject attachPrefab = ItemStand.GetAttachPrefab(item.m_dropPrefab);
				if (!Object.op_Implicit((Object)(object)attachPrefab))
				{
					throw new InvalidOperationException("This item has no vanilla attachment visual.");
				}
				model = Object.Instantiate<GameObject>(ItemStand.GetAttachGameObject(attachPrefab), staging.transform, false);
				model.SetActive(false);
				GameAccess.SetupEquipment(model, item.m_variant);
				MonoBehaviour[] componentsInChildren = model.GetComponentsInChildren<MonoBehaviour>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
				}
				if (model.GetComponentsInChildren<MonoBehaviour>(true).Length != 0)
				{
					throw new InvalidOperationException("Could not remove all gameplay scripts from the preview.");
				}
				Collider[] componentsInChildren2 = model.GetComponentsInChildren<Collider>(true);
				for (int i = 0; i < componentsInChildren2.Length; i++)
				{
					Object.DestroyImmediate((Object)(object)componentsInChildren2[i]);
				}
				Rigidbody[] componentsInChildren3 = model.GetComponentsInChildren<Rigidbody>(true);
				for (int i = 0; i < componentsInChildren3.Length; i++)
				{
					Object.DestroyImmediate((Object)(object)componentsInChildren3[i]);
				}
				AudioSource[] componentsInChildren4 = model.GetComponentsInChildren<AudioSource>(true);
				for (int i = 0; i < componentsInChildren4.Length; i++)
				{
					Object.DestroyImmediate((Object)(object)componentsInChildren4[i]);
				}
				Light[] componentsInChildren5 = model.GetComponentsInChildren<Light>(true);
				for (int i = 0; i < componentsInChildren5.Length; i++)
				{
					((Behaviour)componentsInChildren5[i]).enabled = false;
				}
				ParticleSystem[] componentsInChildren6 = model.GetComponentsInChildren<ParticleSystem>(true);
				for (int i = 0; i < componentsInChildren6.Length; i++)
				{
					componentsInChildren6[i].Stop(true, (ParticleSystemStopBehavior)0);
				}
				Animator[] componentsInChildren7 = model.GetComponentsInChildren<Animator>(true);
				for (int i = 0; i < componentsInChildren7.Length; i++)
				{
					((Behaviour)componentsInChildren7[i]).enabled = false;
				}
				Transform[] componentsInChildren8 = model.GetComponentsInChildren<Transform>(true);
				for (int i = 0; i < componentsInChildren8.Length; i++)
				{
					((Component)componentsInChildren8[i]).gameObject.layer = 2;
				}
				Renderer[] componentsInChildren9 = model.GetComponentsInChildren<Renderer>(true);
				foreach (Renderer val in componentsInChildren9)
				{
					if (!(val is MeshRenderer) && !(val is SkinnedMeshRenderer))
					{
						val.enabled = false;
					}
				}
				List<OrientationSettings> list = new List<OrientationSettings>();
				ItemData itemData = item.m_dropPrefab.GetComponent<ItemDrop>().m_itemData;
				stand.GetOrientationSettings(itemData, ref list);
				OrientationSettings val2 = list[Mathf.Clamp(orientation, 0, list.Count - 1)];
				position = attachPrefab.transform.localPosition + val2.m_position;
				rotation = attachPrefab.transform.localRotation * Quaternion.Euler(val2.m_rotation);
				model.transform.SetParent(stand.GetAttach(itemData), false);
				model.transform.localScale = Vector3.Scale(Vector3.Scale(attachPrefab.transform.localScale, itemData.GetScale((float)item.m_quality)), val2.m_scale);
				Shader val3 = Shader.Find("Standard");
				if (Object.op_Implicit((Object)(object)val3))
				{
					ghostMaterial = new Material(val3)
					{
						color = new Color(0.3f, 0.9f, 1f, 0.55f)
					};
					ghostMaterial.SetFloat("_Mode", 2f);
					ghostMaterial.SetInt("_SrcBlend", 5);
					ghostMaterial.SetInt("_DstBlend", 10);
					ghostMaterial.SetInt("_ZWrite", 0);
					ghostMaterial.EnableKeyword("_ALPHABLEND_ON");
					ghostMaterial.renderQueue = 3000;
					componentsInChildren9 = model.GetComponentsInChildren<Renderer>(true);
					foreach (Renderer val4 in componentsInChildren9)
					{
						if (!(val4 is MeshRenderer) && !(val4 is SkinnedMeshRenderer))
						{
							val4.enabled = false;
							continue;
						}
						Material[] sharedMaterials = val4.sharedMaterials;
						for (int j = 0; j < sharedMaterials.Length; j++)
						{
							sharedMaterials[j] = ghostMaterial;
						}
						val4.sharedMaterials = sharedMaterials;
						val4.shadowCastingMode = (ShadowCastingMode)0;
					}
				}
				model.SetActive(true);
				SetPose(0f, FacingRotation.Identity, FacingRotation.Identity, Vector3.zero);
			}
			catch
			{
				Dispose();
				throw;
			}
		}

		internal void SetPose(float angle, FacingRotation facing, FacingRotation standRotation, Vector3 offset)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)model))
			{
				GameAccess.Apply(model.transform, position, rotation, stand, angle, facing, standRotation, offset);
			}
		}

		internal Vector3 DisplayAngles(float angle, FacingRotation facing, FacingRotation standRotation)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)model))
			{
				return Vector3.zero;
			}
			return GameAccess.DisplayAngles(stand, model.transform.parent, rotation, angle, facing, standRotation);
		}

		public void Dispose()
		{
			if (Object.op_Implicit((Object)(object)model))
			{
				model.SetActive(false);
				Object.Destroy((Object)(object)model);
			}
			if (Object.op_Implicit((Object)(object)staging))
			{
				Object.Destroy((Object)(object)staging);
			}
			if (Object.op_Implicit((Object)(object)ghostMaterial))
			{
				Object.Destroy((Object)(object)ghostMaterial);
			}
		}
	}
	public sealed class StandVisual : MonoBehaviour
	{
		private ItemStand stand;

		private GameObject visual;

		private Vector3 originalPosition;

		private Quaternion originalRotation;

		internal float? PreviewAngle;

		internal FacingRotation? PreviewFacing;

		internal FacingRotation? PreviewRotation;

		internal Vector3? PreviewOffset;

		private void Awake()
		{
			stand = ((Component)this).GetComponent<ItemStand>();
		}

		internal void Capture()
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: 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)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			if (!GameAccess.Valid(stand))
			{
				return;
			}
			GameObject val = GameAccess.Visual.Invoke(stand);
			if (!((Object)(object)val == (Object)(object)visual))
			{
				visual = val;
				if (Object.op_Implicit((Object)(object)visual))
				{
					originalPosition = visual.transform.localPosition;
					originalRotation = visual.transform.localRotation;
				}
			}
		}

		private void LateUpdate()
		{
			Refresh();
		}

		internal Vector3 DisplayAngles(float angle, FacingRotation facing, FacingRotation rotation)
		{
			//IL_002a: 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)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			Capture();
			if (!Object.op_Implicit((Object)(object)visual) || !Object.op_Implicit((Object)(object)visual.transform.parent))
			{
				return Vector3.zero;
			}
			return GameAccess.DisplayAngles(stand, visual.transform.parent, originalRotation, angle, facing, rotation);
		}

		internal void Refresh()
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
			Capture();
			if (Object.op_Implicit((Object)(object)visual) && Object.op_Implicit((Object)(object)visual.transform.parent) && GameAccess.Valid(stand))
			{
				GameAccess.Apply(visual.transform, originalPosition, originalRotation, stand, PreviewAngle ?? GameAccess.ReadAngle(stand), PreviewFacing ?? GameAccess.ReadFacing(stand), PreviewRotation ?? GameAccess.ReadRotation(stand), (Vector3)(((??)PreviewOffset) ?? GameAccess.ReadOffset(stand)));
			}
		}

		private void OnDestroy()
		{
			//IL_001a: 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)
			if (Object.op_Implicit((Object)(object)visual))
			{
				visual.transform.localPosition = originalPosition;
				visual.transform.localRotation = originalRotation;
			}
		}
	}
}