Decompiled source of GK2LaboratoryFolioHelper v0.3.2

plugins/GK2KnownFormulaHelper/GK2KnownFormulaHelper.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GK2LaboratoryFolioHelper.Alchemy;
using GK2LaboratoryFolioHelper.Compatibility;
using GK2LaboratoryFolioHelper.Configuration;
using GK2LaboratoryFolioHelper.Infrastructure;
using GK2LaboratoryFolioHelper.Input;
using GK2LaboratoryFolioHelper.Patches;
using GK2LaboratoryFolioHelper.Runtime;
using GK2LaboratoryFolioHelper.UI;
using GK2LaboratoryFolioHelper.UI.Typography;
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("GK2KnownFormulaHelper")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.3.2.0")]
[assembly: AssemblyInformationalVersion("0.3.2+fc1450f54322fd546fa6d6f9c5cdede5eb94718c")]
[assembly: AssemblyProduct("GK2KnownFormulaHelper")]
[assembly: AssemblyTitle("GK2KnownFormulaHelper")]
[assembly: AssemblyVersion("0.3.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 GK2LaboratoryFolioHelper
{
	[BepInPlugin("w00dst0ckOo.GK2LaboratoryFolioHelper", "GK2 Known Formula Helper", "0.3.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "w00dst0ckOo.GK2LaboratoryFolioHelper";

		public const string PluginName = "GK2 Known Formula Helper";

		public const string PluginVersion = "0.3.2";

		private readonly ModRuntime runtime = new ModRuntime();

		public static Plugin Instance { get; private set; }

		private void Awake()
		{
			Instance = this;
			runtime.Initialize(((BaseUnityPlugin)this).Logger, ((BaseUnityPlugin)this).Config);
		}

		private void Update()
		{
			runtime.Update();
		}

		private void OnDestroy()
		{
			runtime.Shutdown();
			if (Instance == this)
			{
				Instance = null;
			}
		}
	}
}
namespace GK2LaboratoryFolioHelper.UI
{
	internal sealed class AlchemyVariantControls
	{
		private const float IngredientArrowGap = 10f;

		private const float CounterIngredientGap = 6f;

		private static readonly FieldInfo PlusButtonField = AccessTools.Field(typeof(UIAlchemyWindow), "plusBtn");

		private static readonly FieldInfo IngredientsField = AccessTools.Field(typeof(UIAlchemyWindow), "ingredients");

		private UIAlchemyWindow window;

		private GameObject controls;

		private RectTransform controlsRect;

		private RectTransform leftButtonRect;

		private RectTransform rightButtonRect;

		private RectTransform counterRect;

		private TextMeshProUGUI counter;

		internal GameObject Root => controls;

		internal bool Build(UIAlchemyWindow target, UnityAction selectPrevious, UnityAction selectNext)
		{
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Expected O, but got Unknown
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			Destroy();
			window = target;
			UIAlchemyWindow obj = window;
			Transform obj2 = ((obj != null) ? ((Component)obj).transform : null);
			RectTransform val = (RectTransform)(object)((obj2 is RectTransform) ? obj2 : null);
			object? obj3 = PlusButtonField?.GetValue(window);
			LazyButton val2 = (LazyButton)((obj3 is LazyButton) ? obj3 : null);
			LazyButton val3 = FindQueueButton(useRightArrow: false) ?? val2;
			LazyButton val4 = FindQueueButton(useRightArrow: true) ?? val2;
			if ((Object)(object)val == (Object)null || (Object)(object)val3 == (Object)null || (Object)(object)val4 == (Object)null)
			{
				ModLog.Warning($"Could not create laboratory mix controls | window={(Object)(object)val != (Object)null} | queueTemplates={(Object)(object)val3 != (Object)null && (Object)(object)val4 != (Object)null}");
				return false;
			}
			controls = new GameObject("GK2AlchemyMixVariants", new Type[2]
			{
				typeof(RectTransform),
				typeof(LayoutElement)
			});
			controls.transform.SetParent((Transform)(object)val, false);
			controlsRect = controls.GetComponent<RectTransform>();
			controlsRect.anchorMin = new Vector2(0.5f, 0.5f);
			controlsRect.anchorMax = new Vector2(0.5f, 0.5f);
			controlsRect.sizeDelta = Vector2.zero;
			controlsRect.pivot = new Vector2(0.5f, 0.5f);
			((Transform)controlsRect).SetAsLastSibling();
			controls.GetComponent<LayoutElement>().ignoreLayout = true;
			leftButtonRect = CreateButtonClone(val3, "<", selectPrevious, (Object)(object)val3 == (Object)(object)val2);
			counter = CreateLabel();
			counterRect = ((TMP_Text)counter).rectTransform;
			rightButtonRect = CreateButtonClone(val4, ">", selectNext, (Object)(object)val4 == (Object)(object)val2);
			Position();
			return true;
		}

		internal void UpdateCounter(int index, IReadOnlyList<PinnedFormulaManager.LaboratoryMixOption> options)
		{
			if (!((Object)(object)counter == (Object)null) && options != null && options.Count != 0 && index >= 0 && index < options.Count)
			{
				PinnedFormulaManager.LaboratoryMixOption laboratoryMixOption = options[index];
				((TMP_Text)counter).text = string.Format("{0}/{1}\n{2}", index + 1, options.Count, laboratoryMixOption.IsCraftable ? "Ready" : $"Missing {laboratoryMixOption.MissingItemCount}");
			}
		}

		internal void Position()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: 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_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: 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_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)controlsRect == (Object)null || (Object)(object)window == (Object)null || !(((Component)window).transform is RectTransform))
			{
				return;
			}
			controlsRect.anchorMin = new Vector2(0.5f, 0.5f);
			controlsRect.anchorMax = new Vector2(0.5f, 0.5f);
			controlsRect.anchoredPosition = Vector2.zero;
			if ((Object)(object)leftButtonRect == (Object)null || (Object)(object)rightButtonRect == (Object)null || (Object)(object)counterRect == (Object)null)
			{
				return;
			}
			if (IngredientsField?.GetValue(window) is List<UIAlchemyIngredient> { Count: not 0 } list)
			{
				float num = float.MaxValue;
				float num2 = float.MinValue;
				float num3 = float.MaxValue;
				float num4 = float.MinValue;
				Vector3[] array = (Vector3[])(object)new Vector3[4];
				foreach (UIAlchemyIngredient item in list)
				{
					object obj;
					if (item == null)
					{
						obj = null;
					}
					else
					{
						UIItemCell cell = item.cell;
						obj = ((cell != null) ? ((Component)cell).transform : null);
					}
					RectTransform val = (RectTransform)((obj is RectTransform) ? obj : null);
					if (!((Object)(object)val == (Object)null))
					{
						val.GetWorldCorners(array);
						Vector3[] array2 = array;
						foreach (Vector3 val2 in array2)
						{
							Vector3 val3 = ((Transform)controlsRect).InverseTransformPoint(val2);
							num = Mathf.Min(num, val3.x);
							num2 = Mathf.Max(num2, val3.x);
							num3 = Mathf.Min(num3, val3.y);
							num4 = Mathf.Max(num4, val3.y);
						}
					}
				}
				if (num == float.MaxValue)
				{
					SetControlPositions(new Vector2(-48f, 126f), new Vector2(0f, 126f), new Vector2(48f, 126f));
					return;
				}
				float num5 = (num3 + num4) * 0.5f;
				float num6 = (num + num2) * 0.5f;
				float num7 = num - 10f;
				Rect rect = leftButtonRect.rect;
				Vector2 leftPosition = new Vector2(num7 - ((Rect)(ref rect)).width * 0.5f, num5);
				float num8 = num4 + 6f;
				rect = counterRect.rect;
				Vector2 counterPosition = new Vector2(num6, num8 + ((Rect)(ref rect)).height * 0.5f);
				float num9 = num2 + 10f;
				rect = rightButtonRect.rect;
				SetControlPositions(leftPosition, counterPosition, new Vector2(num9 + ((Rect)(ref rect)).width * 0.5f, num5));
			}
			else
			{
				SetControlPositions(new Vector2(-48f, 126f), new Vector2(0f, 126f), new Vector2(48f, 126f));
			}
		}

		internal void Destroy()
		{
			if ((Object)(object)controls != (Object)null)
			{
				Object.Destroy((Object)(object)controls);
			}
			window = null;
			controls = null;
			controlsRect = null;
			leftButtonRect = null;
			rightButtonRect = null;
			counterRect = null;
			counter = null;
		}

		private RectTransform CreateButtonClone(LazyButton template, string label, UnityAction action, bool replaceText)
		{
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(((Component)template).gameObject, controls.transform, false);
			((Object)val).name = "VariantButton_" + label;
			val.SetActive(true);
			LazyButton component = val.GetComponent<LazyButton>();
			((UnityEventBase)((Button)component).onClick).RemoveAllListeners();
			((UnityEvent)((Button)component).onClick).AddListener(action);
			((Selectable)component).interactable = true;
			if (replaceText)
			{
				TMP_Text[] componentsInChildren = val.GetComponentsInChildren<TMP_Text>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					componentsInChildren[i].text = label;
				}
			}
			LayoutElement val2 = val.GetComponent<LayoutElement>() ?? val.AddComponent<LayoutElement>();
			RectTransform component2 = val.GetComponent<RectTransform>();
			component2.anchorMin = new Vector2(0.5f, 0.5f);
			component2.anchorMax = new Vector2(0.5f, 0.5f);
			component2.pivot = new Vector2(0.5f, 0.5f);
			component2.sizeDelta = new Vector2(28f, 28f);
			val2.minWidth = 28f;
			val2.preferredWidth = 28f;
			val2.minHeight = 28f;
			val2.preferredHeight = 28f;
			return component2;
		}

		private TextMeshProUGUI CreateLabel()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: 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_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("VariantCounter", new Type[3]
			{
				typeof(RectTransform),
				typeof(TextMeshProUGUI),
				typeof(LayoutElement)
			});
			val.transform.SetParent(controls.transform, false);
			LayoutElement component = val.GetComponent<LayoutElement>();
			component.minWidth = 34f;
			component.preferredWidth = 34f;
			component.minHeight = 28f;
			component.preferredHeight = 28f;
			TextMeshProUGUI component2 = val.GetComponent<TextMeshProUGUI>();
			RectTransform rectTransform = ((TMP_Text)component2).rectTransform;
			rectTransform.anchorMin = new Vector2(0.5f, 0.5f);
			rectTransform.anchorMax = new Vector2(0.5f, 0.5f);
			rectTransform.pivot = new Vector2(0.5f, 0.5f);
			rectTransform.sizeDelta = new Vector2(34f, 28f);
			((TMP_Text)component2).alignment = (TextAlignmentOptions)514;
			((TMP_Text)component2).fontSize = 10f;
			((Graphic)component2).color = Color.white;
			((Graphic)component2).raycastTarget = false;
			ModTypography.ApplyStatus((TMP_Text)(object)component2);
			return component2;
		}

		private static LazyButton FindQueueButton(bool useRightArrow)
		{
			UICraftQueueElementWidget[] array = Resources.FindObjectsOfTypeAll<UICraftQueueElementWidget>();
			foreach (UICraftQueueElementWidget val in array)
			{
				LazyButton val2 = (useRightArrow ? val.QueueDownButton : val.QueueUpButton);
				if ((Object)(object)val2 != (Object)null && (Object)(object)((Component)val2).gameObject != (Object)null)
				{
					return val2;
				}
			}
			return null;
		}

		private void SetControlPositions(Vector2 leftPosition, Vector2 counterPosition, Vector2 rightPosition)
		{
			//IL_0006: 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_001e: Unknown result type (might be due to invalid IL or missing references)
			leftButtonRect.anchoredPosition = leftPosition;
			counterRect.anchoredPosition = counterPosition;
			rightButtonRect.anchoredPosition = rightPosition;
		}
	}
	internal sealed class HudPositionPreview : MonoBehaviour
	{
		private static readonly string[] Scenarios = new string[10] { "Off - normal HUD", "Baseline - no external panel", "GK2RecipePin - small panel on the right", "GK2RecipePin - tall panel on the right", "Kebo - right", "Kebo - left (no displacement expected)", "Kebo - center (only displace if overlapping)", "Both panels - use the lowest bottom edge", "Kebo - transparent (no displacement expected)", "Kebo - inactive (no displacement expected)" };

		private static HudPositionPreview instance;

		private GameObject canvasObject;

		private RectTransform recipePanel;

		private RectTransform keboPanel;

		private TextMeshProUGUI status;

		private int scenario;

		private static bool IsActive
		{
			get
			{
				if ((Object)(object)instance != (Object)null && ((Behaviour)instance).isActiveAndEnabled)
				{
					return instance.scenario > 0;
				}
				return false;
			}
		}

		internal static void Attach(GameObject anchor, TextMeshProUGUI fontSource)
		{
			Shutdown();
			ConfigEntry<bool> enabled = HudPreviewConfig.Enabled;
			if (enabled != null && enabled.Value)
			{
				instance = anchor.AddComponent<HudPositionPreview>();
				instance.Build(fontSource);
			}
		}

		private void Build(TextMeshProUGUI fontSource)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_0075: 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_00c5: 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_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			canvasObject = new GameObject("FormulaHelper_PositionPreview", new Type[3]
			{
				typeof(RectTransform),
				typeof(Canvas),
				typeof(CanvasScaler)
			});
			Canvas component = canvasObject.GetComponent<Canvas>();
			component.renderMode = (RenderMode)0;
			component.sortingOrder = 30001;
			CanvasScaler component2 = canvasObject.GetComponent<CanvasScaler>();
			component2.uiScaleMode = (ScaleMode)1;
			component2.referenceResolution = new Vector2(1920f, 1080f);
			recipePanel = CreatePanel("GK2RecipePin (simulated)", new Color(0.12f, 0.35f, 0.65f, 0.85f), fontSource);
			keboPanel = CreatePanel("Kebo Recipe Pins (simulated)", new Color(0.65f, 0.32f, 0.1f, 0.85f), fontSource);
			RectTransform val = CreatePanel("Position preview", new Color(0.08f, 0.08f, 0.08f, 0.9f), fontSource);
			Place(val, new Vector2(0f, 0f), new Vector2(16f, 100f), new Vector2(620f, 85f));
			status = ((Component)val).GetComponentInChildren<TextMeshProUGUI>();
			ApplyScenario();
			canvasObject.SetActive(((Behaviour)this).isActiveAndEnabled);
		}

		private RectTransform CreatePanel(string title, Color color, TextMeshProUGUI fontSource)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(title, new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(CanvasGroup)
			});
			val.transform.SetParent(canvasObject.transform, false);
			Image component = val.GetComponent<Image>();
			((Graphic)component).color = color;
			((Graphic)component).raycastTarget = false;
			CanvasGroup component2 = val.GetComponent<CanvasGroup>();
			component2.interactable = false;
			component2.blocksRaycasts = false;
			GameObject val2 = new GameObject("Label", new Type[2]
			{
				typeof(RectTransform),
				typeof(TextMeshProUGUI)
			});
			val2.transform.SetParent(val.transform, false);
			RectTransform component3 = val2.GetComponent<RectTransform>();
			component3.anchorMin = Vector2.zero;
			component3.anchorMax = Vector2.one;
			component3.offsetMin = new Vector2(12f, 12f);
			component3.offsetMax = new Vector2(-12f, -12f);
			TextMeshProUGUI component4 = val2.GetComponent<TextMeshProUGUI>();
			if ((Object)(object)fontSource != (Object)null)
			{
				((TMP_Text)component4).font = ((TMP_Text)fontSource).font;
				((TMP_Text)component4).fontSharedMaterial = ((TMP_Text)fontSource).fontSharedMaterial;
			}
			((TMP_Text)component4).text = title;
			((TMP_Text)component4).fontSize = 22f;
			((Graphic)component4).color = Color.white;
			((Graphic)component4).raycastTarget = false;
			((TMP_Text)component4).alignment = (TextAlignmentOptions)257;
			((TMP_Text)component4).textWrappingMode = (TextWrappingModes)1;
			ModTypography.ApplyPreviewText((TMP_Text)(object)component4);
			RectTransform component5 = val.GetComponent<RectTransform>();
			LaboratoryPinsLayoutListener.Observe(component5);
			return component5;
		}

		private static void Place(RectTransform panel, Vector2 anchor, Vector2 offset, Vector2 size)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			panel.anchorMin = anchor;
			panel.anchorMax = anchor;
			panel.pivot = new Vector2(anchor.x, 1f);
			panel.anchoredPosition = offset;
			panel.sizeDelta = size;
		}

		private void ApplyScenario()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: 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_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: 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)
			Place(recipePanel, Vector2.one, new Vector2(-12f, -110f), new Vector2(380f, (scenario == 3) ? 350f : 150f));
			Vector2 anchor = (Vector2)((scenario == 5) ? new Vector2(0f, 1f) : ((scenario == 6) ? new Vector2(0.5f, 1f) : Vector2.one));
			Place(keboPanel, anchor, new Vector2((scenario == 5) ? 16f : ((scenario == 6) ? 0f : (-16f)), (scenario == 7) ? (-280f) : (-110f)), new Vector2(420f, 240f));
			((Component)recipePanel).gameObject.SetActive(scenario == 2 || scenario == 3 || scenario == 7);
			((Component)keboPanel).gameObject.SetActive(scenario >= 4 && scenario <= 8);
			((Component)keboPanel).GetComponent<CanvasGroup>().alpha = ((scenario == 8) ? 0f : 1f);
			((TMP_Text)status).text = $"HUD position test {scenario}/{Scenarios.Length - 1}: {Scenarios[scenario]}\n{HudPreviewConfig.PreviousScenario.Value}: previous | {HudPreviewConfig.NextScenario.Value}: next";
			LaboratoryPinsHud.RequestRefresh();
			LaboratoryPinsHud.RequestPositionUpdate();
		}

		private void Update()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			KeyboardShortcut value = HudPreviewConfig.NextScenario.Value;
			int num;
			if (!((KeyboardShortcut)(ref value)).IsDown())
			{
				value = HudPreviewConfig.PreviousScenario.Value;
				num = (((KeyboardShortcut)(ref value)).IsDown() ? (-1) : 0);
			}
			else
			{
				num = 1;
			}
			int num2 = num;
			if (num2 != 0)
			{
				scenario = (scenario + num2 + Scenarios.Length) % Scenarios.Length;
				ApplyScenario();
			}
		}

		internal static void IncludeBottom(float left, float right, ref float bottom, ref bool found)
		{
			if (IsActive)
			{
				ExternalHudCompatibility.IncludeOverlappingBottom(instance.recipePanel, left, right, ref bottom, ref found);
				ExternalHudCompatibility.IncludeOverlappingBottom(instance.keboPanel, left, right, ref bottom, ref found);
			}
		}

		internal static void AddSampleIfEmpty(List<PinnedFormulaManager.PinnedFormulaViewData> pins)
		{
			if (IsActive && pins.Count == 0)
			{
				pins.Add(new PinnedFormulaManager.PinnedFormulaViewData
				{
					FormulaId = "__hud_position_preview__",
					Name = "Position test",
					StatusText = "Preview only"
				});
			}
		}

		private void OnEnable()
		{
			if ((Object)(object)canvasObject != (Object)null)
			{
				canvasObject.SetActive(true);
			}
			LaboratoryPinsHud.RequestRefresh();
		}

		private void OnDisable()
		{
			if ((Object)(object)canvasObject != (Object)null)
			{
				canvasObject.SetActive(false);
			}
			LaboratoryPinsHud.RequestRefresh();
			LaboratoryPinsHud.RequestPositionUpdate();
		}

		private void OnDestroy()
		{
			if ((Object)(object)canvasObject != (Object)null)
			{
				Object.Destroy((Object)(object)canvasObject);
			}
			if ((Object)(object)instance == (Object)(object)this)
			{
				instance = null;
			}
		}

		internal static void Shutdown()
		{
			if ((Object)(object)instance != (Object)null)
			{
				((Behaviour)instance).enabled = false;
				Object.Destroy((Object)(object)instance);
				instance = null;
			}
		}
	}
	internal static class HudScreenGeometry
	{
		private static readonly Vector3[] Corners = (Vector3[])(object)new Vector3[4];

		internal static Camera GetCanvasCamera(RectTransform rect)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Invalid comparison between Unknown and I4
			Canvas val = ((rect != null) ? ((Component)rect).GetComponentInParent<Canvas>() : null);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			val = val.rootCanvas;
			if ((int)val.renderMode == 0)
			{
				return null;
			}
			if (!((Object)(object)val.worldCamera != (Object)null))
			{
				if ((int)val.renderMode != 2)
				{
					return null;
				}
				return Camera.main;
			}
			return val.worldCamera;
		}

		internal static bool TryGetScreenRect(RectTransform root, out Rect screenRect)
		{
			//IL_0001: 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_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: 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_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: 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_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			screenRect = default(Rect);
			if (IsVisible(root))
			{
				Rect rect = root.rect;
				if (!(((Rect)(ref rect)).width <= 0f))
				{
					rect = root.rect;
					if (!(((Rect)(ref rect)).height <= 0f))
					{
						Camera canvasCamera = GetCanvasCamera(root);
						root.GetWorldCorners(Corners);
						Vector2 val = default(Vector2);
						((Vector2)(ref val))..ctor(float.MaxValue, float.MaxValue);
						Vector2 val2 = default(Vector2);
						((Vector2)(ref val2))..ctor(float.MinValue, float.MinValue);
						Vector3[] corners = Corners;
						foreach (Vector3 val3 in corners)
						{
							Vector2 val4 = RectTransformUtility.WorldToScreenPoint(canvasCamera, val3);
							if (float.IsNaN(val4.x) || float.IsInfinity(val4.x) || float.IsNaN(val4.y) || float.IsInfinity(val4.y))
							{
								return false;
							}
							val = Vector2.Min(val, val4);
							val2 = Vector2.Max(val2, val4);
						}
						screenRect = Rect.MinMaxRect(val.x, val.y, val2.x, val2.y);
						if (((Rect)(ref screenRect)).width > 0f)
						{
							return ((Rect)(ref screenRect)).height > 0f;
						}
						return false;
					}
				}
			}
			return false;
		}

		internal static void IncludeBottom(RectTransform root, ref float bottomScreenY, ref bool found)
		{
			if (TryGetScreenRect(root, out var screenRect))
			{
				bottomScreenY = Mathf.Min(bottomScreenY, ((Rect)(ref screenRect)).yMin);
				found = true;
			}
		}

		internal static void IncludeOverlappingBottom(RectTransform root, float left, float right, ref float bottom, ref bool found)
		{
			if (TryGetScreenRect(root, out var screenRect) && ((Rect)(ref screenRect)).xMax > left && ((Rect)(ref screenRect)).xMin < right)
			{
				bottom = Mathf.Min(bottom, ((Rect)(ref screenRect)).yMin);
				found = true;
			}
		}

		internal static bool IsVisible(RectTransform root)
		{
			if ((Object)(object)root == (Object)null || !((Component)root).gameObject.activeInHierarchy)
			{
				return false;
			}
			Canvas componentInParent = ((Component)root).GetComponentInParent<Canvas>();
			if ((Object)(object)componentInParent == (Object)null || !((Behaviour)componentInParent).isActiveAndEnabled || !((Behaviour)componentInParent.rootCanvas).isActiveAndEnabled)
			{
				return false;
			}
			Transform val = (Transform)(object)root;
			while ((Object)(object)val != (Object)null)
			{
				bool flag = false;
				CanvasGroup[] components = ((Component)val).GetComponents<CanvasGroup>();
				foreach (CanvasGroup val2 in components)
				{
					if (((Behaviour)val2).enabled)
					{
						if (val2.alpha <= 0f)
						{
							return false;
						}
						flag |= val2.ignoreParentGroups;
					}
				}
				if (flag)
				{
					break;
				}
				val = val.parent;
			}
			return true;
		}
	}
	internal static class LaboratoryPinCardFactory
	{
		private static readonly Color CardColor = new Color(0.14f, 0.15f, 0.18f, 0.96f);

		internal static void Create(RectTransform contentRoot, PinnedFormulaManager.PinnedFormulaViewData pin)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Expected O, but got Unknown
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Expected O, but got Unknown
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Expected O, but got Unknown
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: Expected O, but got Unknown
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0315: Unknown result type (might be due to invalid IL or missing references)
			//IL_031c: Expected O, but got Unknown
			//IL_03fd: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Pin_" + pin.FormulaId, new Type[4]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(LazyButton),
				typeof(VerticalLayoutGroup)
			});
			AttachToHud(val, (Transform)(object)contentRoot);
			Image component = val.GetComponent<Image>();
			((Graphic)component).color = CardColor;
			((Graphic)component).raycastTarget = true;
			LazyButton component2 = val.GetComponent<LazyButton>();
			AlchemyFormulaDef formula = ((GameBalanceBase)GameBalance.Me).GetDataOrNull<AlchemyFormulaDef>(pin.FormulaId);
			if ((Object)(object)component2 != (Object)null && formula != null)
			{
				((Selectable)component2).interactable = true;
				((UnityEventBase)((Button)component2).onClick).RemoveAllListeners();
				((UnityEvent)((Button)component2).onClick).AddListener((UnityAction)delegate
				{
					PinnedFormulaManager.Toggle(formula);
				});
			}
			VerticalLayoutGroup component3 = val.GetComponent<VerticalLayoutGroup>();
			((LayoutGroup)component3).padding = new RectOffset(6, 6, 4, 4);
			((HorizontalOrVerticalLayoutGroup)component3).spacing = 4f;
			((LayoutGroup)component3).childAlignment = (TextAnchor)0;
			((HorizontalOrVerticalLayoutGroup)component3).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)component3).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)component3).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)component3).childForceExpandHeight = false;
			GameObject val2 = new GameObject("Header", new Type[3]
			{
				typeof(RectTransform),
				typeof(HorizontalLayoutGroup),
				typeof(LayoutElement)
			});
			AttachToHud(val2, val.transform);
			LayoutElement component4 = val2.GetComponent<LayoutElement>();
			component4.minWidth = 0f;
			component4.preferredWidth = 0f;
			component4.flexibleWidth = 1f;
			component4.minHeight = 30f;
			HorizontalLayoutGroup component5 = val2.GetComponent<HorizontalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)component5).spacing = 8f;
			((LayoutGroup)component5).childAlignment = (TextAnchor)3;
			((HorizontalOrVerticalLayoutGroup)component5).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)component5).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)component5).childForceExpandWidth = false;
			((HorizontalOrVerticalLayoutGroup)component5).childForceExpandHeight = false;
			Transform transform = val2.transform;
			AlchemyFormulaDef obj = formula;
			CreateItemIcon(transform, (obj != null) ? obj.ItemDef : null, 30f, framed: true);
			GameObject val3 = new GameObject("TitleAndStatus", new Type[3]
			{
				typeof(RectTransform),
				typeof(VerticalLayoutGroup),
				typeof(LayoutElement)
			});
			AttachToHud(val3, val2.transform);
			LayoutElement component6 = val3.GetComponent<LayoutElement>();
			component6.minWidth = 0f;
			component6.preferredWidth = 0f;
			component6.flexibleWidth = 1f;
			VerticalLayoutGroup component7 = val3.GetComponent<VerticalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)component7).spacing = 0f;
			((HorizontalOrVerticalLayoutGroup)component7).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)component7).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)component7).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)component7).childForceExpandHeight = false;
			((LayoutGroup)component7).childAlignment = (TextAnchor)3;
			CreateText(val3.transform, pin.Name, 16f, 21f, (TextAlignmentOptions)513, Color.white);
			ModTypography.ApplyStatus((TMP_Text)(object)CreateText(val3.transform, pin.StatusText, 13f, 16f, (TextAlignmentOptions)513, (Color)(pin.IsCraftable ? new Color(0.5f, 0.84f, 0.42f) : Color.white)));
			GameObject val4 = new GameObject("Ingredients", new Type[3]
			{
				typeof(RectTransform),
				typeof(VerticalLayoutGroup),
				typeof(LayoutElement)
			});
			AttachToHud(val4, val.transform);
			LayoutElement component8 = val4.GetComponent<LayoutElement>();
			component8.minWidth = 0f;
			component8.preferredWidth = 0f;
			component8.flexibleWidth = 1f;
			VerticalLayoutGroup component9 = val4.GetComponent<VerticalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)component9).spacing = 3f;
			((LayoutGroup)component9).childAlignment = (TextAnchor)3;
			((HorizontalOrVerticalLayoutGroup)component9).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)component9).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)component9).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)component9).childForceExpandHeight = false;
			foreach (PinnedFormulaManager.PinnedIngredientViewData ingredient in pin.Ingredients)
			{
				CreateIngredientRow(val4.transform, ingredient);
			}
			if (pin.NoPowderIngredients.Count <= 0)
			{
				return;
			}
			ModTypography.ApplyText((TMP_Text)(object)CreateText(val4.transform, "Alt. recipe", 10f, 13f, (TextAlignmentOptions)513, new Color(0.72f, 0.72f, 0.72f)));
			foreach (PinnedFormulaManager.PinnedIngredientViewData noPowderIngredient in pin.NoPowderIngredients)
			{
				CreateIngredientRow(val4.transform, noPowderIngredient, alternative: true);
			}
		}

		private static void CreateIngredientRow(Transform parent, PinnedFormulaManager.PinnedIngredientViewData ingredient, bool alternative = false)
		{
			//IL_004b: 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_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Expected O, but got Unknown
			//IL_009a: 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_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: 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_01fb: Unknown result type (might be due to invalid IL or missing references)
			Color color = (ingredient.IsAvailable ? new Color(0.5f, 0.84f, 0.42f) : (ingredient.IsBuyable ? new Color(0.45f, 0.72f, 0.95f) : new Color(0.91f, 0.7f, 0.42f)));
			GameObject val = new GameObject("Ingredient_" + ingredient.ItemId, new Type[3]
			{
				typeof(RectTransform),
				typeof(HorizontalLayoutGroup),
				typeof(LayoutElement)
			});
			AttachToHud(val, parent);
			val.GetComponent<LayoutElement>().minHeight = (alternative ? 14f : 16f);
			HorizontalLayoutGroup component = val.GetComponent<HorizontalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)component).spacing = 4f;
			((LayoutGroup)component).childAlignment = (TextAnchor)3;
			((HorizontalOrVerticalLayoutGroup)component).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)component).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)component).childForceExpandWidth = false;
			((HorizontalOrVerticalLayoutGroup)component).childForceExpandHeight = false;
			CreateItemIcon(item: ((GameBalanceBase)GameBalance.Me).GetDataOrNull<ItemDef>(ingredient.ItemId), parent: val.transform, side: alternative ? 12f : 14f, framed: false);
			string text = ingredient.Name;
			if (ingredient.IsBuyable && !string.IsNullOrEmpty(ingredient.VendorName))
			{
				text += $"  <size=10>{ingredient.VendorName} ({ingredient.VendorStock})</size>";
			}
			TextMeshProUGUI val2 = CreateText(val.transform, text, alternative ? 11f : 12f, alternative ? 14f : 16f, (TextAlignmentOptions)513, color, wrap: true);
			if (ingredient.IsBuyable && !string.IsNullOrEmpty(ingredient.VendorName))
			{
				ModTypography.ApplyVendorText((TMP_Text)(object)val2);
			}
			else
			{
				ModTypography.ApplyText((TMP_Text)(object)val2);
			}
			LayoutElement component2 = ((Component)val2).GetComponent<LayoutElement>();
			component2.minWidth = 0f;
			component2.preferredWidth = 0f;
			component2.flexibleWidth = 1f;
			TextMeshProUGUI obj = CreateText(val.transform, ingredient.CountText, alternative ? 11f : 12f, alternative ? 14f : 16f, (TextAlignmentOptions)516, color);
			ModTypography.ApplyCount((TMP_Text)(object)obj);
			LayoutElement component3 = ((Component)obj).GetComponent<LayoutElement>();
			component3.minWidth = 30f;
			component3.preferredWidth = 30f;
			component3.flexibleWidth = 0f;
		}

		private static void CreateItemIcon(Transform parent, ItemDef item, float side, bool framed)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_00b7: 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_00c8: Expected O, but got Unknown
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("ItemIcon", new Type[2]
			{
				typeof(RectTransform),
				typeof(LayoutElement)
			});
			AttachToHud(val, parent);
			LayoutElement component = val.GetComponent<LayoutElement>();
			component.minWidth = side;
			component.preferredWidth = side;
			component.minHeight = side;
			component.preferredHeight = side;
			component.flexibleWidth = 0f;
			component.flexibleHeight = 0f;
			if (framed)
			{
				Image obj = val.AddComponent<Image>();
				((Graphic)obj).color = new Color(0.22f, 0.23f, 0.28f);
				((Graphic)obj).raycastTarget = false;
			}
			GameObject val2 = new GameObject("Icon", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			AttachToHud(val2, val.transform);
			RectTransform component2 = val2.GetComponent<RectTransform>();
			component2.anchorMin = Vector2.zero;
			component2.anchorMax = Vector2.one;
			float num = (framed ? 3f : 0f);
			component2.offsetMin = new Vector2(num, num);
			component2.offsetMax = new Vector2(0f - num, 0f - num);
			Image component3 = val2.GetComponent<Image>();
			component3.sprite = ((item == null) ? null : LazySingletonSO<EasySpritesCollection>.Instance.GetSprite(item.iconId, (string)null));
			component3.preserveAspect = true;
			((Graphic)component3).raycastTarget = false;
			((Behaviour)component3).enabled = (Object)(object)component3.sprite != (Object)null;
		}

		private static TextMeshProUGUI CreateText(Transform parent, string text, float fontSize, float height, TextAlignmentOptions alignment, Color color, bool wrap = false)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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)
			GameObject val = new GameObject("Text", new Type[3]
			{
				typeof(RectTransform),
				typeof(TextMeshProUGUI),
				typeof(LayoutElement)
			});
			AttachToHud(val, parent);
			LayoutElement component = val.GetComponent<LayoutElement>();
			component.minHeight = height;
			component.preferredHeight = (wrap ? (-1f) : height);
			TextMeshProUGUI component2 = val.GetComponent<TextMeshProUGUI>();
			((TMP_Text)component2).text = text;
			((TMP_Text)component2).fontSize = fontSize;
			((Graphic)component2).color = color;
			((TMP_Text)component2).alignment = alignment;
			ModTypography.ApplyTitle((TMP_Text)(object)component2);
			((TMP_Text)component2).textWrappingMode = (TextWrappingModes)(wrap ? 1 : 0);
			((TMP_Text)component2).overflowMode = (TextOverflowModes)(!wrap);
			return component2;
		}

		private static void AttachToHud(GameObject child, Transform parent)
		{
			child.layer = ((Component)parent).gameObject.layer;
			child.transform.SetParent(parent, false);
		}
	}
	internal static class LaboratoryPinsHud
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static Action <0>__Refresh;

			public static WillRenderCanvases <1>__BeforeLayout;

			public static WillRenderCanvases <2>__AfterLayout;
		}

		private const float DefaultCardWidth = 310f;

		private const float CardScale = 0.8f;

		private static readonly FieldInfo RightUpGroupField = AccessTools.Field(typeof(HUD), "rightUpGroup");

		private static readonly FieldInfo HappinessLabelField = AccessTools.Field(typeof(HUD), "happinessLabel");

		private static GameObject panelObject;

		private static RectTransform contentRoot;

		private static bool layoutUpdateQueued;

		private static bool refreshPending;

		private static bool updatingPosition;

		private static List<PinnedFormulaManager.PinnedFormulaViewData> renderedPins;

		public static void Initialize(HUD hud)
		{
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Expected O, but got Unknown
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Expected O, but got Unknown
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Expected O, but got Unknown
			if ((Object)(object)hud == (Object)null)
			{
				return;
			}
			DestroyExisting();
			object? obj = RightUpGroupField?.GetValue(hud);
			GameObject val = (GameObject)((obj is GameObject) ? obj : null);
			if ((Object)(object)val == (Object)null)
			{
				ModLog.Warning("Could not find HUD.rightUpGroup.");
				return;
			}
			object? obj2 = HappinessLabelField?.GetValue(hud);
			TextMeshProUGUI val2 = (TextMeshProUGUI)((obj2 is TextMeshProUGUI) ? obj2 : null);
			if ((Object)(object)val2 != (Object)null)
			{
				ModTypography.Initialize(val2);
			}
			panelObject = new GameObject("GK2LaboratoryPins", new Type[2]
			{
				typeof(RectTransform),
				typeof(LayoutElement)
			});
			panelObject.GetComponent<LayoutElement>().ignoreLayout = true;
			AttachToHud(panelObject, val.transform);
			RectTransform component = panelObject.GetComponent<RectTransform>();
			component.anchorMin = new Vector2(1f, 1f);
			component.anchorMax = new Vector2(1f, 1f);
			component.pivot = new Vector2(1f, 1f);
			component.anchoredPosition = LaboratoryPinsPositioner.DefaultPosition;
			component.sizeDelta = new Vector2(310f, 0f);
			((Transform)component).localScale = new Vector3(0.8f, 0.8f, 1f);
			Transform transform = val.transform;
			RectTransform val3 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			if (val3 != null)
			{
				LaboratoryPinsLayoutListener.Observe(val3);
			}
			GameObject val4 = new GameObject("Content", new Type[3]
			{
				typeof(RectTransform),
				typeof(VerticalLayoutGroup),
				typeof(ContentSizeFitter)
			});
			AttachToHud(val4, panelObject.transform);
			contentRoot = val4.GetComponent<RectTransform>();
			contentRoot.anchorMin = new Vector2(0f, 1f);
			contentRoot.anchorMax = new Vector2(1f, 1f);
			contentRoot.pivot = new Vector2(0.5f, 1f);
			contentRoot.anchoredPosition = Vector2.zero;
			contentRoot.sizeDelta = Vector2.zero;
			val4.GetComponent<ContentSizeFitter>().verticalFit = (FitMode)2;
			VerticalLayoutGroup component2 = val4.GetComponent<VerticalLayoutGroup>();
			((LayoutGroup)component2).padding = new RectOffset(0, 0, 0, 0);
			((HorizontalOrVerticalLayoutGroup)component2).spacing = 6f;
			((LayoutGroup)component2).childAlignment = (TextAnchor)0;
			((HorizontalOrVerticalLayoutGroup)component2).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)component2).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)component2).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)component2).childForceExpandHeight = false;
			PinnedFormulaManager.PinsChanged -= Refresh;
			PinnedFormulaManager.PinsChanged += Refresh;
			PinsInventoryWatcher.Initialize();
			HudPositionPreview.Attach(val, val2);
			Refresh();
			ModLog.Debug("Laboratory pins HUD initialized.");
		}

		public static void Refresh()
		{
			if ((Object)(object)panelObject == (Object)null || (Object)(object)contentRoot == (Object)null)
			{
				return;
			}
			UpdatePosition();
			List<PinnedFormulaManager.PinnedFormulaViewData> pinnedViewData = PinnedFormulaManager.GetPinnedViewData();
			HudPositionPreview.AddSampleIfEmpty(pinnedViewData);
			if (PinnedFormulaContentComparer.AreEqual(renderedPins, pinnedViewData))
			{
				return;
			}
			ClearChildren((Transform)(object)contentRoot);
			foreach (PinnedFormulaManager.PinnedFormulaViewData item in pinnedViewData)
			{
				LaboratoryPinCardFactory.Create(contentRoot, item);
			}
			renderedPins = pinnedViewData;
			if (panelObject.activeSelf != pinnedViewData.Count > 0)
			{
				panelObject.SetActive(pinnedViewData.Count > 0);
			}
			if (pinnedViewData.Count > 0)
			{
				LayoutRebuilder.ForceRebuildLayoutImmediate(contentRoot);
			}
		}

		internal static void RequestRefresh()
		{
			//IL_002b: 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_0036: Expected O, but got Unknown
			if (!((Object)(object)panelObject == (Object)null) && !refreshPending)
			{
				refreshPending = true;
				object obj = <>O.<1>__BeforeLayout;
				if (obj == null)
				{
					WillRenderCanvases val = BeforeLayout;
					<>O.<1>__BeforeLayout = val;
					obj = (object)val;
				}
				Canvas.preWillRenderCanvases += (WillRenderCanvases)obj;
			}
		}

		internal static void RequestPositionUpdate()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			if (!((Object)(object)panelObject == (Object)null) && !layoutUpdateQueued && !updatingPosition)
			{
				_ = CanvasUpdateRegistry.instance;
				layoutUpdateQueued = true;
				object obj = <>O.<2>__AfterLayout;
				if (obj == null)
				{
					WillRenderCanvases val = AfterLayout;
					<>O.<2>__AfterLayout = val;
					obj = (object)val;
				}
				Canvas.willRenderCanvases += (WillRenderCanvases)obj;
			}
		}

		internal static void Shutdown()
		{
			DestroyExisting();
			LaboratoryPinsLayoutListener.StopObserving();
		}

		private static void BeforeLayout()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			object obj = <>O.<1>__BeforeLayout;
			if (obj == null)
			{
				WillRenderCanvases val = BeforeLayout;
				<>O.<1>__BeforeLayout = val;
				obj = (object)val;
			}
			Canvas.preWillRenderCanvases -= (WillRenderCanvases)obj;
			refreshPending = false;
			Refresh();
			RequestPositionUpdate();
		}

		private static void AfterLayout()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			object obj = <>O.<2>__AfterLayout;
			if (obj == null)
			{
				WillRenderCanvases val = AfterLayout;
				<>O.<2>__AfterLayout = val;
				obj = (object)val;
			}
			Canvas.willRenderCanvases -= (WillRenderCanvases)obj;
			layoutUpdateQueued = false;
			UpdatePosition();
		}

		private static void UpdatePosition()
		{
			if ((Object)(object)panelObject == (Object)null || updatingPosition)
			{
				return;
			}
			updatingPosition = true;
			try
			{
				LaboratoryPinsPositioner.Update(panelObject.GetComponent<RectTransform>());
			}
			finally
			{
				updatingPosition = false;
			}
		}

		private static void DestroyExisting()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			HudPositionPreview.Shutdown();
			object obj = <>O.<1>__BeforeLayout;
			if (obj == null)
			{
				WillRenderCanvases val = BeforeLayout;
				<>O.<1>__BeforeLayout = val;
				obj = (object)val;
			}
			Canvas.preWillRenderCanvases -= (WillRenderCanvases)obj;
			object obj2 = <>O.<2>__AfterLayout;
			if (obj2 == null)
			{
				WillRenderCanvases val2 = AfterLayout;
				<>O.<2>__AfterLayout = val2;
				obj2 = (object)val2;
			}
			Canvas.willRenderCanvases -= (WillRenderCanvases)obj2;
			layoutUpdateQueued = false;
			refreshPending = false;
			PinnedFormulaManager.PinsChanged -= Refresh;
			if ((Object)(object)panelObject != (Object)null)
			{
				Object.Destroy((Object)(object)panelObject);
			}
			panelObject = null;
			contentRoot = null;
			renderedPins = null;
		}

		private static void ClearChildren(Transform parent)
		{
			for (int num = parent.childCount - 1; num >= 0; num--)
			{
				((Component)parent.GetChild(num)).gameObject.SetActive(false);
				Object.Destroy((Object)(object)((Component)parent.GetChild(num)).gameObject);
			}
		}

		private static void AttachToHud(GameObject child, Transform parent)
		{
			child.layer = ((Component)parent).gameObject.layer;
			child.transform.SetParent(parent, false);
		}
	}
	internal sealed class LaboratoryPinsLayoutListener : MonoBehaviour
	{
		private static readonly List<LaboratoryPinsLayoutListener> Listeners = new List<LaboratoryPinsLayoutListener>();

		internal static void Observe(RectTransform root)
		{
			if ((Object)(object)root != (Object)null && (Object)(object)((Component)root).GetComponent<LaboratoryPinsLayoutListener>() == (Object)null)
			{
				Listeners.Add(((Component)root).gameObject.AddComponent<LaboratoryPinsLayoutListener>());
			}
		}

		internal static void StopObserving()
		{
			LaboratoryPinsLayoutListener[] array = Listeners.ToArray();
			foreach (LaboratoryPinsLayoutListener laboratoryPinsLayoutListener in array)
			{
				if ((Object)(object)laboratoryPinsLayoutListener != (Object)null)
				{
					Object.Destroy((Object)(object)laboratoryPinsLayoutListener);
				}
			}
			Listeners.Clear();
		}

		private void OnRectTransformDimensionsChange()
		{
			LaboratoryPinsHud.RequestPositionUpdate();
		}

		private void OnEnable()
		{
			LaboratoryPinsHud.RequestPositionUpdate();
		}

		private void OnCanvasGroupChanged()
		{
			LaboratoryPinsHud.RequestPositionUpdate();
		}

		private void OnTransformParentChanged()
		{
			LaboratoryPinsHud.RequestPositionUpdate();
		}

		private void OnDisable()
		{
			LaboratoryPinsHud.RequestPositionUpdate();
		}

		private void OnDestroy()
		{
			Listeners.Remove(this);
			LaboratoryPinsHud.RequestPositionUpdate();
		}
	}
	internal static class LaboratoryPinsPositioner
	{
		private const float ExternalSpacingPixels = 12f;

		internal static readonly Vector2 DefaultPosition = new Vector2(-16f, -85f);

		internal static void Update(RectTransform panelRect)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: 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_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)panelRect == (Object)null)
			{
				return;
			}
			Transform parent = ((Transform)panelRect).parent;
			RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null);
			if (val == null)
			{
				return;
			}
			Vector2 defaultPosition = DefaultPosition;
			Camera canvasCamera = ExternalHudCompatibility.GetCanvasCamera(val);
			Rect rect = val.rect;
			float num = ((Rect)(ref rect)).xMax + DefaultPosition.x;
			rect = val.rect;
			Vector3 val2 = default(Vector3);
			((Vector3)(ref val2))..ctor(num, ((Rect)(ref rect)).yMax + DefaultPosition.y, ((Transform)panelRect).localPosition.z);
			Vector2 val3 = RectTransformUtility.WorldToScreenPoint(canvasCamera, ((Transform)val).TransformPoint(val2));
			Vector3 val4 = val2;
			rect = panelRect.rect;
			Vector2 val5 = RectTransformUtility.WorldToScreenPoint(canvasCamera, ((Transform)val).TransformPoint(val4 - new Vector3(((Rect)(ref rect)).width * ((Transform)panelRect).localScale.x, 0f, 0f)));
			float num2 = Mathf.Abs(val3.x - val5.x);
			if (ExternalHudCompatibility.TryGetRecipePinScreenRect(out var screenRect))
			{
				val3.x = ((Rect)(ref screenRect)).xMax;
			}
			if (!ExternalHudCompatibility.TryGetExternalBottomScreenY(val3.x - num2, val3.x, out var bottomScreenY))
			{
				Apply(panelRect, defaultPosition);
				return;
			}
			val3.y = bottomScreenY - 12f;
			Vector2 val6 = default(Vector2);
			if (RectTransformUtility.ScreenPointToLocalPointInRectangle(val, val3, canvasCamera, ref val6))
			{
				float x = val6.x;
				rect = val.rect;
				float num3 = x - ((Rect)(ref rect)).xMax;
				float y = val6.y;
				rect = val.rect;
				((Vector2)(ref defaultPosition))..ctor(num3, y - ((Rect)(ref rect)).yMax);
			}
			Apply(panelRect, defaultPosition);
		}

		private static void Apply(RectTransform panelRect, Vector2 targetPosition)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if (panelRect.anchoredPosition != targetPosition)
			{
				panelRect.anchoredPosition = targetPosition;
			}
		}
	}
	internal static class PinnedFormulaContentComparer
	{
		internal static bool AreEqual(List<PinnedFormulaManager.PinnedFormulaViewData> previous, List<PinnedFormulaManager.PinnedFormulaViewData> current)
		{
			if (previous == null || previous.Count != current.Count)
			{
				return false;
			}
			for (int i = 0; i < current.Count; i++)
			{
				PinnedFormulaManager.PinnedFormulaViewData pinnedFormulaViewData = previous[i];
				PinnedFormulaManager.PinnedFormulaViewData pinnedFormulaViewData2 = current[i];
				if (pinnedFormulaViewData.FormulaId != pinnedFormulaViewData2.FormulaId || pinnedFormulaViewData.Name != pinnedFormulaViewData2.Name || pinnedFormulaViewData.StatusText != pinnedFormulaViewData2.StatusText || pinnedFormulaViewData.IsCraftable != pinnedFormulaViewData2.IsCraftable || !IngredientsEqual(pinnedFormulaViewData.Ingredients, pinnedFormulaViewData2.Ingredients) || !IngredientsEqual(pinnedFormulaViewData.NoPowderIngredients, pinnedFormulaViewData2.NoPowderIngredients))
				{
					return false;
				}
			}
			return true;
		}

		private static bool IngredientsEqual(List<PinnedFormulaManager.PinnedIngredientViewData> previous, List<PinnedFormulaManager.PinnedIngredientViewData> current)
		{
			if (previous == null || current == null)
			{
				return previous == current;
			}
			if (previous.Count != current.Count)
			{
				return false;
			}
			for (int i = 0; i < current.Count; i++)
			{
				PinnedFormulaManager.PinnedIngredientViewData pinnedIngredientViewData = previous[i];
				PinnedFormulaManager.PinnedIngredientViewData pinnedIngredientViewData2 = current[i];
				if (pinnedIngredientViewData.ItemId != pinnedIngredientViewData2.ItemId || pinnedIngredientViewData.Name != pinnedIngredientViewData2.Name || pinnedIngredientViewData.CountText != pinnedIngredientViewData2.CountText || pinnedIngredientViewData.IsAvailable != pinnedIngredientViewData2.IsAvailable || pinnedIngredientViewData.IsBuyable != pinnedIngredientViewData2.IsBuyable || pinnedIngredientViewData.VendorName != pinnedIngredientViewData2.VendorName || pinnedIngredientViewData.VendorStock != pinnedIngredientViewData2.VendorStock)
				{
					return false;
				}
			}
			return true;
		}
	}
}
namespace GK2LaboratoryFolioHelper.UI.Typography
{
	internal static class ModTypography
	{
		internal static void Initialize(TextMeshProUGUI source)
		{
			TypographyFontResolver.Initialize(source);
		}

		internal static void ApplyTitle(TMP_Text text)
		{
			ApplyReadableText(text);
		}

		internal static void ApplyText(TMP_Text text)
		{
			ApplyReadableText(text);
		}

		internal static void ApplyStatus(TMP_Text text)
		{
			ApplyReadableText(text);
			if (TypographyFontResolver.IsSharp && (Object)(object)text != (Object)null)
			{
				text.lineSpacing = -1f;
			}
		}

		internal static void ApplyCount(TMP_Text text)
		{
			ApplyReadableText(text);
		}

		internal static void ApplyVendorText(TMP_Text text)
		{
			ApplyReadableText(text);
		}

		internal static void ApplyPreviewText(TMP_Text text)
		{
			ApplyReadableText(text);
		}

		internal static void Shutdown()
		{
			TypographyFontResolver.Shutdown();
		}

		private static void ApplyReadableText(TMP_Text text)
		{
			if ((Object)(object)text == (Object)null)
			{
				return;
			}
			TMP_FontAsset val = TypographyFontResolver.ResolveFont();
			if ((Object)(object)val != (Object)null)
			{
				text.font = val;
				Material val2 = (((Object)(object)TypographyFontResolver.BundledFont == (Object)(object)val) ? ((TMP_Asset)val).material : TypographyFontResolver.ReferenceMaterial);
				if ((Object)(object)val2 != (Object)null)
				{
					text.fontSharedMaterial = val2;
				}
			}
			else
			{
				TypographyFontResolver.WarnMissingReferenceOnce();
			}
			if ((Object)(object)TypographyFontResolver.ReferenceSpriteAsset != (Object)null)
			{
				text.spriteAsset = TypographyFontResolver.ReferenceSpriteAsset;
			}
			text.richText = true;
			((Graphic)text).raycastTarget = false;
			if (TypographyFontResolver.IsSharp)
			{
				text.enableAutoSizing = false;
				text.fontWeight = (FontWeight)400;
				text.wordSpacing = 0f;
				text.lineSpacingAdjustment = 0f;
				text.extraPadding = false;
				text.fontStyle = (FontStyles)0;
				text.characterSpacing = -1f;
				text.lineSpacing = 0f;
			}
		}
	}
	internal static class TypographyFontResolver
	{
		private const string BundleName = "knownformulahelper_fonts.bundle";

		private const string RequiredCharacters = "0123456789<>+-/.,:;!?%()[]{}&'\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzÄÖÜäöüẞßÀÁÂÃÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕØŒÙÚÛÝŸàáâãåæçèéêëìíîïðñòóôõøœùúûýÿ";

		private static TMP_FontAsset referenceFont;

		private static Material referenceMaterial;

		private static TMP_SpriteAsset referenceSpriteAsset;

		private static TMP_FontAsset bundledFont;

		private static AssetBundle fontBundle;

		private static bool inventoryLogged;

		private static bool bundleAttempted;

		private static bool fallbackLogged;

		private static bool missingReferenceLogged;

		internal static bool IsSharp
		{
			get
			{
				ConfigEntry<UiFontStyle> fontStyle = UiConfig.FontStyle;
				if (fontStyle == null)
				{
					return false;
				}
				return fontStyle.Value == UiFontStyle.Sharp;
			}
		}

		internal static Material ReferenceMaterial => referenceMaterial;

		internal static TMP_SpriteAsset ReferenceSpriteAsset => referenceSpriteAsset;

		internal static TMP_FontAsset BundledFont => bundledFont;

		internal static void Initialize(TextMeshProUGUI source)
		{
			if ((Object)(object)source != (Object)null)
			{
				if (referenceFont == null)
				{
					referenceFont = ((TMP_Text)source).font;
				}
				if (referenceMaterial == null)
				{
					referenceMaterial = ((TMP_Text)source).fontSharedMaterial;
				}
				if (referenceSpriteAsset == null)
				{
					referenceSpriteAsset = ((TMP_Text)source).spriteAsset;
				}
			}
			ResolveReferenceFromLoadedUi();
			LogLoadedFontsOnce();
			TryLoadBundledFont();
		}

		internal static TMP_FontAsset ResolveFont()
		{
			ResolveReferenceFromLoadedUi();
			TryLoadBundledFont();
			if (!IsSharp)
			{
				return referenceFont;
			}
			return bundledFont ?? referenceFont;
		}

		internal static void WarnMissingReferenceOnce()
		{
			if (!missingReferenceLogged)
			{
				missingReferenceLogged = true;
				ModLog.Warning("Could not resolve a loaded TMP font for helper UI; retaining TMP defaults.");
			}
		}

		internal static void Shutdown()
		{
			if ((Object)(object)fontBundle != (Object)null)
			{
				fontBundle.Unload(false);
			}
			fontBundle = null;
			bundledFont = null;
			referenceFont = null;
			referenceMaterial = null;
			referenceSpriteAsset = null;
			inventoryLogged = false;
			bundleAttempted = false;
			fallbackLogged = false;
			missingReferenceLogged = false;
		}

		private static void ResolveReferenceFromLoadedUi()
		{
			if ((Object)(object)referenceFont != (Object)null)
			{
				return;
			}
			TMP_Text[] array = Resources.FindObjectsOfTypeAll<TMP_Text>();
			foreach (TMP_Text val in array)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val.font == (Object)null))
				{
					referenceFont = val.font;
					referenceMaterial = val.fontSharedMaterial;
					referenceSpriteAsset = val.spriteAsset;
					break;
				}
			}
		}

		private static void LogLoadedFontsOnce()
		{
			if (inventoryLogged)
			{
				return;
			}
			inventoryLogged = true;
			TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>();
			if (array.Length == 0)
			{
				ModLog.Debug("No TMP_FontAsset resources are loaded yet.");
				return;
			}
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			TMP_FontAsset[] array2 = array;
			foreach (TMP_FontAsset val in array2)
			{
				if ((Object)(object)val != (Object)null && !string.IsNullOrEmpty(((Object)val).name))
				{
					hashSet.Add(((Object)val).name);
				}
			}
			ModLog.Debug(string.Format("Loaded game TMP fonts ({0}): {1}", hashSet.Count, string.Join(", ", hashSet)));
		}

		private static void TryLoadBundledFont()
		{
			if (bundleAttempted || !IsSharp)
			{
				return;
			}
			bundleAttempted = true;
			string bundlePath = GetBundlePath();
			if (!File.Exists(bundlePath))
			{
				LogFallbackOnce("Bundle file was not found: '" + bundlePath + "'.");
				return;
			}
			try
			{
				fontBundle = AssetBundle.LoadFromFile(bundlePath);
				if ((Object)(object)fontBundle == (Object)null)
				{
					LogFallbackOnce("AssetBundle.LoadFromFile returned null: '" + bundlePath + "'.");
					return;
				}
				TMP_FontAsset[] array = fontBundle.LoadAllAssets<TMP_FontAsset>();
				foreach (TMP_FontAsset val in array)
				{
					if (!((Object)(object)val == (Object)null) && ContainsRequiredCharacters(val))
					{
						bundledFont = val;
						ModLog.Info("Loaded validated helper TMP font '" + ((Object)val).name + "' from '" + bundlePath + "'.");
						return;
					}
				}
				LogFallbackOnce("The helper font bundle contains no TMP font with the required Latin, German, digit and punctuation glyphs: '" + bundlePath + "'.");
			}
			catch (Exception ex)
			{
				LogFallbackOnce("Could not load the optional helper font bundle '" + bundlePath + "': " + ex.Message);
			}
		}

		private static bool ContainsRequiredCharacters(TMP_FontAsset font)
		{
			string text = "0123456789<>+-/.,:;!?%()[]{}&'\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzÄÖÜäöüẞßÀÁÂÃÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕØŒÙÚÛÝŸàáâãåæçèéêëìíîïðñòóôõøœùúûýÿ";
			foreach (char character in text)
			{
				if (!ContainsCharacter(font, character, new HashSet<TMP_FontAsset>()))
				{
					return false;
				}
			}
			return true;
		}

		private static bool ContainsCharacter(TMP_FontAsset font, char character, HashSet<TMP_FontAsset> visited)
		{
			if ((Object)(object)font == (Object)null || !visited.Add(font))
			{
				return false;
			}
			if (font.characterLookupTable.ContainsKey(character))
			{
				return true;
			}
			if (font.fallbackFontAssetTable == null)
			{
				return false;
			}
			foreach (TMP_FontAsset item in font.fallbackFontAssetTable)
			{
				if (ContainsCharacter(item, character, visited))
				{
					return true;
				}
			}
			return false;
		}

		private static string GetBundlePath()
		{
			string text = Path.GetDirectoryName(typeof(ModTypography).Assembly.Location);
			if (string.IsNullOrEmpty(text))
			{
				text = Path.Combine(Paths.PluginPath, "GK2KnownFormulaHelper");
			}
			return Path.Combine(text, "assets", "knownformulahelper_fonts.bundle");
		}

		private static void LogFallbackOnce(string reason)
		{
			if (!fallbackLogged)
			{
				fallbackLogged = true;
				ModLog.Warning("Optional helper font unavailable; using the loaded game font. " + reason);
			}
		}
	}
}
namespace GK2LaboratoryFolioHelper.Runtime
{
	internal sealed class ModRuntime
	{
		private Harmony harmony;

		internal void Initialize(ManualLogSource logger, ConfigFile config)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			ModLog.Initialize(logger);
			ModConfig.Bind(config);
			ModLog.Info("GK2 Known Formula Helper 0.3.2 loading...");
			harmony = new Harmony("w00dst0ckOo.GK2LaboratoryFolioHelper");
			harmony.PatchAll();
			CompatibilityBootstrap.Initialize(harmony);
			ModLog.Info("GK2 Known Formula Helper loaded.");
		}

		internal void Update()
		{
			CompatibilityBootstrap.Update();
		}

		internal void Shutdown()
		{
			PinsInventoryWatcher.DetachAll();
			AlchemyInventoryWatcher.Detach();
			CompatibilityBootstrap.Shutdown();
			LaboratoryPinsHud.Shutdown();
			ModTypography.Shutdown();
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			harmony = null;
		}
	}
}
namespace GK2LaboratoryFolioHelper.Patches
{
	[HarmonyPatch(typeof(UIAlchemyFolioWindow), "GetFormulaWidget")]
	internal static class AlchemyFolioPinPatch
	{
		private static readonly FieldInfo ItemCellField = AccessTools.Field(typeof(UIAlchemyFormulaWidget), "itemCell");

		private static readonly FieldInfo NameLabelField = AccessTools.Field(typeof(UIAlchemyFormulaWidget), "nameLabel");

		private static void Postfix(LazyScrollableElement parent, UIAlchemyFormulaWidget __result)
		{
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Expected O, but got Unknown
			//IL_01ae: Expected O, but got Unknown
			//IL_01ae: Expected O, but got Unknown
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)parent == (Object)null || (Object)(object)__result == (Object)null)
			{
				return;
			}
			object? obj = ItemCellField?.GetValue(__result);
			UIItemCell val = (UIItemCell)((obj is UIItemCell) ? obj : null);
			TextMeshProUGUI nameLabel = default(TextMeshProUGUI);
			ref TextMeshProUGUI reference = ref nameLabel;
			object? obj2 = NameLabelField?.GetValue(__result);
			reference = (TextMeshProUGUI)((obj2 is TextMeshProUGUI) ? obj2 : null);
			if ((Object)(object)val == (Object)null || (Object)(object)nameLabel == (Object)null)
			{
				return;
			}
			val.ClearCallbacks();
			LazyWidgetDataBase data = parent.Data;
			UIAlchemyFormulaWidgetData widgetData = (UIAlchemyFormulaWidgetData)(object)((data is UIAlchemyFormulaWidgetData) ? data : null);
			if (widgetData == null)
			{
				return;
			}
			AlchemyFormulaDef formula = widgetData.AlchemyFormulaDef;
			if (formula == null)
			{
				return;
			}
			if (AlchemyFolioSelectionContext.IsActive)
			{
				int ingredientSlotCount = AlchemyRecipeLoader.GetIngredientSlotCount(AlchemyFolioSelectionContext.Window);
				if (ingredientSlotCount <= 0 || !PinnedFormulaManager.TryGetBestMixForLaboratory(((BalanceBaseObject)formula).id, ingredientSlotCount, out var _, out var _))
				{
					((Selectable)val.LazyButton).interactable = false;
					if ((Object)(object)parent.GamepadNavigationItem != (Object)null)
					{
						parent.GamepadNavigationItem.Active = false;
					}
					((Graphic)nameLabel).color = new Color(((Graphic)nameLabel).color.r, ((Graphic)nameLabel).color.g, ((Graphic)nameLabel).color.b, 0.45f);
					RefreshPinVisual();
					return;
				}
			}
			((Selectable)val.LazyButton).interactable = true;
			val.OnItemCellPress = HandleFormulaPress;
			if ((Object)(object)parent.GamepadNavigationItem != (Object)null)
			{
				parent.GamepadNavigationItem.Active = true;
				parent.GamepadNavigationItem.SetCallbacks(new UnityAction(val.OnGamepadOver), new UnityAction(val.OnGamepadOut), new UnityAction(val.OnGamepadPress));
			}
			RefreshPinVisual();
			void HandleFormulaPress(UIItemCell _)
			{
				if (AlchemyFolioSelectionContext.IsActive)
				{
					SelectFormulaForLaboratory(formula);
				}
				else
				{
					PinnedFormulaManager.Toggle(formula);
					RefreshPinVisual();
				}
			}
			void RefreshPinVisual()
			{
				ItemDef displayItemDef = widgetData.GetDisplayItemDef();
				if (displayItemDef != null)
				{
					((TMP_Text)nameLabel).text = LLBase.L(((BalanceBaseObject)displayItemDef).id);
				}
			}
		}

		private static void SelectFormulaForLaboratory(AlchemyFormulaDef formula)
		{
			if (formula == null || !AlchemyFolioSelectionContext.IsActive)
			{
				return;
			}
			UIAlchemyWindow window = AlchemyFolioSelectionContext.Window;
			int ingredientSlotCount = AlchemyRecipeLoader.GetIngredientSlotCount(window);
			if (ingredientSlotCount <= 0)
			{
				ModLog.Warning("Could not determine laboratory ingredient slot count for '" + ((BalanceBaseObject)formula).id + "'.");
				return;
			}
			if (!PinnedFormulaManager.TryGetBestMixForLaboratory(((BalanceBaseObject)formula).id, ingredientSlotCount, out var mixId, out var isCraftable) || string.IsNullOrEmpty(mixId))
			{
				ModLog.Info("Formula cannot be used at this laboratory | formula='" + ((BalanceBaseObject)formula).id + "' | " + $"slots={ingredientSlotCount}");
				return;
			}
			UIAlchemyFolioWindow window2 = LazyUI.GetWindow<UIAlchemyFolioWindow>();
			if (!isCraftable && !PinnedFormulaManager.IsPinned(((BalanceBaseObject)formula).id))
			{
				PinnedFormulaManager.PinForMissingIngredients(formula);
				ModLog.Info("Alchemy formula pinned because ingredients are missing | formula='" + ((BalanceBaseObject)formula).id + "' | mix='" + mixId + "'");
			}
			((LazyWindow<UIAlchemyFolioWindowData>)(object)window2)?.Close();
			AlchemyFolioSelectionContext.End();
			bool flag = AlchemyRecipeLoader.LoadMix(window, mixId);
			bool flag2 = flag && AlchemyMixSelectionController.Begin(window, ((BalanceBaseObject)formula).id);
			ModLog.Info("Alchemy formula selected from folio | formula='" + ((BalanceBaseObject)formula).id + "' | mix='" + mixId + "' | " + $"slots={ingredientSlotCount} | " + $"craftable={isCraftable} | " + $"loaded={flag} | " + $"variants={flag2}");
		}
	}
	[HarmonyPatch(typeof(UIAlchemyWindow), "Update")]
	internal static class AlchemyMixSelectionPatch
	{
		private static void Postfix(UIAlchemyWindow __instance)
		{
			AlchemyMixSelectionController.Tick(__instance);
		}
	}
	[HarmonyPatch(typeof(UIAlchemyWindow), "GetGameKeyDelegates")]
	internal static class AlchemyMixSelectionGamepadPatch
	{
		private static void Postfix(UIAlchemyWindow __instance, ref Dictionary<GameKey, Func<bool>> __result)
		{
			__result.TryGetValue(GameKey.DpadLeft, out var left);
			__result[GameKey.DpadLeft] = () => AlchemyMixSelectionController.TryHandleDpad(__instance, -1, left);
			__result.TryGetValue(GameKey.DpadRight, out var right);
			__result[GameKey.DpadRight] = () => AlchemyMixSelectionController.TryHandleDpad(__instance, 1, right);
		}
	}
	[HarmonyPatch(typeof(LazyInput), "Update")]
	internal static class GlobalPinRemovalPatch
	{
		private static void Postfix()
		{
			ConfigEntry<bool> removeLastPinWithR = InputConfig.RemoveLastPinWithR3;
			if (removeLastPinWithR != null && removeLastPinWithR.Value && LazyInput.GetKeyDown(GameKey.RightStick))
			{
				PinnedFormulaManager.RemoveLastPin();
			}
		}
	}
	[HarmonyPatch(typeof(UIAlchemyWindow), "Close")]
	internal static class AlchemyMixSelectionClosePatch
	{
		private static void Postfix(UIAlchemyWindow __instance)
		{
			AlchemyMixSelectionController.Clear(__instance);
		}
	}
	[HarmonyPatch(typeof(UIAlchemyWindow), "Hide")]
	internal static class AlchemyMixSelectionHidePatch
	{
		private static void Postfix(UIAlchemyWindow __instance)
		{
			AlchemyMixSelectionController.Clear(__instance);
		}
	}
	[HarmonyPatch(typeof(UIAlchemyWindow), "Close")]
	internal static class AlchemyWindowClosePatch
	{
		private static void Prefix()
		{
			AlchemyInventoryWatcher.Detach();
		}
	}
	[HarmonyPatch(typeof(UIAlchemyWindow), "RedrawAlchemyTabLite", new Type[] { typeof(AlchemyMixDef) })]
	internal static class AlchemyWindowPatch
	{
		private static readonly FieldInfo ResultField = AccessTools.Field(typeof(UIAlchemyWindow), "result");

		private static readonly FieldInfo MixCraftIdField = AccessTools.Field(typeof(UIAlchemyWindow), "mixCraftId");

		private static readonly FieldInfo DataField = AccessTools.Field(typeof(UIAlchemyWindow), "data");

		private static void Postfix(UIAlchemyWindow __instance, AlchemyMixDef mix)
		{
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Expected O, but got Unknown
			//IL_0141: Expected O, but got Unknown
			//IL_0141: Expected O, but got Unknown
			UIAlchemyWindowData data = default(UIAlchemyWindowData);
			ref UIAlchemyWindowData reference = ref data;
			object? obj = DataField?.GetValue(__instance);
			reference = (UIAlchemyWindowData)((obj is UIAlchemyWindowData) ? obj : null);
			UIAlchemyWindowData obj2 = data;
			object obj3;
			if (obj2 == null)
			{
				obj3 = null;
			}
			else
			{
				Wgo wgo = obj2.Wgo;
				obj3 = ((wgo != null) ? wgo.Data : null);
			}
			if (obj3 != null)
			{
				MultiInventory craftableMultiInventory = data.Wgo.Data.GetCraftableMultiInventory(true);
				AlchemyInventoryWatcher.Attach(__instance, craftableMultiInventory);
			}
			object? obj4 = ResultField?.GetValue(__instance);
			UIItemCell val = (UIItemCell)((obj4 is UIItemCell) ? obj4 : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			string text = MixCraftIdField?.GetValue(__instance) as string;
			if ((string.IsNullOrEmpty(text) ? null : GameBalance.GetAlchemyMixDef(text)) == null)
			{
				val.DrawEmpty(false, true, false);
				val.NoSelectionFrames = false;
				((Selectable)val.LazyButton).interactable = true;
				val.OnItemCellPress = delegate
				{
					OpenAlchemyFolio(__instance, data);
				};
				if ((Object)(object)val.GamepadNavigationItem != (Object)null)
				{
					val.GamepadNavigationItem.Active = true;
					val.GamepadNavigationItem.SetCallbacks(new UnityAction(val.OnGamepadOver), new UnityAction(val.OnGamepadOut), new UnityAction(val.OnGamepadPress));
				}
			}
		}

		private static void OpenAlchemyFolio(UIAlchemyWindow alchemyWindow, UIAlchemyWindowData alchemyData)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			if ((Object)(object)alchemyWindow == (Object)null)
			{
				return;
			}
			object obj;
			if (alchemyData == null)
			{
				obj = null;
			}
			else
			{
				Wgo wgo = alchemyData.Wgo;
				obj = ((wgo != null) ? wgo.Data : null);
			}
			if (obj != null)
			{
				UIAlchemyFolioWindow window = LazyUI.GetWindow<UIAlchemyFolioWindow>();
				if ((Object)(object)window == (Object)null)
				{
					ModLog.Warning("Could not obtain UIAlchemyFolioWindow.");
					return;
				}
				UIAlchemyFolioWindowData val = new UIAlchemyFolioWindowData();
				val.FillFromGaveSave(alchemyData.Wgo.Data);
				AlchemyFolioSelectionContext.Begin(alchemyWindow);
				((LazyWindow<UIAlchemyFolioWindowData>)(object)window).Open(val);
				ModLog.Debug("Opened alchemy folio from laboratory.");
			}
		}
	}
	[HarmonyPatch(typeof(HUD), "Init")]
	internal static class HudPinsPatch
	{
		private static void Postfix(HUD __instance)
		{
			LaboratoryPinsHud.Initialize(__instance);
		}
	}
	[HarmonyPatch(typeof(InventoryUIItemMoveOpHandler), "TryMoveItem")]
	internal static class InventoryMovePatch
	{
		[HarmonyPostfix]
		private static void Postfix(Inventory from, Inventory to, bool __result)
		{
			if (__result)
			{
				PlayerData playerData = MainGame.PlayerData;
				Inventory val = ((playerData != null) ? playerData.Inventory : null);
				if (val != null && (from == val || to == val))
				{
					LaboratoryPinsHud.Refresh();
				}
			}
		}
	}
	internal static class RecipePinCompatibilityPatch
	{
		private static bool installed;

		public static void TryInstall(Harmony harmony)
		{
			if (!installed && Chainloader.PluginInfos.TryGetValue("br.pedro.gk2.recipepin", out var value))
			{
				object instance = value.Instance;
				if (instance != null)
				{
					Type type = instance.GetType();
					PatchPostfix(harmony, type, "ToggleRecipe");
					PatchPostfix(harmony, type, "RemoveRecipe");
					PatchPostfix(harmony, type, "ArrangeRecipes");
					PatchPostfix(harmony, type, "ResetSession");
					installed = true;
					ModLog.Debug("RecipePin HUD change hooks installed.");
				}
			}
		}

		private static void PatchPostfix(Harmony harmony, Type type, string methodName)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(type, methodName, (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				ModLog.Warning("RecipePin method '" + methodName + "' not found.");
				return;
			}
			MethodInfo methodInfo2 = AccessTools.Method(typeof(RecipePinCompatibilityPatch), "AfterRecipePinChanged", (Type[])null, (Type[])null);
			harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static void AfterRecipePinChanged()
		{
			LaboratoryPinsHud.Refresh();
			LaboratoryPinsHud.RequestPositionUpdate();
		}
	}
	internal static class ShoppingListCompatibilityPatch
	{
		private static ConfigFile config;

		private static BaseUnityPlugin plugin;

		private static Coroutine configRefresh;

		private static bool installed;

		public static void TryInstall(Harmony harmony)
		{
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Expected O, but got Unknown
			if (installed || !Chainloader.PluginInfos.TryGetValue("gk2.shoppinglist", out var value) || (Object)(object)value.Instance == (Object)null)
			{
				return;
			}
			try
			{
				BaseUnityPlugin instance = value.Instance;
				Type type = ((object)instance).GetType();
				Type type2 = AccessTools.Field(type, "_hud")?.FieldType;
				Type type3 = AccessTools.Field(type, "List")?.FieldType;
				MethodInfo methodInfo = ((type2 == null || type3 == null) ? null : AccessTools.Method(type2, "Tick", new Type[3]
				{
					type3,
					typeof(bool),
					typeof(bool)
				}, (Type[])null));
				if (methodInfo == null || AccessTools.Field(type2, "_sig")?.FieldType != typeof(string))
				{
					ModLog.Warning("Shopping List HudPanel.Tick layout hooks were not found.");
					return;
				}
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(ShoppingListCompatibilityPatch), "NotifyLayoutChanges", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null);
				config = instance.Config;
				plugin = instance;
				config.SettingChanged += OnSettingChanged;
				installed = true;
				ModLog.Debug("Shopping List HUD change hooks installed (no frame polling).");
			}
			catch (Exception ex)
			{
				ModLog.Warning("Could not install Shopping List HUD hooks: " + ex.Message);
			}
		}

		private static IEnumerable<CodeInstruction> NotifyLayoutChanges(IEnumerable<CodeInstruction> instructions, MethodBase original)
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Expected O, but got Unknown
			FieldInfo objB = AccessTools.Field(original.DeclaringType, "_sig");
			MethodInfo methodInfo = AccessTools.Method(typeof(GameObject), "SetActive", (Type[])null, (Type[])null);
			MethodInfo operand = AccessTools.Method(typeof(ShoppingListCompatibilityPatch), "SetActiveAndNotify", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(LaboratoryPinsHud), "RequestRefresh", (Type[])null, (Type[])null);
			List<CodeInstruction> list = new List<CodeInstruction>();
			int num = 0;
			int num2 = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				CodeInstruction val = new CodeInstruction(instruction);
				if (CodeInstructionExtensions.Calls(val, methodInfo))
				{
					val.opcode = OpCodes.Call;
					val.operand = operand;
					num++;
				}
				list.Add(val);
				if (instruction.opcode == OpCodes.Stfld && object.Equals(instruction.operand, objB))
				{
					list.Add(new CodeInstruction(OpCodes.Call, (object)methodInfo2));
					num2++;
				}
			}
			if (num == 0 || num2 != 1)
			{
				throw new InvalidOperationException("Shopping List Tick no longer matches the inspected visibility/redraw branches.");
			}
			return list;
		}

		private static void SetActiveAndNotify(GameObject target, bool active)
		{
			bool num = target.activeSelf != active;
			target.SetActive(active);
			if (num)
			{
				LaboratoryPinsHud.RequestRefresh();
			}
		}

		private static void OnSettingChanged(object sender, SettingChangedEventArgs args)
		{
			if (args.ChangedSetting.Definition.Section == "HUD" && configRefresh == null && (Object)(object)plugin != (Object)null)
			{
				configRefresh = ((MonoBehaviour)plugin).StartCoroutine(RefreshAfterSettingsApplied());
			}
		}

		private static IEnumerator RefreshAfterSettingsApplied()
		{
			yield return null;
			configRefresh = null;
			LaboratoryPinsHud.RequestRefresh();
		}

		internal static void Shutdown()
		{
			if ((Object)(object)plugin != (Object)null && configRefresh != null)
			{
				((MonoBehaviour)plugin).StopCoroutine(configRefresh);
			}
			configRefresh = null;
			plugin = null;
			if (config != null)
			{
				config.SettingChanged -= OnSettingChanged;
				config = null;
			}
			installed = false;
		}
	}
}
namespace GK2LaboratoryFolioHelper.Integration
{
	public static class KnownFormulaHelperIntegrationApi
	{
		public static ConfigEntry<int> MaxMixVariants => LaboratoryConfig.MaxMixVariants;

		public static ConfigEntry<UiFontStyle> FontStyle => UiConfig.FontStyle;
	}
}
namespace GK2LaboratoryFolioHelper.Input
{
	internal sealed class AlchemyVariantNavigation
	{
		private sealed class NavigationLink
		{
			internal GamepadNavigationItem From;

			internal GUIDirection Direction;

			internal GamepadNavigationItem Previous;

			internal GamepadNavigationItem Applied;
		}

		private static readonly FieldInfo IngredientsField = AccessTools.Field(typeof(UIAlchemyWindow), "ingredients");

		private static readonly FieldInfo ResultField = AccessTools.Field(typeof(UIAlchemyWindow), "result");

		private readonly List<NavigationLink> navigationLinks = new List<NavigationLink>();

		private GamepadNavigationController navigationController;

		private GamepadNavigationItem leftNavigation;

		private GamepadNavigationItem rightNavigation;

		internal void Refresh(UIAlchemyWindow window, GameObject controls)
		{
			GamepadNavigationController controller = GamepadNavigationHelper.GetController<UIAlchemyWindow>(window);
			if ((Object)(object)controller == (Object)null || (Object)(object)controls == (Object)null)
			{
				return;
			}
			navigationController = controller;
			LazyButton[] componentsInChildren = controls.GetComponentsInChildren<LazyButton>(true);
			foreach (LazyButton val in componentsInChildren)
			{
				GamepadNavigationItem val2 = ((Component)val).GetComponentInChildren<GamepadNavigationItem>(true);
				if (val2 == null)
				{
					val2 = ((Component)val).gameObject.GetComponent<GamepadNavigationItem>();
				}
				if (val2 == null)
				{
					val2 = ((Component)val).gameObject.AddComponent<GamepadNavigationItem>();
				}
				((Behaviour)val2).enabled = true;
				val2.Active = true;
				GamepadNavigationHelper.Register(controller, val2, 1f);
				GamepadNavigationHelper.BindButtonPress(val2, val);
				if (((Object)((Component)val).gameObject).name == "VariantButton_<")
				{
					leftNavigation = val2;
				}
				else if (((Object)((Component)val).gameObject).name == "VariantButton_>")
				{
					rightNavigation = val2;
				}
			}
			LinkGamepadControls(window, controller);
		}

		internal void Clear()
		{
			RestoreGamepadNavigation();
			if ((Object)(object)navigationController != (Object)null)
			{
				GamepadNavigationHelper.Unregister(navigationController, leftNavigation);
				GamepadNavigationHelper.Unregister(navigationController, rightNavigation);
			}
			leftNavigation = null;
			rightNavigation = null;
			navigationController = null;
		}

		private void LinkGamepadControls(UIAlchemyWindow window, GamepadNavigationController controller)
		{
			if ((Object)(object)leftNavigation == (Object)null || (Object)(object)rightNavigation == (Object)null)
			{
				return;
			}
			List<GamepadNavigationItem> items = GamepadNavigationHelper.GetItems(controller);
			if (items == null)
			{
				return;
			}
			GamepadNavigationItem val = FindCraftMaxNavigation(items);
			GamepadNavigationItem val2 = FindResultNavigation(window);
			List<GamepadNavigationItem> list = FindIngredientNavigations(window, controller);
			if ((Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null && list.Count > 0)
			{
				LinkLaboratoryRoute(val2, list, val);
				return;
			}
			GamepadNavigationItem val3 = FindNavigationAnchor(leftNavigation, items);
			GamepadNavigationItem val4 = FindNavigationAnchor(rightNavigation, items);
			if ((Object)(object)val == (Object)null && (Object)(object)val3 == (Object)null)
			{
				val3 = FindClosestNavigationItem(leftNavigation, items);
			}
			if ((Object)(object)val4 == (Object)null)
			{
				val4 = FindClosestNavigationItem(rightNavigation, items);
			}
			if ((Object)(object)val != (Object)null)
			{
				leftNavigation.group = val.group;
				rightNavigation.group = val.group;
				SetNavigationLink(val, (GUIDirection)3, leftNavigation);
				SetNavigationLink(leftNavigation, (GUIDirection)2, val);
				SetNavigationLink(rightNavigation, (GUIDirection)2, val);
			}
			if ((Object)(object)val3 != (Object)null && (Object)(object)val == (Object)null)
			{
				leftNavigation.group = val3.group;
				LinkVerticalNeighbors(val3, leftNavigation);
			}
			if ((Object)(object)val4 != (Object)null)
			{
				rightNavigation.group = val4.group;
				LinkVerticalNeighbors(val4, rightNavigation);
			}
			if ((Object)(object)val4 == (Object)null)
			{
				rightNavigation.group = leftNavigation.group;
			}
			SetNavigationLink(leftNavigation, (GUIDirection)1, rightNavigation);
			SetNavigationLink(rightNavigation, (GUIDirection)0, leftNavigation);
		}

		private static GamepadNavigationItem FindResultNavigation(UIAlchemyWindow window)
		{
			object? obj = ResultField?.GetValue(window);
			object? obj2 = ((obj is UIItemCell) ? obj : null);
			if (obj2 == null)
			{
				return null;
			}
			return ((UIItemCell)obj2).GamepadNavigationItem;
		}

		private static List<GamepadNavigationItem> FindIngredientNavigations(UIAlchemyWindow window, GamepadNavigationController controller)
		{
			List<GamepadNavigationItem> list = new List<GamepadNavigationItem>();
			if (!(IngredientsField?.GetValue(window) is List<UIAlchemyIngredient> list2))
			{
				return list;
			}
			foreach (UIAlchemyIngredient item in list2)
			{
				object obj;
				if (item == null)
				{
					obj = null;
				}
				else
				{
					UIItemCell cell = item.cell;
					obj = ((cell != null) ? cell.GamepadNavigationItem : null);
				}
				GamepadNavigationItem val = (GamepadNavigationItem)obj;
				if (!((Object)(object)val == (Object)null))
				{
					((Behaviour)val).enabled = true;
					val.Active = true;
					GamepadNavigationHelper.Register(controller, val, 1f);
					list.Add(val);
				}
			}
			return list;
		}

		private void LinkLaboratoryRoute(GamepadNavigationItem result, List<GamepadNavigationItem> ingredients, GamepadNavigationItem craftMax)
		{
			List<GamepadNavigationItem> list = new List<GamepadNavigationItem>(ingredients.Count + 4) { result, leftNavigation };
			list.AddRange(ingredients);
			list.Add(rightNavigation);
			list.Add(craftMax);
			leftNavigation.group = result.group;
			rightNavigation.group = result.group;
			for (int i = 0; i < list.Count; i++)
			{
				GamepadNavigationItem val = list[i];
				GamepadNavigationItem to = list[(i + 1) % list.Count];
				GamepadNavigationItem to2 = list[(i - 1 + list.Count) % list.Count];
				SetNavigationLink(val, (GUIDirection)1, to);
				SetNavigationLink(val, (GUIDirection)0, to2);
			}
		}

		private void LinkVerticalNeighbors(GamepadNavigationItem anchor, GamepadNavigationItem target)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)anchor == (Object)null || (Object)(object)target == (Object)null)
			{
				return;
			}
			Vector2 val = target.Pos - anchor.Pos;
			if (Mathf.Abs(val.y) >= Mathf.Abs(val.x))
			{
				if (val.y >= 0f)
				{
					SetNavigationLink(anchor, (GUIDirection)3, target);
					SetNavigationLink(target, (GUIDirection)2, anchor);
				}
				else
				{
					SetNavigationLink(anchor, (GUIDirection)2, target);
					SetNavigationLink(target, (GUIDirection)3, anchor);
				}
			}
			else if (val.x >= 0f)
			{
				SetNavigationLink(anchor, (GUIDirection)1, target);
				SetNavigationLink(target, (GUIDirection)0, anchor);
			}
			else
			{
				SetNavigationLink(anchor, (GUIDirection)0, target);
				SetNavigationLink(target, (GUIDirection)1, anchor);
			}
		}

		private GamepadNavigationItem FindClosestNavigationItem(GamepadNavigationItem target, List<GamepadNavigationItem> items)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			GamepadNavigationItem result = null;
			float num = float.MaxValue;
			for