Decompiled source of Valhalla Wardrobe v1.6.0

ValhallaWardrobe.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace Primerochnaya;

public static class Biomes
{
	public static readonly Biome[] Order;

	private static readonly Dictionary<string, Biome> Map;

	private static readonly HashSet<string> Fixed;

	public static int Tier(Biome b)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Expected I4, but got Unknown
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Invalid comparison between Unknown and I4
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Invalid comparison between Unknown and I4
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Invalid comparison between Unknown and I4
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Invalid comparison between Unknown and I4
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Invalid comparison between Unknown and I4
		switch (b - 1)
		{
		default:
			if ((int)b != 16)
			{
				if ((int)b != 32)
				{
					if ((int)b != 64)
					{
						if ((int)b != 256)
						{
							if ((int)b == 512)
							{
								return 6;
							}
							return 0;
						}
						return 3;
					}
					return 8;
				}
				return 7;
			}
			return 5;
		case 0:
			return 1;
		case 7:
			return 2;
		case 1:
			return 3;
		case 3:
			return 4;
		}
	}

	public static string Name(Biome b)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Expected I4, but got Unknown
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Invalid comparison between Unknown and I4
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Invalid comparison between Unknown and I4
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Invalid comparison between Unknown and I4
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Invalid comparison between Unknown and I4
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Invalid comparison between Unknown and I4
		switch (b - 1)
		{
		default:
			if ((int)b != 16)
			{
				if ((int)b != 32)
				{
					if ((int)b != 64)
					{
						if ((int)b != 256)
						{
							if ((int)b == 512)
							{
								return Loc.T("Туманные земли", "Mistlands");
							}
							return Loc.T("неизвестно", "unknown");
						}
						return Loc.T("Океан", "Ocean");
					}
					return Loc.T("Крайний север", "Deep North");
				}
				return Loc.T("Пепельные земли", "Ashlands");
			}
			return Loc.T("Равнины", "Plains");
		case 0:
			return Loc.T("Луга", "Meadows");
		case 7:
			return Loc.T("Чёрный лес", "Black Forest");
		case 1:
			return Loc.T("Болото", "Swamp");
		case 3:
			return Loc.T("Горы", "Mountains");
		}
	}

	public static string Color(Biome b)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Expected I4, but got Unknown
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Invalid comparison between Unknown and I4
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Invalid comparison between Unknown and I4
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Invalid comparison between Unknown and I4
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Invalid comparison between Unknown and I4
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Invalid comparison between Unknown and I4
		switch (b - 1)
		{
		default:
			if ((int)b != 16)
			{
				if ((int)b != 32)
				{
					if ((int)b != 64)
					{
						if ((int)b != 256)
						{
							if ((int)b == 512)
							{
								return "#b79ad8";
							}
							return "#a89f8c";
						}
						return "#6fb3d6";
					}
					return "#9fd3e8";
				}
				return "#e0805a";
			}
			return "#e3cc6e";
		case 0:
			return "#a7d47a";
		case 7:
			return "#6fae7f";
		case 1:
			return "#a2a36a";
		case 3:
			return "#d3dde6";
		}
	}

	public static string Tag(Biome b)
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		return "<color=" + Color(b) + ">" + Name(b) + "</color>";
	}

	public static Biome Of(string prefab)
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		Biome value;
		return (Biome)((prefab != null && Map.TryGetValue(prefab, out value)) ? ((int)value) : 0);
	}

	private static void Seed(Biome b, params string[] names)
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		foreach (string text in names)
		{
			Map[text] = b;
			Fixed.Add(text);
		}
	}

	private static void Offer(string prefab, Biome flags)
	{
		//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)
		//IL_0022: 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_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		if (!string.IsNullOrEmpty(prefab) && !Fixed.Contains(prefab))
		{
			Biome val = Lowest(flags);
			if ((int)val != 0 && (!Map.TryGetValue(prefab, out var value) || Tier(val) < Tier(value)))
			{
				Map[prefab] = val;
			}
		}
	}

	private static Biome Lowest(Biome flags)
	{
		//IL_0010: 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_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: 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)
		Biome[] order = Order;
		foreach (Biome val in order)
		{
			if ((flags & val) != 0)
			{
				return val;
			}
		}
		return (Biome)0;
	}

	public static void Build(ObjectDB db)
	{
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: 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_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_01ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
		Map.Clear();
		Fixed.Clear();
		SeedVanilla();
		try
		{
			FromVegetation();
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Биомы: растительность не прочитана: " + ex.Message));
		}
		try
		{
			FromSpawns();
		}
		catch (Exception ex2)
		{
			Plugin.Log.LogWarning((object)("Биомы: спавны не прочитаны: " + ex2.Message));
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
		try
		{
			CollectConversions(list);
		}
		catch (Exception ex3)
		{
			Plugin.Log.LogWarning((object)("Биомы: станции переработки не прочитаны: " + ex3.Message));
		}
		for (int i = 0; i < 2; i++)
		{
			bool flag = i == 0;
			for (int j = 0; j < 12; j++)
			{
				bool flag2 = false;
				foreach (KeyValuePair<string, string> item in list)
				{
					Biome val = Of(item.Key);
					if ((int)val != 0 && !Map.ContainsKey(item.Value))
					{
						Map[item.Value] = val;
						flag2 = true;
					}
				}
				foreach (Recipe recipe in db.m_recipes)
				{
					if ((Object)(object)recipe == (Object)null || (Object)(object)recipe.m_item == (Object)null || recipe.m_resources == null)
					{
						continue;
					}
					string name = ((Object)((Component)recipe.m_item).gameObject).name;
					if (!Map.ContainsKey(name))
					{
						bool allKnown;
						Biome val2 = MaxOf(recipe, 1, out allKnown);
						if ((int)val2 != 0 && (allKnown || !flag))
						{
							Map[name] = val2;
							flag2 = true;
						}
					}
				}
				if (!flag2)
				{
					break;
				}
				if (!flag)
				{
					flag = true;
				}
			}
		}
		Plugin.Log.LogInfo((object)("Биомы определены для " + Map.Count + " предметов"));
	}

	public static Biome MaxOf(Recipe r, int quality)
	{
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		bool allKnown;
		return MaxOf(r, quality, out allKnown);
	}

	public static Biome MaxOf(Recipe r, int quality, out bool allKnown)
	{
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: 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_00e6: 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)
		allKnown = true;
		Biome val = (Biome)0;
		if ((Object)(object)r == (Object)null || r.m_resources == null)
		{
			return val;
		}
		Requirement[] resources = r.m_resources;
		foreach (Requirement val2 in resources)
		{
			if (val2 == null || (Object)(object)val2.m_resItem == (Object)null)
			{
				continue;
			}
			bool flag = false;
			for (int j = 1; j <= quality; j++)
			{
				if (flag)
				{
					break;
				}
				int num;
				try
				{
					num = val2.GetAmount(j);
				}
				catch
				{
					num = ((j > 1) ? val2.m_amountPerLevel : val2.m_amount);
				}
				if (num > 0)
				{
					flag = true;
				}
			}
			if (flag)
			{
				Biome val3 = Of(((Object)((Component)val2.m_resItem).gameObject).name);
				if ((int)val3 == 0)
				{
					allKnown = false;
				}
				if (Tier(val3) > Tier(val))
				{
					val = val3;
				}
			}
		}
		return val;
	}

	private static void FromVegetation()
	{
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		ZoneSystem instance = ZoneSystem.instance;
		if ((Object)(object)instance == (Object)null || instance.m_vegetation == null)
		{
			return;
		}
		foreach (ZoneVegetation item in instance.m_vegetation)
		{
			if (item == null || !item.m_enable || (Object)(object)item.m_prefab == (Object)null)
			{
				continue;
			}
			foreach (string item2 in DropsOf(item.m_prefab, 0))
			{
				Offer(item2, item.m_biome);
			}
		}
	}

	private static void FromSpawns()
	{
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		SpawnSystemList[] array = Resources.FindObjectsOfTypeAll<SpawnSystemList>();
		foreach (SpawnSystemList val in array)
		{
			if ((Object)(object)val == (Object)null || val.m_spawners == null)
			{
				continue;
			}
			foreach (SpawnData spawner in val.m_spawners)
			{
				if (spawner == null || !spawner.m_enabled || (Object)(object)spawner.m_prefab == (Object)null)
				{
					continue;
				}
				foreach (string item in DropsOf(spawner.m_prefab, 0))
				{
					Offer(item, spawner.m_biome);
				}
			}
		}
	}

	private static void CollectConversions(List<KeyValuePair<string, string>> outList)
	{
		ZNetScene instance = ZNetScene.instance;
		if ((Object)(object)instance == (Object)null)
		{
			return;
		}
		foreach (GameObject prefab in instance.m_prefabs)
		{
			if ((Object)(object)prefab == (Object)null)
			{
				continue;
			}
			Smelter component = prefab.GetComponent<Smelter>();
			if ((Object)(object)component != (Object)null && component.m_conversion != null)
			{
				foreach (ItemConversion item in component.m_conversion)
				{
					if (item != null && (Object)(object)item.m_from != (Object)null && (Object)(object)item.m_to != (Object)null)
					{
						outList.Add(new KeyValuePair<string, string>(((Object)((Component)item.m_from).gameObject).name, ((Object)((Component)item.m_to).gameObject).name));
					}
				}
			}
			CookingStation component2 = prefab.GetComponent<CookingStation>();
			if ((Object)(object)component2 != (Object)null && component2.m_conversion != null)
			{
				foreach (ItemConversion item2 in component2.m_conversion)
				{
					if (item2 != null && (Object)(object)item2.m_from != (Object)null && (Object)(object)item2.m_to != (Object)null)
					{
						outList.Add(new KeyValuePair<string, string>(((Object)((Component)item2.m_from).gameObject).name, ((Object)((Component)item2.m_to).gameObject).name));
					}
				}
			}
			Fermenter component3 = prefab.GetComponent<Fermenter>();
			if (!((Object)(object)component3 != (Object)null) || component3.m_conversion == null)
			{
				continue;
			}
			foreach (ItemConversion item3 in component3.m_conversion)
			{
				if (item3 != null && (Object)(object)item3.m_from != (Object)null && (Object)(object)item3.m_to != (Object)null)
				{
					outList.Add(new KeyValuePair<string, string>(((Object)((Component)item3.m_from).gameObject).name, ((Object)((Component)item3.m_to).gameObject).name));
				}
			}
		}
	}

	private static IEnumerable<string> DropsOf(GameObject go, int depth)
	{
		List<string> list = new List<string>();
		if ((Object)(object)go == (Object)null || depth > 3)
		{
			return list;
		}
		CharacterDrop component = go.GetComponent<CharacterDrop>();
		if ((Object)(object)component != (Object)null && component.m_drops != null)
		{
			foreach (Drop drop in component.m_drops)
			{
				if (drop != null && (Object)(object)drop.m_prefab != (Object)null)
				{
					list.Add(((Object)drop.m_prefab).name);
				}
			}
		}
		Pickable component2 = go.GetComponent<Pickable>();
		if ((Object)(object)component2 != (Object)null)
		{
			if ((Object)(object)component2.m_itemPrefab != (Object)null)
			{
				list.Add(((Object)component2.m_itemPrefab).name);
			}
			AddTable(list, component2.m_extraDrops);
		}
		MineRock component3 = go.GetComponent<MineRock>();
		if ((Object)(object)component3 != (Object)null)
		{
			AddTable(list, component3.m_dropItems);
		}
		MineRock5 component4 = go.GetComponent<MineRock5>();
		if ((Object)(object)component4 != (Object)null)
		{
			AddTable(list, component4.m_dropItems);
		}
		DropOnDestroyed component5 = go.GetComponent<DropOnDestroyed>();
		if ((Object)(object)component5 != (Object)null)
		{
			AddTable(list, component5.m_dropWhenDestroyed);
		}
		TreeBase component6 = go.GetComponent<TreeBase>();
		if ((Object)(object)component6 != (Object)null)
		{
			AddTable(list, component6.m_dropWhenDestroyed);
			list.AddRange(DropsOf(component6.m_logPrefab, depth + 1));
		}
		TreeLog component7 = go.GetComponent<TreeLog>();
		if ((Object)(object)component7 != (Object)null)
		{
			AddTable(list, component7.m_dropWhenDestroyed);
			list.AddRange(DropsOf(component7.m_subLogPrefab, depth + 1));
		}
		Destructible component8 = go.GetComponent<Destructible>();
		if ((Object)(object)component8 != (Object)null && (Object)(object)component8.m_spawnWhenDestroyed != (Object)null)
		{
			list.AddRange(DropsOf(component8.m_spawnWhenDestroyed, depth + 1));
		}
		return list;
	}

	private static void AddTable(List<string> list, DropTable t)
	{
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		if (t == null || t.m_drops == null)
		{
			return;
		}
		foreach (DropData drop in t.m_drops)
		{
			if ((Object)(object)drop.m_item != (Object)null)
			{
				list.Add(((Object)drop.m_item).name);
			}
		}
	}

	private static void SeedVanilla()
	{
		Seed((Biome)1, "Wood", "Stone", "Resin", "Flint", "LeatherScraps", "DeerHide", "Feathers", "RawMeat", "DeerMeat", "NeckTail", "Raspberry", "Mushroom", "Dandelion", "HardAntler", "TrophyDeer", "TrophyBoar", "TrophyNeck", "Honey", "QueenBee", "TrophyEikthyr", "BeechSeeds", "Acorn", "BirchSeeds");
		Seed((Biome)8, "FineWood", "RoundLog", "CopperOre", "Copper", "TinOre", "Tin", "Bronze", "TrollHide", "GreydwarfEye", "AncientSeed", "SurtlingCore", "Thistle", "Carrot", "CarrotSeeds", "BoneFragments", "Blueberries", "Coal", "CryptKey", "PineCone", "TrophyGreydwarf", "TrophyGreydwarfBrute", "TrophyGreydwarfShaman", "TrophyTroll", "TrophySkeleton", "TrophySkeletonPoison", "TrophyTheElder", "BjornHide", "BjornPaw", "TrophyBjorn", "TrophyGhost", "TrophyRazorback");
		Seed((Biome)2, "IronScrap", "IronOre", "Iron", "Guck", "Ooze", "Bloodbag", "Entrails", "WitheredBone", "ElderBark", "Root", "Turnip", "TurnipSeeds", "Wishbone", "TrophyDraugr", "TrophyDraugrElite", "TrophyDraugrFem", "TrophyBlob", "TrophyLeech", "TrophyWraith", "TrophyAbomination", "TrophyBonemass", "TrophySurtling", "Thunderstone");
		Seed((Biome)256, "SerpentScale", "SerpentMeat", "TrophySerpent", "Chitin");
		Seed((Biome)4, "SilverOre", "Silver", "WolfPelt", "WolfFang", "WolfClaw", "WolfMeat", "FreezeGland", "Obsidian", "Crystal", "DragonEgg", "DragonTear", "JuteRed", "Onion", "OnionSeeds", "FenrisHair", "FenrisClaw", "TrophyWolf", "TrophyHatchling", "TrophyFenring", "TrophyCultist", "TrophySGolem", "TrophyDragonQueen", "TrophyUlv", "TrophyFrostTroll", "TrophyCultist_Hildir", "TrophyBjornUndead");
		Seed((Biome)16, "BlackMetalScrap", "BlackMetal", "Flax", "Barley", "LinenThread", "Needle", "LoxPelt", "LoxMeat", "Tar", "Cloudberry", "GoblinTotem", "YagluthDrop", "TrophyGoblin", "TrophyGoblinBrute", "TrophyGoblinShaman", "TrophyLox", "TrophyDeathsquito", "TrophyGrowth", "TrophyGoblinKing", "BarleyFlour", "TrophyGoblinBruteBrosShaman");
		Seed((Biome)512, "Sap", "Eitr", "BlackCore", "Softtissue", "YggdrasilWood", "Carapace", "ScaleHide", "Mandible", "RoyalJelly", "BlackMarble", "Wisp", "DvergrNeedle", "DvergrKeyFragment", "JuteBlue", "Bilebag", "MushroomJotunPuffs", "MushroomMagecap", "QueenDrop", "TrophySeeker", "TrophySeekerBrute", "TrophyGjall", "TrophyTick", "TrophyDvergr", "TrophyHare", "TrophySeekerQueen", "GiantBloodSack", "CopperScrap", "HareMeat", "ChickenEgg");
		Seed((Biome)32, "FlametalOre", "FlametalOreNew", "FlametalNew", "Flametal", "CharredBone", "MoltenCore", "Blackwood", "AskHide", "AskBladder", "BonemawSerpentScale", "BonemawSerpentTooth", "CelestialFeather", "CharcoalResin", "GemstoneBlue", "GemstoneGreen", "GemstoneRed", "MorgenHeart", "MorgenSinew", "ProustitePowder", "SulfurStone", "Grausten", "FaderDrop", "Fiddleheadfern", "Vineberry", "VineberrySeeds", "TrophyFader", "TrophyAsksvin", "TrophyBonemawSerpent", "TrophyCharredArcher", "TrophyCharredMage", "TrophyCharredMelee", "TrophyFallenValkyrie", "TrophyKvastur", "TrophyMorgen", "TrophyVolture", "AsksvinMeat", "VoltureMeat", "BellFragment");
	}

	static Biomes()
	{
		Biome[] array = new Biome[9];
		RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
		Order = (Biome[])(object)array;
		Map = new Dictionary<string, Biome>(StringComparer.OrdinalIgnoreCase);
		Fixed = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
	}
}
public enum Role
{
	Mage,
	Tank,
	Damage,
	Archer
}
public class Entry
{
	public string Key;

	public string Name;

	public string Mod;

	public bool IsSet;

	public bool IsWeapon;

	public string Category;

	public List<ItemDrop> Pieces = new List<ItemDrop>();

	public StatusEffect SetEffect;

	public HashSet<Role> Roles = new HashSet<Role>();

	public Sprite Icon;

	public string SearchText;

	public int MaxQuality = 1;

	public Biome Biome;
}
public static class Catalog
{
	public static readonly List<Entry> Armor = new List<Entry>();

	public static readonly List<Entry> Weapons = new List<Entry>();

	public static readonly List<Entry> ArmorPieces = new List<Entry>();

	private static bool _builtRu;

	public static readonly List<string> Mods = new List<string>();

	public static readonly Dictionary<string, List<Recipe>> RecipesByItem = new Dictionary<string, List<Recipe>>();

	public static readonly HashSet<string> VanillaNames = new HashSet<string>();

	private static int _builtForCount = -1;

	private static ObjectDB _builtForDb;

	private static readonly ItemType[] ArmorSlots;

	private static readonly Regex SlotWords;

	public static int SlotOrder(ItemDrop d)
	{
		//IL_000b: 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_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Expected I4, but got Unknown
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Invalid comparison between Unknown and I4
		ItemType itemType = d.m_itemData.m_shared.m_itemType;
		switch (itemType - 6)
		{
		default:
			if ((int)itemType == 17)
			{
				return 3;
			}
			return 4;
		case 0:
			return 0;
		case 1:
			return 1;
		case 5:
			return 2;
		}
	}

	public static string L(string s)
	{
		if (string.IsNullOrEmpty(s))
		{
			return string.Empty;
		}
		try
		{
			return (Localization.instance == null) ? s : Localization.instance.Localize(s);
		}
		catch
		{
			return s;
		}
	}

	public static bool EnsureBuilt()
	{
		ObjectDB instance = ObjectDB.instance;
		if ((Object)(object)instance == (Object)null || instance.m_items == null || instance.m_items.Count == 0)
		{
			return false;
		}
		if ((Object)(object)instance == (Object)(object)_builtForDb && instance.m_items.Count == _builtForCount && _builtRu == Loc.Ru && Armor.Count + Weapons.Count > 0)
		{
			return true;
		}
		try
		{
			Build(instance);
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("Не удалось собрать каталог: " + ex));
		}
		_builtForDb = instance;
		_builtRu = Loc.Ru;
		_builtForCount = instance.m_items.Count;
		return true;
	}

	private static bool IsJunk(GameObject go, SharedData sh, string locName)
	{
		if (sh.m_icons == null || sh.m_icons.Length == 0 || (Object)(object)sh.m_icons[0] == (Object)null)
		{
			return true;
		}
		if (string.IsNullOrEmpty(locName) || locName.StartsWith("$") || locName.StartsWith("["))
		{
			return true;
		}
		string text = ((Object)go).name.ToLowerInvariant();
		if (text.Contains("cheat") || text.Contains("dummy") || text.Contains("debug") || text.Contains("_dev") || text.Contains("test"))
		{
			return true;
		}
		if (text.StartsWith("player") && text.Contains("unarmed"))
		{
			return true;
		}
		return false;
	}

	private static void Build(ObjectDB db)
	{
		//IL_044a: Unknown result type (might be due to invalid IL or missing references)
		//IL_044f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0168: Unknown result type (might be due to invalid IL or missing references)
		//IL_016d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0174: 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_0186: Invalid comparison between Unknown and I4
		//IL_018b: Unknown result type (might be due to invalid IL or missing references)
		//IL_018f: Invalid comparison between Unknown and I4
		//IL_0194: Unknown result type (might be due to invalid IL or missing references)
		//IL_0198: Invalid comparison between Unknown and I4
		//IL_019d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a0: Invalid comparison between Unknown and I4
		//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a8: Invalid comparison between Unknown and I4
		//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_0203: Unknown result type (might be due to invalid IL or missing references)
		//IL_0207: Invalid comparison between Unknown and I4
		//IL_020c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0210: Invalid comparison between Unknown and I4
		//IL_0215: Unknown result type (might be due to invalid IL or missing references)
		//IL_0219: Invalid comparison between Unknown and I4
		//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ae: Invalid comparison between Unknown and I4
		//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b7: Invalid comparison between Unknown and I4
		//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d2: Invalid comparison between Unknown and I4
		//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ed: Invalid comparison between Unknown and I4
		//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f6: Invalid comparison between Unknown and I4
		//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fe: Invalid comparison between Unknown and I4
		Armor.Clear();
		Weapons.Clear();
		ArmorPieces.Clear();
		Mods.Clear();
		RecipesByItem.Clear();
		ModResolver.Prepare();
		foreach (Recipe recipe in db.m_recipes)
		{
			if (!((Object)(object)recipe == (Object)null) && !((Object)(object)recipe.m_item == (Object)null))
			{
				string name = ((Object)((Component)recipe.m_item).gameObject).name;
				if (!RecipesByItem.TryGetValue(name, out var value))
				{
					value = new List<Recipe>();
					RecipesByItem[name] = value;
				}
				value.Add(recipe);
			}
		}
		List<ItemDrop> list = new List<ItemDrop>();
		HashSet<string> hashSet = new HashSet<string>();
		foreach (GameObject item in db.m_items)
		{
			if ((Object)(object)item == (Object)null || !hashSet.Add(((Object)item).name))
			{
				continue;
			}
			ItemDrop component = item.GetComponent<ItemDrop>();
			if ((Object)(object)component == (Object)null || component.m_itemData == null || component.m_itemData.m_shared == null)
			{
				continue;
			}
			SharedData shared = component.m_itemData.m_shared;
			ItemType itemType = shared.m_itemType;
			bool flag = Array.IndexOf(ArmorSlots, itemType) >= 0;
			bool flag2 = (int)itemType == 3 || (int)itemType == 14 || (int)itemType == 22 || (int)itemType == 4 || (int)itemType == 5;
			if (!flag && !flag2)
			{
				continue;
			}
			string text = L(shared.m_name);
			if (IsJunk(item, shared, text))
			{
				continue;
			}
			if (flag)
			{
				list.Add(component);
				continue;
			}
			SkillType skillType = shared.m_skillType;
			if ((int)skillType != 12 && (int)skillType != 104 && (int)skillType != 13)
			{
				Entry entry = new Entry();
				entry.Key = "w:" + ((Object)item).name;
				entry.Name = text;
				entry.Mod = ModResolver.Resolve(((Object)item).name);
				entry.IsWeapon = true;
				entry.Category = WeaponCategory(shared);
				entry.Icon = shared.m_icons[0];
				entry.MaxQuality = Mathf.Max(1, shared.m_maxQuality);
				Entry entry2 = entry;
				entry2.Pieces.Add(component);
				if ((int)skillType == 9 || (int)skillType == 10)
				{
					entry2.Roles.Add(Role.Mage);
				}
				else if ((int)itemType == 5)
				{
					entry2.Roles.Add(Role.Tank);
				}
				else if ((int)skillType == 8 || (int)skillType == 14 || (int)itemType == 4)
				{
					entry2.Roles.Add(Role.Archer);
				}
				else
				{
					entry2.Roles.Add(Role.Damage);
				}
				if (shared.m_attack != null && shared.m_attack.m_attackEitr > 0f && !entry2.Roles.Contains(Role.Mage))
				{
					entry2.Roles.Add(Role.Mage);
				}
				entry2.SearchText = (entry2.Name + " " + entry2.Mod + " " + entry2.Category + " " + ((Object)item).name).ToLowerInvariant();
				Weapons.Add(entry2);
			}
		}
		BuildArmorSets(list);
		try
		{
			Biomes.Build(db);
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Биомы не определены: " + ex));
		}
		foreach (Entry item2 in Armor.Concat(Weapons).Concat(ArmorPieces))
		{
			item2.Biome = EntryBiome(item2, 1);
		}
		ArmorPieces.Sort((Entry a, Entry b) => string.Compare(a.Name, b.Name, StringComparison.CurrentCultureIgnoreCase));
		foreach (Entry item3 in Armor.Concat(Weapons))
		{
			if (!Mods.Contains(item3.Mod))
			{
				Mods.Add(item3.Mod);
			}
		}
		Mods.Sort(delegate(string a, string b)
		{
			if (a == "Valheim")
			{
				return -1;
			}
			return (b == "Valheim") ? 1 : string.Compare(a, b, StringComparison.OrdinalIgnoreCase);
		});
		Armor.Sort(CompareEntries);
		Weapons.Sort(delegate(Entry a, Entry b)
		{
			int num = string.Compare(a.Category, b.Category, StringComparison.Ordinal);
			return (num == 0) ? CompareEntries(a, b) : num;
		});
		Plugin.Log.LogInfo((object)$"Каталог собран: {Armor.Count} сетов/вещей брони, {Weapons.Count} оружия, модов: {Mods.Count}");
	}

	private static int CompareEntries(Entry a, Entry b)
	{
		if (a.IsSet != b.IsSet)
		{
			return (!a.IsSet) ? 1 : (-1);
		}
		return string.Compare(a.Name, b.Name, StringComparison.CurrentCultureIgnoreCase);
	}

	private static string Stem(string prefabName)
	{
		string text = SlotWords.Replace(prefabName, string.Empty);
		return text.ToLowerInvariant().Trim();
	}

	private static void BuildArmorSets(List<ItemDrop> pieces)
	{
		Dictionary<string, List<ItemDrop>> dictionary = new Dictionary<string, List<ItemDrop>>();
		List<string> list = new List<string>();
		foreach (ItemDrop piece in pieces)
		{
			SharedData shared = piece.m_itemData.m_shared;
			string text;
			if (!string.IsNullOrEmpty(shared.m_setName))
			{
				text = "set:" + shared.m_setName;
			}
			else
			{
				string text2 = Stem(((Object)((Component)piece).gameObject).name);
				text = ((!string.IsNullOrEmpty(text2)) ? ("stem:" + ModResolver.Resolve(((Object)((Component)piece).gameObject).name) + ":" + text2) : ("one:" + ((Object)((Component)piece).gameObject).name));
			}
			if (!dictionary.TryGetValue(text, out var value))
			{
				value = (dictionary[text] = new List<ItemDrop>());
				list.Add(text);
			}
			value.Add(piece);
		}
		List<float> list3 = new List<float>();
		foreach (ItemDrop piece2 in pieces)
		{
			list3.Add(piece2.m_itemData.m_shared.m_armor);
		}
		list3.Sort();
		float heavyArmor = ((list3.Count <= 0) ? 999f : list3[(int)((float)list3.Count * 0.7f)]);
		foreach (string item in list)
		{
			List<ItemDrop> list4 = dictionary[item];
			if (item.StartsWith("stem:"))
			{
				HashSet<ItemType> hashSet = new HashSet<ItemType>(list4.Select((ItemDrop x) => x.m_itemData.m_shared.m_itemType));
				if (hashSet.Count < 2 || hashSet.Count < list4.Count - 1)
				{
					foreach (ItemDrop item2 in list4)
					{
						List<ItemDrop> list5 = new List<ItemDrop>();
						list5.Add(item2);
						AddArmorEntry(list5, "one:" + ((Object)((Component)item2).gameObject).name, heavyArmor);
					}
					continue;
				}
			}
			AddArmorEntry(list4, item, heavyArmor);
		}
	}

	private static void AddArmorEntry(List<ItemDrop> g, string key, float heavyArmor)
	{
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0572: Unknown result type (might be due to invalid IL or missing references)
		g.Sort((ItemDrop a, ItemDrop b) => SlotOrder(a).CompareTo(SlotOrder(b)));
		ItemDrop val = g[0];
		ItemDrop val2 = ((IEnumerable<ItemDrop>)g).FirstOrDefault((Func<ItemDrop, bool>)((ItemDrop x) => (int)x.m_itemData.m_shared.m_itemType == 7)) ?? val;
		SharedData shared = val2.m_itemData.m_shared;
		StatusEffect val3 = g.Select((ItemDrop x) => x.m_itemData.m_shared.m_setStatusEffect).FirstOrDefault((Func<StatusEffect, bool>)((StatusEffect x) => (Object)(object)x != (Object)null));
		Entry entry = new Entry();
		entry.Key = key;
		entry.Mod = ModResolver.Resolve(((Object)((Component)val).gameObject).name);
		entry.IsSet = g.Count > 1;
		entry.Category = ((g.Count <= 1) ? SlotName(val.m_itemData.m_shared.m_itemType) : Loc.T("Сет", "Set"));
		entry.Icon = shared.m_icons[0];
		entry.SetEffect = val3;
		entry.MaxQuality = Mathf.Max(1, g.Max((ItemDrop x) => x.m_itemData.m_shared.m_maxQuality));
		Entry entry2 = entry;
		entry2.Pieces.AddRange(g);
		string text = ((!((Object)(object)val3 != (Object)null)) ? string.Empty : L(val3.m_name));
		if (g.Count > 1)
		{
			string text2 = (entry2.Name = L(shared.m_name));
			if (!string.IsNullOrEmpty(text) && !text.StartsWith("$"))
			{
				entry2.Name = text2 + "  ·  " + text;
			}
		}
		else
		{
			entry2.Name = L(val.m_itemData.m_shared.m_name);
		}
		float num = 0f;
		float num2 = 0f;
		float num3 = 0f;
		foreach (ItemDrop item in g)
		{
			SharedData shared2 = item.m_itemData.m_shared;
			num += shared2.m_eitrRegenModifier;
			num2 += shared2.m_movementModifier;
			num3 += shared2.m_armor;
		}
		string text3 = string.Empty;
		if ((Object)(object)val3 != (Object)null)
		{
			try
			{
				text3 = (L(val3.m_name) + " " + L(val3.GetTooltipString())).ToLowerInvariant();
			}
			catch
			{
			}
		}
		string text4 = string.Join(" ", g.Select((ItemDrop p) => L(p.m_itemData.m_shared.m_description) + " " + ((Object)((Component)p).gameObject).name).ToArray()).ToLowerInvariant();
		string text5 = text3 + " " + text4;
		if (num > 0.001f || text5.Contains("eitr") || text5.Contains("эйтр") || text5.Contains("magic") || text5.Contains("маги"))
		{
			entry2.Roles.Add(Role.Mage);
		}
		if (num2 <= -0.099f || (num3 / (float)g.Count >= heavyArmor && heavyArmor > 0f))
		{
			entry2.Roles.Add(Role.Tank);
		}
		if (text5.Contains("bow") || text5.Contains("лук") || text5.Contains("стрел") || text5.Contains("arrow") || text5.Contains("sneak") || text5.Contains("скрыт") || text5.Contains("ranger") || text5.Contains("hunter") || text5.Contains("охотн"))
		{
			entry2.Roles.Add(Role.Archer);
		}
		if (!entry2.Roles.Contains(Role.Mage) && !entry2.Roles.Contains(Role.Tank))
		{
			entry2.Roles.Add(Role.Damage);
		}
		entry2.SearchText = (entry2.Name + " " + entry2.Mod + " " + string.Join(" ", g.Select((ItemDrop p) => L(p.m_itemData.m_shared.m_name) + " " + ((Object)((Component)p).gameObject).name).ToArray())).ToLowerInvariant();
		Armor.Add(entry2);
		foreach (ItemDrop item2 in g)
		{
			SharedData shared3 = item2.m_itemData.m_shared;
			entry = new Entry();
			entry.Key = "piece:" + ((Object)((Component)item2).gameObject).name;
			entry.Name = L(shared3.m_name);
			entry.Mod = entry2.Mod;
			entry.IsSet = false;
			entry.Category = SlotName(shared3.m_itemType);
			entry.Icon = shared3.m_icons[0];
			entry.SetEffect = entry2.SetEffect;
			entry.MaxQuality = Mathf.Max(1, shared3.m_maxQuality);
			Entry entry3 = entry;
			entry3.Pieces.Add(item2);
			foreach (Role role in entry2.Roles)
			{
				entry3.Roles.Add(role);
			}
			entry3.SearchText = (entry3.Name + " " + entry3.Mod + " " + entry2.Name + " " + ((Object)((Component)item2).gameObject).name).ToLowerInvariant();
			ArmorPieces.Add(entry3);
		}
	}

	public static string SlotName(ItemType t)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Expected I4, but got Unknown
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Invalid comparison between Unknown and I4
		switch (t - 6)
		{
		default:
			if ((int)t == 17)
			{
				return Loc.T("Плащ", "Cape");
			}
			return Loc.T("Вещь", "Item");
		case 0:
			return Loc.T("Шлем", "Helmet");
		case 1:
			return Loc.T("Грудь", "Chest");
		case 5:
			return Loc.T("Ноги", "Legs");
		}
	}

	private static string WeaponCategory(SharedData sh)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Invalid comparison between Unknown and I4
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: 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_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Expected I4, but got Unknown
		//IL_0129: Unknown result type (might be due to invalid IL or missing references)
		//IL_012f: Invalid comparison between Unknown and I4
		if ((int)sh.m_itemType == 5)
		{
			return Loc.T("Щиты", "Shields");
		}
		SkillType skillType = sh.m_skillType;
		switch (skillType - 1)
		{
		case 0:
			return Loc.T("Мечи", "Swords");
		case 6:
			return Loc.T("Топоры", "Axes");
		case 2:
			return Loc.T("Дубины и молоты", "Clubs & maces");
		case 1:
			return Loc.T("Ножи", "Knives");
		case 3:
			return Loc.T("Древковое", "Polearms");
		case 4:
			return Loc.T("Копья", "Spears");
		case 7:
			return Loc.T("Луки", "Bows");
		case 13:
			return Loc.T("Арбалеты", "Crossbows");
		case 8:
			return Loc.T("Посохи: стихии", "Staffs: elemental");
		case 9:
			return Loc.T("Посохи: кровь", "Staffs: blood");
		case 10:
			return Loc.T("Кастеты", "Fists");
		case 5:
			return Loc.T("Щиты", "Shields");
		default:
			if ((int)sh.m_itemType == 4)
			{
				return Loc.T("Луки", "Bows");
			}
			return Loc.T("Прочее", "Other");
		}
	}

	public static Biome EntryBiome(Entry e, int quality)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: 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)
		Biome val = (Biome)0;
		foreach (ItemDrop piece in e.Pieces)
		{
			Recipe recipe = GetRecipe(piece);
			int quality2 = Mathf.Min(quality, Mathf.Max(1, piece.m_itemData.m_shared.m_maxQuality));
			Biome val2 = ((!((Object)(object)recipe != (Object)null)) ? Biomes.Of(((Object)((Component)piece).gameObject).name) : Biomes.MaxOf(recipe, quality2));
			if (Biomes.Tier(val2) > Biomes.Tier(val))
			{
				val = val2;
			}
		}
		return val;
	}

	public static Recipe GetRecipe(ItemDrop d)
	{
		if (!RecipesByItem.TryGetValue(((Object)((Component)d).gameObject).name, out var value))
		{
			return null;
		}
		Recipe val = ((IEnumerable<Recipe>)value).FirstOrDefault((Func<Recipe, bool>)((Recipe x) => x.m_enabled && x.m_resources != null && x.m_resources.Length > 0));
		return val ?? value.FirstOrDefault();
	}

	static Catalog()
	{
		ItemType[] array = new ItemType[4];
		RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
		ArmorSlots = (ItemType[])(object)array;
		SlotWords = new Regex("(helmet|helm|hood|hat|cap|crown|circlet|mask|head|armou?r|chest|cuirass|torso|body|tunic|robe|shirt|coat|jacket|vest|legs?|pants|trousers|leggings|greaves|boots|cape|cloak|mantle|shoulders?|pauldrons?|scarf|_|-|\\d+$)", RegexOptions.IgnoreCase);
	}
}
public static class ModResolver
{
	public const string Vanilla = "Valheim";

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

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

	private static readonly string[][] KnownBundles = new string[17][]
	{
		new string[2] { "southsil", "Southsil Armor" },
		new string[2] { "warfare", "Warfare" },
		new string[2] { "wizardry", "Wizardry" },
		new string[2] { "hugo", "Hugo's Armory" },
		new string[2] { "ascend", "Ascendant Armory" },
		new string[2] { "magicsupremacy", "Magic Supremacy" },
		new string[2] { "supremacy", "Magic Supremacy" },
		new string[2] { "valheimarmory", "Valheim Armory" },
		new string[2] { "epicloot", "Epic Loot" },
		new string[2] { "magicrevamp", "Magic Revamp" },
		new string[2] { "magicplugin", "Magic Plugin" },
		new string[2] { "bowplugin", "Bow Plugin" },
		new string[2] { "wildweapons", "Wild Weapons" },
		new string[2] { "odin", "OdinPlus" },
		new string[2] { "corsair", "Corsairs" },
		new string[2] { "backpack", "Backpacks" },
		new string[2] { "fortress", "Valheim Fortress" }
	};

	private static string Unknown => Loc.T("Мод (неизвестный)", "Unknown mod");

	public static void Prepare()
	{
		PrefabToBundle.Clear();
		PrefabToJotunnMod.Clear();
		try
		{
			foreach (AssetBundle allLoadedAssetBundle in AssetBundle.GetAllLoadedAssetBundles())
			{
				if ((Object)(object)allLoadedAssetBundle == (Object)null || allLoadedAssetBundle.isStreamedSceneAssetBundle)
				{
					continue;
				}
				string[] allAssetNames;
				try
				{
					allAssetNames = allLoadedAssetBundle.GetAllAssetNames();
				}
				catch
				{
					continue;
				}
				string[] array = allAssetNames;
				foreach (string text in array)
				{
					if (text.EndsWith(".prefab"))
					{
						int num = text.LastIndexOf('/');
						string key = text.Substring(num + 1, text.Length - num - 1 - ".prefab".Length);
						if (!PrefabToBundle.ContainsKey(key))
						{
							PrefabToBundle[key] = ((Object)allLoadedAssetBundle).name;
						}
					}
				}
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Ассет-бандлы не прочитались: " + ex.Message));
		}
		try
		{
			Type type = AccessTools.TypeByName("Jotunn.Managers.ItemManager");
			if (!(type != null))
			{
				return;
			}
			object value = Traverse.Create(type).Property("Instance", (object[])null).GetValue();
			if (!(Traverse.Create(value).Field("Items").GetValue() is IEnumerable enumerable))
			{
				return;
			}
			foreach (object item in enumerable)
			{
				object obj2 = Traverse.Create(item).Property("Value", (object[])null).GetValue() ?? item;
				object value2 = Traverse.Create(obj2).Property("ItemPrefab", (object[])null).GetValue();
				GameObject val = (GameObject)((value2 is GameObject) ? value2 : null);
				object value3 = Traverse.Create(obj2).Property("SourceMod", (object[])null).GetValue();
				string value4 = ((value3 == null) ? null : (Traverse.Create(value3).Property("Name", (object[])null).GetValue() as string));
				if ((Object)(object)val != (Object)null && !string.IsNullOrEmpty(value4))
				{
					PrefabToJotunnMod[((Object)val).name] = value4;
				}
			}
		}
		catch (Exception ex2)
		{
			Plugin.Log.LogDebug((object)("Jotunn не опрошен: " + ex2.Message));
		}
	}

	public static string Resolve(string prefab)
	{
		if (Catalog.VanillaNames.Contains(prefab))
		{
			return "Valheim";
		}
		if (PrefabToJotunnMod.TryGetValue(prefab, out var value))
		{
			return value;
		}
		if (PrefabToBundle.TryGetValue(prefab.ToLowerInvariant(), out var value2))
		{
			return Pretty(value2);
		}
		return Unknown;
	}

	private static string Pretty(string bundle)
	{
		string text = bundle.ToLowerInvariant();
		string[][] knownBundles = KnownBundles;
		foreach (string[] array in knownBundles)
		{
			if (text.Contains(array[0]))
			{
				return array[1];
			}
		}
		int num = text.LastIndexOf('/');
		if (num >= 0)
		{
			bundle = bundle.Substring(num + 1);
		}
		if (bundle.Length > 0)
		{
			bundle = char.ToUpperInvariant(bundle[0]) + bundle.Substring(1);
		}
		return bundle;
	}
}
public static class Loc
{
	public static bool Ru = true;

	public static void Detect()
	{
		string text = ((Plugin.Language == null) ? "Auto" : Plugin.Language.Value);
		if (text == "Russian")
		{
			Ru = true;
			return;
		}
		if (text == "English")
		{
			Ru = false;
			return;
		}
		string text2 = "English";
		try
		{
			if (Localization.instance != null)
			{
				text2 = Localization.instance.GetSelectedLanguage();
			}
		}
		catch
		{
		}
		Ru = text2 == "Russian" || text2 == "Ukrainian" || text2 == "Belarusian";
	}

	public static string T(string ru, string en)
	{
		return (!Ru) ? en : ru;
	}
}
public static class Outfits
{
	public class Outfit
	{
		public string Name;

		public string[] Slots = new string[4];

		public string Right = string.Empty;

		public string Left = string.Empty;
	}

	public static readonly List<Outfit> List = new List<Outfit>();

	private static bool _loaded;

	private static string FilePath => Path.Combine(Paths.ConfigPath, "umorise.valhallawardrobe.outfits.txt");

	public static void EnsureLoaded()
	{
		if (_loaded)
		{
			return;
		}
		_loaded = true;
		List.Clear();
		try
		{
			if (!File.Exists(FilePath))
			{
				return;
			}
			string[] array = File.ReadAllLines(FilePath);
			foreach (string text in array)
			{
				string[] array2 = text.Split('\t');
				if (array2.Length >= 7 && !string.IsNullOrEmpty(array2[0]))
				{
					Outfit outfit = new Outfit();
					outfit.Name = array2[0];
					outfit.Right = array2[5];
					outfit.Left = array2[6];
					Outfit outfit2 = outfit;
					for (int j = 0; j < 4; j++)
					{
						outfit2.Slots[j] = array2[1 + j];
					}
					List.Add(outfit2);
				}
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Outfits not loaded: " + ex.Message));
		}
	}

	private static void Save()
	{
		try
		{
			List<string> list = new List<string>();
			foreach (Outfit item in List)
			{
				list.Add(string.Join("\t", item.Name.Replace("\t", " "), item.Slots[0], item.Slots[1], item.Slots[2], item.Slots[3], item.Right, item.Left));
			}
			File.WriteAllLines(FilePath, list.ToArray());
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Outfits not saved: " + ex.Message));
		}
	}

	private static string Code(ItemDrop d, bool empty)
	{
		return ((Object)(object)d != (Object)null) ? ((Object)((Component)d).gameObject).name : ((!empty) ? string.Empty : "-");
	}

	public static void SaveCurrent(string name)
	{
		EnsureLoaded();
		Outfit o = new Outfit
		{
			Name = ((!string.IsNullOrEmpty(name)) ? name.Trim() : ("Outfit " + (List.Count + 1)))
		};
		for (int i = 0; i < 4; i++)
		{
			o.Slots[i] = Code(Preview.Slots[i], Preview.Naked[i]);
		}
		o.Right = Code(Preview.RightItem, Preview.RightEmpty);
		o.Left = Code(Preview.LeftItem, Preview.LeftEmpty);
		int num = List.FindIndex((Outfit x) => x.Name == o.Name);
		if (num >= 0)
		{
			List[num] = o;
		}
		else
		{
			List.Add(o);
		}
		Save();
	}

	public static void Delete(int idx)
	{
		if (idx >= 0 && idx < List.Count)
		{
			List.RemoveAt(idx);
			Save();
		}
	}

	private static ItemDrop Find(string code)
	{
		if (string.IsNullOrEmpty(code) || code == "-" || (Object)(object)ObjectDB.instance == (Object)null)
		{
			return null;
		}
		GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(code);
		return (!((Object)(object)itemPrefab != (Object)null)) ? null : itemPrefab.GetComponent<ItemDrop>();
	}

	public static void Apply(Outfit o)
	{
		Preview.ClearAll();
		for (int i = 0; i < 4; i++)
		{
			if (o.Slots[i] == "-")
			{
				Preview.EmptySlot(i);
				continue;
			}
			ItemDrop val = Find(o.Slots[i]);
			if ((Object)(object)val != (Object)null)
			{
				Preview.SetArmorPiece(val);
			}
		}
		Preview.RightItem = Find(o.Right);
		Preview.RightEmpty = o.Right == "-";
		Preview.LeftItem = Find(o.Left);
		Preview.LeftEmpty = o.Left == "-";
		Preview.MarkDirty();
	}
}
[BepInPlugin("umorise.valhallawardrobe", "Valhalla Wardrobe", "1.6.0")]
public class Plugin : BaseUnityPlugin
{
	[HarmonyPatch(typeof(ObjectDB), "Awake")]
	private static class ObjectDBAwake
	{
		[HarmonyPriority(800)]
		private static void Prefix(ObjectDB __instance)
		{
			if (Catalog.VanillaNames.Count > 0 || __instance.m_items == null)
			{
				return;
			}
			foreach (GameObject item in __instance.m_items)
			{
				if ((Object)(object)item != (Object)null)
				{
					Catalog.VanillaNames.Add(((Object)item).name);
				}
			}
		}
	}

	[HarmonyPatch(typeof(PlayerController), "TakeInput")]
	private static class BlockControllerInput
	{
		private static bool Prefix(ref bool __result)
		{
			if ((Object)(object)Instance == (Object)null || !Instance.Ui.Open)
			{
				return true;
			}
			__result = false;
			return false;
		}
	}

	[HarmonyPatch(typeof(Player), "TakeInput")]
	private static class BlockPlayerInput
	{
		private static bool Prefix(ref bool __result)
		{
			if ((Object)(object)Instance == (Object)null || !Instance.Ui.Open)
			{
				return true;
			}
			__result = false;
			return false;
		}
	}

	[HarmonyPatch(typeof(GameCamera), "UpdateMouseCapture")]
	private static class FreeCursor
	{
		private static void Postfix()
		{
			if (!((Object)(object)Instance == (Object)null) && Instance.Ui.Open)
			{
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
			}
		}
	}

	[HarmonyPatch(typeof(Menu), "Update")]
	private static class NoEscMenu
	{
		private static bool Prefix()
		{
			return (Object)(object)Instance == (Object)null || (!Instance.Ui.Open && Instance.Ui.ClosedFrame != Time.frameCount);
		}
	}

	[HarmonyPatch(typeof(InventoryGui), "Update")]
	private static class NoInventoryWhileOpen
	{
		private static bool Prefix()
		{
			return (Object)(object)Instance == (Object)null || !Instance.Ui.Open;
		}
	}

	[HarmonyPatch(typeof(Minimap), "Update")]
	private static class NoMapWhileOpen
	{
		private static bool Prefix()
		{
			return (Object)(object)Instance == (Object)null || !Instance.Ui.Open;
		}
	}

	public const string Guid = "umorise.valhallawardrobe";

	public const string Version = "1.6.0";

	public static ManualLogSource Log;

	public static Plugin Instance;

	public static ConfigEntry<KeyCode> Hotkey;

	public static ConfigEntry<float> ChestRadius;

	public static ConfigEntry<float> UiScale;

	public static ConfigEntry<string> Language;

	private Harmony _harmony;

	public Window Ui = new Window();

	private ObjectDB _recoloredFor;

	private void Awake()
	{
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Expected O, but got Unknown
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Expected O, but got Unknown
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		Instance = this;
		Log = ((BaseUnityPlugin)this).Logger;
		Hotkey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "Hotkey", (KeyCode)290, "Open/close Valhalla Wardrobe / Открыть или закрыть окно");
		ChestRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Crafting", "Chest radius", 30f, "Chests within this radius count toward have/need (0 = inventory only) / Радиус сундуков для счётчика «есть / нужно»");
		UiScale = ((BaseUnityPlugin)this).Config.Bind<float>("General", "UI scale", 1f, "Window size multiplier / Масштаб окна");
		Language = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Language", "Auto", new ConfigDescription("Interface language / Язык интерфейса: Auto follows the game language", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[3] { "Auto", "English", "Russian" }), Array.Empty<object>()));
		_harmony = new Harmony("umorise.valhallawardrobe");
		_harmony.PatchAll(typeof(Plugin).Assembly);
		Log.LogInfo((object)("Valhalla Wardrobe загружен. Клавиша: " + Hotkey.Value));
	}

	private void OnDestroy()
	{
		Preview.Destroy();
		if (_harmony != null)
		{
			_harmony.UnpatchSelf();
		}
	}

	private static bool OtherUiBusy()
	{
		if (Console.IsVisible() || TextInput.IsVisible() || Menu.IsVisible() || Minimap.InTextInput() || StoreGui.IsVisible())
		{
			return true;
		}
		if ((Object)(object)Chat.instance != (Object)null && Chat.instance.HasFocus())
		{
			return true;
		}
		return false;
	}

	private void Update()
	{
		//IL_00c9: 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)
		if ((Object)(object)Player.m_localPlayer != (Object)null && (Object)(object)ObjectDB.instance != (Object)null && (Object)(object)ObjectDB.instance != (Object)(object)_recoloredFor)
		{
			_recoloredFor = ObjectDB.instance;
			try
			{
				Recolor.ApplyAll();
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Recolor: " + ex.Message));
			}
		}
		if ((Object)(object)Player.m_localPlayer != (Object)null)
		{
			Recolor.Tick();
		}
		if ((Object)(object)Player.m_localPlayer == (Object)null)
		{
			if (Ui.Open)
			{
				Ui.Close();
			}
			return;
		}
		bool flag = false;
		try
		{
			flag = ZInput.GetKeyDown(Hotkey.Value, false);
		}
		catch
		{
			flag = Input.GetKeyDown(Hotkey.Value);
		}
		if (Ui.Open)
		{
			if (flag || ZInput.GetKeyDown((KeyCode)27, false))
			{
				Ui.Close();
			}
			else if (((Character)Player.m_localPlayer).IsDead())
			{
				Ui.Close();
			}
		}
		else if (flag && !OtherUiBusy())
		{
			if (InventoryGui.IsVisible())
			{
				InventoryGui.instance.Hide();
			}
			Ui.Show();
		}
	}

	private void LateUpdate()
	{
		if (Ui.Open)
		{
			Preview.Update();
		}
	}

	private void OnGUI()
	{
		if (Ui.Open)
		{
			Ui.Draw();
		}
	}
}
public static class Preview
{
	public const int Keep = -1;

	public static readonly ItemDrop[] Slots = (ItemDrop[])(object)new ItemDrop[4];

	public static readonly bool[] Naked = new bool[4];

	public static ItemDrop RightItem;

	public static ItemDrop LeftItem;

	public static bool RightEmpty;

	public static bool LeftEmpty;

	public static float Yaw = 0f;

	public static float Zoom = 3.4f;

	public static RenderTexture Texture;

	private static GameObject _clone;

	private static GameObject _camGo;

	private static GameObject _lightGo;

	private static GameObject _fillGo;

	private static VisEquipment _vis;

	private static Camera _cam;

	private static int _layer = -1;

	private static Vector3 _origin;

	private static bool _dirty;

	private static int _lastLayerFix;

	private static int sHelmet;

	private static int sChest;

	private static int sLegs;

	private static int sShoulder;

	private static int sShoulderVar;

	private static int sShoulderQ;

	private static int sUtility;

	private static int sRight;

	private static int sRightQ;

	private static int sLeft;

	private static int sLeftVar;

	private static int sLeftQ;

	private static int sModel;

	private static int sHair;

	private static int sBeard;

	private static Vector3 sSkin;

	private static Vector3 sHairColor;

	private static readonly FieldInfo VisRef = AccessTools.Field(typeof(Humanoid), "m_visEquipment");

	public static bool WeaponActive => (Object)(object)RightItem != (Object)null || (Object)(object)LeftItem != (Object)null || RightEmpty || LeftEmpty;

	public static VisEquipment Vis => _vis;

	public static bool Active => (Object)(object)_clone != (Object)null;

	public static int SlotOf(ItemDrop p)
	{
		//IL_000b: 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_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Expected I4, but got Unknown
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Invalid comparison between Unknown and I4
		ItemType itemType = p.m_itemData.m_shared.m_itemType;
		switch (itemType - 6)
		{
		default:
			if ((int)itemType == 17)
			{
				return 3;
			}
			return -1;
		case 0:
			return 0;
		case 1:
			return 1;
		case 5:
			return 2;
		}
	}

	private static FieldInfo F(string n)
	{
		return AccessTools.Field(typeof(VisEquipment), n);
	}

	private static int GetI(VisEquipment v, string n)
	{
		FieldInfo fieldInfo = F(n);
		return (fieldInfo != null) ? ((int)fieldInfo.GetValue(v)) : 0;
	}

	public static void SetArmor(Entry e)
	{
		for (int i = 0; i < 4; i++)
		{
			Slots[i] = null;
			Naked[i] = false;
		}
		if (e != null)
		{
			foreach (ItemDrop piece in e.Pieces)
			{
				int num = SlotOf(piece);
				if (num >= 0 && (Object)(object)Slots[num] == (Object)null)
				{
					Slots[num] = piece;
				}
			}
		}
		_dirty = true;
	}

	public static void SetArmorPiece(ItemDrop p)
	{
		int num = SlotOf(p);
		if (num >= 0)
		{
			Slots[num] = p;
			Naked[num] = false;
			_dirty = true;
		}
	}

	public static void ResetSlot(int s)
	{
		Slots[s] = null;
		Naked[s] = false;
		_dirty = true;
	}

	public static void EmptySlot(int s)
	{
		Slots[s] = null;
		Naked[s] = true;
		_dirty = true;
	}

	public static void SetWeapon(Entry e)
	{
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Invalid comparison between Unknown and I4
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Invalid comparison between Unknown and I4
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Invalid comparison between Unknown and I4
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Invalid comparison between Unknown and I4
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		//IL_010d: Invalid comparison between Unknown and I4
		if (e == null)
		{
			RightItem = (LeftItem = null);
			RightEmpty = (LeftEmpty = false);
			_dirty = true;
			return;
		}
		ItemDrop val = e.Pieces[0];
		ItemType itemType = val.m_itemData.m_shared.m_itemType;
		if ((int)itemType == 4)
		{
			goto IL_00a2;
		}
		if ((int)itemType != 5)
		{
			if ((int)itemType != 14)
			{
				if ((int)itemType == 22)
				{
					goto IL_00a2;
				}
				RightItem = val;
				RightEmpty = false;
				if ((Object)(object)LeftItem != (Object)null && (int)LeftItem.m_itemData.m_shared.m_itemType != 5)
				{
					LeftItem = null;
					LeftEmpty = true;
				}
			}
			else
			{
				RightItem = val;
				RightEmpty = false;
				LeftItem = null;
				LeftEmpty = true;
			}
		}
		else
		{
			LeftItem = val;
			LeftEmpty = false;
			if ((Object)(object)RightItem != (Object)null && IsTwoHanded(RightItem))
			{
				RightItem = null;
				RightEmpty = true;
			}
		}
		goto IL_0123;
		IL_0123:
		_dirty = true;
		return;
		IL_00a2:
		LeftItem = val;
		LeftEmpty = false;
		RightItem = null;
		RightEmpty = true;
		goto IL_0123;
	}

	private static bool IsTwoHanded(ItemDrop d)
	{
		//IL_000b: 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_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Invalid comparison between Unknown and I4
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Invalid comparison between Unknown and I4
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Invalid comparison between Unknown and I4
		ItemType itemType = d.m_itemData.m_shared.m_itemType;
		return (int)itemType == 14 || (int)itemType == 22 || (int)itemType == 4;
	}

	public static void MarkDirty()
	{
		_dirty = true;
	}

	public static void ClearHand(bool right)
	{
		if (right)
		{
			RightItem = null;
			RightEmpty = false;
		}
		else
		{
			LeftItem = null;
			LeftEmpty = false;
		}
		_dirty = true;
	}

	public static void ClearAll()
	{
		for (int i = 0; i < 4; i++)
		{
			Slots[i] = null;
			Naked[i] = false;
		}
		RightItem = (LeftItem = null);
		RightEmpty = (LeftEmpty = false);
		_dirty = true;
	}

	public static void Undress()
	{
		for (int i = 0; i < 4; i++)
		{
			Slots[i] = null;
			Naked[i] = true;
		}
		_dirty = true;
	}

	private static int Hash(ItemDrop d)
	{
		return StringExtensionMethods.GetStableHashCode(((Object)((Component)d).gameObject).name);
	}

	private static int SlotHash(int i, int own)
	{
		if ((Object)(object)Slots[i] != (Object)null)
		{
			return Hash(Slots[i]);
		}
		return (!Naked[i]) ? own : 0;
	}

	public static bool Create()
	{
		//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_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ce: Expected O, but got Unknown
		//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f8: Expected O, but got Unknown
		//IL_022b: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ab: Expected O, but got Unknown
		//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0304: Unknown result type (might be due to invalid IL or missing references)
		//IL_030e: Expected O, but got Unknown
		//IL_033f: Unknown result type (might be due to invalid IL or missing references)
		Destroy();
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null || (Object)(object)ZNetScene.instance == (Object)null)
		{
			return false;
		}
		try
		{
			SnapshotPlayer(localPlayer);
			GameObject prefab = ZNetScene.instance.GetPrefab("Player");
			if ((Object)(object)prefab == (Object)null)
			{
				Plugin.Log.LogError((object)"Не найден префаб Player");
				return false;
			}
			_origin = ((Component)localPlayer).transform.position + new Vector3(0f, 3000f, 0f);
			ZNetView.m_forceDisableInit = true;
			try
			{
				_clone = Object.Instantiate<GameObject>(prefab, _origin, Quaternion.identity);
			}
			finally
			{
				ZNetView.m_forceDisableInit = false;
			}
			((Object)_clone).name = "ValhallaWardrobe_Mannequin";
			Rigidbody component = _clone.GetComponent<Rigidbody>();
			if ((Object)(object)component != (Object)null)
			{
				Object.Destroy((Object)(object)component);
			}
			Collider[] componentsInChildren = _clone.GetComponentsInChildren<Collider>(true);
			foreach (Collider val in componentsInChildren)
			{
				val.enabled = false;
			}
			Animator[] componentsInChildren2 = _clone.GetComponentsInChildren<Animator>(true);
			foreach (Animator val2 in componentsInChildren2)
			{
				val2.updateMode = (AnimatorUpdateMode)2;
			}
			RemoveFromStaticList(typeof(Player), "s_players", _clone.GetComponent<Player>());
			RemoveFromStaticList(typeof(Character), "s_characters", _clone.GetComponent<Character>());
			RemoveFromInstances(_clone.GetComponent<Character>());
			_vis = _clone.GetComponent<VisEquipment>();
			_layer = FindFreeLayer();
			SetLayer(_clone, _layer);
			RenderTexture val3 = new RenderTexture(640, 1000, 24, (RenderTextureFormat)0);
			val3.antiAliasing = 4;
			RenderTexture val4 = val3;
			val4.Create();
			Texture = val4;
			_camGo = new GameObject("ValhallaWardrobe_Camera");
			_cam = _camGo.AddComponent<Camera>();
			_cam.clearFlags = (CameraClearFlags)2;
			_cam.backgroundColor = new Color(0.1f, 0.085f, 0.07f, 1f);
			_cam.cullingMask = 1 << _layer;
			_cam.fieldOfView = 30f;
			_cam.nearClipPlane = 0.05f;
			_cam.farClipPlane = 50f;
			_cam.targetTexture = val4;
			_cam.allowHDR = false;
			_cam.depth = -50f;
			_lightGo = new GameObject("ValhallaWardrobe_Key");
			Light val5 = _lightGo.AddComponent<Light>();
			val5.type = (LightType)1;
			val5.intensity = 1.25f;
			val5.color = new Color(1f, 0.93f, 0.82f);
			val5.cullingMask = 1 << _layer;
			val5.shadows = (LightShadows)0;
			_fillGo = new GameObject("ValhallaWardrobe_Fill");
			Light val6 = _fillGo.AddComponent<Light>();
			val6.type = (LightType)1;
			val6.intensity = 0.55f;
			val6.color = new Color(0.7f, 0.78f, 1f);
			val6.cullingMask = 1 << _layer;
			val6.shadows = (LightShadows)0;
			ApplyAppearance();
			_dirty = true;
			Update();
			return true;
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("Не удалось создать манекен: " + ex));
			Destroy();
			return false;
		}
	}

	public static void Destroy()
	{
		if ((Object)(object)_clone != (Object)null)
		{
			Object.Destroy((Object)(object)_clone);
		}
		if ((Object)(object)_camGo != (Object)null)
		{
			Object.Destroy((Object)(object)_camGo);
		}
		if ((Object)(object)_lightGo != (Object)null)
		{
			Object.Destroy((Object)(object)_lightGo);
		}
		if ((Object)(object)_fillGo != (Object)null)
		{
			Object.Destroy((Object)(object)_fillGo);
		}
		if ((Object)(object)Texture != (Object)null)
		{
			Texture.Release();
			Object.Destroy((Object)(object)Texture);
		}
		_clone = (_camGo = (_lightGo = (_fillGo = null)));
		_vis = null;
		_cam = null;
		Texture = null;
	}

	public static void Update()
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: 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)
		if (!((Object)(object)_clone == (Object)null) && !((Object)(object)_vis == (Object)null))
		{
			_clone.transform.position = _origin;
			_clone.transform.rotation = Quaternion.Euler(0f, 180f + Yaw, 0f);
			if (_dirty)
			{
				_dirty = false;
				ApplyEquipment();
			}
			if (Time.frameCount - _lastLayerFix > 5)
			{
				_lastLayerFix = Time.frameCount;
				SetLayer(_clone, _layer);
			}
			float num = 1f;
			Vector3 val = _origin + Vector3.up * num;
			Vector3 val2 = _origin + new Vector3(0f, num + 0.15f, 0f - Zoom);
			_camGo.transform.position = val2;
			_camGo.transform.rotation = Quaternion.LookRotation(val - val2, Vector3.up);
			_lightGo.transform.rotation = Quaternion.Euler(35f, 25f, 0f);
			_fillGo.transform.rotation = Quaternion.Euler(15f, 160f, 0f);
		}
	}

	private static void SnapshotPlayer(Player p)
	{
		//IL_012c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0131: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Unknown result type (might be due to invalid IL or missing references)
		//IL_0159: Unknown result type (might be due to invalid IL or missing references)
		object? value = VisRef.GetValue(p);
		VisEquipment val = (VisEquipment)((value is VisEquipment) ? value : null);
		if (!((Object)(object)val == (Object)null))
		{
			sHelmet = GetI(val, "m_helmetItem");
			sChest = GetI(val, "m_chestItem");
			sLegs = GetI(val, "m_legItem");
			sShoulder = GetI(val, "m_shoulderItem");
			sShoulderVar = GetI(val, "m_shoulderItemVariant");
			sShoulderQ = GetI(val, "m_shoulderItemQuality");
			sUtility = GetI(val, "m_utilityItem");
			sRight = GetI(val, "m_rightItem");
			sRightQ = GetI(val, "m_rightItemQuality");
			sLeft = GetI(val, "m_leftItem");
			sLeftVar = GetI(val, "m_leftItemVariant");
			sLeftQ = GetI(val, "m_leftItemQuality");
			sModel = GetI(val, "m_modelIndex");
			sHair = GetI(val, "m_hairItem");
			sBeard = GetI(val, "m_beardItem");
			FieldInfo fieldInfo = F("m_skinColor");
			if (fieldInfo != null)
			{
				sSkin = (Vector3)fieldInfo.GetValue(val);
			}
			FieldInfo fieldInfo2 = F("m_hairColor");
			if (fieldInfo2 != null)
			{
				sHairColor = (Vector3)fieldInfo2.GetValue(val);
			}
		}
	}

	private static void ApplyAppearance()
	{
		//IL_0014: 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)
		try
		{
			_vis.SetModel(sModel);
			_vis.SetSkinColor(sSkin);
			_vis.SetHairColor(sHairColor);
			_vis.SetHairItem(sHair);
			_vis.SetBeardItem(sBeard);
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Внешность не скопирована: " + ex.Message));
		}
	}

	private static void ApplyEquipment()
	{
		try
		{
			_vis.SetHelmetItem(SlotHash(0, sHelmet));
			_vis.SetChestItem(SlotHash(1, sChest));
			_vis.SetLegItem(SlotHash(2, sLegs));
			if ((Object)(object)Slots[3] != (Object)null)
			{
				_vis.SetShoulderItem(Hash(Slots[3]), 0, 1);
			}
			else
			{
				_vis.SetShoulderItem((!Naked[3]) ? sShoulder : 0, sShoulderVar, Mathf.Max(1, sShoulderQ));
			}
			_vis.SetUtilityItem(sUtility);
			if ((Object)(object)RightItem != (Object)null)
			{
				_vis.SetRightItem(Hash(RightItem), 1);
			}
			else
			{
				_vis.SetRightItem((!RightEmpty) ? sRight : 0, Mathf.Max(1, sRightQ));
			}
			if ((Object)(object)LeftItem != (Object)null)
			{
				_vis.SetLeftItem(Hash(LeftItem), 0, 1);
			}
			else
			{
				_vis.SetLeftItem((!LeftEmpty) ? sLeft : 0, sLeftVar, Mathf.Max(1, sLeftQ));
			}
			_vis.SetRightBackItem(0, 1);
			_vis.SetLeftBackItem(0, 0, 1);
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Не удалось надеть вещи на манекен: " + ex.Message));
		}
	}

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

	private static void SetLayer(GameObject go, int layer)
	{
		Transform[] componentsInChildren = go.GetComponentsInChildren<Transform>(true);
		foreach (Transform val in componentsInChildren)
		{
			((Component)val).gameObject.layer = layer;
		}
	}

	private static void RemoveFromStaticList(Type t, string field, object item)
	{
		if (item == null)
		{
			return;
		}
		try
		{
			FieldInfo fieldInfo = AccessTools.Field(t, field);
			IList list = ((!(fieldInfo != null)) ? null : (fieldInfo.GetValue(null) as IList));
			if (list != null)
			{
				while (list.Contains(item))
				{
					list.Remove(item);
				}
			}
		}
		catch
		{
		}
	}

	private static void RemoveFromInstances(Character c)
	{
		if ((Object)(object)c == (Object)null)
		{
			return;
		}
		try
		{
			PropertyInfo propertyInfo = AccessTools.Property(typeof(Character), "Instances");
			IList list = ((!(propertyInfo != null)) ? null : (propertyInfo.GetValue(null, null) as IList));
			if (list != null)
			{
				while (list.Contains(c))
				{
					list.Remove(c);
				}
			}
		}
		catch
		{
		}
	}
}
public static class Recolor
{
	public class Preset
	{
		public string Ru;

		public string En;

		public Color Swatch;

		public float Hue = -1f;

		public float SatMul = 1f;

		public float ValMul = 1f;

		public float ValAdd;

		public float MinSat = 0.55f;

		public float Lift;

		public string Name => Loc.T(Ru, En);
	}

	[HarmonyPatch(typeof(VisEquipment), "SetHelmetEquipped")]
	private static class PHelmet
	{
		private static void Postfix(VisEquipment __instance, bool __result, int hash)
		{
			if (__result)
			{
				Safe(delegate
				{
					ApplyInstances(__instance, "m_helmetItemInstance", hash);
				});
			}
		}
	}

	[HarmonyPatch(typeof(VisEquipment), "SetChestEquipped")]
	private static class PChest
	{
		private static void Postfix(VisEquipment __instance, bool __result, int hash)
		{
			if (__result)
			{
				Safe(delegate
				{
					ApplyInstances(__instance, "m_chestItemInstances", hash);
					ApplyBody(__instance, hash, "_ChestTex");
				});
			}
		}
	}

	[HarmonyPatch(typeof(VisEquipment), "SetLegEquipped")]
	private static class PLegs
	{
		private static void Postfix(VisEquipment __instance, bool __result, int hash)
		{
			if (__result)
			{
				Safe(delegate
				{
					ApplyInstances(__instance, "m_legItemInstances", hash);
					ApplyBody(__instance, hash, "_LegsTex");
				});
			}
		}
	}

	[HarmonyPatch(typeof(VisEquipment), "SetShoulderEquipped")]
	private static class PShoulder
	{
		private static void Postfix(VisEquipment __instance, bool __result, int hash)
		{
			if (__result)
			{
				Safe(delegate
				{
					ApplyInstances(__instance, "m_shoulderItemInstances", hash);
				});
			}
		}
	}

	[HarmonyPatch(typeof(VisEquipment), "SetUtilityEquipped")]
	private static class PUtility
	{
		private static void Postfix(VisEquipment __instance, bool __result, int hash)
		{
			if (__result)
			{
				Safe(delegate
				{
					ApplyInstances(__instance, "m_utilityItemInstances", hash);
				});
			}
		}
	}

	[HarmonyPatch(typeof(VisEquipment), "SetRightHandEquipped")]
	private static class PRight
	{
		private static void Postfix(VisEquipment __instance, bool __result, int hash)
		{
			if (__result)
			{
				Safe(delegate
				{
					ApplyInstances(__instance, "m_rightItemInstance", hash);
				});
			}
		}
	}

	[HarmonyPatch(typeof(VisEquipment), "SetLeftHandEquipped")]
	private static class PLeft
	{
		private static void Postfix(VisEquipment __instance, bool __result, int hash)
		{
			if (__result)
			{
				Safe(delegate
				{
					ApplyInstances(__instance, "m_leftItemInstance", hash);
				});
			}
		}
	}

	[HarmonyPatch(typeof(VisEquipment), "SetBackEquipped")]
	private static class PBack
	{
		private static void Postfix(VisEquipment __instance, bool __result, int leftItem, int rightItem)
		{
			if (__result)
			{
				Safe(delegate
				{
					ApplyInstances(__instance, "m_leftBackItemInstance", leftItem);
					ApplyInstances(__instance, "m_rightBackItemInstance", rightItem);
				});
			}
		}
	}

	public static readonly Preset[] Presets = new Preset[12]
	{
		new Preset
		{
			Ru = "Оригинал",
			En = "Original",
			Swatch = new Color(0.25f, 0.22f, 0.19f)
		},
		new Preset
		{
			Ru = "Красный",
			En = "Red",
			Swatch = new Color(0.78f, 0.13f, 0.13f),
			Hue = 0f,
			MinSat = 0.65f
		},
		new Preset
		{
			Ru = "Оранжевый",
			En = "Orange",
			Swatch = new Color(0.9f, 0.45f, 0.1f),
			Hue = 0.075f,
			MinSat = 0.78f,
			Lift = 0.3f
		},
		new Preset
		{
			Ru = "Жёлтый",
			En = "Yellow",
			Swatch = new Color(0.9f, 0.78f, 0.15f),
			Hue = 0.14f,
			MinSat = 0.78f,
			Lift = 0.42f
		},
		new Preset
		{
			Ru = "Зелёный",
			En = "Green",
			Swatch = new Color(0.2f, 0.62f, 0.22f),
			Hue = 0.33f
		},
		new Preset
		{
			Ru = "Бирюзовый",
			En = "Teal",
			Swatch = new Color(0.1f, 0.62f, 0.62f),
			Hue = 0.49f,
			MinSat = 0.55f,
			Lift = 0.08f
		},
		new Preset
		{
			Ru = "Синий",
			En = "Blue",
			Swatch = new Color(0.15f, 0.3f, 0.82f),
			Hue = 0.62f
		},
		new Preset
		{
			Ru = "Фиолетовый",
			En = "Purple",
			Swatch = new Color(0.5f, 0.2f, 0.78f),
			Hue = 0.76f
		},
		new Preset
		{
			Ru = "Розовый",
			En = "Pink",
			Swatch = new Color(0.9f, 0.35f, 0.62f),
			Hue = 0.91f,
			MinSat = 0.5f,
			Lift = 0.22f
		},
		new Preset
		{
			Ru = "Чёрный",
			En = "Black",
			Swatch = new Color(0.08f, 0.08f, 0.09f),
			SatMul = 0.12f,
			ValMul = 0.32f
		},
		new Preset
		{
			Ru = "Белый",
			En = "White",
			Swatch = new Color(0.92f, 0.92f, 0.9f),
			SatMul = 0.08f,
			ValMul = 0.45f,
			ValAdd = 0.55f
		},
		new Preset
		{
			Ru = "Серый",
			En = "Grey",
			Swatch = new Color(0.5f, 0.5f, 0.52f),
			SatMul = 0.06f
		}
	};

	public const string ZdoKey = "vw_recolors";

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

	private static bool _loaded;

	private static string _rulesString = string.Empty;

	private static readonly Dictionary<string, float> HueCache = new Dictionary<string, float>();

	private static readonly Dictionary<string, Texture2D> TexCache = new Dictionary<string, Texture2D>();

	private static readonly Dictionary<string, Material> MatCache = new Dictionary<string, Material>();

	private static readonly Dictionary<string, Sprite[]> OrigIcons = new Dictionary<string, Sprite[]>();

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

	private static readonly Dictionary<VisEquipment, string> SeenRemote = new Dictionary<VisEquipment, string>();

	private static readonly FieldInfo VisRef = AccessTools.Field(typeof(Humanoid), "m_visEquipment");

	private static readonly FieldInfo NviewRef = AccessTools.Field(typeof(VisEquipment), "m_nview");

	private static readonly FieldInfo BodyRef = AccessTools.Field(typeof(VisEquipment), "m_bodyModel");

	private static float _tick;

	private static readonly string[] HashFields = new string[9] { "m_currentLeftItemHash", "m_currentRightItemHash", "m_currentChestItemHash", "m_currentLegItemHash", "m_currentHelmetItemHash", "m_currentShoulderItemHash", "m_currentUtilityItemHash", "m_currentLeftBackItemHash", "m_currentRightBackItemHash" };

	private static FieldInfo[] _hashFields;

	private static readonly string[] ColorProps = new string[3] { "_Color", "_TintColor", "_BaseColor" };

	private static string FilePath => Path.Combine(Paths.ConfigPath, "umorise.valhallawardrobe.recolors.txt");

	public static int Get(string prefab)
	{
		EnsureLoaded();
		int value;
		return Rules.TryGetValue(prefab, out value) ? value : 0;
	}

	private static void EnsureLoaded()
	{
		if (_loaded)
		{
			return;
		}
		_loaded = true;
		try
		{
			if (File.Exists(FilePath))
			{
				string[] array = File.ReadAllLines(FilePath);
				foreach (string text in array)
				{
					string[] array2 = text.Split('\t');
					if (array2.Length >= 2 && int.TryParse(array2[1], out var result) && result > 0 && result < Presets.Length)
					{
						Rules[array2[0]] = result;
					}
				}
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Recolors not loaded: " + ex.Message));
		}
		_rulesString = Serialize(Rules);
	}

	private static void Save()
	{
		try
		{
			File.WriteAllLines(FilePath, Rules.Select((KeyValuePair<string, int> kv) => kv.Key + "\t" + kv.Value).ToArray());
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Recolors not saved: " + ex.Message));
		}
	}

	private static string Serialize(Dictionary<string, int> r)
	{
		return string.Join(";", (from kv in r
			orderby kv.Key
			select kv.Key + ":" + kv.Value).ToArray());
	}

	private static Dictionary<string, int> Parse(string s)
	{
		if (ParsedCache.TryGetValue(s, out var value))
		{
			return value;
		}
		value = new Dictionary<string, int>();
		string[] array = s.Split(';');
		foreach (string text in array)
		{
			int num = text.LastIndexOf(':');
			if (num > 0 && int.TryParse(text.Substring(num + 1), out var result) && result > 0 && result < Presets.Length)
			{
				value[text.Substring(0, num)] = result;
			}
		}
		if (ParsedCache.Count > 200)
		{
			ParsedCache.Clear();
		}
		ParsedCache[s] = value;
		return value;
	}

	public static void Set(IEnumerable<ItemDrop> items, int preset)
	{
		EnsureLoaded();
		foreach (ItemDrop item in items)
		{
			if (!((Object)(object)item == (Object)null))
			{
				string name = ((Object)((Component)item).gameObject).name;
				if (preset <= 0)
				{
					Rules.Remove(name);
				}
				else
				{
					Rules[name] = preset;
				}
				ApplyIcon(item, preset);
			}
		}
		_rulesString = Serialize(Rules);
		Save();
		Publish();
		ForceRefresh(LocalVis());
		ForceRefresh(Preview.Vis);
	}

	public static void ApplyAll()
	{
		EnsureLoaded();
		ObjectDB instance = ObjectDB.instance;
		if ((Object)(object)instance == (Object)null)
		{
			return;
		}
		foreach (KeyValuePair<string, int> rule in Rules)
		{
			GameObject itemPrefab = instance.GetItemPrefab(rule.Key);
			ItemDrop val = ((!((Object)(object)itemPrefab != (Object)null)) ? null : itemPrefab.GetComponent<ItemDrop>());
			if ((Object)(object)val != (Object)null)
			{
				ApplyIcon(val, rule.Value);
			}
		}
		Publish();
		ForceRefresh(LocalVis());
	}

	private static VisEquipment LocalVis()
	{
		Player localPlayer = Player.m_localPlayer;
		return (VisEquipment)((!((Object)(object)localPlayer != (Object)null)) ? null : /*isinst with value type is only supported in some contexts*/);
	}

	private static ZDO ZdoOf(VisEquipment v)
	{
		object? value = NviewRef.GetValue(v);
		ZNetView val = (ZNetView)((value is ZNetView) ? value : null);
		return (!((Object)(object)val != (Object)null) || !val.IsValid()) ? null : val.GetZDO();
	}

	private static void Publish()
	{
		VisEquipment val = LocalVis();
		if (!((Object)(object)val == (Object)null))
		{
			ZDO val2 = ZdoOf(val);
			if (val2 != null && val2.GetString("vw_recolors", string.Empty) != _rulesString)
			{
				val2.Set("vw_recolors", _rulesString);
			}
		}
	}

	private static Dictionary<string, int> RulesFor(VisEquipment v)
	{
		if ((Object)(object)v == (Object)null)
		{
			return null;
		}
		if ((Object)(object)v == (Object)(object)LocalVis() || (Object)(object)v == (Object)(object)Preview.Vis)
		{
			EnsureLoaded();
			return Rules;
		}
		ZDO val = ZdoOf(v);
		if (val == null)
		{
			return null;
		}
		string text = val.GetString("vw_recolors", string.Empty);
		return (!string.IsNullOrEmpty(text)) ? Parse(text) : null;
	}

	public static void Tick()
	{
		if (Time.unscaledTime - _tick < 1f)
		{
			return;
		}
		_tick = Time.unscaledTime;
		try
		{
			EnsureLoaded();
			Publish();
			VisEquipment val = LocalVis();
			IList list = InstancesList();
			if (list == null)
			{
				return;
			}
			HashSet<VisEquipment> alive = new HashSet<VisEquipment>();
			foreach (object item in list)
			{
				VisEquipment val2 = (VisEquipment)((item is VisEquipment) ? item : null);
				if ((Object)(object)val2 == (Object)null || (Object)(object)val2 == (Object)(object)val || (Object)(object)val2 == (Object)(object)Preview.Vis || !val2.m_isPlayer)
				{
					continue;
				}
				ZDO val3 = ZdoOf(val2);
				if (val3 == null)
				{
					continue;
				}
				alive.Add(val2);
				string text = val3.GetString("vw_recolors", string.Empty);
				if (!SeenRemote.TryGetValue(val2, out var value))
				{
					SeenRemote[val2] = text;
					if (text.Length > 0)
					{
						ForceRefresh(val2);
					}
				}
				else if (value != text)
				{
					SeenRemote[val2] = text;
					ForceRefresh(val2);
				}
			}
			foreach (VisEquipment item2 in SeenRemote.Keys.Where((VisEquipment k) => (Object)(object)k == (Object)null || !alive.Contains(k)).ToList())
			{
				SeenRemote.Remove(item2);
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogDebug((object)("Recolor tick: " + ex.Message));
		}
	}

	private static IList InstancesList()
	{
		PropertyInfo propertyInfo = AccessTools.Property(typeof(VisEquipment), "Instances");
		return (!(propertyInfo != null)) ? null : (propertyInfo.GetValue(null, null) as IList);
	}

	public static void ForceRefresh(VisEquipment v)
	{
		if ((Object)(object)v == (Object)null)
		{
			return;
		}
		if (_hashFields == null)
		{
			_hashFields = (from n in HashFields
				select AccessTools.Field(typeof(VisEquipment), n) into f
				where f != null
				select f).ToArray();
		}
		FieldInfo[] hashFields = _hashFields;
		foreach (FieldInfo fieldInfo in hashFields)
		{
			fieldInfo.SetValue(v, -1);
		}
	}

	private static ItemDrop ItemOf(int hash)
	{
		if (hash == 0 || (Object)(object)ObjectDB.instance == (Object)null)
		{
			return null;
		}
		GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(hash);
		return (!((Object)(object)itemPrefab != (Object)null)) ? null : itemPrefab.GetComponent<ItemDrop>();
	}

	private static int PresetFor(VisEquipment v, ItemDrop d)
	{
		if ((Object)(object)d == (Object)null)
		{
			return 0;
		}
		Dictionary<string, int> dictionary = RulesFor(v);
		int value;
		return (dictionary != null && dictionary.TryGetValue(((Object)((Component)d).gameObject).name, out value)) ? value : 0;
	}

	private static void ApplyInstance(VisEquipment v, GameObject inst, int hash)
	{
		if ((Object)(object)inst == (Object)null)
		{
			return;
		}
		ItemDrop d = ItemOf(hash);
		int num = PresetFor(v, d);
		if (num <= 0)
		{
			return;
		}
		float hue = HueOf(d);
		Preset p = Presets[num];
		Renderer[] componentsInChildren = inst.GetComponentsInChildren<Renderer>(true);
		foreach (Renderer val in componentsInChildren)
		{
			if ((Object)(object)val == (Object)null || ((object)val).GetType().Name == "ParticleSystemRenderer")
			{
				continue;
			}
			Material[] sharedMaterials = val.sharedMaterials;
			bool flag = false;
			for (int j = 0; j < sharedMaterials.Length; j++)
			{
				Material val2 = RecolorMaterialCached(sharedMaterials[j], hue, p, num);
				if ((Object)(object)val2 != (Object)(object)sharedMaterials[j])
				{
					sharedMaterials[j] = val2;
					flag = true;
				}
			}
			if (flag)
			{
				val.sharedMaterials = sharedMaterials;
			}
		}
	}

	private static void ApplyInstances(VisEquipment v, string field, int hash)
	{
		FieldInfo fieldInfo = AccessTools.Field(typeof(VisEquipment), field);
		object obj = ((!(fieldInfo != null)) ? null : fieldInfo.GetValue(v));
		if (obj is List<GameObject> list)
		{
			{
				foreach (GameObject item in list)
				{
					ApplyInstance(v, item, hash);
				}
				return;
			}
		}
		ApplyInstance(v, (GameObject)((obj is GameObject) ? obj : null), hash);
	}

	private static void ApplyBody(VisEquipment v, int hash, string prop)
	{
		ItemDrop val = ItemOf(hash);
		int num = PresetFor(v, val);
		if (num <= 0)
		{
			return;
		}
		Material armorMaterial = val.m_itemData.m_shared.m_armorMaterial;
		if ((Object)(object)armorMaterial == (Object)null || !armorMaterial.HasProperty(prop))
		{
			return;
		}
		Texture texture = armorMaterial.GetTexture(prop);
		object? value = BodyRef.GetValue(v);
		SkinnedMeshRenderer val2 = (SkinnedMeshRenderer)((value is SkinnedMeshRenderer) ? value : null);
		if ((Object)(object)texture == (Object)null || (Object)(object)val2 == (Object)null)
		{
			return;
		}
		try
		{
			((Renderer)val2).material.SetTexture(prop, RecolorTexture(texture, HueOf(val), Presets[num], num));
		}
		catch (Exception ex)
		{
			Plugin.Log.LogDebug((object)("Recolor body: " + ex.Message));
		}
	}

	private static Material RecolorMaterialCached(Material m, float hue, Preset p, int preset)
	{
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Expected O, but got Unknown
		if ((Object)(object)m == (Object)null)
		{
			return null;
		}
		string key = ((Object)m).GetInstanceID() + ":" + preset + ":" + hue.ToString("0.000");
		if (MatCache.TryGetValue(key, out var value) && (Object)(object)value != (Object)null)
		{
			return value;
		}
		Material val = new Material(m);
		bool flag = RecolorTints(val, hue, p);
		if (m.HasProperty("_MainTex") && (Object)(object)m.GetTexture("_MainTex") != (Object)null)
		{
			val.SetTexture("_MainTex", RecolorTexture(m.GetTexture("_MainTex"), hue, p, preset));
			flag = true;
		}
		if (!flag)
		{
			Object.Destroy((Object)(object)val);
			val = m;
		}
		MatCache[key] = val;
		return val;
	}

	private static float HueOf(ItemDrop d)
	{
		//IL_0115: Unknown result type (might be due to invalid IL or missing references)
		string name = ((Object)((Component)d).gameObject).name;
		if (HueCache.TryGetValue(name, out var value))
		{
			return value;
		}
		List<Texture> list = new List<Texture>();
		List<Color> list2 = new List<Color>();
		Renderer[] componentsInChildren = ((Component)d).GetComponentsInChildren<Renderer>(true);
		foreach (Renderer val in componentsInChildren)
		{
			if ((Object)(object)val == (Object)null || ((object)val).GetType().Name == "ParticleSystemRenderer")
			{
				continue;
			}
			Material[] sharedMaterials = val.sharedMaterials;
			foreach (Material val2 in sharedMaterials)
			{
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				if (val2.HasProperty("_MainTex") && (Object)(object)val2.GetTexture("_MainTex") != (Object)null && !list.Contains(val2.GetTexture("_MainTex")))
				{
					list.Add(val2.GetTexture("_MainTex"));
				}
				string[] colorProps = ColorProps;
				foreach (string text in colorProps)
				{
					if (val2.HasProperty(text))
					{
						list2.Add(val2.GetColor(text));
					}
				}
			}
		}
		Material armorMaterial = d.m_itemData.m_shared.m_armorMaterial;
		if ((Object)(object)armorMaterial != (Object)null)
		{
			string[] array = new string[2] { "_ChestTex", "_LegsTex" };
			foreach (string text2 in array)
			{
				if (armorMaterial.HasProperty(text2) && (Object)(object)armorMaterial.GetTexture(text2) != (Object)null && !list.Contains(armorMaterial.GetTexture(text2)))
				{
					list.Add(armorMaterial.GetTexture(text2));
				}
			}
		}
		try
		{
			value = DominantHue(list, list2);
		}
		catch
		{
			value = -1f;
		}
		HueCache[name] = value;
		return value;
	}

	private static void ApplyIcon(ItemDrop d, int preset)
	{
		SharedData shared = d.m_itemData.m_shared;
		string name = ((Object)((Component)d).gameObject).name;
		if (!OrigIcons.TryGetValue(name, out var value))
		{
			value = ((shared.m_icons == null) ? null : ((Sprite[])shared.m_icons.Clone()));
			OrigIcons[name] = value;
		}
		if (value == null)
		{
			return;
		}
		if (preset <= 0)
		{
			shared.m_icons = (Sprite[])value.Clone();
			return;
		}
		try
		{
			float hue = HueOf(d);
			Sprite[] array = (Sprite[])value.Clone();
			for (int i = 0; i < array.Length; i++)
			{
				if ((Object)(object)array[i] != (Object)null)
				{
					array[i] = RecolorSprite(array[i], hue, Presets[preset], preset);
				}
			}
			shared.m_icons = array;
		}
		catch (Exception ex)
		{
			Plugin.Log.LogDebug((object)("Recolor icon: " + ex.Message));
		}
	}

	private static void Safe(Action a)
	{
		try
		{
			a();
		}
		catch (Exception ex)
		{
			Plugin.Log.LogDebug((object)("Recolor apply: " + ex.Message));
		}
	}

	private static Color32[] ReadPixels(Texture src, int x, int y, int w, int h, out int outW, out int outH)
	{
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Expected O, but got Unknown
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		RenderTexture temporary = RenderTexture.GetTemporary(src.width, src.height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)2);
		RenderTexture active = RenderTexture.active;
		Graphics.Blit(src, temporary);
		RenderTexture.active = temporary;
		Texture2D val = new Texture2D(w, h, (TextureFormat)4, false, false);
		val.ReadPixels(new Rect((float)x, (float)y, (float)w, (float)h), 0, 0);
		val.Apply();
		RenderTexture.active = active;
		RenderTexture.ReleaseTemporary(temporary);
		Color32[] pixels = val.GetPixels32();
		Object.Destroy((Object)(object)val);
		outW = w;
		outH = h;
		return pixels;
	}

	private static float DominantHue(List<Texture> textures, List<Color> tints)
	{
		//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_011d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0122: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: 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_0089: Unknown result type (might be due to invalid IL or missing references)
		float[] array = new float[36];
		float num = 0f;
		float num3 = default(float);
		float num4 = default(float);
		float num5 = default(float);
		foreach (Texture texture in textures)
		{
			Color32[] array2;
			try
			{
				array2 = ReadPixels(texture, 0, 0, texture.width, texture.height, out var _, out var _);
			}
			catch
			{
				continue;
			}
			int num2 = Mathf.Max(1, array2.Length / 60000);
			for (int i = 0; i < array2.Length; i += num2)
			{
				Color32 val = array2[i];
				if (val.a >= 128)
				{
					Color.RGBToHSV(Color32.op_Implicit(val), ref num3, ref num4, ref num5);
					if (!(num4 < 0.22f) && !(num5 < 0.12f))
					{
						array[Mathf.Min(35, (int)(num3 * 36f))] += num4 * num5;
						num += num4 * num5;
					}
				}
			}
		}
		float num6 = default(float);
		float num7 = default(float);
		float num8 = default(float);
		foreach (Color tint in tints)
		{
			Color.RGBToHSV(tint, ref num6, ref num7, ref num8);
			if (!(num7 < 0.2f) && !(num8 < 0.1f))
			{
				array[Mathf.Min(35, (int)(num6 * 36f))] += Mathf.Max(num * 0.35f, 1f) * num7;
			}
		}
		int num9 = -1;
		float num10 = 0f;
		for (int j = 0; j < 36; j++)
		{
			float num11 = array[j] + 0.6f * (array[(j + 1) % 36] + array[(j + 36 - 1) % 36]);
			if (num11 > num10)
			{
				num10 = num11;
				num9 = j;
			}
		}
		return (num9 >= 0) ? (((float)num9 + 0.5f) / 36f) : (-1f);
	}

	private static float HueDist(float a, float b)
	{
		float num = Mathf.Abs(a - b);
		return Mathf.Min(num, 1f - num);
	}

	private static void Transform(float h, float s, float v, float hue, Preset p, out float nh, out float ns, out float nv)
	{
		nh = h;
		ns = s;
		nv = v;
		if (p.Hue >= 0f)
		{
			float num = ((!(hue >= 0f)) ? 0f : (h - hue));
			if (num > 0.5f)
			{
				num -= 1f;
			}
			if (num < -0.5f)
			{
				num += 1f;
			}
			nh = Mathf.Repeat(p.Hue + num * 0.4f, 1f);
			ns = Mathf.Clamp01(p.MinSat + s * (1f - p.MinSat));
			nv = Mathf.Clamp01(v + (1f - v) * p.Lift);
		}
		else
		{
			ns = s * p.SatMul;
			nv = Mathf.Clamp01(v * p.ValMul + p.ValAdd);
		}
	}

	private static bool RecolorTints(Material m, float hue, Preset p)
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: 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_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		bool result = false;
		string[] colorProps = ColorProps;
		float num = default(float);
		float num2 = default(float);
		float v = default(float);
		foreach (string text in colorProps)
		{
			if (m.HasProperty(text))
			{
				Color color = m.GetColor(text);
				Color.RGBToHSV(color, ref num, ref num2, ref v);
				if (!(num2 < 0.2f) && (!(hue >= 0f) || !(HueDist(num, hue) > 0.12f)))
				{
					Transform(num, num2, v, hue, p, out var nh, out var ns, out var nv);
					Color val = Color.HSVToRGB(nh, ns, nv);
					val.a = color.a;
					m.SetColor(text, val);
					result = true;
				}
			}
		}
		return result;
	}

	private static void RecolorPixels(Color32[] px, float hue, Preset p)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: 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_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: 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_0133: Unknown result type (might be due to invalid IL or missing references)
		//IL_0138: Unknown result type (might be due to invalid IL or missing references)
		float num = default(float);
		float num2 = default(float);
		float v = default(float);
		for (int i = 0; i < px.Length; i++)
		{
			Color32 val = px[i];
			Color.RGBToHSV(Color32.op_Implicit(val), ref num, ref num2, ref v);
			if (num2 < 0.08f)
			{
				continue;
			}
			float num3;
			if (hue < 0f)
			{
				num3 = 1f;
			}
			else
			{
				float num4 = HueDist(num, hue);
				if (num4 >= 0.12f)
				{
					continue;
				}
				num3 = ((!(num4 <= 0.07f)) ? (1f - (num4 - 0.07f) / 0.049999997f) : 1f);
			}
			num3 *= Mathf.Clamp01((num2 - 0.08f) / 0.1f);
			if (!(num3 <= 0f))
			{
				Transform(num, num2, v, hue, p, out var nh, out var ns, out var nv);
				Color32 val2 = Color32.op_Implicit(Color.HSVToRGB(nh, ns, nv));
				ref Color32 reference = ref px[i];
				reference = new Color32((byte)Mathf.Lerp((float)(int)val.r, (float)(int)val2.r, num3), (byte)Mathf.Lerp((float)(int)val.g, (float)(int)val2.g, num3), (byte)Mathf.Lerp((float)(int)val.b, (float)(int)val2.b, num3), val.a);
			}
		}
	}

	private static Texture RecolorTexture(Texture src, float hue, Preset p, int preset)
	{
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Expected O, but got Unknown
		//IL_00ab: 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)
		string key = ((Object)src).GetInstanceID() + ":" + preset + ":" + hue.ToString("0.000");
		if (TexCache.TryGetValue(key, out var value) && (Object)(object)value != (Object)null)
		{
			return (Texture)(object)value;
		}
		int outW;
		int outH;
		Color32[] array = ReadPixels(src, 0, 0, src.width, src.height, out outW, out outH);
		RecolorPixels(array, hue, p);
		Texture2D val = new Texture2D(outW, outH, (TextureFormat)4, true, false);
		((Object)val).name = ((Object)src).name + "_recolor";
		((Texture)val).wrapMode = src.wrapMode;
		((Texture)val).filterMode = src.filterMode;
		((Texture)val).anisoLevel = src.anisoLevel;
		Texture2D val2 = val;
		val2.SetPixels32(array);
		val2.Apply(true, true);
		TexCache[key] = val2;
		return (Texture)(object)val2;
	}

	private static Sprite RecolorSprite(Sprite s, float hue, Preset p, int preset)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Expected O, but got Unknown
		//IL_0087: 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)
		Rect textureRect = s.textureRect;
		int outW;
		int outH;
		Color32[] array = ReadPixels((Texture)(object)s.texture, (int)((Rect)(ref textureRect)).x, (int)((Rect)(ref textureRect)).y, (int)((Rect)(ref textureRect)).width, (int)((Rect)(ref textureRect)).height, out outW, out outH);
		RecolorPixels(array, hue, p);
		Texture2D val = new Texture2D(outW, outH, (TextureFormat)4, false, false);
		((Object)val).name = ((Object)s).name + "_recolor";
		Texture2D val2 = val;
		val2.SetPixels32(array);
		val2.Apply(false, true);
		return Sprite.Create(val2, new Rect(0f, 0f, (float)outW, (float)outH), new Vector2(0.5f, 0.5f), s.pixelsPerUnit);
	}
}
public class Window
{
	private class Need
	{
		public ItemDrop Item;

		public int Amount;
	}

	public bool Open;

	public int ClosedFrame = -1;

	private int _tab;

	private int _role = -1;

	private int _modIdx = -1;

	private int _catIdx = -1;

	private int _biomeIdx = -1;

	private bool _biomeAndEarlier;

	private bool _showOutfit;

	private string _outfitName = string.Empty;

	private int _outfitIdx = -1;

	private int _slot = -1;

	private string _search = string.Empty;

	private Vector2 _listScroll;

	private Vector2 _detailScroll;

	private Entry _selArmor;

	private Entry _selWeapon;

	private int _quality = 1;

	private readonly HashSet<string> _expanded = new HashSet<string>();

	private List<Entry> _filtered = new List<Entry>();

	private string _filt