Decompiled source of CraftSearch v2.0.1

BepInEx/plugins/CraftSearch/CraftSearch.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("SearchBarPlus")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("2.0.1.0")]
[assembly: AssemblyInformationalVersion("2.0.1")]
[assembly: AssemblyProduct("SearchBarPlus")]
[assembly: AssemblyTitle("SearchBarPlus")]
[assembly: AssemblyVersion("2.0.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace CraftSearch
{
	internal static class CraftRequirementCompatibility
	{
		private static bool checkedForProvider;

		private static bool hasExternalProvider;

		internal static bool HasExternalProvider
		{
			get
			{
				DetectProvider();
				return hasExternalProvider;
			}
		}

		private static void DetectProvider()
		{
			if (checkedForProvider)
			{
				return;
			}
			checkedForProvider = true;
			try
			{
				HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
				bool flag = HasExternalPatch(typeof(InventoryGui), "SetupRequirement", hashSet) || HasExternalPatch(typeof(Player), "HaveRequirements", hashSet) || HasExternalPatch(typeof(Player), "HaveRequirementItems", hashSet) || HasExternalPatch(typeof(Humanoid), "HaveRequirementItems", hashSet) || HasExternalPatch(typeof(Inventory), "CountItems", hashSet);
				bool flag2 = HasExternalPatch(typeof(Player), "ConsumeResources", hashSet) || HasExternalPatch(typeof(Humanoid), "ConsumeResources", hashSet) || HasExternalPatch(typeof(InventoryGui), "DoCrafting", hashSet);
				hasExternalProvider = FindNamedChestCraftingPlugins(hashSet) || (flag && flag2);
				if (hasExternalProvider)
				{
					string text = ((hashSet.Count == 0) ? "unknown plugin" : string.Join(", ", hashSet));
					Plugin.LogInfo("External crafting resource provider detected (" + text + "). Using native recipe requirements and craft availability.");
				}
			}
			catch (Exception ex)
			{
				Plugin.LogWarning("Could not inspect external crafting resource providers: " + ex.GetType().Name);
			}
		}

		private static bool FindNamedChestCraftingPlugins(HashSet<string> sources)
		{
			bool result = false;
			foreach (PluginInfo value in Chainloader.PluginInfos.Values)
			{
				BepInPlugin val = ((value != null) ? value.Metadata : null);
				if (val != null)
				{
					string text = ((val.GUID ?? string.Empty) + " " + (val.Name ?? string.Empty)).ToLowerInvariant();
					bool num = text.Contains("chest") || text.Contains("container") || text.Contains("storage");
					bool flag = text.Contains("craft") || text.Contains("pull") || text.Contains("resource");
					if (num && flag)
					{
						sources.Add(val.Name + " (" + val.GUID + ")");
						result = true;
					}
				}
			}
			return result;
		}

		private static bool HasExternalPatch(Type type, string methodName, HashSet<string> sources)
		{
			bool flag = false;
			for (Type type2 = type; type2 != null; type2 = type2.BaseType)
			{
				MethodInfo[] methods;
				try
				{
					methods = type2.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				}
				catch
				{
					continue;
				}
				foreach (MethodInfo methodInfo in methods)
				{
					if (string.Equals(methodInfo.Name, methodName, StringComparison.Ordinal))
					{
						flag |= HasExternalPatch(methodInfo, sources);
					}
				}
			}
			return flag;
		}

		private static bool HasExternalPatch(MethodBase method, HashSet<string> sources)
		{
			Patches patchInfo = Harmony.GetPatchInfo(method);
			if (patchInfo == null)
			{
				return false;
			}
			bool result = false;
			string[] array = new string[4] { "Prefixes", "Postfixes", "Transpilers", "Finalizers" };
			for (int i = 0; i < array.Length; i++)
			{
				if (!(((object)patchInfo).GetType().GetProperty(array[i], BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(patchInfo, null) is IEnumerable enumerable))
				{
					continue;
				}
				foreach (object item2 in enumerable)
				{
					if (item2 == null)
					{
						continue;
					}
					string text = item2.GetType().GetField("owner", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(item2) as string;
					if (!string.IsNullOrWhiteSpace(text) && !string.Equals(text, "com.kimbauer.valheim.craftsearch", StringComparison.OrdinalIgnoreCase))
					{
						result = true;
						string item = text;
						if (Chainloader.PluginInfos.TryGetValue(text, out var value) && ((value != null) ? value.Metadata : null) != null)
						{
							item = value.Metadata.Name + " (" + text + ")";
						}
						sources.Add(item);
					}
				}
			}
			return result;
		}
	}
	internal static class ModSourceResolver
	{
		private static readonly Dictionary<int, string> Cache = new Dictionary<int, string>();

		private static readonly Dictionary<int, string> FastModCache = new Dictionary<int, string>();

		private static readonly Dictionary<Assembly, List<string>> RegistryCache = new Dictionary<Assembly, List<string>>();

		internal static string Get(ItemDrop item)
		{
			if (!Object.op_Implicit((Object)(object)item))
			{
				return string.Empty;
			}
			int instanceID = ((Object)item).GetInstanceID();
			if (Cache.TryGetValue(instanceID, out var value))
			{
				return value;
			}
			List<string> list = new List<string>();
			Add(list, ((Object)item).name);
			Add(list, ((Object)((Component)item).gameObject).name);
			try
			{
				Add(list, item.m_itemData?.m_shared?.m_name);
			}
			catch
			{
			}
			Component[] componentsInChildren = ((Component)item).GetComponentsInChildren<Component>(true);
			foreach (Component val in componentsInChildren)
			{
				if (!Object.op_Implicit((Object)(object)val))
				{
					continue;
				}
				Type type = ((object)val).GetType();
				Add(list, type.FullName);
				Assembly assembly = type.Assembly;
				Add(list, assembly.GetName().Name);
				Add(list, type.Namespace);
				foreach (PluginInfo value2 in Chainloader.PluginInfos.Values)
				{
					if (Object.op_Implicit((Object)(object)((value2 != null) ? value2.Instance : null)) && ((object)value2.Instance).GetType().Assembly == assembly)
					{
						Add(list, value2.Metadata.Name);
						Add(list, value2.Metadata.GUID);
					}
				}
				FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (FieldInfo fieldInfo in fields)
				{
					if (LooksLikeSource(fieldInfo.Name) && !(fieldInfo.FieldType != typeof(string)))
					{
						try
						{
							Add(list, fieldInfo.GetValue(val) as string);
						}
						catch
						{
						}
					}
				}
				PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (PropertyInfo propertyInfo in properties)
				{
					if (LooksLikeSource(propertyInfo.Name) && !(propertyInfo.PropertyType != typeof(string)) && propertyInfo.CanRead)
					{
						try
						{
							Add(list, propertyInfo.GetValue(val, null) as string);
						}
						catch
						{
						}
					}
				}
			}
			Transform[] componentsInChildren2 = ((Component)item).GetComponentsInChildren<Transform>(true);
			foreach (Transform val2 in componentsInChildren2)
			{
				if (Object.op_Implicit((Object)(object)val2))
				{
					Add(list, ((Object)val2).name);
				}
			}
			foreach (PluginInfo value3 in Chainloader.PluginInfos.Values)
			{
				if (value3 != null && PluginIdentityMatches(list, value3.Metadata.Name, value3.Metadata.GUID))
				{
					Add(list, value3.Metadata.Name);
					Add(list, value3.Metadata.GUID);
				}
			}
			foreach (PluginInfo value4 in Chainloader.PluginInfos.Values)
			{
				if (!((Object)(object)((value4 != null) ? value4.Instance : null) == (Object)null))
				{
					Assembly assembly2 = ((object)value4.Instance).GetType().Assembly;
					if (RegistryMatches(list, GetRegistryStrings(assembly2)))
					{
						Add(list, value4.Metadata.Name);
						Add(list, value4.Metadata.GUID);
					}
				}
			}
			string text = string.Join(" ", list);
			Cache[instanceID] = text;
			return text;
		}

		internal static string GetModName(ItemDrop item)
		{
			if (!Object.op_Implicit((Object)(object)item))
			{
				return string.Empty;
			}
			return FindModName(Normalize(Get(item)));
		}

		internal static string GetModNameCached(ItemDrop item)
		{
			if (!Object.op_Implicit((Object)(object)item))
			{
				return string.Empty;
			}
			if (Cache.TryGetValue(((Object)item).GetInstanceID(), out var value))
			{
				return FindModName(Normalize(value));
			}
			return GetModNameFast(item);
		}

		internal static string GetModNameFast(ItemDrop item)
		{
			if (!Object.op_Implicit((Object)(object)item))
			{
				return string.Empty;
			}
			int instanceID = ((Object)item).GetInstanceID();
			if (FastModCache.TryGetValue(instanceID, out var value))
			{
				return value;
			}
			List<string> list = new List<string>();
			Add(list, ((Object)item).name);
			Add(list, ((Object)((Component)item).gameObject).name);
			try
			{
				Add(list, item.m_itemData?.m_shared?.m_name);
			}
			catch
			{
			}
			Component[] componentsInChildren = ((Component)item).GetComponentsInChildren<Component>(true);
			foreach (Component val in componentsInChildren)
			{
				if (!Object.op_Implicit((Object)(object)val))
				{
					continue;
				}
				Type type = ((object)val).GetType();
				Add(list, type.FullName);
				Add(list, type.Assembly.GetName().Name);
				Add(list, type.Namespace);
				foreach (PluginInfo value2 in Chainloader.PluginInfos.Values)
				{
					if (Object.op_Implicit((Object)(object)((value2 != null) ? value2.Instance : null)) && ((object)value2.Instance).GetType().Assembly == type.Assembly)
					{
						Add(list, value2.Metadata.Name);
						Add(list, value2.Metadata.GUID);
					}
				}
			}
			Transform[] componentsInChildren2 = ((Component)item).GetComponentsInChildren<Transform>(true);
			foreach (Transform val2 in componentsInChildren2)
			{
				if (Object.op_Implicit((Object)(object)val2))
				{
					Add(list, ((Object)val2).name);
				}
			}
			string text = FindModName(list);
			FastModCache[instanceID] = text;
			return text;
		}

		private static string FindModName(string source)
		{
			if (string.IsNullOrEmpty(source))
			{
				return string.Empty;
			}
			foreach (PluginInfo value2 in Chainloader.PluginInfos.Values)
			{
				if (value2 != null && value2.Metadata != null)
				{
					string text = value2.Metadata.Name ?? string.Empty;
					string value = value2.Metadata.GUID ?? string.Empty;
					string text2 = Normalize(text);
					string text3 = Normalize(value);
					if ((text2.Length >= 4 && source.Contains(text2)) || (text3.Length >= 4 && source.Contains(text3)))
					{
						return text;
					}
				}
			}
			return string.Empty;
		}

		private static string FindModName(List<string> candidates)
		{
			if (candidates == null || candidates.Count == 0)
			{
				return string.Empty;
			}
			StringBuilder stringBuilder = new StringBuilder();
			for (int i = 0; i < candidates.Count; i++)
			{
				if (i > 0)
				{
					stringBuilder.Append(' ');
				}
				stringBuilder.Append(candidates[i]);
			}
			return FindModName(Normalize(stringBuilder.ToString()));
		}

		private static bool PluginIdentityMatches(List<string> candidates, string name, string guid)
		{
			string text = Normalize(name);
			string text2 = Normalize(guid);
			if (text.Length < 4 && text2.Length < 4)
			{
				return false;
			}
			for (int i = 0; i < candidates.Count; i++)
			{
				string text3 = Normalize(candidates[i]);
				if (text3.Length >= 4)
				{
					if (text.Length >= 4 && text3.Contains(text))
					{
						return true;
					}
					if (text2.Length >= 4 && text3.Contains(text2))
					{
						return true;
					}
				}
			}
			return false;
		}

		private static bool RegistryMatches(List<string> candidates, List<string> registryStrings)
		{
			if (registryStrings == null || registryStrings.Count == 0)
			{
				return false;
			}
			for (int i = 0; i < candidates.Count; i++)
			{
				string text = Normalize(candidates[i]);
				if (text.Length < 6)
				{
					continue;
				}
				for (int j = 0; j < registryStrings.Count; j++)
				{
					string text2 = Normalize(registryStrings[j]);
					if (text2.Length >= 6)
					{
						string text3 = TrimCloneSuffix(text);
						string text4 = TrimCloneSuffix(text2);
						if (string.Equals(text3, text4, StringComparison.Ordinal) || text3.Contains(text4) || text4.Contains(text3))
						{
							return true;
						}
					}
				}
			}
			return false;
		}

		private static string TrimCloneSuffix(string value)
		{
			if (!value.EndsWith("clone", StringComparison.Ordinal) || value.Length <= 5)
			{
				return value;
			}
			return value.Substring(0, value.Length - 5);
		}

		private static List<string> GetRegistryStrings(Assembly assembly)
		{
			if (assembly == null)
			{
				return null;
			}
			if (RegistryCache.TryGetValue(assembly, out var value))
			{
				return value;
			}
			List<string> list = new List<string>();
			RegistryCache[assembly] = list;
			Type[] types;
			try
			{
				types = assembly.GetTypes();
			}
			catch (ReflectionTypeLoadException ex)
			{
				types = ex.Types;
			}
			if (types == null)
			{
				return list;
			}
			HashSet<int> visited = new HashSet<int>();
			foreach (Type type in types)
			{
				if (type == null)
				{
					continue;
				}
				FieldInfo[] fields;
				try
				{
					fields = type.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				}
				catch
				{
					continue;
				}
				foreach (FieldInfo fieldInfo in fields)
				{
					if (fieldInfo.IsLiteral)
					{
						continue;
					}
					string name = fieldInfo.Name;
					if (LooksLikeRegistry(type, name))
					{
						try
						{
							CollectRegistryStrings(fieldInfo.GetValue(null), list, visited, 0, assembly);
						}
						catch
						{
						}
					}
				}
			}
			return list;
		}

		private static bool LooksLikeRegistry(Type type, string fieldName)
		{
			string text = ((type?.Name ?? string.Empty) + " " + (fieldName ?? string.Empty)).ToLowerInvariant();
			if (!text.Contains("pack") && !text.Contains("prefab") && !text.Contains("registered"))
			{
				return text.Contains("item");
			}
			return true;
		}

		private static void CollectRegistryStrings(object value, List<string> output, HashSet<int> visited, int depth, Assembly owner)
		{
			if (value == null || depth > 3 || output.Count >= 2048)
			{
				return;
			}
			if (value is string value2)
			{
				Add(output, value2);
				return;
			}
			Object val = (Object)((value is Object) ? value : null);
			if (val != null)
			{
				Add(output, val.name);
				return;
			}
			Type type = value.GetType();
			if (type.IsPrimitive || type.IsEnum || type == typeof(decimal))
			{
				return;
			}
			int hashCode = RuntimeHelpers.GetHashCode(value);
			if (!visited.Add(hashCode))
			{
				return;
			}
			if (value is IEnumerable enumerable)
			{
				int num = 0;
				{
					foreach (object item in enumerable)
					{
						CollectRegistryStrings(item, output, visited, depth + 1, owner);
						if (++num >= 512)
						{
							break;
						}
					}
					return;
				}
			}
			if (type.Assembly != owner && depth > 0)
			{
				return;
			}
			FieldInfo[] fields;
			try
			{
				fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			}
			catch
			{
				return;
			}
			foreach (FieldInfo fieldInfo in fields)
			{
				if (!fieldInfo.IsStatic && !fieldInfo.FieldType.IsPointer && !typeof(Delegate).IsAssignableFrom(fieldInfo.FieldType))
				{
					try
					{
						CollectRegistryStrings(fieldInfo.GetValue(value), output, visited, depth + 1, owner);
					}
					catch
					{
					}
				}
			}
		}

		private static string Normalize(string value)
		{
			if (string.IsNullOrWhiteSpace(value))
			{
				return string.Empty;
			}
			string text = value.Normalize(NormalizationForm.FormD);
			StringBuilder stringBuilder = new StringBuilder(text.Length);
			for (int i = 0; i < text.Length; i++)
			{
				if (CharUnicodeInfo.GetUnicodeCategory(text[i]) != UnicodeCategory.NonSpacingMark && char.IsLetterOrDigit(text[i]))
				{
					stringBuilder.Append(char.ToLowerInvariant(text[i]));
				}
			}
			return stringBuilder.ToString();
		}

		private static bool LooksLikeSource(string name)
		{
			string text = name.ToLowerInvariant();
			if (!text.Contains("mod") && !text.Contains("plugin") && !text.Contains("source") && !text.Contains("author"))
			{
				return text.Contains("origin");
			}
			return true;
		}

		private static void Add(List<string> list, string value)
		{
			if (!string.IsNullOrWhiteSpace(value) && !list.Exists((string existing) => string.Equals(existing, value, StringComparison.OrdinalIgnoreCase)))
			{
				list.Add(value);
			}
		}
	}
	internal sealed class ConfigurationManagerAttributes
	{
		public string Category;

		public string DispName;

		public int? Order;

		public bool? Browsable;
	}
	[BepInPlugin("com.kimbauer.valheim.craftsearch", "Search Bar Plus", "2.0.1")]
	[BepInProcess("valheim.exe")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Id = "com.kimbauer.valheim.craftsearch";

		public const string Version = "2.0.1";

		internal static Plugin Instance;

		internal static SearchBar Bar;

		internal static string CraftSearchText = string.Empty;

		internal static string ChestSearchText = string.Empty;

		internal static ConfigEntry<bool> EnableCraftSearch;

		internal static ConfigEntry<bool> EnableCraftQuantity;

		internal static ConfigEntry<bool> KeepCraftSearchText;

		internal static ConfigEntry<bool> KeepChestSearchText;

		internal static ConfigEntry<bool> EnableModSearch;

		internal static ConfigEntry<bool> EnableChestSearch;

		internal static ConfigEntry<bool> EnableChestSort;

		internal static ConfigEntry<bool> EnableRecipeTypeFilters;

		internal static ConfigEntry<bool> KeepRecipeTypeFilters;

		internal static ConfigEntry<string> ExcludedRecipeCategories;

		internal static ConfigEntry<bool> EnableCraftDebugLogs;

		internal static ConfigEntry<bool> SuppressRecipeSelectionLog;

		private Harmony harmony;

		private static ConfigDescription UiDescription(string description, string category, int order, string displayName = null)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			return new ConfigDescription(description, (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Category = category,
					Order = order,
					DispName = displayName
				}
			});
		}

		private void Awake()
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c4: Expected O, but got Unknown
			Instance = this;
			ConfigEntry<bool> val = ((BaseUnityPlugin)this).Config.Bind<bool>("Features", "KeepSearchTextAcrossStations", true, new ConfigDescription("Legacy persistence setting retained for migration.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Category = "99 - Legacy",
					Order = -100,
					Browsable = false
				}
			}));
			EnableCraftSearch = ((BaseUnityPlugin)this).Config.Bind<bool>("Features", "EnableCraftSearch", true, UiDescription("Show and filter the recipe search field in the inventory, workbench, forge and other crafting panels.", "00 - Toggles", 100, "Enable Craft Search"));
			EnableCraftQuantity = ((BaseUnityPlugin)this).Config.Bind<bool>("Features", "EnableCraftQuantity", true, UiDescription("Replace the vanilla craft action with quantity controls, scaled requirements and the custom progress/cancel row. Requires a game restart after changing.", "00 - Toggles", 90, "Enable Quantity Crafting"));
			KeepCraftSearchText = ((BaseUnityPlugin)this).Config.Bind<bool>("Features", "KeepCraftSearchText", val.Value, UiDescription("Keep the crafting and station search text in memory until it is cleared or the world is left.", "10 - Search", 100, "Keep Craft Search Text"));
			KeepChestSearchText = ((BaseUnityPlugin)this).Config.Bind<bool>("Features", "KeepChestSearchText", val.Value, UiDescription("Keep the chest search text in memory until it is cleared or the world is left.", "30 - Chest", 90, "Keep Chest Search Text"));
			EnableModSearch = ((BaseUnityPlugin)this).Config.Bind<bool>("Features", "EnableModSearch", true, UiDescription("Enable JEI-style @mod item filtering. Use @ModName item or @\"Mod Name\" item.", "10 - Search", 90, "Enable Mod Name Search"));
			EnableChestSearch = ((BaseUnityPlugin)this).Config.Bind<bool>("Features", "EnableChestSearch", true, UiDescription("Show a separate search field inside opened chest and container panels.", "30 - Chest", 100, "Enable Chest Search"));
			EnableChestSort = ((BaseUnityPlugin)this).Config.Bind<bool>("Features", "EnableChestSort", true, UiDescription("Show the small sort button below the chest weight indicator and arrange contents alphabetically by localized item name.", "30 - Chest", 80, "Enable Chest Sort"));
			EnableRecipeTypeFilters = ((BaseUnityPlugin)this).Config.Bind<bool>("Features", "EnableRecipeTypeFilters", true, UiDescription("Show single-selection category and mod filter buttons below the repair button and use them to filter the recipe list in the inventory, containers and crafting stations.", "20 - Recipe Filters", 100, "Enable Recipe Type Filters"));
			KeepRecipeTypeFilters = ((BaseUnityPlugin)this).Config.Bind<bool>("Features", "KeepRecipeTypeFilters", true, UiDescription("Keep the selected recipe-type filters when the inventory or crafting interface is closed.", "20 - Recipe Filters", 90, "Keep Recipe Type Filters"));
			ExcludedRecipeCategories = ((BaseUnityPlugin)this).Config.Bind<string>("Features", "ExcludedRecipeCategories", string.Empty, UiDescription("Comma-separated category or mod names to omit from the filter buttons. Use Weapons, Armor, Consumables, Construction, Other, Mods, or a mod name; All is always kept.", "20 - Recipe Filters", 80, "Excluded Recipe Categories"));
			EnableCraftDebugLogs = ((BaseUnityPlugin)this).Config.Bind<bool>("Features", "EnableCraftDebugLogs", false, UiDescription("Write one-shot craft quantity diagnostics to the BepInEx log while investigating batch production.", "40 - Diagnostics", 90, "Enable Craft Debug Logs"));
			SuppressRecipeSelectionLog = ((BaseUnityPlugin)this).Config.Bind<bool>("Features", "SuppressRecipeSelectionLog", true, UiDescription("Hide the repetitive vanilla 'Setting selected recipe' diagnostic while keeping other logs intact. Requires a game restart after changing.", "40 - Diagnostics", 100, "Suppress Recipe Selection Log"));
			harmony = new Harmony("com.kimbauer.valheim.craftsearch");
			harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Search Bar Plus 2.0.1 loaded.");
		}

		internal void Report(Exception error)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)error);
		}

		internal static void LogInfo(string message)
		{
			Plugin instance = Instance;
			if (instance != null)
			{
				((BaseUnityPlugin)instance).Logger.LogInfo((object)message);
			}
		}

		internal static void LogWarning(string message)
		{
			Plugin instance = Instance;
			if (instance != null)
			{
				((BaseUnityPlugin)instance).Logger.LogWarning((object)message);
			}
		}

		internal static void CraftDebug(string message)
		{
			if (EnableCraftDebugLogs == null || EnableCraftDebugLogs.Value)
			{
				Plugin instance = Instance;
				if (instance != null)
				{
					((BaseUnityPlugin)instance).Logger.LogInfo((object)("[CraftDebug] " + message));
				}
			}
		}

		internal static void ClearSession()
		{
			CraftSearchText = string.Empty;
			ChestSearchText = string.Empty;
			if (Object.op_Implicit((Object)(object)Bar))
			{
				Bar.ClearAllTexts();
				if (KeepRecipeTypeFilters == null || !KeepRecipeTypeFilters.Value)
				{
					Bar.ClearRecipeTypeFilters();
				}
			}
		}

		private void OnDestroy()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			if (Object.op_Implicit((Object)(object)Bar))
			{
				Object.Destroy((Object)(object)Bar);
			}
			CraftSearchText = string.Empty;
			ChestSearchText = string.Empty;
			Instance = null;
		}
	}
	public sealed class SearchBar : MonoBehaviour
	{
		private sealed class RecipeTypeFilter
		{
			internal string Key;

			internal Button Button;

			internal Image Background;

			internal TMP_Text Label;

			internal TMP_Text Glyph;

			internal Image Icon;

			internal string Tooltip;

			internal Color NormalColor;
		}

		private static readonly MethodInfo Refresh = AccessTools.Method(typeof(InventoryGui), "UpdateCraftingPanel", (Type[])null, (Type[])null);

		private static readonly FieldInfo ContainerField = AccessTools.Field(typeof(InventoryGui), "m_container");

		private static readonly FieldInfo ContainerNameField = AccessTools.Field(typeof(InventoryGui), "m_containerName");

		private static readonly FieldInfo ContainerWeightField = AccessTools.Field(typeof(InventoryGui), "m_containerWeight");

		private static readonly FieldInfo CraftingField = AccessTools.Field(typeof(InventoryGui), "m_crafting");

		private static readonly MethodInfo InCraftTabMethod = AccessTools.Method(typeof(InventoryGui), "InCraftTab", (Type[])null, (Type[])null);

		private static readonly MethodInfo InUpgradeTabMethod = AccessTools.Method(typeof(InventoryGui), "InUpradeTab", (Type[])null, (Type[])null);

		private static readonly FieldInfo CraftTabField = AccessTools.Field(typeof(InventoryGui), "m_tabCraft");

		private static readonly FieldInfo UpgradeTabField = AccessTools.Field(typeof(InventoryGui), "m_tabUpgrade");

		private static readonly FieldInfo GridScrollbarField = AccessTools.Field(typeof(InventoryGrid), "m_scrollbar");

		private static readonly FieldInfo RepairButtonField = AccessTools.Field(typeof(InventoryGui), "m_repairButton");

		private static readonly FieldInfo CraftButtonField = AccessTools.Field(typeof(InventoryGui), "m_craftButton");

		private static readonly FieldInfo CraftCancelButtonField = AccessTools.Field(typeof(InventoryGui), "m_craftCancelButton");

		private static readonly FieldInfo CraftProgressPanelField = AccessTools.Field(typeof(InventoryGui), "m_craftProgressPanel");

		private static readonly FieldInfo CraftProgressBarField = AccessTools.Field(typeof(InventoryGui), "m_craftProgressBar");

		private static readonly FieldInfo GuiBarWidthField = AccessTools.Field(typeof(GuiBar), "m_width");

		private static readonly FieldInfo CraftTimerField = AccessTools.Field(typeof(InventoryGui), "m_craftTimer");

		private static readonly FieldInfo SelectedRecipeField = AccessTools.Field(typeof(InventoryGui), "m_selectedRecipe");

		private static readonly FieldInfo CraftRecipeField = AccessTools.Field(typeof(InventoryGui), "m_craftRecipe");

		private static readonly FieldInfo MultiCraftingField = AccessTools.Field(typeof(InventoryGui), "m_multiCrafting");

		private static readonly FieldInfo MultiCraftAmountField = AccessTools.Field(typeof(InventoryGui), "m_multiCraftAmount");

		private static readonly FieldInfo CraftDurationField = AccessTools.Field(typeof(InventoryGui), "m_craftDuration");

		private static readonly FieldInfo MultiCraftDurationField = AccessTools.Field(typeof(InventoryGui), "m_multiCraftDuration");

		private static readonly FieldInfo TouchMultiCraftingField = AccessTools.Field(typeof(InventoryGui), "m_touchMultiCrafting");

		private static readonly FieldInfo CraftUpgradeItemField = AccessTools.Field(typeof(InventoryGui), "m_craftUpgradeItem");

		private static readonly FieldInfo RecipeNameField = AccessTools.Field(typeof(InventoryGui), "m_recipeName");

		private static readonly FieldInfo RecipeDescriptionField = AccessTools.Field(typeof(InventoryGui), "m_recipeDecription");

		private static readonly FieldInfo RecipeRequirementListField = AccessTools.Field(typeof(InventoryGui), "m_recipeRequirementList");

		private static readonly FieldInfo ItemGridPositionField = AccessTools.Field(typeof(ItemData), "m_gridPos");

		private static readonly MethodInfo InventoryChangedMethod = AccessTools.Method(typeof(Inventory), "Changed", new Type[2]
		{
			typeof(bool),
			typeof(bool)
		}, (Type[])null);

		private static readonly MethodInfo GridUpdateGuiMethod = AccessTools.Method(typeof(InventoryGrid), "UpdateGui", new Type[2]
		{
			typeof(Player),
			typeof(ItemData)
		}, (Type[])null);

		private static readonly MethodInfo UpdateRecipeMethod = AccessTools.Method(typeof(InventoryGui), "UpdateRecipe", new Type[2]
		{
			typeof(Player),
			typeof(float)
		}, (Type[])null);

		private static readonly MethodInfo SetupRequirementListMethod = AccessTools.Method(typeof(InventoryGui), "SetupRequirementList", new Type[4]
		{
			typeof(int),
			typeof(Player),
			typeof(bool),
			typeof(int)
		}, (Type[])null);

		private static readonly MethodInfo CraftPressedMethod = AccessTools.Method(typeof(InventoryGui), "OnCraftPressed", (Type[])null, (Type[])null);

		private static readonly MethodInfo CraftCancelMethod = AccessTools.Method(typeof(InventoryGui), "OnCraftCancelPressed", (Type[])null, (Type[])null);

		private const float ChestSearchGap = 6f;

		private InventoryGui gui;

		private TMP_InputField input;

		private TMP_InputField chestInput;

		private TMP_Text placeholder;

		private TMP_Text chestPlaceholder;

		private RectTransform recipeList;

		private RectTransform scroll;

		private RectTransform containerRoot;

		private Transform craftParent;

		private Vector2 originalMax;

		private GameObject root;

		private GameObject chestRoot;

		private GameObject craftControls;

		private Button createButton;

		private Button quantityDownButton;

		private Button quantityUpButton;

		private TMP_InputField quantityInput;

		private Button chestSortButton;

		private RectTransform recipeTypeFilterRoot;

		private Button repairButton;

		private TMP_Text recipeTypeSample;

		private readonly List<RecipeTypeFilter> recipeTypeFilters = new List<RecipeTypeFilter>();

		private string selectedRecipeFilterKey;

		private bool recipeTypeFiltersDirty = true;

		private Button nativeCraftButton;

		private Button nativeCraftCancelButton;

		private Transform nativeCraftProgressPanel;

		private CanvasGroup nativeCraftCancelCanvasGroup;

		private bool nativeCraftCancelCanvasGroupCreated;

		private float nativeCraftCancelCanvasAlpha = 1f;

		private bool nativeCraftCancelCanvasInteractable = true;

		private bool nativeCraftCancelCanvasBlocksRaycasts = true;

		private bool craftInProgress;

		private bool progressLayoutCaptured;

		private bool progressCustomLayoutApplied;

		private bool progressMaskAdded;

		private Transform progressOriginalParent;

		private int progressOriginalSiblingIndex;

		private Vector2 progressOriginalAnchorMin;

		private Vector2 progressOriginalAnchorMax;

		private Vector2 progressOriginalPivot;

		private Vector2 progressOriginalSizeDelta;

		private Vector2 progressOriginalAnchoredPosition;

		private Vector3 progressOriginalLocalScale;

		private Quaternion progressOriginalLocalRotation;

		private float progressOriginalGuiBarWidth;

		private bool progressOriginalGuiBarWidthCaptured;

		private float progressOriginalBarRectWidth;

		private bool progressOriginalBarRectWidthCaptured;

		private CanvasGroup nativeCraftCanvasGroup;

		private bool nativeCraftCanvasGroupCreated;

		private bool nativeCraftCanvasVisualHidden;

		private float nativeCraftCanvasAlpha = 1f;

		private bool nativeCraftCanvasInteractable = true;

		private bool nativeCraftCanvasBlocksRaycasts = true;

		private bool craftControlsDirty = true;

		private int craftQuantity = 1;

		private int pendingCraftBatch;

		private Recipe pendingCraftRecipe;

		private bool nativeCraftStateCaptured;

		private bool originalMultiCrafting;

		private int originalMultiCraftAmount = 1;

		private bool customCraftDuration;

		private float originalMultiCraftDuration;

		private int nativeDoCraftingDepth;

		private bool stationLayoutApplied;

		private RectTransform chestGridRect;

		private RectTransform chestScrollbarRect;

		private Vector2 chestGridBasePosition;

		private Vector2 chestGridBaseSize;

		private Vector2 chestScrollbarBasePosition;

		private Vector2 chestScrollbarBaseSize;

		private Vector3 chestGridBaseTop;

		private Vector3 chestGridBaseBottom;

		private bool chestGridPositionCaptured;

		private bool chestScrollbarPositionCaptured;

		private bool lastContainerOpen;

		private bool craftDirty;

		private bool chestDirty;

		private bool hadPlayer;

		private string lastChestQuery;

		private bool lastInventoryVisible;

		private bool lastChestSearchVisible;

		private bool craftTabKnown;

		private bool lastCraftTab;

		private bool recipeScrollResetPending = true;

		private bool craftSearchLayoutDirty = true;

		private bool chestLayoutDirty = true;

		private string lastExcludedRecipeCategories;

		private Sprite weaponCategorySprite;

		private Sprite armorCategorySprite;

		private Sprite consumableCategorySprite;

		private Sprite hammerCategorySprite;

		private readonly Vector3[] recipeListCorners = (Vector3[])(object)new Vector3[4];

		private static readonly Vector3[] SharedCorners = (Vector3[])(object)new Vector3[4];

		private TMP_InputField pendingCtrlBackspaceField;

		private string pendingCtrlBackspaceText;

		private int pendingCtrlBackspaceCaret;

		private int pendingCtrlBackspaceAnchor;

		private const float RecipeTypeFilterSize = 28f;

		private const float RecipeTypeFilterGap = 3f;

		private const float RecipeTypeFilterOffset = 48f;

		private const int RecipeTypeFilterModRows = 20;

		private const string AllFilterKey = "category:all";

		private const string WeaponsFilterKey = "category:weapons";

		private const string ArmorFilterKey = "category:armor";

		private const string ConsumablesFilterKey = "category:consumables";

		private const string ConstructionFilterKey = "category:construction";

		private const string OtherFilterKey = "category:other";

		public string CraftQuery
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)input))
				{
					return Plugin.CraftSearchText;
				}
				return input.text;
			}
		}

		public string ChestQuery
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)chestInput))
				{
					return Plugin.ChestSearchText;
				}
				return chestInput.text;
			}
		}

		public string Query => CraftQuery;

		public bool Typing
		{
			get
			{
				if (IsCraftUiVisible() && ((Object.op_Implicit((Object)(object)input) && ((Component)input).gameObject.activeInHierarchy && input.isFocused) || (Object.op_Implicit((Object)(object)chestInput) && ((Component)chestInput).gameObject.activeInHierarchy && chestInput.isFocused) || (Object.op_Implicit((Object)(object)quantityInput) && ((Component)quantityInput).gameObject.activeInHierarchy && quantityInput.isFocused)))
				{
					return !IsGlobalShortcutPressed();
				}
				return false;
			}
		}

		internal bool IgnoreCraftModifier
		{
			get
			{
				if (Plugin.EnableCraftQuantity != null && Plugin.EnableCraftQuantity.Value && Object.op_Implicit((Object)(object)craftControls))
				{
					return craftControls.activeSelf;
				}
				return false;
			}
		}

		internal bool IsCustomProductionActive
		{
			get
			{
				if (Object.op_Implicit((Object)(object)craftControls) && craftControls.activeSelf)
				{
					return IsCraftTab();
				}
				return false;
			}
		}

		internal bool IsNativeDoCrafting => nativeDoCraftingDepth > 0;

		internal bool IsNestedNativeDoCrafting => nativeDoCraftingDepth > 1;

		private static bool IsGlobalShortcutPressed()
		{
			if (!Input.GetKey((KeyCode)9))
			{
				return Input.GetKey((KeyCode)27);
			}
			return true;
		}

		private bool IsCraftUiVisible()
		{
			if (InventoryGui.IsVisible())
			{
				return true;
			}
			object? obj = CraftingField?.GetValue(gui);
			RectTransform val = (RectTransform)((obj is RectTransform) ? obj : null);
			if (Object.op_Implicit((Object)(object)val))
			{
				return ((Component)val).gameObject.activeInHierarchy;
			}
			return false;
		}

		private bool IsCraftTab()
		{
			if (!Object.op_Implicit((Object)(object)gui))
			{
				return false;
			}
			try
			{
				if (InCraftTabMethod != null)
				{
					return (bool)InCraftTabMethod.Invoke(gui, null);
				}
				if (InUpgradeTabMethod != null)
				{
					return !(bool)InUpgradeTabMethod.Invoke(gui, null);
				}
			}
			catch (Exception error)
			{
				Plugin.Instance.Report(error);
			}
			bool? flag = ActiveState(CraftTabField?.GetValue(gui));
			bool? flag2 = ActiveState(UpgradeTabField?.GetValue(gui));
			if (flag.HasValue && flag2.HasValue && flag.Value != flag2.Value)
			{
				return flag.Value;
			}
			if (flag.HasValue)
			{
				return flag.Value;
			}
			if (flag2.HasValue)
			{
				return !flag2.Value;
			}
			return true;
		}

		private static bool? ActiveState(object value)
		{
			GameObject val = (GameObject)((value is GameObject) ? value : null);
			if (val != null)
			{
				return val.activeInHierarchy;
			}
			Component val2 = (Component)((value is Component) ? value : null);
			if (val2 != null)
			{
				return val2.gameObject.activeInHierarchy;
			}
			return null;
		}

		public void Initialize(InventoryGui owner)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Expected O, but got Unknown
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Expected O, but got Unknown
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_0270: Expected O, but got Unknown
			//IL_0272: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0294: Unknown result type (might be due to invalid IL or missing references)
			//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f6: Expected O, but got Unknown
			//IL_0415: Unknown result type (might be due to invalid IL or missing references)
			//IL_041a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0425: Unknown result type (might be due to invalid IL or missing references)
			//IL_042f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0430: Unknown result type (might be due to invalid IL or missing references)
			//IL_043a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0445: Unknown result type (might be due to invalid IL or missing references)
			//IL_044f: Unknown result type (might be due to invalid IL or missing references)
			//IL_045a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0464: Unknown result type (might be due to invalid IL or missing references)
			//IL_0484: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04de: Expected O, but got Unknown
			//IL_0532: Unknown result type (might be due to invalid IL or missing references)
			gui = owner;
			recipeList = (RectTransform)AccessTools.Field(typeof(InventoryGui), "m_recipeListRoot").GetValue(gui);
			ScrollRect componentInParent = ((Component)recipeList).GetComponentInParent<ScrollRect>();
			if (!Object.op_Implicit((Object)(object)componentInParent))
			{
				throw new InvalidOperationException("Recipe ScrollRect not found.");
			}
			scroll = (RectTransform)((Component)componentInParent).transform;
			craftParent = (Transform)(Object.op_Implicit((Object)(object)((Transform)scroll).parent) ? ((Transform)scroll).parent : (((object)/*isinst with value type is only supported in some contexts*/) ?? ((object)((Component)gui).transform)));
			originalMax = scroll.offsetMax;
			object obj = ContainerField?.GetValue(gui);
			containerRoot = (RectTransform)((obj is RectTransform) ? obj : null);
			if (!Object.op_Implicit((Object)(object)containerRoot))
			{
				GameObject val = (GameObject)((obj is GameObject) ? obj : null);
				if (val != null)
				{
					containerRoot = val.GetComponent<RectTransform>();
				}
			}
			if (!Object.op_Implicit((Object)(object)containerRoot))
			{
				Component val2 = (Component)((obj is Component) ? obj : null);
				if (val2 != null)
				{
					containerRoot = val2.GetComponent<RectTransform>();
				}
			}
			chestGridRect = (Object.op_Implicit((Object)(object)gui.ContainerGrid) ? ((Component)gui.ContainerGrid).GetComponent<RectTransform>() : null);
			object obj2;
			if (!Object.op_Implicit((Object)(object)gui.ContainerGrid))
			{
				obj2 = null;
			}
			else
			{
				object? obj3 = GridScrollbarField?.GetValue(gui.ContainerGrid);
				object? obj4 = ((obj3 is Scrollbar) ? obj3 : null);
				Transform obj5 = ((obj4 != null) ? ((Component)obj4).transform : null);
				obj2 = ((obj5 is RectTransform) ? obj5 : null);
			}
			chestScrollbarRect = (RectTransform)obj2;
			root = new GameObject("SearchBarPlus", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			root.transform.SetParent(craftParent, false);
			SetCraftLayout();
			TMP_Text val3 = ((Component)gui).GetComponentInChildren<TMP_Text>(true);
			if (!Object.op_Implicit((Object)(object)val3) || !Object.op_Implicit((Object)(object)val3.font))
			{
				val3 = FindTextSample();
			}
			GameObject val4 = new GameObject("TextArea", new Type[2]
			{
				typeof(RectTransform),
				typeof(RectMask2D)
			});
			val4.transform.SetParent(root.transform, false);
			RectTransform val5 = (RectTransform)val4.transform;
			val5.anchorMin = Vector2.zero;
			val5.anchorMax = Vector2.one;
			val5.offsetMin = new Vector2(10f, 0f);
			val5.offsetMax = new Vector2(-38f, 0f);
			TextMeshProUGUI val6 = Label("Text", val4.transform, val3);
			placeholder = (TMP_Text)(object)Label("Placeholder", val4.transform, val3);
			((TMP_Text)val6).fontSize = 17f;
			placeholder.fontSize = 17f;
			input = root.AddComponent<TMP_InputField>();
			input.textViewport = val5;
			input.textComponent = (TMP_Text)(object)val6;
			input.placeholder = (Graphic)(object)placeholder;
			((Selectable)input).targetGraphic = (Graphic)(object)root.GetComponent<Image>();
			input.lineType = (LineType)0;
			input.characterLimit = 100;
			input.richText = false;
			((UnityEvent<string>)(object)input.onValueChanged).AddListener((UnityAction<string>)OnQueryChanged);
			((UnityEvent<string>)(object)input.onSubmit).AddListener((UnityAction<string>)delegate
			{
				Blur();
			});
			input.SetTextWithoutNotify(Plugin.CraftSearchText);
			GameObject val7 = new GameObject("Clear", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Button)
			});
			val7.transform.SetParent(root.transform, false);
			RectTransform val8 = (RectTransform)val7.transform;
			val8.anchorMin = new Vector2(1f, 0f);
			val8.anchorMax = Vector2.one;
			val8.pivot = new Vector2(1f, 0.5f);
			val8.sizeDelta = new Vector2(32f, 0f);
			val8.anchoredPosition = Vector2.zero;
			((Graphic)val7.GetComponent<Image>()).color = new Color(0.25f, 0.22f, 0.16f);
			TextMeshProUGUI obj6 = Label("Label", val7.transform, val3);
			((TMP_Text)obj6).text = "×";
			((TMP_Text)obj6).fontSize = 17f;
			((TMP_Text)obj6).alignment = (TextAlignmentOptions)514;
			((UnityEvent)val7.GetComponent<Button>().onClick).AddListener(new UnityAction(ClearSearch));
			CreateChestSearch(val3);
			if (Plugin.EnableCraftQuantity.Value)
			{
				CreateCraftControls(val3);
			}
			CreateChestSortButton(val3);
			CreateRecipeTypeFilters(val3);
			RefreshLanguage();
			if (Object.op_Implicit((Object)(object)placeholder))
			{
				((Graphic)placeholder).color = new Color(0.75f, 0.71f, 0.63f);
			}
		}

		private TMP_Text FindTextSample()
		{
			TMP_Text[] array = (Object.op_Implicit((Object)(object)gui) ? ((Component)gui).GetComponentsInChildren<TMP_Text>(true) : null);
			if (array == null)
			{
				return null;
			}
			for (int i = 0; i < array.Length; i++)
			{
				if (Object.op_Implicit((Object)(object)array[i]) && Object.op_Implicit((Object)(object)array[i].font))
				{
					return array[i];
				}
			}
			return null;
		}

		private void CreateChestSearch(TMP_Text sample)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Expected O, but got Unknown
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Expected O, but got Unknown
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Expected O, but got Unknown
			//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0304: Unknown result type (might be due to invalid IL or missing references)
			//IL_030e: Unknown result type (might be due to invalid IL or missing references)
			//IL_032d: Unknown result type (might be due to invalid IL or missing references)
			//IL_036f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0379: Expected O, but got Unknown
			if (Object.op_Implicit((Object)(object)containerRoot))
			{
				chestRoot = new GameObject("ChestSearch", new Type[2]
				{
					typeof(RectTransform),
					typeof(Image)
				});
				chestRoot.transform.SetParent((Transform)(object)containerRoot, false);
				((Graphic)chestRoot.GetComponent<Image>()).color = new Color(0.08f, 0.07f, 0.06f, 0.96f);
				RectTransform val = (RectTransform)chestRoot.transform;
				val.anchorMin = new Vector2(0f, 1f);
				val.anchorMax = new Vector2(1f, 1f);
				val.pivot = new Vector2(0.5f, 1f);
				val.sizeDelta = new Vector2(-24f, 26f);
				val.anchoredPosition = new Vector2(0f, -42f);
				GameObject val2 = new GameObject("TextArea", new Type[2]
				{
					typeof(RectTransform),
					typeof(RectMask2D)
				});
				val2.transform.SetParent(chestRoot.transform, false);
				RectTransform val3 = (RectTransform)val2.transform;
				val3.anchorMin = Vector2.zero;
				val3.anchorMax = Vector2.one;
				val3.offsetMin = new Vector2(10f, 2f);
				val3.offsetMax = new Vector2(-38f, -2f);
				TextMeshProUGUI textComponent = Label("Text", val2.transform, sample);
				chestPlaceholder = (TMP_Text)(object)Label("Placeholder", val2.transform, sample);
				chestInput = chestRoot.AddComponent<TMP_InputField>();
				chestInput.textViewport = val3;
				chestInput.textComponent = (TMP_Text)(object)textComponent;
				chestInput.placeholder = (Graphic)(object)chestPlaceholder;
				((Selectable)chestInput).targetGraphic = (Graphic)(object)chestRoot.GetComponent<Image>();
				chestInput.lineType = (LineType)0;
				chestInput.characterLimit = 100;
				chestInput.richText = false;
				((UnityEvent<string>)(object)chestInput.onValueChanged).AddListener((UnityAction<string>)OnChestQueryChanged);
				((UnityEvent<string>)(object)chestInput.onSubmit).AddListener((UnityAction<string>)delegate
				{
					BlurChest();
				});
				chestInput.SetTextWithoutNotify(Plugin.ChestSearchText);
				GameObject val4 = new GameObject("Clear", new Type[3]
				{
					typeof(RectTransform),
					typeof(Image),
					typeof(Button)
				});
				val4.transform.SetParent(chestRoot.transform, false);
				RectTransform val5 = (RectTransform)val4.transform;
				val5.anchorMin = new Vector2(1f, 0f);
				val5.anchorMax = Vector2.one;
				val5.pivot = new Vector2(1f, 0.5f);
				val5.sizeDelta = new Vector2(32f, 0f);
				val5.anchoredPosition = Vector2.zero;
				((Graphic)val4.GetComponent<Image>()).color = new Color(0.25f, 0.22f, 0.16f);
				TextMeshProUGUI obj = Label("Label", val4.transform, sample);
				((TMP_Text)obj).text = "×";
				((TMP_Text)obj).alignment = (TextAlignmentOptions)514;
				((UnityEvent)val4.GetComponent<Button>().onClick).AddListener(new UnityAction(ClearChestSearch));
			}
		}

		private void CreateChestSortButton(TMP_Text sample)
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Expected O, but got Unknown
			if (Object.op_Implicit((Object)(object)containerRoot))
			{
				Button source = (Button)(((object)nativeCraftButton) ?? ((object)/*isinst with value type is only supported in some contexts*/));
				chestSortButton = CloneCraftButton((Transform)(object)containerRoot, source, sample);
				if (Object.op_Implicit((Object)(object)chestSortButton))
				{
					((Object)chestSortButton).name = "SearchBarPlusChestSort";
					((UnityEvent)chestSortButton.onClick).AddListener(new UnityAction(SortContainerByName));
					((Component)chestSortButton).gameObject.SetActive(false);
					SetChestSortLabel();
				}
			}
		}

		private void CreateRecipeTypeFilters(TMP_Text sample)
		{
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Expected O, but got Unknown
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			recipeTypeSample = sample;
			ref Button reference = ref repairButton;
			object? obj = RepairButtonField?.GetValue(gui);
			reference = (Button)((obj is Button) ? obj : null);
			Transform val = ((Object.op_Implicit((Object)(object)repairButton) && Object.op_Implicit((Object)(object)((Component)repairButton).transform.parent)) ? ((Component)repairButton).transform.parent : craftParent);
			if (Object.op_Implicit((Object)(object)val))
			{
				GameObject val2 = new GameObject("SearchBarPlusRecipeTypeFilters", new Type[1] { typeof(RectTransform) });
				recipeTypeFilterRoot = val2.GetComponent<RectTransform>();
				((Transform)recipeTypeFilterRoot).SetParent(val, false);
				recipeTypeFilterRoot.pivot = new Vector2(0.5f, 0.5f);
				recipeTypeFilterRoot.anchorMin = new Vector2(0.5f, 0.5f);
				recipeTypeFilterRoot.anchorMax = new Vector2(0.5f, 0.5f);
				recipeTypeFilterRoot.sizeDelta = new Vector2(0f, 28f);
				((Component)recipeTypeFilterRoot).gameObject.SetActive(false);
				if (string.IsNullOrEmpty(selectedRecipeFilterKey))
				{
					selectedRecipeFilterKey = "category:all";
				}
				lastExcludedRecipeCategories = ((Plugin.ExcludedRecipeCategories != null) ? (Plugin.ExcludedRecipeCategories.Value ?? string.Empty) : string.Empty);
				EnsureBuiltInRecipeTypeFilters();
				recipeTypeFiltersDirty = true;
			}
		}

		private void EnsureBuiltInRecipeTypeFilters()
		{
			EnsureRecipeTypeFilter("category:all", "All");
			EnsureRecipeTypeFilter("category:weapons", "Weapons");
			EnsureRecipeTypeFilter("category:armor", "Armor");
			EnsureRecipeTypeFilter("category:consumables", "Consumables");
			EnsureRecipeTypeFilter("category:construction", "Construction");
			EnsureRecipeTypeFilter("category:other", "Other");
			SortRecipeTypeFilters();
		}

		internal void RegisterRecipeType(Recipe recipe)
		{
			if (!Object.op_Implicit((Object)(object)recipe) || !Object.op_Implicit((Object)(object)recipe.m_item) || recipe.m_item.m_itemData == null || recipe.m_item.m_itemData.m_shared == null || !Object.op_Implicit((Object)(object)recipeTypeFilterRoot))
			{
				return;
			}
			int count = recipeTypeFilters.Count;
			string text = ((object)Unsafe.As<ItemType, ItemType>(ref recipe.m_item.m_itemData.m_shared.m_itemType)/*cast due to .constrained prefix*/).ToString();
			if (!string.IsNullOrEmpty(text))
			{
				bool flag = false;
				if (IsWeaponType(text))
				{
					EnsureRecipeTypeFilter("category:weapons", "Weapons");
					flag = true;
				}
				if (IsArmorType(text))
				{
					EnsureRecipeTypeFilter("category:armor", "Armor");
					flag = true;
				}
				if (IsConsumableType(text))
				{
					EnsureRecipeTypeFilter("category:consumables", "Consumables");
					flag = true;
				}
				if (IsConstructionType(text))
				{
					EnsureRecipeTypeFilter("category:construction", "Construction");
					flag = true;
				}
				if (!flag)
				{
					EnsureRecipeTypeFilter("category:other", "Other");
				}
				string modNameFast = ModSourceResolver.GetModNameFast(recipe.m_item);
				if (!string.IsNullOrWhiteSpace(modNameFast))
				{
					RegisterRecipeModSource(modNameFast);
				}
				if (recipeTypeFilters.Count != count)
				{
					recipeTypeFiltersDirty = true;
				}
			}
		}

		internal void RegisterRecipeModSource(string modName)
		{
			if (!string.IsNullOrWhiteSpace(modName) && Object.op_Implicit((Object)(object)recipeTypeFilterRoot))
			{
				string key = "mod:" + modName;
				if (FindRecipeTypeFilter(key) == null && EnsureRecipeTypeFilter(key, modName) != null)
				{
					recipeTypeFiltersDirty = true;
				}
			}
		}

		private RecipeTypeFilter EnsureRecipeTypeFilter(string key, string tooltip)
		{
			if (!Object.op_Implicit((Object)(object)recipeTypeFilterRoot) || string.IsNullOrEmpty(key))
			{
				return null;
			}
			if (IsRecipeTypeFilterExcluded(key, tooltip))
			{
				return null;
			}
			RecipeTypeFilter recipeTypeFilter = FindRecipeTypeFilter(key);
			if (recipeTypeFilter != null)
			{
				return recipeTypeFilter;
			}
			recipeTypeFilter = new RecipeTypeFilter
			{
				Key = key,
				Tooltip = tooltip
			};
			CreateRecipeTypeFilter(recipeTypeFilter);
			recipeTypeFilters.Add(recipeTypeFilter);
			SortRecipeTypeFilters();
			return recipeTypeFilter;
		}

		private void SortRecipeTypeFilters()
		{
			recipeTypeFilters.Sort(delegate(RecipeTypeFilter left, RecipeTypeFilter right)
			{
				if (left == right)
				{
					return 0;
				}
				if (left == null)
				{
					return 1;
				}
				if (right == null)
				{
					return -1;
				}
				int num = BaseRecipeTypeOrder(left.Key);
				int num2 = BaseRecipeTypeOrder(right.Key);
				return (num != num2) ? num.CompareTo(num2) : string.Compare(left.Tooltip, right.Tooltip, StringComparison.OrdinalIgnoreCase);
			});
		}

		private static int BaseRecipeTypeOrder(string key)
		{
			if (string.Equals(key, "category:all", StringComparison.OrdinalIgnoreCase))
			{
				return 0;
			}
			if (string.Equals(key, "category:weapons", StringComparison.OrdinalIgnoreCase))
			{
				return 1;
			}
			if (string.Equals(key, "category:armor", StringComparison.OrdinalIgnoreCase))
			{
				return 2;
			}
			if (string.Equals(key, "category:consumables", StringComparison.OrdinalIgnoreCase))
			{
				return 3;
			}
			if (string.Equals(key, "category:construction", StringComparison.OrdinalIgnoreCase))
			{
				return 4;
			}
			if (string.Equals(key, "category:other", StringComparison.OrdinalIgnoreCase))
			{
				return 5;
			}
			return 100;
		}

		private static bool IsWeaponType(string typeName)
		{
			if (typeName.IndexOf("Weapon", StringComparison.OrdinalIgnoreCase) < 0 && !string.Equals(typeName, "Bow", StringComparison.OrdinalIgnoreCase) && !string.Equals(typeName, "Ammo", StringComparison.OrdinalIgnoreCase))
			{
				return string.Equals(typeName, "Torch", StringComparison.OrdinalIgnoreCase);
			}
			return true;
		}

		private static bool IsArmorType(string typeName)
		{
			if (!string.Equals(typeName, "Shield", StringComparison.OrdinalIgnoreCase) && !string.Equals(typeName, "Helmet", StringComparison.OrdinalIgnoreCase) && !string.Equals(typeName, "Chest", StringComparison.OrdinalIgnoreCase) && !string.Equals(typeName, "Legs", StringComparison.OrdinalIgnoreCase) && !string.Equals(typeName, "Shoulder", StringComparison.OrdinalIgnoreCase))
			{
				return string.Equals(typeName, "Hands", StringComparison.OrdinalIgnoreCase);
			}
			return true;
		}

		private static bool IsConsumableType(string typeName)
		{
			return string.Equals(typeName, "Consumable", StringComparison.OrdinalIgnoreCase);
		}

		private static bool IsConstructionType(string typeName)
		{
			if (typeName.IndexOf("Build", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return string.Equals(typeName, "BuildPiece", StringComparison.OrdinalIgnoreCase);
			}
			return true;
		}

		private RecipeTypeFilter FindRecipeTypeFilter(string key)
		{
			for (int i = 0; i < recipeTypeFilters.Count; i++)
			{
				if (string.Equals(recipeTypeFilters[i].Key, key, StringComparison.OrdinalIgnoreCase))
				{
					return recipeTypeFilters[i];
				}
			}
			return null;
		}

		private static bool IsRecipeTypeFilterExcluded(string key, string label)
		{
			if (string.Equals(key, "category:all", StringComparison.OrdinalIgnoreCase))
			{
				return false;
			}
			string text = ((Plugin.ExcludedRecipeCategories != null) ? Plugin.ExcludedRecipeCategories.Value : string.Empty);
			if (string.IsNullOrWhiteSpace(text))
			{
				return false;
			}
			string[] array = text.Split(new char[5] { ',', ';', '|', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
			for (int i = 0; i < array.Length; i++)
			{
				string text2 = array[i].Trim().Trim('"', '\'');
				if (text2.Length == 0)
				{
					continue;
				}
				if (IsModFilter(key))
				{
					if (string.Equals(text2, "mods", StringComparison.OrdinalIgnoreCase))
					{
						return true;
					}
					if (text2.StartsWith("mod:", StringComparison.OrdinalIgnoreCase))
					{
						text2 = text2.Substring(4).Trim();
					}
					if (text2.Length > 0 && SearchText.Matches(label, null, text2))
					{
						return true;
					}
				}
				else
				{
					string name = (key.StartsWith("category:", StringComparison.OrdinalIgnoreCase) ? key.Substring("category:".Length) : key);
					if (SearchText.Matches(label, null, text2) || SearchText.Matches(name, null, text2))
					{
						return true;
					}
				}
			}
			return false;
		}

		private void CreateRecipeTypeFilter(RecipeTypeFilter filter)
		{
			//IL_00cd: 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_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0316: Expected O, but got Unknown
			Button val = (Button)(chestSortButton ?? repairButton ?? ((object)nativeCraftButton) ?? ((object)/*isinst with value type is only supported in some contexts*/));
			Button val2 = CloneCraftButton((Transform)(object)recipeTypeFilterRoot, val, recipeTypeSample);
			if (Object.op_Implicit((Object)(object)val2))
			{
				((Object)val2).name = "SearchBarPlusRecipeType_" + filter.Key;
				filter.Button = val2;
				filter.Background = ((Component)val2).GetComponent<Image>();
				filter.NormalColor = (Object.op_Implicit((Object)(object)filter.Background) ? ((Graphic)filter.Background).color : Color.white);
				filter.Label = ((Component)val2).GetComponentInChildren<TMP_Text>(true);
				if (Object.op_Implicit((Object)(object)filter.Label))
				{
					((Component)filter.Label).gameObject.SetActive(false);
				}
				filter.Glyph = (TMP_Text)(object)Label("Glyph", ((Component)val2).transform, recipeTypeSample);
				filter.Glyph.alignment = (TextAlignmentOptions)514;
				filter.Glyph.fontSize = (Object.op_Implicit((Object)(object)recipeTypeSample) ? Mathf.Max(18f, recipeTypeSample.fontSize * 1.1f) : 20f);
				if (string.Equals(filter.Key, "category:all", StringComparison.OrdinalIgnoreCase))
				{
					filter.Glyph.fontSize = (Object.op_Implicit((Object)(object)recipeTypeSample) ? Mathf.Min(12f, recipeTypeSample.fontSize * 0.65f) : 11f);
				}
				((Graphic)filter.Glyph).raycastTarget = false;
				filter.Glyph.text = RecipeTypeGlyph(filter.Key, filter.Tooltip, filter.Glyph);
				filter.Icon = CreateGeneratedCategoryIcon(filter.Key, ((Component)val2).transform);
				if (Object.op_Implicit((Object)(object)filter.Icon))
				{
					((Component)filter.Glyph).gameObject.SetActive(false);
				}
				UITooltip val3 = ((Component)val2).GetComponent<UITooltip>();
				if (!Object.op_Implicit((Object)(object)val3))
				{
					val3 = ((Component)val2).gameObject.AddComponent<UITooltip>();
				}
				val3.m_text = LocalizedRecipeTypeTooltip(filter);
				Button val4 = repairButton ?? nativeCraftButton ?? val;
				UITooltip val5 = (Object.op_Implicit((Object)(object)val4) ? ((Component)val4).GetComponent<UITooltip>() : null);
				if (Object.op_Implicit((Object)(object)val5))
				{
					val3.m_tooltipPrefab = val5.m_tooltipPrefab;
					val3.m_gamepadFocusObject = val5.m_gamepadFocusObject;
				}
				((Component)val2).gameObject.AddComponent<DelayedRecipeTooltip>().Configure(val3, 1f);
				((UnityEvent)val2.onClick).AddListener((UnityAction)delegate
				{
					ToggleRecipeType(filter.Key);
				});
				ApplyRecipeTypeVisual(filter);
			}
		}

		private Image CreateGeneratedCategoryIcon(string key, Transform parent)
		{
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			Sprite val = null;
			if (string.Equals(key, "category:weapons", StringComparison.OrdinalIgnoreCase))
			{
				val = weaponCategorySprite ?? (weaponCategorySprite = CreateWeaponsSprite());
			}
			else if (string.Equals(key, "category:armor", StringComparison.OrdinalIgnoreCase))
			{
				val = armorCategorySprite ?? (armorCategorySprite = CreateArmorSprite());
			}
			else if (string.Equals(key, "category:consumables", StringComparison.OrdinalIgnoreCase))
			{
				val = consumableCategorySprite ?? (consumableCategorySprite = CreateConsumableSprite());
			}
			else if (string.Equals(key, "category:construction", StringComparison.OrdinalIgnoreCase))
			{
				val = hammerCategorySprite ?? (hammerCategorySprite = CreateHammerSprite());
			}
			if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)parent))
			{
				return null;
			}
			GameObject val2 = new GameObject("Icon", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val2.transform.SetParent(parent, false);
			RectTransform val3 = (RectTransform)val2.transform;
			val3.anchorMin = new Vector2(0.12f, 0.12f);
			val3.anchorMax = new Vector2(0.88f, 0.88f);
			val3.offsetMin = Vector2.zero;
			val3.offsetMax = Vector2.zero;
			Image component = val2.GetComponent<Image>();
			component.sprite = val;
			component.preserveAspect = true;
			((Graphic)component).raycastTarget = false;
			return component;
		}

		private static Sprite CreateArmorSprite()
		{
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			Texture2D obj = NewCategoryTexture("SearchBarPlusArmorIcon", 48);
			Color32 color = default(Color32);
			((Color32)(ref color))..ctor((byte)43, (byte)49, (byte)58, byte.MaxValue);
			Color32 color2 = default(Color32);
			((Color32)(ref color2))..ctor((byte)54, (byte)126, (byte)185, byte.MaxValue);
			Color32 color3 = default(Color32);
			((Color32)(ref color3))..ctor((byte)130, (byte)211, (byte)239, byte.MaxValue);
			Color32 color4 = default(Color32);
			((Color32)(ref color4))..ctor((byte)27, (byte)67, (byte)116, byte.MaxValue);
			Color32 color5 = default(Color32);
			((Color32)(ref color5))..ctor((byte)239, (byte)177, (byte)47, byte.MaxValue);
			DrawRect(obj, 15, 11, 33, 35, color);
			DrawRect(obj, 18, 14, 30, 33, color2);
			DrawRect(obj, 10, 28, 19, 39, color);
			DrawRect(obj, 29, 28, 38, 39, color);
			DrawRect(obj, 12, 30, 18, 37, color2);
			DrawRect(obj, 30, 30, 36, 37, color2);
			DrawLine(obj, 16, 36, 32, 36, color, 4);
			DrawLine(obj, 18, 14, 14, 9, color, 4);
			DrawLine(obj, 30, 14, 34, 9, color, 4);
			DrawRect(obj, 21, 11, 27, 17, color);
			DrawRect(obj, 23, 13, 25, 16, color4);
			DrawLine(obj, 24, 18, 24, 31, color3, 2);
			DrawLine(obj, 19, 16, 19, 30, color4, 1);
			DrawLine(obj, 24, 18, 24, 31, color5, 1);
			obj.Apply(false, false);
			return Sprite.Create(obj, new Rect(0f, 0f, 48f, 48f), new Vector2(0.5f, 0.5f), 48f);
		}

		private static Sprite CreateWeaponsSprite()
		{
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			Texture2D obj = NewCategoryTexture("SearchBarPlusWeaponsIcon", 48);
			Color32 color = default(Color32);
			((Color32)(ref color))..ctor((byte)42, (byte)38, (byte)35, byte.MaxValue);
			Color32 color2 = default(Color32);
			((Color32)(ref color2))..ctor((byte)172, (byte)190, (byte)207, byte.MaxValue);
			Color32 color3 = default(Color32);
			((Color32)(ref color3))..ctor((byte)239, (byte)246, (byte)250, byte.MaxValue);
			Color32 color4 = default(Color32);
			((Color32)(ref color4))..ctor((byte)143, (byte)79, (byte)35, byte.MaxValue);
			Color32 color5 = default(Color32);
			((Color32)(ref color5))..ctor((byte)239, (byte)177, (byte)47, byte.MaxValue);
			DrawLine(obj, 11, 10, 37, 36, color, 7);
			DrawLine(obj, 37, 10, 11, 36, color, 7);
			DrawLine(obj, 14, 13, 35, 34, color2, 4);
			DrawLine(obj, 34, 13, 13, 34, color2, 4);
			DrawLine(obj, 16, 15, 33, 32, color3, 1);
			DrawLine(obj, 32, 15, 15, 32, color3, 1);
			DrawLine(obj, 8, 8, 16, 16, color4, 4);
			DrawLine(obj, 40, 8, 32, 16, color4, 4);
			DrawLine(obj, 8, 16, 19, 16, color5, 3);
			DrawLine(obj, 29, 16, 40, 16, color5, 3);
			obj.Apply(false, false);
			return Sprite.Create(obj, new Rect(0f, 0f, 48f, 48f), new Vector2(0.5f, 0.5f), 48f);
		}

		private static Sprite CreateConsumableSprite()
		{
			//IL_0096: 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_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: 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_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			Texture2D obj = NewCategoryTexture("SearchBarPlusConsumablesIcon", 48);
			Color32 color = default(Color32);
			((Color32)(ref color))..ctor((byte)48, (byte)37, (byte)32, byte.MaxValue);
			Color32 color2 = default(Color32);
			((Color32)(ref color2))..ctor((byte)111, (byte)205, (byte)220, byte.MaxValue);
			Color32 color3 = default(Color32);
			((Color32)(ref color3))..ctor((byte)226, (byte)72, (byte)64, byte.MaxValue);
			Color32 color4 = default(Color32);
			((Color32)(ref color4))..ctor((byte)154, (byte)32, (byte)47, byte.MaxValue);
			Color32 color5 = default(Color32);
			((Color32)(ref color5))..ctor(byte.MaxValue, (byte)225, (byte)122, byte.MaxValue);
			Color32 color6 = default(Color32);
			((Color32)(ref color6))..ctor((byte)184, (byte)116, (byte)56, byte.MaxValue);
			DrawRect(obj, 20, 35, 28, 43, color);
			DrawRect(obj, 21, 36, 27, 42, color6);
			DrawRect(obj, 14, 12, 34, 36, color);
			DrawRect(obj, 17, 15, 31, 33, color2);
			DrawRect(obj, 16, 22, 32, 34, color4);
			DrawRect(obj, 17, 18, 31, 29, color3);
			DrawLine(obj, 18, 30, 30, 30, color5, 2);
			DrawRect(obj, 20, 22, 24, 29, color5);
			DrawLine(obj, 15, 14, 19, 10, color, 4);
			DrawLine(obj, 33, 14, 29, 10, color, 4);
			obj.Apply(false, false);
			return Sprite.Create(obj, new Rect(0f, 0f, 48f, 48f), new Vector2(0.5f, 0.5f), 48f);
		}

		private static Sprite CreateHammerSprite()
		{
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			Texture2D obj = NewCategoryTexture("SearchBarPlusHammerIcon", 48);
			Color32 color = default(Color32);
			((Color32)(ref color))..ctor((byte)42, (byte)38, (byte)35, byte.MaxValue);
			Color32 color2 = default(Color32);
			((Color32)(ref color2))..ctor((byte)143, (byte)79, (byte)35, byte.MaxValue);
			Color32 color3 = default(Color32);
			((Color32)(ref color3))..ctor((byte)222, (byte)147, (byte)72, byte.MaxValue);
			Color32 color4 = default(Color32);
			((Color32)(ref color4))..ctor((byte)145, (byte)153, (byte)162, byte.MaxValue);
			Color32 color5 = default(Color32);
			((Color32)(ref color5))..ctor((byte)225, (byte)231, (byte)236, byte.MaxValue);
			DrawLine(obj, 17, 5, 24, 31, color, 9);
			DrawLine(obj, 17, 6, 24, 31, color2, 6);
			DrawLine(obj, 16, 7, 23, 30, color3, 1);
			DrawRect(obj, 20, 26, 28, 33, color);
			DrawRect(obj, 7, 27, 40, 39, color);
			DrawRect(obj, 10, 29, 37, 37, color4);
			DrawRect(obj, 10, 34, 37, 37, color5);
			DrawRect(obj, 4, 30, 11, 37, color);
			DrawRect(obj, 6, 31, 11, 36, color4);
			DrawRect(obj, 36, 28, 42, 38, color);
			DrawRect(obj, 37, 30, 40, 36, color4);
			obj.Apply(false, false);
			return Sprite.Create(obj, new Rect(0f, 0f, 48f, 48f), new Vector2(0.5f, 0.5f), 48f);
		}

		private static Texture2D NewCategoryTexture(string name, int size)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Expected O, but got Unknown
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(size, size, (TextureFormat)4, false);
			((Object)val).name = name;
			((Texture)val).filterMode = (FilterMode)0;
			Color32 val2 = default(Color32);
			((Color32)(ref val2))..ctor((byte)0, (byte)0, (byte)0, (byte)0);
			Color32[] array = (Color32[])(object)new Color32[size * size];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = val2;
			}
			val.SetPixels32(array);
			val.Apply(false, false);
			return val;
		}

		private static void DrawRect(Texture2D texture, int left, int bottom, int right, int top, Color32 color)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)texture))
			{
				return;
			}
			left = Mathf.Clamp(left, 0, ((Texture)texture).width - 1);
			right = Mathf.Clamp(right, 0, ((Texture)texture).width);
			bottom = Mathf.Clamp(bottom, 0, ((Texture)texture).height - 1);
			top = Mathf.Clamp(top, 0, ((Texture)texture).height);
			for (int i = bottom; i < top; i++)
			{
				for (int j = left; j < right; j++)
				{
					texture.SetPixel(j, i, Color32.op_Implicit(color));
				}
			}
		}

		private static void DrawLine(Texture2D texture, int x0, int y0, int x1, int y1, Color32 color, int thickness)
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			int num = Mathf.Max(Mathf.Abs(x1 - x0), Mathf.Abs(y1 - y0));
			for (int i = 0; i <= num; i++)
			{
				float num2 = ((num == 0) ? 0f : ((float)i / (float)num));
				int num3 = Mathf.RoundToInt(Mathf.Lerp((float)x0, (float)x1, num2));
				int num4 = Mathf.RoundToInt(Mathf.Lerp((float)y0, (float)y1, num2));
				DrawRect(texture, num3 - thickness / 2, num4 - thickness / 2, num3 + (thickness + 1) / 2, num4 + (thickness + 1) / 2, color);
			}
		}

		private static string RecipeTypeGlyph(string key, string tooltip, TMP_Text target)
		{
			if (string.Equals(key, "category:all", StringComparison.OrdinalIgnoreCase))
			{
				return "All";
			}
			if (string.Equals(key, "category:weapons", StringComparison.OrdinalIgnoreCase))
			{
				return "⚔";
			}
			if (string.Equals(key, "category:armor", StringComparison.OrdinalIgnoreCase))
			{
				return SupportedGlyph(target, "⛨", "A");
			}
			if (string.Equals(key, "category:consumables", StringComparison.OrdinalIgnoreCase))
			{
				return "✚";
			}
			if (string.Equals(key, "category:construction", StringComparison.OrdinalIgnoreCase))
			{
				return SupportedGlyph(target, "⚒", "H");
			}
			if (string.Equals(key, "category:other", StringComparison.OrdinalIgnoreCase))
			{
				return "⋯";
			}
			if (key.StartsWith("mod:", StringComparison.OrdinalIgnoreCase))
			{
				string text = key.Substring(4).Trim();
				if (text.Length <= 0)
				{
					return "M";
				}
				return SupportedGlyph(target, text.Substring(0, 1).ToUpperInvariant(), "M");
			}
			if (tooltip.Length <= 0)
			{
				return "?";
			}
			return SupportedGlyph(target, tooltip.Substring(0, 1).ToUpperInvariant(), "?");
		}

		private static string SupportedGlyph(TMP_Text target, string preferred, string fallback)
		{
			TMP_FontAsset val = (Object.op_Implicit((Object)(object)target) ? target.font : null);
			if ((Object)(object)val == (Object)null || string.IsNullOrEmpty(preferred))
			{
				return fallback;
			}
			for (int i = 0; i < preferred.Length; i++)
			{
				if (!val.HasCharacter(preferred[i], true, false))
				{
					return fallback;
				}
			}
			return preferred;
		}

		private static string LocalizedRecipeTypeTooltip(RecipeTypeFilter filter)
		{
			return Translations.RecipeFilter((Localization.instance != null) ? Localization.instance.GetSelectedLanguage() : "English", filter.Key, filter.Tooltip);
		}

		private void ToggleRecipeType(string key)
		{
			if (string.Equals(key, "category:all", StringComparison.OrdinalIgnoreCase) || string.Equals(selectedRecipeFilterKey, key, StringComparison.OrdinalIgnoreCase))
			{
				selectedRecipeFilterKey = "category:all";
			}
			else
			{
				selectedRecipeFilterKey = key;
			}
			for (int i = 0; i < recipeTypeFilters.Count; i++)
			{
				ApplyRecipeTypeVisual(recipeTypeFilters[i]);
			}
			craftDirty = true;
		}

		internal void ClearRecipeTypeFilters()
		{
			if (!string.Equals(selectedRecipeFilterKey, "category:all", StringComparison.OrdinalIgnoreCase))
			{
				selectedRecipeFilterKey = "category:all";
				for (int i = 0; i < recipeTypeFilters.Count; i++)
				{
					ApplyRecipeTypeVisual(recipeTypeFilters[i]);
				}
				craftDirty = true;
			}
		}

		private void ApplyRecipeTypeVisual(RecipeTypeFilter filter)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			if (filter != null)
			{
				bool flag = string.Equals(selectedRecipeFilterKey, filter.Key, StringComparison.OrdinalIgnoreCase);
				if (Object.op_Implicit((Object)(object)filter.Background))
				{
					((Graphic)filter.Background).color = (Color)(flag ? filter.NormalColor : new Color(0.42f, 0.42f, 0.42f, 0.82f));
				}
				if (Object.op_Implicit((Object)(object)filter.Glyph))
				{
					((Graphic)filter.Glyph).color = (Color)(flag ? Color.white : new Color(0.5f, 0.5f, 0.5f, 1f));
				}
				if (Object.op_Implicit((Object)(object)filter.Icon))
				{
					((Graphic)filter.Icon).color = (Color)(flag ? Color.white : new Color(0.5f, 0.5f, 0.5f, 1f));
				}
			}
		}

		private void SyncRecipeTypeFilterConfiguration()
		{
			if (!Object.op_Implicit((Object)(object)recipeTypeFilterRoot) || Plugin.ExcludedRecipeCategories == null)
			{
				return;
			}
			string a = Plugin.ExcludedRecipeCategories.Value ?? string.Empty;
			if (string.Equals(a, lastExcludedRecipeCategories, StringComparison.Ordinal))
			{
				return;
			}
			lastExcludedRecipeCategories = a;
			for (int num = recipeTypeFilters.Count - 1; num >= 0; num--)
			{
				RecipeTypeFilter recipeTypeFilter = recipeTypeFilters[num];
				if (recipeTypeFilter != null && IsRecipeTypeFilterExcluded(recipeTypeFilter.Key, recipeTypeFilter.Tooltip))
				{
					if (Object.op_Implicit((Object)(object)recipeTypeFilter.Button))
					{
						Object.Destroy((Object)(object)((Component)recipeTypeFilter.Button).gameObject);
					}
					recipeTypeFilters.RemoveAt(num);
				}
			}
			EnsureBuiltInRecipeTypeFilters();
			if (FindRecipeTypeFilter(selectedRecipeFilterKey) == null)
			{
				selectedRecipeFilterKey = "category:all";
			}
			for (int i = 0; i < recipeTypeFilters.Count; i++)
			{
				ApplyRecipeTypeVisual(recipeTypeFilters[i]);
			}
			recipeTypeFiltersDirty = true;
			craftDirty = true;
		}

		internal bool MatchesRecipeType(Recipe recipe)
		{
			if (string.IsNullOrEmpty(selectedRecipeFilterKey) || string.Equals(selectedRecipeFilterKey, "category:all", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			if (!Object.op_Implicit((Object)(object)recipe) || !Object.op_Implicit((Object)(object)recipe.m_item) || recipe.m_item.m_itemData == null || recipe.m_item.m_itemData.m_shared == null)
			{
				return false;
			}
			string typeName = ((object)Unsafe.As<ItemType, ItemType>(ref recipe.m_item.m_itemData.m_shared.m_itemType)/*cast due to .constrained prefix*/).ToString();
			if (string.Equals(selectedRecipeFilterKey, "category:weapons", StringComparison.OrdinalIgnoreCase))
			{
				return IsWeaponType(typeName);
			}
			if (string.Equals(selectedRecipeFilterKey, "category:armor", StringComparison.OrdinalIgnoreCase))
			{
				return IsArmorType(typeName);
			}
			if (string.Equals(selectedRecipeFilterKey, "category:consumables", StringComparison.OrdinalIgnoreCase))
			{
				return IsConsumableType(typeName);
			}
			if (string.Equals(selectedRecipeFilterKey, "category:construction", StringComparison.OrdinalIgnoreCase))
			{
				return IsConstructionType(typeName);
			}
			if (string.Equals(selectedRecipeFilterKey, "category:other", StringComparison.OrdinalIgnoreCase))
			{
				if (!IsWeaponType(typeName) && !IsArmorType(typeName) && !IsConsumableType(typeName))
				{
					return !IsConstructionType(typeName);
				}
				return false;
			}
			if (selectedRecipeFilterKey.StartsWith("mod:", StringComparison.OrdinalIgnoreCase))
			{
				return string.Equals(selectedRecipeFilterKey.Substring(4), ModSourceResolver.GetModNameCached(recipe.m_item), StringComparison.OrdinalIgnoreCase);
			}
			return true;
		}

		private void PositionRecipeTypeFilters()
		{
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_029d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)recipeTypeFilterRoot) || recipeTypeFilters.Count == 0)
			{
				return;
			}
			int num = 0;
			int num2 = 0;
			for (int i = 0; i < recipeTypeFilters.Count; i++)
			{
				if (IsModFilter(recipeTypeFilters[i].Key))
				{
					num2++;
				}
				else
				{
					num++;
				}
			}
			int num3 = Mathf.Max(0, (num2 + 20 - 1) / 20);
			int num4 = Mathf.Max(1, 1 + num3);
			int num5 = Mathf.Max(num, (num2 != 0) ? Mathf.Min(20, num2) : 0);
			float num6 = (float)num5 * 28f + (float)Mathf.Max(0, num5 - 1) * 3f;
			float num7 = (float)num4 * 28f + (float)Mathf.Max(0, num4 - 1) * 3f;
			recipeTypeFilterRoot.SetSizeWithCurrentAnchors((Axis)0, num7);
			recipeTypeFilterRoot.SetSizeWithCurrentAnchors((Axis)1, num6);
			int num8 = 0;
			int num9 = 0;
			for (int j = 0; j < recipeTypeFilters.Count; j++)
			{
				RectTransform val = (RectTransform)(Object.op_Implicit((Object)(object)recipeTypeFilters[j].Button) ? /*isinst with value type is only supported in some contexts*/: null);
				if (Object.op_Implicit((Object)(object)val))
				{
					val.anchorMin = new Vector2(0.5f, 0.5f);
					val.anchorMax = new Vector2(0.5f, 0.5f);
					val.pivot = new Vector2(0.5f, 0.5f);
					val.sizeDelta = new Vector2(28f, 28f);
					int num10 = 0;
					int num11;
					if (IsModFilter(recipeTypeFilters[j].Key))
					{
						num10 = num8 / 20;
						num11 = num8 % 20;
						num8++;
					}
					else
					{
						num10 = num3;
						num11 = num9++;
					}
					float num12 = (0f - num7) * 0.5f + 14f + (float)num10 * 31f;
					float num13 = num6 * 0.5f - 14f - (float)num11 * 31f;
					val.anchoredPosition = new Vector2(num12, num13);
				}
			}
			if (Object.op_Implicit((Object)(object)repairButton))
			{
				Transform transform = ((Component)repairButton).transform;
				RectTransform val2 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
				if (Object.op_Implicit((Object)(object)val2))
				{
					val2.GetWorldCorners(SharedCorners);
					Vector3 val3 = (SharedCorners[0] + SharedCorners[3]) * 0.5f;
					((Transform)recipeTypeFilterRoot).position = val3 + Vector3.down * (num6 * 0.5f + 48f);
				}
			}
			recipeTypeFiltersDirty = false;
		}

		private static bool IsModFilter(string key)
		{
			return key?.StartsWith("mod:", StringComparison.OrdinalIgnoreCase) ?? false;
		}

		private void CreateCraftControls(TMP_Text sample)
		{
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Expected O, but got Unknown
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Expected O, but got Unknown
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Expected O, but got Unknown
			//IL_01b2: 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_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e2: Expected O, but got Unknown
			//IL_02f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fe: Expected O, but got Unknown
			//IL_0310: Unknown result type (might be due to invalid IL or missing references)
			//IL_031a: Expected O, but got Unknown
			//IL_0325: Unknown result type (might be due to invalid IL or missing references)
			//IL_032a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0335: 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_034a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0354: Unknown result type (might be due to invalid IL or missing references)
			//IL_0355: Unknown result type (might be due to invalid IL or missing references)
			//IL_035f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0374: Unknown result type (might be due to invalid IL or missing references)
			//IL_0379: Unknown result type (might be due to invalid IL or missing references)
			//IL_0384: Unknown result type (might be due to invalid IL or missing references)
			//IL_038e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0399: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0406: Unknown result type (might be due to invalid IL or missing references)
			//IL_0407: Unknown result type (might be due to invalid IL or missing references)
			//IL_0411: Unknown result type (might be due to invalid IL or missing references)
			//IL_0426: Unknown result type (might be due to invalid IL or missing references)
			//IL_042b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0436: Unknown result type (might be due to invalid IL or missing references)
			//IL_0440: Unknown result type (might be due to invalid IL or missing references)
			//IL_0441: Unknown result type (might be due to invalid IL or missing references)
			//IL_044b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0456: Unknown result type (might be due to invalid IL or missing references)
			//IL_0460: Unknown result type (might be due to invalid IL or missing references)
			ref Button reference = ref nativeCraftButton;
			object? obj = CraftButtonField?.GetValue(gui);
			reference = (Button)((obj is Button) ? obj : null);
			if (!Object.op_Implicit((Object)(object)nativeCraftButton))
			{
				return;
			}
			ref Button reference2 = ref nativeCraftCancelButton;
			object? obj2 = CraftCancelButtonField?.GetValue(gui);
			reference2 = (Button)((obj2 is Button) ? obj2 : null);
			ref Transform reference3 = ref nativeCraftProgressPanel;
			object? obj3 = CraftProgressPanelField?.GetValue(gui);
			reference3 = (Transform)((obj3 is Transform) ? obj3 : null);
			Transform transform = ((Component)nativeCraftButton).transform;
			RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			Transform val2 = (Object.op_Implicit((Object)(object)val) ? ((Transform)val).parent : null);
			if (Object.op_Implicit((Object)(object)val2))
			{
				nativeCraftStateCaptured = true;
				originalMultiCrafting = MultiCraftingField != null && (bool)MultiCraftingField.GetValue(gui);
				originalMultiCraftAmount = ((!(MultiCraftAmountField != null)) ? 1 : ((int)MultiCraftAmountField.GetValue(gui)));
				craftControls = new GameObject("SearchBarPlusCraftControls", new Type[1] { typeof(RectTransform) });
				craftControls.transform.SetParent(val2, false);
				RectTransform val3 = (RectTransform)craftControls.transform;
				CopyRect(val, val3);
				Rect rect = val.rect;
				val3.SetSizeWithCurrentAnchors((Axis)1, ((Rect)(ref rect)).height * 1.3f);
				craftControls.AddComponent<LayoutElement>().ignoreLayout = true;
				GameObject val4 = new GameObject("QuantityRow", new Type[1] { typeof(RectTransform) });
				val4.transform.SetParent(craftControls.transform, false);
				RectTransform val5 = (RectTransform)val4.transform;
				val5.anchorMin = new Vector2(0f, 0.15f);
				val5.anchorMax = new Vector2(1f, 0.85f);
				val5.offsetMin = new Vector2(6f, 2f);
				val5.offsetMax = new Vector2(-6f, -2f);
				quantityDownButton = SmallButton("Minus", val4.transform, sample, "-");
				quantityUpButton = SmallButton("Plus", val4.transform, sample, "+");
				quantityInput = CreateQuantityInput(val4.transform, sample);
				((UnityEvent<string>)(object)quantityInput.onValueChanged).AddListener((UnityAction<string>)OnCraftQuantityChanged);
				((UnityEvent<string>)(object)quantityInput.onSubmit).AddListener((UnityAction<string>)delegate
				{
					BlurQuantity();
				});
				((UnityEvent<string>)(object)quantityInput.onEndEdit).AddListener((UnityAction<string>)delegate
				{
					CommitCraftQuantity();
				});
				createButton = CloneCraftButton(val4.transform, nativeCraftButton, sample);
				RemoveNativeCraftVisualOnce();
				((UnityEvent)quantityDownButton.onClick).AddListener((UnityAction)delegate
				{
					SetCraftQuantity(craftQuantity - 1);
				});
				((UnityEvent)quantityUpButton.onClick).AddListener((UnityAction)delegate
				{
					SetCraftQuantity(craftQuantity + 1);
				});
				((UnityEvent)createButton.onClick).AddListener(new UnityAction(HandleCreateClick));
				RectTransform val6 = (RectTransform)((Component)quantityDownButton).transform;
				val6.anchorMin = new Vector2(0f, 0f);
				val6.anchorMax = new Vector2(0.14f, 1f);
				val6.offsetMin = Vector2.zero;
				val6.offsetMax = Vector2.zero;
				RectTransform val7 = (RectTransform)((Component)quantityInput).transform;
				val7.anchorMin = new Vector2(0.15f, 0f);
				val7.anchorMax = new Vector2(0.36f, 1f);
				val7.offsetMin = new Vector2(2f, 0f);
				val7.offsetMax = new Vector2(-2f, 0f);
				RectTransform val8 = (RectTransform)((Component)quantityUpButton).transform;
				val8.anchorMin = new Vector2(0.37f, 0f);
				val8.anchorMax = new Vector2(0.51f, 1f);
				val8.offsetMin = Vector2.zero;
				val8.offsetMax = Vector2.zero;
				RectTransform val9 = (RectTransform)((Component)createButton).transform;
				val9.anchorMin = new Vector2(0.53f, 0f);
				val9.anchorMax = Vector2.one;
				val9.offsetMin = new Vector2(2f, 0f);
				val9.offsetMax = Vector2.zero;
				RemoveNativeCraftCancelVisualOnce();
				ConfigureProgressPanel();
				craftControls.transform.SetAsLastSibling();
				craftControls.SetActive(false);
			}
		}

		private void RemoveNativeCraftVisualOnce()
		{
			if (Object.op_Implicit((Object)(object)nativeCraftButton))
			{
				nativeCraftCanvasGroup = ((Component)nativeCraftButton).GetComponent<CanvasGroup>();
				if (!Object.op_Implicit((Object)(object)nativeCraftCanvasGroup))
				{
					nativeCraftCanvasGroup = ((Component)nativeCraftButton).gameObject.AddComponent<CanvasGroup>();
					nativeCraftCanvasGroupCreated = true;
				}
				nativeCraftCanvasAlpha = nativeCraftCanvasGroup.alpha;
				nativeCraftCanvasInteractable = nativeCraftCanvasGroup.interactable;
				nativeCraftCanvasBlocksRaycasts = nativeCraftCanvasGroup.blocksRaycasts;
				SetNativeCraftVisualHidden(hidden: true);
			}
		}

		private void SetNativeCraftVisualHidden(bool hidden)
		{
			if (Object.op_Implicit((Object)(object)nativeCraftCanvasGroup) && nativeCraftCanvasVisualHidden != hidden)
			{
				nativeCraftCanvasVisualHidden = hidden;
				if (hidden)
				{
					nativeCraftCanvasGroup.alpha = 0f;
					nativeCraftCanvasGroup.interactable = false;
					nativeCraftCanvasGroup.blocksRaycasts = false;
				}
				else
				{
					nativeCraftCanvasGroup.alpha = nativeCraftCanvasAlpha;
					nativeCraftCanvasGroup.interactable = nativeCraftCanvasInteractable;
					nativeCraftCanvasGroup.blocksRaycasts = nativeCraftCanvasBlocksRaycasts;
				}
			}
		}

		private void RemoveNativeCraftCancelVisualOnce()
		{
			if (Object.op_Implicit((Object)(object)nativeCraftCancelButton))
			{
				nativeCraftCancelCanvasGroup = ((Component)nativeCraftCancelButton).GetComponent<CanvasGroup>();
				if (!Object.op_Implicit((Object)(object)nativeCraftCancelCanvasGroup))
				{
					nativeCraftCancelCanvasGroup = ((Component)nativeCraftCancelButton).gameObject.AddComponent<CanvasGroup>();
					nativeCraftCancelCanvasGroupCreated = true;
				}
				nativeCraftCancelCanvasAlpha = nativeCraftCancelCanvasGroup.alpha;
				nativeCraftCancelCanvasInteractable = nativeCraftCancelCanvasGroup.interactable;
				nativeCraftCancelCanvasBlocksRaycasts = nativeCraftCancelCanvasGroup.blocksRaycasts;
				nativeCraftCancelCanvasGroup.alpha = 0f;
				nativeCraftCancelCanvasGroup.interactable = false;
				nativeCraftCancelCanvasGroup.blocksRaycasts = false;
			}
		}

		private void ConfigureProgressPanel()
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			Transform obj = nativeCraftProgressPanel;
			RectTransform val = (RectTransform)(object)((obj is RectTransform) ? obj : null);
			if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)craftControls))
			{
				return;
			}
			if (!progressLayoutCaptured)
			{
				progressLayoutCaptured = true;
				progressOriginalParent = ((Transform)val).parent;
				progressOriginalSiblingIndex = ((Transform)val).GetSiblingIndex();
				progressOriginalAnchorMin = val.anchorMin;
				progressOriginalAnchorMax = val.anchorMax;
				progressOriginalPivot = val.pivot;
				progressOriginalSizeDelta = val.sizeDelta;
				progressOriginalAnchoredPosition = val.anchoredPosition;
				progressOrig