Decompiled source of Controller Support Revamped v1.0.2

BepInEx\plugins\ControllerSupport\ControllerSupport.dll

Decompiled 14 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.DualShock;
using UnityEngine.InputSystem.LowLevel;
using UnityEngine.InputSystem.Switch;
using UnityEngine.InputSystem.Utilities;
using UnityEngine.InputSystem.XInput;
using UnityEngine.TextCore;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("ControllerSupport")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.2.0")]
[assembly: AssemblyInformationalVersion("1.0.2+6bd8635c21563e73b67211474a60513b7751f487")]
[assembly: AssemblyProduct("Controller Support")]
[assembly: AssemblyTitle("ControllerSupport")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.2.0")]
[module: UnverifiableCode]
[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 ControllerSupport
{
	internal static class ColorLedPatches
	{
		internal static ControllerLedManager Led;

		internal static ConfigManager Config;

		internal static ManualLogSource Logger;

		internal static void Initialize(ControllerLedManager led, ConfigManager config, ManualLogSource logger)
		{
			Led = led;
			Config = config;
			Logger = logger;
		}

		internal static bool ShouldSyncLed()
		{
			if (Config != null && Led != null)
			{
				return Config.EnableLedSync;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(PlayerCosmetics), "SetupColorsLogic")]
	internal static class PlayerCosmeticsSetupColorsLogicLedPatch
	{
		[HarmonyPostfix]
		private static void Postfix(PlayerCosmetics __instance)
		{
			if (ColorLedPatches.ShouldSyncLed() && ControllerLedManager.IsLocalPlayerCosmetics(__instance))
			{
				ColorLedPatches.Led.SyncFromPlayer();
			}
		}
	}
	[HarmonyPatch(typeof(PlayerCosmetics), "SetupColors")]
	internal static class PlayerCosmeticsSetupColorsLedPatch
	{
		[HarmonyPostfix]
		private static void Postfix(PlayerCosmetics __instance)
		{
			if (ColorLedPatches.ShouldSyncLed() && ControllerLedManager.IsLocalPlayerCosmetics(__instance))
			{
				ColorLedPatches.Led.SyncFromPlayer();
			}
		}
	}
	[HarmonyPatch(typeof(DataDirector), "ColorSetBody")]
	internal static class DataDirectorColorSetBodyLedPatch
	{
		[HarmonyPostfix]
		private static void Postfix()
		{
			if (ColorLedPatches.ShouldSyncLed())
			{
				ColorLedPatches.Led.SyncFromPlayer();
			}
		}
	}
	[HarmonyPatch(typeof(MenuPageColor), "ConfirmButton")]
	internal static class MenuPageColorConfirmLedPatch
	{
		[HarmonyPostfix]
		private static void Postfix()
		{
			if (ColorLedPatches.ShouldSyncLed())
			{
				ColorLedPatches.Led.SyncFromPlayer();
			}
		}
	}
	[HarmonyPatch(typeof(PlayerAvatar), "Awake")]
	internal static class PlayerAvatarAwakeLedPatch
	{
		[HarmonyPostfix]
		private static void Postfix(PlayerAvatar __instance)
		{
			if (ColorLedPatches.ShouldSyncLed() && ControllerLedManager.IsAvatarMarkedLocal(__instance))
			{
				ColorLedPatches.Led.SyncFromPlayer();
			}
		}
	}
	[HarmonyPatch(typeof(PlayerCosmetics), "SetupColorsAllLogic")]
	internal static class PlayerCosmeticsSetupColorsAllLogicLedPatch
	{
		[HarmonyPostfix]
		private static void Postfix(PlayerCosmetics __instance)
		{
			if (ColorLedPatches.ShouldSyncLed() && ControllerLedManager.IsLocalPlayerCosmetics(__instance))
			{
				ColorLedPatches.Led.SyncFromPlayer();
			}
		}
	}
	public enum ControllerGlyphStyleOverride
	{
		Auto,
		Xbox,
		PlayStation,
		Switch,
		SteamDeck
	}
	public class ConfigManager
	{
		private ConfigFile _config;

		private ConfigEntry<float> _mouseSensitivityConfig;

		private ConfigEntry<float> _scrollSpeedConfig;

		private ConfigEntry<float> _deadZoneRadiusConfig;

		private ConfigEntry<float> _diagonalZoneSizeConfig;

		private ConfigEntry<bool> _enableTabToggleConfig;

		private ConfigEntry<bool> _enableCtrlToggleConfig;

		private ConfigEntry<bool> _enableShiftToggleConfig;

		private ConfigEntry<bool> _releaseTabOnShiftConfig;

		private ConfigEntry<bool> _releaseCtrlOnShiftConfig;

		private ConfigEntry<bool> _releaseCtrlOnAConfig;

		private ConfigEntry<bool> _autoReleaseShiftAfterWASDConfig;

		private ConfigEntry<float> _shiftReleaseDelayConfig;

		private ConfigEntry<bool> _enableLedSyncConfig;

		private ConfigEntry<bool> _enableVibrationConfig;

		private ConfigEntry<float> _vibrationIntensityConfig;

		private ConfigEntry<bool> _enableInputVibrationConfig;

		private ConfigEntry<bool> _enableDamageVibrationConfig;

		private ConfigEntry<bool> _enableItemBreakVibrationConfig;

		private ConfigEntry<bool> _enableHoldVibrationConfig;

		private ConfigEntry<bool> _enableMenuNavigationConfig;

		private ConfigEntry<float> _menuScrollSpeedConfig;

		private ConfigEntry<bool> _enableControllerGlyphsConfig;

		private ConfigEntry<string> _controllerGlyphStyleConfig;

		private ConfigEntry<bool> _debugOutputConfig;

		private ConfigEntry<bool> _devModeConfig;

		public float MouseSensitivity => _mouseSensitivityConfig.Value;

		public float ScrollSpeed => _scrollSpeedConfig.Value;

		public float DeadZoneRadius => _deadZoneRadiusConfig.Value;

		public float DiagonalZoneSize => _diagonalZoneSizeConfig.Value;

		public bool EnableTabToggle => _enableTabToggleConfig.Value;

		public bool EnableCtrlToggle => _enableCtrlToggleConfig.Value;

		public bool EnableShiftToggle => _enableShiftToggleConfig.Value;

		public bool ReleaseTabOnShift => _releaseTabOnShiftConfig.Value;

		public bool ReleaseCtrlOnShift => _releaseCtrlOnShiftConfig.Value;

		public bool ReleaseCtrlOnA => _releaseCtrlOnAConfig.Value;

		public bool AutoReleaseShiftAfterWASD => _autoReleaseShiftAfterWASDConfig.Value;

		public float ShiftReleaseDelay => _shiftReleaseDelayConfig.Value;

		public bool EnableLedSync => _enableLedSyncConfig.Value;

		public bool EnableVibration => _enableVibrationConfig.Value;

		public float VibrationIntensity => _vibrationIntensityConfig.Value;

		public bool EnableInputVibration => _enableInputVibrationConfig.Value;

		public bool EnableDamageVibration => _enableDamageVibrationConfig.Value;

		public bool EnableItemBreakVibration => _enableItemBreakVibrationConfig.Value;

		public bool EnableHoldVibration => _enableHoldVibrationConfig.Value;

		public bool EnableMenuNavigation => _enableMenuNavigationConfig.Value;

		public float MenuScrollSpeed => _menuScrollSpeedConfig.Value;

		public bool EnableControllerGlyphs => _enableControllerGlyphsConfig.Value;

		public ControllerGlyphStyleOverride ControllerGlyphStyle => ParseGlyphStyle(_controllerGlyphStyleConfig.Value);

		public bool DebugOutput => _debugOutputConfig.Value;

		public bool DevMode => _devModeConfig.Value;

		public float CurrentJoystickX { get; set; }

		public float CurrentJoystickY { get; set; }

		public float CurrentJoystickAngle { get; set; }

		public ConfigManager(ConfigFile config)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Expected O, but got Unknown
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Expected O, but got Unknown
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Expected O, but got Unknown
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Expected O, but got Unknown
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Expected O, but got Unknown
			//IL_031c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0326: Expected O, but got Unknown
			//IL_0395: Unknown result type (might be due to invalid IL or missing references)
			//IL_039f: Expected O, but got Unknown
			_config = config;
			string configFilePath = config.ConfigFilePath;
			_mouseSensitivityConfig = config.Bind<float>("Mouse Controls", "MouseSensitivity", 10f, new ConfigDescription("Sensitivity of the right stick for mouse movement. Higher values make the mouse move faster.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 1000f), Array.Empty<object>()));
			_scrollSpeedConfig = config.Bind<float>("Mouse Controls", "ScrollSpeed", 0.0021f, new ConfigDescription("Adjust the scroll speed for bumper buttons (RB/LB). Lower values result in slower scrolling, higher values in faster scrolling.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.0001f, 0.01f), Array.Empty<object>()));
			_deadZoneRadiusConfig = config.Bind<float>("Movement Controls", "DeadZoneRadius", 0.25f, new ConfigDescription("Radius of the center dead zone for the left joystick (0.0 to 1.0). Higher values require more joystick movement before keys are pressed.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			_diagonalZoneSizeConfig = config.Bind<float>("Movement Controls", "DiagonalZoneSize", 0.7071f, new ConfigDescription("Size of the diagonal zones for the left joystick (0.5 to 1.0). Higher values make diagonal movement more likely.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 1f), Array.Empty<object>()));
			_enableTabToggleConfig = config.Bind<bool>("Toggle Controls", "EnableMapToggle", true, "Enable toggle functionality for the Map key (Back button).");
			_enableCtrlToggleConfig = config.Bind<bool>("Toggle Controls", "EnableCrouchToggle", true, "Enable toggle functionality for the Crouch key (B button).");
			_enableShiftToggleConfig = config.Bind<bool>("Toggle Controls", "EnableRunToggle", false, "Enable toggle functionality for the Run key (L3 button).");
			_releaseTabOnShiftConfig = config.Bind<bool>("Key Interactions", "ReleaseMapOnRun", true, "When enabled, pressing Run will automatically release Map if active.");
			_releaseCtrlOnShiftConfig = config.Bind<bool>("Key Interactions", "ReleaseCrouchOnRun", true, "When enabled, activating Run will automatically release Crouch.");
			_releaseCtrlOnAConfig = config.Bind<bool>("Key Interactions", "ReleaseCrouchOnJump", true, "When enabled, pressing Jump will automatically release Crouch.");
			_autoReleaseShiftAfterWASDConfig = config.Bind<bool>("Key Interactions", "AutoReleaseRunAfterWASD", true, "Automatically release Run after WASD inactivity.");
			_shiftReleaseDelayConfig = config.Bind<float>("Key Interactions", "RunReleaseDelay", 0.5f, new ConfigDescription("Delay before auto-releasing Run (seconds).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), Array.Empty<object>()));
			_enableLedSyncConfig = config.Bind<bool>("Controller LED", "EnableLedSync", true, "Sync the controller LED/light bar to your player head color when Unity exposes LED control for the connected device.");
			_enableVibrationConfig = config.Bind<bool>("Vibration", "EnableVibration", true, "Enable controller vibration/rumble.");
			_vibrationIntensityConfig = config.Bind<float>("Vibration", "VibrationIntensity", 1f, new ConfigDescription("Overall vibration strength (0.0 to 1.0).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			_enableInputVibrationConfig = config.Bind<bool>("Vibration", "EnableInputVibration", true, "Rumble on controller actions such as shooting, jumping, and interacting.");
			_enableDamageVibrationConfig = config.Bind<bool>("Vibration", "EnableDamageVibration", true, "Rumble when your player takes damage.");
			_enableItemBreakVibrationConfig = config.Bind<bool>("Vibration", "EnableItemBreakVibration", true, "Rumble when an item you are holding breaks or takes impact damage.");
			_enableHoldVibrationConfig = config.Bind<bool>("Vibration", "EnableHoldVibration", true, "Subtle continuous rumble while holding an item with the grab beam.");
			_enableMenuNavigationConfig = config.Bind<bool>("Menu Navigation", "EnableMenuNavigation", true, "Navigate menus with the controller using focus-based selection (left stick/D-pad to move, A to confirm, B to go back).");
			_menuScrollSpeedConfig = config.Bind<float>("Menu Navigation", "MenuScrollSpeed", 0.0021f, new ConfigDescription("Scroll speed for LB/RB when a scrollable menu list is focused.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.0001f, 0.01f), Array.Empty<object>()));
			_enableControllerGlyphsConfig = config.Bind<bool>("Controller Glyphs", "EnableControllerGlyphs", true, "Replace keyboard/mouse prompt text with controller button glyphs when a gamepad is connected.");
			_controllerGlyphStyleConfig = config.Bind<string>("Controller Glyphs", "GlyphStyle", "Auto", new ConfigDescription("Which glyph set to use. Auto picks Xbox, PlayStation, Switch, or Steam Deck based on the connected controller.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[5] { "Auto", "Xbox", "PlayStation", "Switch", "SteamDeck" }), Array.Empty<object>()));
			_debugOutputConfig = config.Bind<bool>("Debug", "EnableDebugOutput", false, "Enable detailed debug logging.");
			_devModeConfig = config.Bind<bool>("Debug", "DevMode", false, "Enable developer tools with numpad controls.");
			InjectAboutSection(configFilePath);
		}

		private void InjectAboutSection(string configPath)
		{
			string[] collection = new string[11]
			{
				"[About]", "## Thunderstore Link.", "# Setting type: String", "# Default value: https://thunderstore.io/c/repo/p/AKASGaming/Controller_Support_Revamped/", "Thunderstore = https://thunderstore.io/c/repo/p/AKASGaming/Controller_Support_Revamped/", "", "## Github Link.", "# Setting type: String", "# Default value: https://github.com/AKASGaming/R.E.P.O.ControllerSupport", "Github = https://github.com/AKASGaming/R.E.P.O.ControllerSupport",
				""
			};
			try
			{
				if (!File.Exists(configPath))
				{
					return;
				}
				List<string> list = File.ReadAllLines(configPath).ToList();
				if (!list.Any((string l) => l.Trim().Equals("[About]", StringComparison.OrdinalIgnoreCase)))
				{
					int i;
					for (i = 0; i < list.Count && (list[i].StartsWith("##") || string.IsNullOrWhiteSpace(list[i])); i++)
					{
					}
					list.InsertRange(i, collection);
					File.WriteAllLines(configPath, list);
				}
			}
			catch (Exception)
			{
				_ = Debugger.IsAttached;
			}
		}

		public float IncreaseScrollSpeed()
		{
			float num = ScrollSpeed + 0.0001f;
			_scrollSpeedConfig.Value = num;
			return num;
		}

		public float DecreaseScrollSpeed()
		{
			float num = Math.Max(0.0001f, ScrollSpeed - 0.0001f);
			_scrollSpeedConfig.Value = num;
			return num;
		}

		public float UpdateDeadZoneRadius(float magnitude)
		{
			_deadZoneRadiusConfig.Value = magnitude;
			return magnitude;
		}

		public float UpdateDiagonalZoneSize(float angle)
		{
			_diagonalZoneSizeConfig.Value = angle;
			return angle;
		}

		private static ControllerGlyphStyleOverride ParseGlyphStyle(string value)
		{
			return value?.Trim() switch
			{
				"Xbox" => ControllerGlyphStyleOverride.Xbox, 
				"PlayStation" => ControllerGlyphStyleOverride.PlayStation, 
				"Switch" => ControllerGlyphStyleOverride.Switch, 
				"SteamDeck" => ControllerGlyphStyleOverride.SteamDeck, 
				_ => ControllerGlyphStyleOverride.Auto, 
			};
		}
	}
	internal enum ControllerGlyphStyle
	{
		Xbox,
		PlayStation,
		Switch,
		SteamDeck
	}
	internal enum ControllerGlyphButton
	{
		South,
		West,
		East,
		North,
		LeftShoulder,
		RightShoulder,
		LeftTrigger,
		RightTrigger,
		LeftStick,
		RightStick,
		LeftStickClick,
		RightStickClick,
		DpadUp,
		DpadDown,
		DpadLeft,
		DpadRight,
		Select,
		Start
	}
	internal class ControllerGlyphManager
	{
		private readonly struct LoadedGlyph
		{
			internal string SpriteName { get; }

			internal Texture2D Texture { get; }

			internal LoadedGlyph(string spriteName, Texture2D texture)
			{
				SpriteName = spriteName;
				Texture = texture;
			}
		}

		internal const string SpriteAssetName = "ControllerSupportGlyphs";

		private const string SpriteTagFormat = "<size=120%><voffset=0.2em><sprite=\"{0}\" name=\"{1}\"></size>";

		private static readonly Dictionary<ControllerGlyphButton, string> SpriteNames = new Dictionary<ControllerGlyphButton, string>
		{
			{
				ControllerGlyphButton.South,
				"btn_south"
			},
			{
				ControllerGlyphButton.West,
				"btn_west"
			},
			{
				ControllerGlyphButton.East,
				"btn_east"
			},
			{
				ControllerGlyphButton.North,
				"btn_north"
			},
			{
				ControllerGlyphButton.LeftShoulder,
				"btn_lb"
			},
			{
				ControllerGlyphButton.RightShoulder,
				"btn_rb"
			},
			{
				ControllerGlyphButton.LeftTrigger,
				"btn_lt"
			},
			{
				ControllerGlyphButton.RightTrigger,
				"btn_rt"
			},
			{
				ControllerGlyphButton.LeftStick,
				"btn_left_stick"
			},
			{
				ControllerGlyphButton.RightStick,
				"btn_right_stick"
			},
			{
				ControllerGlyphButton.LeftStickClick,
				"btn_l3"
			},
			{
				ControllerGlyphButton.RightStickClick,
				"btn_r3"
			},
			{
				ControllerGlyphButton.DpadUp,
				"btn_dpad_up"
			},
			{
				ControllerGlyphButton.DpadDown,
				"btn_dpad_down"
			},
			{
				ControllerGlyphButton.DpadLeft,
				"btn_dpad_left"
			},
			{
				ControllerGlyphButton.DpadRight,
				"btn_dpad_right"
			},
			{
				ControllerGlyphButton.Select,
				"btn_select"
			},
			{
				ControllerGlyphButton.Start,
				"btn_start"
			}
		};

		private readonly ManualLogSource _logger;

		private readonly ConfigManager _configManager;

		private readonly string _glyphRoot;

		private static readonly FieldInfo SpriteGlyphTableField = typeof(TMP_SpriteAsset).GetField("m_SpriteGlyphTable", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo SpriteCharacterTableField = typeof(TMP_SpriteAsset).GetField("m_SpriteCharacterTable", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo SpriteAssetVersionField = typeof(TMP_SpriteAsset).GetField("m_Version", BindingFlags.Instance | BindingFlags.NonPublic);

		private const string SpriteAssetVersion = "1.1.0";

		private static readonly Assembly PluginAssembly = typeof(ControllerGlyphManager).Assembly;

		private const string EmbeddedResourcePrefix = "ControllerSupport.Glyphs";

		private TMP_SpriteAsset _spriteAsset;

		private ControllerGlyphStyle _activeStyle;

		private Gamepad _activeGamepad;

		private bool _initialized;

		internal static ControllerGlyphManager Instance { get; private set; }

		internal ControllerGlyphManager(ManualLogSource logger, ConfigManager configManager, string pluginPath)
		{
			_logger = logger;
			_configManager = configManager;
			_glyphRoot = Path.Combine(Path.GetDirectoryName(pluginPath) ?? string.Empty, "glyphs");
			Instance = this;
		}

		internal void Initialize()
		{
			if (!_initialized)
			{
				if (!HasEmbeddedGlyphPack())
				{
					_logger.LogWarning((object)"No embedded controller glyphs found in ControllerSupport.dll. Rebuild the mod or place PNGs in a glyphs folder next to the DLL.");
					return;
				}
				_initialized = true;
				RefreshActiveGamepad(forceReload: true);
			}
		}

		private static bool HasEmbeddedGlyphPack()
		{
			string name = "ControllerSupport.Glyphs.XboxSeries.XboxSeriesX_A.png";
			using Stream stream = PluginAssembly.GetManifestResourceStream(name);
			return stream != null;
		}

		internal void Update()
		{
			if (_initialized && _configManager.EnableControllerGlyphs)
			{
				RefreshActiveGamepad(forceReload: false);
			}
		}

		internal bool ShouldUseGlyphs()
		{
			if (_initialized && _configManager.EnableControllerGlyphs && _activeGamepad != null)
			{
				return (Object)(object)_spriteAsset != (Object)null;
			}
			return false;
		}

		internal bool TryGetInputKeyGlyph(InputKey inputKey, KeyType keyType, MovementDirection movementDirection, out string glyphTag)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between Unknown and I4
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected I4, but got Unknown
			glyphTag = null;
			if (!ShouldUseGlyphs())
			{
				return false;
			}
			if ((int)keyType == 1)
			{
				if ((int)inputKey != 0)
				{
					return false;
				}
				switch ((int)movementDirection)
				{
				case 0:
					glyphTag = BuildTag(ControllerGlyphButton.DpadUp);
					return glyphTag != null;
				case 1:
					glyphTag = BuildTag(ControllerGlyphButton.DpadDown);
					return glyphTag != null;
				case 2:
					glyphTag = BuildTag(ControllerGlyphButton.DpadLeft);
					return glyphTag != null;
				case 3:
					glyphTag = BuildTag(ControllerGlyphButton.DpadRight);
					return glyphTag != null;
				default:
					return false;
				}
			}
			ControllerGlyphButton? controllerGlyphButton = MapInputKey(inputKey);
			if (!controllerGlyphButton.HasValue)
			{
				return false;
			}
			glyphTag = BuildTag(controllerGlyphButton.Value);
			return glyphTag != null;
		}

		internal bool TryGetMouseGlyph(string originalDisplay, out string glyphTag)
		{
			glyphTag = null;
			if (!ShouldUseGlyphs() || string.IsNullOrEmpty(originalDisplay))
			{
				return false;
			}
			string text = originalDisplay.Trim().ToUpperInvariant();
			ControllerGlyphButton? controllerGlyphButton = null;
			if (text.Contains("MOUSE LEFT") || text.Contains("LEFT BUTTON"))
			{
				controllerGlyphButton = ControllerGlyphButton.RightTrigger;
			}
			else if (text.Contains("MOUSE RIGHT") || text.Contains("RIGHT BUTTON"))
			{
				controllerGlyphButton = ControllerGlyphButton.LeftTrigger;
			}
			else if (text.Contains("MOUSE SCROLL") || text.Contains("SCROLL"))
			{
				controllerGlyphButton = ControllerGlyphButton.RightShoulder;
			}
			if (!controllerGlyphButton.HasValue)
			{
				return false;
			}
			glyphTag = BuildTag(controllerGlyphButton.Value);
			return glyphTag != null;
		}

		private void RefreshActiveGamepad(bool forceReload)
		{
			Gamepad val = GamepadHelper.FindActiveGamepad();
			if (!forceReload && val == _activeGamepad)
			{
				return;
			}
			_activeGamepad = val;
			if (_activeGamepad == null)
			{
				_spriteAsset = null;
				return;
			}
			ControllerGlyphStyle controllerGlyphStyle = ResolveStyle(_activeGamepad);
			if (!forceReload && controllerGlyphStyle == _activeStyle && (Object)(object)_spriteAsset != (Object)null)
			{
				return;
			}
			if (!TryBuildSpriteAsset(controllerGlyphStyle, out var spriteAsset))
			{
				_spriteAsset = null;
				return;
			}
			if ((Object)(object)_spriteAsset != (Object)null)
			{
				Object.Destroy((Object)(object)_spriteAsset);
			}
			_activeStyle = controllerGlyphStyle;
			_spriteAsset = spriteAsset;
			MaterialReferenceManager.AddSpriteAsset(_spriteAsset);
			_logger.LogInfo((object)$"Controller glyphs loaded for {_activeStyle} ({((InputControl)_activeGamepad).displayName}).");
		}

		private ControllerGlyphStyle ResolveStyle(Gamepad gamepad)
		{
			switch (_configManager.ControllerGlyphStyle)
			{
			case ControllerGlyphStyleOverride.Xbox:
				return ControllerGlyphStyle.Xbox;
			case ControllerGlyphStyleOverride.PlayStation:
				return ControllerGlyphStyle.PlayStation;
			case ControllerGlyphStyleOverride.Switch:
				return ControllerGlyphStyle.Switch;
			case ControllerGlyphStyleOverride.SteamDeck:
				return ControllerGlyphStyle.SteamDeck;
			default:
			{
				if (gamepad is DualShockGamepad)
				{
					return ControllerGlyphStyle.PlayStation;
				}
				if (gamepad is SwitchProControllerHID)
				{
					return ControllerGlyphStyle.Switch;
				}
				string obj = ((InputControl)gamepad).displayName ?? string.Empty;
				string text = ((InputControl)gamepad).layout ?? string.Empty;
				string text2 = (obj + " " + text).ToLowerInvariant();
				if (text2.Contains("steam deck") || text2.Contains("steam controller"))
				{
					return ControllerGlyphStyle.SteamDeck;
				}
				if (text2.Contains("switch") || text2.Contains("nintendo"))
				{
					return ControllerGlyphStyle.Switch;
				}
				if (text2.Contains("dualsense") || text2.Contains("dualshock") || text2.Contains("playstation") || text2.Contains("wireless controller"))
				{
					return ControllerGlyphStyle.PlayStation;
				}
				if (!(gamepad is XInputController) && !text2.Contains("xbox"))
				{
					text2.Contains("xinput");
				}
				return ControllerGlyphStyle.Xbox;
			}
			}
		}

		private bool TryBuildSpriteAsset(ControllerGlyphStyle style, out TMP_SpriteAsset spriteAsset)
		{
			spriteAsset = null;
			try
			{
				return TryBuildSpriteAssetInternal(style, out spriteAsset);
			}
			catch (Exception arg)
			{
				if ((Object)(object)spriteAsset != (Object)null)
				{
					Object.Destroy((Object)(object)spriteAsset);
					spriteAsset = null;
				}
				_logger.LogError((object)$"Failed to build controller glyph sprite asset for '{style}': {arg}");
				return false;
			}
		}

		private bool TryBuildSpriteAssetInternal(ControllerGlyphStyle style, out TMP_SpriteAsset spriteAsset)
		{
			spriteAsset = null;
			List<LoadedGlyph> list = new List<LoadedGlyph>();
			foreach (KeyValuePair<ControllerGlyphButton, string> spriteName in SpriteNames)
			{
				string glyphFileName = GetGlyphFileName(style, spriteName.Key);
				if (string.IsNullOrEmpty(glyphFileName))
				{
					continue;
				}
				Texture2D texture;
				if (!TryReadGlyphBytes(style, glyphFileName, out var bytes))
				{
					if (_configManager.DebugOutput)
					{
						_logger.LogWarning((object)("Missing controller glyph: " + GetStyleResourceFolder(style) + "/" + glyphFileName));
					}
				}
				else if (TryLoadGlyphTexture(bytes, out texture))
				{
					list.Add(new LoadedGlyph(spriteName.Value, texture));
				}
			}
			if (list.Count == 0)
			{
				_logger.LogWarning((object)$"No controller glyphs loaded for style '{style}'.");
				return false;
			}
			if (!TryCreateAtlasSpriteAsset(list, out spriteAsset))
			{
				DestroyLoadedGlyphs(list);
				return false;
			}
			DestroyLoadedGlyphs(list);
			return true;
		}

		private bool TryCreateAtlasSpriteAsset(List<LoadedGlyph> loadedGlyphs, out TMP_SpriteAsset spriteAsset)
		{
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: 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_00ed: Expected O, but got Unknown
			//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_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Expected O, but got Unknown
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Expected O, but got Unknown
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dd: Expected O, but got Unknown
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Expected O, but got Unknown
			spriteAsset = ScriptableObject.CreateInstance<TMP_SpriteAsset>();
			((Object)spriteAsset).name = "ControllerSupportGlyphs";
			((TMP_Asset)spriteAsset).hashCode = TMP_TextUtilities.GetSimpleHashCode(((Object)spriteAsset).name);
			SpriteAssetVersionField?.SetValue(spriteAsset, "1.1.0");
			int num = 0;
			int num2 = 0;
			foreach (LoadedGlyph loadedGlyph2 in loadedGlyphs)
			{
				num = Math.Max(num, ((Texture)loadedGlyph2.Texture).width);
				num2 = Math.Max(num2, ((Texture)loadedGlyph2.Texture).height);
			}
			int num3 = num + 4;
			int num4 = num2 + 4;
			int count = loadedGlyphs.Count;
			int num5 = Mathf.CeilToInt(Mathf.Sqrt((float)count));
			int num6 = Mathf.CeilToInt((float)count / (float)num5);
			int num7 = Math.Max(64, num5 * num3);
			int num8 = Math.Max(64, num6 * num4);
			Texture2D val = new Texture2D(num7, num8, (TextureFormat)4, false)
			{
				filterMode = (FilterMode)1,
				wrapMode = (TextureWrapMode)1
			};
			Color32[] array = (Color32[])(object)new Color32[num7 * num8];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = new Color32((byte)0, (byte)0, (byte)0, (byte)0);
			}
			val.SetPixels32(array);
			List<TMP_SpriteGlyph> orCreateGlyphTable = GetOrCreateGlyphTable(spriteAsset, clearExisting: true);
			List<TMP_SpriteCharacter> orCreateCharacterTable = GetOrCreateCharacterTable(spriteAsset, clearExisting: true);
			uint num9 = 0u;
			GlyphRect val2 = default(GlyphRect);
			GlyphMetrics val3 = default(GlyphMetrics);
			for (int j = 0; j < loadedGlyphs.Count; j++)
			{
				LoadedGlyph loadedGlyph = loadedGlyphs[j];
				int num10 = j % num5;
				int num11 = j / num5;
				int num12 = num10 * num3 + 2;
				int num13 = num11 * num4 + 2;
				int width = ((Texture)loadedGlyph.Texture).width;
				int height = ((Texture)loadedGlyph.Texture).height;
				val.SetPixels(num12, num13, width, height, loadedGlyph.Texture.GetPixels());
				((GlyphRect)(ref val2))..ctor(num12, num13, width, height);
				((GlyphMetrics)(ref val3))..ctor((float)width, (float)height, 0f, (float)height * 0.85f, (float)width + 2f);
				TMP_SpriteGlyph val4 = new TMP_SpriteGlyph(num9, val3, val2, 1f, 0);
				TMP_SpriteCharacter item = new TMP_SpriteCharacter(65534 + num9, val4)
				{
					name = loadedGlyph.SpriteName,
					scale = 1f
				};
				orCreateGlyphTable.Add(val4);
				orCreateCharacterTable.Add(item);
				num9++;
			}
			val.Apply(false, false);
			spriteAsset.spriteSheet = (Texture)(object)val;
			TMP_SpriteAsset defaultSpriteAsset = TMP_Settings.defaultSpriteAsset;
			if ((Object)(object)defaultSpriteAsset != (Object)null && (Object)(object)((TMP_Asset)defaultSpriteAsset).material != (Object)null)
			{
				((TMP_Asset)spriteAsset).material = new Material(((TMP_Asset)defaultSpriteAsset).material);
				((TMP_Asset)spriteAsset).material.mainTexture = (Texture)(object)val;
			}
			else
			{
				Shader val5 = Shader.Find("TextMeshPro/Sprite");
				if ((Object)(object)val5 == (Object)null)
				{
					Object.Destroy((Object)(object)val);
					Object.Destroy((Object)(object)spriteAsset);
					spriteAsset = null;
					_logger.LogError((object)"TextMeshPro/Sprite shader not found; controller glyphs cannot render.");
					return false;
				}
				((TMP_Asset)spriteAsset).material = new Material(val5)
				{
					mainTexture = (Texture)(object)val
				};
			}
			spriteAsset.UpdateLookupTables();
			return true;
		}

		private static bool TryLoadGlyphTexture(byte[] bytes, out Texture2D texture)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			texture = new Texture2D(2, 2, (TextureFormat)4, false);
			if (!ImageConversion.LoadImage(texture, bytes))
			{
				Object.Destroy((Object)(object)texture);
				texture = null;
				return false;
			}
			((Texture)texture).filterMode = (FilterMode)1;
			((Texture)texture).wrapMode = (TextureWrapMode)1;
			return true;
		}

		private static void DestroyLoadedGlyphs(List<LoadedGlyph> loadedGlyphs)
		{
			foreach (LoadedGlyph loadedGlyph in loadedGlyphs)
			{
				if ((Object)(object)loadedGlyph.Texture != (Object)null)
				{
					Object.Destroy((Object)(object)loadedGlyph.Texture);
				}
			}
		}

		private static List<TMP_SpriteGlyph> GetOrCreateGlyphTable(TMP_SpriteAsset spriteAsset, bool clearExisting)
		{
			List<TMP_SpriteGlyph> list = SpriteGlyphTableField?.GetValue(spriteAsset) as List<TMP_SpriteGlyph>;
			if (list == null)
			{
				list = new List<TMP_SpriteGlyph>();
				SpriteGlyphTableField?.SetValue(spriteAsset, list);
			}
			else if (clearExisting)
			{
				list.Clear();
			}
			return list;
		}

		private static List<TMP_SpriteCharacter> GetOrCreateCharacterTable(TMP_SpriteAsset spriteAsset, bool clearExisting)
		{
			List<TMP_SpriteCharacter> list = SpriteCharacterTableField?.GetValue(spriteAsset) as List<TMP_SpriteCharacter>;
			if (list == null)
			{
				list = new List<TMP_SpriteCharacter>();
				SpriteCharacterTableField?.SetValue(spriteAsset, list);
			}
			else if (clearExisting)
			{
				list.Clear();
			}
			return list;
		}

		private bool TryReadGlyphBytes(ControllerGlyphStyle style, string fileName, out byte[] bytes)
		{
			string name = "ControllerSupport.Glyphs." + GetStyleResourceFolder(style) + "." + fileName;
			using (Stream stream = PluginAssembly.GetManifestResourceStream(name))
			{
				if (stream != null)
				{
					bytes = ReadAllBytes(stream);
					return bytes.Length != 0;
				}
			}
			if (!string.IsNullOrEmpty(_glyphRoot))
			{
				string path = Path.Combine(_glyphRoot, GetStyleFolder(style), fileName);
				if (File.Exists(path))
				{
					bytes = File.ReadAllBytes(path);
					return bytes.Length != 0;
				}
			}
			bytes = null;
			return false;
		}

		private static byte[] ReadAllBytes(Stream stream)
		{
			using MemoryStream memoryStream = new MemoryStream();
			stream.CopyTo(memoryStream);
			return memoryStream.ToArray();
		}

		private string BuildTag(ControllerGlyphButton button)
		{
			if ((Object)(object)_spriteAsset == (Object)null || !SpriteNames.TryGetValue(button, out var value))
			{
				return null;
			}
			if (_spriteAsset.GetSpriteIndexFromName(value) < 0)
			{
				return null;
			}
			return string.Format("<size=120%><voffset=0.2em><sprite=\"{0}\" name=\"{1}\"></size>", "ControllerSupportGlyphs", value);
		}

		private static ControllerGlyphButton? MapInputKey(InputKey inputKey)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected I4, but got Unknown
			switch (inputKey - 1)
			{
			case 0:
			case 8:
				return ControllerGlyphButton.South;
			case 1:
				return ControllerGlyphButton.West;
			case 11:
				return ControllerGlyphButton.East;
			case 13:
				return ControllerGlyphButton.North;
			case 14:
				return ControllerGlyphButton.LeftStickClick;
			case 7:
				return ControllerGlyphButton.Select;
			case 5:
			case 17:
			case 21:
				return ControllerGlyphButton.Start;
			case 9:
			case 23:
				return ControllerGlyphButton.RightTrigger;
			case 10:
			case 22:
				return ControllerGlyphButton.LeftTrigger;
			case 3:
			case 4:
			case 16:
				return ControllerGlyphButton.RightShoulder;
			case 18:
				return ControllerGlyphButton.DpadLeft;
			case 19:
				return ControllerGlyphButton.DpadUp;
			case 20:
				return ControllerGlyphButton.DpadRight;
			default:
				return null;
			}
		}

		private static string GetStyleFolder(ControllerGlyphStyle style)
		{
			return style switch
			{
				ControllerGlyphStyle.PlayStation => "PS5", 
				ControllerGlyphStyle.Switch => "Switch", 
				ControllerGlyphStyle.SteamDeck => "Steam Deck", 
				_ => "Xbox Series", 
			};
		}

		private static string GetStyleResourceFolder(ControllerGlyphStyle style)
		{
			return style switch
			{
				ControllerGlyphStyle.PlayStation => "PS5", 
				ControllerGlyphStyle.Switch => "Switch", 
				ControllerGlyphStyle.SteamDeck => "SteamDeck", 
				_ => "XboxSeries", 
			};
		}

		private static string GetGlyphFileName(ControllerGlyphStyle style, ControllerGlyphButton button)
		{
			return style switch
			{
				ControllerGlyphStyle.PlayStation => GetPlayStationFileName(button), 
				ControllerGlyphStyle.Switch => GetSwitchFileName(button), 
				ControllerGlyphStyle.SteamDeck => GetSteamDeckFileName(button), 
				_ => GetXboxFileName(button), 
			};
		}

		private static string GetXboxFileName(ControllerGlyphButton button)
		{
			return button switch
			{
				ControllerGlyphButton.South => "XboxSeriesX_A.png", 
				ControllerGlyphButton.West => "XboxSeriesX_X.png", 
				ControllerGlyphButton.East => "XboxSeriesX_B.png", 
				ControllerGlyphButton.North => "XboxSeriesX_Y.png", 
				ControllerGlyphButton.LeftShoulder => "XboxSeriesX_LB.png", 
				ControllerGlyphButton.RightShoulder => "XboxSeriesX_RB.png", 
				ControllerGlyphButton.LeftTrigger => "XboxSeriesX_LT.png", 
				ControllerGlyphButton.RightTrigger => "XboxSeriesX_RT.png", 
				ControllerGlyphButton.LeftStick => "XboxSeriesX_Left_Stick.png", 
				ControllerGlyphButton.RightStick => "XboxSeriesX_Right_Stick.png", 
				ControllerGlyphButton.LeftStickClick => "XboxSeriesX_Left_Stick_Click.png", 
				ControllerGlyphButton.RightStickClick => "XboxSeriesX_Right_Stick_Click.png", 
				ControllerGlyphButton.DpadUp => "XboxSeriesX_Dpad_Up.png", 
				ControllerGlyphButton.DpadDown => "XboxSeriesX_Dpad_Down.png", 
				ControllerGlyphButton.DpadLeft => "XboxSeriesX_Dpad_Left.png", 
				ControllerGlyphButton.DpadRight => "XboxSeriesX_Dpad_Right.png", 
				ControllerGlyphButton.Select => "XboxSeriesX_View.png", 
				ControllerGlyphButton.Start => "XboxSeriesX_Menu.png", 
				_ => null, 
			};
		}

		private static string GetPlayStationFileName(ControllerGlyphButton button)
		{
			return button switch
			{
				ControllerGlyphButton.South => "PS5_Cross.png", 
				ControllerGlyphButton.West => "PS5_Square.png", 
				ControllerGlyphButton.East => "PS5_Circle.png", 
				ControllerGlyphButton.North => "PS5_Triangle.png", 
				ControllerGlyphButton.LeftShoulder => "PS5_L1.png", 
				ControllerGlyphButton.RightShoulder => "PS5_R1.png", 
				ControllerGlyphButton.LeftTrigger => "PS5_L2.png", 
				ControllerGlyphButton.RightTrigger => "PS5_R2.png", 
				ControllerGlyphButton.LeftStick => "PS5_Left_Stick.png", 
				ControllerGlyphButton.RightStick => "PS5_Right_Stick.png", 
				ControllerGlyphButton.LeftStickClick => "PS5_Left_Stick_Click.png", 
				ControllerGlyphButton.RightStickClick => "PS5_Right_Stick_Click.png", 
				ControllerGlyphButton.DpadUp => "PS5_Dpad_Up.png", 
				ControllerGlyphButton.DpadDown => "PS5_Dpad_Down.png", 
				ControllerGlyphButton.DpadLeft => "PS5_Dpad_Left.png", 
				ControllerGlyphButton.DpadRight => "PS5_Dpad_Right.png", 
				ControllerGlyphButton.Select => "PS5_Share.png", 
				ControllerGlyphButton.Start => "PS5_Options.png", 
				_ => null, 
			};
		}

		private static string GetSwitchFileName(ControllerGlyphButton button)
		{
			return button switch
			{
				ControllerGlyphButton.South => "Switch_B.png", 
				ControllerGlyphButton.West => "Switch_Y.png", 
				ControllerGlyphButton.East => "Switch_A.png", 
				ControllerGlyphButton.North => "Switch_X.png", 
				ControllerGlyphButton.LeftShoulder => "Switch_LB.png", 
				ControllerGlyphButton.RightShoulder => "Switch_RB.png", 
				ControllerGlyphButton.LeftTrigger => "Switch_LT.png", 
				ControllerGlyphButton.RightTrigger => "Switch_RT.png", 
				ControllerGlyphButton.LeftStick => "Switch_Left_Stick.png", 
				ControllerGlyphButton.RightStick => "Switch_Right_Stick.png", 
				ControllerGlyphButton.LeftStickClick => "Switch_Left_Stick_Click.png", 
				ControllerGlyphButton.RightStickClick => "Switch_Right_Stick_Click.png", 
				ControllerGlyphButton.DpadUp => "Switch_Dpad_Up.png", 
				ControllerGlyphButton.DpadDown => "Switch_Dpad_Down.png", 
				ControllerGlyphButton.DpadLeft => "Switch_Dpad_Left.png", 
				ControllerGlyphButton.DpadRight => "Switch_Dpad_Right.png", 
				ControllerGlyphButton.Select => "Switch_Minus.png", 
				ControllerGlyphButton.Start => "Switch_Plus.png", 
				_ => null, 
			};
		}

		private static string GetSteamDeckFileName(ControllerGlyphButton button)
		{
			return button switch
			{
				ControllerGlyphButton.South => "SteamDeck_A.png", 
				ControllerGlyphButton.West => "SteamDeck_X.png", 
				ControllerGlyphButton.East => "SteamDeck_B.png", 
				ControllerGlyphButton.North => "SteamDeck_Y.png", 
				ControllerGlyphButton.LeftShoulder => "SteamDeck_L1.png", 
				ControllerGlyphButton.RightShoulder => "SteamDeck_R1.png", 
				ControllerGlyphButton.LeftTrigger => "SteamDeck_L2.png", 
				ControllerGlyphButton.RightTrigger => "SteamDeck_R2.png", 
				ControllerGlyphButton.LeftStick => "SteamDeck_Left_Stick.png", 
				ControllerGlyphButton.RightStick => "SteamDeck_Right_Stick.png", 
				ControllerGlyphButton.LeftStickClick => "SteamDeck_Left_Stick_Click.png", 
				ControllerGlyphButton.RightStickClick => "SteamDeck_Right_Stick_Click.png", 
				ControllerGlyphButton.DpadUp => "SteamDeck_Dpad_Up.png", 
				ControllerGlyphButton.DpadDown => "SteamDeck_Dpad_Down.png", 
				ControllerGlyphButton.DpadLeft => "SteamDeck_Dpad_Left.png", 
				ControllerGlyphButton.DpadRight => "SteamDeck_Dpad_Right.png", 
				ControllerGlyphButton.Select => "SteamDeck_Minus.png", 
				ControllerGlyphButton.Start => "SteamDeck_Plus.png", 
				_ => null, 
			};
		}
	}
	[HarmonyPatch(typeof(InputManager), "InputDisplayGet")]
	internal static class InputDisplayGetGlyphPatch
	{
		[HarmonyPostfix]
		private static void Postfix(InputKey _inputKey, KeyType _keyType, MovementDirection _movementDirection, ref string __result)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if (ControllerGlyphManager.Instance != null && ControllerGlyphManager.Instance.TryGetInputKeyGlyph(_inputKey, _keyType, _movementDirection, out var glyphTag))
			{
				__result = glyphTag;
			}
		}
	}
	[HarmonyPatch(typeof(InputManager), "InputDisplayGetString")]
	internal static class InputDisplayGetStringGlyphPatch
	{
		[HarmonyPostfix]
		private static void Postfix(ref string __result)
		{
			if (ControllerGlyphManager.Instance != null && ControllerGlyphManager.Instance.TryGetMouseGlyph(__result, out var glyphTag))
			{
				__result = glyphTag;
			}
		}
	}
	[HarmonyPatch(typeof(InputManager), "InputDisplayMouseStringGet")]
	internal static class InputDisplayMouseStringGetGlyphPatch
	{
		[HarmonyPostfix]
		private static void Postfix(ref string __result)
		{
			if (ControllerGlyphManager.Instance != null && ControllerGlyphManager.Instance.TryGetMouseGlyph(__result, out var glyphTag))
			{
				__result = glyphTag;
			}
		}
	}
	public class ControllerLedManager
	{
		private readonly ManualLogSource _logger;

		private readonly ConfigManager _configManager;

		private readonly VibrationManager _vibrationManager;

		private InputDevice _device;

		private bool _supported;

		private bool _loggedUnsupported;

		private Color? _lastAppliedColor;

		private float _nextHeartbeatTime;

		private const float HeartbeatIntervalSeconds = 2f;

		public Color? CurrentColor { get; private set; }

		public ControllerLedManager(ManualLogSource logger, ConfigManager configManager, VibrationManager vibrationManager)
		{
			_logger = logger;
			_configManager = configManager;
			_vibrationManager = vibrationManager;
			_vibrationManager.MotorStateChanged = ApplyManagedVibrationOutput;
		}

		public void SetGamepad(Gamepad gamepad)
		{
			if (_device == gamepad)
			{
				return;
			}
			_device = (InputDevice)(object)gamepad;
			_supported = ControllerLedUtility.SupportsLed((InputDevice)(object)gamepad);
			_lastAppliedColor = null;
			_loggedUnsupported = false;
			if (_configManager.EnableLedSync && gamepad != null)
			{
				if (_supported)
				{
					_logger.LogInfo((object)("Controller LED sync enabled for " + ((InputControl)gamepad).displayName));
				}
				else if (_configManager.DebugOutput)
				{
					_logger.LogInfo((object)("Controller LED sync unavailable for " + ((InputControl)gamepad).displayName + " (no Unity LED API)"));
				}
			}
		}

		public void Update()
		{
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			if (_device == null)
			{
				return;
			}
			if (_configManager.EnableLedSync && _supported)
			{
				ApplyManagedVibrationOutput();
			}
			else if (!_supported && _configManager.EnableLedSync && _configManager.DebugOutput && !_loggedUnsupported)
			{
				_loggedUnsupported = true;
				_logger.LogInfo((object)("Controller LED sync skipped: " + ((InputControl)_device).displayName + " has no Unity LED API"));
			}
			if (!_configManager.EnableLedSync || !_supported)
			{
				return;
			}
			Color? localPlayerHeadColor = GetLocalPlayerHeadColor();
			if (localPlayerHeadColor.HasValue)
			{
				bool num = _vibrationManager != null && _vibrationManager.HasActiveMotors;
				bool flag = Time.realtimeSinceStartup >= _nextHeartbeatTime;
				if (flag)
				{
					_nextHeartbeatTime = Time.realtimeSinceStartup + 2f;
				}
				if (num || flag || !_lastAppliedColor.HasValue || !ColorsApproximatelyEqual(_lastAppliedColor.Value, localPlayerHeadColor.Value))
				{
					ApplyLedColor(localPlayerHeadColor.Value);
				}
			}
		}

		internal void ApplyManagedVibrationOutput()
		{
			//IL_008c: 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_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: 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_007a: Unknown result type (might be due to invalid IL or missing references)
			if (_device == null || _vibrationManager == null || !_configManager.EnableVibration || !_configManager.EnableLedSync || !_supported)
			{
				return;
			}
			float activeLowMotor = _vibrationManager.ActiveLowMotor;
			float activeHighMotor = _vibrationManager.ActiveHighMotor;
			if (ControllerLedUtility.SupportsCombinedMotorLed(_device))
			{
				Color color = (Color)(((??)CurrentColor) ?? ((??)_lastAppliedColor) ?? Color.black);
				ControllerLedUtility.TrySetLedColor(_device, color, activeLowMotor, activeHighMotor);
				return;
			}
			InputDevice device = _device;
			Gamepad val = (Gamepad)(object)((device is Gamepad) ? device : null);
			if (val != null)
			{
				val.SetMotorSpeeds(activeLowMotor, activeHighMotor);
				if (CurrentColor.HasValue)
				{
					ControllerLedUtility.TrySetLedColor(_device, CurrentColor.Value);
				}
			}
		}

		private void ApplyLedColor(Color color)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			CurrentColor = color;
			if (ControllerLedUtility.SupportsCombinedMotorLed(_device))
			{
				float value = ((_vibrationManager != null) ? _vibrationManager.ActiveLowMotor : 0f);
				float value2 = ((_vibrationManager != null) ? _vibrationManager.ActiveHighMotor : 0f);
				if (ControllerLedUtility.TrySetLedColor(_device, color, value, value2))
				{
					_lastAppliedColor = color;
				}
			}
			else if (ControllerLedUtility.TrySetLedColor(_device, color))
			{
				_lastAppliedColor = color;
				if (_configManager.DebugOutput)
				{
					_logger.LogInfo((object)$"Controller LED set to ({color.r:F2}, {color.g:F2}, {color.b:F2})");
				}
			}
		}

		private void ApplyLedAndMotors(Color color, float lowMotor, float highMotor)
		{
			//IL_0001: 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_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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_0096: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
			CurrentColor = color;
			if (ControllerLedUtility.SupportsCombinedMotorLed(_device))
			{
				if (ControllerLedUtility.TrySetLedColor(_device, color, lowMotor, highMotor))
				{
					_lastAppliedColor = color;
				}
				return;
			}
			InputDevice device = _device;
			Gamepad val = (Gamepad)(object)((device is Gamepad) ? device : null);
			if (val != null && _configManager.EnableVibration)
			{
				val.SetMotorSpeeds(lowMotor, highMotor);
			}
			if (ControllerLedUtility.TrySetLedColor(_device, color))
			{
				_lastAppliedColor = color;
				if (_configManager.DebugOutput)
				{
					_logger.LogInfo((object)$"Controller LED set to ({color.r:F2}, {color.g:F2}, {color.b:F2})");
				}
			}
		}

		public void SyncFromPlayer()
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			if (_configManager.EnableLedSync && _device != null && _supported)
			{
				Color? localPlayerHeadColor = GetLocalPlayerHeadColor();
				if (localPlayerHeadColor.HasValue)
				{
					float lowMotor = ((_vibrationManager != null) ? _vibrationManager.ActiveLowMotor : 0f);
					float highMotor = ((_vibrationManager != null) ? _vibrationManager.ActiveHighMotor : 0f);
					ApplyLedAndMotors(localPlayerHeadColor.Value, lowMotor, highMotor);
				}
			}
		}

		private void ApplyColor(Color color)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			float lowMotor = ((_vibrationManager != null) ? _vibrationManager.ActiveLowMotor : 0f);
			float highMotor = ((_vibrationManager != null) ? _vibrationManager.ActiveHighMotor : 0f);
			ApplyLedAndMotors(color, lowMotor, highMotor);
		}

		internal static PlayerAvatar GetLocalPlayerAvatar()
		{
			try
			{
				PlayerAvatar val = SemiFunc.PlayerGetLocal();
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			catch
			{
			}
			try
			{
				PlayerAvatar val2 = SemiFunc.PlayerAvatarLocal();
				if ((Object)(object)val2 != (Object)null)
				{
					return val2;
				}
			}
			catch
			{
			}
			if ((Object)(object)PlayerAvatar.instance != (Object)null)
			{
				return PlayerAvatar.instance;
			}
			try
			{
				foreach (PlayerAvatar item in SemiFunc.PlayerGetAll())
				{
					if ((Object)(object)item != (Object)null && Traverse.Create((object)item).Field("isLocal").GetValue<bool>())
					{
						return item;
					}
				}
			}
			catch
			{
			}
			try
			{
				List<PlayerAvatar> playerList = GameDirector.instance.PlayerList;
				if (playerList != null)
				{
					foreach (PlayerAvatar item2 in playerList)
					{
						if ((Object)(object)item2 != (Object)null && Traverse.Create((object)item2).Field("isLocal").GetValue<bool>())
						{
							return item2;
						}
					}
					if (playerList.Count == 1 && (Object)(object)playerList[0] != (Object)null)
					{
						return playerList[0];
					}
				}
			}
			catch
			{
			}
			return null;
		}

		internal static bool IsLocalPlayer(PlayerAvatar avatar)
		{
			if ((Object)(object)avatar == (Object)null)
			{
				return false;
			}
			if (IsAvatarMarkedLocal(avatar))
			{
				return true;
			}
			PlayerAvatar localPlayerAvatar = GetLocalPlayerAvatar();
			if ((Object)(object)localPlayerAvatar != (Object)null)
			{
				return localPlayerAvatar == avatar;
			}
			return false;
		}

		internal static bool IsAvatarMarkedLocal(PlayerAvatar avatar)
		{
			if ((Object)(object)avatar == (Object)null)
			{
				return false;
			}
			try
			{
				if (Traverse.Create((object)avatar).Field("isLocal").GetValue<bool>())
				{
					return true;
				}
			}
			catch
			{
			}
			return !GameManager.Multiplayer();
		}

		internal static bool IsLocalPlayerCosmetics(PlayerCosmetics cosmetics)
		{
			if ((Object)(object)cosmetics == (Object)null || (Object)(object)cosmetics.playerAvatarVisuals == (Object)null)
			{
				return false;
			}
			return IsLocalPlayer(cosmetics.playerAvatarVisuals.playerAvatar);
		}

		internal static Color? GetLocalPlayerHeadColor()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: 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_0048: 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_00c7: Unknown result type (might be due to invalid IL or missing references)
			PlayerAvatar localPlayerAvatar = GetLocalPlayerAvatar();
			if ((Object)(object)localPlayerAvatar == (Object)null)
			{
				return null;
			}
			try
			{
				Color val = SemiFunc.PlayerGetColorMain(localPlayerAvatar);
				if (val.a > 0f || val.r > 0f || val.g > 0f || val.b > 0f)
				{
					return val;
				}
			}
			catch
			{
			}
			if ((Object)(object)localPlayerAvatar.playerAvatarVisuals == (Object)null)
			{
				return null;
			}
			Traverse val2 = Traverse.Create((object)localPlayerAvatar.playerAvatarVisuals);
			try
			{
				Color value = val2.Field("playerColorTop").GetValue<Color>();
				if (value.a > 0f || value.r > 0f || value.g > 0f || value.b > 0f)
				{
					return value;
				}
			}
			catch
			{
			}
			try
			{
				return val2.Field("color").GetValue<Color>();
			}
			catch
			{
			}
			return GetSavedPlayerColor();
		}

		private static Color? GetSavedPlayerColor()
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)DataDirector.instance == (Object)null || (Object)(object)AssetManager.instance == (Object)null)
				{
					return null;
				}
				int num = DataDirector.instance.ColorGetBody();
				Color[] value = Traverse.Create((object)AssetManager.instance).Field("playerColors").GetValue<Color[]>();
				if (value == null || num < 0 || num >= value.Length)
				{
					return null;
				}
				return value[num];
			}
			catch
			{
				return null;
			}
		}

		private static bool ColorsApproximatelyEqual(Color a, Color b)
		{
			//IL_0000: 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_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (Mathf.Approximately(a.r, b.r) && Mathf.Approximately(a.g, b.g))
			{
				return Mathf.Approximately(a.b, b.b);
			}
			return false;
		}
	}
	internal static class ControllerLedUtility
	{
		public static bool SupportsLed(InputDevice device)
		{
			if (device == null)
			{
				return false;
			}
			if (device is IDualShockHaptics)
			{
				return true;
			}
			return FindSetLightBarColorMethod(device) != null;
		}

		public static bool SupportsCombinedMotorLed(InputDevice device)
		{
			return FindSetMotorSpeedsAndLightBarColorMethod(device) != null;
		}

		public static bool TrySetLedColor(InputDevice device, Color color)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return TrySetLedColor(device, color, null, null);
		}

		public static bool TrySetLedColor(InputDevice device, Color color, float? lowMotor, float? highMotor)
		{
			//IL_0005: 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_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: 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)
			if (device == null)
			{
				return false;
			}
			color = ClampColor(color);
			if (lowMotor.HasValue || highMotor.HasValue)
			{
				MethodInfo methodInfo = FindSetMotorSpeedsAndLightBarColorMethod(device);
				if (methodInfo != null)
				{
					methodInfo.Invoke(device, new object[3] { lowMotor, highMotor, color });
					return true;
				}
			}
			IDualShockHaptics val = (IDualShockHaptics)(object)((device is IDualShockHaptics) ? device : null);
			if (val != null)
			{
				val.SetLightBarColor(color);
				return true;
			}
			MethodInfo methodInfo2 = FindSetLightBarColorMethod(device);
			if (methodInfo2 != null)
			{
				methodInfo2.Invoke(device, new object[1] { color });
				return true;
			}
			return false;
		}

		private static Color ClampColor(Color color)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			return new Color(Mathf.Clamp01(color.r), Mathf.Clamp01(color.g), Mathf.Clamp01(color.b), 1f);
		}

		private static MethodInfo FindSetLightBarColorMethod(InputDevice device)
		{
			foreach (Type item in GetTypeHierarchy(((object)device).GetType()))
			{
				MethodInfo method = item.GetMethod("SetLightBarColor", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(Color) }, null);
				if (method != null)
				{
					return method;
				}
			}
			return null;
		}

		private static MethodInfo FindSetMotorSpeedsAndLightBarColorMethod(InputDevice device)
		{
			foreach (Type item in GetTypeHierarchy(((object)device).GetType()))
			{
				MethodInfo method = item.GetMethod("SetMotorSpeedsAndLightBarColor", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[3]
				{
					typeof(float?),
					typeof(float?),
					typeof(Color?)
				}, null);
				if (method != null)
				{
					return method;
				}
			}
			return null;
		}

		private static IEnumerable<Type> GetTypeHierarchy(Type type)
		{
			while (type != null)
			{
				yield return type;
				type = type.BaseType;
			}
		}
	}
	[BepInPlugin("pacmanninja998.nexus.ControllerSupport", "Controller Support", "1.0.2")]
	public class ControllerSupportPlugin : BaseUnityPlugin
	{
		private InputManager _inputManager;

		private ConfigManager _configManager;

		private VibrationManager _vibrationManager;

		private ControllerLedManager _ledManager;

		private ControllerGlyphManager _glyphManager;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Expected O, but got Unknown
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Controller Support plugin loaded!");
			_configManager = new ConfigManager(((BaseUnityPlugin)this).Config);
			_vibrationManager = new VibrationManager(((BaseUnityPlugin)this).Logger, _configManager);
			_ledManager = new ControllerLedManager(((BaseUnityPlugin)this).Logger, _configManager, _vibrationManager);
			_inputManager = new InputManager(((BaseUnityPlugin)this).Logger, _configManager, _vibrationManager, _ledManager);
			_glyphManager = new ControllerGlyphManager(((BaseUnityPlugin)this).Logger, _configManager, ((BaseUnityPlugin)this).Info.Location);
			if (!_configManager.EnableVibration && !_configManager.EnableLedSync && !_configManager.EnableMenuNavigation && !_configManager.EnableControllerGlyphs)
			{
				return;
			}
			if (_configManager.EnableVibration)
			{
				GameEventPatches.Initialize(_vibrationManager, _configManager, ((BaseUnityPlugin)this).Logger);
			}
			ColorLedPatches.Initialize(_ledManager, _configManager, ((BaseUnityPlugin)this).Logger);
			MenuNavigationPatches.Initialize(_inputManager.MenuNavigation, _configManager, ((BaseUnityPlugin)this).Logger);
			_harmony = new Harmony("pacmanninja998.nexus.ControllerSupport");
			try
			{
				_harmony.PatchAll(typeof(ControllerSupportPlugin).Assembly);
				if (_configManager.EnableVibration)
				{
					if (_configManager.EnableDamageVibration)
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)"Damage vibration patches applied.");
					}
					if (_configManager.EnableItemBreakVibration)
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)"Item break vibration patches applied.");
					}
					if (_configManager.EnableHoldVibration)
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)"Hold vibration patches applied.");
					}
				}
				if (_configManager.EnableLedSync)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)"Controller LED sync patches applied.");
				}
				if (_configManager.EnableMenuNavigation)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)"Menu navigation patches applied.");
				}
				if (_configManager.EnableControllerGlyphs)
				{
					_glyphManager.Initialize();
					((BaseUnityPlugin)this).Logger.LogInfo((object)"Controller glyph patches applied.");
				}
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Harmony patching failed: {arg}");
			}
		}

		private void Update()
		{
			_inputManager?.Update();
			_glyphManager?.Update();
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_vibrationManager?.Stop();
			if (Keyboard.current != null && _inputManager != null)
			{
				_inputManager.ReleaseAllKeys();
			}
		}
	}
	internal static class GameEventPatches
	{
		internal static VibrationManager Vibration;

		internal static ConfigManager Config;

		internal static ManualLogSource Logger;

		internal static void Initialize(VibrationManager vibration, ConfigManager config, ManualLogSource logger)
		{
			Vibration = vibration;
			Config = config;
			Logger = logger;
		}

		internal static bool ShouldApplyGameVibration()
		{
			if (Config != null && Vibration != null)
			{
				return Config.EnableVibration;
			}
			return false;
		}

		internal static bool IsLocalPlayerHealth(PlayerHealth instance)
		{
			PlayerAvatar localPlayerAvatar = ControllerLedManager.GetLocalPlayerAvatar();
			if ((Object)(object)localPlayerAvatar == (Object)null || (Object)(object)instance == (Object)null)
			{
				return false;
			}
			return localPlayerAvatar.playerHealth == instance;
		}

		internal static bool IsHeldByLocalPlayer(PhysGrabObject physGrabObject)
		{
			if ((Object)(object)physGrabObject == (Object)null)
			{
				return false;
			}
			return Traverse.Create((object)physGrabObject).Field("heldByLocalPlayer").GetValue<bool>();
		}

		internal static bool ShouldSkipDamageFeedback(PlayerHealth instance, int damage)
		{
			if (damage <= 0)
			{
				return true;
			}
			Traverse val = Traverse.Create((object)instance);
			if (val.Field("godMode").GetValue<bool>())
			{
				return true;
			}
			PlayerAvatar value = val.Field("playerAvatar").GetValue<PlayerAvatar>();
			if ((Object)(object)value != (Object)null && Traverse.Create((object)value).Field("deadSet").GetValue<bool>())
			{
				return true;
			}
			if (val.Field("invincibleTimer").GetValue<float>() > 0f)
			{
				return true;
			}
			if (GameManager.Multiplayer())
			{
				PhotonView value2 = val.Field("photonView").GetValue<PhotonView>();
				if ((Object)(object)value2 != (Object)null && !value2.IsMine)
				{
					return true;
				}
			}
			return false;
		}

		internal static void ApplyHoldSustain(PhysGrabObject grabbedObject)
		{
			float num = 0.5f;
			if ((Object)(object)grabbedObject != (Object)null)
			{
				object value = Traverse.Create((object)grabbedObject).Field("rb").GetValue<object>();
				if (value != null)
				{
					num = Traverse.Create(value).Property("mass", (object[])null).GetValue<float>();
				}
			}
			float num2 = Mathf.Clamp01(num / 7f);
			float lowFrequency = Mathf.Lerp(0.04f, 0.12f, num2);
			float highFrequency = Mathf.Lerp(0.06f, 0.18f, num2);
			Vibration.SetHoldSustain(lowFrequency, highFrequency);
		}
	}
	[HarmonyPatch(typeof(PlayerHealth), "Hurt")]
	internal static class PlayerHealthHurtVibrationPatch
	{
		[HarmonyPostfix]
		private static void Postfix(PlayerHealth __instance, int damage)
		{
			if (GameEventPatches.ShouldApplyGameVibration() && GameEventPatches.Config.EnableDamageVibration && GameEventPatches.IsLocalPlayerHealth(__instance) && !GameEventPatches.ShouldSkipDamageFeedback(__instance, damage))
			{
				float num = Mathf.Clamp01((float)damage / 50f);
				float lowFrequency = Mathf.Lerp(0.25f, 0.85f, num);
				float highFrequency = Mathf.Lerp(0.4f, 1f, num);
				float durationSeconds = Mathf.Lerp(0.12f, 0.45f, num);
				GameEventPatches.Vibration.Pulse(lowFrequency, highFrequency, durationSeconds);
			}
		}
	}
	[HarmonyPatch(typeof(PhysGrabObjectImpactDetector), "BreakRPC")]
	internal static class PhysGrabObjectBreakVibrationPatch
	{
		[HarmonyPostfix]
		private static void Postfix(PhysGrabObjectImpactDetector __instance, float valueLost, int breakLevel, bool _loseValue)
		{
			if (!GameEventPatches.ShouldApplyGameVibration() || !GameEventPatches.Config.EnableItemBreakVibration || !_loseValue || !GameEventPatches.IsHeldByLocalPlayer(Traverse.Create((object)__instance).Field("physGrabObject").GetValue<PhysGrabObject>()))
			{
				return;
			}
			float num = Mathf.Clamp01(valueLost / 500f);
			if (breakLevel > 1)
			{
				num = Mathf.Max(num, Mathf.Clamp01(0.35f + (float)breakLevel * 0.12f));
			}
			float lowFrequency = Mathf.Lerp(0.3f, 0.9f, num);
			float highFrequency = Mathf.Lerp(0.5f, 1f, num);
			float durationSeconds = Mathf.Lerp(0.15f, 0.5f, num);
			GameEventPatches.Vibration.Pulse(lowFrequency, highFrequency, durationSeconds);
			if (GameEventPatches.Config.DebugOutput)
			{
				ManualLogSource logger = GameEventPatches.Logger;
				if (logger != null)
				{
					logger.LogInfo((object)$"Item break vibration: valueLost={valueLost:F0}, breakLevel={breakLevel}, severity={num:F2}");
				}
			}
		}
	}
	[HarmonyPatch(typeof(PhysGrabber), "PhysGrabStartEffects")]
	internal static class PhysGrabberStartVibrationPatch
	{
		[HarmonyPostfix]
		private static void Postfix(PhysGrabber __instance)
		{
			if (!GameEventPatches.ShouldApplyGameVibration() || !GameEventPatches.Config.EnableHoldVibration || !__instance.isLocal)
			{
				return;
			}
			GameEventPatches.ApplyHoldSustain(Traverse.Create((object)__instance).Field("grabbedPhysGrabObject").GetValue<PhysGrabObject>());
			GameEventPatches.Vibration.Pulse(0.1f, 0.16f, 0.06f);
			if (GameEventPatches.Config.DebugOutput)
			{
				ManualLogSource logger = GameEventPatches.Logger;
				if (logger != null)
				{
					logger.LogInfo((object)"Hold vibration started.");
				}
			}
		}
	}
	[HarmonyPatch(typeof(PhysGrabber), "PhysGrabEndEffects")]
	internal static class PhysGrabberEndVibrationPatch
	{
		[HarmonyPostfix]
		private static void Postfix(PhysGrabber __instance)
		{
			if (!GameEventPatches.ShouldApplyGameVibration() || !GameEventPatches.Config.EnableHoldVibration || !__instance.isLocal)
			{
				return;
			}
			GameEventPatches.Vibration.ClearHoldSustain();
			if (GameEventPatches.Config.DebugOutput)
			{
				ManualLogSource logger = GameEventPatches.Logger;
				if (logger != null)
				{
					logger.LogInfo((object)"Hold vibration stopped.");
				}
			}
		}
	}
	internal static class GamepadHelper
	{
		internal static Gamepad FindActiveGamepad()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			Gamepad current = Gamepad.current;
			if (current is IDualShockHaptics)
			{
				return current;
			}
			Enumerator<Gamepad> enumerator = Gamepad.all.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					Gamepad current2 = enumerator.Current;
					if (current2 is IDualShockHaptics)
					{
						return current2;
					}
				}
			}
			finally
			{
				((IDisposable)enumerator).Dispose();
			}
			if (current != null)
			{
				return current;
			}
			enumerator = Gamepad.all.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					Gamepad current3 = enumerator.Current;
					if (current3 != null)
					{
						return current3;
					}
				}
			}
			finally
			{
				((IDisposable)enumerator).Dispose();
			}
			return null;
		}
	}
	public class InputManager
	{
		private readonly ManualLogSource _logger;

		private readonly ConfigManager _configManager;

		private readonly KeyboardSimulator _keyboardSimulator;

		private readonly MouseSimulator _mouseSimulator;

		private readonly JoystickZoneHandler _joystickZoneHandler;

		private readonly VibrationManager _vibrationManager;

		private readonly ControllerLedManager _ledManager;

		private readonly MenuNavigationManager _menuNavigation;

		private Gamepad _gamepad;

		private bool _isControllerConnected;

		private float _previousLeftTrigger;

		private float _previousRightTrigger;

		internal MenuNavigationManager MenuNavigation => _menuNavigation;

		[DllImport("user32.dll")]
		private static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr lpdwProcessId);

		[DllImport("user32.dll")]
		private static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);

		[DllImport("user32.dll")]
		private static extern IntPtr GetForegroundWindow();

		[DllImport("kernel32.dll")]
		private static extern uint GetCurrentThreadId();

		[DllImport("user32.dll")]
		private static extern bool BringWindowToTop(IntPtr hWnd);

		[DllImport("user32.dll")]
		private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

		public InputManager(ManualLogSource logger, ConfigManager configManager, VibrationManager vibrationManager, ControllerLedManager ledManager)
		{
			_logger = logger;
			_configManager = configManager;
			_vibrationManager = vibrationManager;
			_ledManager = ledManager;
			_keyboardSimulator = new KeyboardSimulator(logger, configManager);
			_mouseSimulator = new MouseSimulator(logger, configManager);
			_joystickZoneHandler = new JoystickZoneHandler(logger, configManager, _keyboardSimulator);
			_menuNavigation = new MenuNavigationManager(logger, configManager);
			_gamepad = GamepadHelper.FindActiveGamepad();
			_isControllerConnected = _gamepad != null;
			if (_isControllerConnected)
			{
				_logger.LogInfo((object)("Controller connected: " + ((InputControl)_gamepad).displayName));
			}
			else
			{
				_logger.LogWarning((object)"No controller connected. Waiting for connection...");
			}
		}

		public void Update()
		{
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			ProcessDevInputs();
			if (_configManager.EnableMenuNavigation)
			{
				_menuNavigation.Update();
			}
			bool isControllerConnected = _isControllerConnected;
			_gamepad = GamepadHelper.FindActiveGamepad();
			_isControllerConnected = _gamepad != null;
			if (_isControllerConnected && !isControllerConnected)
			{
				_logger.LogInfo((object)("Controller connected: " + ((InputControl)_gamepad).displayName));
			}
			if (_configManager.EnableMenuNavigation && _menuNavigation.IsActive)
			{
				_vibrationManager.ClearRunSustain();
				if (_isControllerConnected)
				{
					_vibrationManager.SetGamepad(_gamepad);
					_ledManager.SetGamepad(_gamepad);
					_menuNavigation.ProcessControllerInput(_gamepad, _keyboardSimulator, _mouseSimulator, _vibrationManager);
				}
				_vibrationManager.Update();
				_ledManager.Update();
			}
			else if (!_isControllerConnected && isControllerConnected)
			{
				_logger.LogWarning((object)"Controller disconnected!");
				_vibrationManager.Stop();
				ReleaseAllKeys();
			}
			else
			{
				if (!_isControllerConnected)
				{
					return;
				}
				_vibrationManager.SetGamepad(_gamepad);
				_ledManager.SetGamepad(_gamepad);
				try
				{
					if (_configManager.DebugOutput)
					{
						Vector2 val = ((InputControl<Vector2>)(object)_gamepad.leftStick).ReadValue();
						Vector2 val2 = ((InputControl<Vector2>)(object)_gamepad.rightStick).ReadValue();
						_logger.LogInfo((object)$"Left Stick: X={val.x:F3}, Y={val.y:F3}");
						_logger.LogInfo((object)$"Right Stick: X={val2.x:F3}, Y={val2.y:F3}");
						_logger.LogInfo((object)$"Triggers: Left={((InputControl<float>)(object)_gamepad.leftTrigger).ReadValue():F3}, Right={((InputControl<float>)(object)_gamepad.rightTrigger).ReadValue():F3}");
					}
					ProcessButtonInputs(_gamepad);
					ProcessJoystickInputs(_gamepad);
					ProcessRunVibration(_gamepad);
					ProcessTriggerInputs(_gamepad);
					_vibrationManager.Update();
					_ledManager.Update();
					if (!_configManager.AutoReleaseShiftAfterWASD || !_keyboardSimulator.IsShiftPressed || !(Time.realtimeSinceStartup - _joystickZoneHandler.LastWASDActivityTime > _configManager.ShiftReleaseDelay))
					{
						return;
					}
					if (_configManager.EnableShiftToggle)
					{
						if (_keyboardSimulator.IsShiftPressed)
						{
							_keyboardSimulator.ToggleShift();
							if (_configManager.DebugOutput)
							{
								_logger.LogInfo((object)"Auto-released Shift after WASD inactivity");
							}
						}
					}
					else
					{
						_keyboardSimulator.SendKeyEvent((Key)51, isPressed: false);
						if (_configManager.DebugOutput)
						{
							_logger.LogInfo((object)"Auto-released Shift after WASD inactivity");
						}
					}
				}
				catch (Exception ex)
				{
					_logger.LogError((object)("Error reading controller: " + ex.Message));
					_isControllerConnected = false;
					ReleaseAllKeys();
				}
			}
		}

		private void ForceForegroundWindow(IntPtr hWnd)
		{
			if (!(hWnd == IntPtr.Zero))
			{
				uint windowThreadProcessId = GetWindowThreadProcessId(GetForegroundWindow(), IntPtr.Zero);
				uint currentThreadId = GetCurrentThreadId();
				if (windowThreadProcessId != currentThreadId)
				{
					AttachThreadInput(windowThreadProcessId, currentThreadId, fAttach: true);
					BringWindowToTop(hWnd);
					ShowWindow(hWnd, 5);
					AttachThreadInput(windowThreadProcessId, currentThreadId, fAttach: false);
				}
				else
				{
					BringWindowToTop(hWnd);
					ShowWindow(hWnd, 5);
				}
			}
		}

		private bool ActivateREPOProcess()
		{
			try
			{
				Process[] processesByName = Process.GetProcessesByName("REPO");
				if (processesByName.Length == 0)
				{
					if (_configManager.DebugOutput)
					{
						_logger.LogWarning((object)"No REPO.exe process found.");
					}
					return false;
				}
				Process process = processesByName.OrderByDescending((Process p) => p.WorkingSet64).FirstOrDefault((Process p) => p.MainWindowHandle != IntPtr.Zero);
				if (process == null)
				{
					process = processesByName.FirstOrDefault((Process p) => p.MainWindowHandle != IntPtr.Zero);
				}
				if (process != null)
				{
					ForceForegroundWindow(process.MainWindowHandle);
					if (_configManager.DebugOutput)
					{
						_logger.LogInfo((object)$"Activated REPO.exe process (PID: {process.Id})");
					}
					return true;
				}
				if (_configManager.DebugOutput)
				{
					_logger.LogWarning((object)"Could not find a valid window handle for any REPO.exe process.");
				}
				return false;
			}
			catch (Exception ex)
			{
				_logger.LogError((object)("Error activating REPO.exe process: " + ex.Message));
				return false;
			}
		}

		private void ProcessDevInputs()
		{
			if (_configManager.DevMode && Keyboard.current != null)
			{
				if (((ButtonControl)Keyboard.current[(Key)80]).wasPressedThisFrame)
				{
					float num = _configManager.IncreaseScrollSpeed();
					_logger.LogInfo((object)$"Increased ScrollSpeed to {num:F6}");
				}
				if (((ButtonControl)Keyboard.current[(Key)81]).wasPressedThisFrame)
				{
					float num2 = _configManager.DecreaseScrollSpeed();
					_logger.LogInfo((object)$"Decreased ScrollSpeed to {num2:F6}");
				}
				if (((ButtonControl)Keyboard.current[(Key)91]).wasPressedThisFrame)
				{
					float magnitude = (float)Math.Sqrt(_configManager.CurrentJoystickX * _configManager.CurrentJoystickX + _configManager.CurrentJoystickY * _configManager.CurrentJoystickY);
					float num3 = _configManager.UpdateDeadZoneRadius(magnitude);
					_logger.LogInfo((object)$"Updated DeadZoneRadius to {num3:F4} based on current joystick position");
				}
				if (((ButtonControl)Keyboard.current[(Key)88]).wasPressedThisFrame)
				{
					float num4 = _configManager.UpdateDiagonalZoneSize(_configManager.CurrentJoystickAngle);
					_logger.LogInfo((object)$"Updated DiagonalZoneSize to {num4:F4} based on current joystick angle");
				}
			}
		}

		private void RumbleInput(float lowFrequency, float highFrequency, float durationSeconds)
		{
			if (_configManager.EnableVibration && _configManager.EnableInputVibration)
			{
				_vibrationManager.Pulse(lowFrequency, highFrequency, durationSeconds);
			}
		}

		private void ProcessButtonInputs(Gamepad gamepad)
		{
			if (gamepad.buttonSouth.wasPressedThisFrame)
			{
				if (_configManager.ReleaseCtrlOnA && _keyboardSimulator.IsCtrlToggled)
				{
					_keyboardSimulator.ToggleCtrl();
					if (_configManager.DebugOutput)
					{
						_logger.LogInfo((object)"Released Ctrl due to A button press");
					}
				}
				_keyboardSimulator.SendKeyEvent((Key)1, isPressed: true);
				RumbleInput(0.12f, 0.22f, 0.07f);
				if (_configManager.DebugOutput)
				{
					_logger.LogInfo((object)"A pressed - Space");
				}
			}
			else if (gamepad.buttonSouth.wasReleasedThisFrame)
			{
				_keyboardSimulator.SendKeyEvent((Key)1, isPressed: false);
			}
			if (gamepad.buttonWest.wasPressedThisFrame)
			{
				_keyboardSimulator.SendKeyEvent((Key)19, isPressed: true);
				RumbleInput(0.1f, 0.18f, 0.06f);
				if (_configManager.DebugOutput)
				{
					_logger.LogInfo((object)"X pressed - E");
				}
			}
			else if (gamepad.buttonWest.wasReleasedThisFrame)
			{
				_keyboardSimulator.SendKeyEvent((Key)19, isPressed: false);
			}
			if (gamepad.buttonEast.wasPressedThisFrame)
			{
				if (_configManager.EnableCtrlToggle)
				{
					_keyboardSimulator.ToggleCtrl();
					RumbleInput(0.08f, 0.14f, 0.05f);
					if (_configManager.DebugOutput)
					{
						_logger.LogInfo((object)("B pressed - Ctrl " + (_keyboardSimulator.IsCtrlToggled ? "ON" : "OFF")));
					}
				}
				else
				{
					_keyboardSimulator.SendKeyEvent((Key)55, isPressed: true);
					if (_configManager.DebugOutput)
					{
						_logger.LogInfo((object)"B pressed - Ctrl");
					}
				}
			}
			else if (gamepad.buttonEast.wasReleasedThisFrame && !_configManager.EnableCtrlToggle)
			{
				_keyboardSimulator.SendKeyEvent((Key)55, isPressed: false);
			}
			if (gamepad.buttonNorth.wasPressedThisFrame)
			{
				_keyboardSimulator.SendKeyEvent((Key)31, isPressed: true);
				if (_configManager.DebugOutput)
				{
					_logger.LogInfo((object)"Y pressed - Q");
				}
			}
			else if (gamepad.buttonNorth.wasReleasedThisFrame)
			{
				_keyboardSimulator.SendKeyEvent((Key)31, isPressed: false);
			}
			if (gamepad.leftStickButton.wasPressedThisFrame)
			{
				if (_configManager.ReleaseCtrlOnShift && _keyboardSimulator.IsCtrlToggled)
				{
					_keyboardSimulator.ToggleCtrl();
					if (_configManager.DebugOutput)
					{
						_logger.LogInfo((object)"Released Ctrl due to Shift activation");
					}
				}
				if (_configManager.ReleaseTabOnShift && _keyboardSimulator.IsTabToggled)
				{
					_keyboardSimulator.ToggleTab();
					if (_configManager.DebugOutput)
					{
						_logger.LogInfo((object)"Released Tab due to Shift activation");
					}
				}
				if (_configManager.EnableShiftToggle)
				{
					_keyboardSimulator.ToggleShift();
					RumbleInput(0.08f, 0.14f, 0.05f);
					if (_configManager.DebugOutput)
					{
						_logger.LogInfo((object)("L3 pressed - Shift " + (_keyboardSimulator.IsShiftPressed ? "ON" : "OFF")));
					}
				}
				else
				{
					_keyboardSimulator.SendKeyEvent((Key)51, isPressed: true);
					if (_configManager.DebugOutput)
					{
						_logger.LogInfo((object)"L3 pressed - Shift ON");
					}
				}
			}
			else if (gamepad.leftStickButton.wasReleasedThisFrame && !_configManager.EnableShiftToggle)
			{
				_keyboardSimulator.SendKeyEvent((Key)51, isPressed: false);
				if (_configManager.DebugOutput)
				{
					_logger.LogInfo((object)"L3 released - Shift OFF");
				}
			}
			if (gamepad.rightShoulder.isPressed)
			{
				_mouseSimulator.Scroll(_configManager.ScrollSpeed);
				if (_configManager.DebugOutput)
				{
					_logger.LogInfo((object)$"RB held - Scroll Up ({_configManager.ScrollSpeed})");
				}
			}
			if (gamepad.leftShoulder.isPressed)
			{
				_mouseSimulator.Scroll(0f - _configManager.ScrollSpeed);
				if (_configManager.DebugOutput)
				{
					_logger.LogInfo((object)$"LB held - Scroll Down ({0f - _configManager.ScrollSpeed})");
				}
			}
			if (gamepad.dpad.left.wasPressedThisFrame)
			{
				_keyboardSimulator.SendKeyEvent((Key)41, isPressed: true);
				if (_configManager.DebugOutput)
				{
					_logger.LogInfo((object)"D-Pad Left - 1");
				}
			}
			else if (gamepad.dpad.left.wasReleasedThisFrame)
			{
				_keyboardSimulator.SendKeyEvent((Key)41, isPressed: false);
			}
			if (gamepad.dpad.up.wasPressedThisFrame)
			{
				_keyboardSimulator.SendKeyEvent((Key)42, isPressed: true);
				if (_configManager.DebugOutput)
				{
					_logger.LogInfo((object)"D-Pad Up - 2");
				}
			}
			else if (gamepad.dpad.up.wasReleasedThisFrame)
			{
				_keyboardSimulator.SendKeyEvent((Key)42, isPressed: false);
			}
			if (gamepad.dpad.right.wasPressedThisFrame)
			{
				_keyboardSimulator.SendKeyEvent((Key)43, isPressed: true);
				if (_configManager.DebugOutput)
				{
					_logger.LogInfo((object)"D-Pad Right - 3");
				}
			}
			else if (gamepad.dpad.right.wasReleasedThisFrame)
			{
				_keyboardSimulator.SendKeyEvent((Key)43, isPressed: false);
			}
			if (gamepad.startButton.wasPressedThisFrame)
			{
				_keyboardSimulator.SendKeyEvent((Key)60, isPressed: true);
				if (_configManager.DebugOutput)
				{
					_logger.LogInfo((object)"Start pressed - Escape");
				}
			}
			else if (gamepad.startButton.wasReleasedThisFrame)
			{
				_keyboardSimulator.SendKeyEvent((Key)60, isPressed: false);
			}
			if (gamepad.selectButton.wasPressedThisFrame)
			{
				if (_configManager.EnableTabToggle)
				{
					_keyboardSimulator.ToggleTab();
					RumbleInput(0.08f, 0.14f, 0.05f);
					if (_configManager.DebugOutput)
					{
						_logger.LogInfo((object)("Back pressed - Tab " + (_keyboardSimulator.IsTabToggled ? "ON" : "OFF")));
					}
				}
				else
				{
					_keyboardSimulator.SendKeyEvent((Key)3, isPressed: true);
					if (_configManager.DebugOutput)
					{
						_logger.LogInfo((object)"Back pressed - Tab");
					}
				}
			}
			else if (gamepad.selectButton.wasReleasedThisFrame && !_configManager.EnableTabToggle)
			{
				_keyboardSimulator.SendKeyEvent((Key)3, isPressed: false);
			}
		}

		private void ProcessJoystickInputs(Gamepad gamepad)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = ((InputControl<Vector2>)(object)gamepad.leftStick).ReadValue();
			Vector2 val2 = ((InputControl<Vector2>)(object)gamepad.rightStick).ReadValue();
			short x = (short)(Mathf.Clamp(val.x, -1f, 1f) * 32767f);
			short y = (short)(Mathf.Clamp(val.y, -1f, 1f) * 32767f);
			short x2 = (short)(Mathf.Clamp(val2.x, -1f, 1f) * 32767f);
			short y2 = (short)(Mathf.Clamp(val2.y, -1f, 1f) * 32767f);
			_joystickZoneHandler.ProcessLeftJoystick(x, y);
			_mouseSimulator.MoveMouse(x2, y2);
		}

		private void ProcessRunVibration(Gamepad gamepad)
		{
			//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)
			if (!_configManager.EnableVibration || !_configManager.EnableInputVibration)
			{
				_vibrationManager.ClearRunSustain();
				return;
			}
			if (!_keyboardSimulator.IsShiftPressed)
			{
				_vibrationManager.ClearRunSustain();
				return;
			}
			Vector2 val = ((InputControl<Vector2>)(object)gamepad.leftStick).ReadValue();
			float deadZoneRadius = _configManager.DeadZoneRadius;
			if (((Vector2)(ref val)).sqrMagnitude <= deadZoneRadius * deadZoneRadius)
			{
				_vibrationManager.ClearRunSustain();
				return;
			}
			float num = Mathf.Clamp01(((Vector2)(ref val)).magnitude);
			_vibrationManager.SetRunSustain(Mathf.Lerp(0.05f, 0.12f, num), Mathf.Lerp(0.08f, 0.16f, num));
		}

		private void ProcessTriggerInputs(Gamepad gamepad)
		{
			float num = ((InputControl<float>)(object)gamepad.leftTrigger).ReadValue();
			float num2 = ((InputControl<float>)(object)gamepad.rightTrigger).ReadValue();
			if (num2 > 0.5f && _previousRightTrigger <= 0.5f)
			{
				ActivateREPOProcess();
				_mouseSimulator.LeftMouseDown();
				RumbleInput(0.18f, 0.35f, 0.08f);
				if (_configManager.DebugOutput)
				{
					_logger.LogInfo((object)"RT pressed - Left Mouse Down");
				}
			}
			else if (num2 <= 0.5f && _previousRightTrigger > 0.5f)
			{
				_mouseSimulator.LeftMouseUp();
			}
			if (num > 0.5f && _previousLeftTrigger <= 0.5f)
			{
				_mouseSimulator.RightMouseDown();
				RumbleInput(0.1f, 0.16f, 0.06f);
				if (_configManager.DebugOutput)
				{
					_logger.LogInfo((object)"LT pressed - Right Mouse Down");
				}
			}
			else if (num <= 0.5f && _previousLeftTrigger > 0.5f)
			{
				_mouseSimulator.RightMouseUp();
			}
			_previousLeftTrigger = num;
			_previousRightTrigger = num2;
		}

		public void ReleaseAllKeys()
		{
			_keyboardSimulator.ReleaseAllKeys();
			_mouseSimulator.ReleaseAllButtons();
			_previousLeftTrigger = 0f;
			_previousRightTrigger = 0f;
		}
	}
	public class JoystickZoneHandler
	{
		private readonly ManualLogSource _logger;

		private readonly ConfigManager _configManager;

		private readonly KeyboardSimulator _keyboardSimulator;

		private float _lastX;

		private float _lastY;

		private bool _lastWPressed;

		private bool _lastAPressed;

		private bool _lastSPressed;

		private bool _lastDPressed;

		private float _lastWASDActivityTime;

		public float LastWASDActivityTime => _lastWASDActivityTime;

		public JoystickZoneHandler(ManualLogSource logger, ConfigManager configManager, KeyboardSimulator keyboardSimulator)
		{
			_logger = logger;
			_configManager = configManager;
			_keyboardSimulator = keyboardSimulator;
			_lastWASDActivityTime = Time.realtimeSinceStartup;
		}

		public void ProcessLeftJoystick(short x, short y)
		{
			float num = (float)x / 32768f;
			float num2 = (float)y / 32768f;
			_configManager.CurrentJoystickX = num;
			_configManager.CurrentJoystickY = num2;
			bool flag = Math.Abs(num - _lastX) > 0.01f || Math.Abs(num2 - _lastY) > 0.01f;
			_lastX = num;
			_lastY = num2;
			float num3 = (float)Math.Sqrt(num * num + num2 * num2);
			bool flag2 = false;
			bool flag3 = false;
			bool flag4 = false;
			bool flag5 = false;
			if (!(num3 < _configManager.DeadZoneRadius))
			{
				float num4 = (float)Math.Atan2(num2, num) * 180f / (float)Math.PI;
				if (num4 < 0f)
				{
					num4 += 360f;
				}
				_configManager.CurrentJoystickAngle = num4;
				if (num4 > 45f && num4 < 135f)
				{
					flag2 = true;
				}
				else if (num4 > 225f && num4 < 315f)
				{
					flag4 = true;
				}
				else if (num4 > 135f && num4 < 225f)
				{
					flag3 = true;
				}
				else if (num4 < 45f || num4 > 315f)
				{
					flag5 = true;
				}
				if (num4 > 45f && num4 < 75f)
				{
					flag2 = true;
					flag5 = true;
				}
				else if (num4 > 105f && num4 < 135f)
				{
					flag2 = true;
					flag3 = true;
				}
				else if (num4 > 225f && num4 < 255f)
				{
					flag4 = true;
					flag3 = true;
				}
				else if (num4 > 285f && num4 < 315f)
				{
					flag4 = true;
					flag5 = true;
				}
				if (flag && _configManager.DebugOutput)
				{
					_logger.LogInfo((object)$"Joystick: X={num:F2}, Y={num2:F2}, Angle={num4:F1}, Magnitude={num3:F2}");
				}
			}
			if (flag2 || flag3 || flag4 || flag5)
			{
				_lastWASDActivityTime = Time.realtimeSinceStartup;
			}
			if (flag2 != _lastWPressed)
			{
				_keyboardSimulator.SendKeyEvent((Key)37, flag2);
				_lastWPressed = flag2;
				if (_configManager.DebugOutput)
				{
					_logger.LogInfo((object)("W key " + (flag2 ? "pressed" : "released")));
				}
			}
			if (flag3 != _lastAPressed)
			{
				_keyboardSimulator.SendKeyEvent((Key)15, flag3);
				_lastAPressed = flag3;
				if (_configManager.DebugOutput)
				{
					_logger.LogInfo((object)("A key " + (flag3 ? "pressed" : "released")));
				}
			}
			if (flag4 != _lastSPressed)
			{
				_keyboardSimulator.SendKeyEvent((Key)33, flag4);
				_lastSPressed = flag4;
				if (_configManager.DebugOutput)
				{
					_logger.LogInfo((object)("S key " + (flag4 ? "pressed" : "released")));
				}
			}
			if (flag5 != _lastDPressed)
			{
				_keyboardSimulator.SendKeyEvent((Key)18, flag5);
				_lastDPressed = flag5;
				if (_configManager.DebugOutput)
				{
					_logger.LogInfo((object)("D key " + (flag5 ? "pressed" : "released")));
				}
			}
		}

		public void ReleaseAllDirectionKeys()
		{
			if (Keyboard.current != null)
			{
				if (_lastWPressed)
				{
					_keyboardSimulator.SendKeyEvent((Key)37, isPressed: false);
				}
				if (_lastAPressed)
				{
					_keyboardSimulator.SendKeyEvent((Key)15, isPressed: false);
				}
				if (_lastSPressed)
				{
					_keyboardSimulator.SendKeyEvent((Key)33, isPressed: false);
				}
				if (_lastDPressed)
				{
					_keyboardSimulator.SendKeyEvent((Key)18, isPressed: false);
				}
				_lastWPressed = false;
				_lastAPressed = false;
				_lastSPressed = false;
				_lastDPressed = false;
			}
		}
	}
	public class KeyboardSimulator
	{
		private readonly ManualLogSource _logger;

		private readonly ConfigManager _configManager;

		private bool _wPressed;

		private bool _aPressed;

		private bool _sPressed;

		private bool _dPressed;

		private bool _shiftPressed;

		private bool _ctrlToggled;

		private bool _tabToggled;

		public bool IsWPressed => _wPressed;

		public bool IsAPressed => _aPressed;

		public bool IsSPressed => _sPressed;

		public bool IsDPressed => _dPressed;

		public bool IsShiftPressed => _shiftPressed;

		public bool IsCtrlToggled => _ctrlToggled;

		public bool IsTabToggled => _tabToggled;

		public KeyboardSimulator(ManualLogSource logger, ConfigManager configManager)
		{
			_logger = logger;
			_configManager = configManager;
		}

		public void ToggleCtrl()
		{
			_ctrlToggled = !_ctrlToggled;
			SendKeyEvent((Key)55, _ctrlToggled);
		}

		public void ToggleTab()
		{
			_tabToggled = !_tabToggled;
			SendKeyEvent((Key)3, _tabToggled);
		}

		public void ToggleShift()
		{
			_shiftPressed = !_shiftPressed;
			SendKeyEvent((Key)51, _shiftPressed);
		}

		public void SendKeyEvent(Key key, bool isPressed)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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_00ca: Unknown result type (might be due to invalid IL or missing references)
			if (Keyboard.current != null)
			{
				UpdateKeyState(key, isPressed);
				KeyboardState val = default(KeyboardState);
				if (_wPressed)
				{
					((KeyboardState)(ref val)).Set((Key)37, true);
				}
				if (_aPressed)
				{
					((KeyboardState)(ref val)).Set((Key)15, true);
				}
				if (_sPressed)
				{
					((KeyboardState)(ref val)).Set((Key)33, true);
				}
				if (_dPressed)
				{
					((KeyboardState)(ref val)).Set((Key)18, true);
				}
				if (_shiftPressed)
				{
					((KeyboardState)(ref val)).Set((Key)51, true);
				}
				if (_ctrlToggled)
				{
					((KeyboardState)(ref val)).Set((Key)55, true);
				}
				if (_tabToggled)
				{
					((KeyboardState)(ref val)).Set((Key)3, true);
				}
				((KeyboardState)(ref val)).Set(key, isPressed);
				InputSystem.QueueStateEvent<KeyboardState>((InputDevice)(object)Keyboard.current, val, -1.0);
				if (_configManager.DebugOutput)
				{
					_logger.LogInfo((object)string.Format("Key {0} {1}", key, isPressed ? "pressed" : "released"));
				}
			}
		}

		private void UpdateKeyState(Key key, bool isPressed)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Invalid comparison between Unknown and I4
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Invalid comparison between Unknown and I4
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Invalid comparison between Unknown and I4
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Invalid comparison between Unknown and I4
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Invalid comparison between Unknown and I4
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Invalid comparison between Unknown and I4
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Invalid comparison between Unknown and I4
			if ((int)key <= 18)
			{
				if ((int)key != 3)
				{
					if ((int)key != 15)
					{
						if ((int)key == 18)
						{
							_dPressed = isPressed;
						}
					}
					else
					{
						_aPressed = isPressed;
					}
				}
				else
				{
					_tabToggled = isPressed;
				}
			}
			else if ((int)key <= 37)
			{
				if ((int)key != 33)
				{
					if ((int)key == 37)
					{
						_wPressed = isPressed;
					}
				}
				else
				{
					_sPressed = isPressed;
				}
			}
			else if ((int)key != 51)
			{
				if ((int)key == 55)
				{
					_ctrlToggled = isPressed;
				}
			}
			else
			{
				_shiftPressed = isPressed;
			}
		}

		public void ReleaseAllKeys()
		{
			try
			{
				if (Keyboard.current != null)
				{
					if (_wPressed)
					{
						SendKeyEvent((Key)37, isPressed: false);
					}
					if (_aPressed)
					{
						SendKeyEvent((Key)15, isPressed: false);
					}
					if (_sPressed)
					{
						SendKeyEvent((Key)33, isPressed: false);
					}
					if (_dPressed)
					{
						SendKeyEvent((Key)18, isPressed: false);
					}
					if (_shiftPressed)
					{
						SendKeyEvent((Key)51, isPressed: false);
					}
					if (_ctrlToggled)
					{
						SendKeyEvent((Key)55, isPressed: false);
					}
					if (_tabToggled)
					{
						SendKeyEvent((Key)3, isPressed: false);
					}
					SendKeyEvent((Key)1, isPressed: false);
					SendKeyEvent((Key)19, isPressed: false);
					SendKeyEvent((Key)31, isPressed: false);
					SendKeyEvent((Key)41, isPressed: false);
					SendKeyEvent((Key)42, isPressed: false);
					SendKeyEvent((Key)43, isPressed: false);
					SendKeyEvent((Key)60, isPressed: false);
					SendKeyEvent((Key)3, isPressed: false);
				}
			}
			catch (ArgumentNullException ex)
			{
				if (_configManager.DebugOutput)
				{
					_logger.LogError((object)("Error releasing keys: " + ex.Message));
				}
			}
		}
	}
	internal class MenuNavigationManager
	{
		private const int MenuStateOpen = 0;

		private const float NavInitialDelay = 0.35f;

		private const float NavRepeatInterval = 0.12f;

		private const float RowYTolerance = 40f;

		private readonly ManualLogSource _logger;

		private readonly ConfigManager _configManager;

		private MenuSelectableElement _focusedElement;

		private MenuPage _currentPage;

		private readonly List<MenuSelectableElement> _elements = new List<MenuSelectableElement>();

		private int _lastSourceElementCount = -1;

		private Vector2 _activeDirection;

		private float _nextRepeatTime;

		private bool _wasMenuActive;

		private int _focusedIndex = -1;

		private float _previousRightTrigger;

		public bool IsActive { get; private set; }

		public MenuSelectableElement FocusedElement => _focusedElement;

		public MenuNavigationManager(ManualLogSource logger, ConfigManager configManager)
		{
			_logger = logger;
			_configManager = configManager;
		}

		internal MenuButton GetFocusedMenuButton()
		{
			if (!((Object)(object)_focusedElement == (Object)null))
			{
				return FindMenuButton(_focusedElement);
			}
			return null;
		}

		public bool TryGetForcedHover(RectTransform rectTransform, out bool hover)
		{
			hover = false;
			if (!IsActive || (Object)(object)_focusedElement == (Object)null || (Object)(object)rectTransform == (Object)null)
			{
				return false;
			}
			hover = IsFocusedRect(rectTransform);
			return true;
		}

		public bool TryGetSyntheticMousePosition(out Vector2 position)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			position = default(Vector2);
			if (!IsActive || (Object)(object)_focusedElement == (Object)null)
			{
				return false;
			}
			RectTransform focusRectTransform = GetFocusRectTransform(_focusedElement);
			if ((Object)(object)focusRectTransform == (Object)null)
			{
				return false;
			}
			position = SemiFunc.UIGetRectTransformPositionOnScreen(focusRectTransform, false);
			return true;
		}

		public void Update()
		{
			UpdateMenuState();
		}

		public void ProcessControllerInput(Gamepad gamepad, KeyboardSimulator keyboard, MouseSimulator mouse, VibrationManager vibration)
		{
			//IL_002a: 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_0031: Unknown result type (might be due to invalid IL or missing references)
			if (IsActive)
			{
				if (!_wasMenuActive)
				{
					keyboard.ReleaseAllKeys();
					mouse.ReleaseAllButtons();
				}
				RefreshElements();
				EnsureFocus();
				Vector2 navInput = ReadNavig