Decompiled source of CraftMenu v0.1.23

plugins/CraftMenu.dll

Decompiled a day ago
using System;
using System.Collections;
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.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GUIFramework;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.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 CraftMenu
{
	internal static class Biomes
	{
		internal enum Tier
		{
			None,
			Meadows,
			BlackForest,
			Swamp,
			Mountain,
			Plains,
			Mistlands,
			Ashlands,
			DeepNorth
		}

		private static readonly Dictionary<string, Tier> Materials = new Dictionary<string, Tier>(StringComparer.OrdinalIgnoreCase)
		{
			{
				"Copper",
				Tier.BlackForest
			},
			{
				"CopperOre",
				Tier.BlackForest
			},
			{
				"Tin",
				Tier.BlackForest
			},
			{
				"TinOre",
				Tier.BlackForest
			},
			{
				"Bronze",
				Tier.BlackForest
			},
			{
				"BronzeNails",
				Tier.BlackForest
			},
			{
				"RoundLog",
				Tier.BlackForest
			},
			{
				"FineWood",
				Tier.BlackForest
			},
			{
				"TrollHide",
				Tier.BlackForest
			},
			{
				"SurtlingCore",
				Tier.BlackForest
			},
			{
				"Thistle",
				Tier.BlackForest
			},
			{
				"GreydwarfEye",
				Tier.BlackForest
			},
			{
				"Blueberries",
				Tier.BlackForest
			},
			{
				"Carrot",
				Tier.BlackForest
			},
			{
				"Coal",
				Tier.BlackForest
			},
			{
				"Iron",
				Tier.Swamp
			},
			{
				"IronScrap",
				Tier.Swamp
			},
			{
				"IronNails",
				Tier.Swamp
			},
			{
				"Chain",
				Tier.Swamp
			},
			{
				"ElderBark",
				Tier.Swamp
			},
			{
				"Guck",
				Tier.Swamp
			},
			{
				"Bloodbag",
				Tier.Swamp
			},
			{
				"Entrails",
				Tier.Swamp
			},
			{
				"Turnip",
				Tier.Swamp
			},
			{
				"Ooze",
				Tier.Swamp
			},
			{
				"WitheredBone",
				Tier.Swamp
			},
			{
				"Root",
				Tier.Swamp
			},
			{
				"Silver",
				Tier.Mountain
			},
			{
				"SilverOre",
				Tier.Mountain
			},
			{
				"WolfPelt",
				Tier.Mountain
			},
			{
				"WolfFang",
				Tier.Mountain
			},
			{
				"Obsidian",
				Tier.Mountain
			},
			{
				"Crystal",
				Tier.Mountain
			},
			{
				"FreezeGland",
				Tier.Mountain
			},
			{
				"DragonTear",
				Tier.Mountain
			},
			{
				"Onion",
				Tier.Mountain
			},
			{
				"WolfHairBundle",
				Tier.Mountain
			},
			{
				"JuteRed",
				Tier.Mountain
			},
			{
				"WolfClaw",
				Tier.Mountain
			},
			{
				"BlackMetal",
				Tier.Plains
			},
			{
				"BlackMetalScrap",
				Tier.Plains
			},
			{
				"LinenThread",
				Tier.Plains
			},
			{
				"Flax",
				Tier.Plains
			},
			{
				"Barley",
				Tier.Plains
			},
			{
				"LoxPelt",
				Tier.Plains
			},
			{
				"Needle",
				Tier.Plains
			},
			{
				"Tar",
				Tier.Plains
			},
			{
				"Cloudberry",
				Tier.Plains
			},
			{
				"Fuling",
				Tier.Plains
			},
			{
				"Tunic",
				Tier.Plains
			},
			{
				"YggdrasilWood",
				Tier.Mistlands
			},
			{
				"Eitr",
				Tier.Mistlands
			},
			{
				"Softtissue",
				Tier.Mistlands
			},
			{
				"BlackMarble",
				Tier.Mistlands
			},
			{
				"Carapace",
				Tier.Mistlands
			},
			{
				"ScaleHide",
				Tier.Mistlands
			},
			{
				"Mandible",
				Tier.Mistlands
			},
			{
				"Sap",
				Tier.Mistlands
			},
			{
				"JuteBlue",
				Tier.Mistlands
			},
			{
				"RoyalJelly",
				Tier.Mistlands
			},
			{
				"MushroomMagecap",
				Tier.Mistlands
			},
			{
				"MushroomJotunPuffs",
				Tier.Mistlands
			},
			{
				"BlackCore",
				Tier.Mistlands
			},
			{
				"Wisp",
				Tier.Mistlands
			},
			{
				"Bilebag",
				Tier.Mistlands
			},
			{
				"CeramicPlate",
				Tier.Mistlands
			},
			{
				"Sword_Mistwalker",
				Tier.Mistlands
			},
			{
				"FlametalNew",
				Tier.Ashlands
			},
			{
				"FlametalOreNew",
				Tier.Ashlands
			},
			{
				"Flametal",
				Tier.Ashlands
			},
			{
				"CharcoalResin",
				Tier.Ashlands
			},
			{
				"AskHide",
				Tier.Ashlands
			},
			{
				"AskBladder",
				Tier.Ashlands
			},
			{
				"MorgenSinew",
				Tier.Ashlands
			},
			{
				"MorgenHeart",
				Tier.Ashlands
			},
			{
				"Grausten",
				Tier.Ashlands
			},
			{
				"Blackwood",
				Tier.Ashlands
			},
			{
				"BonemawSerpentTooth",
				Tier.Ashlands
			},
			{
				"BonemawSerpentScale",
				Tier.Ashlands
			},
			{
				"ProustitePowder",
				Tier.Ashlands
			},
			{
				"VoltureEgg",
				Tier.Ashlands
			},
			{
				"CelestialFeather",
				Tier.Ashlands
			},
			{
				"GemstoneBlue",
				Tier.Ashlands
			},
			{
				"GemstoneGreen",
				Tier.Ashlands
			},
			{
				"GemstoneRed",
				Tier.Ashlands
			},
			{
				"MoltenCore",
				Tier.Ashlands
			},
			{
				"Vineberry",
				Tier.Ashlands
			},
			{
				"SulfurStone",
				Tier.Ashlands
			},
			{
				"FaderDrop",
				Tier.Ashlands
			},
			{
				"Pot_Shard_Green",
				Tier.Ashlands
			},
			{
				"ShieldCore",
				Tier.Ashlands
			},
			{
				"DvergrNeedle",
				Tier.Ashlands
			},
			{
				"AsksvinPelt",
				Tier.Ashlands
			}
		};

		private static readonly Dictionary<Tier, string> Trophies = new Dictionary<Tier, string>
		{
			{
				Tier.Meadows,
				"TrophyEikthyr"
			},
			{
				Tier.BlackForest,
				"TrophyTheElder"
			},
			{
				Tier.Swamp,
				"TrophyBonemass"
			},
			{
				Tier.Mountain,
				"TrophyDragonQueen"
			},
			{
				Tier.Plains,
				"TrophyGoblinKing"
			},
			{
				Tier.Mistlands,
				"TrophySeekerQueen"
			},
			{
				Tier.Ashlands,
				"TrophyFader"
			},
			{
				Tier.DeepNorth,
				"TrophyFader"
			}
		};

		private static readonly Dictionary<Recipe, Tier> cache = new Dictionary<Recipe, Tier>();

		private static readonly Dictionary<Tier, Sprite> icons = new Dictionary<Tier, Sprite>();

		internal static Tier Of(Recipe recipe)
		{
			if ((Object)(object)recipe == (Object)null)
			{
				return Tier.None;
			}
			if (cache.TryGetValue(recipe, out var value))
			{
				return value;
			}
			value = Tier.Meadows;
			Requirement[] resources = recipe.m_resources;
			foreach (Requirement val in resources)
			{
				if ((Object)(object)val.m_resItem == (Object)null)
				{
					continue;
				}
				string name = ((Object)((Component)val.m_resItem).gameObject).name;
				if (Materials.TryGetValue(name, out var value2) && value2 > value)
				{
					value = value2;
				}
				else
				{
					if (Materials.ContainsKey(name) || !((Object)(object)ObjectDB.instance != (Object)null))
					{
						continue;
					}
					Recipe recipe2 = ObjectDB.instance.GetRecipe(val.m_resItem.m_itemData);
					Tier value3;
					if ((Object)(object)recipe2 != (Object)null && (Object)(object)recipe2 != (Object)(object)recipe && !cache.ContainsKey(recipe2))
					{
						cache[recipe2] = Tier.Meadows;
						Tier tier = Of(recipe2);
						if (tier > value)
						{
							value = tier;
						}
					}
					else if ((Object)(object)recipe2 != (Object)null && cache.TryGetValue(recipe2, out value3) && value3 > value)
					{
						value = value3;
					}
				}
			}
			return cache[recipe] = value;
		}

		internal static string Name(Tier t)
		{
			return t switch
			{
				Tier.Meadows => Plugin.T("Луга", "Meadows"), 
				Tier.BlackForest => Plugin.T("Чёрный лес", "Black Forest"), 
				Tier.Swamp => Plugin.T("Болота", "Swamp"), 
				Tier.Mountain => Plugin.T("Горы", "Mountain"), 
				Tier.Plains => Plugin.T("Равнины", "Plains"), 
				Tier.Mistlands => Plugin.T("Туманные земли", "Mistlands"), 
				Tier.Ashlands => Plugin.T("Пепельные земли", "Ashlands"), 
				Tier.DeepNorth => Plugin.T("Глубокий север", "Deep North"), 
				_ => "", 
			};
		}

		internal static Sprite Icon(Tier t)
		{
			if (icons.TryGetValue(t, out var value))
			{
				return value;
			}
			value = null;
			if (Trophies.TryGetValue(t, out var value2) && (Object)(object)ObjectDB.instance != (Object)null)
			{
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(value2);
				ItemDrop val = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null);
				if ((Object)(object)val != (Object)null && val.m_itemData.m_shared.m_icons != null && val.m_itemData.m_shared.m_icons.Length != 0)
				{
					value = val.m_itemData.m_shared.m_icons[0];
				}
			}
			if ((Object)(object)value != (Object)null)
			{
				icons[t] = value;
			}
			return value;
		}

		internal static void Clear()
		{
			cache.Clear();
			icons.Clear();
		}
	}
	internal static class Categories
	{
		internal sealed class Category
		{
			internal string Key;

			internal string Sprite;

			internal string Ru;

			internal string En;

			internal string Name => Plugin.T(Ru, En);
		}

		internal const string All = "all";

		internal const string Melee = "melee";

		internal const string Ranged = "ranged";

		internal const string Magic = "magic";

		internal const string Ammo = "ammo";

		internal const string Shields = "shields";

		internal const string Armor = "armor";

		internal const string Tools = "tools";

		internal const string Food = "food";

		internal const string Meads = "meads";

		internal const string Materials = "materials";

		internal const string Trophies = "trophies";

		internal const string Misc = "misc";

		internal static readonly Category[] List = new Category[13]
		{
			new Category
			{
				Key = "all",
				Sprite = "category_all",
				Ru = "Все",
				En = "All"
			},
			new Category
			{
				Key = "melee",
				Sprite = "category_melee",
				Ru = "Ближний бой",
				En = "Melee"
			},
			new Category
			{
				Key = "ranged",
				Sprite = "category_ranged",
				Ru = "Дальний бой",
				En = "Ranged"
			},
			new Category
			{
				Key = "magic",
				Sprite = "category_magic",
				Ru = "Магия",
				En = "Magic"
			},
			new Category
			{
				Key = "ammo",
				Sprite = "category_arrows",
				Ru = "Стрелы и болты",
				En = "Arrows and bolts"
			},
			new Category
			{
				Key = "shields",
				Sprite = "category_shields",
				Ru = "Щиты",
				En = "Shields"
			},
			new Category
			{
				Key = "armor",
				Sprite = "category_armor",
				Ru = "Броня",
				En = "Armor"
			},
			new Category
			{
				Key = "tools",
				Sprite = "category_tools",
				Ru = "Инструменты",
				En = "Tools"
			},
			new Category
			{
				Key = "food",
				Sprite = "category_food",
				Ru = "Еда",
				En = "Food"
			},
			new Category
			{
				Key = "meads",
				Sprite = "category_meads",
				Ru = "Медовухи",
				En = "Meads"
			},
			new Category
			{
				Key = "materials",
				Sprite = "category_materials",
				Ru = "Материалы",
				En = "Materials"
			},
			new Category
			{
				Key = "trophies",
				Sprite = "category_trophies",
				Ru = "Трофеи",
				En = "Trophies"
			},
			new Category
			{
				Key = "misc",
				Sprite = "category_misc",
				Ru = "Прочее",
				En = "Other"
			}
		};

		internal static Category Find(string key)
		{
			return List.FirstOrDefault((Category c) => c.Key == key) ?? List[0];
		}

		internal static string Of(SharedData shared)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: 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_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected I4, but got Unknown
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Invalid comparison between Unknown and I4
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Invalid comparison between Unknown and I4
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Invalid comparison between Unknown and I4
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Invalid comparison between Unknown and I4
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Invalid comparison between Unknown and I4
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Invalid comparison between Unknown and I4
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Invalid comparison between Unknown and I4
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Invalid comparison between Unknown and I4
			if (shared == null)
			{
				return "misc";
			}
			SkillType skillType = shared.m_skillType;
			ItemType itemType = shared.m_itemType;
			switch (itemType - 1)
			{
			case 2:
			case 3:
			case 13:
			case 19:
			case 21:
				if ((int)skillType == 9 || (int)skillType == 10)
				{
					return "magic";
				}
				if ((int)skillType == 8 || (int)skillType == 14 || (int)shared.m_itemType == 4)
				{
					return "ranged";
				}
				if ((int)skillType == 12 || ((int)skillType == 7 && (int)shared.m_itemType == 3))
				{
					return "tools";
				}
				return "melee";
			case 4:
				return "shields";
			case 8:
			case 22:
				return "ammo";
			case 5:
			case 6:
			case 10:
			case 11:
			case 16:
			case 17:
			case 23:
				return "armor";
			case 14:
			case 18:
				return "tools";
			case 1:
				if (!(shared.m_food > 0f) && !(shared.m_foodStamina > 0f) && !(shared.m_foodEitr > 0f))
				{
					return "meads";
				}
				return "food";
			case 0:
				return "materials";
			case 12:
				return "trophies";
			default:
				return "misc";
			}
		}
	}
	internal static class Craft
	{
		internal static int Amount = 1;

		private static int batch = -1;

		internal const int MaxAmount = 99;

		internal static int Batch
		{
			get
			{
				if (batch <= 0)
				{
					return 5;
				}
				return batch;
			}
		}

		internal static bool BatchHeld
		{
			get
			{
				if (!ZInput.GetButton("AltPlace"))
				{
					return ZInput.GetButton("JoyLStick");
				}
				return true;
			}
		}

		internal static int Now
		{
			get
			{
				if (Amount > 1 || !BatchHeld)
				{
					return Amount;
				}
				return Batch;
			}
		}

		internal static bool InProgress
		{
			get
			{
				if ((Object)(object)InventoryGui.instance != (Object)null)
				{
					return InventoryGui.instance.m_craftTimer >= 0f;
				}
				return false;
			}
		}

		internal static void ReadBatch(InventoryGui inv)
		{
			if (batch < 0 && (Object)(object)inv != (Object)null)
			{
				batch = Mathf.Max(2, inv.m_multiCraftAmount);
			}
		}

		internal static float Duration(InventoryGui inv, Recipe recipe, ItemData upgrade, int amount)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			CraftingStation currentCraftingStation = Player.m_localPlayer.GetCurrentCraftingStation();
			bool num = (Object)(object)currentCraftingStation != (Object)null && currentCraftingStation.m_upgrader;
			int num2 = ((upgrade == null) ? 1 : (upgrade.m_quality + 1));
			float num3 = (num ? (inv.m_upgraderDuration + (float)num2 * inv.m_upgraderDurationPerLevel) : ((amount > 1) ? inv.m_multiCraftDuration : inv.m_craftDuration));
			if ((Object)(object)currentCraftingStation != (Object)null && (int)currentCraftingStation.m_craftingSkill != 0)
			{
				num3 *= 1f - ((Character)Player.m_localPlayer).GetSkillFactor(currentCraftingStation.m_craftingSkill) * inv.m_craftDurationSkillMaxDecrease;
			}
			return num3;
		}

		internal static bool Can(Recipes.Entry e, int amount, out string why)
		{
			why = "";
			InventoryGui instance = InventoryGui.instance;
			Player localPlayer = Player.m_localPlayer;
			if (e == null || (Object)(object)instance == (Object)null || (Object)(object)localPlayer == (Object)null)
			{
				return false;
			}
			CraftingStation currentCraftingStation = localPlayer.GetCurrentCraftingStation();
			bool flag = (Object)(object)currentCraftingStation != (Object)null && currentCraftingStation.m_upgrader;
			int num = ((e.Item == null) ? 1 : (e.Item.m_quality + 1));
			bool flag2 = localPlayer.NoCostCheat();
			bool flag3 = flag2 || ZoneSystem.instance.GetGlobalKey((GlobalKeys)25);
			if (num > e.Shared.m_maxQuality && !flag)
			{
				why = Localization.instance.Localize("$inventory_maxquality");
				return false;
			}
			if (!flag2)
			{
				CraftingStation requiredStation = e.Recipe.GetRequiredStation(num);
				if (!((Object)(object)requiredStation == (Object)null) && (!((Object)(object)currentCraftingStation != (Object)null) || !currentCraftingStation.CheckUsable(localPlayer, false)))
				{
					why = Localization.instance.Localize("$msg_missingstation");
					return false;
				}
				int num2 = (flag ? 1 : e.Recipe.GetRequiredStationLevel(num));
				if ((Object)(object)requiredStation != (Object)null && !flag3 && ((Object)(object)currentCraftingStation == (Object)null || currentCraftingStation.GetLevel(true) < num2))
				{
					why = Localization.instance.Localize("$msg_missingstation");
					return false;
				}
				if (!flag3 && !localPlayer.HaveRequirements(e.Recipe, false, num, amount))
				{
					why = Localization.instance.Localize("$msg_missingrequirement");
					return false;
				}
			}
			if (e.Item == null)
			{
				int num3 = e.Recipe.m_amount * amount;
				if (!((Humanoid)localPlayer).GetInventory().CanAddItem(((Component)e.Recipe.m_item).gameObject, num3))
				{
					why = Localization.instance.Localize("$inventory_full");
					return false;
				}
			}
			return true;
		}

		internal static void Start(Recipes.Entry e, int amount)
		{
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: 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_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			InventoryGui instance = InventoryGui.instance;
			Player localPlayer = Player.m_localPlayer;
			if (e == null || (Object)(object)instance == (Object)null || (Object)(object)localPlayer == (Object)null || InProgress)
			{
				return;
			}
			amount = Mathf.Clamp(amount, 1, 99);
			if (e.Item != null)
			{
				amount = 1;
			}
			if (!Can(e, amount, out var why))
			{
				if (why.Length > 0)
				{
					((Character)localPlayer).Message((MessageType)2, why, 0, (Sprite)null, false);
				}
				return;
			}
			instance.m_craftRecipe = e.Recipe;
			instance.m_craftUpgradeItem = e.Item;
			instance.m_craftVariant = instance.m_selectedVariant;
			instance.m_multiCrafting = e.Item == null && amount > 1;
			if (instance.m_multiCrafting)
			{
				instance.m_multiCraftAmount = amount;
			}
			CraftingStation currentCraftingStation = localPlayer.GetCurrentCraftingStation();
			if (e.Item != null && (Object)(object)currentCraftingStation != (Object)null && currentCraftingStation.m_upgrader)
			{
				int num = 0;
				Requirement[] resources = e.Recipe.m_resources;
				for (int i = 0; i < resources.Length; i++)
				{
					if (resources[i].m_recover)
					{
						num++;
					}
				}
				if (num + 1 > ((Humanoid)localPlayer).GetInventory().GetEmptySlots())
				{
					((Character)localPlayer).Message((MessageType)2, "$inventory_needspace", 0, (Sprite)null, false);
					return;
				}
			}
			instance.m_craftTimer = 0f;
			if ((Object)(object)e.Recipe.m_craftingStation != (Object)null)
			{
				if ((Object)(object)currentCraftingStation != (Object)null)
				{
					currentCraftingStation.m_craftItemEffects.Create(((Component)localPlayer).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
				}
			}
			else
			{
				instance.m_craftItemEffects.Create(((Component)localPlayer).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
			}
		}

		internal static void Cancel()
		{
			InventoryGui instance = InventoryGui.instance;
			if ((Object)(object)instance != (Object)null && instance.m_craftTimer >= 0f)
			{
				instance.m_craftTimer = -1f;
			}
		}

		internal static void ChooseVariant(Recipes.Entry e)
		{
			InventoryGui instance = InventoryGui.instance;
			if (e != null && !((Object)(object)instance == (Object)null) && !((Object)(object)instance.m_variantDialog == (Object)null))
			{
				instance.m_variantDialog.Setup(e.Recipe.m_item.m_itemData);
			}
		}
	}
	internal static class Dismantle
	{
		internal static bool Possible(ItemData item, out Recipe recipe)
		{
			recipe = null;
			if (item == null || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return false;
			}
			recipe = ObjectDB.instance.GetRecipe(item);
			if ((Object)(object)recipe == (Object)null || recipe.m_resources == null || recipe.m_resources.Length == 0)
			{
				return false;
			}
			return Returns(item, recipe, 1).Count > 0;
		}

		internal static bool Allowed(ItemData item, Recipe recipe)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)recipe == (Object)null)
			{
				return false;
			}
			if (localPlayer.NoCostCheat())
			{
				return true;
			}
			CraftingStation requiredStation = recipe.GetRequiredStation(item.m_quality);
			if ((Object)(object)requiredStation == (Object)null)
			{
				return true;
			}
			CraftingStation currentCraftingStation = localPlayer.GetCurrentCraftingStation();
			if ((Object)(object)currentCraftingStation != (Object)null && currentCraftingStation.m_name == requiredStation.m_name && currentCraftingStation.GetLevel(true) >= recipe.GetRequiredStationLevel(item.m_quality))
			{
				return currentCraftingStation.CheckUsable(localPlayer, false);
			}
			return false;
		}

		internal static List<(ItemDrop item, int amount)> Returns(ItemData item, Recipe recipe, int count)
		{
			List<(ItemDrop, int)> list = new List<(ItemDrop, int)>();
			float num = (float)Mathf.Clamp(Plugin.DismantlePercent.Value, 0, 100) / 100f;
			Requirement[] resources = recipe.m_resources;
			foreach (Requirement val in resources)
			{
				if (!((Object)(object)val.m_resItem == (Object)null))
				{
					int num2 = 0;
					for (int j = 1; j <= Mathf.Max(1, item.m_quality); j++)
					{
						num2 += val.GetAmount(j);
					}
					int num3 = Mathf.FloorToInt((float)num2 * num) * count;
					if (num3 > 0)
					{
						list.Add((val.m_resItem, num3));
					}
				}
			}
			return list;
		}

		internal static void Run(Recipes.Entry e, int count)
		{
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (e == null || e.Item == null || (Object)(object)localPlayer == (Object)null || !Plugin.DismantleTab.Value)
			{
				return;
			}
			Inventory inventory = ((Humanoid)localPlayer).GetInventory();
			if (!inventory.ContainsItem(e.Item) || !Allowed(e.Item, e.Recipe))
			{
				return;
			}
			count = Mathf.Clamp(count, 1, e.Item.m_stack);
			List<(ItemDrop, int)> list = Returns(e.Item, e.Recipe, count);
			if (list.Count == 0 || !inventory.RemoveItem(e.Item, count))
			{
				return;
			}
			long playerID = localPlayer.GetPlayerID();
			string playerName = localPlayer.GetPlayerName();
			foreach (var item in list)
			{
				var (val, num) = item;
				while (num > 0)
				{
					int num2 = Mathf.Min(num, Mathf.Max(1, val.m_itemData.m_shared.m_maxStackSize));
					num -= num2;
					if (inventory.AddItem(((Object)((Component)val).gameObject).name, num2, 1, 0, playerID, playerName, false, false) == null)
					{
						ItemData obj = val.m_itemData.Clone();
						obj.m_dropPrefab = ((Component)val).gameObject;
						obj.m_stack = num2;
						ItemDrop.DropItem(obj, num2, ((Component)localPlayer).transform.position + ((Component)localPlayer).transform.forward + Vector3.up, ((Component)localPlayer).transform.rotation);
					}
				}
			}
			CraftingStation currentCraftingStation = localPlayer.GetCurrentCraftingStation();
			if ((Object)(object)currentCraftingStation != (Object)null)
			{
				currentCraftingStation.m_craftItemDoneEffects.Create(((Component)localPlayer).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
			}
			((Character)localPlayer).Message((MessageType)2, Plugin.T("Разобрано: ", "Dismantled: ") + Localization.instance.Localize(e.Shared.m_name) + ((count > 1) ? (" x" + count) : ""), 0, (Sprite)null, false);
			Window.Rebuild();
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "Awake")]
	internal static class AttachWindow
	{
		private static void Postfix(InventoryGui __instance)
		{
			try
			{
				if (Plugin.Enabled.Value)
				{
					Window.Attach(__instance);
				}
			}
			catch (Exception ex)
			{
				Plugin.Warn("crafting window: " + ex);
			}
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "UpdateCraftingPanel")]
	internal static class ListFilled
	{
		private static void Postfix()
		{
			try
			{
				if (Plugin.Enabled.Value)
				{
					Window.OnGameList();
				}
			}
			catch (Exception ex)
			{
				Plugin.Warn("recipe list: " + ex);
			}
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "Hide")]
	internal static class Closed
	{
		private static void Postfix()
		{
			try
			{
				if (Plugin.Enabled.Value)
				{
					Window.OnHide();
				}
			}
			catch (Exception ex)
			{
				Plugin.Warn("close: " + ex.Message);
			}
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "OnVariantSelected")]
	internal static class VariantChosen
	{
		private static void Postfix()
		{
			try
			{
				if (Plugin.Enabled.Value)
				{
					Window.RefreshCard();
				}
			}
			catch (Exception ex)
			{
				Plugin.Warn("variant: " + ex.Message);
			}
		}
	}
	[BepInPlugin("chistix.craftmenu", "CraftMenu", "0.1.23")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Guid = "chistix.craftmenu";

		public const string Version = "0.1.23";

		private static ManualLogSource log;

		internal static ConfigFile Cfg;

		internal static string Folder;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<bool> Wide;

		internal static ConfigEntry<bool> Portrait3D;

		internal static ConfigEntry<bool> ShowPreview;

		internal static ConfigEntry<bool> OnlyAvailable;

		internal static ConfigEntry<bool> ListView;

		internal static ConfigEntry<bool> FavouritesOnly;

		internal static ConfigEntry<bool> CentreStrip;

		internal static ConfigEntry<bool> DismantleTab;

		internal static ConfigEntry<bool> VneiCategories;

		internal static ConfigEntry<bool> DebugLog;

		internal static ConfigEntry<int> Sort;

		internal static ConfigEntry<int> DismantlePercent;

		internal static ConfigEntry<int> Columns;

		internal static ConfigEntry<int> Rows;

		internal static ConfigEntry<int> CategoriesInRow;

		internal static ConfigEntry<int> Look;

		internal static ConfigEntry<int> WindowWidth;

		internal static ConfigEntry<int> WindowHeight;

		internal static ConfigEntry<int> WindowRaise;

		internal static ConfigEntry<int> VneiSort;

		internal const float NarrowWidth = 640f;

		internal const float WideWidth = 940f;

		internal static bool Russian
		{
			get
			{
				if (Localization.instance != null)
				{
					return Localization.instance.GetSelectedLanguage() == "Russian";
				}
				return false;
			}
		}

		private void Awake()
		{
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Expected O, but got Unknown
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Expected O, but got Unknown
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Expected O, but got Unknown
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Expected O, but got Unknown
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Expected O, but got Unknown
			//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bb: Expected O, but got Unknown
			//IL_0304: Unknown result type (might be due to invalid IL or missing references)
			//IL_030e: Expected O, but got Unknown
			//IL_0364: Unknown result type (might be due to invalid IL or missing references)
			//IL_036e: Expected O, but got Unknown
			//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
			log = ((BaseUnityPlugin)this).Logger;
			Cfg = ((BaseUnityPlugin)this).Config;
			Folder = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "The new crafting window. Off - the game's own (after a restart).\nНовое окно ремесла. Выключено — родное окно игры (после перезапуска).");
			Wide = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Wide", false, "The default window wide (more room for the grid and the card) instead of narrow, as wide as the character's strip; both run from under the strip to the screen's bottom. The size set by dragging the window's edges ([Window]) comes over it.\nОкно по умолчанию широкое (больше места сетке и карточке) вместо узкого шириной с полосу персонажа; оба — от полосы до низа экрана. Размер, заданный перетаскиванием краёв окна ([Window]), важнее.");
			ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes
			{
				CustomDrawer = SizeDrawer
			};
			WindowWidth = ((BaseUnityPlugin)this).Config.Bind<int>("Window", "Width", 0, new ConfigDescription("The window's width on the interface canvas, set by dragging its left or right edge; 0 - the default. Kept within the screen. A double click on an edge or a corner of the window: the default size.\nШирина окна в единицах интерфейса, задаётся перетаскиванием левого или правого края; 0 — по умолчанию. Не шире экрана. Двойной щелчок по краю или углу окна — размер по умолчанию.", (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }));
			WindowHeight = ((BaseUnityPlugin)this).Config.Bind<int>("Window", "Height", 0, "The window's height, set by dragging its top or bottom edge; 0 - the default (from under the character's strip to the screen's bottom).\nВысота окна, задаётся перетаскиванием верхнего или нижнего края; 0 — по умолчанию (от полосы персонажа до низа экрана).");
			WindowRaise = ((BaseUnityPlugin)this).Config.Bind<int>("Window", "Raise", 0, "How far the window's top stands above its default place under the character's strip (its top edge dragged up). Over the strip, the strip folds into a bar with the player's name and an arrow.\nНа сколько верх окна выше своего места под полосой персонажа (верхний край вытянут вверх). Если окно заходит на полосу, она сворачивается в полоску с именем игрока и стрелкой.");
			Look = ((BaseUnityPlugin)this).Config.Bind<int>("General", "Look", 1, new ConfigDescription("The window's surfaces: 0 the sketch cut into textures, 1 the game's own panels, buttons and frames (the icons of the sketch in both). After a restart.\nПоверхности окна: 0 — нарезка эскиза, 1 — родные панели, кнопки и рамки игры (значки эскиза в обоих). После перезапуска.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 1), Array.Empty<object>()));
			CentreStrip = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "CentreCharacterStrip", true, "The game's character strip (name, texts, skills, trophies) centred over the window.\nРодная полоса персонажа (имя, записи, навыки, трофеи) — по центру над окном.");
			Columns = ((BaseUnityPlugin)this).Config.Bind<int>("Grid", "Columns", 4, new ConfigDescription("Cards in a row of the grid.\nКарточек в ряду сетки.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(3, 8), Array.Empty<object>()));
			Rows = ((BaseUnityPlugin)this).Config.Bind<int>("Grid", "Rows", 5, new ConfigDescription("Rows of cards on a page.\nРядов карточек на странице.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(3, 8), Array.Empty<object>()));
			ShowPreview = ((BaseUnityPlugin)this).Config.Bind<bool>("Card", "ShowPreview", true, "The item's picture over its card in the grid view (the tick on the card); the list view always shows it.\nКартинка предмета в карточке в режиме сетки (галочка на карточке); в режиме списка она есть всегда.");
			Portrait3D = ((BaseUnityPlugin)this).Config.Bind<bool>("Card", "Portrait3D", true, "A live turning model of the item in the card (else the game's icon).\nЖивая поворотная модель предмета в карточке (иначе — значок игры).");
			OnlyAvailable = ((BaseUnityPlugin)this).Config.Bind<bool>("Filter", "OnlyAvailable", false, "Show only recipes you can craft now (the tick in the window).\nПоказывать только то, что можно создать сейчас (галочка в окне).");
			ListView = ((BaseUnityPlugin)this).Config.Bind<bool>("Filter", "ListView", false, "Recipes as a list instead of a grid (the switch in the window).\nРецепты списком вместо сетки (переключатель в окне).");
			FavouritesOnly = ((BaseUnityPlugin)this).Config.Bind<bool>("Filter", "FavouritesOnly", false, "Show only favourites (the star in the window).\nПоказывать только избранное (звезда в окне).");
			Sort = ((BaseUnityPlugin)this).Config.Bind<int>("Filter", "Sort", 0, new ConfigDescription("Sorting: 0 default (craftable first), 1 by name, 2 by station level, 3 by biome, 4 by weight.\nСортировка: 0 — по умолчанию (сначала доступные), 1 — по имени, 2 — по уровню станции, 3 — по биому, 4 — по весу.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, Sorting.Names.Length - 1), Array.Empty<object>()));
			CategoriesInRow = ((BaseUnityPlugin)this).Config.Bind<int>("Filter", "CategoriesInRow", 7, new ConfigDescription("Category buttons in the row; the More button turns the row to the next ones.\nКнопок категорий в ряду; кнопка «Ещё» листает ряд дальше.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(4, 13), Array.Empty<object>()));
			DismantleTab = ((BaseUnityPlugin)this).Config.Bind<bool>("Dismantle", "Enabled", true, "The Dismantle tab. Off - no tab and no dismantling.\nВкладка «Разобрать». Выключено — вкладки нет и разбирать нельзя.");
			DismantlePercent = ((BaseUnityPlugin)this).Config.Bind<int>("Dismantle", "ReturnPercent", 50, new ConfigDescription("Part of the resources (of every quality level) returned when an item is dismantled, rounded down.\nДоля ресурсов (за все уровни качества), возвращаемая при разборке предмета, с округлением вниз.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			VneiCategories = ((BaseUnityPlugin)this).Config.Bind<bool>("VNEI", "OurCategories", false, "On the VNEI tab: our categories (the window's row, as on Craft and Upgrade) over VNEI's browser; off - VNEI's own types alone. Only with VNEI installed.\nНа вкладке VNEI: наши категории (ряд окна, как на «Создать» и «Улучшить») над браузером VNEI; выключено — только его собственные типы. Только при установленном VNEI.");
			VneiSort = ((BaseUnityPlugin)this).Config.Bind<int>("VNEI", "Sort", 0, new ConfigDescription("The order of VNEI's items on the VNEI tab: 0 VNEI's own, 1 by name, 2 by station level, 3 by biome, 4 by weight (‹ › on the tab).\nПорядок предметов VNEI на вкладке VNEI: 0 — как у VNEI, 1 — по имени, 2 — по уровню станции, 3 — по биому, 4 — по весу (‹ › на вкладке).", (AcceptableValueBase)(object)new AcceptableValueList<int>(new int[5] { 0, 1, 2, 3, 4 }), Array.Empty<object>()));
			DebugLog = ((BaseUnityPlugin)this).Config.Bind<bool>("Advanced", "DebugLog", false, "More details in the log.\nПодробности в журнал.");
			((BaseUnityPlugin)this).Config.SettingChanged += delegate(object _, SettingChangedEventArgs args)
			{
				ConfigEntryBase changedSetting = args.ChangedSetting;
				if (!(changedSetting.Definition.Section == "Advanced") && (object)changedSetting != Enabled)
				{
					if (changedSetting.Definition.Section == "Window" || (object)changedSetting == Wide)
					{
						Window.Resize();
					}
					else if (changedSetting.Definition.Section == "VNEI")
					{
						Window.VneiChoices();
					}
					else
					{
						Window.Refresh();
					}
				}
			};
			new Harmony("chistix.craftmenu").PatchAll(typeof(Plugin).Assembly);
			Log("CraftMenu 0.1.23");
		}

		private void OnDestroy()
		{
			Preview.Clear();
		}

		private static void SizeDrawer(ConfigEntryBase entry)
		{
			ConfigEntry<int> val = (ConfigEntry<int>)(object)entry;
			if (int.TryParse(GUILayout.TextField(val.Value.ToString(), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) }), out var result) && result >= 0 && result != val.Value)
			{
				val.Value = result;
			}
			if (GUILayout.Button(T("Размер по умолчанию", "Default size"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) }))
			{
				Window.DefaultSize();
			}
		}

		internal static string T(string ru, string en)
		{
			if (!Russian)
			{
				return en;
			}
			return ru;
		}

		internal static void Log(string text)
		{
			ManualLogSource obj = log;
			if (obj != null)
			{
				obj.LogInfo((object)text);
			}
		}

		internal static void Warn(string text)
		{
			ManualLogSource obj = log;
			if (obj != null)
			{
				obj.LogWarning((object)text);
			}
		}

		internal static void Debug(string text)
		{
			if (DebugLog != null && DebugLog.Value)
			{
				ManualLogSource obj = log;
				if (obj != null)
				{
					obj.LogInfo((object)text);
				}
			}
		}
	}
	internal sealed class ConfigurationManagerAttributes
	{
		public Action<ConfigEntryBase> CustomDrawer;
	}
	internal static class Preview
	{
		private static GameObject rig;

		private static GameObject model;

		private static Camera cam;

		private static Light light;

		private static Light fill;

		private static RenderTexture live;

		private static string shown;

		private static float yaw;

		private static readonly Vector3 Place = new Vector3(0f, -20000f, 0f);

		private static int layer = -1;

		private static Vector3 centre;

		private static float radius;

		private static bool empty;

		private static Quaternion pose = Quaternion.identity;

		private static float sinceDrawn;

		private static readonly int sunDir = Shader.PropertyToID("_SunDir");

		private static readonly int sunColor = Shader.PropertyToID("_SunColor");

		private static readonly int ambientColor = Shader.PropertyToID("_AmbientColor");

		private static readonly int wet = Shader.PropertyToID("_Wet");

		private static readonly Color Key = new Color(0.9f, 0.87f, 0.82f);

		private static readonly Color Ambient = new Color(0.46f, 0.46f, 0.48f);

		public static RenderTexture Texture => live;

		private static int Layer()
		{
			if (layer >= 0)
			{
				return layer;
			}
			for (int num = 31; num >= 8; num--)
			{
				if (string.IsNullOrEmpty(LayerMask.LayerToName(num)))
				{
					return layer = num;
				}
			}
			return layer = 31;
		}

		private static void Setup()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_0105: 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_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: 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)
			if (!((Object)(object)rig != (Object)null))
			{
				rig = new GameObject("CraftMenu preview");
				Object.DontDestroyOnLoad((Object)(object)rig);
				rig.transform.position = Place;
				GameObject val = new GameObject("camera");
				val.transform.SetParent(rig.transform, false);
				cam = val.AddComponent<Camera>();
				((Behaviour)cam).enabled = false;
				cam.cullingMask = 1 << Layer();
				cam.clearFlags = (CameraClearFlags)2;
				cam.backgroundColor = new Color(0f, 0f, 0f, 0f);
				cam.fieldOfView = 28f;
				cam.nearClipPlane = 0.05f;
				cam.farClipPlane = 200f;
				cam.allowHDR = false;
				cam.allowMSAA = true;
				cam.useOcclusionCulling = false;
				GameObject val2 = new GameObject("light");
				val2.transform.SetParent(rig.transform, false);
				light = val2.AddComponent<Light>();
				light.type = (LightType)1;
				light.intensity = 1.1f;
				light.color = new Color(1f, 0.95f, 0.88f);
				light.cullingMask = 1 << Layer();
				light.shadows = (LightShadows)0;
				((Behaviour)light).enabled = false;
				GameObject val3 = new GameObject("fill");
				val3.transform.SetParent(rig.transform, false);
				fill = val3.AddComponent<Light>();
				fill.type = (LightType)1;
				fill.intensity = 0.45f;
				fill.color = new Color(0.75f, 0.82f, 1f);
				fill.cullingMask = 1 << Layer();
				fill.shadows = (LightShadows)0;
				((Behaviour)fill).enabled = false;
			}
		}

		private static GameObject Copy(GameObject prefab)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			//IL_00fd: 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_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: 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_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("model " + ((Object)prefab).name);
			val.layer = Layer();
			val.transform.SetParent(rig.transform, false);
			HashSet<Transform> hashSet = new HashSet<Transform>();
			LODGroup[] componentsInChildren = prefab.GetComponentsInChildren<LODGroup>(true);
			Renderer[] renderers;
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				LOD[] lODs = componentsInChildren[i].GetLODs();
				for (int j = 1; j < lODs.Length; j++)
				{
					renderers = lODs[j].renderers;
					foreach (Renderer r in renderers)
					{
						if ((Object)(object)r != (Object)null && !Array.Exists(lODs[0].renderers, (Renderer x) => (Object)(object)x == (Object)(object)r))
						{
							hashSet.Add(((Component)r).transform);
						}
					}
				}
			}
			Matrix4x4 worldToLocalMatrix = prefab.transform.worldToLocalMatrix;
			renderers = prefab.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val2 in renderers)
			{
				if ((val2 is MeshRenderer || val2 is SkinnedMeshRenderer) && val2.enabled && On(((Component)val2).transform, prefab.transform) && !Skipped(((Component)val2).transform, hashSet))
				{
					SkinnedMeshRenderer val3 = (SkinnedMeshRenderer)(object)((val2 is SkinnedMeshRenderer) ? val2 : null);
					object obj;
					if (val3 == null)
					{
						MeshFilter component = ((Component)val2).GetComponent<MeshFilter>();
						obj = ((component != null) ? component.sharedMesh : null);
					}
					else
					{
						obj = val3.sharedMesh;
					}
					Mesh val4 = (Mesh)obj;
					if (!((Object)(object)val4 == (Object)null))
					{
						GameObject val5 = new GameObject(((Object)val2).name)
						{
							layer = Layer()
						};
						val5.transform.SetParent(val.transform, false);
						Matrix4x4 val6 = worldToLocalMatrix * ((Component)val2).transform.localToWorldMatrix;
						val5.transform.localPosition = Vector4.op_Implicit(((Matrix4x4)(ref val6)).GetColumn(3));
						val5.transform.localRotation = ((Matrix4x4)(ref val6)).rotation;
						val5.transform.localScale = ((Matrix4x4)(ref val6)).lossyScale;
						val5.AddComponent<MeshFilter>().sharedMesh = val4;
						MeshRenderer obj2 = val5.AddComponent<MeshRenderer>();
						((Renderer)obj2).sharedMaterials = val2.sharedMaterials;
						((Renderer)obj2).shadowCastingMode = (ShadowCastingMode)0;
						((Renderer)obj2).receiveShadows = false;
					}
				}
			}
			return val;
		}

		private static bool On(Transform t, Transform root)
		{
			while ((Object)(object)t != (Object)null)
			{
				if (!((Component)t).gameObject.activeSelf)
				{
					return false;
				}
				if ((Object)(object)t == (Object)(object)root)
				{
					break;
				}
				t = t.parent;
			}
			return true;
		}

		private static bool Skipped(Transform t, HashSet<Transform> skip)
		{
			while ((Object)(object)t != (Object)null)
			{
				if (skip.Contains(t))
				{
					return true;
				}
				t = t.parent;
			}
			return false;
		}

		private static void Measure(GameObject root)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: 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_00df: 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_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: 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)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: 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_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: 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)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			root.transform.localRotation = Quaternion.identity;
			Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>();
			empty = componentsInChildren.Length == 0;
			Bounds val = (Bounds)((componentsInChildren.Length != 0) ? componentsInChildren[0].bounds : new Bounds(root.transform.position, Vector3.one * 0.2f));
			Renderer[] array = componentsInChildren;
			foreach (Renderer val2 in array)
			{
				((Bounds)(ref val)).Encapsulate(val2.bounds);
			}
			centre = root.transform.InverseTransformPoint(((Bounds)(ref val)).center);
			Vector3 extents = ((Bounds)(ref val)).extents;
			radius = Mathf.Max(((Vector3)(ref extents)).magnitude, 0.05f);
			Vector3 extents2 = ((Bounds)(ref val)).extents;
			float num = Mathf.Max(new float[3] { extents2.x, extents2.y, extents2.z });
			float num2 = extents2.x + extents2.y + extents2.z - num - Mathf.Min(new float[3] { extents2.x, extents2.y, extents2.z });
			pose = Quaternion.identity;
			if (num > num2 * 1.6f)
			{
				Vector3 val3 = ((extents2.x >= extents2.y && extents2.x >= extents2.z) ? Vector3.right : ((extents2.y >= extents2.z) ? Vector3.up : Vector3.forward));
				pose = Quaternion.AngleAxis(-35f, Vector3.forward) * Quaternion.FromToRotation(val3, Vector3.up);
			}
		}

		private static void Frame(GameObject root, float turn)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: 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_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_006d: 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_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
			root.transform.localRotation = Quaternion.Euler(0f, turn, 0f) * pose;
			Vector3 val = root.transform.TransformPoint(centre);
			float num = radius / Mathf.Sin(cam.fieldOfView * 0.5f * ((float)Math.PI / 180f)) * 0.85f;
			Vector3 val2 = Quaternion.Euler(18f, 180f, 0f) * Vector3.back;
			((Component)cam).transform.position = val + val2 * num;
			((Component)cam).transform.LookAt(val);
			cam.nearClipPlane = Mathf.Max(0.02f, num - radius * 1.5f);
			cam.farClipPlane = num + radius * 1.5f;
		}

		public static bool Show(GameObject prefab, float pixels)
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Expected O, but got Unknown
			if ((Object)(object)prefab == (Object)null)
			{
				Hide();
				return false;
			}
			Setup();
			int num = Mathf.Clamp(Mathf.CeilToInt(pixels / 64f) * 64, 128, 512);
			if ((Object)(object)live != (Object)null && ((Texture)live).width != num)
			{
				live.Release();
				Object.Destroy((Object)(object)live);
				live = null;
			}
			if ((Object)(object)live == (Object)null)
			{
				live = new RenderTexture(num, num, 24, (RenderTextureFormat)0)
				{
					antiAliasing = 2,
					name = "CraftMenu preview"
				};
				live.Create();
			}
			if (shown != ((Object)prefab).name || (Object)(object)model == (Object)null)
			{
				if ((Object)(object)model != (Object)null)
				{
					Object.Destroy((Object)(object)model);
				}
				model = Copy(prefab);
				Measure(model);
				shown = ((Object)prefab).name;
				yaw = -30f;
			}
			if (empty)
			{
				Hide();
				return false;
			}
			model.SetActive(true);
			sinceDrawn = 1f;
			return true;
		}

		public static void Hide()
		{
			if ((Object)(object)model != (Object)null)
			{
				model.SetActive(false);
			}
		}

		public static void Update(float dt)
		{
			if (!((Object)(object)model == (Object)null) && model.activeSelf && !((Object)(object)cam == (Object)null))
			{
				yaw += dt * 24f;
				if (!((sinceDrawn += dt) < 1f / 24f))
				{
					sinceDrawn = 0f;
					Frame(model, yaw);
					Render(live);
				}
			}
		}

		private static void Render(RenderTexture target)
		{
			//IL_000a: 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_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: 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_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: 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_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			Quaternion val = ((Component)cam).transform.rotation * Quaternion.Euler(30f, -35f, 0f);
			if ((Object)(object)light != (Object)null)
			{
				((Component)light).transform.rotation = val;
			}
			if ((Object)(object)fill != (Object)null)
			{
				((Component)fill).transform.rotation = ((Component)cam).transform.rotation * Quaternion.Euler(10f, 145f, 0f);
			}
			bool fog = RenderSettings.fog;
			AmbientMode ambientMode = RenderSettings.ambientMode;
			Color ambientLight = RenderSettings.ambientLight;
			Vector4 globalVector = Shader.GetGlobalVector(sunDir);
			Color globalColor = Shader.GetGlobalColor(sunColor);
			Color globalColor2 = Shader.GetGlobalColor(ambientColor);
			float globalFloat = Shader.GetGlobalFloat(wet);
			RenderSettings.fog = false;
			RenderSettings.ambientMode = (AmbientMode)3;
			RenderSettings.ambientLight = Ambient;
			Shader.SetGlobalVector(sunDir, Vector4.op_Implicit(-(val * Vector3.forward)));
			Shader.SetGlobalColor(sunColor, Key);
			Shader.SetGlobalColor(ambientColor, Ambient);
			Shader.SetGlobalFloat(wet, 0f);
			try
			{
				if ((Object)(object)light != (Object)null)
				{
					((Behaviour)light).enabled = true;
				}
				if ((Object)(object)fill != (Object)null)
				{
					((Behaviour)fill).enabled = true;
				}
				cam.targetTexture = target;
				cam.Render();
			}
			finally
			{
				if ((Object)(object)light != (Object)null)
				{
					((Behaviour)light).enabled = false;
				}
				if ((Object)(object)fill != (Object)null)
				{
					((Behaviour)fill).enabled = false;
				}
				RenderSettings.fog = fog;
				RenderSettings.ambientMode = ambientMode;
				RenderSettings.ambientLight = ambientLight;
				Shader.SetGlobalVector(sunDir, globalVector);
				Shader.SetGlobalColor(sunColor, globalColor);
				Shader.SetGlobalColor(ambientColor, globalColor2);
				Shader.SetGlobalFloat(wet, globalFloat);
				cam.targetTexture = null;
			}
		}

		public static bool ClearAndFalse()
		{
			Clear();
			return false;
		}

		public static void Clear()
		{
			if ((Object)(object)rig != (Object)null)
			{
				Object.Destroy((Object)(object)rig);
			}
			if ((Object)(object)live != (Object)null)
			{
				live.Release();
				Object.Destroy((Object)(object)live);
			}
			rig = null;
			model = null;
			cam = null;
			live = null;
			shown = null;
		}
	}
	internal static class Recipes
	{
		internal enum Tab
		{
			Craft,
			Upgrade,
			Dismantle,
			Vnei
		}

		internal sealed class Entry
		{
			internal Recipe Recipe;

			internal ItemData Item;

			internal bool CanCraft;

			internal string Name;

			internal string Category;

			internal int StationLevel;

			internal SharedData Shared => Recipe.m_item.m_itemData.m_shared;

			internal string Prefab => ((Object)((Component)Recipe.m_item).gameObject).name;

			internal Sprite Icon
			{
				get
				{
					if (Item == null)
					{
						return Recipe.m_item.m_itemData.GetIcon();
					}
					return Item.GetIcon();
				}
			}

			internal bool Same(Entry other)
			{
				if (other != null && (Object)(object)other.Recipe == (Object)(object)Recipe)
				{
					return other.Item == Item;
				}
				return false;
			}
		}

		internal static Tab Current = Tab.Craft;

		internal static string Category = "all";

		internal static string Search = "";

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

		internal static readonly List<Entry> Shown = new List<Entry>();

		internal static bool DismantleOnlyAvailable = true;

		internal static bool OnlyAvailable
		{
			get
			{
				if (Current != Tab.Dismantle)
				{
					return Plugin.OnlyAvailable.Value;
				}
				return DismantleOnlyAvailable;
			}
		}

		internal static int Count => all.Count;

		internal static void Gather()
		{
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			all.Clear();
			InventoryGui instance = InventoryGui.instance;
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)instance == (Object)null || (Object)(object)localPlayer == (Object)null || Current == Tab.Vnei)
			{
				return;
			}
			if (Current == Tab.Dismantle)
			{
				foreach (ItemData allItem in ((Humanoid)localPlayer).GetInventory().GetAllItems())
				{
					if (allItem != null && !allItem.m_equipped && Dismantle.Possible(allItem, out var recipe))
					{
						all.Add(Make(recipe, allItem, Dismantle.Allowed(allItem, recipe)));
					}
				}
				return;
			}
			foreach (RecipeDataPair availableRecipe in instance.m_availableRecipes)
			{
				RecipeDataPair current2 = availableRecipe;
				if (!((Object)(object)((RecipeDataPair)(ref current2)).Recipe == (Object)null))
				{
					all.Add(Make(((RecipeDataPair)(ref current2)).Recipe, ((RecipeDataPair)(ref current2)).ItemData, ((RecipeDataPair)(ref current2)).CanCraft));
				}
			}
		}

		private static Entry Make(Recipe recipe, ItemData item, bool can)
		{
			Entry obj = new Entry
			{
				Recipe = recipe,
				Item = item,
				CanCraft = can,
				Name = Localization.instance.Localize(recipe.m_item.m_itemData.m_shared.m_name),
				Category = Categories.Of(recipe.m_item.m_itemData.m_shared)
			};
			int num = ((item == null) ? 1 : (item.m_quality + ((Current == Tab.Upgrade) ? 1 : 0)));
			obj.StationLevel = (((Object)(object)recipe.m_craftingStation != (Object)null) ? recipe.GetRequiredStationLevel(num) : 0);
			return obj;
		}

		internal static void Filter()
		{
			Shown.Clear();
			string text = Search.Trim();
			bool onlyAvailable = OnlyAvailable;
			bool value = Plugin.FavouritesOnly.Value;
			foreach (Entry item in all)
			{
				if ((!(Category != "all") || !(item.Category != Category)) && (!onlyAvailable || item.CanCraft) && (!onlyAvailable || Current != Tab.Dismantle || item.Item == null || item.Item.m_gridPos.y != 0) && (!value || Favourites.Has(item.Prefab)) && (text.Length <= 0 || item.Name.IndexOf(text, StringComparison.CurrentCultureIgnoreCase) >= 0 || item.Prefab.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0))
				{
					Shown.Add(item);
				}
			}
			Comparison<Entry> order = Sorting.Of(Plugin.Sort.Value);
			List<(Entry, int)> list = Shown.Select((Entry e, int i) => (e: e, i: i)).ToList();
			list.Sort(delegate((Entry e, int i) a, (Entry e, int i) b)
			{
				int num = order(a.e, b.e);
				return (num == 0) ? a.i.CompareTo(b.i) : num;
			});
			Shown.Clear();
			Shown.AddRange(list.Select<(Entry, int), Entry>(((Entry e, int i) p) => p.e));
		}

		internal static void ToggleOnlyAvailable()
		{
			if (Current == Tab.Dismantle)
			{
				DismantleOnlyAvailable = !DismantleOnlyAvailable;
				Window.Refresh();
			}
			else
			{
				Plugin.OnlyAvailable.Value = !Plugin.OnlyAvailable.Value;
			}
		}

		internal static int CountIn(string category)
		{
			if (!(category == "all"))
			{
				return all.Count((Entry e) => e.Category == category);
			}
			return all.Count;
		}
	}
	internal static class Favourites
	{
		private const string Key = "chistix.craftmenu.favourites";

		private static HashSet<string> set;

		private static Player owner;

		private static HashSet<string> Set()
		{
			Player localPlayer = Player.m_localPlayer;
			if (set == null || (Object)(object)owner != (Object)(object)localPlayer)
			{
				owner = localPlayer;
				set = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
				if ((Object)(object)localPlayer != (Object)null && localPlayer.m_customData.TryGetValue("chistix.craftmenu.favourites", out var value))
				{
					string[] array = value.Split(',');
					foreach (string text in array)
					{
						if (text.Length > 0)
						{
							set.Add(text);
						}
					}
				}
			}
			return set;
		}

		internal static bool Has(string prefab)
		{
			if (prefab != null)
			{
				return Set().Contains(prefab);
			}
			return false;
		}

		internal static void Toggle(string prefab)
		{
			if (prefab != null)
			{
				HashSet<string> hashSet = Set();
				if (!hashSet.Remove(prefab))
				{
					hashSet.Add(prefab);
				}
				if ((Object)(object)owner != (Object)null)
				{
					owner.m_customData["chistix.craftmenu.favourites"] = string.Join(",", hashSet);
				}
			}
		}
	}
	internal static class Skin
	{
		private sealed class Piece
		{
			internal Sprite Sprite;

			internal Color Color = Color.white;

			internal Material Material;
		}

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

		private static Texture2D atlas;

		private static Texture2D wood;

		private static Sprite woodSprite;

		private static bool loaded;

		public static float Multiplier = 1f;

		private static Dictionary<string, Piece> game;

		private static readonly string[] Drawn = new string[22]
		{
			"panel_outer", "panel_inset", "card_panel", "toolbar", "tooltip", "header_plain", "slot_normal", "slot_selected", "slot_hover", "req_cell",
			"category_selected", "utility_normal", "utility_selected", "button_normal", "button_selected", "button_pressed", "dropdown", "checkbox_empty", "tab_normal", "tab_selected",
			"tab_hover", "input"
		};

		public static bool Present => (Object)(object)atlas != (Object)null;

		public static Sprite Wood
		{
			get
			{
				Ensure();
				return woodSprite;
			}
		}

		public static bool GameLook
		{
			get
			{
				if (Plugin.Look != null)
				{
					return Plugin.Look.Value == 1;
				}
				return false;
			}
		}

		private static string Folder()
		{
			string[] array = new string[2]
			{
				Path.Combine(Path.Combine(Plugin.Folder, "CraftMenu"), "skin"),
				Path.Combine(Plugin.Folder, "skin")
			};
			foreach (string text in array)
			{
				if (File.Exists(Path.Combine(text, "atlas.png")))
				{
					return text;
				}
			}
			return null;
		}

		private static byte[] Bytes(string folder, string name)
		{
			if (folder != null)
			{
				string path = Path.Combine(folder, name);
				if (!File.Exists(path))
				{
					return null;
				}
				return File.ReadAllBytes(path);
			}
			using Stream stream = typeof(Skin).Assembly.GetManifestResourceStream("CraftMenu.skin." + name);
			if (stream == null)
			{
				return null;
			}
			byte[] array = new byte[stream.Length];
			int num;
			for (int i = 0; i < array.Length; i += num)
			{
				num = stream.Read(array, i, array.Length - i);
				if (num <= 0)
				{
					break;
				}
			}
			return array;
		}

		private static Texture2D Load(byte[] bytes, string name, bool mipmaps)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			if (bytes == null)
			{
				return null;
			}
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, mipmaps)
			{
				name = "CraftMenu " + name
			};
			if (!ImageConversion.LoadImage(val, bytes))
			{
				Object.Destroy((Object)(object)val);
				return null;
			}
			((Texture)val).filterMode = (FilterMode)1;
			return val;
		}

		public static void Ensure()
		{
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			if (loaded)
			{
				return;
			}
			loaded = true;
			string text = Folder();
			try
			{
				atlas = Load(Bytes(text, "atlas.png"), "atlas", mipmaps: false);
				byte[] array = Bytes(text, "atlas.tsv");
				if ((Object)(object)atlas == (Object)null || array == null)
				{
					Plugin.Warn("skin: no atlas, the window uses the game's panels");
					atlas = null;
					return;
				}
				((Texture)atlas).wrapMode = (TextureWrapMode)1;
				string[] array2 = Encoding.UTF8.GetString(array).Split('\n');
				Rect val = default(Rect);
				Vector4 val2 = default(Vector4);
				foreach (string text2 in array2)
				{
					if (!text2.StartsWith("#") && text2.Trim().Length != 0)
					{
						string[] array3 = text2.TrimEnd('\r').Split('\t');
						if (array3.Length >= 9)
						{
							((Rect)(ref val))..ctor(F(array3[1]), F(array3[2]), F(array3[3]), F(array3[4]));
							((Vector4)(ref val2))..ctor(F(array3[5]), F(array3[6]), F(array3[7]), F(array3[8]));
							Sprite val3 = Sprite.Create(atlas, val, new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, val2);
							((Object)val3).name = "CraftMenu " + array3[0];
							sprites[array3[0]] = val3;
						}
					}
				}
				wood = Load(Bytes(text, "wood.png"), "wood", mipmaps: true);
				if ((Object)(object)wood != (Object)null)
				{
					((Texture)wood).wrapMode = (TextureWrapMode)0;
					woodSprite = Sprite.Create(wood, new Rect(0f, 0f, (float)((Texture)wood).width, (float)((Texture)wood).height), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0);
					((Object)woodSprite).name = "CraftMenu wood";
				}
				Plugin.Log(string.Format("skin: {0} sprites from {1}", sprites.Count, text ?? "the DLL"));
			}
			catch (Exception ex)
			{
				Plugin.Warn("skin: " + ex.Message);
			}
		}

		private static float F(string s)
		{
			return float.Parse(s, CultureInfo.InvariantCulture);
		}

		public static Sprite Get(string name)
		{
			if (name == null)
			{
				return null;
			}
			if (GameLook)
			{
				GameSetup();
				if (game.TryGetValue(name, out var value))
				{
					return value.Sprite;
				}
			}
			Ensure();
			if (!sprites.TryGetValue(name, out var value2))
			{
				return null;
			}
			return value2;
		}

		private static void GameSetup()
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: 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_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_038a: Unknown result type (might be due to invalid IL or missing references)
			//IL_038f: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0491: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: 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_0301: Unknown result type (might be due to invalid IL or missing references)
			//IL_034b: Unknown result type (might be due to invalid IL or missing references)
			if (game != null)
			{
				return;
			}
			game = new Dictionary<string, Piece>();
			InventoryGui instance = InventoryGui.instance;
			if ((Object)(object)instance == (Object)null)
			{
				game = null;
				return;
			}
			try
			{
				Transform obj = ((Transform)instance.m_crafting).Find("Bkg");
				Image val = ((obj != null) ? ((Component)obj).GetComponent<Image>() : null);
				if ((Object)(object)val != (Object)null)
				{
					Add("panel_outer", val.sprite, ((Graphic)val).color, ((Graphic)val).material);
				}
				Image component = ((Component)instance.m_recipeDecription.transform.parent).GetComponent<Image>();
				if ((Object)(object)component != (Object)null)
				{
					string[] array = new string[5] { "panel_inset", "card_panel", "toolbar", "tooltip", "header_plain" };
					for (int i = 0; i < array.Length; i++)
					{
						Add(array[i], component.sprite, ((Graphic)component).color, ((Graphic)component).material);
					}
					Add("slot_normal", component.sprite, new Color(0f, 0f, 0f, 0.6f), ((Graphic)component).material);
					Add("req_cell", component.sprite, new Color(0f, 0f, 0f, 0.55f), ((Graphic)component).material);
				}
				object obj2;
				if (!((Object)(object)instance.m_playerGrid != (Object)null) || !((Object)(object)instance.m_playerGrid.m_elementPrefab != (Object)null))
				{
					obj2 = null;
				}
				else
				{
					Transform obj3 = instance.m_playerGrid.m_elementPrefab.transform.Find("selected");
					obj2 = ((obj3 != null) ? ((Component)obj3).GetComponent<Image>() : null);
				}
				Image val2 = (Image)obj2;
				if ((Object)(object)val2 != (Object)null)
				{
					Add("slot_selected", val2.sprite, ((Graphic)val2).color, ((Graphic)val2).material);
					Add("slot_hover", val2.sprite, new Color(((Graphic)val2).color.r, ((Graphic)val2).color.g, ((Graphic)val2).color.b, 0.5f), ((Graphic)val2).material);
					Add("category_selected", val2.sprite, ((Graphic)val2).color, ((Graphic)val2).material);
				}
				Button craftButton = instance.m_craftButton;
				if ((Object)(object)craftButton != (Object)null && (Object)(object)((Selectable)craftButton).image != (Object)null)
				{
					SpriteState spriteState = ((Selectable)craftButton).spriteState;
					Sprite val3 = (((Object)(object)((SpriteState)(ref spriteState)).highlightedSprite != (Object)null) ? ((SpriteState)(ref spriteState)).highlightedSprite : ((Selectable)craftButton).image.sprite);
					string[] array = new string[4] { "utility_normal", "button_normal", "dropdown", "checkbox_empty" };
					for (int i = 0; i < array.Length; i++)
					{
						Add(array[i], ((Selectable)craftButton).image.sprite, ((Graphic)((Selectable)craftButton).image).color, ((Graphic)((Selectable)craftButton).image).material);
					}
					array = new string[2] { "utility_selected", "button_selected" };
					for (int i = 0; i < array.Length; i++)
					{
						Add(array[i], val3, ((Graphic)((Selectable)craftButton).image).color, ((Graphic)((Selectable)craftButton).image).material);
					}
					Add("button_pressed", ((Object)(object)((SpriteState)(ref spriteState)).pressedSprite != (Object)null) ? ((SpriteState)(ref spriteState)).pressedSprite : val3, ((Graphic)((Selectable)craftButton).image).color, ((Graphic)((Selectable)craftButton).image).material);
				}
				Button tabCraft = instance.m_tabCraft;
				if ((Object)(object)tabCraft != (Object)null && (Object)(object)((Selectable)tabCraft).image != (Object)null)
				{
					SpriteState spriteState2 = ((Selectable)tabCraft).spriteState;
					Add("tab_normal", ((Selectable)tabCraft).image.sprite, ((Graphic)((Selectable)tabCraft).image).color, ((Graphic)((Selectable)tabCraft).image).material);
					Add("tab_selected", ((Object)(object)((SpriteState)(ref spriteState2)).disabledSprite != (Object)null) ? ((SpriteState)(ref spriteState2)).disabledSprite : ((SpriteState)(ref spriteState2)).pressedSprite, ((Graphic)((Selectable)tabCraft).image).color, ((Graphic)((Selectable)tabCraft).image).material);
					Add("tab_hover", ((Object)(object)((SpriteState)(ref spriteState2)).highlightedSprite != (Object)null) ? ((SpriteState)(ref spriteState2)).highlightedSprite : ((Selectable)tabCraft).image.sprite, ((Graphic)((Selectable)tabCraft).image).color, ((Graphic)((Selectable)tabCraft).image).material);
				}
				Image val4 = (((Object)(object)TextInput.instance != (Object)null && (Object)(object)TextInput.instance.m_inputField != (Object)null) ? ((Selectable)TextInput.instance.m_inputField).image : null);
				if ((Object)(object)val4 != (Object)null)
				{
					Add("input", val4.sprite, ((Graphic)val4).color, ((Graphic)val4).material);
				}
			}
			catch (Exception ex)
			{
				Plugin.Warn("game look: " + ex.Message);
			}
			Plugin.Log($"game look: {game.Count} pieces");
			static void Add(string n, Sprite s, Color c, Material m = null)
			{
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)s != (Object)null)
				{
					game[n] = new Piece
					{
						Sprite = s,
						Color = c,
						Material = m
					};
				}
			}
		}

		public static void Tint(Image img, string name)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)img == (Object)null) && GameLook)
			{
				GameSetup();
				if (game.TryGetValue(name, out var value))
				{
					((Graphic)img).color = value.Color;
					((Graphic)img).material = value.Material;
					img.pixelsPerUnitMultiplier = 1f;
				}
			}
		}

		public static Image Panel(GameObject go, string name, Color fallback)
		{
			//IL_00e2: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			Image val = go.GetComponent<Image>();
			if ((Object)(object)val == (Object)null)
			{
				val = go.AddComponent<Image>();
			}
			if (GameLook)
			{
				GameSetup();
				if (game.TryGetValue(name, out var value))
				{
					val.sprite = value.Sprite;
					val.type = (Type)1;
					((Graphic)val).color = value.Color;
					((Graphic)val).material = value.Material;
					return val;
				}
				if (Array.IndexOf(Drawn, name) < 0)
				{
					val.sprite = Window.FlatSprite();
					((Graphic)val).color = new Color(0f, 0f, 0f, 0f);
					return val;
				}
			}
			Sprite val2 = Get(name);
			if ((Object)(object)val2 != (Object)null)
			{
				val.sprite = val2;
				val.type = (Type)1;
				((Graphic)val).color = Color.white;
				val.pixelsPerUnitMultiplier = Multiplier;
			}
			else
			{
				val.sprite = Window.FlatSprite();
				val.type = (Type)1;
				((Graphic)val).color = fallback;
			}
			return val;
		}

		public static Image Icon(GameObject go, string name)
		{
			Image val = go.GetComponent<Image>();
			if ((Object)(object)val == (Object)null)
			{
				val = go.AddComponent<Image>();
			}
			Sprite val2 = (val.sprite = Get(name));
			val.type = (Type)0;
			val.preserveAspect = true;
			((Graphic)val).raycastTarget = false;
			((Behaviour)val).enabled = (Object)(object)val2 != (Object)null;
			return val;
		}

		public static void Button(Button b, string normal, string hover, string pressed)
		{
			//IL_003d: 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_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			Sprite val = Get(normal);
			if (!((Object)(object)val == (Object)null) && !((Object)(object)((Selectable)b).image == (Object)null))
			{
				((Selectable)b).image.sprite = val;
				((Selectable)b).image.type = (Type)1;
				((Graphic)((Selectable)b).image).color = Color.white;
				((Selectable)b).image.pixelsPerUnitMultiplier = Multiplier;
				Tint(((Selectable)b).image, normal);
				((Selectable)b).transition = (Transition)2;
				SpriteState spriteState = ((Selectable)b).spriteState;
				((SpriteState)(ref spriteState)).highlightedSprite = Get(hover) ?? val;
				((SpriteState)(ref spriteState)).pressedSprite = Get(pressed) ?? ((SpriteState)(ref spriteState)).highlightedSprite;
				((SpriteState)(ref spriteState)).selectedSprite = val;
				((SpriteState)(ref spriteState)).disabledSprite = val;
				((Selectable)b).spriteState = spriteState;
			}
		}

		public static void Clear()
		{
			foreach (Sprite value in sprites.Values)
			{
				if ((Object)(object)value != (Object)null)
				{
					Object.Destroy((Object)(object)value);
				}
			}
			sprites.Clear();
			if ((Object)(object)woodSprite != (Object)null)
			{
				Object.Destroy((Object)(object)woodSprite);
			}
			if ((Object)(object)atlas != (Object)null)
			{
				Object.Destroy((Object)(object)atlas);
			}
			if ((Object)(object)wood != (Object)null)
			{
				Object.Destroy((Object)(object)wood);
			}
			atlas = (wood = null);
			woodSprite = null;
			loaded = false;
			game = null;
		}
	}
	internal static class Sorting
	{
		internal static readonly (string ru, string en)[] Names = new(string, string)[5]
		{
			("По умолчанию", "Default"),
			("По имени", "By name"),
			("По уровню станции", "By station level"),
			("По биому", "By biome"),
			("По весу", "By weight")
		};

		internal static string Name(int i)
		{
			if (i < 0 || i >= Names.Length)
			{
				return "";
			}
			return Plugin.T(Names[i].ru, Names[i].en);
		}

		internal static Comparison<Recipes.Entry> Of(int mode)
		{
			return mode switch
			{
				1 => (Recipes.Entry a, Recipes.Entry b) => Chain(ByName(a, b), ByLevel(a, b)), 
				2 => (Recipes.Entry a, Recipes.Entry b) => Chain(ByStation(a, b), ByName(a, b), ByLevel(a, b)), 
				3 => (Recipes.Entry a, Recipes.Entry b) => Chain(ByBiome(a, b), ByStation(a, b), ByName(a, b), ByLevel(a, b)), 
				4 => (Recipes.Entry a, Recipes.Entry b) => Chain(ByWeight(a, b), ByName(a, b), ByLevel(a, b)), 
				_ => (Recipes.Entry a, Recipes.Entry b) => Chain(ByCraftable(a, b), ByWeightKey(a, b), ByName(a, b), ByLevel(a, b)), 
			};
		}

		private static int Chain(params int[] results)
		{
			foreach (int num in results)
			{
				if (num != 0)
				{
					return num;
				}
			}
			return 0;
		}

		private static int ByCraftable(Recipes.Entry a, Recipes.Entry b)
		{
			return b.CanCraft.CompareTo(a.CanCraft);
		}

		private static int ByWeightKey(Recipes.Entry a, Recipes.Entry b)
		{
			return a.Recipe.m_listSortWeight.CompareTo(b.Recipe.m_listSortWeight);
		}

		private static int ByName(Recipes.Entry a, Recipes.Entry b)
		{
			return string.Compare(a.Name, b.Name, StringComparison.CurrentCultureIgnoreCase);
		}

		private static int ByLevel(Recipes.Entry a, Recipes.Entry b)
		{
			if (a.Item == null || b.Item == null)
			{
				return 0;
			}
			return b.Item.m_quality.CompareTo(a.Item.m_quality);
		}

		private static int ByStation(Recipes.Entry a, Recipes.Entry b)
		{
			return a.StationLevel.CompareTo(b.StationLevel);
		}

		private static int ByBiome(Recipes.Entry a, Recipes.Entry b)
		{
			return Biomes.Of(a.Recipe).CompareTo(Biomes.Of(b.Recipe));
		}

		private static int ByWeight(Recipes.Entry a, Recipes.Entry b)
		{
			return a.Recipe.m_item.m_itemData.m_shared.m_weight.CompareTo(b.Recipe.m_item.m_itemData.m_shared.m_weight);
		}
	}
	public static class UiLook
	{
		public static Func<string, Texture2D> Texture;

		public static Func<string, RectOffset> Border;

		public static Func<string, RectOffset> Overflow;

		public static Func<string, Sprite> Sprite;

		public static Action<Image, string> Style;

		public static Func<Transform, Vector2, string, RectTransform> NewPanel;

		public static Func<Transform, string, string, Button> NewButton;

		public static Func<Transform, string, float, RectTransform> NewDivider;

		public static Func<string, Color> Color;

		public static Font Font;

		public static Font BoldFont;

		public static int Version;

		public static event Action<RectTransform> WindowCreated;

		internal static void Created(RectTransform root)
		{
			UiLook.WindowCreated?.Invoke(root);
		}

		internal static Color Tint(string role, Color own)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			if (Color == null)
			{
				return own;
			}
			try
			{
				Color val = Color(role);
				return (val.a > 0f) ? val : own;
			}
			catch
			{
				return own;
			}
		}
	}
	internal static class Vnei
	{
		private sealed class Key
		{
			internal string Category;

			internal string Name;

			internal float Weight;

			internal int Station;

			internal int Biome;

			internal int Index;
		}

		private sealed class Same : IEqualityComparer<object>
		{
			public new bool Equals(object a, object b)
			{
				return a == b;
			}

			public int GetHashCode(object o)
			{
				return RuntimeHelpers.GetHashCode(o);
			}
		}

		private const string Guid = "com.maxsch.valheim.vnei";

		private const string Auga = "randyknapp.mods.auga";

		private static bool tried;

		private static bool ok;

		private static ConfigEntry<bool> attach;

		private static ConfigEntry<string> tabName;

		private static PropertyInfo handlerInstance;

		private static PropertyInfo tabActive;

		private static FieldInfo uiOpen;

		private static FieldInfo baseRoot;

		private static MethodInfo getBase;

		private static MethodInfo setActive;

		private static MethodInfo setInactive;

		private static MethodInfo setSize;

		private static MethodInfo showRecipe;

		private static MethodInfo getItem;

		private static MethodInfo openUi;

		private static int cellsX = -1;

		private static int cellsY = -1;

		private static Component adopted;

		internal static bool Ordered;

		private static FieldInfo searchUiField;

		private static FieldInfo listItemsField;

		private static FieldInfo listItemItem;

		private static FieldInfo itemPrefab;

		private static FieldInfo itemName;

		private static MethodInfo updateSearch;

		private static readonly Dictionary<object, Key> keys = new Dictionary<object, Key>(new Same());

		private static volatile bool ours;

		private static volatile string category = "all";

		private static int sortMode;

		private static int sortedMode = -1;

		private static int sortedCount = -1;

		internal static bool Present
		{
			get
			{
				if (tried)
				{
					return ok;
				}
				tried = true;
				try
				{
					if (!Chainloader.PluginInfos.TryGetValue("com.maxsch.valheim.vnei", out var value) || (Object)(object)value.Instance == (Object)null || Chainloader.PluginInfos.ContainsKey("randyknapp.mods.auga"))
					{
						return false;
					}
					Assembly assembly = ((object)value.Instance).GetType().Assembly;
					Type type = assembly.GetType("VNEI.Plugin", throwOnError: true);
					Type type2 = assembly.GetType("VNEI.UI.MainVneiHandler", throwOnError: true);
					Type type3 = assembly.GetType("VNEI.UI.BaseUI", throwOnError: true);
					Type type4 = assembly.GetType("VNEI.Logic.Item", throwOnError: true);
					Type type5 = assembly.GetType("VNEI.Logic.Indexing", throwOnError: true);
					attach = type.GetField("attachToCrafting", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public)?.GetValue(null) as ConfigEntry<bool>;
					tabName = type.GetField("tabName", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public)?.GetValue(null) as ConfigEntry<string>;
					uiOpen = type.GetField("isUiOpen", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
					openUi = type.GetMethod("OpenUI", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public, null, Type.EmptyTypes, null);
					handlerInstance = type2.GetProperty("Instance", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
					tabActive = type2.GetProperty("VneiTabActive", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
					getBase = type2.GetMethod("GetBaseUI", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public, null, Type.EmptyTypes, null);
					setActive = type2.GetMethod("SetTabActive", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public, null, Type.EmptyTypes, null);
					setInactive = type2.GetMethod("SetTabInactive", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public, null, Type.EmptyTypes, null);
					baseRoot = type3.GetField("root", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
					setSize = type3.GetMethod("SetSize", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public, null, new Type[3]
					{
						typeof(bool),
						typeof(int),
						typeof(int)
					}, null);
					showRecipe = type3.GetMethod("ShowRecipe", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public, null, new Type[2]
					{
						type4,
						typeof(bool)
					}, null);
					getItem = type5.GetMethod("GetItem", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(string) }, null);
					ok = attach != null && uiOpen != null && openUi != null && handlerInstance != null && tabActive != null && getBase != null && setActive != null && setInactive != null && baseRoot != null && setSize != null && showRecipe != null && getItem != null;
					if (ok)
					{
						Plugin.Log("VNEI " + value.Metadata.Version?.ToString() + ": its browser as a tab of the window");
					}
					else
					{
						Plugin.Warn("VNEI " + value.Metadata.Version?.ToString() + ": its API is not as expected, no VNEI tab");
					}
					if (ok)
					{
						PatchBrowser(assembly, type4, type3);
					}
				}
				catch (Exception ex)
				{
					ok = false;
					Plugin.Warn("VNEI: " + ex.Message);
				}
				return ok;
			}
		}

		internal static bool Attached
		{
			get
			{
				if (Present)
				{
					return attach.Value;
				}
				return false;
			}
		}

		internal static string TabName
		{
			get
			{
				if (!Present || tabName == null || string.IsNullOrEmpty(tabName.Value))
				{
					return "VNEI";
				}
				return tabName.Value;
			}
		}

		private static object Handler => handlerInstance.GetValue(null, null);

		private static Component BaseUi
		{
			get
			{
				object? obj = getBase.Invoke(Handler, null);
				return (Component)((obj is Component) ? obj : null);
			}
		}

		internal static bool TabActive
		{
			get
			{
				if (!Attached)
				{
					return false;
				}
				try
				{
					return (bool)tabActive.GetValue(Handler, null);
				}
				catch (Exception e)
				{
					Fail("tab", e);
					return false;
				}
			}
		}

		private static void Fail(string what, Exception e)
		{
			ok = false;
			Plugin.Warn("VNEI " + what + ": " + (e.InnerException ?? e).Message);
		}

		internal static void Show(RectTransform area)
		{
			if (!Attached)
			{
				return;
			}
			try
			{
				setActive.Invoke(Handler, null);
				Adopt(area);
			}
			catch (Exception e)
			{
				Fail("show", e);
			}
		}

		internal static void Hide()
		{
			if (!Present)
			{
				return;
			}
			try
			{
				setInactive.Invoke(Handler, null);
			}
			catch (Exception e)
			{
				Fail("hide", e);
			}
		}

		internal static void Adopt(RectTransform area)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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_007f: 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_0095: 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_00e0: 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_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			if (!Attached || (Object)(object)area == (Object)null)
			{
				return;
			}
			try
			{
				Component baseUi = BaseUi;
				if ((Object)(object)baseUi == (Object)null)
				{
					return;
				}
				RectTransform val = (RectTransform)baseUi.transform;
				if ((Object)(object)((Transform)val).parent != (Object)(object)area || (Object)(object)baseUi != (Object)(object)adopted)
				{
					adopted = baseUi;
					((Transform)val).SetParent((Transform)(object)area, false);
					Vector2 anchorMin = (val.anchorMax = new Vector2(0.5f, 0.5f));
					val.anchorMin = anchorMin;
					val.anchoredPosition = Vector2.zero;
					((Transform)val).localScale = Vector3.one;
					((Transform)val).localRotation = Quaternion.identity;
					cellsX = (cellsY = -1);
					CanvasGroup component = baseUi.GetComponent<CanvasGroup>();
					if ((Object)(object)component != (Object)null)
					{
						component.alpha = 1f;
						component.blocksRaycasts = true;
						component.interactable = true;
					}
				}
				Rect rect = area.rect;
				int num = Mathf.Max(1, Mathf.FloorToInt((((Rect)(ref rect)).width - 10f) / 50f));
				rect = area.rect;
				int num2 = Mathf.Max(1, Mathf.FloorToInt((((Rect)(ref rect)).height - 100f) / 50f));
				if (num != cellsX || num2 != cellsY)
				{
					cellsX = num;
					cellsY = num2;
					setSize.Invoke(baseUi, new object[3] { false, num, num2 });
					object[] obj = new object[4] { num, num2, null, null };
					rect = area.rect;
					obj[2] = ((Rect)(ref rect)).width;
					rect = area.rect;
					obj[3] = ((Rect)(ref rect)).height;
					Plugin.Debug(string.Format("VNEI: browser {0} x {1} cells in {2:0} x {3:0}", obj));
				}
				object? value = baseRoot.GetValue(baseUi);
				RectTransform val3 = (RectTransform)((value is RectTransform) ? value : null);
				if ((Object)(object)val3 != (Object)null)
				{
					rect = val3.rect;
					Vector2 val4 = Vector2.op_Implicit(((Transform)area).InverseTransformPoint(((Transform)val3).TransformPoint(Vector2.op_Implicit(((Rect)(ref rect)).center))));
					rect = area.rect;
					Vector2 val5 = val4 - ((Rect)(ref rect)).center;
					if (((Vector2)(ref val5)).sqrMagnitude > 0.25f)
					{
						val.anchoredPosition -= val5;
					}
				}
			}
			catch (Exception e)
			{
				Fail("adopt", e);
			}
		}

		private static void PatchBrowser(Assembly asm, Type item, Type baseUi)
		{
			//IL_0112: 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_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Expected O, but got Unknown
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Expected O, but got Unknown
			try
			{
				Type type = asm.GetType("VNEI.UI.SearchUI", throwOnError: true);
				MethodInfo methodInfo = AccessTools.Method(type, "CalculateActive", (Type[])null, (Type[])null);
				updateSearch = AccessTools.Method(type, "UpdateSearch", new Type[1] { typeof(bool) }, (Type[])null);
				listItemsField = AccessTools.Field(type, "listItems");
				listItemItem = type.GetNestedType("ListItem", BindingFlags.Public | BindingFlags.NonPublic)?.GetField("item", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				searc