Decompiled source of GK2CraftMax v0.5.0

BepInEx/plugins/GK2CraftMax/GK2CraftMax.dll

Decompiled 5 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using GK2CraftMax.Helpers;
using HarmonyLib;
using LazyBearTechnology;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("GK2CraftMax")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+213ebdcf1838be34d8205a8ee3f3099fec840cd4")]
[assembly: AssemblyProduct("GK2CraftMax")]
[assembly: AssemblyTitle("GK2CraftMax")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace GK2CraftMax
{
	[BepInPlugin("de.w00dst0ckOo.gk2.craftmax", "Graveyard Keeper 2 - Craft Max", "0.5.0")]
	public class Plugin : BaseUnityPlugin
	{
		private Harmony _harmony;

		public const string PluginVersion = "0.5.0";

		private void Awake()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			((BaseUnityPlugin)this).Logger.LogInfo((object)"GK2 Craft Max 0.5.0 loading...");
			_harmony = new Harmony("de.w00dst0ckOo.gk2.craftmax");
			_harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"GK2 Craft Max loaded.");
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
}
namespace GK2CraftMax.Patches
{
	[HarmonyPatch(typeof(UICraftSelectionWindow), "Redraw")]
	internal static class CraftSelectionWindowPatch
	{
		[HarmonyPostfix]
		private static void Postfix(UICraftSelectionWindow __instance)
		{
			CraftMaxHelper.HandleRedraw((UIBaseCraftSelectionWindow)(object)__instance);
		}
	}
	[HarmonyPatch(typeof(UIFuelCraftWindow), "Redraw")]
	internal static class FuelCraftWindowPatch
	{
		[HarmonyPostfix]
		private static void Postfix(UIFuelCraftWindow __instance)
		{
			CraftMaxHelper.HandleRedraw((UIBaseCraftSelectionWindow)(object)__instance);
		}
	}
	[HarmonyPatch(typeof(UISingleCraftWindow), "Redraw")]
	internal static class SingleCraftWindowPatch
	{
		[HarmonyPostfix]
		private static void Postfix(UISingleCraftWindow __instance)
		{
			CraftMaxHelper.HandleRedraw((UIBaseCraftSelectionWindow)(object)__instance);
		}
	}
	[HarmonyPatch(typeof(UIBaseCraftSelectionWindow), "OnStartCraft")]
	internal static class CraftMaxStartCraftPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(UIBaseCraftSelectionWindow __instance, ref bool __result)
		{
			if (!CraftMaxHelper.TryActivateFocusedMax(__instance))
			{
				return true;
			}
			__result = true;
			return false;
		}
	}
	[HarmonyPatch]
	internal static class CraftQuantityShortcutPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(UICraftSelectionWindow), "GetGameKeyDelegates", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(UIFuelCraftWindow), "GetGameKeyDelegates", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(UISingleCraftWindow), "GetGameKeyDelegates", (Type[])null, (Type[])null);
		}

		[HarmonyPostfix]
		private static void Postfix(UIBaseCraftSelectionWindow __instance, Dictionary<GameKey, Func<bool>> __result)
		{
			CraftQuantityShortcutHelper.Register(__instance, __result);
		}
	}
	[HarmonyPatch(typeof(UIBaseCraftSelectionWindow), "AddCraftCountGamepadTips")]
	internal static class CraftQuantityShortcutTipsPatch
	{
		[HarmonyPostfix]
		private static void Postfix(UIBaseCraftSelectionWindow __instance, List<LazyGameKeyTip> tips)
		{
			CraftQuantityShortcutHelper.AddTips(__instance, tips);
		}
	}
	[HarmonyPatch(typeof(UIItemCountWindow), "GetGameKeyDelegates")]
	internal static class ItemCountShortcutPatches
	{
		private const int FastStep = 10;

		private static readonly FieldRef<UIItemCountWindow, SmartSlider> ReadSlider = AccessTools.FieldRefAccess<UIItemCountWindow, SmartSlider>("slider");

		private static readonly MethodInfo ChangeValue = AccessTools.Method(typeof(SmartSlider), "ChangeValue", new Type[2]
		{
			typeof(int),
			typeof(bool)
		}, (Type[])null);

		[HarmonyPostfix]
		private static void Postfix(UIItemCountWindow __instance, ref Dictionary<GameKey, Func<bool>> __result)
		{
			if (!((Object)(object)__instance == (Object)null) && __result != null)
			{
				__result[GameKey.PrevTab] = () => Change(__instance, -10);
				__result[GameKey.NextTab] = () => Change(__instance, 10);
			}
		}

		private static bool Change(UIItemCountWindow window, int delta)
		{
			if ((Object)(object)window == (Object)null || !((LazyWindow<UIItemCountWindowData>)(object)window).IsShownAndTop)
			{
				return false;
			}
			SmartSlider val = ReadSlider.Invoke(window);
			if ((Object)(object)val == (Object)null || ChangeValue == null)
			{
				return false;
			}
			if (LazyInput.GetKey((delta > 0) ? GameKey.PrevTab : GameKey.NextTab))
			{
				return true;
			}
			int value = val.Value;
			ChangeValue.Invoke(val, new object[2] { delta, true });
			return val.Value != value;
		}
	}
	[HarmonyPatch(typeof(UIItemCountWindow), "PrintTips")]
	internal static class ItemCountShortcutTipsPatch
	{
		private static readonly MethodInfo AddTransferTipsMethod = AccessTools.Method(typeof(ItemCountShortcutTipsPatch), "AddTransferTips", (Type[])null, (Type[])null);

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			foreach (CodeInstruction instruction in instructions)
			{
				if (instruction.opcode == OpCodes.Ldstr && instruction.operand is string text && text == "  ")
				{
					yield return new CodeInstruction(OpCodes.Dup, (object)null);
					yield return new CodeInstruction(OpCodes.Call, (object)AddTransferTipsMethod);
				}
				yield return instruction;
			}
		}

		private static void AddTransferTips(List<LazyGameKeyTip> tips)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			if (tips != null)
			{
				tips.Add(new LazyGameKeyTip(GameKey.PrevTab, "-10", true, true, false));
				tips.Add(new LazyGameKeyTip(GameKey.NextTab, "+10", true, true, false));
			}
		}
	}
	[HarmonyPatch(typeof(SmartSlider), "Update")]
	internal static class ItemCountShortcutHoldPatch
	{
		private sealed class RepeatState
		{
			internal int Direction;

			internal float NextRepeatTime;
		}

		private const float InitialDelay = 0.5f;

		private const float RepeatInterval = 0.2f;

		private static readonly ConditionalWeakTable<SmartSlider, RepeatState> States = new ConditionalWeakTable<SmartSlider, RepeatState>();

		private static readonly MethodInfo ChangeValue = AccessTools.Method(typeof(SmartSlider), "ChangeValue", new Type[2]
		{
			typeof(int),
			typeof(bool)
		}, (Type[])null);

		[HarmonyPostfix]
		private static void Postfix(SmartSlider __instance)
		{
			if ((Object)(object)__instance == (Object)null || ChangeValue == null)
			{
				return;
			}
			UIItemCountWindow componentInParent = ((Component)__instance).GetComponentInParent<UIItemCountWindow>();
			if ((Object)(object)componentInParent == (Object)null || !((LazyWindow<UIItemCountWindowData>)(object)componentInParent).IsShownAndTop || !LazyInput.IsGamepadActive || !LazyInput.IsInputActive())
			{
				Reset(__instance);
				return;
			}
			bool key = LazyInput.GetKey(GameKey.PrevTab);
			bool key2 = LazyInput.GetKey(GameKey.NextTab);
			if (key == key2)
			{
				Reset(__instance);
				return;
			}
			int num = (key2 ? 1 : (-1));
			RepeatState orCreateValue = States.GetOrCreateValue(__instance);
			if (orCreateValue.Direction != num)
			{
				orCreateValue.Direction = num;
				orCreateValue.NextRepeatTime = Time.unscaledTime + 0.5f;
			}
			else if (!(Time.unscaledTime < orCreateValue.NextRepeatTime))
			{
				ChangeValue.Invoke(__instance, new object[2]
				{
					num * 10,
					true
				});
				orCreateValue.NextRepeatTime = Time.unscaledTime + 0.2f;
			}
		}

		private static void Reset(SmartSlider slider)
		{
			if (States.TryGetValue(slider, out var value))
			{
				value.Direction = 0;
				value.NextRepeatTime = 0f;
			}
		}
	}
	[HarmonyPatch(typeof(UIResourceBasedCraftWindow), "Redraw")]
	internal static class ScienceDecomposeMaxPatch
	{
		private const string MaxButtonName = "GK2CraftMax_ScienceMaxButton";

		private static readonly FieldRef<UIResourceBasedCraftWindow, UIResourceBasedCraftWindowData> ReadData = AccessTools.FieldRefAccess<UIResourceBasedCraftWindow, UIResourceBasedCraftWindowData>("data");

		private static readonly FieldRef<UIResourceBasedCraftWindow, LazyButton> ReadCraftButton = AccessTools.FieldRefAccess<UIResourceBasedCraftWindow, LazyButton>("craftBtn");

		private static readonly FieldRef<UIResourceBasedCraftWindowData, SurveyDef> ReadSurvey = AccessTools.FieldRefAccess<UIResourceBasedCraftWindowData, SurveyDef>("currentSurveyDef");

		private static readonly FieldRef<UIResourceBasedCraftWindow, UIItemCell> ReadIngredient = AccessTools.FieldRefAccess<UIResourceBasedCraftWindow, UIItemCell>("mainIngredient");

		private static readonly MethodInfo OnStartSurveyMethod = AccessTools.Method(typeof(UIResourceBasedCraftWindowData), "OnStartSurvey", (Type[])null, (Type[])null);

		[HarmonyPostfix]
		private static void Postfix(UIResourceBasedCraftWindow __instance)
		{
			if ((Object)(object)__instance == (Object)null)
			{
				return;
			}
			UIResourceBasedCraftWindowData val = ReadData.Invoke(__instance);
			LazyButton val2 = ReadCraftButton.Invoke(__instance);
			if (val == null || (Object)(object)val2 == (Object)null)
			{
				return;
			}
			SurveyDef val3 = ReadSurvey.Invoke(val);
			if (val.SelectedItem == null || val.SelectedItem.IsEmpty || val3 == null || !val3.isScienceFuelCraft)
			{
				LazyButton val4 = MaxButtonState.For((Component)(object)__instance).Resolve(val2, "GK2CraftMax_ScienceMaxButton");
				if ((Object)(object)val4 != (Object)null && ((Component)val4).gameObject.activeSelf)
				{
					((Component)val4).gameObject.SetActive(false);
				}
				return;
			}
			LazyButton orCreateMaxButton = GetOrCreateMaxButton(__instance, val2);
			if (!((Object)(object)orCreateMaxButton == (Object)null))
			{
				if (!((Component)orCreateMaxButton).gameObject.activeSelf)
				{
					((Component)orCreateMaxButton).gameObject.SetActive(true);
				}
				((Selectable)orCreateMaxButton).interactable = val.CanStartCraft();
				if (LazyInput.IsGamepadActive)
				{
					SetupGamepadNavigation(__instance, orCreateMaxButton);
				}
			}
		}

		private static LazyButton GetOrCreateMaxButton(UIResourceBasedCraftWindow window, LazyButton craftButton)
		{
			MaxButtonState maxButtonState = MaxButtonState.For((Component)(object)window);
			LazyButton val = maxButtonState.Resolve(craftButton, "GK2CraftMax_ScienceMaxButton");
			if ((Object)(object)val == (Object)null)
			{
				val = MaxButtonHelper.CloneButton(craftButton, "GK2CraftMax_ScienceMaxButton");
				if ((Object)(object)val != (Object)null)
				{
					BindMaximumClick(window, val);
				}
				maxButtonState.Button = val;
			}
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			MaxButtonHelper.PositionRightOf(val, craftButton);
			if (!maxButtonState.Initialized || (Object)(object)maxButtonState.Label == (Object)null)
			{
				maxButtonState.Label = MaxButtonHelper.SetExistingLabel(val, "MAX");
			}
			if ((Object)(object)maxButtonState.Navigation == (Object)null)
			{
				maxButtonState.Navigation = MaxButtonHelper.EnsureNavigationItem(val);
			}
			maxButtonState.Initialized = true;
			return val;
		}

		private static void BindMaximumClick(UIResourceBasedCraftWindow window, LazyButton button)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			((UnityEvent)((Button)button).onClick).AddListener((UnityAction)delegate
			{
				DecomposeMaximum(window);
			});
		}

		private static void DecomposeMaximum(UIResourceBasedCraftWindow window)
		{
			if ((Object)(object)window == (Object)null || (Object)(object)MainGame.PlayerController == (Object)null || MainGame.PlayerData == null)
			{
				return;
			}
			UIResourceBasedCraftWindowData val = ReadData.Invoke(window);
			if (val == null || val.SelectedItem == null || val.SelectedItem.IsEmpty)
			{
				return;
			}
			SurveyDef val2 = ReadSurvey.Invoke(val);
			if (val2 == null || !val2.isScienceFuelCraft || OnStartSurveyMethod == null)
			{
				return;
			}
			int num = 999;
			while (val.CanStartCraft() && num-- > 0)
			{
				int mainIngredientCount = val.MainIngredientCount;
				OnStartSurveyMethod.Invoke(val, null);
				int mainIngredientCount2 = val.MainIngredientCount;
				if (mainIngredientCount2 >= mainIngredientCount)
				{
					Debug.LogWarning((object)("[CraftMax] Science MAX stopped: item count did not decrease " + $"({mainIngredientCount} -> {mainIngredientCount2})."));
					break;
				}
				if (val.SelectedItem == null || val.SelectedItem.IsEmpty)
				{
					break;
				}
			}
		}

		private static void SetupGamepadNavigation(UIResourceBasedCraftWindow window, LazyButton maxButton)
		{
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)window == (Object)null || (Object)(object)maxButton == (Object)null)
			{
				return;
			}
			UIItemCell val = ReadIngredient.Invoke(window);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			GamepadNavigationController controller = GamepadNavigationHelper.GetController<UIResourceBasedCraftWindow>(window);
			if (!((Object)(object)controller == (Object)null))
			{
				GamepadNavigationItem gamepadNavigationItem = val.GamepadNavigationItem;
				MaxButtonState maxButtonState = MaxButtonState.For((Component)(object)window);
				if ((Object)(object)maxButtonState.Navigation == (Object)null)
				{
					maxButtonState.Navigation = MaxButtonHelper.EnsureNavigationItem(maxButton);
				}
				GamepadNavigationItem navigation = maxButtonState.Navigation;
				if (!((Object)(object)gamepadNavigationItem == (Object)null) && !((Object)(object)navigation == (Object)null))
				{
					navigation.Active = true;
					((Behaviour)navigation).enabled = true;
					navigation.group = gamepadNavigationItem.group;
					GamepadNavigationHelper.RegisterAndReinit(controller, ((Component)window).transform.lossyScale.x, gamepadNavigationItem, navigation);
					GamepadNavigationHelper.Link(gamepadNavigationItem, (GUIDirection)3, navigation);
					GamepadNavigationHelper.Link(navigation, (GUIDirection)2, gamepadNavigationItem);
					GamepadNavigationHelper.BindButtonPress(navigation, maxButton);
					controller.SetFocusedItem(gamepadNavigationItem);
				}
			}
		}
	}
}
namespace GK2CraftMax.Helpers
{
	internal static class CraftMaxHelper
	{
		internal const string MaxButtonName = "GK2CraftMax_Button";

		private static readonly FieldRef<UIBaseCraftSelectionWindow, UIBaseCraftSelectionWindowData> ReadData = AccessTools.FieldRefAccess<UIBaseCraftSelectionWindow, UIBaseCraftSelectionWindowData>("data");

		private static readonly FieldRef<UIBaseCraftSelectionWindow, LazyButton> ReadPlusButton = AccessTools.FieldRefAccess<UIBaseCraftSelectionWindow, LazyButton>("plusCraftButton");

		private static readonly FieldRef<UIBaseCraftSelectionWindow, LazyButton> ReadStartButton = AccessTools.FieldRefAccess<UIBaseCraftSelectionWindow, LazyButton>("startCraftButton");

		private static readonly MethodInfo StartCraft = AccessTools.Method(typeof(UIBaseCraftSelectionWindow), "OnStartCraftPressed", (Type[])null, (Type[])null);

		private static readonly MethodInfo ChangeCraftCount = AccessTools.Method(typeof(UIBaseCraftSelectionWindow), "ChangeCraftCount", new Type[1] { typeof(int) }, (Type[])null);

		internal static void HandleRedraw(UIBaseCraftSelectionWindow window)
		{
			if ((Object)(object)window == (Object)null)
			{
				return;
			}
			UIBaseCraftSelectionWindowData val = ReadData.Invoke(window);
			if (val == null || val.CraftDefinition == null)
			{
				SetMaxButtonActive(window, active: false);
				return;
			}
			if (!(window is UIFuelCraftWindow) && val.CraftDefinition.IsMultipleCraftsDisabled)
			{
				SetMaxButtonActive(window, active: false);
				return;
			}
			LazyButton val2 = ReadPlusButton.Invoke(window);
			if ((Object)(object)val2 == (Object)null)
			{
				return;
			}
			LazyButton orCreateMaxButton = GetOrCreateMaxButton(window, val2);
			if ((Object)(object)orCreateMaxButton == (Object)null)
			{
				return;
			}
			if (!((Component)orCreateMaxButton).gameObject.activeSelf)
			{
				((Component)orCreateMaxButton).gameObject.SetActive(true);
			}
			MaxButtonState maxButtonState = MaxButtonState.For((Component)(object)window);
			try
			{
				SetupGamepadNavigation(window, orCreateMaxButton, maxButtonState);
			}
			finally
			{
				maxButtonState.CraftCells.Clear();
			}
		}

		private static LazyButton GetOrCreateMaxButton(UIBaseCraftSelectionWindow window, LazyButton plusButton)
		{
			MaxButtonState maxButtonState = MaxButtonState.For((Component)(object)window);
			LazyButton val = maxButtonState.Resolve(plusButton, "GK2CraftMax_Button");
			if ((Object)(object)val == (Object)null)
			{
				val = MaxButtonHelper.CloneButton(plusButton, "GK2CraftMax_Button");
				if ((Object)(object)val != (Object)null)
				{
					BindMaximumClick(window, val);
				}
				maxButtonState.Button = val;
			}
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			if (!maxButtonState.Initialized)
			{
				maxButtonState.Icon = ((Component)val).transform.Find("Content/Icon");
				if ((Object)(object)maxButtonState.Icon != (Object)null && ((Component)maxButtonState.Icon).gameObject.activeSelf)
				{
					((Component)maxButtonState.Icon).gameObject.SetActive(false);
				}
			}
			MaxButtonHelper.PositionRightOf(val, plusButton);
			if (!maxButtonState.Initialized || (Object)(object)maxButtonState.Label == (Object)null)
			{
				maxButtonState.Label = MaxButtonHelper.CreateLabel(val, "MAX");
			}
			maxButtonState.Initialized = true;
			return val;
		}

		private static void BindMaximumClick(UIBaseCraftSelectionWindow window, LazyButton button)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			((UnityEvent)((Button)button).onClick).AddListener((UnityAction)delegate
			{
				SetMaximumCraftCount(window);
			});
		}

		private static void SetupGamepadNavigation(UIBaseCraftSelectionWindow window, LazyButton maxButton, MaxButtonState state)
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)window == (Object)null || (Object)(object)maxButton == (Object)null || state == null)
			{
				return;
			}
			state.Insertion.Restore();
			if (!LazyInput.IsGamepadActive)
			{
				if ((Object)(object)state.Navigation != (Object)null)
				{
					state.Navigation.Active = false;
				}
				return;
			}
			GamepadNavigationController controller = GamepadNavigationHelper.GetController<UIBaseCraftSelectionWindow>(window);
			if ((Object)(object)controller == (Object)null)
			{
				return;
			}
			if ((Object)(object)state.Navigation == (Object)null)
			{
				state.Navigation = MaxButtonHelper.EnsureNavigationItem(maxButton);
			}
			GamepadNavigationItem navigation = state.Navigation;
			if ((Object)(object)navigation == (Object)null)
			{
				return;
			}
			navigation.Active = false;
			List<GamepadNavigationItem> items = GamepadNavigationHelper.GetItems(controller);
			if (items == null)
			{
				return;
			}
			GamepadNavigationHelper.Register(controller, navigation, ((Component)window).transform.lossyScale.x);
			List<UICraftItemCell> craftCells = state.CraftCells;
			((Component)window).GetComponentsInChildren<UICraftItemCell>(true, craftCells);
			GamepadNavigationItem val = null;
			GamepadNavigationItem val2 = null;
			foreach (UICraftItemCell item in craftCells)
			{
				if ((Object)(object)item == (Object)null || !((Component)item).gameObject.activeInHierarchy)
				{
					continue;
				}
				GamepadNavigationItem gamepadNavigationItem = item.GamepadNavigationItem;
				if (GamepadNavigationHelper.IsUsable(gamepadNavigationItem) && items.Contains(gamepadNavigationItem))
				{
					if ((Object)(object)val == (Object)null || gamepadNavigationItem.Pos.x < val.Pos.x)
					{
						val = gamepadNavigationItem;
					}
					if ((Object)(object)val2 == (Object)null || gamepadNavigationItem.Pos.x > val2.Pos.x)
					{
						val2 = gamepadNavigationItem;
					}
				}
			}
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
			{
				navigation.Active = false;
				return;
			}
			GamepadNavigationItem val3 = null;
			foreach (GamepadNavigationItem item2 in items)
			{
				if (!((Object)(object)item2 == (Object)null) && !((Object)(object)item2 == (Object)(object)navigation) && !((Object)(object)item2 == (Object)(object)val) && !((Object)(object)item2 == (Object)(object)val2) && GamepadNavigationHelper.IsUsable(item2) && item2.Pos.x < val.Pos.x && Mathf.Abs(item2.Pos.y - val.Pos.y) < 10f && ((Object)(object)val3 == (Object)null || item2.Pos.x > val3.Pos.x))
				{
					val3 = item2;
				}
			}
			if ((Object)(object)val3 == (Object)null)
			{
				navigation.Active = false;
				return;
			}
			state.Insertion.AttachRing(controller, val3, val2, navigation);
			if (!state.Insertion.IsAttached)
			{
				navigation.Active = false;
			}
			else
			{
				GamepadNavigationHelper.BindButtonPress(navigation, maxButton);
			}
		}

		internal static bool TryActivateFocusedMax(UIBaseCraftSelectionWindow window)
		{
			if ((Object)(object)window == (Object)null || !LazyInput.IsGamepadActive)
			{
				return false;
			}
			GamepadNavigationController controller = GamepadNavigationHelper.GetController<UIBaseCraftSelectionWindow>(window);
			if ((Object)(object)controller == (Object)null)
			{
				return false;
			}
			GamepadNavigationItem focusedItem = controller.FocusedItem;
			if ((Object)(object)focusedItem == (Object)null || (Object)(object)((Component)focusedItem).gameObject == (Object)null || ((Object)((Component)focusedItem).gameObject).name != "GK2CraftMax_Button")
			{
				return false;
			}
			LazyButton component = ((Component)focusedItem).GetComponent<LazyButton>();
			if ((Object)(object)component == (Object)null)
			{
				return false;
			}
			((UnityEvent)((Button)component).onClick).Invoke();
			LazyButton val = ReadStartButton.Invoke(window);
			if ((Object)(object)val != (Object)null && ((Selectable)val).interactable)
			{
				StartCraft.Invoke(window, null);
			}
			return true;
		}

		private static void SetMaximumCraftCount(UIBaseCraftSelectionWindow window)
		{
			UIBaseCraftSelectionWindowData val = ReadData.Invoke(window);
			if (val == null || val.CraftItemCellsData == null || val.CraftItemCellsData.Count == 0)
			{
				return;
			}
			int num = 999;
			foreach (UICraftItemCellData craftItemCellsDatum in val.CraftItemCellsData)
			{
				if (craftItemCellsDatum != null && craftItemCellsDatum.currentItem != null && craftItemCellsDatum.MultiInventory != null)
				{
					int count = craftItemCellsDatum.currentItem.GetCount(val.WgoData);
					if (count > 0)
					{
						int val2 = craftItemCellsDatum.MultiInventory.GetTotalCount(craftItemCellsDatum.currentItem.Id) / count;
						num = Math.Min(num, val2);
					}
				}
			}
			if (window is UIFuelCraftWindow && val.CraftDefinition != null && ((CraftDefBase)val.CraftDefinition).isFuelCraft && val.WgoData != null && ((ObjectLinkedToDefinition<WGODef>)(object)val.WgoData).Definition != null && val.WgoData.Inventory != null && val.WgoData.Inventory.Data != null)
			{
				ItemDef fuelItemDef = ((CraftDefBase)val.CraftDefinition).FuelItemDef;
				OutputPreview outputPreview = ((CraftDefBase)val.CraftDefinition).GetOutputPreview(val.WgoData);
				if (fuelItemDef != null && outputPreview != null && outputPreview.count > 0)
				{
					int totalCountInInventory = val.WgoData.Inventory.Data.GetTotalCountInInventory(((BalanceBaseObject)fuelItemDef).id, (Item)null, false);
					int num2 = ((ObjectLinkedToDefinition<WGODef>)(object)val.WgoData).Definition.emptyCellStackCount * val.WgoData.Inventory.Data.InventorySize;
					int num3 = Math.Max(0, num2 - totalCountInInventory);
					int count2 = outputPreview.count;
					int val3 = ((num3 > 0) ? (num3 / count2) : 0);
					num = Math.Min(num, val3);
				}
			}
			num = ((!(window is UIFuelCraftWindow)) ? Math.Max(1, Math.Min(999, num)) : Math.Max(0, Math.Min(999, num)));
			if (!(window is UIFuelCraftWindow) || num > 0)
			{
				int num4 = num - val.CraftsCount;
				if (num4 != 0)
				{
					ChangeCraftCount.Invoke(window, new object[1] { num4 });
				}
			}
		}

		private static void SetMaxButtonActive(UIBaseCraftSelectionWindow window, bool active)
		{
			if ((Object)(object)window == (Object)null)
			{
				return;
			}
			LazyButton val = ReadPlusButton.Invoke(window);
			if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).transform.parent == (Object)null)
			{
				return;
			}
			MaxButtonState maxButtonState = MaxButtonState.For((Component)(object)window);
			LazyButton val2 = maxButtonState.Resolve(val, "GK2CraftMax_Button");
			if (!active)
			{
				maxButtonState.Insertion.Restore();
				if ((Object)(object)maxButtonState.Navigation != (Object)null)
				{
					maxButtonState.Navigation.Active = false;
				}
				maxButtonState.Context = null;
				maxButtonState.CraftCells.Clear();
			}
			if ((Object)(object)val2 != (Object)null && ((Component)val2).gameObject.activeSelf != active)
			{
				((Component)val2).gameObject.SetActive(active);
			}
		}
	}
	internal sealed class CraftQuantityHoldRepeater : MonoBehaviour
	{
		private const float HoldDelay = 0.5f;

		private const float RepeatInterval = 0.2f;

		private UIBaseCraftSelectionWindow window;

		private int direction;

		private float holdStartedAt;

		private float nextRepeatAt;

		internal void Initialize(UIBaseCraftSelectionWindow craftWindow)
		{
			window = craftWindow;
			ResetHold();
		}

		private void Update()
		{
			if ((Object)(object)window == (Object)null || !((LazyWindow<UIBaseCraftSelectionWindowData>)(object)window).IsShownAndTop || !LazyInput.IsGamepadActive || !LazyInput.IsInputActive())
			{
				ResetHold();
				return;
			}
			bool key = LazyInput.GetKey(GameKey.PrevTab);
			bool key2 = LazyInput.GetKey(GameKey.NextTab);
			if (key == key2)
			{
				ResetHold();
				return;
			}
			int num = (key2 ? 1 : (-1));
			if (direction != num)
			{
				direction = num;
				holdStartedAt = Time.unscaledTime;
				nextRepeatAt = holdStartedAt + 0.5f;
			}
			else if (!(Time.unscaledTime < nextRepeatAt))
			{
				CraftQuantityShortcutHelper.TryChange(window, direction > 0);
				nextRepeatAt = Time.unscaledTime + 0.2f;
			}
		}

		private void ResetHold()
		{
			direction = 0;
			holdStartedAt = 0f;
			nextRepeatAt = 0f;
		}

		private void OnDisable()
		{
			ResetHold();
		}
	}
	internal static class CraftQuantityShortcutHelper
	{
		private static readonly FieldRef<UIBaseCraftSelectionWindow, UIBaseCraftSelectionWindowData> ReadData = AccessTools.FieldRefAccess<UIBaseCraftSelectionWindow, UIBaseCraftSelectionWindowData>("data");

		private static readonly FieldRef<UIBaseCraftSelectionWindow, LazyButton> ReadPlus = AccessTools.FieldRefAccess<UIBaseCraftSelectionWindow, LazyButton>("plusCraftButton");

		private static readonly FieldRef<UIBaseCraftSelectionWindow, LazyButton> ReadMinus = AccessTools.FieldRefAccess<UIBaseCraftSelectionWindow, LazyButton>("minusCraftButton");

		private static readonly MethodInfo CanChangeWithGamepad = AccessTools.Method(typeof(UIBaseCraftSelectionWindow), "CanChangeCraftCountWithGamepad", (Type[])null, (Type[])null);

		private static readonly MethodInfo ChangeCount = AccessTools.Method(typeof(UIBaseCraftSelectionWindow), "ChangeCraftCount", new Type[1] { typeof(int) }, (Type[])null);

		internal static void Register(UIBaseCraftSelectionWindow window, Dictionary<GameKey, Func<bool>> callbacks)
		{
			if ((Object)(object)window == (Object)null || callbacks == null)
			{
				return;
			}
			if (!callbacks.ContainsKey(GameKey.PrevTab))
			{
				callbacks.Add(GameKey.PrevTab, () => TryChange(window, increase: false));
			}
			if (!callbacks.ContainsKey(GameKey.NextTab))
			{
				callbacks.Add(GameKey.NextTab, () => TryChange(window, increase: true));
			}
			CraftQuantityHoldRepeater craftQuantityHoldRepeater = ((Component)window).GetComponent<CraftQuantityHoldRepeater>();
			if ((Object)(object)craftQuantityHoldRepeater == (Object)null)
			{
				craftQuantityHoldRepeater = ((Component)window).gameObject.AddComponent<CraftQuantityHoldRepeater>();
			}
			craftQuantityHoldRepeater.Initialize(window);
		}

		internal static void AddTips(UIBaseCraftSelectionWindow window, List<LazyGameKeyTip> tips)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			if (tips != null)
			{
				LazyButton val = ReadPlus.Invoke(window);
				LazyButton val2 = ReadMinus.Invoke(window);
				if ((Object)(object)val2 != (Object)null && ((Component)val2).gameObject.activeSelf)
				{
					tips.Add(new LazyGameKeyTip(GameKey.PrevTab, "-10", ((Selectable)val2).interactable, true, false));
				}
				if ((Object)(object)val != (Object)null && ((Component)val).gameObject.activeSelf)
				{
					tips.Add(new LazyGameKeyTip(GameKey.NextTab, "+10", ((Selectable)val).interactable, true, false));
				}
			}
		}

		internal static bool TryChange(UIBaseCraftSelectionWindow window, bool increase)
		{
			if ((Object)(object)window == (Object)null || !((LazyWindow<UIBaseCraftSelectionWindowData>)(object)window).IsShownAndTop || !LazyInput.IsGamepadActive || !LazyInput.IsInputActive() || !(bool)CanChangeWithGamepad.Invoke(window, null))
			{
				return false;
			}
			UIBaseCraftSelectionWindowData val = ReadData.Invoke(window);
			if (((val != null) ? val.CraftDefinition : null) == null || val.WgoData == null)
			{
				return false;
			}
			LazyButton val2 = (increase ? ReadPlus.Invoke(window) : ReadMinus.Invoke(window));
			if ((Object)(object)val2 == (Object)null || !((Behaviour)val2).isActiveAndEnabled || !((Selectable)val2).interactable)
			{
				return false;
			}
			if (LazyInput.GetKey(increase ? GameKey.PrevTab : GameKey.NextTab))
			{
				return true;
			}
			List<CraftElementBase> list = ((window is UIFuelCraftWindow || window is UISingleCraftWindow) ? val.CraftQueue : null);
			int num = list?.Count ?? 0;
			if (num > 2)
			{
				return true;
			}
			CraftElementBase val3 = ((num > 0) ? list[num - 1] : null);
			CraftElementBase val4 = ((num == 2) ? list[0] : null);
			if ((num > 0 && val3 == null) || (num == 2 && val4 == null) || (val3 != null && (val3.IsInfinite || val3.CraftId != ((BalanceBaseObject)val.CraftDefinition).id)) || (val4 != null && (val4.IsInfinite || val4.CraftId != ((BalanceBaseObject)val.CraftDefinition).id)))
			{
				return true;
			}
			int num2 = ((val4 != null) ? val4.Count : 0);
			int current = ((window is UIFuelCraftWindow && val3 != null) ? (val3.Count + num2) : val.CraftsCount);
			int minimum = ((val3 == null || list[0].IsStarted) ? 1 : 0);
			int num3 = 999;
			if (window is UIFuelCraftWindow && val3 != null)
			{
				num3 += num2;
			}
			if (window is UIFuelCraftWindow && val3 != null)
			{
				num3 += num2;
			}
			int delta = CraftQuantityStep.GetDelta(current, minimum, num3, increase);
			if (delta != 0)
			{
				ChangeCount.Invoke(window, new object[1] { delta });
			}
			return true;
		}

		private static int GetMaximum(UIBaseCraftSelectionWindowData data, CraftElementBase target, CraftElementBase other, int maximum, bool isFuel)
		{
			List<NeedItemData> list = ((target != null) ? target.Requirements : null) ?? data.CurrentNeedItems;
			if (list == null)
			{
				return 0;
			}
			MultiInventory inventory = data.WgoData.GetCraftableMultiInventory(false);
			int committedCount = ((other != null) ? other.Count : 0) + ((target != null && target.IsStarted) ? 1 : 0);
			int reservedCrafts = ((other != null) ? Math.Max(0, other.Count - (other.IsStarted ? 1 : 0)) : 0);
			maximum = LimitByIngredients(maximum, list, (other != null) ? other.Requirements : null, reservedCrafts, committedCount, data.WgoData, (string id) => inventory.GetTotalCount(id));
			maximum = LimitByIngredients(maximum, ((CraftDefBase)data.CraftDefinition).needItemsFromWgo, (other != null) ? other.Def.needItemsFromWgo : null, reservedCrafts, committedCount, data.WgoData, (string id) => data.WgoData.Inventory.Data.GetTotalCountInInventory(id, (Item)null, false));
			if (isFuel && ((CraftDefBase)data.CraftDefinition).isFuelCraft)
			{
				ItemDef fuelItemDef = ((CraftDefBase)data.CraftDefinition).FuelItemDef;
				OutputPreview outputPreview = ((CraftDefBase)data.CraftDefinition).GetOutputPreview(data.WgoData);
				if (fuelItemDef == null || outputPreview == null || outputPreview.count <= 0)
				{
					return 0;
				}
				Inventory inventory2 = data.WgoData.Inventory;
				Item val = ((inventory2 != null) ? inventory2.Data : null);
				if (val == null || ((ObjectLinkedToDefinition<WGODef>)(object)data.WgoData).Definition == null)
				{
					return 0;
				}
				long num = (long)((ObjectLinkedToDefinition<WGODef>)(object)data.WgoData).Definition.emptyCellStackCount * (long)val.InventorySize;
				long available = Math.Max(0L, num - val.GetTotalCountInInventory(((BalanceBaseObject)fuelItemDef).id, (Item)null, false));
				maximum = CraftQuantityStep.LimitByResource(maximum, available, outputPreview.count, 0L, 0);
			}
			return maximum;
		}

		private static int LimitByIngredients(int maximum, List<NeedItemData> requirements, List<NeedItemData> reservedRequirements, int reservedCrafts, int committedCount, WgoData wgo, Func<string, int> available)
		{
			Dictionary<string, long> dictionary = SumRequirements(requirements, wgo);
			Dictionary<string, long> dictionary2 = SumRequirements(reservedRequirements, wgo);
			foreach (KeyValuePair<string, long> item in dictionary)
			{
				dictionary2.TryGetValue(item.Key, out var value);
				maximum = CraftQuantityStep.LimitByResource(maximum, available(item.Key), item.Value, value * reservedCrafts, committedCount);
			}
			return maximum;
		}

		private static Dictionary<string, long> SumRequirements(List<NeedItemData> items, WgoData wgo)
		{
			Dictionary<string, long> dictionary = new Dictionary<string, long>();
			if (items == null)
			{
				return dictionary;
			}
			foreach (NeedItemData item in items)
			{
				if (item != null && !string.IsNullOrEmpty(item.Id))
				{
					int count = item.GetCount(wgo);
					if (count > 0)
					{
						dictionary.TryGetValue(item.Id, out var value);
						dictionary[item.Id] = value + count;
					}
				}
			}
			return dictionary;
		}
	}
	internal static class CraftQuantityStep
	{
		internal static int GetDelta(int current, int minimum, int maximum, bool increase)
		{
			if (increase)
			{
				return (int)Math.Max(0L, Math.Min(10L, (long)maximum - (long)current));
			}
			return -(int)Math.Max(0L, Math.Min(10L, (long)current - (long)minimum));
		}

		internal static int LimitByResource(int maximum, long available, long required, long reserved, int committedCount)
		{
			if (required <= 0)
			{
				return maximum;
			}
			long num = Math.Max(0L, available - reserved) / required;
			return (int)Math.Min(maximum, num + committedCount);
		}
	}
	internal static class GamepadNavigationHelper
	{
		private static class ControllerAccessor<T>
		{
			internal static readonly MethodInfo Getter = AccessTools.PropertyGetter(typeof(T), "GamepadNavigationController");
		}

		private sealed class ButtonPress
		{
			private readonly LazyButton button;

			internal readonly UnityAction Callback;

			internal ButtonPress(LazyButton button)
			{
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: Expected O, but got Unknown
				this.button = button;
				Callback = new UnityAction(Press);
			}

			private void Press()
			{
				if ((Object)(object)button != (Object)null && ((Selectable)button).interactable)
				{
					((UnityEvent)((Button)button).onClick).Invoke();
				}
			}
		}

		private static readonly FieldRef<GamepadNavigationController, List<GamepadNavigationItem>> ReadItems = AccessTools.FieldRefAccess<GamepadNavigationController, List<GamepadNavigationItem>>("selectableItems");

		private static readonly ConditionalWeakTable<LazyButton, ButtonPress> PressCallbacks = new ConditionalWeakTable<LazyButton, ButtonPress>();

		private static readonly MethodInfo OtherGroup = AccessTools.Method(typeof(GamepadNavigationController), "TryGetItemFromOtherGroup", (Type[])null, (Type[])null);

		private static readonly MethodInfo NearestGrid = AccessTools.Method(typeof(GamepadNavigationController), "GetNearestItemWithLegacyGridAndMaxDistance", (Type[])null, (Type[])null);

		private static readonly MethodInfo NearestCorridor = AccessTools.Method(typeof(GamepadNavigationController), "GetNearestItemWithCrossAxisCorridor", (Type[])null, (Type[])null);

		private static readonly MethodInfo VerticalWrap = AccessTools.Method(typeof(GamepadNavigationController), "GetVerticalWrapItem", (Type[])null, (Type[])null);

		private static readonly FieldRef<GamepadNavigationController, Dictionary<int, GamepadNavigationItem>> ReadLastFocus = AccessTools.FieldRefAccess<GamepadNavigationController, Dictionary<int, GamepadNavigationItem>>("lastFocusedItems");

		internal static bool IsUsable(GamepadNavigationItem item)
		{
			if ((Object)(object)item != (Object)null && item.Active)
			{
				return ((Behaviour)item).isActiveAndEnabled;
			}
			return false;
		}

		internal static GamepadNavigationItem ResolveDirection(GamepadNavigationController controller, GamepadNavigationItem from, GUIDirection direction)
		{
			//IL_0008: 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_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Expected O, but got Unknown
			//IL_0061: 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_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Expected O, but got Unknown
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Invalid comparison between Unknown and I4
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Expected O, but got Unknown
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Invalid comparison between Unknown and I4
			List<GamepadNavigationItem> items = GetItems(controller);
			GamepadNavigationItem customDirectionItem = from.GetCustomDirectionItem(direction);
			if ((Object)(object)customDirectionItem != (Object)null && items.Contains(customDirectionItem))
			{
				return customDirectionItem;
			}
			List<GamepadNavigationItem> list = new List<GamepadNavigationItem>();
			foreach (GamepadNavigationItem item in items)
			{
				if ((Object)(object)item != (Object)(object)from && IsUsable(item) && item.group == from.group && item.CorrectDirection(from.Pos, direction))
				{
					list.Add(item);
				}
			}
			if (list.Count == 0)
			{
				GamepadNavigationItem val = (GamepadNavigationItem)OtherGroup.Invoke(controller, new object[3] { from.group, from.Pos, direction });
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
				if (controller.loopVerticalNavigation && from.group == 0 && ((int)direction == 2 || (int)direction == 3))
				{
					return (GamepadNavigationItem)VerticalWrap.Invoke(controller, new object[3] { from, from.group, direction });
				}
				return null;
			}
			GamepadNavigationItem val2 = (controller.checkMaxCrossAxisDistance ? ((GamepadNavigationItem)NearestCorridor.Invoke(controller, new object[3] { list, from.Pos, direction })) : ((GamepadNavigationItem)NearestGrid.Invoke(controller, new object[4] { list, from.Pos, from.group, direction })));
			if ((Object)(object)val2 != (Object)null && controller.restoreLastInGroup && val2.group != from.group && controller.HaveSavedFocusForGroup(val2.group))
			{
				return ReadLastFocus.Invoke(controller)[val2.group];
			}
			return val2;
		}

		internal static GamepadNavigationController GetController<T>(T window) where T : Object
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			if ((Object)(object)window == (Object)null)
			{
				return null;
			}
			return (GamepadNavigationController)ControllerAccessor<T>.Getter.Invoke(window, null);
		}

		internal static List<GamepadNavigationItem> GetItems(GamepadNavigationController controller)
		{
			if ((Object)(object)controller == (Object)null)
			{
				return null;
			}
			return ReadItems.Invoke(controller);
		}

		internal static void Register(GamepadNavigationController controller, GamepadNavigationItem item, float guiScale)
		{
			if (!((Object)(object)controller == (Object)null) && !((Object)(object)item == (Object)null))
			{
				List<GamepadNavigationItem> items = GetItems(controller);
				if (items != null && !items.Contains(item))
				{
					items.Add(item);
					item.Init(items.Count - 1, controller, guiScale);
				}
			}
		}

		internal static void RegisterAndReinit(GamepadNavigationController controller, float guiScale, GamepadNavigationItem first, GamepadNavigationItem second)
		{
			List<GamepadNavigationItem> items = GetItems(controller);
			if (items == null)
			{
				return;
			}
			if ((Object)(object)first != (Object)null && !items.Contains(first))
			{
				items.Add(first);
			}
			if ((Object)(object)second != (Object)null && !items.Contains(second))
			{
				items.Add(second);
			}
			for (int i = 0; i < items.Count; i++)
			{
				if ((Object)(object)items[i] != (Object)null)
				{
					items[i].Init(i, controller, guiScale);
				}
			}
		}

		internal static void Link(GamepadNavigationItem from, GUIDirection direction, GamepadNavigationItem to)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)from == (Object)null) && !((Object)(object)to == (Object)null))
			{
				from.SetCustomDirectionItem(direction, to, false);
			}
		}

		internal static void BindButtonPress(GamepadNavigationItem nav, LazyButton button)
		{
			if (!((Object)(object)nav == (Object)null) && !((Object)(object)button == (Object)null))
			{
				if (!PressCallbacks.TryGetValue(button, out var value))
				{
					value = new ButtonPress(button);
					PressCallbacks.Add(button, value);
				}
				nav.SetCallbacks((UnityAction)null, (UnityAction)null, value.Callback);
			}
		}
	}
	internal static class MaxButtonHelper
	{
		internal static LazyButton CloneButton(LazyButton template, string objectName)
		{
			if ((Object)(object)template == (Object)null || (Object)(object)((Component)template).transform.parent == (Object)null)
			{
				return null;
			}
			Transform parent = ((Component)template).transform.parent;
			Transform val = parent.Find(objectName);
			if ((Object)(object)val != (Object)null)
			{
				return ((Component)val).GetComponent<LazyButton>();
			}
			GameObject val2 = Object.Instantiate<GameObject>(((Component)template).gameObject, parent);
			((Object)val2).name = objectName;
			LazyButton component = val2.GetComponent<LazyButton>();
			if ((Object)(object)component == (Object)null)
			{
				Object.Destroy((Object)(object)val2);
				return null;
			}
			((UnityEventBase)((Button)component).onClick).RemoveAllListeners();
			return component;
		}

		internal static void PositionRightOf(LazyButton button, LazyButton referenceButton, float spacing = 10f)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: 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_0061: 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_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)button == (Object)null || (Object)(object)referenceButton == (Object)null)
			{
				return;
			}
			Transform transform = ((Component)referenceButton).transform;
			RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			Transform transform2 = ((Component)button).transform;
			RectTransform val2 = (RectTransform)(object)((transform2 is RectTransform) ? transform2 : null);
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null))
			{
				Vector2 val3 = val2.anchorMin;
				if (!((Vector2)(ref val3)).Equals(val.anchorMin))
				{
					val2.anchorMin = val.anchorMin;
				}
				val3 = val2.anchorMax;
				if (!((Vector2)(ref val3)).Equals(val.anchorMax))
				{
					val2.anchorMax = val.anchorMax;
				}
				val3 = val2.pivot;
				if (!((Vector2)(ref val3)).Equals(val.pivot))
				{
					val2.pivot = val.pivot;
				}
				val3 = val2.sizeDelta;
				if (!((Vector2)(ref val3)).Equals(val.sizeDelta))
				{
					val2.sizeDelta = val.sizeDelta;
				}
				Vector2 anchoredPosition = val.anchoredPosition;
				Rect rect = val.rect;
				Vector2 val4 = anchoredPosition + new Vector2(((Rect)(ref rect)).width + spacing, 0f);
				val3 = val2.anchoredPosition;
				if (!((Vector2)(ref val3)).Equals(val4))
				{
					val2.anchoredPosition = val4;
				}
			}
		}

		internal static GamepadNavigationItem EnsureNavigationItem(LazyButton button)
		{
			if ((Object)(object)button == (Object)null)
			{
				return null;
			}
			GamepadNavigationItem val = ((Component)button).GetComponent<GamepadNavigationItem>();
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)button).gameObject.AddComponent<GamepadNavigationItem>();
			}
			return val;
		}

		internal static TMP_Text SetExistingLabel(LazyButton button, string text)
		{
			if ((Object)(object)button == (Object)null)
			{
				return null;
			}
			TextMeshProUGUI componentInChildren = ((Component)button).GetComponentInChildren<TextMeshProUGUI>(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				((TMP_Text)componentInChildren).text = text;
			}
			return (TMP_Text)(object)componentInChildren;
		}

		internal static TMP_Text CreateLabel(LazyButton button, string text)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: 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_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)button == (Object)null)
			{
				return null;
			}
			Transform val = ((Component)button).transform.Find("GK2CraftMax_Label");
			if ((Object)(object)val != (Object)null)
			{
				return ((Component)val).GetComponent<TMP_Text>();
			}
			GameObject val2 = new GameObject("GK2CraftMax_Label", new Type[2]
			{
				typeof(RectTransform),
				typeof(TextMeshProUGUI)
			});
			val2.transform.SetParent(((Component)button).transform, false);
			RectTransform component = val2.GetComponent<RectTransform>();
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			component.offsetMin = Vector2.zero;
			component.offsetMax = Vector2.zero;
			component.anchoredPosition = new Vector2(0f, -2f);
			TextMeshProUGUI component2 = val2.GetComponent<TextMeshProUGUI>();
			((TMP_Text)component2).text = text;
			((TMP_Text)component2).alignment = (TextAlignmentOptions)514;
			((TMP_Text)component2).fontSize = 18f;
			((Graphic)component2).raycastTarget = false;
			((Graphic)component2).color = Color32.op_Implicit(new Color32(byte.MaxValue, (byte)210, (byte)45, byte.MaxValue));
			return (TMP_Text)(object)component2;
		}
	}
	internal sealed class MaxButtonState
	{
		private static readonly ConditionalWeakTable<Component, MaxButtonState> States = new ConditionalWeakTable<Component, MaxButtonState>();

		private LazyButton template;

		private Transform parent;

		private bool resolved;

		internal LazyButton Button;

		internal Transform Icon;

		internal TMP_Text Label;

		internal GamepadNavigationItem Navigation;

		internal bool Initialized;

		internal object Context;

		internal readonly NavigationInsertion Insertion = new NavigationInsertion();

		internal readonly List<UICraftItemCell> CraftCells = new List<UICraftItemCell>();

		internal static void Restore(Component window)
		{
			if (States.TryGetValue(window, out var value))
			{
				value.Insertion.Restore();
				if ((Object)(object)value.Navigation != (Object)null)
				{
					value.Navigation.Active = false;
				}
				value.Context = null;
				value.CraftCells.Clear();
			}
		}

		internal static MaxButtonState For(Component window)
		{
			if (!States.TryGetValue(window, out var value))
			{
				value = new MaxButtonState();
				States.Add(window, value);
			}
			return value;
		}

		internal LazyButton Resolve(LazyButton source, string name)
		{
			Transform val = (((Object)(object)source != (Object)null) ? ((Component)source).transform.parent : null);
			bool flag = (Object)(object)Button == (Object)null && Button != null;
			if ((Object)(object)template != (Object)(object)source || (Object)(object)parent != (Object)(object)val || flag || ((Object)(object)Button != (Object)null && (Object)(object)((Component)Button).transform.parent != (Object)(object)val))
			{
				Insertion.Restore();
				template = source;
				parent = val;
				Button = null;
				Icon = null;
				Label = null;
				Navigation = null;
				Initialized = false;
				resolved = false;
				Context = null;
				CraftCells.Clear();
			}
			if (!resolved && (Object)(object)val != (Object)null)
			{
				Transform val2 = val.Find(name);
				Button = (((Object)(object)val2 != (Object)null) ? ((Component)val2).GetComponent<LazyButton>() : null);
				resolved = true;
			}
			if ((Object)(object)Icon == (Object)null && Icon != null)
			{
				Initialized = false;
			}
			return Button;
		}
	}
	internal sealed class NavigationInsertion
	{
		private sealed class Link
		{
			internal GamepadNavigationItem From;

			internal GUIDirection Direction;

			internal GamepadNavigationItem Previous;

			internal GamepadNavigationItem Installed;
		}

		private static readonly Dictionary<GUIDirection, FieldInfo> Fields = new Dictionary<GUIDirection, FieldInfo>
		{
			{
				(GUIDirection)0,
				AccessTools.Field(typeof(GamepadNavigationItem), "leftItem")
			},
			{
				(GUIDirection)1,
				AccessTools.Field(typeof(GamepadNavigationItem), "rightItem")
			},
			{
				(GUIDirection)2,
				AccessTools.Field(typeof(GamepadNavigationItem), "upItem")
			},
			{
				(GUIDirection)3,
				AccessTools.Field(typeof(GamepadNavigationItem), "downItem")
			}
		};

		private readonly List<Link> links = new List<Link>();

		private GamepadNavigationItem inserted;

		internal bool IsAttached
		{
			get
			{
				if ((Object)(object)inserted != (Object)null)
				{
					return links.Count > 0;
				}
				return false;
			}
		}

		internal static GUIDirection Opposite(GUIDirection direction)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected I4, but got Unknown
			return (GUIDirection)((int)direction switch
			{
				0 => 1, 
				1 => 0, 
				2 => 3, 
				_ => 2, 
			});
		}

		private static GamepadNavigationItem Read(GamepadNavigationItem item, GUIDirection direction)
		{
			//IL_0005: 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_0017: Expected O, but got Unknown
			return (GamepadNavigationItem)Fields[direction].GetValue(item);
		}

		private void Set(GamepadNavigationItem from, GUIDirection direction, GamepadNavigationItem to)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			links.Add(new Link
			{
				From = from,
				Direction = direction,
				Previous = Read(from, direction),
				Installed = to
			});
			from.SetCustomDirectionItem(direction, to, false);
		}

		internal void Attach(GamepadNavigationController controller, GamepadNavigationItem anchor, GUIDirection direction, GamepadNavigationItem max)
		{
			//IL_003e: 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)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			Restore();
			if ((Object)(object)controller == (Object)null || !GamepadNavigationHelper.IsUsable(anchor) || (Object)(object)max == (Object)null)
			{
				return;
			}
			List<GamepadNavigationItem> items = GamepadNavigationHelper.GetItems(controller);
			if (items == null || !items.Contains(anchor))
			{
				return;
			}
			max.Active = false;
			GUIDirection val = Opposite(direction);
			GamepadNavigationItem val2 = GamepadNavigationHelper.ResolveDirection(controller, anchor, direction);
			bool flag = (Object)(object)val2 != (Object)null && (Object)(object)val2 != (Object)(object)anchor && (Object)(object)GamepadNavigationHelper.ResolveDirection(controller, val2, val) == (Object)(object)anchor;
			int i = int.MinValue;
			HashSet<int> hashSet = new HashSet<int>();
			foreach (GamepadNavigationItem item in items)
			{
				if ((Object)(object)item != (Object)null && (Object)(object)item != (Object)(object)max)
				{
					hashSet.Add(item.group);
				}
			}
			foreach (NavigationGroupSource navigationGroupSource in controller.navigationGroupSources)
			{
				hashSet.Add(navigationGroupSource.group);
				foreach (NavigationGroupTarget groupTarget in navigationGroupSource.groupTargets)
				{
					hashSet.Add(groupTarget.group);
				}
			}
			for (; hashSet.Contains(i); i++)
			{
			}
			max.group = i;
			max.ResetCustomDirections();
			max.SetCustomDirectionItem(val, anchor, false);
			if ((Object)(object)val2 != (Object)null && (Object)(object)val2 != (Object)(object)anchor)
			{
				max.SetCustomDirectionItem(direction, val2, false);
			}
			((Behaviour)max).enabled = true;
			max.Active = true;
			inserted = max;
			Set(anchor, direction, max);
			if (flag)
			{
				Set(val2, val, max);
			}
		}

		internal void Restore()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			foreach (Link link in links)
			{
				if ((Object)(object)link.From != (Object)null && (Object)(object)Read(link.From, link.Direction) == (Object)(object)link.Installed)
				{
					link.From.SetCustomDirectionItem(link.Direction, link.Previous, false);
				}
			}
			links.Clear();
			if ((Object)(object)inserted != (Object)null)
			{
				inserted.ResetCustomDirections();
				inserted.Active = false;
			}
			inserted = null;
		}

		internal void AttachRing(GamepadNavigationController controller, GamepadNavigationItem first, GamepadNavigationItem last, GamepadNavigationItem max)
		{
			Restore();
			if ((Object)(object)controller == (Object)null || !GamepadNavigationHelper.IsUsable(first) || !GamepadNavigationHelper.IsUsable(last) || (Object)(object)max == (Object)null)
			{
				return;
			}
			List<GamepadNavigationItem> items = GamepadNavigationHelper.GetItems(controller);
			if (items == null || !items.Contains(first) || !items.Contains(last))
			{
				return;
			}
			max.Active = false;
			int i = int.MinValue;
			HashSet<int> hashSet = new HashSet<int>();
			foreach (GamepadNavigationItem item in items)
			{
				if ((Object)(object)item != (Object)null && (Object)(object)item != (Object)(object)max)
				{
					hashSet.Add(item.group);
				}
			}
			foreach (NavigationGroupSource navigationGroupSource in controller.navigationGroupSources)
			{
				hashSet.Add(navigationGroupSource.group);
				foreach (NavigationGroupTarget groupTarget in navigationGroupSource.groupTargets)
				{
					hashSet.Add(groupTarget.group);
				}
			}
			for (; hashSet.Contains(i); i++)
			{
			}
			max.group = i;
			max.ResetCustomDirections();
			max.SetCustomDirectionItem((GUIDirection)0, last, false);
			max.SetCustomDirectionItem((GUIDirection)1, first, false);
			((Behaviour)max).enabled = true;
			max.Active = true;
			inserted = max;
			Set(last, (GUIDirection)1, max);
			Set(first, (GUIDirection)0, max);
		}
	}
}