Decompiled source of StoneStick v3.0.5

Mods/StoneStickByNano.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using ButtonLoco;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppRUMBLE.Players.Subsystems;
using MelonLoader;
using Microsoft.CodeAnalysis;
using RumbleModUI;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(ButtonLocoMod), "Stone Stick By Nano", "3.0.5", "Nano", null)]
[assembly: MelonColor(127, 52, 235, 131)]
[assembly: MelonGame("Buckethead Entertainment", "RUMBLE")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 ButtonLoco
{
	internal static class BocoLoggor
	{
		private static bool DiagnosticsEnabled = false;

		private const float InputLogCooldownSeconds = 3f;

		private const float StateLogCooldownSeconds = 20f;

		private const float SprintLogCooldownSeconds = 8f;

		private static bool _initialized;

		private static Vector2 _lastInput = Vector2.zero;

		private static bool _hasInputSample;

		private static float _lastInputLogTime;

		private static float _lastStateLogTime;

		private static float _lastSprintLogTime;

		private static string _lastActiveMovementType = string.Empty;

		private static string _lastSuppressedType = string.Empty;

		private static bool _suppressionLogged;

		public static void Initialize(object logger)
		{
			if (!_initialized)
			{
				_initialized = true;
				if (DiagnosticsEnabled)
				{
					Log("StoneStick diagnostics ready (rate-limited).");
				}
			}
		}

		public static void OnActiveMovementTypeObserved(object activeType)
		{
			if (DiagnosticsEnabled && _initialized)
			{
				string text = activeType?.ToString() ?? "n/a";
				if (!string.Equals(text, _lastActiveMovementType, StringComparison.Ordinal))
				{
					_lastActiveMovementType = text;
					_suppressionLogged = false;
					_lastSuppressedType = string.Empty;
					Log("StoneStick state | activeMovementType=" + text);
				}
			}
		}

		public static void OnMovementSuppressed(string activeType)
		{
			if (DiagnosticsEnabled && _initialized)
			{
				string text = (string.IsNullOrWhiteSpace(activeType) ? "n/a" : activeType);
				if (!_suppressionLogged || !string.Equals(text, _lastSuppressedType, StringComparison.Ordinal))
				{
					_suppressionLogged = true;
					_lastSuppressedType = text;
					Log("StoneStick state | movement override paused (activeMovementType=" + text + ")");
				}
			}
		}

		public static void OnMovementApplied(PlayerMovement movement, Vector2 finalInput)
		{
			//IL_001f: 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)
			if (DiagnosticsEnabled && _initialized)
			{
				_suppressionLogged = false;
				_lastSuppressedType = string.Empty;
				TryLogInput(finalInput);
				TryLogStateSnapshot(movement, finalInput);
			}
		}

		public static void OnSprintScaled(Vector2 baseInput, float sprintFactor, float scale, Vector2 result)
		{
			//IL_0050: 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 (DiagnosticsEnabled && _initialized && !(((Vector2)(ref result)).sqrMagnitude < 0.0001f) && !(scale <= 1.01f) && !(Time.time - _lastSprintLogTime < 8f))
			{
				_lastSprintLogTime = Time.time;
				Log($"StoneStick sprint scale | base={baseInput} factor={sprintFactor:0.00} scale={scale:0.00} result={result}");
			}
		}

		private static void TryLogInput(Vector2 finalInput)
		{
			//IL_001a: 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_00b6: 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_00cb: Unknown result type (might be due to invalid IL or missing references)
			if (!(Time.time - _lastInputLogTime < 3f))
			{
				bool num = !_hasInputSample || Mathf.Abs(finalInput.x - _lastInput.x) > 0.1f || Mathf.Abs(finalInput.y - _lastInput.y) > 0.1f;
				bool flag = (_hasInputSample && ((Vector2)(ref _lastInput)).sqrMagnitude < 0.001f && ((Vector2)(ref finalInput)).sqrMagnitude >= 0.001f) || (_hasInputSample && ((Vector2)(ref _lastInput)).sqrMagnitude >= 0.001f && ((Vector2)(ref finalInput)).sqrMagnitude < 0.001f);
				if (num || flag)
				{
					_hasInputSample = true;
					_lastInput = finalInput;
					_lastInputLogTime = Time.time;
					Log($"StoneStick input | final={finalInput}");
				}
			}
		}

		private static void TryLogStateSnapshot(PlayerMovement movement, Vector2 finalInput)
		{
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)movement == (Object)null) && !(((Vector2)(ref finalInput)).sqrMagnitude < 0.001f) && !(Time.time - _lastStateLogTime < 20f))
			{
				_lastStateLogTime = Time.time;
				object obj = ReadPropertyValue(movement, "activeMovementType");
				object obj2 = ReadPropertyValue(movement, "currentSprintFactor");
				object obj3 = ReadPropertyValue(movement, "desiredMovementVelocity");
				object obj4 = ReadPropertyValue(movement, "maxSprintVectorLength");
				object obj5 = TryCallMethod(movement, "IsGrounded");
				object obj6 = TryCallMethod(movement, "GetSurfaceSpeedMultiplier");
				Log(string.Format("StoneStick state | input={0} active={1} grounded={2} ", finalInput, obj ?? "n/a", obj5 ?? "n/a") + string.Format("surface={0} sprintFactor={1} desiredVel={2} ", obj6 ?? "n/a", obj2 ?? "n/a", obj3 ?? "n/a") + string.Format("maxSprint={0}", obj4 ?? "n/a"));
			}
		}

		private static void Log(string message)
		{
			ButtonLocoMod instance = ButtonLocoMod.Instance;
			if (instance != null)
			{
				Instance loggerInstance = ((MelonBase)instance).LoggerInstance;
				if (loggerInstance != null)
				{
					loggerInstance.Msg(message);
				}
			}
		}

		public static void PttLog(string message)
		{
			ButtonLocoMod instance = ButtonLocoMod.Instance;
			if (instance != null)
			{
				Instance loggerInstance = ((MelonBase)instance).LoggerInstance;
				if (loggerInstance != null)
				{
					loggerInstance.Msg(message);
				}
			}
		}

		public static void PttWarn(string message)
		{
			ButtonLocoMod instance = ButtonLocoMod.Instance;
			if (instance != null)
			{
				Instance loggerInstance = ((MelonBase)instance).LoggerInstance;
				if (loggerInstance != null)
				{
					loggerInstance.Warning(message);
				}
			}
		}

		private static object ReadPropertyValue(PlayerMovement movement, string propName)
		{
			if ((Object)(object)movement == (Object)null)
			{
				return null;
			}
			try
			{
				BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
				return ((object)movement).GetType().GetProperty(propName, bindingAttr)?.GetValue(movement);
			}
			catch
			{
				return null;
			}
		}

		private static object TryCallMethod(PlayerMovement movement, string methodName)
		{
			if ((Object)(object)movement == (Object)null)
			{
				return null;
			}
			try
			{
				BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
				MethodInfo method = ((object)movement).GetType().GetMethod(methodName, bindingAttr);
				if (method == null || method.GetParameters().Length != 0)
				{
					return null;
				}
				return method.Invoke(movement, null);
			}
			catch
			{
				return null;
			}
		}
	}
	public sealed class ButtonLocoMod : MelonMod
	{
		internal static ButtonLocoMod Instance;

		private const string HarmonyId = "nano.stonestick.buttonloco";

		private static bool _patched;

		private static bool _inputFaulted;

		private static float _lastInputFaultLogTime;

		private static Camera _cachedCamera;

		private const bool EnableSprintMultiplier = true;

		private const float SprintMultiplier = 1f;

		private const bool ForceInstantSprint = false;

		private static bool _inputSystemReady;

		private static InputAction _moveAction;

		private const string ControlSettingHint = "0= X Button, 1= Y Button, 2= A Button, 3= B Button, 4=Left Trigger, 5=Right Trigger, 6=Left Grip, 7=Right Grip, 8=Left Stick Press, 9=Right Stick Press";

		private static bool _modActive = true;

		private static int _forwardButtonIndex = 0;

		private static int _leftButtonIndex = 1;

		private static int _backButtonIndex = 2;

		private static int _rightButtonIndex = 3;

		private static int _pttButtonIndex = 5;

		private static Mod _controlsModUi;

		private static ModSetting<bool> _activeSetting;

		private static ModSetting<int> _forwardSetting;

		private static ModSetting<int> _leftSetting;

		private static ModSetting<int> _backSetting;

		private static ModSetting<int> _rightSetting;

		private static ModSetting<int> _pttSetting;

		private static bool _modUiBuilt;

		private static bool _modUiAdded;

		private static bool _uiInitHooked;

		private static bool _handlingModUiSaved;

		private static float _nextUiHookTryTime;

		private static float _nextModUiRegisterTryTime;

		public override void OnInitializeMelon()
		{
			Instance = this;
			TryPatch();
		}

		public override void OnSceneWasInitialized(int buildIndex, string sceneName)
		{
			if (!_patched)
			{
				TryPatch();
			}
		}

		public override void OnLateInitializeMelon()
		{
			InitializeModUi();
			PTTREVOLT.Initialize(((MelonBase)this).LoggerInstance);
			ApplyControlSettingsFromModUi();
			BocoLoggor.Initialize(((MelonBase)this).LoggerInstance);
		}

		public override void OnUpdate()
		{
			if (!_uiInitHooked && Time.unscaledTime >= _nextUiHookTryTime)
			{
				_nextUiHookTryTime = Time.unscaledTime + 1f;
				TrySubscribeUiInitialized();
			}
			if (!_modUiAdded && _modUiBuilt && Time.unscaledTime >= _nextModUiRegisterTryTime)
			{
				_nextModUiRegisterTryTime = Time.unscaledTime + 1f;
				TryRegisterModUi();
			}
		}

		public override void OnLateUpdate()
		{
			PTTREVOLT.OnUpdate();
		}

		private void TryPatch()
		{
			//IL_0036: 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_005a: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(typeof(PlayerMovement), "Move", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				((MelonBase)this).LoggerInstance.Error("PlayerMovement.Move not found.");
				return;
			}
			new Harmony("nano.stonestick.buttonloco").Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(ButtonLocoMod), "PlayerMovement_Move_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_patched = true;
			((MelonBase)this).LoggerInstance.Msg("Stone Stick: patched PlayerMovement.Move");
		}

		private static void PlayerMovement_Move_Prefix(PlayerMovement __instance, ref Vector2 __0)
		{
			//IL_008d: 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_001a: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			if (Instance == null || (Object)(object)__instance == (Object)null)
			{
				return;
			}
			if (_inputFaulted)
			{
				__0 = Vector2.zero;
			}
			else
			{
				if (!_modActive || !Instance.ShouldOverrideMovement(__instance))
				{
					return;
				}
				try
				{
					__0 = Instance.GetButtonMovementVector(__instance);
				}
				catch (Exception arg)
				{
					_inputFaulted = true;
					if (Time.time - _lastInputFaultLogTime > 5f)
					{
						_lastInputFaultLogTime = Time.time;
						((MelonBase)Instance).LoggerInstance.Error($"Stone Stick input disabled due to exception: {arg}");
					}
					__0 = Vector2.zero;
				}
			}
		}

		private Vector2 GetButtonMovementVector(PlayerMovement movement)
		{
			//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_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_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_0026: 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_002f: 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)
			Vector2 val = ReadMoveInput();
			if (((Vector2)(ref val)).sqrMagnitude > 1f)
			{
				((Vector2)(ref val)).Normalize();
			}
			Vector2 input = val;
			val = ApplySprintMultiplier(movement, input);
			TrySetLatestSprintingHeadingVector(movement, input);
			BocoLoggor.OnMovementApplied(movement, val);
			return val;
		}

		private bool ShouldOverrideMovement(PlayerMovement movement)
		{
			object obj = ReadPropertyValue(movement, "activeMovementType");
			BocoLoggor.OnActiveMovementTypeObserved(obj);
			if (obj == null)
			{
				return true;
			}
			string text = obj.ToString();
			if (!string.Equals(text, "Normal", StringComparison.OrdinalIgnoreCase))
			{
				BocoLoggor.OnMovementSuppressed(text);
				return false;
			}
			return true;
		}

		private static object ReadPropertyValue(PlayerMovement movement, string propName)
		{
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
			PropertyInfo property = ((object)movement).GetType().GetProperty(propName, bindingAttr);
			if (property == null)
			{
				return null;
			}
			try
			{
				return property.GetValue(movement);
			}
			catch
			{
				return null;
			}
		}

		private Vector2 ReadMoveInput()
		{
			//IL_0031: 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_0037: Unknown result type (might be due to invalid IL or missing references)
			if (!_inputSystemReady)
			{
				TrySetupInputSystem();
			}
			if (_inputSystemReady && _moveAction != null)
			{
				try
				{
					return _moveAction.ReadValue<Vector2>();
				}
				catch
				{
					_inputSystemReady = false;
				}
			}
			return Vector2.zero;
		}

		private void TrySetupInputSystem()
		{
			if (_inputSystemReady)
			{
				return;
			}
			try
			{
				RebuildMoveAction();
			}
			catch (Exception ex)
			{
				_inputSystemReady = false;
				((MelonBase)this).LoggerInstance.Warning("Stone Stick input system init failed: " + ex.Message);
			}
		}

		private void RebuildMoveAction()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			if (_moveAction != null)
			{
				_moveAction.Disable();
				_moveAction.Dispose();
				_moveAction = null;
			}
			_moveAction = new InputAction("StoneStickMove", (InputActionType)0, (string)null, (string)null, (string)null, "Vector2");
			InputActionSetupExtensions.AddCompositeBinding(_moveAction, "2DVector", (string)null, (string)null).With("Up", GetBindingPathForButtonIndex(_forwardButtonIndex), (string)null, (string)null).With("Left", GetBindingPathForButtonIndex(_leftButtonIndex), (string)null, (string)null)
				.With("Down", GetBindingPathForButtonIndex(_backButtonIndex), (string)null, (string)null)
				.With("Right", GetBindingPathForButtonIndex(_rightButtonIndex), (string)null, (string)null);
			_moveAction.Enable();
			_inputSystemReady = true;
		}

		private static string GetBindingPathForButtonIndex(int index)
		{
			return ClampButtonIndex(index) switch
			{
				0 => "<XRController>{LeftHand}/primaryButton", 
				1 => "<XRController>{LeftHand}/secondaryButton", 
				2 => "<XRController>{RightHand}/primaryButton", 
				3 => "<XRController>{RightHand}/secondaryButton", 
				4 => "<XRController>{LeftHand}/triggerButton", 
				5 => "<XRController>{RightHand}/triggerButton", 
				6 => "<XRController>{LeftHand}/gripPressed", 
				7 => "<XRController>{RightHand}/gripPressed", 
				8 => "<XRController>{LeftHand}/thumbstickClicked", 
				9 => "<XRController>{RightHand}/thumbstickClicked", 
				_ => "<XRController>{LeftHand}/primaryButton", 
			};
		}

		private static int ClampButtonIndex(int index)
		{
			if (index < 0)
			{
				return 0;
			}
			if (index > 9)
			{
				return 9;
			}
			return index;
		}

		private void InitializeModUi()
		{
			//IL_000e: 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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			//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_004a: Expected O, but got Unknown
			if (!_modUiBuilt)
			{
				_modUiBuilt = true;
				_controlsModUi = new Mod
				{
					ModName = "Stone Stick By Nano",
					ModVersion = "3.0.5"
				};
				_controlsModUi.SetFolder("StoneStickByNano");
				Tags val = new Tags
				{
					DoNotSave = false
				};
				_activeSetting = _controlsModUi.AddToList("Active", _modActive, 0, "Enable/disable Stone Stick remaps.", val);
				_forwardSetting = _controlsModUi.AddToList("Straight", _forwardButtonIndex, "0= X Button, 1= Y Button, 2= A Button, 3= B Button, 4=Left Trigger, 5=Right Trigger, 6=Left Grip, 7=Right Grip, 8=Left Stick Press, 9=Right Stick Press", val);
				_leftSetting = _controlsModUi.AddToList("Left", _leftButtonIndex, "0= X Button, 1= Y Button, 2= A Button, 3= B Button, 4=Left Trigger, 5=Right Trigger, 6=Left Grip, 7=Right Grip, 8=Left Stick Press, 9=Right Stick Press", val);
				_rightSetting = _controlsModUi.AddToList("Right", _rightButtonIndex, "0= X Button, 1= Y Button, 2= A Button, 3= B Button, 4=Left Trigger, 5=Right Trigger, 6=Left Grip, 7=Right Grip, 8=Left Stick Press, 9=Right Stick Press", val);
				_backSetting = _controlsModUi.AddToList("Back", _backButtonIndex, "0= X Button, 1= Y Button, 2= A Button, 3= B Button, 4=Left Trigger, 5=Right Trigger, 6=Left Grip, 7=Right Grip, 8=Left Stick Press, 9=Right Stick Press", val);
				_pttSetting = _controlsModUi.AddToList("Push-To-Talk Button", _pttButtonIndex, "0= X Button, 1= Y Button, 2= A Button, 3= B Button, 4=Left Trigger, 5=Right Trigger, 6=Left Grip, 7=Right Grip, 8=Left Stick Press, 9=Right Stick Press", val);
				_controlsModUi.GetFromFile();
				_controlsModUi.ModSaved -= OnModUiSaved;
				_controlsModUi.ModSaved += OnModUiSaved;
				TrySubscribeUiInitialized();
				TryRegisterModUi();
			}
		}

		private static void TrySubscribeUiInitialized()
		{
			if (_uiInitHooked || UI.instance == null)
			{
				return;
			}
			try
			{
				UI.instance.UI_Initialized -= OnModUiInitialized;
				UI.instance.UI_Initialized += OnModUiInitialized;
				_uiInitHooked = true;
			}
			catch
			{
				_uiInitHooked = false;
			}
		}

		private static void OnModUiInitialized()
		{
			TryRegisterModUi();
		}

		private static void TryRegisterModUi()
		{
			if (_modUiAdded || !_modUiBuilt || _controlsModUi == null || UI.instance == null)
			{
				return;
			}
			bool flag = false;
			try
			{
				flag = UI.instance.GetInit();
			}
			catch
			{
				flag = false;
			}
			if (!flag)
			{
				return;
			}
			try
			{
				UI.instance.AddMod(_controlsModUi);
				_modUiAdded = true;
			}
			catch
			{
			}
		}

		private static void OnModUiSaved()
		{
			if (_handlingModUiSaved)
			{
				return;
			}
			_handlingModUiSaved = true;
			try
			{
				TryCommitPendingInputAndResave();
			}
			catch
			{
			}
			finally
			{
				_handlingModUiSaved = false;
			}
			Instance?.ApplyControlSettingsFromModUi();
		}

		private static void TryCommitPendingInputAndResave()
		{
			if (_controlsModUi == null || UI.instance == null)
			{
				return;
			}
			try
			{
				if (!UI.instance.IsUIVisible() || !UI.instance.IsModSelected(_controlsModUi.ModName))
				{
					return;
				}
			}
			catch
			{
				return;
			}
			string text = null;
			foreach (ModSetting setting in _controlsModUi.Settings)
			{
				try
				{
					if (UI.instance.IsOptionSelected(setting.Name))
					{
						text = setting.Name;
						break;
					}
				}
				catch
				{
					return;
				}
			}
			if (!string.IsNullOrWhiteSpace(text))
			{
				string text2 = ReadCurrentModUiInputText();
				if (!string.IsNullOrWhiteSpace(text2) && _controlsModUi.ChangeValue(text, text2.Trim()))
				{
					_controlsModUi.SaveModData("Created by: ModUI 2.1.2");
				}
			}
		}

		private static string ReadCurrentModUiInputText()
		{
			if (UI.instance == null)
			{
				return string.Empty;
			}
			try
			{
				BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.NonPublic;
				object obj = ((object)UI.instance).GetType().GetField("UI_InputField", bindingAttr)?.GetValue(UI.instance);
				if (obj == null)
				{
					return string.Empty;
				}
				Type type = obj.GetType();
				PropertyInfo property = type.GetProperty("text", BindingFlags.Instance | BindingFlags.Public);
				if (property != null)
				{
					string text = property.GetValue(obj)?.ToString();
					if (!string.IsNullOrWhiteSpace(text))
					{
						return text;
					}
				}
				object? obj2 = type.GetProperty("gameObject", BindingFlags.Instance | BindingFlags.Public)?.GetValue(obj);
				GameObject val = (GameObject)((obj2 is GameObject) ? obj2 : null);
				if ((Object)(object)val == (Object)null)
				{
					return string.Empty;
				}
				Component component = val.GetComponent("TMP_InputField");
				if ((Object)(object)component == (Object)null)
				{
					return string.Empty;
				}
				return ((object)component).GetType().GetProperty("text", BindingFlags.Instance | BindingFlags.Public)?.GetValue(component)?.ToString() ?? string.Empty;
			}
			catch
			{
				return string.Empty;
			}
		}

		private void ApplyControlSettingsFromModUi()
		{
			_modActive = ReadBoolSetting(_activeSetting, _modActive);
			_forwardButtonIndex = ReadButtonSetting(_forwardSetting, _forwardButtonIndex);
			_leftButtonIndex = ReadButtonSetting(_leftSetting, _leftButtonIndex);
			_backButtonIndex = ReadButtonSetting(_backSetting, _backButtonIndex);
			_rightButtonIndex = ReadButtonSetting(_rightSetting, _rightButtonIndex);
			_pttButtonIndex = ReadButtonSetting(_pttSetting, _pttButtonIndex);
			PTTREVOLT.SetFeatureActive(_modActive);
			PTTREVOLT.SetPushToTalkBindingPath(GetBindingPathForButtonIndex(_pttButtonIndex));
			if (!_modActive)
			{
				if (_moveAction != null)
				{
					_moveAction.Disable();
					_moveAction.Dispose();
					_moveAction = null;
				}
				_inputSystemReady = false;
				return;
			}
			try
			{
				RebuildMoveAction();
			}
			catch (Exception ex)
			{
				_inputSystemReady = false;
				((MelonBase)this).LoggerInstance.Warning("Stone Stick failed to rebuild bindings: " + ex.Message);
			}
		}

		private static int ReadButtonSetting(ModSetting<int> setting, int fallback)
		{
			if (setting == null)
			{
				return ClampButtonIndex(fallback);
			}
			try
			{
				object savedValue = ((ModSetting)setting).SavedValue;
				if (savedValue is int index)
				{
					return ClampButtonIndex(index);
				}
				if (savedValue is float num)
				{
					return ClampButtonIndex(Mathf.RoundToInt(num));
				}
				if (savedValue is double a)
				{
					return ClampButtonIndex((int)Math.Round(a));
				}
				if (savedValue != null && int.TryParse(savedValue.ToString(), out var result))
				{
					return ClampButtonIndex(result);
				}
			}
			catch
			{
			}
			return ClampButtonIndex(fallback);
		}

		private static bool ReadBoolSetting(ModSetting<bool> setting, bool fallback)
		{
			if (setting == null)
			{
				return fallback;
			}
			try
			{
				object savedValue = ((ModSetting)setting).SavedValue;
				if (savedValue is bool result)
				{
					return result;
				}
				if (savedValue is int num)
				{
					return num != 0;
				}
				if (savedValue is float num2)
				{
					return !Mathf.Approximately(num2, 0f);
				}
				if (savedValue != null && bool.TryParse(savedValue.ToString(), out var result2))
				{
					return result2;
				}
			}
			catch
			{
			}
			return fallback;
		}

		private Vector2 ApplySprintMultiplier(PlayerMovement movement, Vector2 input)
		{
			//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_0017: 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_0097: 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_009f: 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_00a5: 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_0028: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)movement == (Object)null || ((Vector2)(ref input)).sqrMagnitude < 0.0001f)
			{
				return input;
			}
			object obj = ReadPropertyValue(movement, "currentSprintFactor");
			if (obj == null)
			{
				return input;
			}
			if (ReadPropertyValue(movement, "sprintingPoseSet") == null)
			{
				return input;
			}
			float num;
			try
			{
				num = Convert.ToSingle(obj);
			}
			catch
			{
				return input;
			}
			if (num <= 1f)
			{
				return input;
			}
			float num2 = 1f;
			object obj3 = ReadPropertyValue(movement, "maxSprintVectorLength");
			if (obj3 != null)
			{
				try
				{
					num2 = Mathf.Max(1f, Convert.ToSingle(obj3));
				}
				catch
				{
					num2 = 1f;
				}
			}
			float num3 = Mathf.Min(num, num2);
			num3 *= 1f;
			Vector2 result = input * num3;
			BocoLoggor.OnSprintScaled(input, num, num3, result);
			return result;
		}

		private static void TrySetLatestSprintingHeadingVector(PlayerMovement movement, Vector2 input)
		{
			//IL_0053: 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_005f: 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_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: 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_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)movement == (Object)null || ((Vector2)(ref input)).sqrMagnitude < 0.0001f)
			{
				return;
			}
			float num;
			try
			{
				object obj = ReadPropertyValue(movement, "currentSprintFactor");
				if (obj == null)
				{
					return;
				}
				num = Convert.ToSingle(obj);
			}
			catch
			{
				return;
			}
			if (num <= 0f || !TryGetHeadingRotation(movement, out var headingRotation))
			{
				return;
			}
			Vector3 val = headingRotation * new Vector3(input.x, 0f, input.y);
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
			PropertyInfo property = ((object)movement).GetType().GetProperty("latestSprintingHeadingVector", bindingAttr);
			if (property == null || !property.CanWrite)
			{
				return;
			}
			try
			{
				if (property.PropertyType == typeof(Vector3))
				{
					property.SetValue(movement, val);
				}
				else if (property.PropertyType == typeof(Vector2))
				{
					property.SetValue(movement, (object)new Vector2(val.x, val.z));
				}
			}
			catch
			{
			}
		}

		private static bool TryGetHeadingRotation(PlayerMovement movement, out Quaternion headingRotation)
		{
			//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_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_002e: 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_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)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//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)
			headingRotation = Quaternion.identity;
			Camera camera = GetCamera();
			if ((Object)(object)camera != (Object)null)
			{
				Quaternion rotation = ((Component)camera).transform.rotation;
				headingRotation = Quaternion.Euler(0f, ((Quaternion)(ref rotation)).eulerAngles.y, 0f);
				return true;
			}
			if ((Object)(object)movement != (Object)null && (Object)(object)((Component)movement).transform != (Object)null)
			{
				Quaternion rotation2 = ((Component)movement).transform.rotation;
				headingRotation = Quaternion.Euler(0f, ((Quaternion)(ref rotation2)).eulerAngles.y, 0f);
				return true;
			}
			return false;
		}

		private static Camera GetCamera()
		{
			if ((Object)(object)_cachedCamera != (Object)null && ((Behaviour)_cachedCamera).enabled && ((Component)_cachedCamera).gameObject.activeInHierarchy)
			{
				return _cachedCamera;
			}
			Camera main = Camera.main;
			if ((Object)(object)main != (Object)null && ((Behaviour)main).enabled && ((Component)main).gameObject.activeInHierarchy)
			{
				_cachedCamera = main;
				return _cachedCamera;
			}
			int allCamerasCount = Camera.allCamerasCount;
			if (allCamerasCount <= 0)
			{
				return null;
			}
			Camera[] array = (Camera[])(object)new Camera[allCamerasCount];
			int allCameras = Camera.GetAllCameras(Il2CppReferenceArray<Camera>.op_Implicit(array));
			for (int i = 0; i < allCameras; i++)
			{
				Camera val = array[i];
				if (!((Object)(object)val == (Object)null) && ((Behaviour)val).enabled && ((Component)val).gameObject.activeInHierarchy && val.stereoEnabled)
				{
					_cachedCamera = val;
					return _cachedCamera;
				}
			}
			_cachedCamera = array[0];
			return _cachedCamera;
		}
	}
	internal static class PTTREVOLT
	{
		private sealed class VoiceTarget
		{
			public object Instance;

			public string TypeName;

			public PropertyInfo TransmitEnabledProperty;

			public FieldInfo TransmitEnabledField;

			public PropertyInfo RecordingEnabledProperty;

			public FieldInfo RecordingEnabledField;
		}

		private static readonly BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

		private static Instance _logger;

		private static bool _initialized;

		private static InputAction _triggerButtonAction;

		private static InputAction _triggerAxisAction;

		private static bool _inputReady;

		private static string _pttBindingPath = "<XRController>{RightHand}/triggerButton";

		private static bool _featureActive = true;

		private static float _nextRecorderRefreshTime;

		private static float _nextMicModeRefreshTime;

		private static bool _hasResolvedMicMode;

		private static bool _isPushToTalkMode;

		private static bool _loggedMicModeFailure;

		private static bool _loggedMicModeValue;

		private static readonly List<VoiceTarget> _voiceTargets = new List<VoiceTarget>(8);

		private static int _lastVoiceTargetCount = -1;

		private static float _lastVoiceDiscoveryErrorLogTime;

		private static Type _playerVoiceSystemType;

		private static PropertyInfo _playerVoiceRecorderProperty;

		private static FieldInfo _playerVoiceRecorderField;

		private static Type _recorderType;

		private static Type _punVoiceClientType;

		private static PropertyInfo _punVoiceClientInstanceProperty;

		private static FieldInfo _punVoiceClientInstanceField;

		private static PropertyInfo _voiceConnectionPrimaryRecorderProperty;

		private static FieldInfo _voiceConnectionPrimaryRecorderField;

		private static PropertyInfo _voiceConnectionRecordersProperty;

		private static FieldInfo _voiceConnectionRecordersField;

		private static bool _isInVoiceSearchScene;

		private static float _nextNativeRemapAttemptTime;

		private static bool _nativePttRemapApplied;

		private static Type _inputManagerType;

		private static PropertyInfo _pushToTalkInputActionProperty;

		private static PropertyInfo _pushToTalkActionNameProperty;

		private static InputAction _nativeRemappedPushToTalkAction;

		private static object _originalPushToTalkAction;

		private static string _originalPushToTalkActionName;

		private static bool _hasCapturedOriginalPushToTalkAction;

		internal static void Initialize(Instance logger)
		{
			if (!_initialized)
			{
				_initialized = true;
				_logger = logger;
				EnsureInput();
			}
		}

		internal static void SetPushToTalkBindingPath(string bindingPath)
		{
			if (!string.IsNullOrWhiteSpace(bindingPath) && !string.Equals(_pttBindingPath, bindingPath, StringComparison.Ordinal))
			{
				_pttBindingPath = bindingPath;
				_nativePttRemapApplied = false;
				_nextNativeRemapAttemptTime = 0f;
				if (_nativeRemappedPushToTalkAction != null)
				{
					_nativeRemappedPushToTalkAction.Disable();
					_nativeRemappedPushToTalkAction.Dispose();
					_nativeRemappedPushToTalkAction = null;
				}
				_inputReady = false;
				if (_triggerButtonAction != null)
				{
					_triggerButtonAction.Disable();
					_triggerButtonAction.Dispose();
					_triggerButtonAction = null;
				}
				if (_triggerAxisAction != null)
				{
					_triggerAxisAction.Disable();
					_triggerAxisAction.Dispose();
					_triggerAxisAction = null;
				}
			}
		}

		internal static void SetFeatureActive(bool isActive)
		{
			if (_featureActive != isActive)
			{
				_featureActive = isActive;
				_nativePttRemapApplied = false;
				_nextNativeRemapAttemptTime = 0f;
				if (_nativeRemappedPushToTalkAction != null)
				{
					_nativeRemappedPushToTalkAction.Disable();
					_nativeRemappedPushToTalkAction.Dispose();
					_nativeRemappedPushToTalkAction = null;
				}
				if (!_featureActive)
				{
					RestoreNativePushToTalkAction();
					_voiceTargets.Clear();
					_lastVoiceTargetCount = -1;
				}
			}
		}

		internal static void OnUpdate()
		{
			if (!_initialized || !_featureActive)
			{
				return;
			}
			EnsureInput();
			if (UpdateVoiceSceneGate() && !EnsureNativePushToTalkRemap())
			{
				if (Time.unscaledTime >= _nextRecorderRefreshTime)
				{
					_nextRecorderRefreshTime = Time.unscaledTime + 1f;
					RefreshVoiceTargets();
				}
				if (_voiceTargets.Count != 0 && IsGamePushToTalkEnabled())
				{
					ApplyTransmitState(IsRightTriggerPressed());
				}
			}
		}

		private static bool UpdateVoiceSceneGate()
		{
			bool flag = IsGymSceneLoaded();
			if (flag != _isInVoiceSearchScene)
			{
				_isInVoiceSearchScene = flag;
				_nextRecorderRefreshTime = 0f;
				_nextMicModeRefreshTime = 0f;
				_hasResolvedMicMode = false;
				_loggedMicModeFailure = false;
				_loggedMicModeValue = false;
				if (_isInVoiceSearchScene)
				{
					_nativePttRemapApplied = false;
					_nextNativeRemapAttemptTime = 0f;
					Instance logger = _logger;
					if (logger != null)
					{
						logger.Msg("PTTREVOLT: Gym scene detected, starting voice search.");
					}
				}
				else
				{
					_voiceTargets.Clear();
					_lastVoiceTargetCount = -1;
					_nativePttRemapApplied = false;
					Instance logger2 = _logger;
					if (logger2 != null)
					{
						logger2.Msg("PTTREVOLT: outside Gym, voice search paused.");
					}
				}
			}
			return _isInVoiceSearchScene;
		}

		private static bool EnsureNativePushToTalkRemap()
		{
			if (_nativePttRemapApplied)
			{
				return true;
			}
			if (Time.unscaledTime < _nextNativeRemapAttemptTime)
			{
				return false;
			}
			_nextNativeRemapAttemptTime = Time.unscaledTime + 1f;
			try
			{
				ResolveInputManagerBindings();
				if (_inputManagerType == null || _pushToTalkInputActionProperty == null || !_pushToTalkInputActionProperty.CanWrite)
				{
					return false;
				}
				object obj = TryGetInputManagerInstance();
				if (obj == null)
				{
					return false;
				}
				if (_nativeRemappedPushToTalkAction == null)
				{
					_nativeRemappedPushToTalkAction = CreateNativeRemappedPushToTalkAction();
					if (_nativeRemappedPushToTalkAction == null)
					{
						return false;
					}
				}
				if (!_hasCapturedOriginalPushToTalkAction)
				{
					_originalPushToTalkAction = _pushToTalkInputActionProperty.GetValue(obj, null);
					if (_pushToTalkActionNameProperty != null && _pushToTalkActionNameProperty.CanRead)
					{
						_originalPushToTalkActionName = _pushToTalkActionNameProperty.GetValue(obj, null)?.ToString();
					}
					_hasCapturedOriginalPushToTalkAction = true;
				}
				_pushToTalkInputActionProperty.SetValue(obj, _nativeRemappedPushToTalkAction, null);
				if (_pushToTalkActionNameProperty != null && _pushToTalkActionNameProperty.CanWrite)
				{
					_pushToTalkActionNameProperty.SetValue(obj, "StoneStickPTTRemap", null);
				}
				_nativePttRemapApplied = true;
				Instance logger = _logger;
				if (logger != null)
				{
					logger.Msg("PTTREVOLT: native push-to-talk action remapped to right trigger.");
				}
				return true;
			}
			catch (Exception ex)
			{
				if (Time.unscaledTime - _lastVoiceDiscoveryErrorLogTime >= 10f)
				{
					_lastVoiceDiscoveryErrorLogTime = Time.unscaledTime;
					Instance logger2 = _logger;
					if (logger2 != null)
					{
						logger2.Warning("PTTREVOLT: native PTT remap failed (" + ex.GetType().Name + ": " + ex.Message + ")");
					}
				}
				return false;
			}
		}

		private static void RestoreNativePushToTalkAction()
		{
			if (!_hasCapturedOriginalPushToTalkAction)
			{
				return;
			}
			try
			{
				ResolveInputManagerBindings();
				object obj = TryGetInputManagerInstance();
				if (obj != null && !(_pushToTalkInputActionProperty == null) && _pushToTalkInputActionProperty.CanWrite)
				{
					_pushToTalkInputActionProperty.SetValue(obj, _originalPushToTalkAction, null);
					if (_pushToTalkActionNameProperty != null && _pushToTalkActionNameProperty.CanWrite)
					{
						_pushToTalkActionNameProperty.SetValue(obj, _originalPushToTalkActionName, null);
					}
				}
			}
			catch
			{
			}
		}

		private static void ResolveInputManagerBindings()
		{
			if (_inputManagerType == null)
			{
				_inputManagerType = FindType("Il2CppRUMBLE.Input.InputManager") ?? FindType("RUMBLE.Input.InputManager");
			}
			if (!(_inputManagerType == null) && !(_pushToTalkInputActionProperty != null))
			{
				_pushToTalkInputActionProperty = _inputManagerType.GetProperty("PushToTalkInputAction", Flags) ?? _inputManagerType.GetProperty("pushToTalkInputAction", Flags);
				_pushToTalkActionNameProperty = _inputManagerType.GetProperty("pushToTalkActionName", Flags) ?? _inputManagerType.GetProperty("PushToTalkActionName", Flags);
			}
		}

		private static object TryGetInputManagerInstance()
		{
			if (_inputManagerType == null)
			{
				return null;
			}
			BindingFlags bindingAttr = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy;
			PropertyInfo propertyInfo = _inputManagerType.GetProperty("Instance", bindingAttr) ?? _inputManagerType.GetProperty("instance", bindingAttr);
			if (propertyInfo != null && propertyInfo.CanRead)
			{
				try
				{
					object value = propertyInfo.GetValue(null, null);
					if (value != null)
					{
						return value;
					}
				}
				catch
				{
				}
			}
			FieldInfo fieldInfo = _inputManagerType.GetField("Instance", bindingAttr) ?? _inputManagerType.GetField("instance", bindingAttr);
			if (fieldInfo != null)
			{
				try
				{
					object value2 = fieldInfo.GetValue(null);
					if (value2 != null)
					{
						return value2;
					}
				}
				catch
				{
				}
			}
			return TryFindInputManagerFromScene();
		}

		private static object TryFindInputManagerFromScene()
		{
			if (_inputManagerType == null)
			{
				return null;
			}
			GameObject[] array;
			try
			{
				array = Il2CppArrayBase<GameObject>.op_Implicit(Resources.FindObjectsOfTypeAll<GameObject>());
			}
			catch
			{
				return null;
			}
			if (array == null || array.Length == 0)
			{
				return null;
			}
			foreach (GameObject val in array)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				Component[] array2;
				try
				{
					array2 = Il2CppArrayBase<Component>.op_Implicit(val.GetComponents<Component>());
				}
				catch
				{
					continue;
				}
				if (array2 == null || array2.Length == 0)
				{
					continue;
				}
				foreach (Component val2 in array2)
				{
					if (!((Object)(object)val2 == (Object)null))
					{
						Type type;
						try
						{
							type = ((object)val2).GetType();
						}
						catch
						{
							continue;
						}
						if (IsTypeMatch(_inputManagerType, type))
						{
							return val2;
						}
					}
				}
			}
			return null;
		}

		private static InputAction CreateNativeRemappedPushToTalkAction()
		{
			//IL_000e: 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_0021: Expected O, but got Unknown
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			try
			{
				InputAction val = new InputAction("StoneStickPTTRemap", (InputActionType)1, (string)null, (string)null, (string)null, "Button");
				InputActionSetupExtensions.AddBinding(val, _pttBindingPath, (string)null, (string)null, (string)null);
				AddTriggerAxisBindingIfNeeded(val, _pttBindingPath);
				val.Enable();
				return val;
			}
			catch (Exception ex)
			{
				Instance logger = _logger;
				if (logger != null)
				{
					logger.Warning("PTTREVOLT: failed creating native remap action: " + ex.Message);
				}
				return null;
			}
		}

		private static bool IsGymSceneLoaded()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				int sceneCount = SceneManager.sceneCount;
				for (int i = 0; i < sceneCount; i++)
				{
					Scene sceneAt = SceneManager.GetSceneAt(i);
					if (((Scene)(ref sceneAt)).IsValid() && ((Scene)(ref sceneAt)).isLoaded && (((Scene)(ref sceneAt)).name ?? string.Empty).IndexOf("Gym", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		private static bool IsGamePushToTalkEnabled()
		{
			if (Time.unscaledTime < _nextMicModeRefreshTime && _hasResolvedMicMode)
			{
				return _isPushToTalkMode;
			}
			_nextMicModeRefreshTime = Time.unscaledTime + 1.5f;
			_hasResolvedMicMode = TryReadPushToTalkMode(out _isPushToTalkMode);
			if (!_hasResolvedMicMode && !_loggedMicModeFailure)
			{
				_loggedMicModeFailure = true;
				Instance logger = _logger;
				if (logger != null)
				{
					logger.Warning("PTTREVOLT: couldn't resolve VoiceConfiguration.MicMode; disabling PTT override.");
				}
			}
			else if (_hasResolvedMicMode && !_loggedMicModeValue)
			{
				_loggedMicModeValue = true;
				Instance logger2 = _logger;
				if (logger2 != null)
				{
					logger2.Msg("PTTREVOLT: game mic mode is " + (_isPushToTalkMode ? "PushToTalk" : "OpenMicrophone") + ".");
				}
			}
			if (_hasResolvedMicMode)
			{
				return _isPushToTalkMode;
			}
			return false;
		}

		private static bool TryReadPushToTalkMode(out bool isPushToTalk)
		{
			isPushToTalk = false;
			if (TryReadPushToTalkModeFromVoiceConfigurationBase(out isPushToTalk))
			{
				return true;
			}
			Type type = FindType("Il2CppRUMBLE.Managers.SettingsManager") ?? FindType("RUMBLE.Managers.SettingsManager");
			Type type2 = FindType("Il2CppRUMBLE.Serialization.VoiceConfiguration") ?? FindType("RUMBLE.Serialization.VoiceConfiguration");
			if (type == null || type2 == null)
			{
				return false;
			}
			MethodInfo method = type.GetMethod("LoadConfigFile", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			if (method == null || !method.IsGenericMethodDefinition)
			{
				return false;
			}
			MethodInfo methodInfo;
			try
			{
				methodInfo = method.MakeGenericMethod(type2);
			}
			catch
			{
				return false;
			}
			string[] array = new string[4] { "Voice", "VoiceConfiguration", "VoiceConfig", "VoiceSettings" };
			for (int i = 0; i < array.Length; i++)
			{
				object[] parameters = new object[2]
				{
					array[i],
					false
				};
				object obj2;
				try
				{
					obj2 = methodInfo.Invoke(null, parameters);
				}
				catch
				{
					continue;
				}
				if (obj2 == null)
				{
					continue;
				}
				FieldInfo field = type2.GetField("MicMode", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (!(field == null))
				{
					object value;
					try
					{
						value = field.GetValue(obj2);
					}
					catch
					{
						continue;
					}
					if (value != null)
					{
						isPushToTalk = IsPushToTalkModeName(value.ToString());
						return true;
					}
				}
			}
			return false;
		}

		private static bool TryReadPushToTalkModeFromVoiceConfigurationBase(out bool isPushToTalk)
		{
			isPushToTalk = false;
			Type type = FindType("Il2CppRUMBLE.Serialization.VoiceConfiguration") ?? FindType("RUMBLE.Serialization.VoiceConfiguration");
			if (type == null)
			{
				return false;
			}
			object obj = null;
			try
			{
				PropertyInfo property = type.GetProperty("Base", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (property != null && property.CanRead)
				{
					obj = property.GetValue(null, null);
				}
			}
			catch
			{
				obj = null;
			}
			if (obj == null)
			{
				return false;
			}
			try
			{
				PropertyInfo property2 = type.GetProperty("MicMode", Flags);
				if (property2 != null && property2.CanRead)
				{
					object value = property2.GetValue(obj, null);
					if (value != null)
					{
						isPushToTalk = IsPushToTalkModeName(value.ToString());
						return true;
					}
				}
			}
			catch
			{
			}
			try
			{
				FieldInfo field = type.GetField("MicMode", Flags);
				if (field != null)
				{
					object value2 = field.GetValue(obj);
					if (value2 != null)
					{
						isPushToTalk = IsPushToTalkModeName(value2.ToString());
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		private static bool IsPushToTalkModeName(string modeText)
		{
			if (string.IsNullOrWhiteSpace(modeText))
			{
				return false;
			}
			if (!string.Equals(modeText, "PushToTalk", StringComparison.OrdinalIgnoreCase) && !string.Equals(modeText, "PTT", StringComparison.OrdinalIgnoreCase))
			{
				return modeText.IndexOf("Push", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return true;
		}

		private static Type FindType(string fullName)
		{
			if (string.IsNullOrEmpty(fullName))
			{
				return null;
			}
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				if (assembly == null)
				{
					continue;
				}
				try
				{
					Type type = assembly.GetType(fullName, throwOnError: false, ignoreCase: false);
					if (type != null)
					{
						return type;
					}
				}
				catch
				{
				}
			}
			return null;
		}

		private static void RefreshVoiceTargets()
		{
			try
			{
				_voiceTargets.Clear();
				EnsureVoiceBindings();
				HashSet<int> seenRecorderInstanceIds = new HashSet<int>();
				CollectTargetsFromComponentScan(seenRecorderInstanceIds, out var _, out var _);
				CollectTargetsFromPunVoiceClient(seenRecorderInstanceIds, out var _);
				if (_voiceTargets.Count != _lastVoiceTargetCount)
				{
					_lastVoiceTargetCount = _voiceTargets.Count;
					Instance logger = _logger;
					if (logger != null)
					{
						logger.Msg($"PTTREVOLT: voice target count = {_voiceTargets.Count}");
					}
				}
			}
			catch (Exception ex)
			{
				_voiceTargets.Clear();
				if (Time.unscaledTime - _lastVoiceDiscoveryErrorLogTime >= 10f)
				{
					_lastVoiceDiscoveryErrorLogTime = Time.unscaledTime;
					Instance logger2 = _logger;
					if (logger2 != null)
					{
						logger2.Warning("PTTREVOLT: voice discovery failed (" + ex.GetType().Name + ": " + ex.Message + ")");
					}
				}
			}
		}

		private static void EnsureVoiceBindings()
		{
			if (_playerVoiceSystemType == null)
			{
				_playerVoiceSystemType = FindType("Il2CppRUMBLE.Players.Subsystems.PlayerVoiceSystem") ?? FindType("RUMBLE.Players.Subsystems.PlayerVoiceSystem");
			}
			if (_playerVoiceSystemType != null && _playerVoiceRecorderProperty == null && _playerVoiceRecorderField == null)
			{
				_playerVoiceRecorderProperty = _playerVoiceSystemType.GetProperty("recorder", Flags) ?? _playerVoiceSystemType.GetProperty("Recorder", Flags);
				_playerVoiceRecorderField = _playerVoiceSystemType.GetField("recorder", Flags) ?? _playerVoiceSystemType.GetField("Recorder", Flags);
			}
			if (_recorderType == null)
			{
				_recorderType = FindType("Il2CppPhoton.Voice.Unity.Recorder") ?? FindType("Photon.Voice.Unity.Recorder");
			}
			if (_punVoiceClientType == null)
			{
				_punVoiceClientType = FindType("Il2CppPhoton.Voice.PUN.PunVoiceClient") ?? FindType("Photon.Voice.PUN.PunVoiceClient");
			}
			if (_punVoiceClientType != null && _punVoiceClientInstanceProperty == null && _punVoiceClientInstanceField == null)
			{
				_punVoiceClientInstanceProperty = _punVoiceClientType.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) ?? _punVoiceClientType.GetProperty("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				_punVoiceClientInstanceField = _punVoiceClientType.GetField("Instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) ?? _punVoiceClientType.GetField("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			}
			if (_punVoiceClientType != null && _voiceConnectionPrimaryRecorderProperty == null && _voiceConnectionPrimaryRecorderField == null)
			{
				_voiceConnectionPrimaryRecorderProperty = _punVoiceClientType.GetProperty("PrimaryRecorder", Flags) ?? _punVoiceClientType.GetProperty("primaryRecorder", Flags);
				_voiceConnectionPrimaryRecorderField = _punVoiceClientType.GetField("PrimaryRecorder", Flags) ?? _punVoiceClientType.GetField("primaryRecorder", Flags);
			}
			if (_punVoiceClientType != null && _voiceConnectionRecordersProperty == null && _voiceConnectionRecordersField == null)
			{
				_voiceConnectionRecordersProperty = _punVoiceClientType.GetProperty("recorders", Flags) ?? _punVoiceClientType.GetProperty("Recorders", Flags);
				_voiceConnectionRecordersField = _punVoiceClientType.GetField("recorders", Flags) ?? _punVoiceClientType.GetField("Recorders", Flags);
			}
		}

		private static void CollectTargetsFromComponentScan(HashSet<int> seenRecorderInstanceIds, out int playerVoiceSystemCount, out int directRecorderCount)
		{
			playerVoiceSystemCount = 0;
			directRecorderCount = 0;
			if (_playerVoiceSystemType == null && _recorderType == null)
			{
				return;
			}
			Il2CppArrayBase<GameObject> val = Resources.FindObjectsOfTypeAll<GameObject>();
			if (val == null || val.Length == 0)
			{
				return;
			}
			for (int i = 0; i < val.Length; i++)
			{
				GameObject val2 = val[i];
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				Component[] array;
				try
				{
					array = Il2CppArrayBase<Component>.op_Implicit(val2.GetComponents<Component>());
				}
				catch
				{
					continue;
				}
				if (array == null || array.Length == 0)
				{
					continue;
				}
				foreach (Component val3 in array)
				{
					if ((Object)(object)val3 == (Object)null)
					{
						continue;
					}
					Type type;
					try
					{
						type = ((object)val3).GetType();
					}
					catch
					{
						continue;
					}
					if (IsTypeMatch(_recorderType, type))
					{
						directRecorderCount++;
						if (TryCreateVoiceTarget(val3, seenRecorderInstanceIds, out var target))
						{
							_voiceTargets.Add(target);
						}
					}
					if (!IsTypeMatch(_playerVoiceSystemType, type))
					{
						continue;
					}
					playerVoiceSystemCount++;
					object obj3 = null;
					try
					{
						if (_playerVoiceRecorderProperty != null)
						{
							obj3 = _playerVoiceRecorderProperty.GetValue(val3, null);
						}
						else if (_playerVoiceRecorderField != null)
						{
							obj3 = _playerVoiceRecorderField.GetValue(val3);
						}
					}
					catch
					{
						continue;
					}
					if (obj3 != null && TryCreateVoiceTarget(obj3, seenRecorderInstanceIds, out var target2))
					{
						_voiceTargets.Add(target2);
					}
				}
			}
		}

		private static bool IsTypeMatch(Type expectedType, Type actualType)
		{
			if (expectedType == null || actualType == null)
			{
				return false;
			}
			if (expectedType.IsAssignableFrom(actualType))
			{
				return true;
			}
			return string.Equals(expectedType.FullName, actualType.FullName, StringComparison.Ordinal);
		}

		private static int CollectTargetsFromPunVoiceClient(HashSet<int> seenRecorderInstanceIds, out int punRecordersFound)
		{
			punRecordersFound = 0;
			if (_punVoiceClientType == null)
			{
				return 0;
			}
			object obj = null;
			try
			{
				if (_punVoiceClientInstanceProperty != null)
				{
					obj = _punVoiceClientInstanceProperty.GetValue(null, null);
				}
				else if (_punVoiceClientInstanceField != null)
				{
					obj = _punVoiceClientInstanceField.GetValue(null);
				}
			}
			catch
			{
				return 0;
			}
			if (obj == null)
			{
				return 0;
			}
			int result = 1;
			object obj3 = null;
			try
			{
				if (_voiceConnectionPrimaryRecorderProperty != null)
				{
					obj3 = _voiceConnectionPrimaryRecorderProperty.GetValue(obj, null);
				}
				else if (_voiceConnectionPrimaryRecorderField != null)
				{
					obj3 = _voiceConnectionPrimaryRecorderField.GetValue(obj);
				}
			}
			catch
			{
			}
			if (obj3 == null)
			{
				object listObject = null;
				try
				{
					if (_voiceConnectionRecordersProperty != null)
					{
						listObject = _voiceConnectionRecordersProperty.GetValue(obj, null);
					}
					else if (_voiceConnectionRecordersField != null)
					{
						listObject = _voiceConnectionRecordersField.GetValue(obj);
					}
				}
				catch
				{
				}
				obj3 = TryGetFirstListItem(listObject);
			}
			if (obj3 != null && TryCreateVoiceTarget(obj3, seenRecorderInstanceIds, out var target))
			{
				punRecordersFound = 1;
				_voiceTargets.Add(target);
			}
			return result;
		}

		private static object TryGetFirstListItem(object listObject)
		{
			if (listObject == null)
			{
				return null;
			}
			try
			{
				Type type = listObject.GetType();
				PropertyInfo property = type.GetProperty("Count", Flags);
				PropertyInfo property2 = type.GetProperty("Item", Flags);
				if (property != null && property2 != null)
				{
					object value = property.GetValue(listObject, null);
					if (((value is int num) ? num : Convert.ToInt32(value)) > 0)
					{
						return property2.GetValue(listObject, new object[1] { 0 });
					}
				}
			}
			catch
			{
			}
			try
			{
				if (!(listObject is IEnumerable enumerable))
				{
					return null;
				}
				foreach (object item in enumerable)
				{
					if (item != null)
					{
						return item;
					}
				}
			}
			catch
			{
			}
			return null;
		}

		private static bool TryCreateVoiceTarget(object candidate, HashSet<int> seenRecorderInstanceIds, out VoiceTarget target)
		{
			target = null;
			if (candidate == null)
			{
				return false;
			}
			Object val = (Object)((candidate is Object) ? candidate : null);
			if (val != (Object)null)
			{
				int instanceID = val.GetInstanceID();
				if (!seenRecorderInstanceIds.Add(instanceID))
				{
					return false;
				}
			}
			Type type;
			try
			{
				type = candidate.GetType();
			}
			catch
			{
				return false;
			}
			string text = type?.FullName ?? string.Empty;
			if (string.IsNullOrEmpty(text))
			{
				return false;
			}
			if (_recorderType != null && !IsTypeMatch(_recorderType, type))
			{
				return false;
			}
			PropertyInfo propertyInfo = type.GetProperty("TransmitEnabled", Flags) ?? type.GetProperty("transmitEnabled", Flags);
			FieldInfo fieldInfo = type.GetField("transmitEnabled", Flags) ?? type.GetField("TransmitEnabled", Flags);
			if ((!(propertyInfo != null) || !propertyInfo.CanWrite || !(propertyInfo.PropertyType == typeof(bool))) && (!(fieldInfo != null) || !(fieldInfo.FieldType == typeof(bool))))
			{
				return false;
			}
			PropertyInfo propertyInfo2 = type.GetProperty("RecordingEnabled", Flags) ?? type.GetProperty("recordingEnabled", Flags);
			if (propertyInfo2 != null && propertyInfo2.PropertyType != typeof(bool))
			{
				propertyInfo2 = null;
			}
			FieldInfo fieldInfo2 = type.GetField("recordingEnabled", Flags) ?? type.GetField("RecordingEnabled", Flags);
			if (fieldInfo2 != null && fieldInfo2.FieldType != typeof(bool))
			{
				fieldInfo2 = null;
			}
			target = new VoiceTarget
			{
				Instance = candidate,
				TypeName = text,
				TransmitEnabledProperty = propertyInfo,
				TransmitEnabledField = fieldInfo,
				RecordingEnabledProperty = propertyInfo2,
				RecordingEnabledField = fieldInfo2
			};
			return true;
		}

		private static void ApplyTransmitState(bool pressed)
		{
			for (int i = 0; i < _voiceTargets.Count; i++)
			{
				VoiceTarget voiceTarget = _voiceTargets[i];
				if (voiceTarget == null || voiceTarget.Instance == null)
				{
					continue;
				}
				try
				{
					if (voiceTarget.RecordingEnabledProperty != null && voiceTarget.RecordingEnabledProperty.CanWrite)
					{
						voiceTarget.RecordingEnabledProperty.SetValue(voiceTarget.Instance, true, null);
					}
					else if (voiceTarget.RecordingEnabledField != null)
					{
						voiceTarget.RecordingEnabledField.SetValue(voiceTarget.Instance, true);
					}
					if (voiceTarget.TransmitEnabledProperty != null && voiceTarget.TransmitEnabledProperty.CanWrite)
					{
						voiceTarget.TransmitEnabledProperty.SetValue(voiceTarget.Instance, pressed, null);
					}
					else if (voiceTarget.TransmitEnabledField != null)
					{
						voiceTarget.TransmitEnabledField.SetValue(voiceTarget.Instance, pressed);
					}
				}
				catch
				{
				}
			}
		}

		private static bool IsRightTriggerPressed()
		{
			if (!_inputReady)
			{
				return false;
			}
			try
			{
				if (_triggerButtonAction != null && _triggerButtonAction.IsPressed())
				{
					return true;
				}
				if (_triggerAxisAction != null && _triggerAxisAction.ReadValue<float>() >= 0.6f)
				{
					return true;
				}
			}
			catch
			{
				_inputReady = false;
			}
			return false;
		}

		private static void EnsureInput()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			if (_inputReady)
			{
				return;
			}
			try
			{
				_triggerButtonAction = new InputAction("StoneStickPTTButton", (InputActionType)1, (string)null, (string)null, (string)null, "Button");
				_triggerAxisAction = new InputAction("StoneStickPTTAxis", (InputActionType)0, (string)null, (string)null, (string)null, "Axis");
				InputActionSetupExtensions.AddBinding(_triggerButtonAction, _pttBindingPath, (string)null, (string)null, (string)null);
				string axisPathForTriggerBinding = GetAxisPathForTriggerBinding(_pttBindingPath);
				if (!string.IsNullOrEmpty(axisPathForTriggerBinding))
				{
					InputActionSetupExtensions.AddBinding(_triggerAxisAction, axisPathForTriggerBinding, (string)null, (string)null, (string)null);
				}
				_triggerButtonAction.Enable();
				if (!string.IsNullOrEmpty(axisPathForTriggerBinding))
				{
					_triggerAxisAction.Enable();
				}
				else
				{
					_triggerAxisAction.Disable();
				}
				_inputReady = true;
			}
			catch (Exception ex)
			{
				_inputReady = false;
				Instance logger = _logger;
				if (logger != null)
				{
					logger.Warning("PTTREVOLT input init failed: " + ex.Message);
				}
			}
		}

		private static void AddTriggerAxisBindingIfNeeded(InputAction action, string buttonPath)
		{
			string axisPathForTriggerBinding = GetAxisPathForTriggerBinding(buttonPath);
			if (!string.IsNullOrEmpty(axisPathForTriggerBinding))
			{
				InputActionSetupExtensions.AddBinding(action, axisPathForTriggerBinding, (string)null, (string)null, (string)null).WithInteraction("press(pressPoint=0.6)");
			}
		}

		private static string GetAxisPathForTriggerBinding(string buttonPath)
		{
			if (string.IsNullOrEmpty(buttonPath))
			{
				return null;
			}
			if (buttonPath.IndexOf("{LeftHand}", StringComparison.OrdinalIgnoreCase) >= 0 && (buttonPath.IndexOf("triggerButton", StringComparison.OrdinalIgnoreCase) >= 0 || buttonPath.IndexOf("triggerPressed", StringComparison.OrdinalIgnoreCase) >= 0))
			{
				return "<XRController>{LeftHand}/trigger";
			}
			if (buttonPath.IndexOf("{RightHand}", StringComparison.OrdinalIgnoreCase) >= 0 && (buttonPath.IndexOf("triggerButton", StringComparison.OrdinalIgnoreCase) >= 0 || buttonPath.IndexOf("triggerPressed", StringComparison.OrdinalIgnoreCase) >= 0))
			{
				return "<XRController>{RightHand}/trigger";
			}
			return null;
		}
	}
}