Decompiled source of UltimateTelekinesis v0.7.0

Mods/UltimateTelekinesis.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppTMPro;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using UltimateTelekinesis;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.XR;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(UltimateTelekinesisMod), "Ultimate Telekinesis", "0.7.0", "GravWarden", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace UltimateTelekinesis
{
	public sealed class UltimateTelekinesisMod : MelonMod
	{
		private struct IgnoredCollision
		{
			public readonly Collider ObjectCollider;

			public readonly Collider PlayerCollider;

			public IgnoredCollision(Collider objectCollider, Collider playerCollider)
			{
				ObjectCollider = objectCollider;
				PlayerCollider = playerCollider;
			}
		}

		private sealed class MenuControl
		{
			public readonly RectTransform Rect;

			public readonly Image Image;

			public readonly TextMeshProUGUI Label;

			public readonly Action Action;

			public readonly Color BaseColor;

			public MenuControl(RectTransform rect, Image image, TextMeshProUGUI label, Action action, Color baseColor)
			{
				//IL_0024: 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)
				Rect = rect;
				Image = image;
				Label = label;
				Action = action;
				BaseColor = baseColor;
			}
		}

		private const float DefaultMaxRange = 10f;

		private const float DefaultHoldDistance = 2.5f;

		private const float DefaultFollowStrength = 16f;

		private const float DefaultMaxFollowSpeed = 8f;

		private const float DefaultThrowSpeed = 10f;

		private const float DefaultCastRadius = 0.12f;

		private const float DefaultTriggerThreshold = 0.45f;

		private const float DefaultGripThreshold = 0.5f;

		private const float MenuToggleDebounce = 0.35f;

		private MelonPreferences_Category _preferences;

		private MelonPreferences_Entry<bool> _enabledPreference;

		private MelonPreferences_Entry<bool> _leftHandPreference;

		private MelonPreferences_Entry<bool> _gravityWhileHoldingPreference;

		private MelonPreferences_Entry<bool> _holdToGrabPreference;

		private MelonPreferences_Entry<bool> _menuLeftHandPreference;

		private MelonPreferences_Entry<int> _menuButtonPreference;

		private MelonPreferences_Entry<int> _settingsVersionPreference;

		private MelonPreferences_Entry<float> _maxRangePreference;

		private MelonPreferences_Entry<float> _holdDistancePreference;

		private MelonPreferences_Entry<float> _followStrengthPreference;

		private MelonPreferences_Entry<float> _maxFollowSpeedPreference;

		private MelonPreferences_Entry<float> _throwSpeedPreference;

		private MelonPreferences_Entry<float> _castRadiusPreference;

		private MelonPreferences_Entry<float> _triggerThresholdPreference;

		private MelonPreferences_Entry<float> _gripThresholdPreference;

		private InputDevice _controller;

		private InputDevice _menuController;

		private XRNode _controllerNode = (XRNode)5;

		private bool _previousTrigger;

		private bool _previousGrip;

		private bool _previousMenuButton;

		private Rigidbody _heldBody;

		private Vector3 _localGrabPoint;

		private bool _originalUseGravity;

		private readonly List<MenuControl> _menuControls = new List<MenuControl>();

		private bool _enabled = true;

		private bool _gravityWhileHolding;

		private bool _loggedControllerWarning;

		private bool _loggedCollisionIntegrationWarning;

		private readonly List<IgnoredCollision> _ignoredPlayerCollisions = new List<IgnoredCollision>();

		private Transform _cameraTransform;

		private Camera _gameplayCamera;

		private GameObject _menuObject;

		private RectTransform _menuRect;

		private RectTransform _cursorRect;

		private Image _cursorImage;

		private TextMeshProUGUI _statusText;

		private readonly List<GameObject> _menuVisuals = new List<GameObject>();

		private MenuControl _hoveredControl;

		private bool _previousMenuTrigger;

		private float _nextMenuToggleTime;

		private float _nextStatusUpdateTime;

		private float _poseLostSince = -1f;

		private string _lastAction = "Ready";

		private int _menuPage;

		public override void OnInitializeMelon()
		{
			InitializePreferences();
			MelonLogger.Msg("Initialized. Open the in-game Nebula menu with the configured controller button.");
		}

		private void InitializePreferences()
		{
			//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
			_preferences = MelonPreferences.CreateCategory("UltimateTelekinesis", "Ultimate Telekinesis");
			_enabledPreference = _preferences.CreateEntry<bool>("Enabled", true, "Enabled", "Turn telekinesis on or off.", false, false, (ValueValidator)null, (string)null);
			_leftHandPreference = _preferences.CreateEntry<bool>("UseLeftHand", false, "Use left hand", "Use the left controller instead of the right controller.", false, false, (ValueValidator)null, (string)null);
			_gravityWhileHoldingPreference = _preferences.CreateEntry<bool>("GravityWhileHolding", false, "Gravity while holding", "Allow the held object to keep its normal gravity.", false, false, (ValueValidator)null, (string)null);
			_holdToGrabPreference = _preferences.CreateEntry<bool>("HoldToGrab", false, "Hold trigger to grab", "Hold the trigger to keep holding an object; release it to drop.", false, false, (ValueValidator)null, (string)null);
			_menuLeftHandPreference = _preferences.CreateEntry<bool>("MenuUseLeftHand", false, "Menu hand", "Controller used to open and operate the Nebula menu.", false, false, (ValueValidator)null, (string)null);
			_menuButtonPreference = _preferences.CreateEntry<int>("MenuButton", 1, "Menu button", "0 = primary, 1 = secondary, 2 = menu button.", false, false, (ValueValidator)null, (string)null);
			_settingsVersionPreference = _preferences.CreateEntry<int>("SettingsVersion", 0, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_maxRangePreference = _preferences.CreateEntry<float>("MaxRange", 10f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_holdDistancePreference = _preferences.CreateEntry<float>("HoldDistance", 2.5f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_followStrengthPreference = _preferences.CreateEntry<float>("FollowStrength", 16f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_maxFollowSpeedPreference = _preferences.CreateEntry<float>("MaxFollowSpeed", 8f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_throwSpeedPreference = _preferences.CreateEntry<float>("ThrowSpeed", 10f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_castRadiusPreference = _preferences.CreateEntry<float>("CastRadius", 0.12f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_triggerThresholdPreference = _preferences.CreateEntry<float>("TriggerThreshold", 0.45f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_gripThresholdPreference = _preferences.CreateEntry<float>("GripThreshold", 0.5f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			MigrateLegacyDefaults();
			ClampPreference(_maxRangePreference, 1f, 20f);
			ClampPreference(_holdDistancePreference, 0.5f, 10f);
			ClampPreference(_followStrengthPreference, 1f, 30f);
			ClampPreference(_maxFollowSpeedPreference, 1f, 30f);
			ClampPreference(_throwSpeedPreference, 1f, 30f);
			ClampPreference(_castRadiusPreference, 0.02f, 0.5f);
			ClampPreference(_triggerThresholdPreference, 0.1f, 0.95f);
			ClampPreference(_gripThresholdPreference, 0.1f, 0.95f);
			_enabled = _enabledPreference.Value;
			_gravityWhileHolding = _gravityWhileHoldingPreference.Value;
			_controllerNode = (XRNode)(_leftHandPreference.Value ? 4 : 5);
		}

		private void MigrateLegacyDefaults()
		{
			if (_settingsVersionPreference.Value < 1)
			{
				ReplaceLegacyDefault(_maxRangePreference, 18f, 10f);
				ReplaceLegacyDefault(_holdDistancePreference, 3.5f, 2.5f);
				ReplaceLegacyDefault(_followStrengthPreference, 12f, 16f);
				ReplaceLegacyDefault(_maxFollowSpeedPreference, 12f, 8f);
				ReplaceLegacyDefault(_throwSpeedPreference, 12f, 10f);
				ReplaceLegacyDefault(_castRadiusPreference, 0.08f, 0.12f);
				ReplaceLegacyDefault(_triggerThresholdPreference, 0.75f, 0.45f);
				ReplaceLegacyDefault(_gripThresholdPreference, 0.75f, 0.5f);
				_settingsVersionPreference.Value = 1;
				MelonPreferences.Save();
			}
		}

		private static void ReplaceLegacyDefault(MelonPreferences_Entry<float> preference, float legacyDefault, float newDefault)
		{
			if (Mathf.Approximately(preference.Value, legacyDefault))
			{
				preference.Value = newDefault;
			}
		}

		private static void ClampPreference(MelonPreferences_Entry<float> preference, float min, float max)
		{
			preference.Value = Mathf.Clamp(preference.Value, min, max);
		}

		public override void OnUpdate()
		{
			RefreshController();
			bool flag = UpdateMenu();
			if (!((InputDevice)(ref _controller)).isValid || !_enabled || flag)
			{
				_previousTrigger = false;
				_previousGrip = false;
				if ((Object)(object)_heldBody != (Object)null)
				{
					ReleaseHeld();
				}
				if (!((InputDevice)(ref _controller)).isValid && !_loggedControllerWarning)
				{
					MelonLogger.Warning(((object)Unsafe.As<XRNode, XRNode>(ref _controllerNode)/*cast due to .constrained prefix*/).ToString() + " XR controller not detected. Check headset/controller tracking.");
					_loggedControllerWarning = true;
				}
				return;
			}
			_loggedControllerWarning = false;
			bool flag2 = ReadButton(CommonUsages.trigger, CommonUsages.triggerButton, _triggerThresholdPreference.Value);
			bool flag3 = ReadButton(CommonUsages.grip, CommonUsages.gripButton, _gripThresholdPreference.Value);
			if (_holdToGrabPreference.Value)
			{
				if (flag2 && !_previousTrigger && (Object)(object)_heldBody == (Object)null)
				{
					TryGrab();
				}
				else if (!flag2 && _previousTrigger && (Object)(object)_heldBody != (Object)null)
				{
					ReleaseHeld();
				}
			}
			else if (flag2 && !_previousTrigger)
			{
				if ((Object)(object)_heldBody == (Object)null)
				{
					TryGrab();
				}
				else
				{
					ReleaseHeld();
				}
			}
			if (flag3 && !_previousGrip && (Object)(object)_heldBody != (Object)null)
			{
				ThrowHeld();
			}
			_previousTrigger = flag2;
			_previousGrip = flag3;
		}

		public override void OnFixedUpdate()
		{
			if ((Object)(object)_heldBody != (Object)null)
			{
				UpdateHeldObject();
			}
		}

		private bool ReadButton(InputFeatureUsage<float> analogUsage, InputFeatureUsage<bool> buttonUsage, float threshold)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return ReadButton(_controller, analogUsage, buttonUsage, threshold);
		}

		private static bool ReadButton(InputDevice device, InputFeatureUsage<float> analogUsage, InputFeatureUsage<bool> buttonUsage, float threshold)
		{
			float num2 = default(float);
			bool num = ((InputDevice)(ref device)).TryGetFeatureValue(analogUsage, ref num2) && num2 >= threshold;
			bool flag2 = default(bool);
			bool flag = ((InputDevice)(ref device)).TryGetFeatureValue(buttonUsage, ref flag2) && flag2;
			return num || flag;
		}

		private bool UpdateMenu()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			if (!((InputDevice)(ref _menuController)).isValid)
			{
				_previousMenuButton = false;
				_previousMenuTrigger = false;
				return (Object)(object)_menuObject != (Object)null;
			}
			bool flag = ReadConfiguredMenuButton(_menuController);
			bool flag2 = flag && !_previousMenuButton && Time.time >= _nextMenuToggleTime;
			_previousMenuButton = flag;
			if (flag2)
			{
				_nextMenuToggleTime = Time.time + 0.35f;
				if ((Object)(object)_menuObject == (Object)null)
				{
					OpenMenu();
				}
				else
				{
					CloseMenu();
				}
			}
			if ((Object)(object)_menuObject == (Object)null)
			{
				_previousMenuTrigger = false;
				return flag2;
			}
			bool flag3 = ReadButton(_menuController, CommonUsages.trigger, CommonUsages.triggerButton, _triggerThresholdPreference.Value);
			if (flag3 && !_previousMenuTrigger)
			{
				ActivateHoveredControl();
			}
			_previousMenuTrigger = flag3;
			UpdateMenuPointer();
			UpdateMenuStatus();
			return true;
		}

		private bool ReadConfiguredMenuButton(InputDevice device)
		{
			InputFeatureUsage<bool> val = ((_menuButtonPreference.Value == 0) ? CommonUsages.primaryButton : ((_menuButtonPreference.Value == 2) ? CommonUsages.menuButton : CommonUsages.secondaryButton));
			bool flag = default(bool);
			return ((InputDevice)(ref device)).TryGetFeatureValue(val, ref flag) && flag;
		}

		private void OpenMenu()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: 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_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_cameraTransform == (Object)null)
			{
				_lastAction = "Menu unavailable: gameplay camera not found";
				MelonLogger.Warning(_lastAction + ".");
				return;
			}
			_menuObject = new GameObject("UltimateTelekinesisNebulaMenu");
			Canvas obj = _menuObject.AddComponent<Canvas>();
			obj.renderMode = (RenderMode)2;
			obj.worldCamera = _gameplayCamera;
			obj.sortingOrder = 30000;
			_menuObject.transform.SetParent(_cameraTransform, false);
			_menuObject.transform.localPosition = new Vector3(0f, 0f, 0.85f);
			_menuObject.transform.localRotation = Quaternion.identity;
			_menuObject.transform.localScale = Vector3.one * 0.001f;
			_menuRect = _menuObject.GetComponent<RectTransform>();
			_menuRect.sizeDelta = new Vector2(1000f, 1200f);
			((Graphic)_menuObject.AddComponent<Image>()).color = new Color(0.035f, 0.025f, 0.12f, 0.97f);
			BuildMenuPage();
			_previousMenuTrigger = ReadButton(_menuController, CommonUsages.trigger, CommonUsages.triggerButton, _triggerThresholdPreference.Value);
		}

		private void CloseMenu()
		{
			if ((Object)(object)_menuObject != (Object)null)
			{
				Object.Destroy((Object)(object)_menuObject);
			}
			_menuObject = null;
			_menuRect = null;
			_cursorRect = null;
			_cursorImage = null;
			_statusText = null;
			_menuControls.Clear();
			_menuVisuals.Clear();
			_hoveredControl = null;
			_previousMenuTrigger = false;
		}

		private void BuildMenuPage()
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_cursorImage != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_cursorImage).gameObject);
			}
			_cursorRect = null;
			_cursorImage = null;
			DestroyMenuVisuals();
			CreateGalaxyDecoration();
			CreateMenuText("ULTIMATE TELEKINESIS", 0f, 530f, 920f, 64f, 42f, new Color(0.56f, 0.86f, 1f, 1f), bold: true);
			CreateMenuText("NEBULA CONTROL DECK   //   QUEST EDITION", 0f, 482f, 920f, 34f, 18f, new Color(0.73f, 0.68f, 1f, 1f), bold: false);
			CreateMenuButton("CORE", -350f, 410f, 170f, 58f, delegate
			{
				SelectMenuPage(0);
			});
			CreateMenuButton("CONTROLS", -115f, 410f, 205f, 58f, delegate
			{
				SelectMenuPage(1);
			});
			CreateMenuButton("PHYSICS", 125f, 410f, 185f, 58f, delegate
			{
				SelectMenuPage(2);
			});
			CreateMenuButton("STATUS", 350f, 410f, 170f, 58f, delegate
			{
				SelectMenuPage(3);
			});
			if (_menuPage == 0)
			{
				BuildCorePage();
			}
			else if (_menuPage == 1)
			{
				BuildControlsPage();
			}
			else if (_menuPage == 2)
			{
				BuildPhysicsPage();
			}
			else
			{
				BuildStatusPage();
			}
			CreateMenuButton("CLOSE MENU", 0f, -520f, 360f, 64f, (Action)CloseMenu, (Color?)new Color(0.45f, 0.17f, 0.38f, 1f));
			CreateMenuText("AIM AT A CONTROL + SQUEEZE TRIGGER TO SELECT", 0f, -570f, 920f, 30f, 16f, new Color(0.7f, 0.74f, 0.9f, 1f), bold: false);
			CreateMenuCursor();
		}

		private void CreateMenuCursor()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("NebulaMenuCursor");
			val.transform.SetParent(_menuObject.transform, false);
			_cursorImage = val.AddComponent<Image>();
			((Graphic)_cursorImage).color = new Color(0.25f, 0.96f, 1f, 0.95f);
			((Graphic)_cursorImage).raycastTarget = false;
			_cursorRect = val.GetComponent<RectTransform>();
			RectTransform cursorRect = _cursorRect;
			RectTransform cursorRect2 = _cursorRect;
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0.5f, 0.5f);
			cursorRect2.anchorMax = val2;
			cursorRect.anchorMin = val2;
			_cursorRect.pivot = new Vector2(0.5f, 0.5f);
			_cursorRect.sizeDelta = new Vector2(24f, 24f);
		}

		private void CreateGalaxyDecoration()
		{
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			Random random = new Random(2406);
			for (int i = 0; i < 36; i++)
			{
				float x = (float)(random.NextDouble() * 900.0 - 450.0);
				float y = (float)(random.NextDouble() * 1040.0 - 520.0);
				float num = random.Next(12, 23);
				Color color = ((i % 3 == 0) ? new Color(0.55f, 0.58f, 1f, 0.6f) : new Color(0.35f, 0.82f, 0.95f, 0.43f));
				CreateMenuText((i % 4 == 0) ? "+" : ".", x, y, num * 2f, num * 2f, num, color, bold: true);
			}
		}

		private void BuildCorePage()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			CreateMenuText("TELEKINESIS CORE", 0f, 335f, 840f, 54f, 30f, new Color(0.88f, 0.8f, 1f, 1f), bold: true);
			CreateMenuButton("POWER: " + (_enabled ? "ONLINE" : "OFFLINE"), 0f, 245f, 520f, 72f, (Action)delegate
			{
				SetTelekinesisEnabled(!_enabled);
			}, (Color?)(_enabled ? new Color(0.08f, 0.39f, 0.37f, 1f) : new Color(0.43f, 0.13f, 0.25f, 1f)));
			CreateMenuButton("GRAB MODE: " + (_holdToGrabPreference.Value ? "HOLD TRIGGER" : "PRESS TO TOGGLE"), 0f, 145f, 620f, 72f, delegate
			{
				_holdToGrabPreference.Value = !_holdToGrabPreference.Value;
				_previousTrigger = false;
				SavePreferences();
				BuildMenuPage();
			});
			CreateMenuButton("GRAB HAND: " + (_leftHandPreference.Value ? "LEFT" : "RIGHT"), 0f, 45f, 460f, 72f, ToggleGrabHand);
			CreateMenuButton("RELEASE HELD OBJECT", 0f, -55f, 460f, 72f, (Action)ReleaseHeld, (Color?)new Color(0.4f, 0.26f, 0.12f, 1f));
			CreateMenuText("Aim your selected controller at a movable object.\nGrip throws while holding.", 0f, -190f, 760f, 100f, 22f, new Color(0.81f, 0.85f, 1f, 1f), bold: false);
			_statusText = CreateMenuText("", 0f, -330f, 880f, 82f, 17f, new Color(0.52f, 0.94f, 0.97f, 1f), bold: false);
		}

		private void BuildControlsPage()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			CreateMenuText("PLAYER CONTROLS", 0f, 335f, 840f, 54f, 30f, new Color(0.88f, 0.8f, 1f, 1f), bold: true);
			CreateMenuButton("GRAB HAND: " + (_leftHandPreference.Value ? "LEFT" : "RIGHT"), 0f, 230f, 620f, 66f, ToggleGrabHand);
			CreateMenuButton("MENU HAND: " + (_menuLeftHandPreference.Value ? "LEFT" : "RIGHT"), 0f, 140f, 620f, 66f, delegate
			{
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				_menuLeftHandPreference.Value = !_menuLeftHandPreference.Value;
				_menuController = default(InputDevice);
				SavePreferences();
				BuildMenuPage();
			});
			CreateMenuButton("MENU BUTTON: " + MenuButtonName(), 0f, 50f, 620f, 66f, delegate
			{
				_menuButtonPreference.Value = (_menuButtonPreference.Value + 1) % 3;
				_previousMenuButton = false;
				SavePreferences();
				BuildMenuPage();
			});
			CreateMenuButton("HOLD TRIGGER: " + (_holdToGrabPreference.Value ? "ON" : "OFF"), 0f, -40f, 620f, 66f, delegate
			{
				_holdToGrabPreference.Value = !_holdToGrabPreference.Value;
				_previousTrigger = false;
				SavePreferences();
				BuildMenuPage();
			});
			CreateMenuButton("GRAVITY WHILE HOLDING: " + (_gravityWhileHolding ? "ON" : "OFF"), 0f, -130f, 620f, 66f, delegate
			{
				_gravityWhileHolding = !_gravityWhileHolding;
				_gravityWhileHoldingPreference.Value = _gravityWhileHolding;
				if ((Object)(object)_heldBody != (Object)null)
				{
					_heldBody.useGravity = _gravityWhileHolding;
				}
				SavePreferences();
				BuildMenuPage();
			});
			CreateAdjuster("TRIGGER SENSITIVITY", _triggerThresholdPreference.Value, 2, 0.1f, 0.9f, 0.05f, -245f, delegate(float value)
			{
				_triggerThresholdPreference.Value = value;
			});
			CreateAdjuster("GRIP SENSITIVITY", _gripThresholdPreference.Value, 2, 0.1f, 0.9f, 0.05f, -340f, delegate(float value)
			{
				_gripThresholdPreference.Value = value;
			});
		}

		private void BuildPhysicsPage()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			CreateMenuText("REACH & PHYSICS", 0f, 335f, 840f, 54f, 30f, new Color(0.88f, 0.8f, 1f, 1f), bold: true);
			CreateAdjuster("GRAB RANGE (M)", _maxRangePreference.Value, 1, 1f, 20f, 1f, 230f, delegate(float value)
			{
				_maxRangePreference.Value = value;
			});
			CreateAdjuster("HOLD DISTANCE (M)", _holdDistancePreference.Value, 1, 0.5f, 10f, 0.25f, 130f, delegate(float value)
			{
				_holdDistancePreference.Value = value;
			});
			CreateAdjuster("PULL STRENGTH", _followStrengthPreference.Value, 0, 1f, 30f, 1f, 30f, delegate(float value)
			{
				_followStrengthPreference.Value = value;
			});
			CreateAdjuster("MAX PULL SPEED", _maxFollowSpeedPreference.Value, 0, 1f, 30f, 1f, -70f, delegate(float value)
			{
				_maxFollowSpeedPreference.Value = value;
			});
			CreateAdjuster("THROW SPEED", _throwSpeedPreference.Value, 0, 1f, 30f, 1f, -170f, delegate(float value)
			{
				_throwSpeedPreference.Value = value;
			});
			CreateAdjuster("GRAB PRECISION", _castRadiusPreference.Value, 2, 0.02f, 0.5f, 0.02f, -270f, delegate(float value)
			{
				_castRadiusPreference.Value = value;
			});
		}

		private void BuildStatusPage()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			CreateMenuText("LIVE DIAGNOSTICS", 0f, 335f, 840f, 54f, 30f, new Color(0.88f, 0.8f, 1f, 1f), bold: true);
			_statusText = CreateMenuText("", 0f, 130f, 880f, 250f, 21f, new Color(0.62f, 0.97f, 1f, 1f), bold: false);
			CreateMenuButton("WRITE STATUS TO LOADER LOG", 0f, -100f, 620f, 70f, ShowStatus);
			CreateMenuButton("RELEASE HELD OBJECT", 0f, -200f, 620f, 70f, (Action)ReleaseHeld, (Color?)new Color(0.4f, 0.26f, 0.12f, 1f));
		}

		private void CreateAdjuster(string label, float current, int decimals, float min, float max, float step, float y, Action<float> assign)
		{
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			CreateMenuText(label + "   " + current.ToString(decimals switch
			{
				1 => "0.0", 
				0 => "0", 
				_ => "0.00", 
			}), 0f, y, 500f, 46f, 20f, new Color(0.88f, 0.86f, 1f, 1f), bold: false);
			CreateMenuButton("-", -300f, y, 86f, 54f, (Action)delegate
			{
				assign(Mathf.Clamp(current - step, min, max));
				SavePreferences();
				BuildMenuPage();
			}, (Color?)new Color(0.15f, 0.18f, 0.36f, 1f));
			CreateMenuButton("+", 300f, y, 86f, 54f, (Action)delegate
			{
				assign(Mathf.Clamp(current + step, min, max));
				SavePreferences();
				BuildMenuPage();
			}, (Color?)new Color(0.15f, 0.18f, 0.36f, 1f));
		}

		private void CreateMenuButton(string label, float x, float y, float width, float height, Action action, Color? color = null)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0042: 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_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("NebulaMenuButton");
			val.transform.SetParent(_menuObject.transform, false);
			Image val2 = val.AddComponent<Image>();
			RectTransform component = val.GetComponent<RectTransform>();
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(0.5f, 0.5f);
			component.anchorMax = val3;
			component.anchorMin = val3;
			component.pivot = new Vector2(0.5f, 0.5f);
			component.sizeDelta = new Vector2(width, height);
			component.anchoredPosition = new Vector2(x, y);
			((Graphic)val2).color = (Color)(((??)color) ?? new Color(0.12f, 0.12f, 0.3f, 0.98f));
			TextMeshProUGUI label2 = CreateMenuText(label, x, y, width - 16f, height - 8f, 19f, Color.white, bold: true);
			MenuControl item = new MenuControl(component, val2, label2, action, (Color)(((??)color) ?? new Color(0.12f, 0.12f, 0.3f, 0.98f)));
			_menuControls.Add(item);
			_menuVisuals.Add(val);
		}

		private TextMeshProUGUI CreateMenuText(string text, float x, float y, float width, float height, float fontSize, Color color, bool bold)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0041: 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_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("NebulaMenuText");
			val.transform.SetParent(_menuObject.transform, false);
			TextMeshProUGUI obj = val.AddComponent<TextMeshProUGUI>();
			RectTransform component = val.GetComponent<RectTransform>();
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0.5f, 0.5f);
			component.anchorMax = val2;
			component.anchorMin = val2;
			component.pivot = new Vector2(0.5f, 0.5f);
			component.sizeDelta = new Vector2(width, height);
			component.anchoredPosition = new Vector2(x, y);
			((TMP_Text)obj).text = text;
			((TMP_Text)obj).fontSize = fontSize;
			((Graphic)obj).color = color;
			((TMP_Text)obj).alignment = (TextAlignmentOptions)514;
			((TMP_Text)obj).fontStyle = (FontStyles)(bold ? 1 : 0);
			((TMP_Text)obj).enableWordWrapping = true;
			((Graphic)obj).raycastTarget = false;
			_menuVisuals.Add(val);
			return obj;
		}

		private void UpdateMenuPointer()
		{
			//IL_004d: 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_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: 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_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: 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_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_menuRect == (Object)null || (Object)(object)_gameplayCamera == (Object)null)
			{
				return;
			}
			if (!TryGetMenuHandPose(out var worldPosition, out var worldRotation))
			{
				if ((Object)(object)_cursorImage != (Object)null)
				{
					((Behaviour)_cursorImage).enabled = false;
				}
				SetHoveredControl(null);
				return;
			}
			Ray val = default(Ray);
			((Ray)(ref val))..ctor(worldPosition, worldRotation * Vector3.forward);
			Plane val2 = default(Plane);
			((Plane)(ref val2))..ctor(_menuObject.transform.forward, _menuObject.transform.position);
			float num = default(float);
			if (!((Plane)(ref val2)).Raycast(val, ref num))
			{
				if ((Object)(object)_cursorImage != (Object)null)
				{
					((Behaviour)_cursorImage).enabled = false;
				}
				SetHoveredControl(null);
				return;
			}
			Vector3 point = ((Ray)(ref val)).GetPoint(num);
			Vector3 val3 = _menuObject.transform.InverseTransformPoint(point);
			_cursorRect.anchoredPosition = new Vector2(val3.x, val3.y);
			((Behaviour)_cursorImage).enabled = true;
			Vector3 val4 = _gameplayCamera.WorldToScreenPoint(point);
			MenuControl hoveredControl = null;
			for (int num2 = _menuControls.Count - 1; num2 >= 0; num2--)
			{
				MenuControl menuControl = _menuControls[num2];
				if (RectTransformUtility.RectangleContainsScreenPoint(menuControl.Rect, Vector2.op_Implicit(val4), _gameplayCamera))
				{
					hoveredControl = menuControl;
					break;
				}
			}
			SetHoveredControl(hoveredControl);
		}

		private void SetHoveredControl(MenuControl control)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			if (_hoveredControl != control)
			{
				if (_hoveredControl != null)
				{
					((Graphic)_hoveredControl.Image).color = _hoveredControl.BaseColor;
				}
				_hoveredControl = control;
				if (_hoveredControl != null)
				{
					((Graphic)_hoveredControl.Image).color = new Color(0.2f, 0.48f, 0.62f, 1f);
				}
			}
		}

		private void ActivateHoveredControl()
		{
			if (_hoveredControl != null && _hoveredControl.Action != null)
			{
				_hoveredControl.Action();
			}
		}

		private void SelectMenuPage(int page)
		{
			_menuPage = page;
			BuildMenuPage();
		}

		private void ToggleGrabHand()
		{
			//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)
			_leftHandPreference.Value = !_leftHandPreference.Value;
			_controllerNode = (XRNode)(_leftHandPreference.Value ? 4 : 5);
			_controller = default(InputDevice);
			_previousTrigger = false;
			_previousGrip = false;
			ReleaseHeld();
			SavePreferences();
			BuildMenuPage();
		}

		private string MenuButtonName()
		{
			if (_menuButtonPreference.Value == 0)
			{
				return "PRIMARY";
			}
			if (_menuButtonPreference.Value != 2)
			{
				return "SECONDARY";
			}
			return "MENU";
		}

		private void UpdateMenuStatus()
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_statusText == (Object)null) && !(Time.time < _nextStatusUpdateTime))
			{
				_nextStatusUpdateTime = Time.time + 0.15f;
				Vector3 worldPosition;
				Quaternion worldRotation;
				bool flag = TryGetHandPose(out worldPosition, out worldRotation);
				bool flag2 = ((InputDevice)(ref _controller)).isValid && ReadButton(_controller, CommonUsages.trigger, CommonUsages.triggerButton, _triggerThresholdPreference.Value);
				bool flag3 = ((InputDevice)(ref _controller)).isValid && ReadButton(_controller, CommonUsages.grip, CommonUsages.gripButton, _gripThresholdPreference.Value);
				string text = (((Object)(object)_heldBody != (Object)null) ? ((Object)_heldBody).name : "none");
				((TMP_Text)_statusText).text = "POWER: " + (_enabled ? "ONLINE" : "OFFLINE") + "\nGRAB HAND: " + (_leftHandPreference.Value ? "LEFT" : "RIGHT") + "   TRACKING: " + (((InputDevice)(ref _controller)).isValid ? "CONNECTED" : "NOT FOUND") + "\nHAND POSE: " + (flag ? "READY" : "UNAVAILABLE") + "   TRIGGER: " + (flag2 ? "PRESSED" : "RELEASED") + "   GRIP: " + (flag3 ? "PRESSED" : "RELEASED") + "\nHELD OBJECT: " + text + "\nLAST ACTION: " + _lastAction;
			}
		}

		private void DestroyMenuVisuals()
		{
			for (int i = 0; i < _menuVisuals.Count; i++)
			{
				if ((Object)(object)_menuVisuals[i] != (Object)null)
				{
					Object.Destroy((Object)(object)_menuVisuals[i]);
				}
			}
			_menuVisuals.Clear();
			_menuControls.Clear();
			_hoveredControl = null;
			_statusText = null;
		}

		private static void SavePreferences()
		{
			MelonPreferences.Save();
		}

		private void RefreshController()
		{
			//IL_0019: 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_0024: 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_0030: 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_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: 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_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: 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)
			XRNode val = (XRNode)((_leftHandPreference != null && _leftHandPreference.Value) ? 4 : 5);
			if (_controllerNode != val)
			{
				_controllerNode = val;
				_controller = default(InputDevice);
			}
			if (!((InputDevice)(ref _controller)).isValid)
			{
				_controller = InputDevices.GetDeviceAtXRNode(_controllerNode);
			}
			XRNode val2 = (XRNode)(_menuLeftHandPreference.Value ? 4 : 5);
			if (!((InputDevice)(ref _menuController)).isValid || (int)((InputDevice)(ref _menuController)).characteristics == 0)
			{
				_menuController = InputDevices.GetDeviceAtXRNode(val2);
			}
			_gameplayCamera = FindGameplayCamera();
			if ((Object)(object)_gameplayCamera != (Object)null)
			{
				_cameraTransform = ((Component)_gameplayCamera).transform;
				if ((Object)(object)_menuObject != (Object)null && (Object)(object)_menuObject.transform.parent != (Object)(object)_cameraTransform)
				{
					_menuObject.transform.SetParent(_cameraTransform, false);
					_menuObject.transform.localPosition = new Vector3(0f, 0f, 0.85f);
					_menuObject.transform.localRotation = Quaternion.identity;
				}
			}
		}

		private bool TryGetHandPose(out Vector3 worldPosition, out Quaternion worldRotation)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return TryGetDevicePose(_controller, out worldPosition, out worldRotation);
		}

		private bool TryGetMenuHandPose(out Vector3 worldPosition, out Quaternion worldRotation)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return TryGetDevicePose(_menuController, out worldPosition, out worldRotation);
		}

		private bool TryGetDevicePose(InputDevice device, out Vector3 worldPosition, out Quaternion worldRotation)
		{
			//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_000c: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: 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_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: 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)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			worldPosition = Vector3.zero;
			worldRotation = Quaternion.identity;
			if (!((InputDevice)(ref device)).isValid || (Object)(object)_cameraTransform == (Object)null)
			{
				return false;
			}
			Vector3 val = default(Vector3);
			if (!((InputDevice)(ref device)).TryGetFeatureValue(CommonUsages.devicePosition, ref val))
			{
				return false;
			}
			Quaternion val2 = default(Quaternion);
			if (!((InputDevice)(ref device)).TryGetFeatureValue(CommonUsages.deviceRotation, ref val2))
			{
				return false;
			}
			InputDevice deviceAtXRNode = InputDevices.GetDeviceAtXRNode((XRNode)3);
			Vector3 val3 = default(Vector3);
			Quaternion val4 = default(Quaternion);
			if (!((InputDevice)(ref deviceAtXRNode)).isValid || !((InputDevice)(ref deviceAtXRNode)).TryGetFeatureValue(CommonUsages.devicePosition, ref val3) || !((InputDevice)(ref deviceAtXRNode)).TryGetFeatureValue(CommonUsages.deviceRotation, ref val4))
			{
				return false;
			}
			Quaternion val5 = _cameraTransform.rotation * Quaternion.Inverse(val4);
			Vector3 val6 = _cameraTransform.position - val5 * val3;
			worldPosition = val6 + val5 * val;
			worldRotation = val5 * val2;
			return true;
		}

		private void TryGrab()
		{
			//IL_0017: 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_001d: 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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			if (!TryGetHandPose(out var worldPosition, out var worldRotation))
			{
				MelonLogger.Warning("Could not read the controller and headset tracking poses. Check controller tracking.");
				return;
			}
			Vector3 val = worldRotation * Vector3.forward;
			RaycastHit val2 = default(RaycastHit);
			if (!Physics.SphereCast(worldPosition, _castRadiusPreference.Value, val, ref val2, _maxRangePreference.Value, -5, (QueryTriggerInteraction)1))
			{
				_lastAction = "No collider in range";
				MelonLogger.Msg("No object hit.");
				return;
			}
			Rigidbody rigidbody = ((RaycastHit)(ref val2)).rigidbody;
			if ((Object)(object)rigidbody == (Object)null || rigidbody.isKinematic)
			{
				_lastAction = "Closest target is not movable";
				MelonLogger.Msg("The closest target is not a movable Rigidbody.");
				return;
			}
			_heldBody = rigidbody;
			_localGrabPoint = ((Component)rigidbody).transform.InverseTransformPoint(((RaycastHit)(ref val2)).point);
			_originalUseGravity = rigidbody.useGravity;
			rigidbody.useGravity = _gravityWhileHolding;
			_poseLostSince = -1f;
			IgnorePlayerCollisions(rigidbody);
			_lastAction = "Grabbed " + ((Object)rigidbody).name;
			MelonLogger.Msg("Grabbed: " + ((Object)rigidbody).name);
		}

		private void IgnorePlayerCollisions(Rigidbody body)
		{
			Component val;
			try
			{
				val = FindPlayerRig();
			}
			catch (Exception ex)
			{
				if (!_loggedCollisionIntegrationWarning)
				{
					_loggedCollisionIntegrationWarning = true;
					MelonLogger.Warning("Could not access BoneLib's player rig; player collision protection is unavailable. " + ex.Message);
				}
				return;
			}
			if ((Object)(object)val == (Object)null)
			{
				if (!_loggedCollisionIntegrationWarning)
				{
					_loggedCollisionIntegrationWarning = true;
					MelonLogger.Warning("BoneLib is not loaded; player collision protection is unavailable.");
				}
				return;
			}
			Collider[] array = Il2CppArrayBase<Collider>.op_Implicit(((Component)body).GetComponentsInChildren<Collider>());
			Collider[] array2 = Il2CppArrayBase<Collider>.op_Implicit(val.GetComponentsInChildren<Collider>());
			foreach (Collider val2 in array)
			{
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				foreach (Collider val3 in array2)
				{
					if (!((Object)(object)val3 == (Object)null) && !Physics.GetIgnoreCollision(val2, val3))
					{
						Physics.IgnoreCollision(val2, val3, true);
						_ignoredPlayerCollisions.Add(new IgnoredCollision(val2, val3));
					}
				}
			}
		}

		private static Component FindPlayerRig()
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			for (int i = 0; i < assemblies.Length; i++)
			{
				if (!(assemblies[i].GetName().Name != "BoneLib"))
				{
					Type type = assemblies[i].GetType("BoneLib.Player", throwOnError: false);
					if (type == null)
					{
						return null;
					}
					MethodInfo method = type.GetMethod("GetPhysicsRig", BindingFlags.Static | BindingFlags.Public, null, Type.EmptyTypes, null);
					if (method == null)
					{
						return null;
					}
					object? obj = method.Invoke(null, null);
					return (Component)((obj is Component) ? obj : null);
				}
			}
			return null;
		}

		private void UpdateHeldObject()
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: 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_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			Vector3 worldPosition;
			Quaternion worldRotation;
			if ((Object)(object)_heldBody == (Object)null || _heldBody.isKinematic)
			{
				RestoreGravityAndClear();
			}
			else if (!TryGetHandPose(out worldPosition, out worldRotation))
			{
				if (_poseLostSince < 0f)
				{
					_poseLostSince = Time.time;
				}
				else if (Time.time - _poseLostSince >= 0.5f)
				{
					ReleaseHeld();
					_lastAction = "Released after controller pose was lost";
				}
			}
			else
			{
				_poseLostSince = -1f;
				Vector3 val = worldPosition + worldRotation * Vector3.forward * _holdDistancePreference.Value;
				Vector3 val2 = ((Component)_heldBody).transform.TransformPoint(_localGrabPoint);
				Vector3 val3 = Vector3.ClampMagnitude((val - val2) * _followStrengthPreference.Value, _maxFollowSpeedPreference.Value);
				_heldBody.velocity = Vector3.Lerp(_heldBody.velocity, val3, 1f - Mathf.Exp(-10f * Time.fixedDeltaTime));
				_heldBody.angularVelocity = Vector3.Lerp(_heldBody.angularVelocity, Vector3.zero, 1f - Mathf.Exp(-4f * Time.fixedDeltaTime));
			}
		}

		private void ThrowHeld()
		{
			//IL_0021: 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_0037: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_heldBody == (Object)null))
			{
				if (TryGetHandPose(out var _, out var worldRotation))
				{
					_heldBody.velocity = worldRotation * Vector3.forward * _throwSpeedPreference.Value;
					_lastAction = "Thrown " + ((Object)_heldBody).name;
				}
				else
				{
					_lastAction = "Dropped; controller pose unavailable for throw";
					MelonLogger.Warning("Controller pose unavailable; dropping the held object without a throw.");
				}
				RestoreGravityAndClear();
				MelonLogger.Msg(_lastAction + ".");
			}
		}

		private void ReleaseHeld()
		{
			if (!((Object)(object)_heldBody == (Object)null))
			{
				RestoreGravityAndClear();
				_lastAction = "Released";
				MelonLogger.Msg("Released.");
			}
		}

		private void RestoreGravityAndClear()
		{
			//IL_0083: 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)
			if ((Object)(object)_heldBody != (Object)null)
			{
				_heldBody.useGravity = _originalUseGravity;
			}
			for (int i = 0; i < _ignoredPlayerCollisions.Count; i++)
			{
				IgnoredCollision ignoredCollision = _ignoredPlayerCollisions[i];
				if ((Object)(object)ignoredCollision.ObjectCollider != (Object)null && (Object)(object)ignoredCollision.PlayerCollider != (Object)null)
				{
					Physics.IgnoreCollision(ignoredCollision.ObjectCollider, ignoredCollision.PlayerCollider, false);
				}
			}
			_ignoredPlayerCollisions.Clear();
			_heldBody = null;
			_localGrabPoint = Vector3.zero;
			_poseLostSince = -1f;
		}

		private void SetTelekinesisEnabled(bool enabled)
		{
			_enabledPreference.Value = enabled;
			_enabled = enabled;
			_previousTrigger = false;
			_previousGrip = false;
			if (!enabled)
			{
				ReleaseHeld();
			}
			MelonPreferences.Save();
		}

		private void ShowStatus()
		{
			string text = (((Object)(object)_heldBody != (Object)null) ? ((Object)_heldBody).name : "none");
			Vector3 worldPosition;
			Quaternion worldRotation;
			bool flag = TryGetHandPose(out worldPosition, out worldRotation);
			bool flag2 = ReadButton(CommonUsages.trigger, CommonUsages.triggerButton, _triggerThresholdPreference.Value);
			bool flag3 = ReadButton(CommonUsages.grip, CommonUsages.gripButton, _gripThresholdPreference.Value);
			MelonLogger.Msg("Telekinesis " + (_enabled ? "enabled" : "disabled") + "; hand " + ((object)Unsafe.As<XRNode, XRNode>(ref _controllerNode)/*cast due to .constrained prefix*/).ToString() + "; controller " + (((InputDevice)(ref _controller)).isValid ? "connected" : "not detected") + "; hand pose " + (flag ? "available" : "unavailable") + "; trigger " + (flag2 ? "pressed" : "released") + "; grip " + (flag3 ? "pressed" : "released") + "; held object " + text + "; last action: " + _lastAction + ".");
		}

		private static Camera FindGameplayCamera()
		{
			Camera main = Camera.main;
			if ((Object)(object)main != (Object)null && ((Behaviour)main).enabled && ((Component)main).gameObject.activeInHierarchy)
			{
				return main;
			}
			Camera[] array = Il2CppArrayBase<Camera>.op_Implicit(Object.FindObjectsOfType<Camera>());
			Camera val = null;
			foreach (Camera val2 in array)
			{
				if (!((Object)(object)val2 == (Object)null) && ((Behaviour)val2).enabled && ((Component)val2).gameObject.activeInHierarchy)
				{
					if (((Component)val2).CompareTag("MainCamera"))
					{
						return val2;
					}
					if ((Object)(object)val == (Object)null || val2.depth > val.depth)
					{
						val = val2;
					}
				}
			}
			return val;
		}

		public override void OnDeinitializeMelon()
		{
			CloseMenu();
			RestoreGravityAndClear();
		}
	}
}