Decompiled source of ItemBrowser v0.2.0

plugins/com.github.cherrycove.ItemBrowser.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using PEAKLib.UI;
using PEAKLib.UI.Elements;
using Photon.Pun;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using Zorro.Core;
using Zorro.Settings;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("com.github.cherrycove.ItemBrowser")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.0.0")]
[assembly: AssemblyInformationalVersion("0.2.0+35bab4b041febc053ae11334991a0989d68e84af")]
[assembly: AssemblyProduct("com.github.cherrycove.ItemBrowser")]
[assembly: AssemblyTitle("ItemBrowser")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.2.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace ItemBrowser
{
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("com.github.cherrycove.ItemBrowser", "ItemBrowser", "0.2.0")]
	public class Plugin : BaseUnityPlugin
	{
		private enum MajorCategory
		{
			All,
			Food,
			Weapon
		}

		private enum ItemCategory
		{
			NaturalFood,
			MysticalFood,
			PackagedFood,
			Mushroom,
			Consumable,
			Deployable,
			MiscEquipment,
			MysticalItem
		}

		private sealed class ItemEntry
		{
			public Item Prefab { get; }

			public string PrefabName { get; }

			public string DisplayName { get; private set; } = string.Empty;


			public ItemCategory Category { get; }

			public Sprite? Icon { get; }

			public string SearchText { get; private set; } = string.Empty;


			public ItemEntry(Item prefab, string displayName, ItemCategory category, Sprite? icon)
			{
				Prefab = prefab;
				PrefabName = ((Object)prefab).name ?? string.Empty;
				Category = category;
				Icon = icon;
				UpdateDisplayName(displayName);
			}

			public void UpdateDisplayName(string displayName)
			{
				string text2 = (DisplayName = (string.IsNullOrWhiteSpace(displayName) ? PrefabName : displayName.Trim()));
				SearchText = (text2 + " " + PrefabName).ToLowerInvariant();
			}
		}

		private sealed class CategoryTab
		{
			public ItemCategory? Category { get; }

			public GameObject Root { get; }

			public Button Button { get; }

			public Image Background { get; }

			public Image Selected { get; }

			public PeakText Label { get; }

			public CategoryTab(ItemCategory? category, GameObject root, Button button, Image background, Image selected, PeakText label)
			{
				Category = category;
				Root = root;
				Button = button;
				Background = background;
				Selected = selected;
				Label = label;
			}
		}

		private sealed class MajorCategoryTab
		{
			public MajorCategory Category { get; }

			public GameObject Root { get; }

			public Button Button { get; }

			public Image Background { get; }

			public Image Selected { get; }

			public PeakText Label { get; }

			public MajorCategoryTab(MajorCategory category, GameObject root, Button button, Image background, Image selected, PeakText label)
			{
				Category = category;
				Root = root;
				Button = button;
				Background = background;
				Selected = selected;
				Label = label;
			}
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__ClosePage;

			public static UnityAction<string> <1>__OnSearchChanged;

			public static Func<char, bool> <2>__IsLetterOrDigit;
		}

		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static Func<GameObject, bool> <>9__66_0;

			public static Func<GameObject, bool> <>9__66_1;

			public static UnityAction <>9__74_0;

			public static UnityAction <>9__74_1;

			public static Func<ItemEntry, bool> <>9__81_1;

			public static Func<ItemEntry, bool> <>9__81_2;

			public static Func<ItemEntry, string> <>9__81_3;

			public static Func<ItemEntry, ItemCategory> <>9__93_0;

			public static Func<IGrouping<ItemCategory, ItemEntry>, int> <>9__93_1;

			public static Func<IGrouping<ItemCategory, ItemEntry>, string> <>9__93_2;

			public static Func<string, bool> <>9__120_0;

			public static Func<MethodInfo, bool> <>9__154_0;

			public static Func<MethodInfo, bool> <>9__154_1;

			public static Func<string, bool> <>9__167_0;

			internal bool <TryRecoverButtonTemplate>b__66_0(GameObject obj)
			{
				if ((Object)(object)obj != (Object)null)
				{
					return ((Object)obj).name == "UI_MainMenuButton_LeaveGame (2)";
				}
				return false;
			}

			internal bool <TryRecoverButtonTemplate>b__66_1(GameObject obj)
			{
				if ((Object)(object)obj != (Object)null)
				{
					return ((Object)obj).name.StartsWith("UI_MainMenuButton_LeaveGame", StringComparison.Ordinal);
				}
				return false;
			}

			internal void <BuildUI>b__74_0()
			{
				pageOpen = true;
				RefreshLanguageDependentContent(force: true);
				EnsureItemList();
				RefreshList();
			}

			internal void <BuildUI>b__74_1()
			{
				pageOpen = false;
			}

			internal bool <RefreshList>b__81_1(ItemEntry entry)
			{
				return IsEntryInMajorCategory(entry, currentMajorFilter);
			}

			internal bool <RefreshList>b__81_2(ItemEntry entry)
			{
				return entry.Category == currentSubCategoryFilter.Value;
			}

			internal string <RefreshList>b__81_3(ItemEntry entry)
			{
				return entry.DisplayName;
			}

			internal ItemCategory <BuildItemListGradually>b__93_0(ItemEntry entry)
			{
				return entry.Category;
			}

			internal int <BuildItemListGradually>b__93_1(IGrouping<ItemCategory, ItemEntry> group)
			{
				return GetCategoryOrder(group.Key);
			}

			internal string <BuildItemListGradually>b__93_2(IGrouping<ItemCategory, ItemEntry> group)
			{
				return $"{GetCategoryLabel(group.Key)}={group.Count()}";
			}

			internal bool <TryGetCategoryOverride>b__120_0(string x)
			{
				return !string.IsNullOrWhiteSpace(x);
			}

			internal bool <ClosePage>b__154_0(MethodInfo m)
			{
				if (m.Name == "Close")
				{
					return m.GetParameters().Length == 0;
				}
				return false;
			}

			internal bool <ClosePage>b__154_1(MethodInfo m)
			{
				if (m.Name == "Close")
				{
					return m.GetParameters().Length == 1;
				}
				return false;
			}

			internal bool <LoadLocalizedText>b__167_0(string x)
			{
				return !string.IsNullOrWhiteSpace(x);
			}
		}

		[CompilerGenerated]
		private sealed class <BuildItemListGradually>d__93 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public ItemDatabase db;

			private int <budget>5__2;

			private List<Item>.Enumerator <>7__wrap2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <BuildItemListGradually>d__93(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || num == 1)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<>7__wrap2 = default(List<Item>.Enumerator);
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				try
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<budget>5__2 = 6;
						<>7__wrap2 = ((DatabaseAsset<ItemDatabase, Item>)(object)db).Objects.GetEnumerator();
						<>1__state = -3;
						break;
					case 1:
						<>1__state = -3;
						break;
					}
					while (<>7__wrap2.MoveNext())
					{
						Item current = <>7__wrap2.Current;
						itemPreloadProcessedCount++;
						try
						{
							if ((Object)(object)current != (Object)null)
							{
								string localizedItemName = GetLocalizedItemName(current);
								string displayName = (string.IsNullOrWhiteSpace(localizedItemName) ? ((Object)current).name : localizedItemName);
								displayName = GetDisplayNameOverride(current, displayName);
								if (!ShouldHideItemFromBrowser(current, displayName))
								{
									ItemCategory category = GetCategory(current, displayName);
									Sprite itemIcon = GetItemIcon(current);
									itemEntries.Add(new ItemEntry(current, displayName, category, itemIcon));
									itemPreloadAddedCount++;
								}
								else
								{
									VerboseLog("Item hidden: prefab='" + ((Object)current).name + "', display='" + displayName + "'");
								}
							}
						}
						catch (Exception ex)
						{
							Log.LogWarning((object)("[ItemBrowser] Preload item failed: " + ((current != null) ? ((Object)current).name : null) + " (" + ex.GetType().Name + " " + ex.Message + ")"));
						}
						<budget>5__2--;
						if (<budget>5__2 <= 0)
						{
							<budget>5__2 = 6;
							if (pageOpen)
							{
								RefreshList();
							}
							<>2__current = null;
							<>1__state = 1;
							return true;
						}
					}
					<>m__Finally1();
					<>7__wrap2 = default(List<Item>.Enumerator);
					itemPreloadRunning = false;
					itemPreloadCoroutine = null;
					itemListInitialized = true;
					RefreshItemDisplayNamesForCurrentLanguage();
					if (configVerboseLogs != null && configVerboseLogs.Value)
					{
						IEnumerable<string> values = from entry in itemEntries
							group entry by entry.Category into @group
							orderby GetCategoryOrder(@group.Key)
							select $"{GetCategoryLabel(@group.Key)}={@group.Count()}";
						Log.LogInfo((object)string.Format("[ItemBrowser] Item list built in background. Total={0}, Added={1}, Categories: {2}", itemEntries.Count, itemPreloadAddedCount, string.Join(", ", values)));
					}
					if (pageOpen)
					{
						RefreshList();
					}
					return false;
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				((IDisposable)<>7__wrap2).Dispose();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <GetCategoryCandidateKeys>d__123 : IEnumerable<string>, IEnumerable, IEnumerator<string>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private string <>2__current;

			private int <>l__initialThreadId;

			private Item item;

			public Item <>3__item;

			private string displayName;

			public string <>3__displayName;

			private string <prefabName>5__2;

			string IEnumerator<string>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <GetCategoryCandidateKeys>d__123(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<prefabName>5__2 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<prefabName>5__2 = ((Object)item).name ?? string.Empty;
					if (!string.IsNullOrWhiteSpace(<prefabName>5__2))
					{
						<>2__current = NormalizeCategoryKey(<prefabName>5__2);
						<>1__state = 1;
						return true;
					}
					goto IL_00ac;
				case 1:
				{
					<>1__state = -1;
					int num = <prefabName>5__2.IndexOf(" Variant", StringComparison.OrdinalIgnoreCase);
					if (num > 0)
					{
						<>2__current = NormalizeCategoryKey(<prefabName>5__2.Substring(0, num));
						<>1__state = 2;
						return true;
					}
					goto IL_00ac;
				}
				case 2:
					<>1__state = -1;
					goto IL_00ac;
				case 3:
					{
						<>1__state = -1;
						break;
					}
					IL_00ac:
					if (!string.IsNullOrWhiteSpace(displayName))
					{
						<>2__current = NormalizeCategoryKey(displayName);
						<>1__state = 3;
						return true;
					}
					break;
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<string> IEnumerable<string>.GetEnumerator()
			{
				<GetCategoryCandidateKeys>d__123 <GetCategoryCandidateKeys>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<GetCategoryCandidateKeys>d__ = this;
				}
				else
				{
					<GetCategoryCandidateKeys>d__ = new <GetCategoryCandidateKeys>d__123(0);
				}
				<GetCategoryCandidateKeys>d__.item = <>3__item;
				<GetCategoryCandidateKeys>d__.displayName = <>3__displayName;
				return <GetCategoryCandidateKeys>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<string>)this).GetEnumerator();
			}
		}

		private static ConfigEntry<KeyCode> configToggleKey;

		private static ConfigEntry<float> configSpawnDistance;

		private static ConfigEntry<bool> configAllowOnline;

		private static ConfigEntry<bool> configVerboseLogs;

		private static PeakCustomPage? page;

		private static PeakText? headerTitleText;

		private static PeakMenuButton? closeMenuButton;

		private static PeakTextInput? searchInput;

		private static PeakScrollableContent? scrollContent;

		private static Plugin? instance;

		private static Coroutine? itemPreloadCoroutine;

		private static bool itemPreloadRunning;

		private static int itemPreloadTotalCount;

		private static int itemPreloadProcessedCount;

		private static int itemPreloadAddedCount;

		private static float nextPreloadCheckTime;

		private static bool uiBuilt;

		private static bool pageOpen;

		private static string currentSearch = string.Empty;

		private static MajorCategory currentMajorFilter = MajorCategory.All;

		private static ItemCategory? currentSubCategoryFilter;

		private static bool templatesLogged;

		private static PeakHorizontalTabs? majorTabs;

		private static PeakHorizontalTabs? subCategoryTabs;

		private static GameObject? subCategoryTabsRoot;

		private static RectTransform? topControlsRect;

		private static RectTransform? listContainerRect;

		private static Scrollbar? listScrollbar;

		private static readonly List<MajorCategoryTab> majorTabEntries = new List<MajorCategoryTab>();

		private static readonly List<CategoryTab> subCategoryTabEntries = new List<CategoryTab>();

		private static readonly List<ItemEntry> itemEntries = new List<ItemEntry>();

		private static readonly Dictionary<string, Sprite?> itemIconCache = new Dictionary<string, Sprite>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<int, Sprite> generatedTextureSpriteCache = new Dictionary<int, Sprite>();

		private static readonly Dictionary<string, List<Texture2D>> textureNameIndex = new Dictionary<string, List<Texture2D>>(StringComparer.OrdinalIgnoreCase);

		private static bool textureNameIndexBuilt;

		private static GridLayoutGroup? itemGridLayout;

		private static bool itemListInitialized;

		private static readonly Dictionary<string, string> itemNameKeyMap = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

		private static bool itemNameKeyMapInitialized;

		private static readonly Dictionary<string, ItemCategory> wikiCategoryOverrides = BuildWikiCategoryOverrides();

		private static readonly HashSet<string> hiddenPrefabNames = BuildHiddenPrefabNameSet();

		private static bool buttonTemplateRecovered;

		private static readonly Dictionary<string, List<string>> localizedTextTable = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);

		private static bool inputSystemChecked;

		private static bool inputSystemAvailable;

		private static int lastRenderedLanguageIndex = -1;

		private static PropertyInfo? inputSystemKeyboardCurrentProp;

		private static PropertyInfo? inputSystemKeyboardItemProp;

		private static PropertyInfo? inputSystemKeyControlPressedProp;

		private static Type? inputSystemKeyType;

		private static bool legacyInputAvailable = true;

		private static MethodInfo? menuWindowOpenMethod;

		private static MethodInfo? menuWindowCloseMethod;

		public const string Id = "com.github.cherrycove.ItemBrowser";

		internal static ManualLogSource Log { get; private set; } = null;


		public static string Name => "ItemBrowser";

		public static string Version => "0.2.0";

		private void Awake()
		{
			instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			configToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("ItemBrowser", "Toggle Key", (KeyCode)286, "Press to open/close the item browser.");
			configSpawnDistance = ((BaseUnityPlugin)this).Config.Bind<float>("ItemBrowser", "Spawn Distance", 1.5f, "Distance in front of the player to spawn items.");
			configAllowOnline = ((BaseUnityPlugin)this).Config.Bind<bool>("ItemBrowser", "Allow Online Spawn", true, "Allow spawning items while online.");
			configVerboseLogs = ((BaseUnityPlugin)this).Config.Bind<bool>("ItemBrowser", "Verbose Logs", false, "Enable detailed category/UI/spawn logs.");
			LoadLocalizedText();
		}

		private void OnDestroy()
		{
			if ((Object)(object)instance == (Object)(object)this)
			{
				instance = null;
			}
			if (itemPreloadCoroutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(itemPreloadCoroutine);
				itemPreloadCoroutine = null;
			}
			itemPreloadRunning = false;
		}

		private void Update()
		{
			TickBackgroundItemPreload();
			if (IsTogglePressed())
			{
				ToggleUI();
			}
		}

		private static void ToggleUI()
		{
			if (EnsureUIBuilt())
			{
				if (pageOpen)
				{
					ClosePage();
				}
				else
				{
					OpenPage();
				}
			}
		}

		private static bool EnsureUIBuilt()
		{
			if (uiBuilt)
			{
				return true;
			}
			if (!IsUIReady(out string reason))
			{
				if (!string.IsNullOrWhiteSpace(reason))
				{
					Log.LogWarning((object)("[ItemBrowser] UI not ready yet (" + reason + "). Try again after fully entering a match."));
				}
				else
				{
					Log.LogWarning((object)"[ItemBrowser] UI not ready yet. Try again after fully entering a match.");
				}
				return false;
			}
			BuildUI();
			uiBuilt = true;
			LogAvailableTemplates();
			VerboseLog("UI build completed.");
			return true;
		}

		private static bool IsUIReady(out string reason)
		{
			List<string> list = new List<string>(3);
			InputCellMapper val = SingletonAsset<InputCellMapper>.Instance;
			if ((Object)(object)val == (Object)null)
			{
				list.Add("InputCellMapper.Instance == null");
			}
			else if ((Object)(object)val.FloatSettingCell == (Object)null)
			{
				list.Add("InputCellMapper.FloatSettingCell == null");
			}
			if ((Object)(object)Templates.ButtonTemplate == (Object)null && !TryRecoverButtonTemplate(out string reason2))
			{
				if (string.IsNullOrWhiteSpace(reason2))
				{
					list.Add("Templates.ButtonTemplate == null");
				}
				else
				{
					list.Add("Templates.ButtonTemplate == null (" + reason2 + ")");
				}
			}
			if (list.Count == 0)
			{
				reason = string.Empty;
				return true;
			}
			reason = string.Join(", ", list);
			return false;
		}

		private static bool TryRecoverButtonTemplate(out string reason)
		{
			reason = string.Empty;
			if ((Object)(object)Templates.ButtonTemplate != (Object)null)
			{
				return true;
			}
			try
			{
				GameObject[] array = Resources.FindObjectsOfTypeAll<GameObject>();
				if (array == null || array.Length == 0)
				{
					reason = "Resources empty";
					return false;
				}
				GameObject val = ((IEnumerable<GameObject>)array).FirstOrDefault((Func<GameObject, bool>)((GameObject obj) => (Object)(object)obj != (Object)null && ((Object)obj).name == "UI_MainMenuButton_LeaveGame (2)"));
				if ((Object)(object)val == (Object)null)
				{
					val = ((IEnumerable<GameObject>)array).FirstOrDefault((Func<GameObject, bool>)((GameObject obj) => (Object)(object)obj != (Object)null && ((Object)obj).name.StartsWith("UI_MainMenuButton_LeaveGame", StringComparison.Ordinal)));
				}
				if ((Object)(object)val == (Object)null)
				{
					reason = "MainMenu button prefab not found";
					return false;
				}
				GameObject val2 = Object.Instantiate<GameObject>(val);
				((Object)val2).name = "PeakUIButton";
				RemoveLocalizedTextComponent(val2);
				Object.DontDestroyOnLoad((Object)(object)val2);
				if (!TrySetTemplatesProperty("ButtonTemplate", val2, out string reason2))
				{
					reason = reason2;
					return false;
				}
				if (!buttonTemplateRecovered)
				{
					Log.LogInfo((object)"[ItemBrowser] Recovered Templates.ButtonTemplate from Resources.");
					buttonTemplateRecovered = true;
				}
				return true;
			}
			catch (Exception ex)
			{
				reason = ex.GetType().Name + ": " + ex.Message;
				return false;
			}
		}

		private static void RemoveLocalizedTextComponent(GameObject target)
		{
			if ((Object)(object)target == (Object)null)
			{
				return;
			}
			Component[] componentsInChildren = target.GetComponentsInChildren<Component>(true);
			foreach (Component val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && string.Equals(((object)val).GetType().Name, "LocalizedText", StringComparison.Ordinal))
				{
					Object.DestroyImmediate((Object)(object)val);
				}
			}
		}

		private static bool TrySetTemplatesProperty(string propertyName, object value, out string reason)
		{
			reason = string.Empty;
			PropertyInfo property = typeof(Templates).GetProperty(propertyName, BindingFlags.Static | BindingFlags.Public);
			if (property == null)
			{
				reason = "Templates." + propertyName + " property not found";
				return false;
			}
			MethodInfo setMethod = property.GetSetMethod(nonPublic: true);
			if (setMethod == null)
			{
				reason = "Templates." + propertyName + " setter not accessible";
				return false;
			}
			setMethod.Invoke(null, new object[1] { value });
			return true;
		}

		private static void LogAvailableTemplates()
		{
			if (templatesLogged)
			{
				return;
			}
			templatesLogged = true;
			try
			{
				Type typeFromHandle = typeof(Templates);
				PropertyInfo[] properties = typeFromHandle.GetProperties(BindingFlags.Static | BindingFlags.Public);
				if (properties.Length == 0)
				{
					Log.LogInfo((object)"[ItemBrowser] Templates has no public static properties.");
					return;
				}
				PropertyInfo[] array = properties;
				foreach (PropertyInfo propertyInfo in array)
				{
					object obj = null;
					try
					{
						obj = propertyInfo.GetValue(null);
					}
					catch
					{
					}
					string text = ((obj == null) ? "null" : "ok");
					Log.LogInfo((object)("[ItemBrowser] Template " + propertyInfo.Name + " (" + propertyInfo.PropertyType.Name + ") = " + text));
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("[ItemBrowser] Failed to enumerate Templates: " + ex.GetType().Name + " " + ex.Message));
			}
		}

		private static void VerboseLog(string message)
		{
			if (configVerboseLogs != null && configVerboseLogs.Value)
			{
				Log.LogInfo((object)("[ItemBrowser] " + message));
			}
		}

		private static void WarnFallbackCategory(Item item, string displayName)
		{
			if (configVerboseLogs != null && configVerboseLogs.Value)
			{
				string text = ((item != null) ? ((Object)item).name : null) ?? "<null>";
				Log.LogWarning((object)("[ItemBrowser] Category fallback -> MiscEquipment. Prefab='" + text + "', Display='" + displayName + "'"));
			}
		}

		private static void BuildUI()
		{
			//IL_0049: 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_0054: Expected O, but got Unknown
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: 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_00c5: 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_0073: 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_007e: Expected O, but got Unknown
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: 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_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: 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_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: 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_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Expected O, but got Unknown
			//IL_0362: Unknown result type (might be due to invalid IL or missing references)
			//IL_0387: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0313: Unknown result type (might be due to invalid IL or missing references)
			//IL_0329: Unknown result type (might be due to invalid IL or missing references)
			//IL_033f: Unknown result type (might be due to invalid IL or missing references)
			//IL_044a: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0421: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0504: Unknown result type (might be due to invalid IL or missing references)
			//IL_0518: Unknown result type (might be due to invalid IL or missing references)
			//IL_052c: Unknown result type (might be due to invalid IL or missing references)
			//IL_046f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0485: Unknown result type (might be due to invalid IL or missing references)
			//IL_049b: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_058c: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_05df: Unknown result type (might be due to invalid IL or missing references)
			//IL_05fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_060e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0622: Unknown result type (might be due to invalid IL or missing references)
			//IL_0636: Unknown result type (might be due to invalid IL or missing references)
			//IL_055e: Unknown result type (might be due to invalid IL or missing references)
			//IL_068f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0661: Unknown result type (might be due to invalid IL or missing references)
			//IL_0841: Unknown result type (might be due to invalid IL or missing references)
			//IL_0848: Expected O, but got Unknown
			//IL_0881: Unknown result type (might be due to invalid IL or missing references)
			//IL_0724: Unknown result type (might be due to invalid IL or missing references)
			//IL_0762: Unknown result type (might be due to invalid IL or missing references)
			//IL_092b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0967: Unknown result type (might be due to invalid IL or missing references)
			//IL_096e: Expected O, but got Unknown
			//IL_09ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_08aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_08c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_08d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_08ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0902: Unknown result type (might be due to invalid IL or missing references)
			//IL_0797: Unknown result type (might be due to invalid IL or missing references)
			//IL_07be: Unknown result type (might be due to invalid IL or missing references)
			//IL_07e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_07f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0805: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a58: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ab3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0acd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ae1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0af5: Unknown result type (might be due to invalid IL or missing references)
			//IL_09d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_09ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a03: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a19: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a2f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b17: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b53: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b81: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b97: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bc1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bd5: Unknown result type (might be due to invalid IL or missing references)
			page = MenuAPI.CreatePageWithBackground("ItemBrowserPage");
			page.OpenOnStart = false;
			page.CloseOnUICancel = true;
			page.AutoHideOnClose = true;
			PeakCustomPage? obj = page;
			object obj2 = <>c.<>9__74_0;
			if (obj2 == null)
			{
				UnityAction val = delegate
				{
					pageOpen = true;
					RefreshLanguageDependentContent(force: true);
					EnsureItemList();
					RefreshList();
				};
				<>c.<>9__74_0 = val;
				obj2 = (object)val;
			}
			obj.SetOnOpen((UnityAction)obj2);
			PeakCustomPage? obj3 = page;
			object obj4 = <>c.<>9__74_1;
			if (obj4 == null)
			{
				UnityAction val2 = delegate
				{
					pageOpen = false;
				};
				<>c.<>9__74_1 = val2;
				obj4 = (object)val2;
			}
			obj3.SetOnClose((UnityAction)obj4);
			PeakElement val3 = ElementExtensions.SetSize<PeakElement>(ElementExtensions.SetPosition<PeakElement>(ElementExtensions.SetAnchorMax<PeakElement>(ElementExtensions.SetAnchorMin<PeakElement>(ElementExtensions.ParentTo<PeakElement>(new GameObject("Panel").AddComponent<PeakElement>(), (Component)(object)page), new Vector2(0.5f, 0.5f)), new Vector2(0.5f, 0.5f)), Vector2.zero), new Vector2(760f, 760f));
			RectTransform component = ((Component)val3).GetComponent<RectTransform>();
			if ((Object)(object)component != (Object)null)
			{
				component.pivot = new Vector2(0.5f, 0.5f);
				component.anchoredPosition = Vector2.zero;
				component.sizeDelta = new Vector2(760f, 760f);
			}
			Image val4 = ((Component)val3).gameObject.AddComponent<Image>();
			((Graphic)val4).color = new Color(0.05f, 0.04f, 0.03f, 0.9f);
			Outline val5 = ((Component)val3).gameObject.AddComponent<Outline>();
			((Shadow)val5).effectColor = new Color(1f, 1f, 1f, 0.3f);
			((Shadow)val5).effectDistance = new Vector2(2f, -2f);
			((Component)val3).transform.SetAsLastSibling();
			PeakElement val6 = ElementExtensions.SetSize<PeakElement>(ElementExtensions.SetPosition<PeakElement>(ElementExtensions.SetAnchorMax<PeakElement>(ElementExtensions.SetAnchorMin<PeakElement>(ElementExtensions.ParentTo<PeakElement>(new GameObject("Header").AddComponent<PeakElement>(), (Component)(object)val3), new Vector2(0.5f, 1f)), new Vector2(0.5f, 1f)), new Vector2(0f, -16f)), new Vector2(360f, 34f));
			RectTransform component2 = ((Component)val6).GetComponent<RectTransform>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.pivot = new Vector2(0.5f, 1f);
			}
			headerTitleText = ElementExtensions.ExpandToParent<PeakText>(ElementExtensions.ParentTo<PeakText>(MenuAPI.CreateText(GetText("TITLE"), "HeaderText").SetFontSize(26f), (Component)(object)val6));
			((TMP_Text)headerTitleText.TextMesh).alignment = (TextAlignmentOptions)4098;
			PeakMenuButton obj5 = ElementExtensions.ParentTo<PeakMenuButton>(MenuAPI.CreateMenuButton(GetTextOrFallback("CLOSE_BUTTON", "Close")), (Component)(object)val3);
			object obj6 = <>O.<0>__ClosePage;
			if (obj6 == null)
			{
				UnityAction val7 = ClosePage;
				<>O.<0>__ClosePage = val7;
				obj6 = (object)val7;
			}
			closeMenuButton = obj5.OnClick((UnityAction)obj6);
			RemoveLocalizedTextComponent(((Component)closeMenuButton).gameObject);
			RectTransform component3 = ((Component)closeMenuButton).GetComponent<RectTransform>();
			if ((Object)(object)component3 != (Object)null)
			{
				component3.anchorMin = new Vector2(1f, 1f);
				component3.anchorMax = new Vector2(1f, 1f);
				component3.pivot = new Vector2(1f, 1f);
				component3.anchoredPosition = new Vector2(-24f, -10f);
				component3.sizeDelta = new Vector2(82f, 32f);
			}
			closeMenuButton.SetColor(new Color(0.22f, 0.16f, 0.12f, 0.95f), false);
			closeMenuButton.SetBorderColor(new Color(0.62f, 0.54f, 0.44f, 0.55f));
			if ((Object)(object)((PeakLocalizableElement)closeMenuButton).Text != (Object)null)
			{
				((PeakLocalizableElement)closeMenuButton).Text.fontSize = 16f;
				((PeakLocalizableElement)closeMenuButton).Text.alignment = (TextAlignmentOptions)514;
				((PeakLocalizableElement)closeMenuButton).Text.textWrappingMode = (TextWrappingModes)0;
				((PeakLocalizableElement)closeMenuButton).Text.overflowMode = (TextOverflowModes)3;
				((PeakLocalizableElement)closeMenuButton).Text.margin = Vector4.zero;
				((Graphic)((PeakLocalizableElement)closeMenuButton).Text).color = new Color(0.95f, 0.92f, 0.86f, 1f);
				((Graphic)((PeakLocalizableElement)closeMenuButton).Text).raycastTarget = false;
			}
			NormalizeButtonLayout((PeakElement)(object)closeMenuButton, (Vector2?)new Vector2(82f, 32f));
			if ((Object)(object)component3 != (Object)null)
			{
				component3.anchorMin = new Vector2(1f, 1f);
				component3.anchorMax = new Vector2(1f, 1f);
				component3.pivot = new Vector2(1f, 1f);
				component3.anchoredPosition = new Vector2(-12f, -10f);
				component3.sizeDelta = new Vector2(82f, 32f);
			}
			PeakElement val8 = ElementExtensions.SetSize<PeakElement>(ElementExtensions.SetPosition<PeakElement>(ElementExtensions.SetAnchorMax<PeakElement>(ElementExtensions.SetAnchorMin<PeakElement>(ElementExtensions.ParentTo<PeakElement>(new GameObject("TopControls").AddComponent<PeakElement>(), (Component)(object)val3), new Vector2(0.5f, 1f)), new Vector2(0.5f, 1f)), new Vector2(0f, -58f)), new Vector2(720f, 166f));
			RectTransform val9 = (topControlsRect = ((Component)val8).GetComponent<RectTransform>());
			if ((Object)(object)val9 != (Object)null)
			{
				val9.pivot = new Vector2(0.5f, 1f);
			}
			Image val10 = ((Component)val8).gameObject.AddComponent<Image>();
			((Graphic)val10).color = new Color(0.11f, 0.09f, 0.07f, 0.97f);
			Outline val11 = ((Component)val8).gameObject.AddComponent<Outline>();
			((Shadow)val11).effectColor = new Color(1f, 1f, 1f, 0.2f);
			((Shadow)val11).effectDistance = new Vector2(1f, -1f);
			PeakElement val12 = ElementExtensions.SetSize<PeakElement>(ElementExtensions.SetPosition<PeakElement>(ElementExtensions.SetAnchorMax<PeakElement>(ElementExtensions.SetAnchorMin<PeakElement>(ElementExtensions.ParentTo<PeakElement>(new GameObject("SearchContainer").AddComponent<PeakElement>(), (Component)(object)val8), new Vector2(0.5f, 1f)), new Vector2(0.5f, 1f)), new Vector2(0f, -8f)), new Vector2(680f, 48f));
			RectTransform component4 = ((Component)val12).GetComponent<RectTransform>();
			if ((Object)(object)component4 != (Object)null)
			{
				component4.pivot = new Vector2(0.5f, 1f);
			}
			Image val13 = ((Component)val12).gameObject.AddComponent<Image>();
			((Graphic)val13).color = new Color(0.16f, 0.13f, 0.1f, 0.95f);
			searchInput = ElementExtensions.ExpandToParent<PeakTextInput>(ElementExtensions.ParentTo<PeakTextInput>(MenuAPI.CreateTextInput("SearchInput"), (Component)(object)val12)).SetPlaceholder(GetText("SEARCH_PLACEHOLDER")).OnValueChanged((UnityAction<string>)OnSearchChanged);
			if ((Object)(object)searchInput.InputField != (Object)null)
			{
				TMP_InputField inputField = searchInput.InputField;
				((Graphic)inputField.textComponent).color = new Color(0.42f, 0.36f, 0.3f, 1f);
				inputField.textComponent.fontSize = 30f;
				inputField.textComponent.enableAutoSizing = false;
				inputField.caretColor = new Color(0.42f, 0.36f, 0.3f, 1f);
				Graphic placeholder = inputField.placeholder;
				TMP_Text val14 = (TMP_Text)(object)((placeholder is TMP_Text) ? placeholder : null);
				if (val14 != null)
				{
					((Graphic)val14).color = new Color(0.42f, 0.36f, 0.3f, 1f);
					val14.fontSize = 30f;
					val14.enableAutoSizing = false;
					((Graphic)inputField.textComponent).color = ((Graphic)val14).color;
					inputField.textComponent.fontSize = val14.fontSize;
					inputField.textComponent.fontStyle = val14.fontStyle;
					inputField.textComponent.alignment = val14.alignment;
					inputField.caretColor = ((Graphic)val14).color;
				}
			}
			GameObject val15 = new GameObject("MajorTabs", new Type[3]
			{
				typeof(RectTransform),
				typeof(ScrollRect),
				typeof(RectMask2D)
			});
			val15.transform.SetParent(((Component)val8).transform, false);
			majorTabs = val15.AddComponent<PeakHorizontalTabs>();
			majorTabs.SetBackgroundColor(new Color(0.18f, 0.14f, 0.1f, 0.95f));
			RectTransform component5 = val15.GetComponent<RectTransform>();
			if ((Object)(object)component5 != (Object)null)
			{
				component5.anchorMin = new Vector2(0.5f, 1f);
				component5.anchorMax = new Vector2(0.5f, 1f);
				component5.pivot = new Vector2(0.5f, 1f);
				component5.anchoredPosition = new Vector2(0f, -56f);
				component5.sizeDelta = new Vector2(680f, 44f);
			}
			Image val16 = val15.AddComponent<Image>();
			((Graphic)val16).color = new Color(0.16f, 0.13f, 0.1f, 0.95f);
			GameObject val17 = new GameObject("SubCategoryTabs", new Type[3]
			{
				typeof(RectTransform),
				typeof(ScrollRect),
				typeof(RectMask2D)
			});
			val17.transform.SetParent(((Component)val8).transform, false);
			subCategoryTabsRoot = val17;
			subCategoryTabs = val17.AddComponent<PeakHorizontalTabs>();
			subCategoryTabs.SetBackgroundColor(new Color(0.18f, 0.14f, 0.1f, 0.95f));
			RectTransform component6 = val17.GetComponent<RectTransform>();
			if ((Object)(object)component6 != (Object)null)
			{
				component6.anchorMin = new Vector2(0.5f, 1f);
				component6.anchorMax = new Vector2(0.5f, 1f);
				component6.pivot = new Vector2(0.5f, 1f);
				component6.anchoredPosition = new Vector2(0f, -100f);
				component6.sizeDelta = new Vector2(680f, 44f);
			}
			Image val18 = val17.AddComponent<Image>();
			((Graphic)val18).color = new Color(0.16f, 0.13f, 0.1f, 0.95f);
			BuildMajorTabs(majorTabs);
			RebuildSubCategoryTabs();
			UpdateSubCategoryVisibility();
			ConfigureTabsContentLayout(val15.transform.Find("Content"), 0f, forceExpandWidth: true);
			ConfigureTabsContentLayout(val17.transform.Find("Content"), 0f, forceExpandWidth: false);
			PeakElement val19 = ElementExtensions.SetOffsetMax<PeakElement>(ElementExtensions.SetOffsetMin<PeakElement>(ElementExtensions.SetAnchorMax<PeakElement>(ElementExtensions.SetAnchorMin<PeakElement>(ElementExtensions.ParentTo<PeakElement>(new GameObject("ListContainer").AddComponent<PeakElement>(), (Component)(object)val3), new Vector2(0f, 0f)), new Vector2(1f, 1f)), new Vector2(20f, 20f)), new Vector2(-20f, (currentMajorFilter == MajorCategory.All) ? (-192f) : (-236f)));
			listContainerRect = ((Component)val19).GetComponent<RectTransform>();
			Image val20 = ((Component)val19).gameObject.AddComponent<Image>();
			((Graphic)val20).color = new Color(0.11f, 0.09f, 0.07f, 0.95f);
			Outline val21 = ((Component)val19).gameObject.AddComponent<Outline>();
			((Shadow)val21).effectColor = new Color(1f, 1f, 1f, 0.14f);
			((Shadow)val21).effectDistance = new Vector2(1f, -1f);
			scrollContent = ElementExtensions.SetOffsetMax<PeakScrollableContent>(ElementExtensions.SetOffsetMin<PeakScrollableContent>(ElementExtensions.ExpandToParent<PeakScrollableContent>(ElementExtensions.ParentTo<PeakScrollableContent>(MenuAPI.CreateScrollableContent("ItemList"), (Component)(object)val19)), new Vector2(12f, 12f)), new Vector2(-26f, -12f));
			SetupListScrollbar(val19);
			EnsureListLayoutReady();
			UpdateItemGridCellSize();
			((Component)page).gameObject.SetActive(false);
		}

		private static RectTransform? GetListContent()
		{
			if ((Object)(object)scrollContent == (Object)null)
			{
				return null;
			}
			if ((Object)(object)scrollContent.Content != (Object)null)
			{
				return scrollContent.Content;
			}
			Transform obj = ((Component)scrollContent).transform.Find("Content");
			return (RectTransform?)(object)((obj is RectTransform) ? obj : null);
		}

		private static void EnsureListLayoutReady()
		{
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			RectTransform listContent = GetListContent();
			if ((Object)(object)listContent == (Object)null)
			{
				return;
			}
			VerticalLayoutGroup component = ((Component)listContent).GetComponent<VerticalLayoutGroup>();
			if ((Object)(object)component != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)component);
			}
			itemGridLayout = ((Component)listContent).GetComponent<GridLayoutGroup>();
			if ((Object)(object)itemGridLayout == (Object)null)
			{
				try
				{
					itemGridLayout = ((Component)listContent).gameObject.AddComponent<GridLayoutGroup>();
				}
				catch (Exception ex)
				{
					Log.LogError((object)("[ItemBrowser] Failed to add GridLayoutGroup: " + ex.GetType().Name + " " + ex.Message));
					return;
				}
			}
			if (!((Object)(object)itemGridLayout == (Object)null))
			{
				itemGridLayout.constraint = (Constraint)1;
				itemGridLayout.constraintCount = 2;
				itemGridLayout.spacing = new Vector2(12f, 8f);
				itemGridLayout.startAxis = (Axis)0;
				itemGridLayout.startCorner = (Corner)0;
				((LayoutGroup)itemGridLayout).childAlignment = (TextAnchor)0;
			}
		}

		private static void ConfigureTabsContentLayout(Transform? tabsContent, float spacing, bool forceExpandWidth)
		{
			if (!((Object)(object)tabsContent == (Object)null))
			{
				HorizontalLayoutGroup component = ((Component)tabsContent).GetComponent<HorizontalLayoutGroup>();
				if ((Object)(object)component != (Object)null)
				{
					((HorizontalOrVerticalLayoutGroup)component).spacing = spacing;
					((LayoutGroup)component).childAlignment = (TextAnchor)4;
					((HorizontalOrVerticalLayoutGroup)component).childControlWidth = true;
					((HorizontalOrVerticalLayoutGroup)component).childForceExpandWidth = forceExpandWidth;
					((HorizontalOrVerticalLayoutGroup)component).childControlHeight = true;
					((HorizontalOrVerticalLayoutGroup)component).childForceExpandHeight = true;
				}
				ContentSizeFitter component2 = ((Component)tabsContent).GetComponent<ContentSizeFitter>();
				if ((Object)(object)component2 != (Object)null)
				{
					component2.horizontalFit = (FitMode)2;
				}
			}
		}

		private static void UpdateItemGridCellSize()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: 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_00b2: 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_00cf: Expected O, but got Unknown
			EnsureListLayoutReady();
			RectTransform listContent = GetListContent();
			if (!((Object)(object)itemGridLayout == (Object)null) && !((Object)(object)listContent == (Object)null))
			{
				Rect rect = listContent.rect;
				float num = ((Rect)(ref rect)).width;
				if (num <= 0f)
				{
					num = 680f;
				}
				int num2 = Math.Max(1, itemGridLayout.constraintCount);
				float num3 = ((LayoutGroup)itemGridLayout).padding.left + ((LayoutGroup)itemGridLayout).padding.right;
				float num4 = itemGridLayout.spacing.x * (float)(num2 - 1);
				float num5 = (num - num3 - num4) / (float)num2;
				num5 = Mathf.Clamp(num5, 320f, 420f);
				itemGridLayout.cellSize = new Vector2(num5, 72f);
				((LayoutGroup)itemGridLayout).padding = new RectOffset(4, 4, 4, 4);
			}
		}

		private static void SetupListScrollbar(PeakElement listContainer)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			//IL_0088: 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)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: 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_0132: Expected O, but got Unknown
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Expected O, but got Unknown
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)scrollContent == (Object)null) && !((Object)(object)listContainer == (Object)null))
			{
				ScrollRect component = ((Component)scrollContent).GetComponent<ScrollRect>();
				if (!((Object)(object)component == (Object)null))
				{
					GameObject val = new GameObject("ListScrollbar", new Type[3]
					{
						typeof(RectTransform),
						typeof(Image),
						typeof(Scrollbar)
					});
					val.transform.SetParent(((Component)listContainer).transform, false);
					RectTransform component2 = val.GetComponent<RectTransform>();
					component2.anchorMin = new Vector2(1f, 0f);
					component2.anchorMax = new Vector2(1f, 1f);
					component2.pivot = new Vector2(1f, 1f);
					component2.offsetMin = new Vector2(-12f, 12f);
					component2.offsetMax = new Vector2(-4f, -12f);
					Image component3 = val.GetComponent<Image>();
					((Graphic)component3).color = new Color(0.18f, 0.14f, 0.1f, 0.95f);
					((Graphic)component3).raycastTarget = true;
					GameObject val2 = new GameObject("Sliding Area", new Type[1] { typeof(RectTransform) });
					val2.transform.SetParent(val.transform, false);
					RectTransform component4 = val2.GetComponent<RectTransform>();
					component4.anchorMin = Vector2.zero;
					component4.anchorMax = Vector2.one;
					component4.offsetMin = new Vector2(1f, 1f);
					component4.offsetMax = new Vector2(-1f, -1f);
					GameObject val3 = new GameObject("Handle", new Type[2]
					{
						typeof(RectTransform),
						typeof(Image)
					});
					val3.transform.SetParent(val2.transform, false);
					RectTransform component5 = val3.GetComponent<RectTransform>();
					component5.anchorMin = new Vector2(0f, 0f);
					component5.anchorMax = new Vector2(1f, 1f);
					component5.offsetMin = Vector2.zero;
					component5.offsetMax = Vector2.zero;
					Image component6 = val3.GetComponent<Image>();
					((Graphic)component6).color = new Color(0.92f, 0.88f, 0.8f, 0.95f);
					((Graphic)component6).raycastTarget = true;
					listScrollbar = val.GetComponent<Scrollbar>();
					listScrollbar.direction = (Direction)2;
					listScrollbar.handleRect = component5;
					((Selectable)listScrollbar).targetGraphic = (Graphic)(object)component6;
					listScrollbar.size = 0.2f;
					component.verticalScrollbar = listScrollbar;
					component.verticalScrollbarVisibility = (ScrollbarVisibility)0;
					component.verticalScrollbarSpacing = 2f;
				}
			}
		}

		private static void OnSearchChanged(string query)
		{
			currentSearch = query ?? string.Empty;
			RefreshList();
		}

		private static void RefreshList()
		{
			if ((Object)(object)scrollContent == (Object)null)
			{
				return;
			}
			UpdateItemGridCellSize();
			RectTransform listContent = GetListContent();
			if ((Object)(object)listContent == (Object)null)
			{
				Log.LogWarning((object)"[ItemBrowser] Scroll content not ready yet.");
				return;
			}
			ClearContent((Transform)(object)listContent);
			ClearStatusTextOverlay();
			if (!itemListInitialized)
			{
				EnsureItemList();
				AddStatusText(GetPreloadStatusText());
				return;
			}
			IEnumerable<ItemEntry> source = itemEntries;
			string search = currentSearch.Trim().ToLowerInvariant();
			if (!string.IsNullOrEmpty(search))
			{
				source = source.Where((ItemEntry entry) => entry.SearchText.Contains(search));
			}
			source = source.Where((ItemEntry entry) => IsEntryInMajorCategory(entry, currentMajorFilter));
			if (currentSubCategoryFilter.HasValue)
			{
				source = source.Where((ItemEntry entry) => entry.Category == currentSubCategoryFilter.Value);
			}
			List<ItemEntry> list = source.ToList();
			if (list.Count == 0)
			{
				AddStatusText(GetText("STATUS_EMPTY"));
				return;
			}
			if (!currentSubCategoryFilter.HasValue)
			{
				for (int i = 0; i < list.Count; i++)
				{
					AddItemButton(list[i]);
				}
				return;
			}
			foreach (ItemEntry item in list.OrderBy((ItemEntry entry) => entry.DisplayName))
			{
				AddItemButton(item);
			}
		}

		private static void AddCategoryHeader(ItemCategory category)
		{
			if (!((Object)(object)scrollContent == (Object)null))
			{
				RectTransform listContent = GetListContent();
				if (!((Object)(object)listContent == (Object)null))
				{
					string categoryLabel = GetCategoryLabel(category);
					ElementExtensions.ParentTo<PeakText>(MenuAPI.CreateText(categoryLabel).SetFontSize(22f), (Transform)(object)listContent);
				}
			}
		}

		private static void AddItemButton(ItemEntry entry)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			//IL_0073: 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_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: 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)
			ItemEntry entry2 = entry;
			if ((Object)(object)scrollContent == (Object)null)
			{
				return;
			}
			RectTransform listContent = GetListContent();
			if (!((Object)(object)listContent == (Object)null))
			{
				string displayName = entry2.DisplayName;
				PeakMenuButton val = ElementExtensions.ParentTo<PeakMenuButton>(MenuAPI.CreateMenuButton(displayName), (Transform)(object)listContent).OnClick((UnityAction)delegate
				{
					SpawnItem(entry2.Prefab);
				});
				RectTransform component = ((Component)val).GetComponent<RectTransform>();
				if ((Object)(object)component != (Object)null)
				{
					component.anchorMin = new Vector2(0f, 1f);
					component.anchorMax = new Vector2(1f, 1f);
					component.pivot = new Vector2(0.5f, 0.5f);
					component.sizeDelta = new Vector2(0f, 72f);
					((Transform)component).localScale = Vector3.one;
				}
				LayoutElement val2 = ((Component)val).gameObject.GetComponent<LayoutElement>();
				if ((Object)(object)val2 == (Object)null)
				{
					val2 = ((Component)val).gameObject.AddComponent<LayoutElement>();
				}
				val2.preferredHeight = 72f;
				val2.minHeight = 72f;
				val2.flexibleHeight = 0f;
				val2.preferredWidth = 0f;
				val2.minWidth = 0f;
				val2.flexibleWidth = 0f;
				AddItemIcon(val, entry2.Icon);
				ApplyItemButtonStyle(val);
				NormalizeButtonLayout((PeakElement)(object)val);
			}
		}

		private static void ApplyItemButtonStyle(PeakMenuButton button)
		{
			//IL_005c: 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)
			//IL_012f: 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_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: 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_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: 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)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)button == (Object)null))
			{
				Color val = default(Color);
				((Color)(ref val))..ctor(0.18f, 0.14f, 0.1f, 0.96f);
				Color borderColor = default(Color);
				((Color)(ref borderColor))..ctor(0.6f, 0.52f, 0.42f, 0.6f);
				Color color = default(Color);
				((Color)(ref color))..ctor(0.95f, 0.92f, 0.86f, 1f);
				button.SetColor(val, false);
				button.SetBorderColor(borderColor);
				if ((Object)(object)button.Button != (Object)null && (Object)(object)button.Panel != (Object)null)
				{
					((Selectable)button.Button).targetGraphic = (Graphic)(object)button.Panel;
					ColorBlock colors = ((Selectable)button.Button).colors;
					((ColorBlock)(ref colors)).normalColor = Color.white;
					((ColorBlock)(ref colors)).highlightedColor = Color.white;
					((ColorBlock)(ref colors)).pressedColor = new Color(0.92f, 0.88f, 0.8f, 1f);
					((ColorBlock)(ref colors)).selectedColor = Color.white;
					((ColorBlock)(ref colors)).disabledColor = new Color(1f, 1f, 1f, 0.35f);
					((Selectable)button.Button).colors = colors;
				}
				if ((Object)(object)((PeakLocalizableElement)button).Text != (Object)null)
				{
					((Graphic)((PeakLocalizableElement)button).Text).color = color;
					((PeakLocalizableElement)button).Text.fontSize = 20f;
					((PeakLocalizableElement)button).Text.enableAutoSizing = false;
					((PeakLocalizableElement)button).Text.alignment = (TextAlignmentOptions)4097;
					((PeakLocalizableElement)button).Text.margin = new Vector4(78f, 0f, 12f, 0f);
					((Graphic)((PeakLocalizableElement)button).Text).raycastTarget = false;
				}
			}
		}

		private static void AddItemIcon(PeakMenuButton button, Sprite? icon)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//IL_0059: 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_0083: 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_00ad: 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_00dd: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)button == (Object)null))
			{
				GameObject val = new GameObject("ItemIcon", new Type[2]
				{
					typeof(RectTransform),
					typeof(Image)
				});
				val.transform.SetParent(((Component)button).transform, false);
				RectTransform component = val.GetComponent<RectTransform>();
				component.anchorMin = new Vector2(0f, 0.5f);
				component.anchorMax = new Vector2(0f, 0.5f);
				component.pivot = new Vector2(0f, 0.5f);
				component.anchoredPosition = new Vector2(14f, 0f);
				component.sizeDelta = new Vector2(48f, 48f);
				Image component2 = val.GetComponent<Image>();
				component2.sprite = icon;
				component2.preserveAspect = true;
				((Graphic)component2).raycastTarget = false;
				if ((Object)(object)icon != (Object)null)
				{
					((Graphic)component2).color = Color.white;
				}
				else
				{
					((Graphic)component2).color = new Color(0.48f, 0.42f, 0.35f, 0.45f);
				}
			}
		}

		private static void ClearStatusTextOverlay()
		{
			if (!((Object)(object)scrollContent == (Object)null))
			{
				Transform val = ((Component)scrollContent).transform.Find("StatusOverlay");
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)val).gameObject);
				}
			}
		}

		private static void AddStatusText(string text)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: 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)
			//IL_0070: 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)
			if (!((Object)(object)scrollContent == (Object)null))
			{
				ClearStatusTextOverlay();
				GameObject val = new GameObject("StatusOverlay", new Type[1] { typeof(RectTransform) });
				val.transform.SetParent(((Component)scrollContent).transform, false);
				RectTransform component = val.GetComponent<RectTransform>();
				component.anchorMin = Vector2.zero;
				component.anchorMax = Vector2.one;
				component.offsetMin = Vector2.zero;
				component.offsetMax = Vector2.zero;
				PeakText val2 = ElementExtensions.ExpandToParent<PeakText>(ElementExtensions.ParentTo<PeakText>(MenuAPI.CreateText(text).SetFontSize(30f), val.transform));
				((TMP_Text)val2.TextMesh).alignment = (TextAlignmentOptions)514;
				((Graphic)val2.TextMesh).color = new Color(0.9f, 0.86f, 0.78f, 1f);
				((TMP_Text)val2.TextMesh).enableAutoSizing = false;
				((Graphic)val2.TextMesh).raycastTarget = false;
			}
		}

		private static void AddSpacer(float height)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			if (!((Object)(object)scrollContent == (Object)null))
			{
				RectTransform listContent = GetListContent();
				if (!((Object)(object)listContent == (Object)null))
				{
					GameObject val = new GameObject("Spacer", new Type[2]
					{
						typeof(RectTransform),
						typeof(LayoutElement)
					});
					LayoutElement component = val.GetComponent<LayoutElement>();
					component.minHeight = height;
					component.preferredHeight = height;
					val.transform.SetParent((Transform)(object)listContent, false);
				}
			}
		}

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

		private static void EnsureItemList()
		{
			if (!itemListInitialized && !itemPreloadRunning)
			{
				TryStartBackgroundItemPreload("EnsureItemList");
			}
		}

		private static void TickBackgroundItemPreload()
		{
			if (!itemListInitialized && !itemPreloadRunning && !(Time.unscaledTime < nextPreloadCheckTime))
			{
				nextPreloadCheckTime = Time.unscaledTime + 1f;
				if (IsUIReady(out string _))
				{
					TryStartBackgroundItemPreload("AutoWarmup");
				}
			}
		}

		private static bool TryStartBackgroundItemPreload(string reason)
		{
			if (itemListInitialized || itemPreloadRunning)
			{
				return false;
			}
			if ((Object)(object)instance == (Object)null)
			{
				return false;
			}
			ItemDatabase val = SingletonAsset<ItemDatabase>.Instance;
			if ((Object)(object)val == (Object)null || ((DatabaseAsset<ItemDatabase, Item>)(object)val).Objects == null || ((DatabaseAsset<ItemDatabase, Item>)(object)val).Objects.Count == 0)
			{
				return false;
			}
			itemEntries.Clear();
			itemIconCache.Clear();
			itemPreloadTotalCount = ((DatabaseAsset<ItemDatabase, Item>)(object)val).Objects.Count;
			itemPreloadProcessedCount = 0;
			itemPreloadAddedCount = 0;
			itemPreloadRunning = true;
			itemPreloadCoroutine = ((MonoBehaviour)instance).StartCoroutine(BuildItemListGradually(val));
			VerboseLog($"Item preload started ({reason}). Total={itemPreloadTotalCount}");
			return true;
		}

		[IteratorStateMachine(typeof(<BuildItemListGradually>d__93))]
		private static IEnumerator BuildItemListGradually(ItemDatabase db)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <BuildItemListGradually>d__93(0)
			{
				db = db
			};
		}

		private static string GetPreloadStatusText()
		{
			if (itemPreloadRunning)
			{
				if (itemPreloadTotalCount > 0)
				{
					return string.Format("{0} {1}/{2}", GetText("STATUS_LOADING"), itemPreloadProcessedCount, itemPreloadTotalCount);
				}
				return GetText("STATUS_LOADING");
			}
			return GetText("STATUS_NOT_READY");
		}

		private static Sprite? GetItemIcon(Item item)
		{
			if ((Object)(object)item == (Object)null)
			{
				return null;
			}
			string key = ((Object)item).name ?? string.Empty;
			if (itemIconCache.TryGetValue(key, out Sprite value))
			{
				return value;
			}
			Sprite val = null;
			List<string> list = ((configVerboseLogs != null && configVerboseLogs.Value) ? new List<string>() : null);
			HashSet<int> visited = new HashSet<int>();
			try
			{
				val = TryExtractUiDataIcon(item, list);
				if ((Object)(object)val == (Object)null)
				{
					val = TryExtractSprite(item, list, "Item", 0, visited);
				}
				if ((Object)(object)val == (Object)null)
				{
					Component[] components = ((Component)item).GetComponents<Component>();
					for (int i = 0; i < components.Length; i++)
					{
						if (!((Object)(object)val == (Object)null))
						{
							break;
						}
						Component val2 = components[i];
						if (!((Object)(object)val2 == (Object)null))
						{
							val = TryExtractSprite(val2, list, ((object)val2).GetType().Name, 0, visited);
						}
					}
				}
				if ((Object)(object)val == (Object)null)
				{
					SpriteRenderer componentInChildren = ((Component)item).GetComponentInChildren<SpriteRenderer>(true);
					if ((Object)(object)componentInChildren != (Object)null)
					{
						val = componentInChildren.sprite;
						list?.Add(((Object)(object)val != (Object)null) ? ("SpriteRenderer(sprite)=" + DescribeSprite(val)) : "SpriteRenderer(sprite)=null");
					}
					else
					{
						list?.Add("SpriteRenderer=missing");
					}
				}
				if ((Object)(object)val == (Object)null)
				{
					val = TryFindTextureByName(item, list);
				}
				if ((Object)(object)val == (Object)null)
				{
					val = TryExtractMaterialTextureSprite(item, list);
				}
				if ((Object)(object)val == (Object)null)
				{
					Image componentInChildren2 = ((Component)item).GetComponentInChildren<Image>(true);
					if ((Object)(object)componentInChildren2 != (Object)null)
					{
						val = componentInChildren2.sprite;
						list?.Add(((Object)(object)val != (Object)null) ? ("UI.Image(sprite)=" + DescribeSprite(val)) : "UI.Image(sprite)=null");
					}
					else
					{
						list?.Add("UI.Image=missing");
					}
				}
			}
			catch (Exception ex)
			{
				VerboseLog("GetItemIcon failed for " + ((Object)item).name + ": " + ex.GetType().Name + " " + ex.Message);
			}
			if (list != null)
			{
				if ((Object)(object)val != (Object)null)
				{
					VerboseLog("Icon resolved for '" + ((Object)item).name + "': " + DescribeSprite(val) + " | " + FormatProbe(list));
				}
				else
				{
					Log.LogWarning((object)("[ItemBrowser] Icon missing for '" + ((Object)item).name + "'. Probe: " + FormatProbe(list)));
				}
			}
			itemIconCache[key] = val;
			return val;
		}

		private static Sprite? TryExtractUiDataIcon(Item item, List<string>? probe)
		{
			if ((Object)(object)item == (Object)null)
			{
				return null;
			}
			try
			{
				ItemUIData uIData = item.UIData;
				Texture2D icon = uIData.icon;
				if ((Object)(object)icon != (Object)null)
				{
					return ConvertTextureToSprite(icon, "Item.UIData.icon", probe);
				}
				if (uIData.hasAltIcon && (Object)(object)uIData.altIcon != (Object)null)
				{
					return ConvertTextureToSprite(uIData.altIcon, "Item.UIData.altIcon", probe);
				}
				probe?.Add("Item.UIData.icon=null");
			}
			catch (Exception ex)
			{
				probe?.Add("Item.UIData=failed(" + ex.GetType().Name + ")");
			}
			return null;
		}

		private static Sprite? TryExtractSprite(object target, List<string>? probe = null, string? source = null, int depth = 0, HashSet<int>? visited = null)
		{
			if (target == null || depth > 2)
			{
				return null;
			}
			if (visited == null)
			{
				visited = new HashSet<int>();
			}
			if (!(target is string) && !target.GetType().IsValueType)
			{
				int hashCode = RuntimeHelpers.GetHashCode(target);
				if (!visited.Add(hashCode))
				{
					return null;
				}
			}
			string text = (string.IsNullOrWhiteSpace(source) ? target.GetType().Name : source);
			if (TryExtractSpriteFromValue(target, text, probe, depth, visited, out Sprite sprite))
			{
				return sprite;
			}
			Type type = target.GetType();
			string[] array = new string[18]
			{
				"Icon", "icon", "ItemIcon", "itemIcon", "IconSprite", "iconSprite", "Sprite", "sprite", "Thumbnail", "thumbnail",
				"Icons", "icons", "ItemIcons", "itemIcons", "Atlas", "atlas", "Texture", "texture"
			};
			foreach (string name in array)
			{
				FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					object value = null;
					try
					{
						value = field.GetValue(target);
					}
					catch
					{
					}
					if (TryExtractSpriteFromValue(value, text + "." + field.Name, probe, depth + 1, visited, out Sprite sprite2))
					{
						return sprite2;
					}
					probe?.Add(text + "." + field.Name + "<" + field.FieldType.Name + ">=" + DescribeProbeValue(value));
				}
				PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (property != null && property.CanRead && property.GetIndexParameters().Length == 0)
				{
					object obj2 = null;
					try
					{
						obj2 = property.GetValue(target);
					}
					catch
					{
						obj2 = "<get_error>";
					}
					if (TryExtractSpriteFromValue(obj2, text + "." + property.Name, probe, depth + 1, visited, out Sprite sprite3))
					{
						return sprite3;
					}
					probe?.Add(text + "." + property.Name + "<" + property.PropertyType.Name + ">=" + DescribeProbeValue(obj2));
				}
			}
			FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (FieldInfo fieldInfo in fields)
			{
				if (IsIconProbeMember(fieldInfo.Name, fieldInfo.FieldType))
				{
					object value2 = null;
					try
					{
						value2 = fieldInfo.GetValue(target);
					}
					catch
					{
					}
					if (TryExtractSpriteFromValue(value2, text + "." + fieldInfo.Name, probe, depth + 1, visited, out Sprite sprite4))
					{
						return sprite4;
					}
					probe?.Add(text + "." + fieldInfo.Name + "<" + fieldInfo.FieldType.Name + ">=" + DescribeProbeValue(value2));
				}
			}
			PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (PropertyInfo propertyInfo in properties)
			{
				if (propertyInfo.CanRead && propertyInfo.GetIndexParameters().Length == 0 && IsIconProbeMember(propertyInfo.Name, propertyInfo.PropertyType))
				{
					object obj5 = null;
					try
					{
						obj5 = propertyInfo.GetValue(target);
					}
					catch
					{
						obj5 = "<get_error>";
					}
					if (TryExtractSpriteFromValue(obj5, text + "." + propertyInfo.Name, probe, depth + 1, visited, out Sprite sprite5))
					{
						return sprite5;
					}
					probe?.Add(text + "." + propertyInfo.Name + "<" + propertyInfo.PropertyType.Name + ">=" + DescribeProbeValue(obj5));
				}
			}
			return null;
		}

		private static bool TryExtractSpriteFromValue(object? value, string source, List<string>? probe, int depth, HashSet<int> visited, out Sprite? sprite)
		{
			sprite = null;
			if (value == null)
			{
				return false;
			}
			Sprite val = (Sprite)((value is Sprite) ? value : null);
			if (val != null)
			{
				probe?.Add(source + "=" + DescribeSprite(val));
				sprite = val;
				return true;
			}
			Texture2D val2 = (Texture2D)((value is Texture2D) ? value : null);
			if (val2 != null)
			{
				sprite = ConvertTextureToSprite(val2, source, probe);
				return (Object)(object)sprite != (Object)null;
			}
			Texture val3 = (Texture)((value is Texture) ? value : null);
			if (val3 != null)
			{
				Texture2D val4 = (Texture2D)(object)((val3 is Texture2D) ? val3 : null);
				if (val4 != null)
				{
					sprite = ConvertTextureToSprite(val4, source, probe);
					return (Object)(object)sprite != (Object)null;
				}
				probe?.Add(source + "=texture('" + ((Object)val3).name + "') unsupported:" + ((object)val3).GetType().Name);
				return false;
			}
			if (value is IEnumerable enumerable && !(value is string) && ShouldEnumerateIconCollection(source, value))
			{
				int num = 0;
				foreach (object item in enumerable)
				{
					if (TryExtractSpriteFromValue(item, $"{source}[{num}]", probe, depth + 1, visited, out sprite))
					{
						return true;
					}
					num++;
					if (num >= 8)
					{
						break;
					}
				}
				return false;
			}
			if (depth >= 2)
			{
				return false;
			}
			Type type = value.GetType();
			if (type.IsPrimitive || type.IsEnum || value is string || value is decimal)
			{
				return false;
			}
			if (!ShouldDeepProbeSource(source, type))
			{
				return false;
			}
			sprite = TryExtractSprite(value, probe, source, depth + 1, visited);
			return (Object)(object)sprite != (Object)null;
		}

		private static Sprite? ConvertTextureToSprite(Texture2D texture, string source, List<string>? probe)
		{
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)texture == (Object)null)
			{
				return null;
			}
			int instanceID = ((Object)texture).GetInstanceID();
			if (generatedTextureSpriteCache.TryGetValue(instanceID, out Sprite value) && (Object)(object)value != (Object)null)
			{
				probe?.Add(source + "=cached:" + DescribeSprite(value));
				return value;
			}
			if (((Texture)texture).width <= 0 || ((Texture)texture).height <= 0)
			{
				probe?.Add(source + "=texture('" + ((Object)texture).name + "') invalid_size");
				return null;
			}
			try
			{
				Sprite val = Sprite.Create(texture, new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0);
				((Object)val).name = ((Object)texture).name + "_AutoIcon";
				generatedTextureSpriteCache[instanceID] = val;
				probe?.Add(source + "=texture->sprite:" + DescribeSprite(val));
				return val;
			}
			catch (Exception ex)
			{
				probe?.Add(source + "=texture_convert_failed(" + ex.GetType().Name + ")");
				return null;
			}
		}

		private static Sprite? TryExtractMaterialTextureSprite(Item item, List<string>? probe)
		{
			if ((Object)(object)item == (Object)null)
			{
				return null;
			}
			Renderer[] componentsInChildren = ((Component)item).GetComponentsInChildren<Renderer>(true);
			if (componentsInChildren == null || componentsInChildren.Length == 0)
			{
				probe?.Add("Renderer=missing");
				return null;
			}
			Texture2D bestTexture = null;
			string bestSource = string.Empty;
			int bestScore = int.MinValue;
			foreach (Renderer val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				if (ShouldSkipRendererForIcon(val))
				{
					probe?.Add("Renderer(" + ((object)val).GetType().Name + ":" + ((Object)val).name + ")=skip");
					continue;
				}
				Material[] sharedMaterials = val.sharedMaterials;
				if (sharedMaterials == null || sharedMaterials.Length == 0)
				{
					probe?.Add("Renderer(" + ((object)val).GetType().Name + ":" + ((Object)val).name + ").sharedMaterials=empty");
					continue;
				}
				foreach (Material val2 in sharedMaterials)
				{
					if ((Object)(object)val2 == (Object)null)
					{
						continue;
					}
					if (ShouldSkipMaterialForIcon(val2))
					{
						probe?.Add("Renderer(" + ((object)val).GetType().Name + ":" + ((Object)val).name + ").Material(" + ((Object)val2).name + ")=skip");
						continue;
					}
					string text = "Renderer(" + ((object)val).GetType().Name + ":" + ((Object)val).name + ").Material(" + ((Object)val2).name + ")";
					string name = ((Object)item).name;
					Texture mainTexture = val2.mainTexture;
					EvaluateTextureCandidate(name, (Texture2D?)(object)((mainTexture is Texture2D) ? mainTexture : null), text + ".mainTexture", ref bestTexture, ref bestSource, ref bestScore, probe);
					string[] array;
					try
					{
						array = val2.GetTexturePropertyNames();
					}
					catch
					{
						array = Array.Empty<string>();
					}
					foreach (string text2 in array)
					{
						if (!string.IsNullOrWhiteSpace(text2))
						{
							Texture2D texture = null;
							try
							{
								Texture texture2 = val2.GetTexture(text2);
								texture = (Texture2D)(object)((texture2 is Texture2D) ? texture2 : null);
							}
							catch
							{
							}
							EvaluateTextureCandidate(((Object)item).name, texture, text + "." + text2, ref bestTexture, ref bestSource, ref bestScore, probe);
						}
					}
				}
			}
			if ((Object)(object)bestTexture == (Object)null)
			{
				probe?.Add("MaterialTexture=no_candidate");
				return null;
			}
			if (bestScore < 80)
			{
				probe?.Add($"MaterialTexture.skip(score={bestScore})");
				return null;
			}
			probe?.Add($"MaterialTexture=choose(score={bestScore}):{bestSource}");
			return ConvertTextureToSprite(bestTexture, bestSource, probe);
		}

		private static bool ShouldSkipRendererForIcon(Renderer renderer)
		{
			if ((Object)(object)renderer == (Object)null)
			{
				return true;
			}
			string text = ((Object)renderer).name?.ToLowerInvariant() ?? string.Empty;
			if (!text.Contains("hand") && !text.Contains("arm") && !text.Contains("player") && !text.Contains("viewmodel") && !text.Contains("firstperson") && !text.Contains("fp_"))
			{
				return text.Contains("character");
			}
			return true;
		}

		private static bool ShouldSkipMaterialForIcon(Material material)
		{
			if ((Object)(object)material == (Object)null)
			{
				return true;
			}
			string text = ((Object)material).name?.ToLowerInvariant() ?? string.Empty;
			if (!text.Contains("m_player") && !text.Contains("player") && !text.Contains("hand") && !text.Contains("skin") && !text.Contains("hair") && !text.Contains("eye"))
			{
				return text.Contains("face");
			}
			return true;
		}

		private static Sprite? TryFindTextureByName(Item item, List<string>? probe)
		{
			if ((Object)(object)item == (Object)null)
			{
				return null;
			}
			EnsureTextureNameIndex();
			if (textureNameIndex.Count == 0)
			{
				probe?.Add("TextureNameIndex=empty");
				return null;
			}
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			string text = ((Object)item).name ?? string.Empty;
			if (!string.IsNullOrWhiteSpace(text))
			{
				hashSet.Add(text);
				hashSet.Add(text.Replace("_", " "));
				int num = text.IndexOf(" Variant", StringComparison.OrdinalIgnoreCase);
				if (num > 0)
				{
					hashSet.Add(text.Substring(0, num));
				}
			}
			Texture2D val = null;
			int num2 = int.MinValue;
			string text2 = string.Empty;
			foreach (string item2 in hashSet)
			{
				string text3 = NormalizeLookupToken(item2);
				if (string.IsNullOrEmpty(text3) || !textureNameIndex.TryGetValue(text3, out List<Texture2D> value) || value == null)
				{
					continue;
				}
				for (int i = 0; i < value.Count; i++)
				{
					Texture2D val2 = value[i];
					if (!((Object)(object)val2 == (Object)null))
					{
						int num3 = ScoreTextureCandidate(text, val2, "TextureNameIndex." + text3);
						if (IsLikelyGenericTextureName(((Object)val2).name))
						{
							num3 -= 120;
						}
						num3 += 220;
						probe?.Add($"TextureNameIndex.{text3}=texture('{((Object)val2).name}') score={num3}");
						if (num3 > num2)
						{
							num2 = num3;
							val = val2;
							text2 = "TextureNameIndex." + text3;
						}
					}
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			if (num2 < 120)
			{
				probe?.Add($"TextureNameIndex.skip(score={num2})");
				return null;
			}
			probe?.Add($"TextureNameIndex.choose(score={num2}):{text2}");
			return ConvertTextureToSprite(val, text2, probe);
		}

		private static void EnsureTextureNameIndex()
		{
			if (textureNameIndexBuilt)
			{
				return;
			}
			textureNameIndexBuilt = true;
			textureNameIndex.Clear();
			try
			{
				Texture2D[] array = Resources.FindObjectsOfTypeAll<Texture2D>();
				if (array == null || array.Length == 0)
				{
					return;
				}
				foreach (Texture2D val in array)
				{
					if ((Object)(object)val == (Object)null || string.IsNullOrWhiteSpace(((Object)val).name))
					{
						continue;
					}
					string text = NormalizeLookupToken(((Object)val).name);
					if (!string.IsNullOrEmpty(text))
					{
						if (!textureNameIndex.TryGetValue(text, out List<Texture2D> value))
						{
							value = new List<Texture2D>();
							textureNameIndex[text] = value;
						}
						value.Add(val);
					}
				}
				VerboseLog($"TextureNameIndex built: {textureNameIndex.Count} keys");
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("[ItemBrowser] Failed to build texture index: " + ex.GetType().Name + " " + ex.Message));
			}
		}

		private static string NormalizeLookupToken(string value)
		{
			if (string.IsNullOrWhiteSpace(value))
			{
				return string.Empty;
			}
			List<char> list = new List<char>(value.Length);
			foreach (char c in value)
			{
				if (char.IsLetterOrDigit(c))
				{
					list.Add(char.ToLowerInvariant(c));
				}
			}
			return new string(list.ToArray());
		}

		private static void EvaluateTextureCandidate(string itemName, Texture2D? texture, string source, ref Texture2D? bestTexture, ref string bestSource, ref int bestScore, List<string>? probe)
		{
			if ((Object)(object)texture == (Object)null)
			{
				probe?.Add(source + "=null");
				return;
			}
			int num = ScoreTextureCandidate(itemName, texture, source);
			probe?.Add($"{source}=texture('{((Object)texture).name}') score={num}");
			if (num > bestScore)
			{
				bestScore = num;
				bestTexture = texture;
				bestSource = source;
			}
		}

		private static bool IsLikelyGenericTextureName(string textureName)
		{
			if (string.IsNullOrWhiteSpace(textureName))
			{
				return true;
			}
			string text = textureName.ToLowerInvariant();
			if (!text.StartsWith("a_texture") && !text.StartsWith("a_paint") && !text.StartsWith("a_noise") && !text.Contains("noise") && !text.Contains("default") && !text.Contains("gradient") && !text.Contains("cloud"))
			{
				return text.Contains("checker");
			}
			return true;
		}

		private static int ScoreTextureCandidate(string itemName, Texture2D texture, string source)
		{
			string text = source.ToLowerInvariant();
			string text2 = ((Object)texture).name ?? string.Empty;
			string text3 = text2.ToLowerInvariant();
			string source2 = (itemName ?? string.Empty).ToLowerInvariant();
			int num = 0;
			if (text.Contains("icon") || text.Contains("thumb"))
			{
				num += 120;
			}
			if (text3.Contains("icon") || text3.Contains("thumb"))
			{
				num += 100;
			}
			if (text.Contains("atlas"))
			{
				num += 25;
			}
			string value = new string(source2.Where(char.IsLetterOrDigit).ToArray());
			string text4 = new string(text3.Where(char.IsLetterOrDigit).ToArray());
			if (!string.IsNullOrEmpty(value) && text4.Contains(value))
			{
				num += 90;
			}
			if (text.Contains("_basemap") || text.Contains("_maintex") || text.Contains("_basetexture"))
			{
				num += 15;
			}
			if (((Texture)texture).width <= 1024 && ((Texture)texture).height <= 1024)
			{
				num += 20;
			}
			if (((Texture)texture).width <= 512 && ((Texture)texture).height <= 512)
			{
				num += 20;
			}
			if (((Texture)texture).width <= 256 && ((Texture)texture).height <= 256)
			{
				num += 10;
			}
			if (text.Contains("renderer(meshrenderer:hand)") || text.Contains("material(m_player)"))
			{
				num -= 300;
			}
			if (text3.StartsWith("a_texture") || text3.StartsWith("a_paint") || text3.StartsWith("a_noise"))
			{
				num -= 80;
			}
			if (text3.Contains("default") || text3.Contains("fallback") || text3.Contains("noise"))
			{
				num -= 60;
			}
			if (text3.Contains("soft noise") || text3 == "t_leaves" || text3.Contains("leaves") || text3.Contains("foliage"))
			{
				num -= 80;
			}
			return num;
		}

		private static bool ShouldEnumerateIconCollection(string source, object value)
		{
			if (value == null)
			{
				return false;
			}
			if (value is Array array)
			{
				Type c = array.GetType().GetElementType() ?? typeof(object);
				if (typeof(Sprite).IsAssignableFrom(c) || typeof(Texture).IsAssignableFrom(c))
				{
					return true;
				}
			}
			if (source.IndexOf("icon", StringComparison.OrdinalIgnoreCase) < 0 && source.IndexOf("sprite", StringComparison.OrdinalIgnoreCase) < 0 && source.IndexOf("thumb", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return source.IndexOf("texture", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return true;
		}

		private static bool ShouldDeepProbeSource(string source, Type valueType)
		{
			if (valueType == null)
			{
				return false;
			}
			if (typeof(Texture).IsAssignableFrom(valueType) || typeof(Sprite).IsAssignableFrom(valueType))
			{
				return true;
			}
			if (source.IndexOf("icon", StringComparison.OrdinalIgnoreCase) < 0 && source.IndexOf("sprite", StringComparison.OrdinalIgnoreCase) < 0 && source.IndexOf("thumb", StringComparison.OrdinalIgnoreCase) < 0 && source.IndexOf("atlas", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return source.IndexOf("texture", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return true;
		}

		private static bool IsIconProbeMember(string name, Type memberType)
		{
			if (memberType == null)
			{
				return false;
			}
			if (typeof(Sprite).IsAssignableFrom(memberType) || typeof(Texture).IsAssignableFrom(memberType) || memberType.IsArray)
			{
				return true;
			}
			string text = name?.ToLowerInvariant() ?? string.Empty;
			if (string.IsNullOrEmpty(text))
			{
				return false;
			}
			if (!text.Contains("icon") && !text.Contains("sprite") && !text.Contains("thumbnail") && !text.Contains("atlas") && !text.Contains("texture"))
			{
				return text.Contains("tex");
			}
			return true;
		}

		private static string DescribeSprite(Sprite sprite)
		{
			//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_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)sprite == (Object)null)
			{
				return "sprite:null";
			}
			string text = (((Object)(object)sprite.texture != (Object)null) ? ((Object)sprite.texture).name : "null");
			object[] obj = new object[4]
			{
				((Object)sprite).name,
				text,
				null,
				null
			};
			Rect rect = sprite.rect;
			obj[2] = ((Rect)(ref rect)).width;
			rect = sprite.rect;
			obj[3] = ((Rect)(ref rect)).height;
			return string.Format("sprite='{0}', texture='{1}', rect={2}x{3}", obj);
		}

		private static string DescribeProbeValue(object? value)
		{
			if (value == null)
			{
				return "null";
			}
			Sprite val = (Sprite)((value is Sprite) ? value : null);
			if (val != null)
			{
				return DescribeSprite(val);
			}
			Texture val2 = (Texture)((value is Texture) ? value : null);
			if (val2 != null)
			{
				return "texture='" + ((Object)val2).name + "' (" + ((object)val2).GetType().Name + ")";
			}
			if (value is IEnumerable enumerable && !(value is string))
			{
				int num = 0;
				foreach (object item in enumerable)
				{
					num++;
					if (num >= 12)
					{
						break;
					}
				}
				return $"enumerable<{value.GetType().Name}> count~{num}";
			}
			Object val3 = (Object)((value is Object) ? value : null);
			if (val3 != null)
			{
				return "unity='" + val3.name + "' (" + ((object)val3).GetType().Name + ")";
			}
			string text = value.ToString() ?? value.GetType().Name;
			if (text.Length > 80)
			{
				text = text.Substring(0, 80) + "...";
			}
			return text;
		}

		private static string FormatProbe(List<string> probe)
		{
			if (probe == null || probe.Count == 0)
			{
				return "probe=empty";
			}
			if (probe.Count <= 20)
			{
				return string.Join(" | ", probe);
			}
			return string.Join(" | ", probe.Take(20)) + $" | ...(+{probe.Count - 20})";
		}

		private static string GetDisplayNameOverride(Item item, string displayName)
		{
			if ((Object)(object)item == (Object)null)
			{
				return displayName;
			}
			string text = ((Object)item).name ?? string.Empty;
			if (text.Equals("EggTurkey", StringComparison.OrdinalIgnoreCase))
			{
				string text2 = ResolveLocalizedText("NAME_COOKED BIRD");
				if (!string.IsNullOrWhiteSpace(text2))
				{
					return text2;
				}
				return displayName;
			}
			return displayName;
		}

		private static bool ShouldHideItemFromBrowser(Item item, string displayName)
		{
			if ((Object)(object)item == (Object)null)
			{
				return true;
			}
			string text = ((Object)item).name ?? string.Empty;
			if (string.IsNullOrWhiteSpace(text))
			{
				return true;
			}
			string item2 = NormalizeCategoryKey(text);
			if (hiddenPrefabNames.Contains(item2))
			{
				return true;
			}
			if (text.StartsWith("C_", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			if (text.Contains("_Prop", StringComparison.OrdinalIgnoreCase) || text.Contains("_TEMP", StringComparison.OrdinalIgnoreCase) || text.Contains("_UNUSED", StringComparison.OrdinalIgnoreCase) || text.Contains("_Hidden", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			return false;
		}

		private static HashSet<string> BuildHiddenPrefabNameSet()
		{
			return new HashSet<string>(StringComparer.OrdinalIgnoreCase)
			{
				NormalizeCategoryKey("Lollipop_Prop"),
				NormalizeCategoryKey("Lollipop_Prop Variant"),
				NormalizeCategoryKey("FortifiedMilk_TEMP"),
				NormalizeCategoryKey("Clusterberry_UNUSED"),
				NormalizeCategoryKey("Mandrake_Hidden"),
				NormalizeCategoryKey("BingBong_Prop Variant"),
				NormalizeCategoryKey("Binoculars_Prop"),
				NormalizeCategoryKey("Bugle_Prop Variant"),
				NormalizeCategoryKey("Berrynana Peel Blue Variant"),
				NormalizeCategoryKey("Berrynana Peel Brown Variant"),
				NormalizeCategoryKey("Berrynana Peel Pink Variant"),
				NormalizeCategoryKey("Berrynana Peel Yellow"),
				NormalizeCategoryKey("GuidebookPage_4_BodyHeat Variant"),
				NormalizeCategoryKey("GuidebookPage_5_Sleepy Variant"),
				NormalizeCategoryKey("GuidebookPage_6_Awake Variant"),
				NormalizeCategoryKey("GuidebookPage_7_Crashout Variant"),
				NormalizeCategoryKey("Parasol_Roots Variant"),
				NormalizeCategoryKey("ClimbingChalk"),
				NormalizeCategoryKey("Skull")
			};
		}

		private static ItemCategory GetCategory(Item item, string displayName)
		{
			if ((Object)(object)item == (Object)null)
			{
				return ItemCategory.MiscEquipment;
			}
			if (TryGetCategoryByComponent(item, out var category))
			{
				if (TryGetCategoryOverride(item, displayName, out var category2))
				{
					return category2;
				}
				return category;
			}
			if (TryGetCategoryOverride(item, displayName, out var category3))
			{
				return category3;
			}
			if (IsNameKeyword(item, displayName, "berry", "berrynana", "clusterberry", "kingberry", "prickleberry", "shroomberry", "winterberry", "napberry", "scorchberry"))
			{
				return ItemCategory.NaturalFood;
			}
			if (IsNameKeyword(item, displayName, "mushroom", "fungus", "shroom"))
			{
				return ItemCategory.Mushroom;
			}
			if (IsNameKeyword(item, displayName, "packaged", "granola", "trail mix", "cookies", "airplane food", "ration"))
			{
				return ItemCategory.PackagedFood;
			}
			if (IsNameKeyword(item, displayName, "food", "coconut", "hot dog", "marshmallow", "egg", "honeycomb", "aloe"))
			{
				return ItemCategory.NaturalFood;
			}
			WarnFallbackCategory(item, displayName);
			return ItemCategory.MiscEquipment;
		}

		private static bool TryGetCategoryByComponent(Item item, out ItemCategory category)
		{
			category = ItemCategory.NaturalFood;
			if ((Object)(object)item == (Object)null)
			{
				return false;
			}
			if (IsConsumable(item))
			{
				category = ItemCategory.Consumable;
				return true;
			}
			if ((Object)(object)((Component)item).GetComponent<ItemCooking>() != (Object)null || HasKeywordComponent(item, "Cooking"))
			{
				category = ItemCategory.NaturalFood;
				return true;
			}
			if (HasAnyComponentKeyword(item, "Enemy", "Monster", "Creature", "Scorpion", "Beehive"))
			{
				category = ItemCategory.MiscEquipment;
				return true;
			}
			if (HasAnyComponentKeyword(item, "Magic", "Mystic", "Relic", "Artifact", "Ancient", "Curse"))
			{
				category = ItemCategory.MysticalItem;
				return true;
			}
			if (HasAnyComponentKeyword(item, "Deploy", "Place", "Plantable", "Balloon", "PortableStovetop", "RopeShooter", "ClimbingSpike", "ScoutCannon", "ChainShooter"))
			{
				category = ItemCategory.Deployable;
				return true;
			}
			if (HasAnyComponentKeyword(item, "Equipment", "Wearable", "Equip", "Compass", "Lantern", "Backpack", "Parasol", "Guidebook", "Binocular"))
			{
				category = ItemCategory.MiscEquipment;
				return true;
			}
			return false;
		}

		private static bool TryGetCategoryOverride(Item item, string displayName, out ItemCategory category)
		{
			category = ItemCategory.NaturalFood;
			if ((Object)(object)item == (Object)null)
			{
				return false;
			}
			List<string> list = (from x in GetCategoryCandidateKeys(item, displayName)
				where !string.IsNullOrWhiteSpace(x)
				select x).Distinct<string>(StringComparer.OrdinalIgnoreCase).ToList();
			for (int i = 0; i < list.Count; i++)
			{
				string text = list[i];
				if (wikiCategoryOverrides.TryGetValue(text, out category))
				{
					VerboseLog($"Category override hit: key='{text}' -> {category} (prefab='{((Object)item).name}', display='{displayName}')");
					return true;
				}
			}
			int num = int.MinValue;
			string text2 = string.Empty;
			ItemCategory itemCategory = ItemCategory.NaturalFood;
			for (int j = 0; j < list.Count; j++)
			{
				string candidate = list[j];
				foreach (KeyValuePair<string, ItemCategory> wikiCategoryOverride in wikiCategoryOverrides)
				{
					int num2 = ScoreCategoryKeyMatch(candidate, wikiCategoryOverride.Key);
					if (num2 > num)
					{
						num = num2;
						text2 = wikiCategoryOverride.Key;
						itemCategory = wikiCategoryOverride.Value;
					}
				}
			}
			if (num >= 260)
			{
				category = itemCategory;
				VerboseLog($"Category fuzzy hit: score={num}, alias='{text2}', prefab='{((Object)item).name}', display='{displayName}' -> {category}");
				return true;
			}
			return false;
		}

		private static int ScoreCategoryKeyMatch(string candidate, string alias)
		{
			if (string.IsNullOrWhiteSpace(candidate) || string.IsNullOrWhiteSpace(alias))
			{
				return int.MinValue;
			}
			if (string.Equals(candidate, alias, StringComparison.OrdinalIgnoreCase))
			{
				return 1000;
			}
			int num = Math.Min(candidate.Length, alias.Length);
			int val = 0;
			if (candidate.Contains(alias, StringComparison.OrdinalIgnoreCase) || alias.Contains(candidate, StringComparison.OrdinalIgnoreCase))
			{
				val = Math.Max(val, 280 + num * 4);
			}
			int num2 = LongestCommonSubstringLength(candidate, alias);
			val = Math.Max(val, num2 * 24 - Math.Abs(candidate.Length - alias.Length) * 3);
			if (num >= 6 && (candidate.StartsWith(alias.Substring(0, 6), StringComparison.OrdinalIgnoreCase) || alias.StartsWith(candidate.Substring(0, 6), StringComparison.OrdinalIgnoreCase)))
			{
				val += 30;
			}
			return val;
		}

		private static int LongestCommonSubstringLength(string a, string b)
		{
			if (string.IsNullOrEmpty(a) || string.IsNullOrEmpty(b))
			{
				return 0;
			}
			int[,] array = new int[a.Length + 1, b.Length + 1];
			int num = 0;
			for (int i = 1; i <= a.Length; i++)
			{
				for (int j = 1; j <= b.Length; j++)
				{
					if (char.ToLowerInvariant(a[i - 1]) == char.ToLowerInvariant(b[j - 1]))
					{
						array[i, j] = array[i - 1, j - 1] + 1;
						if (array[i, j] > num)
						{
							num = array[i, j];
						}
					}
				}
			}
			return num;
		}

		[IteratorStateMachine(typeof(<GetCategoryCandidateKeys>d__123))]
		private static IEnumerable<string> GetCategoryCandidateKeys(Item item, string displayName)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <GetCategoryCandidateKeys>d__123(-2)
			{
				<>3__item = item,
				<>3__displayName = displayName
			};
		}

		private static Dictionary<string, ItemCategory> BuildWikiCategoryOverrides()
		{
			Dictionary<string, ItemCategory> dictionary = new Dictionary<string, ItemCategory>(StringComparer.OrdinalIgnoreCase);
			AddWikiOverride(dictionary, ItemCategory.NaturalFood, "Coconut", "Half-Coconut", "Red Crispberry", "Yellow Crispberry", "Green Crispberry", "Honeycomb", "Scorchberry", "Purple Kingberry", "Yellow Kingberry", "Green Kingberry", "Pink Berrynana", "Blue Berrynana", "Brown Berrynana", "Yellow Clusterberry", "Red Clusterberry", "Black Clusterberry", "Orange Winterberry", "Yellow Winterberry", "Red Prickleberry", "Gold Prickleberry", "Medicinal Root", "Mandrake", "Marshmallow", "Hot Dog", "Egg", "Cooked Bird", "Tick", "Scorpion", "Napberry", "Red Shroomberry", "Yellow Shroomberry", "Green Shroomberry", "Blue Shroomberry", "Purple Shroomberry", "Item_Coconut", "Item_Coconut_half", "Item_Honeycomb", "Apple Berry Red", "Apple Berry Yellow", "Apple Berry Green", "Pepper Berry", "Kingberry Purple", "Kingberry Yellow", "Kingberry Green", "Berrynana Pink", "Berrynana Blue", "Berrynana Brown", "Clusterberry Red", "Clusterberry Yellow", "Clusterberry Black", "Winterberry Orange", "Prickleberry_Red", "Prickleberry_Gold", "MedicinalRoot", "Glizzy", "EggTurkey");
			AddWikiOverride(dictionary, ItemCategory.MysticalFood, "Cure-All", "Pandora's Lunchbox", "PandorasBox");
			AddWikiOverride(dictionary, ItemCategory.PackagedFood, "Airline Food", "Big Lollipop", "Energy Drink", "Fortified Milk", "Granola Bar", "Scout Cookies", "Sports Drink", "Trail Mix", "Airplane Food", "Lollipop", "FortifiedMilk", "ScoutCookies", "TrailMix");
			AddWikiOverride(dictionary, ItemCategory.Mushroom, "Bugle Shroom", "Bugle Shroom Poison", "Button Shroom", "Button Shroom Poison", "Chubby Shroom", "Cluster Shroom", "Cluster Shroom Poison", "Mushroom Lace", "Mushroom Lace Poison", "Mushroom Normie", "Mushroom Normie Poison", "Mushroom Chubby", "Mushroom Cluster", "Mushroom Cluster Poison");
			AddWikiOverride(dictionary, ItemCategory.Consumable, "Antidote", "Balloon", "Balloon Bunch", "Bandages", "Blowgun", "First Aid Kit", "Flare", "Heat Pack", "Remedy Fungus", "Rescue Claw", "Scroll", "Sunscreen", "BalloonBunch", "FirstAidKit", "HealingDart", "HealingDart Variant", "RescueHook", "GuidebookPageScroll", "GuidebookPageScroll Variant");
			AddWikiOverride(dictionary, ItemCategory.Deployable, "Bounce Fungus", "Chain Launcher", "Checkpoint Flag", "Cloud Fungus", "Magic Bean", "Piton", "Portable Stove", "Rope Cannon", "Rope Spool", "Scout Cannon", "Shelf Fungus", "BounceShroom", "ChainShooter", "Flag_Plantable_Checkpoint", "CloudFungus", "ClimbingSpike", "PortableStovetopItem", "RopeShooter", "ScoutCannonItem", "ShelfShroom");
			AddWikiOverride(dictionary, ItemCategory.MiscEquipment, "Backpack", "Bing Bong", "Binoculars", "Bugle", "Compass", "Flying Disc", "Guidebook", "Lantern", "Parasol", "Pirate's Compass", "Torch", "BingBong", "Frisbee", "Pirate Compass");
			AddWikiOverride(dictionary, ItemCategory.MysticalItem, "Ancient Idol", "Anti-Rope Cannon", "Anti-Rope Spool", "Bugle of Friendship", "Cursed Skull", "Faerie Lantern", "Scout Effigy", "Scoutmaster's Bugle", "The Book of Bones", "AncientIdol", "RopeShooterAnti", "Bugle_Magic", "Lantern_Faerie", "ScoutEffigy", "Bugle_Scoutmaster", "Bugle_Scoutmaster Variant", "BookOfBones");
			return dictionary;
		}

		private static void AddWikiOverride(Dictionary<string, ItemCategory> map, ItemCategory category, params string[] names)
		{
			foreach (string value in names)
			{
				if (!string.IsNullOrWhiteSpace(v