Decompiled source of CraftingSort v0.2.2

CraftingSort.dll

Decompiled 12 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace CraftingSort
{
	[BepInPlugin("com.skyowner.craftingsort", "CraftingSort", "0.2.2")]
	[BepInDependency("seneaL.valheim.ui", "1.1.6")]
	public sealed class Plugin : BaseUnityPlugin
	{
		private sealed class ViewState
		{
			public readonly Dictionary<object, int> Original = new Dictionary<object, int>();

			public bool Rebuilding;

			public RectTransform Button;

			public TextMeshProUGUI Label;

			public int LabelMode = -1;

			public bool LabelRussian;
		}

		private sealed class Entry
		{
			public object Row;

			public int Rank;

			public int Tier;

			public string Material;

			public string Name;
		}

		private static ConfigEntry<int> Mode;

		private static readonly ConditionalWeakTable<object, ViewState> States = new ConditionalWeakTable<object, ViewState>();

		private static Type View;

		private static WeakReference<object> CurrentView;

		private Harmony harmony;

		private static object Field(object obj, string name)
		{
			return AccessTools.Field(obj.GetType(), name).GetValue(obj);
		}

		private void Awake()
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a0: Expected O, but got Unknown
			if (!Chainloader.PluginInfos.TryGetValue("seneaL.valheim.ui", out var value) || (value.Metadata.Version != new Version(1, 1, 6) && value.Metadata.Version != new Version(1, 1, 7)))
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"CraftingSort 0.2.2 requires SeneaL UI 1.1.6 or 1.1.7; addon disabled.");
				return;
			}
			Mode = ((BaseUnityPlugin)this).Config.Bind<int>("Sorting", "DescendingOrderMode", 2, new ConfigDescription("0: SeneaL order, 1: materials, 2: unified list with tier headers (default).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 2), Array.Empty<object>()));
			Mode.Value = Mathf.Clamp(Mode.Value, 0, 2);
			View = AccessTools.TypeByName("SeneaLUI.Inv.CraftView");
			if (View == null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"SeneaL CraftView missing; addon disabled.");
				return;
			}
			string[] array = new string[5] { "Rebuild", "Filter", "Tick", "LayoutFrame", "FillHead" };
			foreach (string text in array)
			{
				if (AccessTools.Method(View, text, (Type[])null, (Type[])null) == null)
				{
					throw new MissingMethodException(View.FullName, text);
				}
			}
			array = new string[10] { "_rows", "_panel", "_tabs", "_tabTexts", "_filtered", "_listContent", "_listView", "_listW", "_first", "_selIndex" };
			foreach (string text2 in array)
			{
				if (AccessTools.Field(View, text2) == null)
				{
					throw new MissingFieldException(View.FullName, text2);
				}
			}
			Type type = AccessTools.Inner(View, "Row");
			Type type2 = AccessTools.Inner(View, "RowUi");
			array = new string[5] { "Recipe", "Item", "Name", "Visible", "Index" };
			foreach (string text3 in array)
			{
				if (type == null || AccessTools.Field(type, text3) == null)
				{
					throw new MissingFieldException("SeneaL CraftView.Row", text3);
				}
			}
			if (type2 == null || AccessTools.Field(type2, "Head") == null)
			{
				throw new MissingFieldException("SeneaL CraftView.RowUi", "Head");
			}
			harmony = new Harmony("com.skyowner.craftingsort");
			try
			{
				Patch(AccessTools.Constructor(View, new Type[2]
				{
					typeof(InventoryGui),
					typeof(RectTransform)
				}, false), null, "Created");
				Patch(AccessTools.Method(View, "Rebuild", (Type[])null, (Type[])null), "Rebuilding", null);
				Patch(AccessTools.Method(View, "Filter", (Type[])null, (Type[])null), "Sort", "GroupTiers");
				Patch(AccessTools.Method(View, "FillHead", (Type[])null, (Type[])null), "HeaderPrefix", "HeaderPostfix");
				Patch(AccessTools.Method(View, "Tick", (Type[])null, (Type[])null), null, "UpdateControl");
				Patch(AccessTools.Method(View, "LayoutFrame", (Type[])null, (Type[])null), null, "UpdateControl");
				if (value.Metadata.Version == new Version(1, 1, 6))
				{
					Patch(AccessTools.Method(typeof(InventoryGui), "UpdateRecipeGamepadInput", (Type[])null, (Type[])null), "Gamepad", null);
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Crafting material and tier sorting enabled for SeneaL UI.");
			}
			catch
			{
				harmony.UnpatchSelf();
				throw;
			}
		}

		private void Patch(MethodBase target, string prefix, string postfix)
		{
			//IL_0016: 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)
			harmony.Patch(target, (prefix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(typeof(Plugin), prefix, (Type[])null), (postfix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(typeof(Plugin), postfix, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private void OnDestroy()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}

		private static void Rebuilding(object __instance)
		{
			States.GetOrCreateValue(__instance).Rebuilding = true;
		}

		private static void Created(object __instance)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Expected O, but got Unknown
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Expected O, but got Unknown
			CurrentView = new WeakReference<object>(__instance);
			ViewState orCreateValue = States.GetOrCreateValue(__instance);
			RectTransform val = (RectTransform)Field(__instance, "_panel");
			GameObject val2 = new GameObject("CraftingSort", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Button)
			});
			RectTransform val3 = (RectTransform)val2.transform;
			((Transform)val3).SetParent((Transform)(object)val, false);
			Vector2 val4 = default(Vector2);
			((Vector2)(ref val4))..ctor(1f, 1f);
			val3.pivot = val4;
			Vector2 anchorMin = (val3.anchorMax = val4);
			val3.anchorMin = anchorMin;
			val3.sizeDelta = new Vector2(190f, 30f);
			((Graphic)val2.GetComponent<Image>()).color = new Color(0.17f, 0.15f, 0.12f, 0.95f);
			((Selectable)val2.GetComponent<Button>()).targetGraphic = (Graphic)(object)val2.GetComponent<Image>();
			GameObject val6 = new GameObject("Label", new Type[2]
			{
				typeof(RectTransform),
				typeof(TextMeshProUGUI)
			});
			val6.transform.SetParent((Transform)(object)val3, false);
			TextMeshProUGUI component = val6.GetComponent<TextMeshProUGUI>();
			TMP_Text val7 = ((TMP_Text[])Field(__instance, "_tabTexts"))[0];
			((TMP_Text)component).font = val7.font;
			((TMP_Text)component).fontSharedMaterial = val7.fontSharedMaterial;
			((TMP_Text)component).fontSize = 14f;
			((TMP_Text)component).alignment = (TextAlignmentOptions)514;
			((Graphic)component).color = new Color(0.94f, 0.8f, 0.5f);
			((Graphic)component).raycastTarget = false;
			((TMP_Text)component).rectTransform.anchorMin = Vector2.zero;
			((TMP_Text)component).rectTransform.anchorMax = Vector2.one;
			RectTransform rectTransform = ((TMP_Text)component).rectTransform;
			anchorMin = (((TMP_Text)component).rectTransform.offsetMax = Vector2.zero);
			rectTransform.offsetMin = anchorMin;
			orCreateValue.Button = val3;
			orCreateValue.Label = component;
			((UnityEvent)val2.GetComponent<Button>().onClick).AddListener((UnityAction)delegate
			{
				Mode.Value = (Mode.Value + 1) % 3;
				AccessTools.Method(View, "Filter", (Type[])null, (Type[])null).Invoke(__instance, null);
				UpdateControl(__instance);
			});
			UpdateControl(__instance);
		}

		private static void UpdateControl(object __instance)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			ViewState orCreateValue = States.GetOrCreateValue(__instance);
			if (Object.op_Implicit((Object)(object)orCreateValue.Button))
			{
				RectTransform[] array = (RectTransform[])Field(__instance, "_tabs");
				orCreateValue.Button.anchoredPosition = new Vector2(-22f, array[0].anchoredPosition.y - 3f);
				bool flag = Localization.instance != null && Localization.instance.GetSelectedLanguage() == "Russian";
				if (orCreateValue.LabelMode != Mode.Value || orCreateValue.LabelRussian != flag)
				{
					string[] array2 = ((!flag) ? new string[3] { "Order: SeneaL", "Order: materials", "Order: tiers" } : new string[3] { "Порядок: SeneaL", "Порядок: материалы", "Порядок: тиры" });
					((TMP_Text)orCreateValue.Label).text = array2[Mode.Value];
					orCreateValue.LabelMode = Mode.Value;
					orCreateValue.LabelRussian = flag;
				}
			}
		}

		private static int RecipeTier(object row)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			Recipe val = (Recipe)Field(row, "Recipe");
			if ((Object)(object)val == (Object)null)
			{
				ItemData val2 = (ItemData)Field(row, "Item");
				if ((Object)(object)val2?.m_dropPrefab != (Object)null && (Object)(object)ObjectDB.instance != (Object)null)
				{
					val = ObjectDB.instance.GetRecipe(val2);
				}
			}
			if (!((Object)(object)val == (Object)null))
			{
				return SortKeys.Tier(from r in val.m_resources
					where r != null && (Object)(object)r.m_resItem != (Object)null && (r.m_amount > 0 || r.m_amountPerLevel > 0)
					select ((Object)((Component)r.m_resItem).gameObject).name.Replace("(Clone)", ""));
			}
			return 0;
		}

		private static void GroupTiers(object __instance)
		{
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Expected O, but got Unknown
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			if (Mode.Value != 2)
			{
				return;
			}
			IList list = (IList)Field(__instance, "_rows");
			List<int> list2 = (List<int>)Field(__instance, "_filtered");
			list2.Clear();
			List<(int, int)> list3 = new List<(int, int)>();
			for (int i = 0; i < list.Count; i++)
			{
				if ((bool)Field(list[i], "Visible"))
				{
					list3.Add((i, RecipeTier(list[i])));
				}
			}
			list2.AddRange(TierList.Build(list3));
			RectTransform val = (RectTransform)Field(__instance, "_listContent");
			val.sizeDelta = new Vector2((float)Field(__instance, "_listW"), Mathf.Max(0f, (float)list2.Count * 48f - 4f));
			float num = Mathf.Max(0f, val.sizeDelta.y - ((RectTransform)Field(__instance, "_listView")).sizeDelta.y);
			val.anchoredPosition = new Vector2(val.anchoredPosition.x, Mathf.Clamp(val.anchoredPosition.y, 0f, num));
			AccessTools.Field(View, "_first").SetValue(__instance, -1);
			AccessTools.Field(View, "_selIndex").SetValue(__instance, -2);
		}

		private static bool Gamepad(InventoryGui __instance)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			if (Mode.Value != 2 || CurrentView == null || !CurrentView.TryGetTarget(out var target) || !((Component)(RectTransform)Field(target, "_panel")).gameObject.activeInHierarchy)
			{
				return true;
			}
			int num = ((ZInput.GetButtonDown("JoyLStickDown") || ZInput.GetButtonDown("JoyDPadDown")) ? 1 : ((ZInput.GetButtonDown("JoyLStickUp") || ZInput.GetButtonDown("JoyDPadUp")) ? (-1) : 0));
			if (num == 0)
			{
				return false;
			}
			IList rows = (IList)Field(target, "_rows");
			List<int> list = (from i in (List<int>)Field(target, "_filtered")
				where i >= 0
				select (int)Field(rows[i], "Index") into i
				where i >= 0
				select i).ToList();
			if (list.Count == 0)
			{
				return false;
			}
			int item = (int)AccessTools.Method(typeof(InventoryGui), "GetSelectedRecipeIndex", (Type[])null, (Type[])null).Invoke(__instance, new object[1] { false });
			int num2 = list.IndexOf(item);
			int index = ((num2 >= 0) ? Mathf.Clamp(num2 + num, 0, list.Count - 1) : ((num <= 0) ? (list.Count - 1) : 0));
			AccessTools.Method(typeof(InventoryGui), "SetRecipe", (Type[])null, (Type[])null).Invoke(__instance, new object[2]
			{
				list[index],
				false
			});
			return false;
		}

		private static void HeaderPrefix(ref int group, out int __state)
		{
			__state = group;
			if (group >= 100)
			{
				group = 0;
			}
		}

		private static void HeaderPostfix(object __instance, object ui, int __state)
		{
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			if (__state >= 100)
			{
				int num = __state - 100;
				bool flag = Localization.instance != null && Localization.instance.GetSelectedLanguage() == "Russian";
				string[] array = ((!flag) ? new string[8] { "Unclassified", "Meadows", "Black Forest", "Swamp", "Mountains", "Plains", "Mistlands", "Ashlands" } : new string[8] { "Без тира", "Луга", "Чёрный лес", "Болота", "Горы", "Равнины", "Туманные земли", "Пепельные земли" });
				string text = ((num == 0) ? array[0] : ((flag ? "Тир " : "Tier ") + num + " — " + array[num]));
				TMP_Text val = (TMP_Text)Field(ui, "Head");
				val.text = text;
				((Graphic)val).color = new Color(0.94f, 0.8f, 0.5f);
			}
		}

		private static void Sort(object __instance)
		{
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Expected O, but got Unknown
			ViewState state = States.GetOrCreateValue(__instance);
			IList list = (IList)Field(__instance, "_rows");
			if (state.Rebuilding)
			{
				state.Original.Clear();
				for (int i = 0; i < list.Count; i++)
				{
					state.Original[list[i]] = i;
				}
				state.Rebuilding = false;
			}
			if (Mode.Value == 0)
			{
				int value2;
				object[] array = (from object row in list
					orderby (!state.Original.TryGetValue(row, out value2)) ? int.MaxValue : value2
					select row).ToArray();
				for (int num = 0; num < array.Length; num++)
				{
					list[num] = array[num];
				}
				return;
			}
			List<Entry> list2 = new List<Entry>(list.Count);
			for (int num2 = 0; num2 < list.Count; num2++)
			{
				object obj = list[num2];
				Recipe val = (Recipe)Field(obj, "Recipe");
				string[] resourcePrefabs = (((Object)(object)val == (Object)null) ? Array.Empty<string>() : (from r in val.m_resources
					where r != null && (Object)(object)r.m_resItem != (Object)null && (r.m_amount > 0 || r.m_amountPerLevel > 0)
					select ((Object)((Component)r.m_resItem).gameObject).name.Replace("(Clone)", "")).ToArray());
				int num3 = RecipeTier(obj);
				list2.Add(new Entry
				{
					Row = obj,
					Rank = (state.Original.TryGetValue(obj, out var value) ? value : num2),
					Tier = ((num3 == 0) ? int.MaxValue : num3),
					Material = SortKeys.MaterialKey(resourcePrefabs),
					Name = (((string)Field(obj, "Name")) ?? "")
				});
			}
			list2.Sort(delegate(Entry a, Entry b)
			{
				int num5 = ((Mode.Value == 2) ? (((a.Tier == int.MaxValue) ? (-1) : a.Tier).CompareTo((b.Tier == int.MaxValue) ? (-1) : b.Tier) * -1) : ((Mode.Value == 1) ? StringComparer.Ordinal.Compare(a.Material, b.Material) : 0));
				if (num5 == 0 && Mode.Value != 0)
				{
					num5 = StringComparer.CurrentCultureIgnoreCase.Compare(a.Name, b.Name);
				}
				return (num5 == 0) ? a.Rank.CompareTo(b.Rank) : num5;
			});
			for (int num4 = 0; num4 < list2.Count; num4++)
			{
				list[num4] = list2[num4].Row;
			}
		}
	}
	public static class SortKeys
	{
		private const char Separator = '\u001f';

		private const int UnknownSortTier = 8;

		private static readonly IReadOnlyDictionary<string, int> VanillaTiers = new Dictionary<string, int>(StringComparer.Ordinal)
		{
			["Wood"] = 1,
			["Stone"] = 1,
			["Flint"] = 1,
			["Resin"] = 1,
			["LeatherScraps"] = 1,
			["DeerHide"] = 1,
			["HardAntler"] = 1,
			["Feather"] = 1,
			["Feathers"] = 1,
			["Honey"] = 1,
			["QueenBee"] = 1,
			["Dandelion"] = 1,
			["Raspberry"] = 1,
			["Mushroom"] = 1,
			["RawMeat"] = 1,
			["BoarMeat"] = 1,
			["DeerMeat"] = 1,
			["NeckTail"] = 1,
			["RoundLog"] = 2,
			["CoreWood"] = 2,
			["FineWood"] = 2,
			["Copper"] = 2,
			["CopperOre"] = 2,
			["Tin"] = 2,
			["TinOre"] = 2,
			["Bronze"] = 2,
			["BronzeNails"] = 2,
			["TrollHide"] = 2,
			["GreydwarfEye"] = 2,
			["BoneFragments"] = 2,
			["SurtlingCore"] = 2,
			["AncientSeed"] = 2,
			["CryptKey"] = 2,
			["Chitin"] = 2,
			["Thistle"] = 2,
			["Carrot"] = 2,
			["CarrotSeeds"] = 2,
			["Blueberries"] = 2,
			["MushroomYellow"] = 2,
			["YmirRemains"] = 2,
			["ElderBark"] = 3,
			["AncientBark"] = 3,
			["Iron"] = 3,
			["ScrapIron"] = 3,
			["IronScrap"] = 3,
			["IronNails"] = 3,
			["Chain"] = 3,
			["Guck"] = 3,
			["Root"] = 3,
			["Bloodbag"] = 3,
			["Entrails"] = 3,
			["Ooze"] = 3,
			["WitheredBone"] = 3,
			["Turnip"] = 3,
			["TurnipSeeds"] = 3,
			["TrophyDraugrElite"] = 3,
			["Silver"] = 4,
			["SilverOre"] = 4,
			["Obsidian"] = 4,
			["Crystal"] = 4,
			["WolfPelt"] = 4,
			["WolfFang"] = 4,
			["FreezeGland"] = 4,
			["DragonEgg"] = 4,
			["DragonTear"] = 4,
			["FenrisHair"] = 4,
			["FenrisClaw"] = 4,
			["WolfHairBundle"] = 4,
			["JuteRed"] = 4,
			["Onion"] = 4,
			["OnionSeeds"] = 4,
			["TrophyCultist"] = 4,
			["BlackMetal"] = 5,
			["BlackMetalScrap"] = 5,
			["LinenThread"] = 5,
			["Flax"] = 5,
			["Barley"] = 5,
			["BarleyFlour"] = 5,
			["LoxPelt"] = 5,
			["Needle"] = 5,
			["Tar"] = 5,
			["Cloudberry"] = 5,
			["GoblinTotem"] = 5,
			["YagluthDrop"] = 5,
			["YggdrasilWood"] = 6,
			["Carapace"] = 6,
			["ScaleHide"] = 6,
			["Mandible"] = 6,
			["BlackCore"] = 6,
			["Softtissue"] = 6,
			["Sap"] = 6,
			["Eitr"] = 6,
			["RefinedEitr"] = 6,
			["Bilebag"] = 6,
			["RoyalJelly"] = 6,
			["JuteBlue"] = 6,
			["DvergrKeyFragment"] = 6,
			["DvergrKey"] = 6,
			["SealbreakerFragment"] = 6,
			["Sealbreaker"] = 6,
			["QueenDrop"] = 6,
			["MechanicalSpring"] = 6,
			["Magecap"] = 6,
			["JotunPuffs"] = 6,
			["Ashwood"] = 7,
			["Blackwood"] = 7,
			["Grausten"] = 7,
			["Flametal"] = 7,
			["FlametalOre"] = 7,
			["FlametalNew"] = 7,
			["FlametalOreNew"] = 7,
			["AskHide"] = 7,
			["AsksvinHide"] = 7,
			["AskBladder"] = 7,
			["MorgenSinew"] = 7,
			["MorgenHeart"] = 7,
			["CelestialFeather"] = 7,
			["VoltureFeather"] = 7,
			["CharredBone"] = 7,
			["CharredCogwheel"] = 7,
			["CeramicPlate"] = 7,
			["SulfurStone"] = 7,
			["ProustitePowder"] = 7,
			["GemstoneBlue"] = 7,
			["GemstoneGreen"] = 7,
			["GemstoneRed"] = 7,
			["Bloodstone"] = 7,
			["Jade"] = 7,
			["Iolite"] = 7,
			["BonemawSerpentTooth"] = 7,
			["BonemawSerpentScale"] = 7,
			["BellFragment"] = 7,
			["DyrnwynBladeFragment"] = 7,
			["DyrnwynHiltFragment"] = 7,
			["DyrnwynTipFragment"] = 7,
			["Fiddlehead"] = 7,
			["Vineberry"] = 7
		};

		public static int TierOf(string prefab)
		{
			if (string.IsNullOrEmpty(prefab))
			{
				return 0;
			}
			if (!VanillaTiers.TryGetValue(prefab, out var value))
			{
				return 0;
			}
			return value;
		}

		public static int Tier(IEnumerable<string> resourcePrefabs)
		{
			if (resourcePrefabs == null)
			{
				throw new ArgumentNullException("resourcePrefabs");
			}
			int num = 0;
			foreach (string resourcePrefab in resourcePrefabs)
			{
				num = Math.Max(num, TierOf(resourcePrefab));
			}
			return num;
		}

		public static string MaterialKey(IEnumerable<string> resourcePrefabs)
		{
			if (resourcePrefabs == null)
			{
				throw new ArgumentNullException("resourcePrefabs");
			}
			string[] array = resourcePrefabs.Select((string prefab) => prefab ?? string.Empty).OrderBy<string, string>((string prefab) => prefab, StringComparer.Ordinal).ToArray();
			int tier = Tier(array);
			string text = array.Where((string prefab) => TierOf(prefab) == tier).FirstOrDefault() ?? string.Empty;
			int num = ((tier == 0) ? 8 : tier);
			string text2 = string.Join('\u001f'.ToString(), array);
			return num.ToString("D2") + "\u001f" + text + "\u001f" + text2;
		}
	}
	public static class TierList
	{
		private const int HeaderBase = -101;

		private const int FirstKnownTier = 1;

		private const int LastKnownTier = 7;

		public static List<int> Build(IEnumerable<(int Index, int Tier)> entries)
		{
			if (entries == null)
			{
				throw new ArgumentNullException("entries");
			}
			List<int>[] array = new List<int>[8];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = new List<int>();
			}
			foreach (var entry in entries)
			{
				int item = entry.Index;
				int item2 = entry.Tier;
				int num = ((item2 >= 1 && item2 <= 7) ? item2 : 0);
				array[num].Add(item);
			}
			List<int> result = new List<int>();
			for (int num2 = 7; num2 >= 1; num2--)
			{
				AppendTier(result, array[num2], num2);
			}
			AppendTier(result, array[0], 0);
			return result;
		}

		private static void AppendTier(List<int> result, List<int> indexes, int tier)
		{
			if (indexes.Count != 0)
			{
				result.Add(-101 - tier);
				result.AddRange(indexes);
			}
		}
	}
}