Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of GamepadFixes v1.0.2
GamepadFixes.dll
Decompiled 15 hours agousing 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; } } }