Decompiled source of GamepadFixes v1.0.2

GamepadFixes.dll

Decompiled 15 hours ago
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Rewired;
using RoR2.RemoteGameBrowser;
using RoR2.UI;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("GamepadFixes")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.2.0")]
[assembly: AssemblyInformationalVersion("1.0.2")]
[assembly: AssemblyProduct("GamepadFixes")]
[assembly: AssemblyTitle("GamepadFixes")]
[assembly: AssemblyVersion("1.0.2.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace GamepadFixes
{
	internal class GamepadTextField : MonoBehaviour
	{
		internal static readonly Color HighlightColor = new Color(0.984f, 0.761f, 0.165f, 1f);

		private static FieldRef<TMP_InputField, bool> shouldActivateNextUpdate;

		private TMP_InputField field;

		private Selectable row;

		private Graphic outline;

		private Color outlineColor;

		private MPEventSystemLocator locator;

		private bool wasFocused;

		private int activateFrame = -1;

		private string lastDiagnostic;

		private bool diagnosticWasSelected;

		private static MPEventSystem cancelConsumedBy;

		private static int cancelConsumedFrame = -1;

		public static void Attach(TMP_InputField field, MPButton row, Graphic outline = null)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: 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_00a0: Expected O, but got Unknown
			if (!((Object)(object)field == (Object)null) && !((Object)(object)((Component)field).GetComponent<GamepadTextField>() != (Object)null))
			{
				GamepadTextField gamepadTextField = ((Component)field).gameObject.AddComponent<GamepadTextField>();
				gamepadTextField.field = field;
				gamepadTextField.row = (Selectable)(object)row;
				gamepadTextField.outline = outline;
				gamepadTextField.outlineColor = (((Object)(object)outline != (Object)null) ? outline.color : Color.white);
				gamepadTextField.locator = ((Component)field).GetComponent<MPEventSystemLocator>();
				if ((Object)(object)gamepadTextField.locator == (Object)null)
				{
					gamepadTextField.locator = ((Component)field).gameObject.AddComponent<MPEventSystemLocator>();
				}
				if ((Object)(object)row != (Object)null)
				{
					((UnityEvent)((Button)row).onClick).AddListener(new UnityAction(gamepadTextField.BeginEdit));
				}
			}
		}

		internal static void TMP_InputField_OnSelect(TMP_InputField __instance)
		{
			GamepadTextField component = ((Component)__instance).GetComponent<GamepadTextField>();
			if (!((Object)(object)component == (Object)null) && component.IsGamepad(out var _))
			{
				if (shouldActivateNextUpdate == null)
				{
					shouldActivateNextUpdate = AccessTools.FieldRefAccess<TMP_InputField, bool>("m_ShouldActivateNextUpdate");
				}
				shouldActivateNextUpdate.Invoke(__instance) = false;
			}
		}

		public static bool IsConsumingCancel(MPEventSystem eventSystem)
		{
			if ((Object)(object)eventSystem != (Object)null && (Object)(object)cancelConsumedBy == (Object)(object)eventSystem && cancelConsumedFrame == Time.frameCount)
			{
				return true;
			}
			return IsEditing(eventSystem);
		}

		private static bool IsEditing(MPEventSystem eventSystem)
		{
			GameObject val = (((Object)(object)eventSystem != (Object)null) ? ((EventSystem)eventSystem).currentSelectedGameObject : null);
			GamepadTextField gamepadTextField = (((Object)(object)val != (Object)null) ? val.GetComponent<GamepadTextField>() : null);
			if ((Object)(object)gamepadTextField != (Object)null && (Object)(object)gamepadTextField.field != (Object)null)
			{
				return gamepadTextField.field.isFocused;
			}
			return false;
		}

		internal static bool MPButton_OnPointerEnter(MPButton __instance)
		{
			return !IsEditing(__instance.eventSystem);
		}

		internal static bool MPControlHelper_OnPointerEnter(ref MPControlHelper __instance)
		{
			return !IsEditing(((MPControlHelper)(ref __instance)).eventSystem);
		}

		private bool IsGamepad(out MPEventSystem eventSystem)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Invalid comparison between Unknown and I4
			eventSystem = (((Object)(object)locator != (Object)null) ? locator.eventSystem : null);
			if ((Object)(object)eventSystem != (Object)null)
			{
				return (int)eventSystem.currentInputSource == 1;
			}
			return false;
		}

		private void BeginEdit()
		{
			if (IsGamepad(out var eventSystem))
			{
				((EventSystem)eventSystem).SetSelectedGameObject(((Component)field).gameObject);
				field.ActivateInputField();
				activateFrame = Time.frameCount;
			}
		}

		private void Update()
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Invalid comparison between Unknown and I4
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			MPEventSystem val = (((Object)(object)locator != (Object)null) ? locator.eventSystem : null);
			bool flag = (Object)(object)field != (Object)null && (Object)(object)val != (Object)null && val.player != null && (Object)(object)((EventSystem)val).currentSelectedGameObject == (Object)(object)((Component)field).gameObject;
			bool flag2 = flag && (int)val.currentInputSource == 1;
			if (Plugin.TextBoxDiagnostics.Value)
			{
				LogDiagnostics(val, flag);
			}
			if ((Object)(object)outline != (Object)null)
			{
				outline.color = (flag2 ? HighlightColor : outlineColor);
			}
			if (!flag)
			{
				wasFocused = false;
				activateFrame = -1;
				return;
			}
			Player player = val.player;
			if (field.isFocused)
			{
				wasFocused = true;
				activateFrame = -1;
				if (!flag2)
				{
					return;
				}
				bool buttonDown = player.GetButtonDown(15);
				if (buttonDown || player.GetButtonDown(13) || player.GetNegativeButtonDown(13))
				{
					if (buttonDown)
					{
						cancelConsumedBy = val;
						cancelConsumedFrame = Time.frameCount;
					}
					field.DeactivateInputField(false);
					ReturnToRow(val);
				}
			}
			else if (flag2)
			{
				if (wasFocused || (activateFrame >= 0 && Time.frameCount > activateFrame + 2))
				{
					ReturnToRow(val);
				}
				else if ((Object)(object)row == (Object)null && player.GetButtonDown(14))
				{
					BeginEdit();
				}
			}
		}

		private void LogDiagnostics(MPEventSystem eventSystem, bool selected)
		{
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			if (selected || diagnosticWasSelected)
			{
				string text = (((Object)(object)row != (Object)null) ? ((Object)row).name : ((Object)((Component)field).transform.parent).name);
				GameObject val = (((Object)(object)eventSystem != (Object)null) ? ((EventSystem)eventSystem).currentSelectedGameObject : null);
				string text2 = (selected ? $"selected, typing={field.isFocused}, windowFocused={Application.isFocused}, input={eventSystem.currentInputSource}" : ("lost selection to '" + (((Object)(object)val != (Object)null) ? ((Object)val).name : "nothing") + "'"));
				if (text2 != lastDiagnostic)
				{
					Plugin.Log.LogInfo((object)("[Text box " + text + "] " + text2));
					lastDiagnostic = text2;
				}
				if (selected && !string.IsNullOrEmpty(Input.inputString))
				{
					Plugin.Log.LogInfo((object)$"[Text box {text}] {Input.inputString.Length} character(s) reached the game this frame");
				}
				diagnosticWasSelected = selected;
			}
		}

		private void ReturnToRow(MPEventSystem eventSystem)
		{
			wasFocused = false;
			activateFrame = -1;
			if ((Object)(object)row != (Object)null)
			{
				((EventSystem)eventSystem).SetSelectedGameObject(((Component)row).gameObject);
			}
		}
	}
	internal static class MultiplayerMenuFixes
	{
		private const string HostGameButtonName = "HostGameButton";

		private const string FilterMainControlName = "MainControl";

		private const string CancelActionName = "UICancel";

		private const string FilterOutlineName = "Outline for Depth";

		private static readonly HashSet<int> loggedObjects = new HashSet<int>();

		internal static void HostGamePanel_OnEnable(HostGamePanelController __instance)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			try
			{
				Transform val = (((Object)(object)__instance.gameModePicker != (Object)null) ? ((Component)__instance.gameModePicker).transform.parent : null);
				if ((Object)(object)val == (Object)null)
				{
					LogOnce((Object)(object)__instance, "Host Game panel layout not found, its gamepad fix is skipped", error: true);
					return;
				}
				List<Selectable> list = new List<Selectable>();
				foreach (Transform item in val)
				{
					Transform val2 = item;
					Selectable val3 = (((Component)val2).gameObject.activeSelf ? FindSelectable(val2) : null);
					if ((Object)(object)val3 != (Object)null)
					{
						list.Add(val3);
					}
				}
				Transform val4 = (((Object)(object)val.parent != (Object)null) ? val.parent.Find("HostGameButton") : null);
				if ((Object)(object)val4 != (Object)null && ((Component)val4).gameObject.activeSelf)
				{
					Selectable component = ((Component)val4).GetComponent<Selectable>();
					if (component != null)
					{
						list.Add(component);
					}
				}
				LinkVertically(list);
				SettingsTextBox[] componentsInChildren = ((Component)val).GetComponentsInChildren<SettingsTextBox>(true);
				foreach (SettingsTextBox val5 in componentsInChildren)
				{
					GamepadTextField.Attach(val5.textbox, ((Component)val5).GetComponent<MPButton>());
				}
				LogOnce((Object)(object)__instance, $"Linked {list.Count} Host Game panel controls for gamepad navigation");
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Failed to fix Host Game panel navigation: {arg}");
			}
		}

		internal static void RemoteGameBrowser_Start(RemoteGameBrowserController __instance)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Invalid comparison between Unknown and I4
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				RectTransform filterControlContainer = __instance.filterControlContainer;
				if ((Object)(object)filterControlContainer == (Object)null)
				{
					return;
				}
				int num = 0;
				List<Selectable> list = new List<Selectable>();
				foreach (Transform item in (Transform)filterControlContainer)
				{
					Transform val = item;
					if (!((Component)val).gameObject.activeSelf)
					{
						continue;
					}
					Transform val2 = val.Find("MainControl");
					Selectable val3 = (((Object)(object)val2 != (Object)null) ? ((Component)val2).GetComponent<Selectable>() : null);
					if (!((Object)(object)val3 == (Object)null))
					{
						if (EnableNavigation(val3))
						{
							num++;
						}
						list.Add(val3);
						TMP_InputField val4 = (TMP_InputField)(object)((val3 is TMP_InputField) ? val3 : null);
						if (val4 != null)
						{
							Transform val5 = ((Component)val4).transform.Find("Outline for Depth");
							GamepadTextField.Attach(val4, null, ((Object)(object)val5 != (Object)null) ? ((Component)val5).GetComponent<Graphic>() : null);
						}
					}
				}
				VerticalNavLink.Chain(list);
				ScrollRect componentInParent = ((Component)filterControlContainer).GetComponentInParent<ScrollRect>(true);
				if ((Object)(object)componentInParent != (Object)null && (Object)(object)((Component)componentInParent).GetComponent<ScrollToSelection>() == (Object)null)
				{
					((Component)componentInParent).gameObject.AddComponent<ScrollToSelection>();
				}
				int num2 = 0;
				Transform val6 = (((Object)(object)__instance.cardPrefab != (Object)null) ? __instance.cardPrefab.transform.parent : null);
				if ((Object)(object)val6 != (Object)null)
				{
					foreach (Transform item2 in val6)
					{
						Selectable component = ((Component)item2).GetComponent<Selectable>();
						if ((Object)(object)component != (Object)null)
						{
							Navigation navigation = component.navigation;
							if ((int)((Navigation)(ref navigation)).mode == 2)
							{
								Navigation navigation2 = component.navigation;
								((Navigation)(ref navigation2)).mode = (Mode)3;
								component.navigation = navigation2;
								num2++;
							}
						}
					}
				}
				LogOnce((Object)(object)__instance, $"Enabled gamepad navigation on {num} server browser filters and {num2} game cards");
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Failed to fix server browser filter navigation: {arg}");
			}
		}

		internal static void LobbyUserList_Awake(LobbyUserList __instance)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				EnableNavigation((Selectable)(object)__instance.copyLobbyButton);
				foreach (Transform item in ((Component)__instance).transform)
				{
					MPButton component = ((Component)item).GetComponent<MPButton>();
					if ((Object)(object)component != (Object)null && EnableNavigation((Selectable)(object)component))
					{
						LogOnce((Object)(object)component, "Enabled gamepad navigation on lobby button '" + ((Object)component).name + "'");
					}
				}
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Failed to fix lobby panel navigation: {arg}");
			}
		}

		internal static bool HGGamepadInputEvent_Update(HGGamepadInputEvent __instance)
		{
			try
			{
				if (__instance.actionName != "UICancel")
				{
					return true;
				}
				MPEventSystemLocator component = ((Component)__instance).GetComponent<MPEventSystemLocator>();
				return !GamepadTextField.IsConsumingCancel(((Object)(object)component != (Object)null) ? component.eventSystem : null);
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Failed to check gamepad cancel input: {arg}");
				return true;
			}
		}

		internal static void MPToggle_LateUpdate(MPToggle __instance)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Invalid comparison between Unknown and I4
			try
			{
				Graphic hoverGraphic = __instance.hoverGraphic;
				if (!((Object)(object)hoverGraphic == (Object)null) && !((Behaviour)hoverGraphic).enabled)
				{
					MPEventSystemLocator component = ((Component)__instance).GetComponent<MPEventSystemLocator>();
					MPEventSystem val = (((Object)(object)component != (Object)null) ? component.eventSystem : null);
					if ((Object)(object)val != (Object)null && (int)val.currentInputSource == 1 && (Object)(object)((EventSystem)val).currentSelectedGameObject == (Object)(object)((Component)__instance).gameObject)
					{
						((Behaviour)hoverGraphic).enabled = true;
					}
				}
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Failed to update checkbox highlight: {arg}");
			}
		}

		private static Selectable FindSelectable(Transform row)
		{
			Selectable component = ((Component)row).GetComponent<Selectable>();
			if (!((Object)(object)component != (Object)null))
			{
				return ((Component)row).GetComponentInChildren<Selectable>();
			}
			return component;
		}

		private static void LinkVertically(List<Selectable> chain)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < chain.Count; i++)
			{
				Navigation navigation = chain[i].navigation;
				((Navigation)(ref navigation)).mode = (Mode)4;
				((Navigation)(ref navigation)).selectOnUp = ((i > 0) ? chain[i - 1] : null);
				((Navigation)(ref navigation)).selectOnDown = ((i < chain.Count - 1) ? chain[i + 1] : null);
				chain[i].navigation = navigation;
			}
		}

		private static bool EnableNavigation(Selectable selectable)
		{
			//IL_000a: 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)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)selectable == (Object)null))
			{
				Navigation navigation = selectable.navigation;
				if ((int)((Navigation)(ref navigation)).mode == 0)
				{
					Navigation navigation2 = selectable.navigation;
					((Navigation)(ref navigation2)).mode = (Mode)3;
					selectable.navigation = navigation2;
					return true;
				}
			}
			return false;
		}

		private static void LogOnce(Object owner, string message, bool error = false)
		{
			if (loggedObjects.Add(owner.GetInstanceID()))
			{
				if (error)
				{
					Plugin.Log.LogError((object)message);
				}
				else
				{
					Plugin.Log.LogInfo((object)message);
				}
			}
		}
	}
	internal static class PickupPickerFixes
	{
		private static FieldRef<PickupPickerPanel, UIElementAllocator<MPButton>> buttonAllocator;

		private static readonly HashSet<int> fallbackDisabled = new HashSet<int>();

		internal static void PickupPickerPanel_Refresh(PickupPickerPanel __instance)
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (buttonAllocator == null)
				{
					buttonAllocator = AccessTools.FieldRefAccess<PickupPickerPanel, UIElementAllocator<MPButton>>("buttonAllocator");
				}
				ReadOnlyCollection<MPButton> readOnlyCollection = buttonAllocator.Invoke(__instance)?.elements;
				if (readOnlyCollection == null)
				{
					return;
				}
				foreach (MPButton item in readOnlyCollection)
				{
					UpdateFallback(item);
				}
				int columnCount = GetColumnCount(__instance, readOnlyCollection.Count);
				if (columnCount <= 0)
				{
					return;
				}
				for (int i = 0; i < readOnlyCollection.Count; i++)
				{
					MPButton val = readOnlyCollection[i];
					if (((Selectable)val).interactable)
					{
						Navigation navigation = ((Selectable)val).navigation;
						((Navigation)(ref navigation)).mode = (Mode)4;
						((Navigation)(ref navigation)).selectOnLeft = FindInRow(readOnlyCollection, columnCount, i, -1);
						((Navigation)(ref navigation)).selectOnRight = FindInRow(readOnlyCollection, columnCount, i, 1);
						((Navigation)(ref navigation)).selectOnUp = FindInColumn(readOnlyCollection, columnCount, i, -1);
						((Navigation)(ref navigation)).selectOnDown = FindInColumn(readOnlyCollection, columnCount, i, 1);
						((Selectable)val).navigation = navigation;
					}
				}
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Failed to fix item picker navigation: {arg}");
			}
		}

		private static int GetColumnCount(PickupPickerPanel panel, int buttonCount)
		{
			//IL_001e: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Invalid comparison between Unknown and I4
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Invalid comparison between Unknown and I4
			GridLayoutGroup gridlayoutGroup = panel.gridlayoutGroup;
			if ((Object)(object)gridlayoutGroup == (Object)null)
			{
				return Mathf.Max(1, panel.maxColumnCount);
			}
			if ((int)gridlayoutGroup.startAxis != 0 || (int)gridlayoutGroup.startCorner != 0)
			{
				return 0;
			}
			Constraint constraint = gridlayoutGroup.constraint;
			if ((int)constraint != 1)
			{
				if ((int)constraint == 2)
				{
					return Mathf.Max(1, Mathf.CeilToInt((float)buttonCount / (float)Mathf.Max(1, gridlayoutGroup.constraintCount) - 0.001f));
				}
				return 0;
			}
			return Mathf.Max(1, gridlayoutGroup.constraintCount);
		}

		private static void UpdateFallback(MPButton button)
		{
			int instanceID = ((Object)button).GetInstanceID();
			if (!((Selectable)button).interactable && button.defaultFallbackButton)
			{
				button.defaultFallbackButton = false;
				fallbackDisabled.Add(instanceID);
			}
			else if (((Selectable)button).interactable && fallbackDisabled.Remove(instanceID))
			{
				button.defaultFallbackButton = true;
			}
		}

		private static Selectable FindInRow(IList<MPButton> buttons, int columns, int index, int step)
		{
			int num = index - index % columns;
			for (int i = index % columns + step; i >= 0 && i < columns; i += step)
			{
				int num2 = num + i;
				if (num2 >= buttons.Count)
				{
					break;
				}
				if (((Selectable)buttons[num2]).interactable)
				{
					return (Selectable)(object)buttons[num2];
				}
			}
			return null;
		}

		private static Selectable FindInColumn(IList<MPButton> buttons, int columns, int index, int step)
		{
			int num = (buttons.Count + columns - 1) / columns;
			int num2 = index % columns;
			for (int i = index / columns + step; i >= 0 && i < num; i += step)
			{
				int num3 = i * columns + num2;
				if (num3 < buttons.Count && ((Selectable)buttons[num3]).interactable)
				{
					return (Selectable)(object)buttons[num3];
				}
			}
			for (int j = index / columns + step; j >= 0 && j < num; j += step)
			{
				Selectable val = null;
				int num4 = int.MaxValue;
				for (int k = 0; k < columns; k++)
				{
					int num5 = j * columns + k;
					if (num5 >= buttons.Count)
					{
						break;
					}
					int num6 = Math.Abs(k - num2);
					if (((Selectable)buttons[num5]).interactable && num6 < num4)
					{
						val = (Selectable)(object)buttons[num5];
						num4 = num6;
					}
				}
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}
	}
	[BepInPlugin("com.syntaxspecter.GamepadFixes", "GamepadFixes", "1.0.2")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.syntaxspecter.GamepadFixes";

		public const string PluginName = "GamepadFixes";

		public const string PluginVersion = "1.0.2";

		private const string GameModeSettingName = "gamemode";

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> TextBoxDiagnostics;

		private Harmony harmony;

		public void Awake()
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			TextBoxDiagnostics = ((BaseUnityPlugin)this).Config.Bind<bool>("Text boxes", "Log text box diagnostics", false, "Log focus and keyboard state while a text box is selected, to help track down typing problems. Typed text itself is never logged.");
			harmony = new Harmony("com.syntaxspecter.GamepadFixes");
			TryPatch(AccessTools.Method(typeof(CarouselController), "Initialize", (Type[])null, (Type[])null), typeof(Plugin), "OnCarouselReady");
			TryPatch(AccessTools.Method(typeof(BaseSettingsControl), "OnEnable", (Type[])null, (Type[])null), typeof(Plugin), "OnCarouselReady");
			TryPatch(AccessTools.Method(typeof(HostGamePanelController), "OnEnable", (Type[])null, (Type[])null), typeof(MultiplayerMenuFixes), "HostGamePanel_OnEnable");
			TryPatch(AccessTools.Method(typeof(RemoteGameBrowserController), "Start", (Type[])null, (Type[])null), typeof(MultiplayerMenuFixes), "RemoteGameBrowser_Start");
			TryPatch(AccessTools.Method(typeof(LobbyUserList), "Awake", (Type[])null, (Type[])null), typeof(MultiplayerMenuFixes), "LobbyUserList_Awake");
			TryPatch(AccessTools.Method(typeof(HGGamepadInputEvent), "Update", (Type[])null, (Type[])null), typeof(MultiplayerMenuFixes), "HGGamepadInputEvent_Update", prefix: true);
			TryPatch(AccessTools.Method(typeof(MPToggle), "LateUpdate", (Type[])null, (Type[])null), typeof(MultiplayerMenuFixes), "MPToggle_LateUpdate");
			TryPatch(AccessTools.Method(typeof(TMP_InputField), "OnSelect", (Type[])null, (Type[])null), typeof(GamepadTextField), "TMP_InputField_OnSelect");
			TryPatch(AccessTools.Method(typeof(MPButton), "OnPointerEnter", (Type[])null, (Type[])null), typeof(GamepadTextField), "MPButton_OnPointerEnter", prefix: true);
			TryPatch(AccessTools.Method(typeof(MPControlHelper), "OnPointerEnter", (Type[])null, (Type[])null), typeof(GamepadTextField), "MPControlHelper_OnPointerEnter", prefix: true);
			TryPatch(AccessTools.Method(typeof(Selectable), "FindSelectableOnUp", (Type[])null, (Type[])null), typeof(VerticalNavLink), "Selectable_FindSelectableOnUp");
			TryPatch(AccessTools.Method(typeof(Selectable), "FindSelectableOnDown", (Type[])null, (Type[])null), typeof(VerticalNavLink), "Selectable_FindSelectableOnDown");
			TryPatch(AccessTools.Method(typeof(PickupPickerPanel), "SetPickupOptions", (Type[])null, (Type[])null), typeof(PickupPickerFixes), "PickupPickerPanel_Refresh");
			TryPatch(AccessTools.Method(typeof(PickupPickerPanel), "RemovePickupButtonAvailability", (Type[])null, (Type[])null), typeof(PickupPickerFixes), "PickupPickerPanel_Refresh");
		}

		private void TryPatch(MethodBase original, Type patchClass, string patchName, bool prefix = false)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			string text = ((original != null) ? (original.DeclaringType?.Name + "." + original.Name) : patchName);
			try
			{
				if (original == null)
				{
					throw new MissingMethodException("Target method not found (the game may have changed)");
				}
				HarmonyMethod val = new HarmonyMethod(AccessTools.Method(patchClass, patchName, (Type[])null, (Type[])null));
				if (prefix)
				{
					harmony.Patch(original, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				else
				{
					harmony.Patch(original, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Could not patch '" + text + "', its gamepad fix will not apply: " + ex.Message));
			}
		}

		private static void OnCarouselReady(BaseSettingsControl __instance)
		{
			try
			{
				if (__instance is CarouselController && __instance.settingName == "gamemode")
				{
					MakeReachable(((Component)__instance).GetComponent<Selectable>());
				}
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Failed to fix game mode picker navigation: {arg}");
			}
		}

		private static void MakeReachable(Selectable picker)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Invalid comparison between Unknown and I4
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Invalid comparison between Unknown and I4
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)picker == (Object)null || (Object)(object)((Component)picker).transform.parent == (Object)null)
			{
				return;
			}
			Navigation navigation = picker.navigation;
			Selectable val = FindNavigableSibling(picker, -1);
			if ((Object)(object)val != (Object)null)
			{
				Navigation navigation2 = val.navigation;
				if ((int)((Navigation)(ref navigation2)).mode == 4)
				{
					navigation2 = val.navigation;
					if ((Object)(object)((Navigation)(ref navigation2)).selectOnDown != (Object)(object)picker)
					{
						Navigation navigation3 = val.navigation;
						Selectable val2 = (((Object)(object)((Navigation)(ref navigation3)).selectOnDown != (Object)null) ? ((Navigation)(ref navigation3)).selectOnDown : FindNavigableSibling(picker, 1));
						((Navigation)(ref navigation)).mode = (Mode)4;
						((Navigation)(ref navigation)).selectOnUp = val;
						((Navigation)(ref navigation)).selectOnDown = val2;
						((Navigation)(ref navigation)).selectOnLeft = null;
						((Navigation)(ref navigation)).selectOnRight = null;
						picker.navigation = navigation;
						((Navigation)(ref navigation3)).selectOnDown = picker;
						val.navigation = navigation3;
						if ((Object)(object)val2 != (Object)null)
						{
							navigation2 = val2.navigation;
							if ((int)((Navigation)(ref navigation2)).mode == 4)
							{
								navigation2 = val2.navigation;
								if ((Object)(object)((Navigation)(ref navigation2)).selectOnUp == (Object)(object)val)
								{
									Navigation navigation4 = val2.navigation;
									((Navigation)(ref navigation4)).selectOnUp = picker;
									val2.navigation = navigation4;
								}
							}
						}
						Log.LogInfo((object)("Linked game mode picker '" + ((Object)picker).name + "' between '" + ((Object)val).name + "' and '" + (((Object)(object)val2 != (Object)null) ? ((Object)val2).name : "nothing") + "'"));
						return;
					}
				}
			}
			if ((int)((Navigation)(ref navigation)).mode == 0)
			{
				((Navigation)(ref navigation)).mode = (Mode)2;
				picker.navigation = navigation;
				Log.LogInfo((object)("Enabled vertical navigation on game mode picker '" + ((Object)picker).name + "'"));
			}
		}

		private static Selectable FindNavigableSibling(Selectable picker, int step)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			Transform parent = ((Component)picker).transform.parent;
			for (int i = ((Component)picker).transform.GetSiblingIndex() + step; i >= 0 && i < parent.childCount; i += step)
			{
				Selectable component = ((Component)parent.GetChild(i)).GetComponent<Selectable>();
				if ((Object)(object)component != (Object)null && ((Component)component).gameObject.activeSelf)
				{
					Navigation navigation = component.navigation;
					if ((int)((Navigation)(ref navigation)).mode != 0)
					{
						return component;
					}
				}
			}
			return null;
		}
	}
	internal class VerticalNavLink : MonoBehaviour
	{
		public Selectable up;

		public Selectable down;

		public static void Chain(List<Selectable> controls)
		{
			for (int i = 0; i < controls.Count; i++)
			{
				VerticalNavLink verticalNavLink = ((Component)controls[i]).GetComponent<VerticalNavLink>();
				if ((Object)(object)verticalNavLink == (Object)null)
				{
					verticalNavLink = ((Component)controls[i]).gameObject.AddComponent<VerticalNavLink>();
				}
				verticalNavLink.up = ((i > 0) ? controls[i - 1] : null);
				verticalNavLink.down = ((i < controls.Count - 1) ? controls[i + 1] : null);
			}
		}

		internal static void Selectable_FindSelectableOnUp(Selectable __instance, ref Selectable __result)
		{
			VerticalNavLink component = ((Component)__instance).GetComponent<VerticalNavLink>();
			if ((Object)(object)component != (Object)null && IsUsable(component.up))
			{
				__result = component.up;
			}
		}

		internal static void Selectable_FindSelectableOnDown(Selectable __instance, ref Selectable __result)
		{
			VerticalNavLink component = ((Component)__instance).GetComponent<VerticalNavLink>();
			if ((Object)(object)component != (Object)null && IsUsable(component.down))
			{
				__result = component.down;
			}
		}

		private static bool IsUsable(Selectable target)
		{
			if ((Object)(object)target != (Object)null && ((Behaviour)target).isActiveAndEnabled)
			{
				return target.IsInteractable();
			}
			return false;
		}
	}
}