Decompiled source of WorkbenchSearchFilters v1.1.0

WorkbenchSearchFilters.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("WorkbenchSearchFilters")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0+a34a8b094cf2ae13d83be2405df58ccfe10f51eb")]
[assembly: AssemblyProduct("WorkbenchSearchFilters")]
[assembly: AssemblyTitle("WorkbenchSearchFilters")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.0.0")]
[module: UnverifiableCode]
[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 WorkbenchSearchFilters
{
	internal enum Category
	{
		All,
		Weapons,
		Armor,
		Tools,
		Consumables,
		Materials,
		Misc,
		FoodStamina,
		FoodHealth,
		FoodEitr,
		FoodBalanced,
		Meads
	}
	internal static class Categories
	{
		internal static readonly int Count = Enum.GetValues(typeof(Category)).Length;

		internal static readonly Category[] Crafting = new Category[7]
		{
			Category.All,
			Category.Weapons,
			Category.Armor,
			Category.Tools,
			Category.Consumables,
			Category.Materials,
			Category.Misc
		};

		internal static readonly Category[] Food = new Category[7]
		{
			Category.All,
			Category.FoodHealth,
			Category.FoodStamina,
			Category.FoodEitr,
			Category.FoodBalanced,
			Category.Meads,
			Category.Misc
		};

		internal static readonly Category[] Buttons = Crafting.Concat(Food).Distinct().ToArray();

		internal static readonly string ReportPath = Path.Combine(Paths.ConfigPath, "WorkbenchSearchFilters.adrirf7.Categories.txt");

		private static readonly Dictionary<ItemDrop, Category> s_cache = new Dictionary<ItemDrop, Category>();

		private static readonly Dictionary<ItemDrop, Category> s_foodCache = new Dictionary<ItemDrop, Category>();

		private static Dictionary<string, Category> s_overrides;

		private static HashSet<string> s_foodIngredients;

		private static Dictionary<string, ItemDrop> s_cookedResults;

		private static HashSet<string> s_fermenterInputs;

		internal static Category[] ForStation(bool foodStation)
		{
			if (!foodStation)
			{
				return Crafting;
			}
			return Food;
		}

		internal static bool IsFoodStation(CraftingStation station)
		{
			if ((Object)(object)station == (Object)null)
			{
				return false;
			}
			string text = (station.m_name + " " + ((Object)((Component)station).gameObject).name).ToLowerInvariant();
			if (!text.Contains("cauldron"))
			{
				return text.Contains("preptable");
			}
			return true;
		}

		internal static string Token(Category category)
		{
			return "$wsf_cat_" + category.ToString().ToLowerInvariant();
		}

		internal static string[] IconPrefabs(Category category)
		{
			return category switch
			{
				Category.Weapons => new string[3] { "SwordIron", "SwordBronze", "AxeBronze" }, 
				Category.Armor => new string[3] { "ShieldBanded:1", "ArmorBronzeChest", "HelmetBronze" }, 
				Category.Tools => new string[3] { "Hammer", "PickaxeIron", "Hoe" }, 
				Category.Consumables => new string[2] { "MeadHealthMinor", "CookedMeat" }, 
				Category.Materials => new string[3] { "Bronze", "Iron", "Wood" }, 
				Category.Misc => new string[2] { "Coins", "Wishbone" }, 
				Category.Meads => new string[2] { "MeadBaseHealthMinor", "MeadHealthMinor" }, 
				_ => new string[0], 
			};
		}

		internal static Color? FoodColor(Category category)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: 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)
			return category switch
			{
				Category.FoodStamina => new Color(1f, 0.85f, 0.25f, 1f), 
				Category.FoodHealth => new Color(1f, 0.35f, 0.35f, 1f), 
				Category.FoodEitr => new Color(0.75f, 0.45f, 1f, 1f), 
				Category.FoodBalanced => Color.white, 
				_ => null, 
			};
		}

		internal static void ResetCache()
		{
			s_cache.Clear();
			s_foodCache.Clear();
			s_overrides = null;
			s_foodIngredients = null;
			s_cookedResults = null;
			s_fermenterInputs = null;
		}

		internal static Category Classify(ItemDrop item, bool foodStation)
		{
			Dictionary<ItemDrop, Category> dictionary = (foodStation ? s_foodCache : s_cache);
			if (!dictionary.TryGetValue(item, out var value))
			{
				value = (dictionary[item] = (foodStation ? ClassifyFood(item) : ClassifyUncached(item)));
			}
			return value;
		}

		private static Category ClassifyFood(ItemDrop item)
		{
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Invalid comparison between Unknown and I4
			if (GetOverrides().TryGetValue(((Object)item).name, out var value) && Food.Contains(value))
			{
				return value;
			}
			SharedData shared = item.m_itemData.m_shared;
			SharedData val = FoodStats(item);
			if (val.m_food > 0f || val.m_foodStamina > 0f || val.m_foodEitr > 0f)
			{
				if (val.m_food < val.m_foodEitr / 2f && val.m_foodStamina < val.m_foodEitr / 2f)
				{
					return Category.FoodEitr;
				}
				if (val.m_foodStamina < val.m_food / 2f)
				{
					return Category.FoodHealth;
				}
				if (val.m_food < val.m_foodStamina / 2f)
				{
					return Category.FoodStamina;
				}
				return Category.FoodBalanced;
			}
			if ((s_fermenterInputs != null && s_fermenterInputs.Contains(((Object)item).name)) || shared.m_isDrink || (int)shared.m_itemType == 2)
			{
				return Category.Meads;
			}
			return Category.Misc;
		}

		private static SharedData FoodStats(ItemDrop item)
		{
			GetFoodIngredients();
			if (s_cookedResults != null && s_cookedResults.TryGetValue(((Object)item).name, out var value) && (Object)(object)value != (Object)null)
			{
				return value.m_itemData.m_shared;
			}
			return item.m_itemData.m_shared;
		}

		internal static float FoodSortValue(ItemDrop item, Category category)
		{
			switch (category)
			{
			case Category.FoodHealth:
				return FoodStats(item).m_food;
			case Category.FoodStamina:
				return FoodStats(item).m_foodStamina;
			case Category.FoodEitr:
				return FoodStats(item).m_foodEitr;
			case Category.FoodBalanced:
			{
				SharedData val = FoodStats(item);
				return val.m_food + val.m_foodStamina;
			}
			default:
				return 0f;
			}
		}

		internal static bool IsFoodType(Category category)
		{
			if (category != Category.FoodHealth && category != Category.FoodStamina && category != Category.FoodEitr)
			{
				return category == Category.FoodBalanced;
			}
			return true;
		}

		private static Category ClassifyUncached(ItemDrop item)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Invalid comparison between Unknown and I4
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Invalid comparison between Unknown and I4
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Invalid comparison between Unknown and I4
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Expected I4, but got Unknown
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Invalid comparison between Unknown and I4
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Invalid comparison between Unknown and I4
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Invalid comparison between Unknown and I4
			if (GetOverrides().TryGetValue(((Object)item).name, out var value) && Crafting.Contains(value))
			{
				return value;
			}
			SharedData shared = item.m_itemData.m_shared;
			ItemType itemType = shared.m_itemType;
			if ((int)itemType == 9 || (int)itemType == 23)
			{
				return Category.Consumables;
			}
			if (shared.m_attack != null && shared.m_attack.m_consumeItem)
			{
				return Category.Consumables;
			}
			if ((int)itemType == 2 || shared.m_isDrink || shared.m_food > 0f || shared.m_foodStamina > 0f || shared.m_foodEitr > 0f)
			{
				return Category.Consumables;
			}
			if (GetFoodIngredients().Contains(((Object)item).name))
			{
				return Category.Consumables;
			}
			switch (itemType - 1)
			{
			case 2:
			case 3:
			case 13:
			case 19:
			case 21:
				if ((int)shared.m_skillType == 12 || (int)shared.m_skillType == 104)
				{
					return Category.Tools;
				}
				if ((int)itemType != 4 && ((DamageTypes)(ref shared.m_damages)).GetTotalDamage() <= 0f)
				{
					return Category.Misc;
				}
				return Category.Weapons;
			case 4:
			case 5:
			case 6:
			case 10:
			case 11:
			case 16:
			case 17:
			case 23:
				return Category.Armor;
			case 14:
			case 18:
				return Category.Tools;
			case 0:
				return Category.Materials;
			default:
				return Category.Misc;
			}
		}

		private static Dictionary<string, Category> GetOverrides()
		{
			if (s_overrides != null)
			{
				return s_overrides;
			}
			s_overrides = new Dictionary<string, Category>(StringComparer.OrdinalIgnoreCase);
			string[] array = WorkbenchSearchFiltersPlugin.CategoryOverrides.Value.Split(',');
			foreach (string text in array)
			{
				string[] array2 = text.Split(':');
				if (array2.Length == 2)
				{
					string text2 = array2[0].Trim();
					if (text2.Length > 0 && Enum.TryParse<Category>(array2[1].Trim(), ignoreCase: true, out var result) && result != Category.All)
					{
						s_overrides[text2] = result;
					}
					else
					{
						WorkbenchSearchFiltersPlugin.Log.LogWarning((object)("Invalid category override: '" + text.Trim() + "'"));
					}
				}
			}
			return s_overrides;
		}

		private static HashSet<string> GetFoodIngredients()
		{
			if (s_foodIngredients != null)
			{
				return s_foodIngredients;
			}
			HashSet<string> hashSet = new HashSet<string>();
			if ((Object)(object)ZNetScene.instance == (Object)null)
			{
				return hashSet;
			}
			Dictionary<string, ItemDrop> dictionary = new Dictionary<string, ItemDrop>();
			HashSet<string> hashSet2 = new HashSet<string>();
			foreach (GameObject prefab in ZNetScene.instance.m_prefabs)
			{
				if ((Object)(object)prefab == (Object)null)
				{
					continue;
				}
				CookingStation component = prefab.GetComponent<CookingStation>();
				if ((Object)(object)component != (Object)null)
				{
					foreach (ItemConversion item in component.m_conversion)
					{
						if ((Object)(object)item?.m_from != (Object)null)
						{
							hashSet.Add(((Object)item.m_from).name);
							if ((Object)(object)item.m_to != (Object)null)
							{
								dictionary[((Object)item.m_from).name] = item.m_to;
							}
						}
					}
				}
				Fermenter component2 = prefab.GetComponent<Fermenter>();
				if (!((Object)(object)component2 != (Object)null))
				{
					continue;
				}
				foreach (ItemConversion item2 in component2.m_conversion)
				{
					if ((Object)(object)item2?.m_from != (Object)null)
					{
						hashSet.Add(((Object)item2.m_from).name);
						hashSet2.Add(((Object)item2.m_from).name);
					}
				}
			}
			s_foodIngredients = hashSet;
			s_cookedResults = dictionary;
			s_fermenterInputs = hashSet2;
			return hashSet;
		}

		internal static void WriteReport()
		{
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ObjectDB.instance == (Object)null)
			{
				return;
			}
			try
			{
				var list = (from item in (from recipe in ObjectDB.instance.m_recipes
						where (Object)(object)recipe != (Object)null && (Object)(object)recipe.m_item != (Object)null && recipe.m_enabled
						select recipe.m_item).Distinct()
					select new
					{
						Category = Classify(item, foodStation: false),
						Prefab = ((Object)item).name,
						Name = Localization.instance.Localize(item.m_itemData.m_shared.m_name),
						Type = item.m_itemData.m_shared.m_itemType
					} into row
					orderby row.Category, row.Name
					select row).ToList();
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("# Category of every craftable item, as shown by WorkbenchSearchFilters.");
				stringBuilder.AppendLine("# Regenerated every time you enter a world. To move an item, add 'Prefab:Category' to");
				stringBuilder.AppendLine("# CategoryOverrides in WorkbenchSearchFilters.adrirf7.cfg (categories: " + string.Join(", ", Crafting.Where((Category c) => c != Category.All)) + ";");
				stringBuilder.AppendLine("# at the cauldron and the food preparation table: " + string.Join(", ", Food.Where((Category c) => c != Category.All)) + ").");
				Category? category = null;
				foreach (var item in list)
				{
					if (category != item.Category)
					{
						category = item.Category;
						stringBuilder.AppendLine();
						stringBuilder.AppendLine("[" + item.Category.ToString() + "]");
					}
					stringBuilder.AppendLine(item.Prefab.PadRight(32) + " " + item.Name.PadRight(32) + " (" + ((object)item.Type/*cast due to .constrained prefix*/).ToString() + ")");
				}
				File.WriteAllText(ReportPath, stringBuilder.ToString(), Encoding.UTF8);
			}
			catch (Exception ex)
			{
				WorkbenchSearchFiltersPlugin.Log.LogWarning((object)("Could not write " + ReportPath + ": " + ex.Message));
			}
		}
	}
	internal static class FilterBar
	{
		private sealed class CategoryButton
		{
			public Category Category;

			public Image Background;

			public Graphic Content;

			public Color ContentColor;
		}

		private struct Entry
		{
			public RecipeDataPair Pair;

			public Category Category;

			public string Name;

			public float FoodValue;
		}

		private const float SearchHeight = 26f;

		private const float ButtonsHeight = 28f;

		private const float Gap = 3f;

		private const float BarHeight = 60f;

		private static readonly Color s_buttonColor = new Color(0f, 0f, 0f, 0.55f);

		private static readonly Color s_selectedColor = new Color(0.85f, 0.6f, 0.2f, 0.9f);

		private const float EmptyIconAlpha = 0.3f;

		private static GameObject s_root;

		private static InventoryGui s_gui;

		private static RectTransform s_list;

		private static RectTransform s_scrollbar;

		private static TMP_InputField s_search;

		private static TMP_Text s_allLabel;

		private static readonly List<CategoryButton> s_buttons = new List<CategoryButton>();

		internal static Category CurrentCategory = Category.All;

		private static Category s_activeCategory = Category.All;

		internal static string SearchText = "";

		private static bool s_foodStation;

		private static bool? s_buttonsFoodStation;

		private static readonly List<Entry> s_entries = new List<Entry>();

		internal static bool IsSearchFocused
		{
			get
			{
				if ((Object)(object)s_search != (Object)null)
				{
					return s_search.isFocused;
				}
				return false;
			}
		}

		internal static void EnsureCreated(InventoryGui gui)
		{
			if ((Object)(object)s_root != (Object)null)
			{
				return;
			}
			try
			{
				Categories.ResetCache();
				Create(gui);
				RefreshTexts();
				Categories.WriteReport();
			}
			catch (Exception ex)
			{
				WorkbenchSearchFiltersPlugin.Log.LogError((object)("Could not create the crafting filter bar: " + ex));
				if ((Object)(object)s_root != (Object)null)
				{
					Object.Destroy((Object)(object)s_root);
				}
				s_root = null;
			}
		}

		internal static void Teardown()
		{
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: 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_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)s_search != (Object)null && s_search.isFocused)
			{
				s_search.DeactivateInputField(false);
			}
			foreach (Entry s_entry in s_entries)
			{
				Entry current = s_entry;
				if ((Object)(object)((RecipeDataPair)(ref current.Pair)).InterfaceElement != (Object)null && !((RecipeDataPair)(ref current.Pair)).InterfaceElement.activeSelf)
				{
					Object.Destroy((Object)(object)((RecipeDataPair)(ref current.Pair)).InterfaceElement);
				}
			}
			s_entries.Clear();
			if ((Object)(object)s_root != (Object)null && (Object)(object)s_gui != (Object)null)
			{
				Object.Destroy((Object)(object)s_root);
				if ((Object)(object)s_list != (Object)null)
				{
					RectTransform obj = s_list;
					obj.offsetMax += new Vector2(0f, 60f);
				}
				if ((Object)(object)s_scrollbar != (Object)null)
				{
					RectTransform obj2 = s_scrollbar;
					obj2.offsetMax += new Vector2(0f, 60f);
				}
				InventoryGui obj3 = s_gui;
				obj3.m_recipeListBaseSize += 60f;
				if (InventoryGui.IsVisible() && (Object)(object)Player.m_localPlayer != (Object)null)
				{
					s_gui.UpdateCraftingPanel(false);
				}
			}
			s_root = null;
			s_gui = null;
			s_list = null;
			s_scrollbar = null;
			s_search = null;
			s_allLabel = null;
			s_buttons.Clear();
			s_buttonsFoodStation = null;
		}

		internal static void BeforeGameRebuild(InventoryGui gui)
		{
			foreach (Entry s_entry in s_entries)
			{
				Entry current = s_entry;
				if ((Object)(object)((RecipeDataPair)(ref current.Pair)).InterfaceElement != (Object)null && !((RecipeDataPair)(ref current.Pair)).InterfaceElement.activeSelf)
				{
					Object.Destroy((Object)(object)((RecipeDataPair)(ref current.Pair)).InterfaceElement);
				}
			}
			s_entries.Clear();
		}

		internal static void AfterGameRebuild(InventoryGui gui)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			s_entries.Clear();
			s_foodStation = Categories.IsFoodStation(((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.GetCurrentCraftingStation() : null);
			foreach (RecipeDataPair availableRecipe in gui.m_availableRecipes)
			{
				RecipeDataPair current = availableRecipe;
				Category category = Categories.Classify(((RecipeDataPair)(ref current)).Recipe.m_item, s_foodStation);
				s_entries.Add(new Entry
				{
					Pair = current,
					Category = category,
					Name = Localization.instance.Localize(((RecipeDataPair)(ref current)).Recipe.m_item.m_itemData.m_shared.m_name),
					FoodValue = Categories.FoodSortValue(((RecipeDataPair)(ref current)).Recipe.m_item, category)
				});
			}
			ApplyFilter(gui);
		}

		private static void SyncWithGame(InventoryGui gui)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			List<RecipeDataPair> availableRecipes = gui.m_availableRecipes;
			HashSet<GameObject> hashSet = new HashSet<GameObject>();
			foreach (RecipeDataPair item in availableRecipes)
			{
				RecipeDataPair current = item;
				if ((Object)(object)((RecipeDataPair)(ref current)).InterfaceElement != (Object)null)
				{
					hashSet.Add(((RecipeDataPair)(ref current)).InterfaceElement);
				}
			}
			int num = 0;
			bool flag = hashSet.Count == availableRecipes.Count;
			foreach (Entry s_entry in s_entries)
			{
				Entry current2 = s_entry;
				GameObject interfaceElement = ((RecipeDataPair)(ref current2.Pair)).InterfaceElement;
				if (!flag)
				{
					break;
				}
				if (!((Object)(object)interfaceElement == (Object)null) && interfaceElement.activeSelf)
				{
					num++;
					flag = hashSet.Contains(interfaceElement);
				}
			}
			if (flag && num == availableRecipes.Count)
			{
				return;
			}
			foreach (Entry s_entry2 in s_entries)
			{
				Entry current3 = s_entry2;
				GameObject interfaceElement2 = ((RecipeDataPair)(ref current3.Pair)).InterfaceElement;
				if ((Object)(object)interfaceElement2 != (Object)null && !hashSet.Contains(interfaceElement2))
				{
					Object.Destroy((Object)(object)interfaceElement2);
				}
			}
			AfterGameRebuild(gui);
		}

		private static void ApplyFilter(InventoryGui gui)
		{
			//IL_01be: 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_01e4: Unknown result type (might be due to invalid IL or missing references)
			List<RecipeDataPair> availableRecipes = gui.m_availableRecipes;
			availableRecipes.Clear();
			string text = SearchText.Trim();
			int[] array = new int[Categories.Count];
			int[] array2 = new int[Categories.Count];
			bool[] array3 = new bool[s_entries.Count];
			for (int i = 0; i < s_entries.Count; i++)
			{
				Category category = s_entries[i].Category;
				array[0]++;
				array[(int)category]++;
				array3[i] = text.Length == 0 || Contains(s_entries[i].Name, text);
				if (array3[i])
				{
					array2[0]++;
					array2[(int)category]++;
				}
			}
			s_activeCategory = ((array[(int)CurrentCategory] > 0) ? CurrentCategory : Category.All);
			int[] array4 = new int[s_entries.Count];
			for (int j = 0; j < array4.Length; j++)
			{
				array4[j] = j;
			}
			if (Categories.IsFoodType(s_activeCategory))
			{
				Array.Sort(array4, delegate(int a, int b)
				{
					int num4 = s_entries[b].FoodValue.CompareTo(s_entries[a].FoodValue);
					return (num4 == 0) ? a.CompareTo(b) : num4;
				});
			}
			int[] array5 = array4;
			foreach (int num2 in array5)
			{
				Entry entry = s_entries[num2];
				bool flag = array3[num2] && (s_activeCategory == Category.All || entry.Category == s_activeCategory);
				GameObject interfaceElement = ((RecipeDataPair)(ref entry.Pair)).InterfaceElement;
				if (!((Object)(object)interfaceElement == (Object)null))
				{
					if (interfaceElement.activeSelf != flag)
					{
						interfaceElement.SetActive(flag);
					}
					if (flag)
					{
						((RectTransform)interfaceElement.transform).anchoredPosition = new Vector2(0f, (float)availableRecipes.Count * (0f - gui.m_recipeListSpace));
						availableRecipes.Add(entry.Pair);
					}
				}
			}
			float num3 = Mathf.Max(gui.m_recipeListBaseSize, (float)availableRecipes.Count * gui.m_recipeListSpace);
			gui.m_recipeListRoot.SetSizeWithCurrentAnchors((Axis)1, num3);
			UpdateButtons(array, array2);
		}

		private static bool Contains(string text, string term)
		{
			return CultureInfo.InvariantCulture.CompareInfo.IndexOf(text, term, CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace) >= 0;
		}

		internal static void OnInventoryHidden()
		{
			if (WorkbenchSearchFiltersPlugin.ClearSearchOnClose.Value)
			{
				SearchText = "";
				if ((Object)(object)s_search != (Object)null)
				{
					s_search.SetTextWithoutNotify("");
				}
			}
			if (!WorkbenchSearchFiltersPlugin.RememberCategory.Value)
			{
				CurrentCategory = Category.All;
			}
			if ((Object)(object)s_search != (Object)null && s_search.isFocused)
			{
				s_search.DeactivateInputField(false);
			}
		}

		private static void RefreshRecipes()
		{
			InventoryGui instance = InventoryGui.instance;
			if (!((Object)(object)instance == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null) && InventoryGui.IsVisible())
			{
				SyncWithGame(instance);
				ApplyFilter(instance);
				if (instance.m_availableRecipes.Count == 0)
				{
					instance.SetRecipe(-1, false);
				}
				else
				{
					instance.SetRecipe(((Object)(object)((RecipeDataPair)(ref instance.m_selectedRecipe)).Recipe != (Object)null) ? instance.GetSelectedRecipeIndex(false) : 0, true);
				}
			}
		}

		internal static void RefreshTexts()
		{
			if (!((Object)(object)s_root == (Object)null))
			{
				Graphic placeholder = s_search.placeholder;
				TMP_Text val = (TMP_Text)(object)((placeholder is TMP_Text) ? placeholder : null);
				if (val != null)
				{
					val.text = Localization.instance.Localize("$wsf_search");
				}
				if ((Object)(object)s_allLabel != (Object)null)
				{
					s_allLabel.text = Localization.instance.Localize("$wsf_cat_all");
				}
			}
		}

		private static void UpdateButtons(int[] available, int[] matches)
		{
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: 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_0146: Unknown result type (might be due to invalid IL or missing references)
			Category[] array = Categories.ForStation(s_foodStation);
			if (s_buttonsFoodStation != s_foodStation)
			{
				s_buttonsFoodStation = s_foodStation;
				Category[] array2 = array;
				foreach (Category category in array2)
				{
					CategoryButton? categoryButton = s_buttons.Find((CategoryButton b) => b.Category == category);
					if (categoryButton != null)
					{
						((Component)categoryButton.Background).transform.SetAsLastSibling();
					}
				}
			}
			foreach (CategoryButton s_button in s_buttons)
			{
				bool flag = s_button.Category == Category.All || (Array.IndexOf(array, s_button.Category) >= 0 && available[(int)s_button.Category] > 0);
				GameObject gameObject = ((Component)s_button.Background).gameObject;
				if (gameObject.activeSelf != flag)
				{
					gameObject.SetActive(flag);
				}
				((Graphic)s_button.Background).color = ((s_button.Category == s_activeCategory) ? s_selectedColor : s_buttonColor);
				Color contentColor = s_button.ContentColor;
				if (matches[(int)s_button.Category] == 0)
				{
					contentColor.a *= 0.3f;
				}
				s_button.Content.color = contentColor;
			}
		}

		private static void Create(InventoryGui gui)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: 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_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: 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)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			s_buttons.Clear();
			s_buttonsFoodStation = null;
			s_allLabel = null;
			ScrollRect componentInParent = ((Component)gui.m_recipeListRoot).GetComponentInParent<ScrollRect>();
			RectTransform val = (((Object)(object)componentInParent != (Object)null) ? ((RectTransform)((Component)componentInParent).transform) : ((RectTransform)((Transform)gui.m_recipeListRoot).parent));
			RectTransform val2 = (RectTransform)((Transform)val).parent;
			s_root = new GameObject("WSF_FilterArea", new Type[1] { typeof(RectTransform) });
			RectTransform val3 = (RectTransform)s_root.transform;
			((Transform)val3).SetParent((Transform)(object)val2, false);
			val3.anchorMin = val.anchorMin;
			val3.anchorMax = val.anchorMax;
			val3.pivot = val.pivot;
			val3.offsetMin = val.offsetMin;
			val3.offsetMax = val.offsetMax;
			((Transform)val3).SetSiblingIndex(((Transform)val).GetSiblingIndex() + 1);
			RectTransform val4 = NewRect("WSF_FilterBar", (Transform)(object)val3);
			SetTop(val4, 0f, 57f);
			val.offsetMax -= new Vector2(0f, 60f);
			s_gui = gui;
			s_list = val;
			s_scrollbar = null;
			RectTransform val5 = ((!((Object)(object)gui.m_recipeListScroll != (Object)null)) ? ((RectTransform)null) : ((RectTransform)((Component)gui.m_recipeListScroll).transform));
			if ((Object)(object)val5 != (Object)null && (Object)(object)((Transform)val5).parent == (Object)(object)val2)
			{
				val5.offsetMax -= new Vector2(0f, 60f);
				s_scrollbar = val5;
			}
			gui.m_recipeListBaseSize -= 60f;
			TMP_Text component = ((Component)gui.m_recipeElementPrefab.transform.Find("name")).GetComponent<TMP_Text>();
			CreateSearchField(val4, component);
			CreateCategoryButtons(gui, val4, component);
		}

		private static void CreateSearchField(RectTransform bar, TMP_Text referenceText)
		{
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Expected O, but got Unknown
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Expected O, but got Unknown
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Expected O, but got Unknown
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Expected O, but got Unknown
			TMP_InputField val = (TMP_InputField)(object)(((Object)(object)Hud.instance != (Object)null && (Object)(object)Hud.instance.m_buildUi != (Object)null) ? Hud.instance.m_buildUi.m_searchField : null);
			GameObject val2 = null;
			if ((Object)(object)val != (Object)null)
			{
				try
				{
					val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, (Transform)(object)bar, false);
					((Object)val2).name = "WSF_Search";
					MonoBehaviour[] componentsInChildren = val2.GetComponentsInChildren<MonoBehaviour>(true);
					foreach (MonoBehaviour val3 in componentsInChildren)
					{
						if ((Object)(object)val3 != (Object)null && ((object)val3).GetType().Name == "Localize")
						{
							Object.DestroyImmediate((Object)(object)val3);
						}
					}
					s_search = val2.GetComponent<TMP_InputField>();
					RemoveExtras(val2, s_search);
				}
				catch (Exception ex)
				{
					WorkbenchSearchFiltersPlugin.Log.LogWarning((object)("Could not copy the build menu search field, using a simple one: " + ex.Message));
					if ((Object)(object)val2 != (Object)null)
					{
						Object.Destroy((Object)(object)val2);
					}
					val2 = null;
				}
			}
			if ((Object)(object)val2 == (Object)null)
			{
				val2 = CreateSimpleInputField(bar, referenceText);
				s_search = val2.GetComponent<TMP_InputField>();
			}
			val2.SetActive(true);
			LayoutElement component = val2.GetComponent<LayoutElement>();
			if ((Object)(object)component != (Object)null)
			{
				component.ignoreLayout = true;
			}
			SetTop((RectTransform)val2.transform, 0f, 26f);
			s_search.onValueChanged = new OnChangeEvent();
			s_search.onEndEdit = new SubmitEvent();
			s_search.onSubmit = new SubmitEvent();
			s_search.restoreOriginalTextOnEscape = false;
			s_search.characterLimit = 40;
			s_search.SetTextWithoutNotify(SearchText);
			((UnityEvent<string>)(object)s_search.onValueChanged).AddListener((UnityAction<string>)delegate(string text)
			{
				SearchText = text ?? "";
				RefreshRecipes();
			});
		}

		private static void RemoveExtras(GameObject go, TMP_InputField input)
		{
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Expected O, but got Unknown
			HashSet<Transform> hashSet = new HashSet<Transform>();
			Component[] array = (Component[])(object)new Component[3]
			{
				(Component)input.textViewport,
				(Component)input.textComponent,
				(Component)input.placeholder
			};
			foreach (Component val in array)
			{
				Transform val2 = (((Object)(object)val != (Object)null) ? val.transform : null);
				while ((Object)(object)val2 != (Object)null && (Object)(object)val2 != (Object)(object)go.transform)
				{
					hashSet.Add(val2);
					val2 = val2.parent;
				}
			}
			List<GameObject> list = new List<GameObject>();
			foreach (Transform item in go.transform)
			{
				Transform val3 = item;
				if (!hashSet.Contains(val3))
				{
					list.Add(((Component)val3).gameObject);
				}
			}
			foreach (GameObject item2 in list)
			{
				Object.DestroyImmediate((Object)(object)item2);
			}
		}

		private static GameObject CreateSimpleInputField(RectTransform bar, TMP_Text referenceText)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = NewRect("WSF_Search", (Transform)(object)bar);
			GameObject gameObject = ((Component)val).gameObject;
			gameObject.SetActive(false);
			Image val2 = gameObject.AddComponent<Image>();
			((Graphic)val2).color = s_buttonColor;
			RectTransform val3 = NewRect("Text Area", (Transform)(object)val);
			Stretch(val3, new Vector2(8f, 2f), new Vector2(-8f, -2f));
			((Component)val3).gameObject.AddComponent<RectMask2D>();
			TextMeshProUGUI val4 = NewText("Placeholder", val3, referenceText, 16f);
			((TMP_Text)val4).fontStyle = (FontStyles)2;
			((Graphic)val4).color = new Color(1f, 1f, 1f, 0.45f);
			TextMeshProUGUI textComponent = NewText("Text", val3, referenceText, 16f);
			TMP_InputField obj = gameObject.AddComponent<TMP_InputField>();
			((Selectable)obj).targetGraphic = (Graphic)(object)val2;
			obj.textViewport = val3;
			obj.textComponent = (TMP_Text)(object)textComponent;
			obj.placeholder = (Graphic)(object)val4;
			obj.fontAsset = referenceText.font;
			obj.pointSize = 16f;
			return gameObject;
		}

		private static void CreateCategoryButtons(InventoryGui gui, RectTransform bar, TMP_Text referenceText)
		{
			//IL_00bb: 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_00df: 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_0117: 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_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Expected O, but got Unknown
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = NewRect("WSF_Categories", (Transform)(object)bar);
			SetTop(val, 29f, 28f);
			HorizontalLayoutGroup obj = ((Component)val).gameObject.AddComponent<HorizontalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)obj).spacing = 3f;
			((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = true;
			UITooltip val2 = (((Object)(object)gui.m_craftButton != (Object)null) ? ((Component)gui.m_craftButton).GetComponent<UITooltip>() : null);
			Sprite val3 = FindFoodIcon(gui);
			Category[] buttons = Categories.Buttons;
			for (int i = 0; i < buttons.Length; i++)
			{
				Category category = buttons[i];
				RectTransform val4 = NewRect("WSF_Cat_" + category, (Transform)(object)val);
				Image val5 = ((Component)val4).gameObject.AddComponent<Image>();
				((Graphic)val5).color = s_buttonColor;
				Button obj2 = ((Component)val4).gameObject.AddComponent<Button>();
				((Selectable)obj2).targetGraphic = (Graphic)(object)val5;
				ColorBlock colors = ((Selectable)obj2).colors;
				((ColorBlock)(ref colors)).highlightedColor = new Color(1.4f, 1.4f, 1.4f, 1f);
				((ColorBlock)(ref colors)).pressedColor = new Color(0.8f, 0.8f, 0.8f, 1f);
				((ColorBlock)(ref colors)).selectedColor = Color.white;
				((Selectable)obj2).colors = colors;
				Category captured = category;
				((UnityEvent)obj2.onClick).AddListener((UnityAction)delegate
				{
					OnCategoryClicked(captured);
				});
				((Component)val4).gameObject.AddComponent<LayoutElement>().flexibleWidth = ((category == Category.All) ? 1.8f : 1f);
				Color? val6 = Categories.FoodColor(category);
				Color contentColor = (Color)(((??)val6) ?? Color.white);
				Sprite val7 = ((category == Category.All) ? null : (val6.HasValue ? val3 : FindIcon(category)));
				Graphic content;
				if ((Object)(object)val7 != (Object)null)
				{
					RectTransform obj3 = NewRect("icon", (Transform)(object)val4);
					Stretch(obj3, new Vector2(2f, 2f), new Vector2(-2f, -2f));
					Image obj4 = ((Component)obj3).gameObject.AddComponent<Image>();
					obj4.sprite = val7;
					obj4.preserveAspect = true;
					((Graphic)obj4).raycastTarget = false;
					content = (Graphic)(object)obj4;
				}
				else
				{
					TextMeshProUGUI val8 = NewText("label", val4, referenceText, 14f);
					((TMP_Text)val8).alignment = (TextAlignmentOptions)514;
					((TMP_Text)val8).enableAutoSizing = true;
					((TMP_Text)val8).fontSizeMin = 8f;
					((TMP_Text)val8).fontSizeMax = 14f;
					((TMP_Text)val8).text = Localization.instance.Localize(Categories.Token(category));
					content = (Graphic)(object)val8;
					if (category == Category.All)
					{
						s_allLabel = (TMP_Text)(object)val8;
					}
				}
				if ((Object)(object)val2 != (Object)null && category != Category.All)
				{
					UITooltip obj5 = ((Component)val4).gameObject.AddComponent<UITooltip>();
					obj5.m_tooltipPrefab = val2.m_tooltipPrefab;
					obj5.m_text = Categories.Token(category);
				}
				s_buttons.Add(new CategoryButton
				{
					Category = category,
					Background = val5,
					Content = content,
					ContentColor = contentColor
				});
			}
		}

		private static Sprite FindFoodIcon(InventoryGui gui)
		{
			if ((Object)(object)Hud.instance != (Object)null && (Object)(object)Hud.instance.m_foodIcon != (Object)null && (Object)(object)Hud.instance.m_foodIcon.sprite != (Object)null)
			{
				return Hud.instance.m_foodIcon.sprite;
			}
			InventoryElement val = (((Object)(object)gui.m_playerGrid != (Object)null && (Object)(object)gui.m_playerGrid.m_elementPrefab != (Object)null) ? gui.m_playerGrid.m_elementPrefab.GetComponent<InventoryElement>() : null);
			if (!((Object)(object)val != (Object)null) || !((Object)(object)val.m_food != (Object)null))
			{
				return null;
			}
			return val.m_food.sprite;
		}

		private static void OnCategoryClicked(Category category)
		{
			CurrentCategory = category;
			RefreshRecipes();
		}

		private static Sprite FindIcon(Category category)
		{
			if ((Object)(object)ObjectDB.instance == (Object)null)
			{
				return null;
			}
			string[] array = Categories.IconPrefabs(category);
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split(':');
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(array2[0]);
				ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null);
				Sprite[] array3 = (((Object)(object)val != (Object)null) ? val.m_itemData.m_shared.m_icons : null);
				if (array3 != null && array3.Length != 0)
				{
					int result;
					int num = ((array2.Length > 1 && int.TryParse(array2[1], out result) && result >= 0 && result < array3.Length) ? result : 0);
					return array3[num];
				}
			}
			return null;
		}

		private static RectTransform NewRect(string name, Transform parent)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			RectTransform val = (RectTransform)new GameObject(name, new Type[1] { typeof(RectTransform) }).transform;
			((Transform)val).SetParent(parent, false);
			return val;
		}

		private static void SetTop(RectTransform rect, float top, float height)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			rect.anchorMin = new Vector2(0f, 1f);
			rect.anchorMax = new Vector2(1f, 1f);
			rect.pivot = new Vector2(0.5f, 1f);
			rect.sizeDelta = new Vector2(0f, height);
			rect.anchoredPosition = new Vector2(0f, 0f - top);
		}

		private static void Stretch(RectTransform rect, Vector2 offsetMin, Vector2 offsetMax)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			rect.anchorMin = Vector2.zero;
			rect.anchorMax = Vector2.one;
			rect.offsetMin = offsetMin;
			rect.offsetMax = offsetMax;
		}

		private static TextMeshProUGUI NewText(string name, RectTransform parent, TMP_Text reference, float size)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			RectTransform obj = NewRect(name, (Transform)(object)parent);
			Stretch(obj, Vector2.zero, Vector2.zero);
			TextMeshProUGUI obj2 = ((Component)obj).gameObject.AddComponent<TextMeshProUGUI>();
			((TMP_Text)obj2).font = reference.font;
			((TMP_Text)obj2).fontSize = size;
			((Graphic)obj2).color = Color.white;
			((TMP_Text)obj2).alignment = (TextAlignmentOptions)4097;
			((TMP_Text)obj2).textWrappingMode = (TextWrappingModes)0;
			((Graphic)obj2).raycastTarget = false;
			return obj2;
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "UpdateRecipeList")]
	internal static class InventoryGui_UpdateRecipeList_Patch
	{
		[HarmonyPriority(800)]
		private static void Prefix(InventoryGui __instance)
		{
			FilterBar.BeforeGameRebuild(__instance);
		}

		[HarmonyPriority(0)]
		[HarmonyAfter(new string[] { "org.lafchi.plugins.valheim_recycle" })]
		private static void Postfix(InventoryGui __instance)
		{
			FilterBar.EnsureCreated(__instance);
			FilterBar.AfterGameRebuild(__instance);
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "Hide")]
	internal static class InventoryGui_Hide_Patch
	{
		private static void Postfix()
		{
			FilterBar.OnInventoryHidden();
		}
	}
	[HarmonyPatch(typeof(Chat), "HasFocus")]
	internal static class Chat_HasFocus_Patch
	{
		private static void Postfix(ref bool __result)
		{
			if (!__result && FilterBar.IsSearchFocused)
			{
				__result = true;
			}
		}
	}
	[BepInPlugin("adrirf7.WorkbenchSearchFilters", "WorkbenchSearchFilters", "1.1.0")]
	public class WorkbenchSearchFiltersPlugin : BaseUnityPlugin
	{
		public const string ModGuid = "adrirf7.WorkbenchSearchFilters";

		public const string ModName = "WorkbenchSearchFilters";

		public const string ModVersion = "1.1.0";

		internal static ManualLogSource Log;

		private Harmony _harmony;

		internal static ConfigEntry<bool> ClearSearchOnClose;

		internal static ConfigEntry<bool> RememberCategory;

		internal static ConfigEntry<string> CategoryOverrides;

		private void Awake()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: 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: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			ConfigFile val = new ConfigFile(Path.Combine(Paths.ConfigPath, "WorkbenchSearchFilters.adrirf7.cfg"), true, ((BaseUnityPlugin)this).Info.Metadata);
			ClearSearchOnClose = val.Bind<bool>("General", "ClearSearchOnClose", true, "true = the search text is cleared every time the inventory is closed.");
			RememberCategory = val.Bind<bool>("General", "RememberCategory", true, "true = the selected category is kept when the inventory is closed and opened again; false = it goes back to 'All' every time.");
			CategoryOverrides = val.Bind<string>("Categories", "CategoryOverrides", "Tankard:Misc,TankardOdin:Misc,Tankard_dvergr:Misc,TankardAnniversary:Misc", "Force the category of specific items, as Prefab:Category separated by commas. Categories: Weapons, Armor, Tools, Consumables, Materials, Misc; at the cauldron and the food preparation table: FoodStamina, FoodHealth, FoodEitr, FoodBalanced, Meads, Misc. The prefab name and current category of every craftable item are listed in WorkbenchSearchFilters.adrirf7.Categories.txt (generated when entering a world).");
			CategoryOverrides.SettingChanged += delegate
			{
				Categories.ResetCache();
			};
			_harmony = new Harmony("adrirf7.WorkbenchSearchFilters");
			_harmony.PatchAll();
			Translations.Register(Localization.instance, Localization.instance.GetSelectedLanguage());
			Log.LogInfo((object)"WorkbenchSearchFilters 1.1.0 loaded.");
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			FilterBar.Teardown();
		}
	}
	internal static class Translations
	{
		private const string DefaultLanguage = "English";

		private static readonly string[] s_keys = new string[13]
		{
			"wsf_search", "wsf_cat_all", "wsf_cat_weapons", "wsf_cat_armor", "wsf_cat_tools", "wsf_cat_consumables", "wsf_cat_materials", "wsf_cat_misc", "wsf_cat_foodstamina", "wsf_cat_foodhealth",
			"wsf_cat_foodeitr", "wsf_cat_foodbalanced", "wsf_cat_meads"
		};

		private static readonly Dictionary<string, string[]> s_languages = new Dictionary<string, string[]>
		{
			["English"] = new string[13]
			{
				"Search...", "All", "Weapons", "Armor", "Tools", "Consumables", "Materials", "Misc", "Stamina food", "Health food",
				"Eitr food", "Balanced food", "Meads"
			},
			["Spanish"] = new string[13]
			{
				"Buscar...", "Todo", "Armas", "Armaduras", "Herramientas", "Consumibles", "Materiales", "Otros", "Comida de vigor", "Comida de vida",
				"Comida de eitr", "Comida equilibrada", "Hidromieles"
			},
			["German"] = new string[13]
			{
				"Suchen...", "Alle", "Waffen", "Rüstung", "Werkzeuge", "Verbrauchsgüter", "Materialien", "Sonstiges", "Ausdauer-Essen", "Lebens-Essen",
				"Eitr-Essen", "Ausgewogenes Essen", "Met"
			},
			["French"] = new string[13]
			{
				"Rechercher...", "Tout", "Armes", "Armures", "Outils", "Consommables", "Matériaux", "Divers", "Nourriture d'endurance", "Nourriture de santé",
				"Nourriture d'eitr", "Nourriture équilibrée", "Hydromels"
			},
			["Italian"] = new string[13]
			{
				"Cerca...", "Tutto", "Armi", "Armature", "Strumenti", "Consumabili", "Materiali", "Varie", "Cibo per la resistenza", "Cibo per la salute",
				"Cibo per l'eitr", "Cibo bilanciato", "Idromele"
			},
			["Portuguese_Brazilian"] = new string[13]
			{
				"Pesquisar...", "Tudo", "Armas", "Armaduras", "Ferramentas", "Consumíveis", "Materiais", "Outros", "Comida de vigor", "Comida de vida",
				"Comida de eitr", "Comida equilibrada", "Hidroméis"
			},
			["Portuguese_European"] = new string[13]
			{
				"Pesquisar...", "Tudo", "Armas", "Armaduras", "Ferramentas", "Consumíveis", "Materiais", "Outros", "Comida de vigor", "Comida de vida",
				"Comida de eitr", "Comida equilibrada", "Hidroméis"
			},
			["Russian"] = new string[13]
			{
				"Поиск...", "Все", "Оружие", "Броня", "Инструменты", "Расходники", "Материалы", "Прочее", "Еда на выносливость", "Еда на здоровье",
				"Еда на эйтр", "Сбалансированная еда", "Медовуха"
			},
			["Ukrainian"] = new string[13]
			{
				"Пошук...", "Усе", "Зброя", "Броня", "Інструменти", "Витратні", "Матеріали", "Інше", "Їжа на витривалість", "Їжа на здоров'я",
				"Їжа на ейтр", "Збалансована їжа", "Медовуха"
			},
			["Polish"] = new string[13]
			{
				"Szukaj...", "Wszystko", "Broń", "Pancerz", "Narzędzia", "Konsumpcyjne", "Materiały", "Inne", "Jedzenie na wytrzymałość", "Jedzenie na zdrowie",
				"Jedzenie na eitr", "Zbilansowane jedzenie", "Miody pitne"
			},
			["Czech"] = new string[13]
			{
				"Hledat...", "Vše", "Zbraně", "Zbroj", "Nástroje", "Spotřební", "Materiály", "Ostatní", "Jídlo na výdrž", "Jídlo na zdraví",
				"Jídlo na eitr", "Vyvážené jídlo", "Medoviny"
			},
			["Dutch"] = new string[13]
			{
				"Zoeken...", "Alles", "Wapens", "Pantser", "Gereedschap", "Verbruiksartikelen", "Materialen", "Overig", "Uithoudingsvoedsel", "Gezondheidsvoedsel",
				"Eitr-voedsel", "Gebalanceerd voedsel", "Mede"
			},
			["Swedish"] = new string[13]
			{
				"Sök...", "Alla", "Vapen", "Rustning", "Verktyg", "Förbrukningsvaror", "Material", "Övrigt", "Uthållighetsmat", "Hälsomat",
				"Eitr-mat", "Balanserad mat", "Mjöd"
			},
			["Norwegian"] = new string[13]
			{
				"Søk...", "Alle", "Våpen", "Rustning", "Verktøy", "Forbruksvarer", "Materialer", "Diverse", "Utholdenhetsmat", "Helsemat",
				"Eitr-mat", "Balansert mat", "Mjød"
			},
			["Danish"] = new string[13]
			{
				"Søg...", "Alle", "Våben", "Rustning", "Værktøj", "Forbrugsvarer", "Materialer", "Diverse", "Udholdenhedsmad", "Helbredsmad",
				"Eitr-mad", "Balanceret mad", "Mjød"
			},
			["Finnish"] = new string[13]
			{
				"Hae...", "Kaikki", "Aseet", "Panssarit", "Työkalut", "Kulutustavarat", "Materiaalit", "Muut", "Kestävyysruoka", "Terveysruoka",
				"Eitr-ruoka", "Tasapainoinen ruoka", "Simat"
			},
			["Turkish"] = new string[13]
			{
				"Ara...", "Tümü", "Silahlar", "Zırhlar", "Aletler", "Sarf Malzemeleri", "Malzemeler", "Diğer", "Dayanıklılık yemeği", "Sağlık yemeği",
				"Eitr yemeği", "Dengeli yemek", "Bal şarapları"
			},
			["Hungarian"] = new string[13]
			{
				"Keresés...", "Mind", "Fegyverek", "Páncélok", "Eszközök", "Fogyóeszközök", "Nyersanyagok", "Egyéb", "Állóképesség-étel", "Életerő-étel",
				"Eitr-étel", "Kiegyensúlyozott étel", "Mézborok"
			},
			["Chinese"] = new string[13]
			{
				"搜索...", "全部", "武器", "护甲", "工具", "消耗品", "材料", "其他", "耐力食物", "生命食物",
				"艾特食物", "均衡食物", "蜂蜜酒"
			},
			["Chinese_Trad"] = new string[13]
			{
				"搜尋...", "全部", "武器", "護甲", "工具", "消耗品", "材料", "其他", "耐力食物", "生命食物",
				"艾特食物", "均衡食物", "蜂蜜酒"
			},
			["Japanese"] = new string[13]
			{
				"検索...", "すべて", "武器", "防具", "道具", "消耗品", "素材", "その他", "スタミナ料理", "体力料理",
				"エイトル料理", "バランス料理", "ミード"
			},
			["Korean"] = new string[13]
			{
				"검색...", "전체", "무기", "방어구", "도구", "소모품", "재료", "기타", "기력 음식", "체력 음식",
				"에이트르 음식", "균형 음식", "미드"
			}
		};

		internal static void Register(Localization localization, string language)
		{
			if (!s_languages.TryGetValue(language, out var value))
			{
				value = s_languages["English"];
			}
			for (int i = 0; i < s_keys.Length; i++)
			{
				localization.AddWord(s_keys[i], value[i]);
			}
		}
	}
	[HarmonyPatch(typeof(Localization), "SetupLanguage")]
	internal static class Localization_SetupLanguage_Patch
	{
		private static void Postfix(Localization __instance, string language)
		{
			Translations.Register(__instance, language);
			FilterBar.RefreshTexts();
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}