Decompiled source of ItemRecipes v0.2.3

plugins/ItemRecipes/ItemRecipes.dll

Decompiled 8 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Localization;
using UnityEngine.Localization.Settings;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("ItemRecipes")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.3.0")]
[assembly: AssemblyInformationalVersion("0.2.3")]
[assembly: AssemblyProduct("ItemRecipes")]
[assembly: AssemblyTitle("ItemRecipes")]
[assembly: AssemblyVersion("0.2.3.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace ItemRecipes
{
	internal static class GrowthInfo
	{
		private static readonly FieldInfo? CropSeed = AccessTools.Field(typeof(BlockDirt), "currentSeed");

		private static readonly FieldInfo? CropDay = AccessTools.Field(typeof(BlockDirt), "dayCounter");

		private static readonly FieldInfo? CropWater = AccessTools.Field(typeof(BlockDirt), "isWatered");

		private static readonly FieldInfo? TreeDay = AccessTools.Field(typeof(BlockTree), "dayCounter");

		private static readonly FieldInfo? TreeWater = AccessTools.Field(typeof(BlockTree), "isWatered");

		private static readonly FieldInfo? AnimalFed = AccessTools.Field(typeof(BlockAnimal), "isFed");

		private static string Text(string zh, string en)
		{
			return RecipeBrowser.Text(zh, en);
		}

		private static T? Read<T>(FieldInfo? field, object instance) where T : struct
		{
			if (!(field?.GetValue(instance) is NetworkVariable<T> val))
			{
				return null;
			}
			return val.Value;
		}

		internal static SeedSO? Seed(BlockDirt dirt)
		{
			if (((NetworkBehaviour)dirt).IsSpawned && (Object)(object)GameManager.Instance != (Object)null)
			{
				long? num = Read<long>(CropSeed, dirt);
				if (num.HasValue)
				{
					long valueOrDefault = num.GetValueOrDefault();
					if (valueOrDefault >= 0)
					{
						ItemSO itemById = GameManager.Instance.GetItemById(valueOrDefault);
						return (SeedSO?)(object)((itemById is SeedSO) ? itemById : null);
					}
				}
			}
			return null;
		}

		internal static string Describe(Interactable? target)
		{
			if ((Object)(object)GameManager.Instance == (Object)null)
			{
				return "";
			}
			BlockDirt val = (BlockDirt)(object)((target is BlockDirt) ? target : null);
			if (val != null)
			{
				SeedSO val2 = Seed(val);
				if (val2 != null && (Object)(object)val2.productSO != (Object)null)
				{
					int? num = Read<int>(CropDay, val);
					if (num.HasValue)
					{
						int valueOrDefault = num.GetValueOrDefault();
						bool? flag = Read<bool>(CropWater, val);
						if (flag.HasValue)
						{
							bool valueOrDefault2 = flag == true;
							return Plant(valueOrDefault, val2.daysToFullGrowth, valueOrDefault2, val.greenhouse || InSeason(val2.productSO));
						}
					}
				}
			}
			BlockTree val3 = (BlockTree)(object)((target is BlockTree) ? target : null);
			if (val3 != null && ((NetworkBehaviour)val3).IsSpawned)
			{
				BlockSO blockSO = ((Block)val3).blockSO;
				TreeSO val4 = (TreeSO)(object)((blockSO is TreeSO) ? blockSO : null);
				if (val4 != null && (Object)(object)val4.productSO != (Object)null)
				{
					int? num = Read<int>(TreeDay, val3);
					if (num.HasValue)
					{
						int valueOrDefault3 = num.GetValueOrDefault();
						bool? flag = Read<bool>(TreeWater, val3);
						if (flag.HasValue)
						{
							bool valueOrDefault4 = flag == true;
							return Plant(valueOrDefault3, val4.daysToHarvestAfterGrowth, valueOrDefault4, InSeason(val4.productSO));
						}
					}
				}
			}
			BlockAnimal val5 = (BlockAnimal)(object)((target is BlockAnimal) ? target : null);
			if (val5 != null && ((NetworkBehaviour)val5).IsSpawned)
			{
				BlockSO blockSO2 = ((Block)val5).blockSO;
				AnimalSO val6 = (AnimalSO)(object)((blockSO2 is AnimalSO) ? blockSO2 : null);
				if (val6 != null && val5.dayCounter != null)
				{
					bool? flag = Read<bool>(AnimalFed, val5);
					if (flag.HasValue)
					{
						bool valueOrDefault5 = flag == true;
						int value = val5.dayCounter.Value;
						if (value >= val6.daysToHarvestAfterGrowth)
						{
							return Text("产物可收取", "Produce ready");
						}
						bool num2 = value >= val6.daysToGrowth;
						int num3 = (num2 ? val6.daysToGrowth : 0);
						return string.Concat(string.Concat(str1: Progress(value - num3, (num2 ? val6.daysToHarvestAfterGrowth : val6.daysToGrowth) - num3), str0: num2 ? Text("产物 ", "Produce ") : Text("成长 ", "Growth ")), " - ", valueOrDefault5 ? Text("已喂食", "Fed") : Text("未喂食", "Not fed"));
					}
				}
			}
			return "";
		}

		private static bool InSeason(ProductSO product)
		{
			if (!((Object)(object)product.season == (Object)null))
			{
				return (Object)(object)product.season == (Object)(object)GameManager.Instance.GetCurrentSeason();
			}
			return true;
		}

		private static string Plant(int day, int goal, bool watered, bool inSeason)
		{
			if (day >= goal)
			{
				return Text("已成熟", "Ready to harvest");
			}
			string text = ((!inSeason) ? Text("非生长季", "Out of season") : (watered ? Text("已浇水", "Watered") : Text("未浇水", "Not watered")));
			return Text("生长 ", "Growth ") + Progress(day, goal) + " - " + text;
		}

		private static string Progress(int day, int goal)
		{
			return $"{Mathf.Clamp(day, 0, goal)}/{goal}" + Text(" 天", " days");
		}
	}
	[BepInPlugin("local.oldmarketsimulator.itemrecipes", "ItemRecipes", "0.2.3")]
	public sealed class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		internal static ConfigEntry<Key> QueryKey;

		internal static ConfigEntry<string> PinnedRecipe;

		private void Awake()
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			QueryKey = ((BaseUnityPlugin)this).Config.Bind<Key>("Controls", "QueryKey", (Key)17, "Open recipes for the aimed-at item, or the held item if no item is targeted.");
			PinnedRecipe = ((BaseUnityPlugin)this).Config.Bind<string>("Tracking", "PinnedRecipe", "", "Recipe pinned in the HUD. Set automatically by the recipe panel.");
			new Harmony("local.oldmarketsimulator.itemrecipes").PatchAll(typeof(Plugin).Assembly);
			Log.LogInfo((object)"ItemRecipes 0.2.3 loaded.");
		}
	}
	[HarmonyPatch(typeof(UIManager))]
	internal static class InterfacePatches
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void Start(UIManager __instance)
		{
			if ((Object)(object)__instance == (Object)(object)UIManager.Instance && !Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<RecipeBrowser>()))
			{
				((Component)__instance).gameObject.AddComponent<RecipeBrowser>();
			}
		}

		[HarmonyPatch("OpenRecipesPanel")]
		[HarmonyPrefix]
		private static void OpenRecipesPanel(UIManager __instance)
		{
			((Component)__instance).GetComponent<RecipeBrowser>()?.EndQuery();
		}

		[HarmonyPatch("UpdateRecipeIngredients")]
		[HarmonyPostfix]
		private static void UpdateRecipeIngredients(UIManager __instance, RecipeSO recipeSO)
		{
			((Component)__instance).GetComponent<RecipeBrowser>()?.AddStationDetails(recipeSO);
		}

		[HarmonyPatch("CloseTopPanel")]
		[HarmonyPrefix]
		private static bool CloseTopPanel(UIManager __instance)
		{
			RecipeBrowser component = ((Component)__instance).GetComponent<RecipeBrowser>();
			if (component == null)
			{
				return true;
			}
			return !component.TryGoBack();
		}
	}
	public sealed class RecipeBrowser : MonoBehaviour
	{
		private UIManager ui;

		private RecipeCatalog? catalog;

		private ItemSO? target;

		private string growthHint = "";

		private GameObject? hint;

		private TextMeshProUGUI? hintText;

		private ControlSlot? hintKey;

		private float nextTargetCheck;

		private bool showingQuery;

		private RecipeTracker tracker;

		private bool restoredPin;

		private bool openingQuery;

		private ItemSO? currentItem;

		private RecipeSO? selectedRecipe;

		private Button? backButton;

		private readonly Stack<(ItemSO Item, RecipeSO? Recipe, float[] Scroll)> history = new Stack<(ItemSO, RecipeSO, float[])>();

		private readonly Dictionary<CanvasGroup, (float Alpha, bool Blocks, bool Interactable)> scrollbars = new Dictionary<CanvasGroup, (float, bool, bool)>();

		private readonly Dictionary<ScrollRect, (ScrollbarVisibility Mode, Vector2 Offset)> scrollLayouts = new Dictionary<ScrollRect, (ScrollbarVisibility, Vector2)>();

		private List<RecipeCatalog.Entry> matches = new List<RecipeCatalog.Entry>();

		private static bool Chinese
		{
			get
			{
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)LocalizationSettings.SelectedLocale != (Object)null)
				{
					LocaleIdentifier identifier = LocalizationSettings.SelectedLocale.Identifier;
					return ((LocaleIdentifier)(ref identifier)).Code.StartsWith("zh");
				}
				return false;
			}
		}

		internal static string Text(string zh, string en)
		{
			if (!Chinese)
			{
				return en;
			}
			return zh;
		}

		private void Awake()
		{
			ui = ((Component)this).GetComponent<UIManager>();
			tracker = new RecipeTracker(ui);
			Plugin.Log.LogInfo((object)"Native recipe browser attached to the game UI.");
		}

		private void LateUpdate()
		{
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			if (showingQuery && !ui.panelRecipes.activeInHierarchy)
			{
				EndQuery();
			}
			NetworkManager singleton = NetworkManager.Singleton;
			NetworkObject val = ((!Object.op_Implicit((Object)(object)singleton) || !singleton.IsClient) ? null : singleton.LocalClient?.PlayerObject);
			PlayerInventory val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<PlayerInventory>() : null);
			if ((Object)(object)GameManager.Instance == (Object)null || (Object)(object)val2 == (Object)null || !((NetworkBehaviour)val2).IsSpawned || !((NetworkBehaviour)val2).IsLocalPlayer || val2.slots == null || val2.slots.Count == 0 || (Object)(object)val2.playerInteraction == (Object)null)
			{
				tracker.Tick(null);
				target = null;
				growthHint = "";
				if ((Object)(object)hint != (Object)null)
				{
					hint.SetActive(false);
				}
				return;
			}
			if (!restoredPin)
			{
				restoredPin = true;
				if (!string.IsNullOrEmpty(Plugin.PinnedRecipe.Value))
				{
					if (catalog == null)
					{
						catalog = new RecipeCatalog(GameManager.Instance.itemDatabase);
					}
					tracker.Restore(catalog.FindPinned(Plugin.PinnedRecipe.Value));
				}
			}
			tracker.Tick(val2);
			if (ui.IsAnyPanelActive())
			{
				if ((Object)(object)hint != (Object)null)
				{
					hint.SetActive(false);
				}
				return;
			}
			KeyControl val3 = ((Keyboard.current != null && (int)Plugin.QueryKey.Value != 0) ? Keyboard.current[Plugin.QueryKey.Value] : null);
			bool flag = val3 != null && ((ButtonControl)val3).wasPressedThisFrame;
			if (Time.unscaledTime >= nextTargetCheck || flag)
			{
				target = FindTarget(val2, out growthHint);
				nextTargetCheck = Time.unscaledTime + 0.12f;
				UpdateHint(val2, ((val3 != null) ? ((InputControl)val3).displayName : null) ?? ((object)Plugin.QueryKey.Value/*cast due to .constrained prefix*/).ToString());
			}
			if (growthHint.Length > 0 && val2.playerInteraction.interactionUI.activeInHierarchy)
			{
				((TMP_Text)val2.playerInteraction.textSubtitle).text = growthHint;
			}
			if (flag && (Object)(object)target != (Object)null)
			{
				Open(target);
			}
		}

		private static ItemSO? FindTarget(PlayerInventory inventory, out string growth)
		{
			//IL_002b: 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_003a: 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)
			growth = "";
			Camera main = Camera.main;
			PlayerInteraction playerInteraction = inventory.playerInteraction;
			RaycastHit val = default(RaycastHit);
			if (Object.op_Implicit((Object)(object)main) && Object.op_Implicit((Object)(object)playerInteraction) && Physics.Raycast(main.ViewportPointToRay(Vector3.one / 2f), ref val, playerInteraction.interactionDistance, LayerMask.op_Implicit(playerInteraction.layerMask), (QueryTriggerInteraction)1))
			{
				Interactable componentInParent = ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<Interactable>();
				growth = GrowthInfo.Describe(componentInParent);
				Resource val2 = (Resource)(object)((componentInParent is Resource) ? componentInParent : null);
				if (val2 != null && ((Harvestable)val2).requiredTools.Count == 0 && !val2.isHarvested.Value)
				{
					return val2.outputItem;
				}
				BlockDirt val3 = (BlockDirt)(object)((componentInParent is BlockDirt) ? componentInParent : null);
				if (val3 != null)
				{
					SeedSO val4 = GrowthInfo.Seed(val3);
					if (val4 != null)
					{
						return (ItemSO?)(object)val4.productSO;
					}
				}
				BlockTree val5 = (BlockTree)(object)((componentInParent is BlockTree) ? componentInParent : null);
				if (val5 != null)
				{
					BlockSO blockSO = ((Block)val5).blockSO;
					TreeSO val6 = (TreeSO)(object)((blockSO is TreeSO) ? blockSO : null);
					if (val6 != null)
					{
						return (ItemSO?)(object)val6.productSO;
					}
				}
				Item val7 = (Item)(object)((componentInParent is Item) ? componentInParent : null);
				if (val7 != null && Object.op_Implicit((Object)(object)val7.itemSO))
				{
					return val7.itemSO;
				}
				Purchasable val8 = (Purchasable)(object)((componentInParent is Purchasable) ? componentInParent : null);
				if (val8 != null && Object.op_Implicit((Object)(object)val8.itemSO))
				{
					return val8.itemSO;
				}
				Block val9 = (Block)(object)((componentInParent is Block) ? componentInParent : null);
				if (val9 != null && Object.op_Implicit((Object)(object)val9.blockSO))
				{
					return (ItemSO?)(object)val9.blockSO;
				}
			}
			return inventory.GetCurrentItemSO();
		}

		private void UpdateHint(PlayerInventory inventory, string keyName)
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)hint == (Object)null)
			{
				hint = Object.Instantiate<GameObject>(inventory.prefabControlHintSlot, inventory.controlHintPanel.transform);
				((Object)hint).name = "ItemRecipesHint";
				hintText = hint.GetComponentInChildren<TextMeshProUGUI>();
				hintKey = Object.Instantiate<GameObject>(inventory.prefabControlHintImage, hint.transform).GetComponent<ControlSlot>();
			}
			bool flag = (int)Plugin.QueryKey.Value != 0 && Object.op_Implicit((Object)(object)target) && !ui.mobileControls.activeInHierarchy && !InputManager.Instance.isUsingGamepad;
			hint.SetActive(flag);
			if (flag)
			{
				inventory.controlHintPanel.SetActive(true);
				((TMP_Text)hintText).text = Text("配方", "Recipes");
				((TMP_Text)hintKey.textBinding).text = keyName.ToUpperInvariant();
				((Component)hintKey.textBinding).gameObject.SetActive(true);
				((Component)hintKey.imageBinding).gameObject.SetActive(false);
				((Behaviour)hintKey.imageBackground).enabled = true;
			}
		}

		private void Open(ItemSO item, RecipeSO? selection = null, float[]? positions = null)
		{
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0282: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Expected O, but got Unknown
			//IL_028f: Expected O, but got Unknown
			//IL_0399: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e0: Unknown result type (might be due to invalid IL or missing references)
			if (catalog == null)
			{
				catalog = new RecipeCatalog(GameManager.Instance.itemDatabase);
			}
			matches = catalog.Find(item);
			List<RecipeSO> list = (from r in matches.Select((RecipeCatalog.Entry e) => e.Recipe).Distinct()
				orderby (r.output.id != item.id) ? 1 : 0, r.output.GetLocalizedName()
				select r).ToList();
			TooltipSystem.Hide();
			foreach (Transform listRecipe in ui.listRecipes)
			{
				((Component)listRecipe).gameObject.SetActive(false);
			}
			openingQuery = true;
			try
			{
				ui.OpenRecipesPanel(list);
			}
			finally
			{
				openingQuery = false;
			}
			showingQuery = true;
			currentItem = item;
			selectedRecipe = null;
			int num = ui.listRecipes.childCount - list.Count;
			for (int num2 = 0; num2 < list.Count; num2++)
			{
				RecipeSO recipe = list[num2];
				ListButton component = ((Component)ui.listRecipes.GetChild(num + num2)).GetComponent<ListButton>();
				string text = ((recipe.output.id == item.id) ? Text("制作来源", "Made from") : Text("用于制作", "Used in"));
				if (matches.Any((RecipeCatalog.Entry e) => (Object)(object)e.Recipe == (Object)(object)recipe && e.Station.id == item.id))
				{
					text = Text("设备配方", "Machine recipe");
				}
				((Component)component.textSubtitle).gameObject.SetActive(true);
				component.BuildButton(recipe.output.GetLocalizedName(), text + " - " + Stations(recipe), "x" + recipe.amount, recipe.output.sprite, (Sprite)null, (UnityAction)delegate
				{
					ui.UpdateRecipeIngredients(recipe);
				}, (UnityAction)delegate
				{
					ui.UpdateRecipeIngredients(recipe);
				}, default(Color));
				((TMP_Text)component.textTitle).alignment = (TextAlignmentOptions)257;
				((TMP_Text)component.textSubtitle).textWrappingMode = (TextWrappingModes)0;
				((TMP_Text)component.textSubtitle).overflowMode = (TextOverflowModes)1;
			}
			if (list.Count > 0)
			{
				RecipeSO val = (RecipeSO)(((Object)(object)selection != (Object)null && list.Contains(selection)) ? ((object)selection) : ((object)list[0]));
				((Selectable)((Component)ui.listRecipes.GetChild(num + list.IndexOf(val))).GetComponent<ListButton>().button).Select();
				ui.UpdateRecipeIngredients(val);
			}
			else
			{
				ShowEmpty(item);
			}
			ScrollRect[] componentsInChildren = ui.panelRecipes.GetComponentsInChildren<ScrollRect>(true);
			foreach (ScrollRect val2 in componentsInChildren)
			{
				val2.verticalNormalizedPosition = 1f;
				if ((Object)(object)val2.verticalScrollbar != (Object)null && (Object)(object)val2.viewport != (Object)null && !scrollLayouts.ContainsKey(val2))
				{
					scrollLayouts.Add(val2, (val2.verticalScrollbarVisibility, val2.viewport.offsetMax));
					val2.verticalScrollbarVisibility = (ScrollbarVisibility)1;
					val2.SetLayoutHorizontal();
					val2.viewport.offsetMax = new Vector2(0f, val2.viewport.offsetMax.y);
				}
				Scrollbar[] array = (Scrollbar[])(object)new Scrollbar[2] { val2.verticalScrollbar, val2.horizontalScrollbar };
				foreach (Scrollbar val3 in array)
				{
					if (!((Object)(object)val3 == (Object)null))
					{
						CanvasGroup val4 = ((Component)val3).GetComponent<CanvasGroup>() ?? ((Component)val3).gameObject.AddComponent<CanvasGroup>();
						if (!scrollbars.ContainsKey(val4))
						{
							scrollbars.Add(val4, (val4.alpha, val4.blocksRaycasts, val4.interactable));
						}
						val4.alpha = 0f;
						bool blocksRaycasts = (val4.interactable = false);
						val4.blocksRaycasts = blocksRaycasts;
					}
				}
			}
			UpdateBackButton();
			if (positions != null)
			{
				((MonoBehaviour)this).StartCoroutine(RestoreScroll(item, positions));
			}
			Plugin.Log.LogDebug((object)$"Recipe query: item={item.itemName}, matches={list.Count}.");
		}

		private void OpenIngredient(ItemSO item)
		{
			if (!((Object)(object)currentItem == (Object)null) && !((Object)(object)currentItem == (Object)(object)item))
			{
				history.Push((currentItem, selectedRecipe, (from s in ui.panelRecipes.GetComponentsInChildren<ScrollRect>(true)
					select s.verticalNormalizedPosition).ToArray()));
				Open(item);
			}
		}

		internal bool TryGoBack()
		{
			if (!showingQuery || !ui.panelRecipes.activeInHierarchy || history.Count == 0)
			{
				return false;
			}
			if (Object.FindObjectsOfType<OverlayPanel>().Length == 0)
			{
				Panel? obj = ((IEnumerable<Panel>)ui.panels).LastOrDefault((Func<Panel, bool>)((Panel p) => p.closeInputEnabled && ((Component)p).gameObject.activeInHierarchy));
				if (!((Object)(object)((obj != null) ? ((Component)obj).gameObject : null) != (Object)(object)ui.panelRecipes))
				{
					(ItemSO, RecipeSO, float[]) tuple = history.Pop();
					Open(tuple.Item1, tuple.Item2, tuple.Item3);
					return true;
				}
			}
			return false;
		}

		private IEnumerator RestoreScroll(ItemSO item, float[] positions)
		{
			yield return null;
			if (showingQuery && !((Object)(object)currentItem != (Object)(object)item))
			{
				Canvas.ForceUpdateCanvases();
				ScrollRect[] componentsInChildren = ui.panelRecipes.GetComponentsInChildren<ScrollRect>(true);
				for (int i = 0; i < componentsInChildren.Length && i < positions.Length; i++)
				{
					componentsInChildren[i].verticalNormalizedPosition = positions[i];
				}
			}
		}

		private void UpdateBackButton()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: 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_00d5: 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_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Expected O, but got Unknown
			if ((Object)(object)backButton == (Object)null)
			{
				backButton = RecipeUi.IconButton(((Component)ui.imageRecipeOutput).transform, "PreviousQuery", null);
				RectTransform val = (RectTransform)((Component)backButton).transform;
				Vector2 val2 = default(Vector2);
				((Vector2)(ref val2))..ctor(0f, 1f);
				val.anchorMax = val2;
				val.anchorMin = val2;
				val.anchoredPosition = new Vector2(-20f, 10f);
				TextMeshProUGUI val3 = RecipeUi.CreateText(ui.textRecipeOutput, (Transform)(object)val, "Arrow", 26f);
				((TMP_Text)val3).text = "←";
				((TMP_Text)val3).alignment = (TextAlignmentOptions)514;
				((TMP_Text)val3).rectTransform.anchorMin = Vector2.zero;
				((TMP_Text)val3).rectTransform.anchorMax = Vector2.one;
				val2 = (((TMP_Text)val3).rectTransform.offsetMin = (((TMP_Text)val3).rectTransform.offsetMax = Vector2.zero));
				((UnityEvent)backButton.onClick).AddListener((UnityAction)delegate
				{
					TryGoBack();
				});
			}
			((Component)backButton).GetComponent<TooltipTrigger>().content = Text("返回", "Back");
			((Component)backButton).gameObject.SetActive(history.Count > 0);
		}

		private string Stations(RecipeSO recipe)
		{
			return string.Join(", ", (from e in matches
				where (Object)(object)e.Recipe == (Object)(object)recipe
				select e.Station.GetLocalizedName()).Distinct());
		}

		internal void AddStationDetails(RecipeSO recipe)
		{
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Expected O, but got Unknown
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			if (!showingQuery)
			{
				return;
			}
			selectedRecipe = recipe;
			tracker.BeginDetails(recipe);
			int num = ui.listRecipeIngredients.childCount - recipe.ingredients.Count;
			for (int i = 0; i < recipe.ingredients.Count; i++)
			{
				ItemSO item = recipe.ingredients[i].itemSO;
				GameObject gameObject = ((Component)ui.listRecipeIngredients.GetChild(num + i)).gameObject;
				Button obj = gameObject.GetComponent<Button>() ?? gameObject.AddComponent<Button>();
				Image val = gameObject.GetComponent<Image>();
				if ((Object)(object)val == (Object)null)
				{
					val = gameObject.AddComponent<Image>();
					((Graphic)val).color = Color.clear;
				}
				((Graphic)val).raycastTarget = true;
				((Selectable)obj).targetGraphic = (Graphic)(object)val;
				((UnityEvent)obj.onClick).AddListener((UnityAction)delegate
				{
					OpenIngredient(item);
				});
				(gameObject.GetComponent<TooltipTrigger>() ?? gameObject.AddComponent<TooltipTrigger>()).content = Text("查看配方:", "Recipes: ") + item.GetLocalizedName();
			}
			foreach (ItemSO item2 in (from e in matches
				where (Object)(object)e.Recipe == (Object)(object)recipe
				select e.Station).Distinct())
			{
				Object.Instantiate<GameObject>(ui.prefabIngredientTile, ui.listRecipeIngredients).GetComponent<IngredientTile>().BuildTile(item2.sprite, Text("制作设备:", "Station: ") + item2.GetLocalizedName(), "");
			}
			if (recipe.requiredDays > 0)
			{
				IngredientTile component = Object.Instantiate<GameObject>(ui.prefabIngredientTile, ui.listRecipeIngredients).GetComponent<IngredientTile>();
				component.BuildTile(recipe.output.sprite, Text("制作时间", "Production time"), recipe.requiredDays + Text(" 天", " days"));
				RecipeUi.FitAmount(component);
			}
			tracker.FinishDetails(recipe);
		}

		private void ShowEmpty(ItemSO item)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			ui.imageRecipeOutput.sprite = item.sprite;
			((TMP_Text)ui.textRecipeOutput).text = item.GetLocalizedName();
			foreach (Transform listRecipeIngredient in ui.listRecipeIngredients)
			{
				Object.Destroy((Object)(object)((Component)listRecipeIngredient).gameObject);
			}
			ListButton component = Object.Instantiate<GameObject>(ui.prefabRecipeTile, ui.listRecipes).GetComponent<ListButton>();
			component.BuildButton(Text("暂无制作配方", "No crafting recipes"), Text("此物品未出现在设备配方中", "This item is not in the machine recipes"), "", item.sprite, (Sprite)null, (UnityAction)null, (UnityAction)null, default(Color));
			((Selectable)component.button).interactable = false;
		}

		internal void EndQuery()
		{
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			showingQuery = false;
			tracker?.EndDetails();
			if ((Object)(object)backButton != (Object)null)
			{
				((Component)backButton).gameObject.SetActive(false);
			}
			if (openingQuery)
			{
				return;
			}
			history.Clear();
			currentItem = null;
			selectedRecipe = null;
			foreach (KeyValuePair<CanvasGroup, (float, bool, bool)> scrollbar in scrollbars)
			{
				if (!((Object)(object)scrollbar.Key == (Object)null))
				{
					scrollbar.Key.alpha = scrollbar.Value.Item1;
					scrollbar.Key.blocksRaycasts = scrollbar.Value.Item2;
					scrollbar.Key.interactable = scrollbar.Value.Item3;
				}
			}
			scrollbars.Clear();
			foreach (KeyValuePair<ScrollRect, (ScrollbarVisibility, Vector2)> scrollLayout in scrollLayouts)
			{
				if (!((Object)(object)scrollLayout.Key == (Object)null) && !((Object)(object)scrollLayout.Key.viewport == (Object)null))
				{
					scrollLayout.Key.verticalScrollbarVisibility = scrollLayout.Value.Item1;
					scrollLayout.Key.viewport.offsetMax = scrollLayout.Value.Item2;
				}
			}
			scrollLayouts.Clear();
		}

		private void OnDestroy()
		{
			EndQuery();
			if (Object.op_Implicit((Object)(object)hint))
			{
				Object.Destroy((Object)(object)hint);
			}
			if ((Object)(object)backButton != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)backButton).gameObject);
			}
			tracker?.Dispose();
		}
	}
	internal sealed class RecipeCatalog
	{
		internal sealed class Entry
		{
			internal readonly RecipeSO Recipe;

			internal readonly ItemSO Station;

			internal Entry(RecipeSO recipe, ItemSO station)
			{
				Recipe = recipe;
				Station = station;
			}
		}

		private readonly List<Entry> entries = new List<Entry>();

		internal RecipeCatalog(IEnumerable<ItemSO> items)
		{
			foreach (BlockSO station in items.OfType<BlockSO>())
			{
				if (!Object.op_Implicit((Object)(object)((ItemSO)station).prefab))
				{
					continue;
				}
				Block[] componentsInChildren = ((ItemSO)station).prefab.GetComponentsInChildren<Block>(true);
				foreach (Block val in componentsInChildren)
				{
					if (!(((object)val).GetType().GetField("recipes")?.GetValue(val) is List<RecipeSO> list))
					{
						continue;
					}
					foreach (RecipeSO recipe in list)
					{
						if (Object.op_Implicit((Object)(object)recipe) && Object.op_Implicit((Object)(object)recipe.output) && recipe.amount > 0 && recipe.ingredients != null && recipe.ingredients.All((Ingredient val2) => val2 != null && Object.op_Implicit((Object)(object)val2.itemSO) && val2.amount > 0) && !entries.Any((Entry e) => (Object)(object)e.Recipe == (Object)(object)recipe && e.Station.id == ((ItemSO)station).id))
						{
							entries.Add(new Entry(recipe, (ItemSO)(object)station));
						}
					}
				}
			}
			Plugin.Log.LogInfo((object)$"Recipe catalog: {entries.Select((Entry e) => e.Recipe).Distinct().Count()} recipes, {entries.Select((Entry e) => e.Station.id).Distinct().Count()} machines.");
		}

		internal List<Entry> Find(ItemSO item)
		{
			return entries.Where((Entry e) => e.Recipe.output.id == item.id || e.Station.id == item.id || e.Recipe.ingredients.Any((Ingredient i) => Object.op_Implicit((Object)(object)i.itemSO) && i.itemSO.id == item.id)).ToList();
		}

		internal static string Key(RecipeSO recipe)
		{
			return ((Object)recipe).name + ":" + recipe.output.id;
		}

		internal RecipeSO? FindPinned(string key)
		{
			return entries.FirstOrDefault((Entry e) => Key(e.Recipe) == key)?.Recipe;
		}
	}
	internal static class RecipeMath
	{
		internal static long CompleteItems(int amount, int packageSize, int stackSize, bool expired)
		{
			if (expired || amount <= 0 || packageSize <= 0)
			{
				return 0L;
			}
			if (stackSize > 1)
			{
				return (packageSize == 1) ? amount : 0;
			}
			return (amount == packageSize) ? 1 : 0;
		}

		internal static long Craftable(IEnumerable<(long Item, int Needed)> ingredients, IReadOnlyDictionary<long, long> owned, int outputAmount)
		{
			if (outputAmount <= 0)
			{
				return 0L;
			}
			List<(long, int)> list = ingredients.ToList();
			if (list.Count == 0 || list.Any<(long, int)>(((long Item, int Needed) i) => i.Needed <= 0))
			{
				return 0L;
			}
			long num = long.MaxValue;
			foreach (IGrouping<long, (long, int)> item in from i in list
				group i by i.Item)
			{
				owned.TryGetValue(item.Key, out var value);
				num = Math.Min(num, Math.Max(0L, value) / ((IEnumerable<(long, int)>)item).Sum((Func<(long, int), long>)(((long Item, int Needed) i) => i.Needed)));
			}
			if (num <= long.MaxValue / outputAmount)
			{
				return num * outputAmount;
			}
			return long.MaxValue;
		}
	}
	internal sealed class RecipeTracker
	{
		private readonly UIManager ui;

		private readonly Dictionary<long, long> owned = new Dictionary<long, long>();

		private readonly List<(IngredientTile Tile, Ingredient Ingredient)> details = new List<(IngredientTile, Ingredient)>();

		private readonly List<(IngredientTile Tile, Ingredient Ingredient)> hudRows = new List<(IngredientTile, Ingredient)>();

		private RecipeSO? selected;

		private RecipeSO? pinned;

		private TextMeshProUGUI? summary;

		private Button? pinButton;

		private RectTransform? hud;

		private IngredientTile? hudOutput;

		private PlayerInventory? inventory;

		private float nextRefresh;

		internal RecipeTracker(UIManager ui)
		{
			this.ui = ui;
		}

		private static string Text(string zh, string en)
		{
			return RecipeBrowser.Text(zh, en);
		}

		internal void Restore(RecipeSO? recipe)
		{
			pinned = recipe;
			if ((Object)(object)pinned != (Object)null)
			{
				BuildHud();
			}
		}

		internal void BeginDetails(RecipeSO recipe)
		{
			EndDetails();
			selected = recipe;
			int num = ui.listRecipeIngredients.childCount - recipe.ingredients.Count;
			for (int i = 0; i < recipe.ingredients.Count; i++)
			{
				IngredientTile component = ((Component)ui.listRecipeIngredients.GetChild(num + i)).GetComponent<IngredientTile>();
				RecipeUi.FitAmount(component);
				details.Add((component, recipe.ingredients[i]));
			}
		}

		internal void FinishDetails(RecipeSO recipe)
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: 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_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Expected O, but got Unknown
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: 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_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: 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_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: 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_0276: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)summary == (Object)null)
			{
				summary = RecipeUi.CreateText(ui.textRecipeOutput, ((TMP_Text)ui.textRecipeOutput).transform, "CraftableCount", ((TMP_Text)ui.textRecipeOutput).fontSize * 0.65f);
				RectTransform rectTransform = ((TMP_Text)summary).rectTransform;
				rectTransform.anchorMin = new Vector2(0f, 0f);
				rectTransform.anchorMax = new Vector2(1f, 0f);
				rectTransform.pivot = new Vector2(0.5f, 1f);
				rectTransform.sizeDelta = new Vector2(0f, 24f);
				rectTransform.anchoredPosition = new Vector2(0f, -2f);
				((TMP_Text)summary).alignment = (TextAlignmentOptions)258;
			}
			if ((Object)(object)pinButton == (Object)null)
			{
				pinButton = RecipeUi.IconButton(((Component)ui.imageRecipeOutput).transform, "PinRecipe", ui.spriteTask);
				RectTransform val = (RectTransform)((Component)pinButton).transform;
				Vector2 val2 = default(Vector2);
				((Vector2)(ref val2))..ctor(1f, 1f);
				val.anchorMax = val2;
				val.anchorMin = val2;
				val.anchoredPosition = new Vector2(20f, 10f);
			}
			((Component)summary).gameObject.SetActive(true);
			((Component)pinButton).gameObject.SetActive(true);
			((UnityEventBase)pinButton.onClick).RemoveAllListeners();
			((UnityEvent)pinButton.onClick).AddListener((UnityAction)delegate
			{
				Toggle(recipe);
			});
			Refresh();
			List<ListButton> list = (from b in ((Component)ui.listRecipes).GetComponentsInChildren<ListButton>()
				where ((Component)b).gameObject.activeInHierarchy
				select b).ToList();
			foreach (ListButton item in list)
			{
				Navigation navigation = ((Selectable)item.button).navigation;
				((Navigation)(ref navigation)).selectOnRight = (Selectable)(object)pinButton;
				((Selectable)item.button).navigation = navigation;
			}
			Navigation navigation2 = ((Selectable)pinButton).navigation;
			((Navigation)(ref navigation2)).mode = (Mode)4;
			((Navigation)(ref navigation2)).selectOnLeft = (Selectable)(object)list.FirstOrDefault()?.button;
			((Selectable)pinButton).navigation = navigation2;
		}

		internal void EndDetails()
		{
			selected = null;
			details.Clear();
			if ((Object)(object)summary != (Object)null)
			{
				((Component)summary).gameObject.SetActive(false);
			}
			if ((Object)(object)pinButton != (Object)null)
			{
				((Component)pinButton).gameObject.SetActive(false);
			}
		}

		internal void Tick(PlayerInventory? playerInventory)
		{
			inventory = playerInventory;
			bool flag = (Object)(object)inventory != (Object)null && ((NetworkBehaviour)inventory).IsSpawned && ((NetworkBehaviour)inventory).IsLocalPlayer;
			if ((Object)(object)hud != (Object)null)
			{
				((Component)hud).gameObject.SetActive(flag && !ui.IsAnyPanelActive());
			}
			if (flag && !((Object)(object)GameManager.Instance == (Object)null) && !(Time.unscaledTime < nextRefresh))
			{
				nextRefresh = Time.unscaledTime + 0.2f;
				if ((Object)(object)pinned != (Object)null || (Object)(object)selected != (Object)null)
				{
					Refresh();
				}
			}
		}

		private void ReadInventory()
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: 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_00b4: Unknown result type (might be due to invalid IL or missing references)
			owned.Clear();
			if ((Object)(object)GameManager.Instance == (Object)null || (Object)(object)inventory == (Object)null || !((NetworkBehaviour)inventory).IsSpawned || !((NetworkBehaviour)inventory).IsLocalPlayer || inventory.slots == null)
			{
				return;
			}
			foreach (InventorySlot slot in inventory.slots)
			{
				if (slot.itemId != -1 && slot.amount > 0)
				{
					ItemSO itemById = GameManager.Instance.GetItemById(slot.itemId);
					if (!((Object)(object)itemById == (Object)null))
					{
						ProductSO val = (ProductSO)(object)((itemById is ProductSO) ? itemById : null);
						bool expired = val != null && val.maxDays > 0 && slot.dayCounter >= val.maxDays;
						long num = RecipeMath.CompleteItems(slot.amount, itemById.amount, itemById.stackSize, expired);
						owned.TryGetValue(itemById.id, out var value);
						owned[itemById.id] = value + num;
					}
				}
			}
		}

		private long Craftable(RecipeSO recipe)
		{
			return RecipeMath.Craftable(recipe.ingredients.Select((Ingredient i) => (id: i.itemSO.id, amount: i.amount)), owned, recipe.amount);
		}

		private void Refresh()
		{
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			ReadInventory();
			UpdateRows(details);
			UpdateRows(hudRows);
			if ((Object)(object)selected != (Object)null && (Object)(object)summary != (Object)null)
			{
				((TMP_Text)summary).text = Text("可制作 x", "Can make x") + Craftable(selected);
				if ((Object)(object)pinButton != (Object)null)
				{
					((Component)pinButton).GetComponent<TooltipTrigger>().content = (((Object)(object)selected == (Object)(object)pinned) ? Text("取消固定", "Unpin recipe") : Text("固定配方", "Pin recipe"));
					((Graphic)((Component)pinButton).GetComponent<Image>()).color = (Color)(((Object)(object)selected == (Object)(object)pinned) ? Color.white : new Color(0.65f, 0.55f, 0.42f, 0.8f));
				}
			}
			if ((Object)(object)pinned != (Object)null && (Object)(object)hudOutput != (Object)null)
			{
				hudOutput.BuildTile(pinned.output.sprite, pinned.output.GetLocalizedName(), Text("可制作 x", "Can make x") + Craftable(pinned));
				PositionHud();
			}
		}

		private void UpdateRows(List<(IngredientTile Tile, Ingredient Ingredient)> rows)
		{
			//IL_00c2: 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)
			foreach (var (val, val2) in rows)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val2.itemSO == (Object)null))
				{
					owned.TryGetValue(val2.itemSO.id, out var value);
					val.BuildTile(val2.itemSO.sprite, val2.itemSO.GetLocalizedName(), $"{value} / {val2.amount}");
					((Graphic)val.textTrailing).color = ((value >= val2.amount) ? new Color(0.25f, 0.72f, 0.43f) : new Color(0.95f, 0.44f, 0.36f));
				}
			}
		}

		private void Toggle(RecipeSO recipe)
		{
			pinned = (((Object)(object)pinned == (Object)(object)recipe) ? null : recipe);
			Plugin.PinnedRecipe.Value = (((Object)(object)pinned != (Object)null) ? RecipeCatalog.Key(pinned) : "");
			BuildHud();
			Refresh();
			Plugin.Log.LogDebug((object)(((Object)(object)pinned != (Object)null) ? ("Pinned recipe: " + ((Object)recipe).name + ".") : "Recipe unpinned."));
		}

		private void BuildHud()
		{
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Expected O, but got Unknown
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Expected O, but got Unknown
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: 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_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: 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_01d2: Expected O, but got Unknown
			if ((Object)(object)hud != (Object)null)
			{
				((Component)hud).gameObject.SetActive(false);
				Object.Destroy((Object)(object)((Component)hud).gameObject);
			}
			hudRows.Clear();
			hud = null;
			if ((Object)(object)pinned == (Object)null)
			{
				return;
			}
			GameObject val = new GameObject("ItemRecipesTracker", new Type[4]
			{
				typeof(RectTransform),
				typeof(VerticalLayoutGroup),
				typeof(ContentSizeFitter),
				typeof(CanvasGroup)
			});
			hud = (RectTransform)val.transform;
			((Transform)hud).SetParent(((Component)ui.canvasScaler).transform, false);
			RectTransform? obj = hud;
			RectTransform? obj2 = hud;
			Vector2 val2 = (hud.pivot = Vector2.one);
			Vector2 anchorMin = (obj2.anchorMax = val2);
			obj.anchorMin = anchorMin;
			val.GetComponent<CanvasGroup>().blocksRaycasts = false;
			val.GetComponent<CanvasGroup>().interactable = false;
			VerticalLayoutGroup component = val.GetComponent<VerticalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)component).spacing = 4f;
			bool childControlWidth = (((HorizontalOrVerticalLayoutGroup)component).childControlHeight = true);
			((HorizontalOrVerticalLayoutGroup)component).childControlWidth = childControlWidth;
			((HorizontalOrVerticalLayoutGroup)component).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)component).childForceExpandHeight = false;
			val.GetComponent<ContentSizeFitter>().verticalFit = (FitMode)2;
			hudOutput = AddHudRow();
			foreach (IGrouping<long, Ingredient> item2 in from i in pinned.ingredients
				group i by i.itemSO.id)
			{
				Ingredient item = new Ingredient
				{
					itemSO = item2.First().itemSO,
					amount = item2.Sum((Ingredient i) => i.amount)
				};
				hudRows.Add((AddHudRow(), item));
			}
			val.SetActive(false);
		}

		private IngredientTile AddHudRow()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Expected O, but got Unknown
			GameObject val = new GameObject("TrackedIngredient", new Type[3]
			{
				typeof(RectTransform),
				typeof(LayoutElement),
				typeof(IngredientTile)
			});
			val.transform.SetParent((Transform)(object)hud, false);
			SetHeight(val, 42f);
			IngredientTile component = val.GetComponent<IngredientTile>();
			GameObject val2 = new GameObject("Icon", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val2.transform.SetParent(val.transform, false);
			component.imageIcon = val2.GetComponent<Image>();
			((Graphic)component.imageIcon).raycastTarget = false;
			component.textTitle = RecipeUi.CreateText(ui.textCoins, val.transform, "Name", 20f);
			component.textTrailing = RecipeUi.CreateText(ui.textCoins, val.transform, "Count", 20f);
			ConfigureHudColumns(component, 132f);
			return component;
		}

		private static void ConfigureHudColumns(IngredientTile row, float numberWidth)
		{
			//IL_001f: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: 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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			RectTransform rectTransform = ((Graphic)row.imageIcon).rectTransform;
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(0f, 0.5f);
			rectTransform.pivot = val;
			Vector2 anchorMin = (rectTransform.anchorMax = val);
			rectTransform.anchorMin = anchorMin;
			rectTransform.anchoredPosition = Vector2.zero;
			rectTransform.sizeDelta = new Vector2(34f, 34f);
			row.imageIcon.preserveAspect = true;
			RectTransform rectTransform2 = ((TMP_Text)row.textTitle).rectTransform;
			rectTransform2.anchorMin = Vector2.zero;
			rectTransform2.anchorMax = Vector2.one;
			rectTransform2.offsetMin = new Vector2(44f, 0f);
			rectTransform2.offsetMax = new Vector2(0f - numberWidth - 8f, 0f);
			RectTransform rectTransform3 = ((TMP_Text)row.textTrailing).rectTransform;
			rectTransform3.anchorMin = new Vector2(1f, 0f);
			rectTransform3.anchorMax = Vector2.one;
			rectTransform3.offsetMin = new Vector2(0f - numberWidth, 0f);
			rectTransform3.offsetMax = Vector2.zero;
			((TMP_Text)row.textTitle).alignment = (TextAlignmentOptions)4097;
			((TMP_Text)row.textTrailing).alignment = (TextAlignmentOptions)4100;
		}

		private static void SetHeight(GameObject obj, float height)
		{
			LayoutElement obj2 = obj.GetComponent<LayoutElement>() ?? obj.AddComponent<LayoutElement>();
			float minHeight = (obj2.preferredHeight = height);
			obj2.minHeight = minHeight;
			obj2.flexibleHeight = 0f;
		}

		private void PositionHud()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: 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_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_00f6: 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_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: 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)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)hud == (Object)null)
			{
				return;
			}
			RectTransform val = (RectTransform)((Component)ui.canvasScaler).transform;
			Rect rect = val.rect;
			float num = Mathf.Clamp(((Rect)(ref rect)).width * 0.26f, 280f, 380f);
			float num2 = 80f;
			GameObject[] array = (GameObject[])(object)new GameObject[4] { ui.panelStats, ui.panelTutorial, ui.panelNotifications, ui.taskLogHint };
			foreach (GameObject val2 in array)
			{
				if ((Object)(object)val2 == (Object)null || !val2.activeInHierarchy)
				{
					continue;
				}
				Transform transform = val2.transform;
				RectTransform val3 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
				if (val3 == null)
				{
					continue;
				}
				Vector3[] array2 = (Vector3[])(object)new Vector3[4];
				val3.GetWorldCorners(array2);
				Vector3 val4 = ((Transform)val).InverseTransformPoint(array2[0]);
				Vector3 val5 = ((Transform)val).InverseTransformPoint(array2[2]);
				float num3 = val5.y - val4.y;
				rect = val.rect;
				if (!(num3 < ((Rect)(ref rect)).height * 0.4f))
				{
					continue;
				}
				float x = val5.x;
				rect = val.rect;
				if (x > ((Rect)(ref rect)).xMax - num - 24f)
				{
					float y = val4.y;
					rect = val.rect;
					if (y > ((Rect)(ref rect)).center.y)
					{
						float num4 = num2;
						rect = val.rect;
						num2 = Mathf.Max(num4, ((Rect)(ref rect)).yMax - val4.y + 16f);
					}
				}
			}
			hud.SetSizeWithCurrentAnchors((Axis)0, num);
			hud.anchoredPosition = new Vector2(-24f, 0f - num2);
		}

		internal void Dispose()
		{
			if ((Object)(object)hud != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)hud).gameObject);
			}
			if ((Object)(object)summary != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)summary).gameObject);
			}
			if ((Object)(object)pinButton != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)pinButton).gameObject);
			}
		}
	}
	internal static class RecipeUi
	{
		internal static void FitAmount(IngredientTile row)
		{
			//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_007b: 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_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			TextMeshProUGUI textTrailing = row.textTrailing;
			((TMP_Text)textTrailing).textWrappingMode = (TextWrappingModes)0;
			((TMP_Text)textTrailing).enableAutoSizing = true;
			((TMP_Text)textTrailing).fontSizeMax = ((TMP_Text)textTrailing).fontSize;
			((TMP_Text)textTrailing).fontSizeMin = ((TMP_Text)textTrailing).fontSize * 0.75f;
			((TMP_Text)textTrailing).alignment = (TextAlignmentOptions)4100;
			RectTransform rectTransform = ((TMP_Text)textTrailing).rectTransform;
			Rect rect = rectTransform.rect;
			float num = 112f - ((Rect)(ref rect)).width;
			rectTransform.SetSizeWithCurrentAnchors((Axis)0, 112f);
			if ((Object)(object)((Component)((Transform)rectTransform).parent).GetComponent<LayoutGroup>() == (Object)null)
			{
				rectTransform.anchoredPosition -= new Vector2(num * (1f - rectTransform.pivot.x), 0f);
			}
			LayoutElement obj = ((Component)textTrailing).GetComponent<LayoutElement>() ?? ((Component)textTrailing).gameObject.AddComponent<LayoutElement>();
			float minWidth = (obj.preferredWidth = 112f);
			obj.minWidth = minWidth;
			obj.flexibleWidth = 0f;
		}

		internal static TextMeshProUGUI CreateText(TextMeshProUGUI source, Transform parent, string name, float size)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[2]
			{
				typeof(RectTransform),
				typeof(TextMeshProUGUI)
			});
			val.transform.SetParent(parent, false);
			TextMeshProUGUI component = val.GetComponent<TextMeshProUGUI>();
			((TMP_Text)component).font = ((TMP_Text)source).font;
			((TMP_Text)component).fontSharedMaterial = ((TMP_Text)source).fontSharedMaterial;
			((Graphic)component).color = ((Graphic)source).color;
			((TMP_Text)component).fontSize = size;
			((TMP_Text)component).fontStyle = ((TMP_Text)source).fontStyle;
			((Graphic)component).raycastTarget = false;
			((TMP_Text)component).textWrappingMode = (TextWrappingModes)0;
			((TMP_Text)component).overflowMode = (TextOverflowModes)1;
			return component;
		}

		internal static Button IconButton(Transform parent, string name, Sprite? sprite)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[4]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Button),
				typeof(TooltipTrigger)
			});
			val.transform.SetParent(parent, false);
			((RectTransform)val.transform).sizeDelta = new Vector2(32f, 32f);
			Image component = val.GetComponent<Image>();
			component.sprite = sprite;
			component.preserveAspect = true;
			if ((Object)(object)sprite == (Object)null)
			{
				((Graphic)component).color = Color.clear;
			}
			Button component2 = val.GetComponent<Button>();
			((Selectable)component2).targetGraphic = (Graphic)(object)component;
			return component2;
		}
	}
}