Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of SortedCrafting v1.0.0
SortedCrafting.dll
Decompiled 2 days agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("SortedCrafting")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("SortedCrafting")] [assembly: AssemblyTitle("SortedCrafting")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace SortedCrafting { [BepInPlugin("com.dreich.sortedcrafting", "Sorted Crafting", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class SortedCraftingPlugin : BaseUnityPlugin { public const string Guid = "com.dreich.sortedcrafting"; public const string Name = "Sorted Crafting"; public const string Version = "1.0.0"; internal static ManualLogSource Log; internal static ConfigEntry<bool> SortEnabled; internal static ConfigEntry<bool> UnknownLast; internal static ConfigEntry<bool> ShowHeaders; internal static ConfigEntry<string> BiomeOverrides; internal static ConfigEntry<bool> LogBiomes; private void Awake() { //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; SortEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Sort the recipes at every crafting station by the biome they come from, Meadows first and the Deep North last."); UnknownLast = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "UnknownLast", true, "Recipes whose biome can't be worked out go at the end of the list. Off puts them at the start."); ShowHeaders = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowHeaders", true, "Show a title with the biome's name above each biome's recipes."); BiomeOverrides = ((BaseUnityPlugin)this).Config.Bind<string>("General", "BiomeOverrides", "IronScrap=Swamp,SurtlingCore=BlackForest,AncientSeed=BlackForest,WitheredBone=Swamp,Crystal=Mountain,DragonEgg=Mountain,BlackMetalScrap=Plains,BugMeat=Mistlands,Carapace=Mistlands,BlackCore=Mistlands,Softtissue=Mistlands,Sap=Mistlands,RoyalJelly=Mistlands,DvergrNeedle=Mistlands,FlametalOreNew=AshLands", "Comma separated ItemPrefab=Biome pairs for items whose biome can't be worked out, mostly loot from dungeons. Anything crafted from them follows. Biomes: Meadows, BlackForest, Swamp, Ocean, Mountain, Plains, Mistlands, AshLands, DeepNorth."); LogBiomes = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogBiomes", false, "Write every item's biome to the log the first time a crafting station is opened."); BiomeOverrides.SettingChanged += delegate { BiomeTable.Clear(); }; Harmony val = new Harmony("com.dreich.sortedcrafting"); val.PatchAll(); JatifyHeaders.Patch(val); } } [HarmonyPatch(typeof(InventoryGui), "UpdateRecipeList")] internal static class UpdateRecipeListPatch { [HarmonyPriority(0)] private static void Postfix(InventoryGui __instance) { try { RecipeLayout.Apply(__instance); } catch (Exception ex) { SortedCraftingPlugin.Log.LogWarning((object)("Sorting recipes failed: " + ex)); } } } internal static class RecipeLayout { private struct Row { internal object Pair; internal int Rank; internal int Position; } private const string NameChild = "name"; private const string HeaderObjectName = "SortedCraftingHeader"; private const string HeaderFormat = "— {0} —"; private const string UnknownTitle = "Other"; private const int UnknownFirst = int.MinValue; private const int UnknownLast = int.MaxValue; private static readonly Color HeaderColor = new Color(1f, 0.8f, 0.4f, 1f); private static readonly FieldInfo AvailableField = AccessTools.Field(typeof(InventoryGui), "m_availableRecipes"); private static readonly FieldInfo BaseSizeField = AccessTools.Field(typeof(InventoryGui), "m_recipeListBaseSize"); private static PropertyInfo recipeProperty; private static PropertyInfo elementProperty; private static readonly List<Row> rows = new List<Row>(); private static readonly List<GameObject> headers = new List<GameObject>(); internal static void Apply(InventoryGui gui) { //IL_01b5: Unknown result type (might be due to invalid IL or missing references) if (!(AvailableField?.GetValue(gui) is IList list)) { return; } if (!SortedCraftingPlugin.SortEnabled.Value || list.Count == 0) { HideHeadersFrom(0); return; } Dictionary<string, int> dictionary = BiomeTable.Tiers(); if (dictionary == null || !LookUpProperties(list[0])) { return; } rows.Clear(); for (int i = 0; i < list.Count; i++) { object? value = recipeProperty.GetValue(list[i], null); Recipe recipe = (Recipe)((value is Recipe) ? value : null); rows.Add(new Row { Pair = list[i], Rank = RankOf(recipe, dictionary), Position = i }); } rows.Sort((Row a, Row b) => (a.Rank == b.Rank) ? a.Position.CompareTo(b.Position) : a.Rank.CompareTo(b.Rank)); float recipeListSpace = gui.m_recipeListSpace; bool value2 = SortedCraftingPlugin.ShowHeaders.Value; int num = 0; int first = 0; bool flag = true; int num2 = 0; for (int num3 = 0; num3 < rows.Count; num3++) { Row row = rows[num3]; list[num3] = row.Pair; object? value3 = elementProperty.GetValue(row.Pair, null); GameObject val = (GameObject)((value3 is GameObject) ? value3 : null); if (!((Object)(object)val == (Object)null)) { if (value2 && (flag || row.Rank != num2)) { PlaceHeader(gui, first++, val, Title(row.Rank), (float)num * recipeListSpace); num++; } flag = false; num2 = row.Rank; Transform transform = val.transform; RectTransform val2 = (RectTransform)(object)((transform is RectTransform) ? transform : null); if (val2 != null) { val2.anchoredPosition = new Vector2(0f, (float)(-num) * recipeListSpace); } num++; } } rows.Clear(); HideHeadersFrom(first); float num4 = ((BaseSizeField?.GetValue(gui) is float num5) ? num5 : 0f); gui.m_recipeListRoot.SetSizeWithCurrentAnchors((Axis)1, Mathf.Max(num4, (float)num * recipeListSpace)); } internal static int RankOf(Recipe recipe, Dictionary<string, int> tiers) { string text = (((Object)(object)recipe != (Object)null && (Object)(object)recipe.m_item != (Object)null) ? ((Object)recipe.m_item).name : null); if (text != null && tiers.TryGetValue(text, out var value)) { return value; } if (!SortedCraftingPlugin.UnknownLast.Value) { return int.MinValue; } return int.MaxValue; } internal static string BiomeName(int rank) { if (rank != int.MinValue && rank != int.MaxValue) { return BiomeTable.DisplayName(rank); } return "Other"; } private static bool LookUpProperties(object pair) { if (recipeProperty != null && elementProperty != null) { return true; } Type type = pair.GetType(); recipeProperty = AccessTools.Property(type, "Recipe"); elementProperty = AccessTools.Property(type, "InterfaceElement"); if (recipeProperty != null) { return elementProperty != null; } return false; } private static string Title(int rank) { return $"— {BiomeName(rank)} —"; } private static void PlaceHeader(InventoryGui gui, int index, GameObject row, string title, float depth) { //IL_00fa: 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_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) while (headers.Count <= index) { headers.Add(null); } GameObject val = headers[index]; if ((Object)(object)val == (Object)null) { Transform val2 = row.transform.Find("name"); if ((Object)(object)val2 == (Object)null) { return; } val = Object.Instantiate<GameObject>(((Component)val2).gameObject, (Transform)(object)gui.m_recipeListRoot); ((Object)val).name = "SortedCraftingHeader"; headers[index] = val; } Transform transform = val.transform; RectTransform val3 = (RectTransform)(object)((transform is RectTransform) ? transform : null); if (val3 != null) { Transform transform2 = row.transform; RectTransform val4 = (RectTransform)(object)((transform2 is RectTransform) ? transform2 : null); if (val4 != null) { val3.anchorMin = val4.anchorMin; val3.anchorMax = val4.anchorMax; val3.pivot = val4.pivot; val3.sizeDelta = val4.sizeDelta; ((Transform)val3).localScale = Vector3.one; val3.anchoredPosition = new Vector2(0f, 0f - depth); } } TMP_Text component = val.GetComponent<TMP_Text>(); if ((Object)(object)component != (Object)null) { component.text = title; ((Graphic)component).color = HeaderColor; component.alignment = (TextAlignmentOptions)514; ((Graphic)component).raycastTarget = false; } val.SetActive(true); } private static void HideHeadersFrom(int first) { for (int i = first; i < headers.Count; i++) { if ((Object)(object)headers[i] != (Object)null && headers[i].activeSelf) { headers[i].SetActive(false); } } } } internal static class JatifyHeaders { internal const string Guid = "jatify.ui"; private const string TitleFormat = "{0} · {1}"; private const char WordBreak = ' '; private static MethodInfo section; private static FieldInfo recipeField; private static bool drawingGroup; internal static void Patch(Harmony harmony) { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown if (Chainloader.PluginInfos.ContainsKey("jatify.ui")) { Type type = AccessTools.TypeByName("Jatify.UI.RecipeView"); section = ((type != null) ? AccessTools.Method(type, "Section", (Type[])null, (Type[])null) : null); if (section == null || section.ReturnType != typeof(float)) { SortedCraftingPlugin.Log.LogWarning((object)"Jatify UI's crafting panel has changed; its recipes won't get biome headers."); } else { harmony.Patch((MethodBase)section, new HarmonyMethod(typeof(JatifyHeaders), "SectionPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } private static bool SectionPrefix(object __instance, string title, Color c, object list, int sel, object g, float y, ref float __result) { //IL_00c7: 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) if (drawingGroup || !SortedCraftingPlugin.SortEnabled.Value || !SortedCraftingPlugin.ShowHeaders.Value) { return true; } if (!(list is IList { Count: not 0 } list2)) { return true; } Dictionary<string, int> dictionary = BiomeTable.Tiers(); if (dictionary == null) { return true; } if (recipeField == null) { recipeField = AccessTools.Field(list2[0].GetType(), "Recipe"); } if (recipeField == null) { return true; } string sectionName = SectionName(title); float num = y; IList list3 = null; int num2 = 0; drawingGroup = true; try { foreach (object item in list2) { object? value = recipeField.GetValue(item); int num3 = RecipeLayout.RankOf((Recipe)((value is Recipe) ? value : null), dictionary); if (list3 != null && num3 != num2) { num = Draw(__instance, sectionName, num2, c, list3, sel, g, num); list3 = null; } if (list3 == null) { list3 = (IList)Activator.CreateInstance(list.GetType()); num2 = num3; } list3.Add(item); } if (list3 != null) { num = Draw(__instance, sectionName, num2, c, list3, sel, g, num); } } finally { drawingGroup = false; } __result = num; return false; } private static float Draw(object view, string sectionName, int rank, Color colour, IList group, int sel, object theme, float y) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) string text = $"{sectionName} · {RecipeLayout.BiomeName(rank).ToUpperInvariant()}"; return (float)section.Invoke(view, new object[6] { text, colour, group, sel, theme, y }); } private static string SectionName(string title) { int num = title.IndexOf(' '); if (num <= 0) { return title; } return title.Substring(0, num); } } internal static class BiomeTable { private sealed class TierScan { internal readonly Dictionary<string, int> Narrow = new Dictionary<string, int>(StringComparer.Ordinal); internal readonly Dictionary<string, int> Broad = new Dictionary<string, int>(StringComparer.Ordinal); internal readonly Dictionary<string, string> NarrowFrom = new Dictionary<string, string>(StringComparer.Ordinal); internal readonly Dictionary<string, string> BroadFrom = new Dictionary<string, string>(StringComparer.Ordinal); internal readonly HashSet<GameObject> Visited = new HashSet<GameObject>(); internal int Rank; internal bool IsBroad; internal string Origin; } private struct Conversion { internal ItemDrop From; internal ItemDrop To; } private const int NoRank = -1; private const int BaseQuality = 1; private const int MostBiomesForNarrowSource = 2; private const int DeepestDropChain = 4; private const int MostTierPasses = 20; private const string BossPrefabs = "Meadows=Eikthyr,BlackForest=gd_king,Swamp=Bonemass,Mountain=Dragon,Plains=GoblinKing,Mistlands=SeekerQueen,AshLands=Fader,DeepNorth=FrozenKing"; private static readonly Biome[] BiomeOrder; private static readonly Dictionary<Biome, string> DisplayNames; private static ObjectDB builtFor; private static Dictionary<string, int> tiers; private static Dictionary<string, string> origins; internal static void Clear() { builtFor = null; tiers = null; } internal static Dictionary<string, int> Tiers() { ObjectDB instance = ObjectDB.instance; if ((Object)(object)instance == (Object)null || (Object)(object)ZNetScene.instance == (Object)null || (Object)(object)ZoneSystem.instance == (Object)null) { return null; } if ((Object)(object)builtFor == (Object)(object)instance && tiers != null) { return tiers; } builtFor = instance; tiers = FindTiers(instance); if (SortedCraftingPlugin.LogBiomes.Value) { LogTable(); } return tiers; } internal unsafe static string DisplayName(int rank) { //IL_0016: 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) Biome key = BiomeOrder[Mathf.Clamp(rank, 0, BiomeOrder.Length - 1)]; if (!DisplayNames.TryGetValue(key, out var value)) { return ((object)(*(Biome*)(&key))/*cast due to .constrained prefix*/).ToString(); } return value; } private static int Rank(Biome biome) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < BiomeOrder.Length; i++) { if ((biome & BiomeOrder[i]) != 0) { return i; } } return -1; } private static int HighestRank(Biome biome) { //IL_000c: 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) for (int num = BiomeOrder.Length - 1; num >= 0; num--) { if ((biome & BiomeOrder[num]) != 0) { return num; } } return -1; } private static int BiomeCount(Biome biome) { //IL_000f: 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_0012: Unknown result type (might be due to invalid IL or missing references) int num = 0; Biome[] biomeOrder = BiomeOrder; foreach (Biome val in biomeOrder) { if ((biome & val) != 0) { num++; } } return num; } private static bool TryParseBiome(string text, out Biome biome) { if (Enum.TryParse<Biome>(text.Trim(), ignoreCase: true, out biome)) { return (int)biome != 0; } return false; } private static Dictionary<string, string> ParsePairs(string raw) { Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); string[] array = (raw ?? "").Split(new char[1] { ',' }); foreach (string text in array) { int num = text.IndexOf('='); if (num > 0) { string text2 = text.Substring(0, num).Trim(); string text3 = text.Substring(num + 1).Trim(); if (text2.Length > 0 && text3.Length > 0) { dictionary[text2] = text3; } } } return dictionary; } private static void Begin(TierScan scan, Biome biome, string origin) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) scan.IsBroad = BiomeCount(biome) > 2; scan.Rank = (scan.IsBroad ? HighestRank(biome) : Rank(biome)); scan.Origin = origin; scan.Visited.Clear(); } private static void AddTier(TierScan scan, GameObject prefab) { if (!((Object)(object)prefab == (Object)null) && scan.Rank >= 0 && !((Object)(object)prefab.GetComponent<ItemDrop>() == (Object)null)) { string name = ((Object)prefab).name; Dictionary<string, int> dictionary = (scan.IsBroad ? scan.Broad : scan.Narrow); Dictionary<string, string> dictionary2 = (scan.IsBroad ? scan.BroadFrom : scan.NarrowFrom); if (!dictionary.TryGetValue(name, out var value) || scan.Rank < value) { dictionary[name] = scan.Rank; dictionary2[name] = scan.Origin; } } } private static void AddDropTable(TierScan scan, DropTable table, int depth) { //IL_001c: 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) //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (table == null || table.m_drops == null) { return; } foreach (DropData drop in table.m_drops) { AddSource(scan, drop.m_item, depth + 1); } } private static void AddSource(TierScan scan, GameObject prefab, int depth) { if ((Object)(object)prefab == (Object)null || scan.Rank < 0 || depth > 4 || !scan.Visited.Add(prefab)) { return; } AddTier(scan, prefab); Pickable component = prefab.GetComponent<Pickable>(); if ((Object)(object)component != (Object)null) { AddTier(scan, component.m_itemPrefab); AddDropTable(scan, component.m_extraDrops, depth); } DropOnDestroyed component2 = prefab.GetComponent<DropOnDestroyed>(); if ((Object)(object)component2 != (Object)null) { AddDropTable(scan, component2.m_dropWhenDestroyed, depth); } MineRock component3 = prefab.GetComponent<MineRock>(); if ((Object)(object)component3 != (Object)null) { AddDropTable(scan, component3.m_dropItems, depth); } MineRock5 component4 = prefab.GetComponent<MineRock5>(); if ((Object)(object)component4 != (Object)null) { AddDropTable(scan, component4.m_dropItems, depth); } TreeBase component5 = prefab.GetComponent<TreeBase>(); if ((Object)(object)component5 != (Object)null) { AddDropTable(scan, component5.m_dropWhenDestroyed, depth); AddSource(scan, component5.m_logPrefab, depth + 1); } TreeLog component6 = prefab.GetComponent<TreeLog>(); if ((Object)(object)component6 != (Object)null) { AddDropTable(scan, component6.m_dropWhenDestroyed, depth); AddSource(scan, component6.m_subLogPrefab, depth + 1); } Destructible component7 = prefab.GetComponent<Destructible>(); if ((Object)(object)component7 != (Object)null) { AddSource(scan, component7.m_spawnWhenDestroyed, depth + 1); } CharacterDrop component8 = prefab.GetComponent<CharacterDrop>(); if (!((Object)(object)component8 != (Object)null) || component8.m_drops == null) { return; } foreach (Drop drop in component8.m_drops) { AddTier(scan, drop.m_prefab); } } private static Dictionary<string, int> FindTiers(ObjectDB db) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: 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_02d2: Unknown result type (might be due to invalid IL or missing references) TierScan tierScan = new TierScan(); foreach (ZoneVegetation item in ZoneSystem.instance.m_vegetation) { if (item != null && item.m_enable && !((Object)(object)item.m_prefab == (Object)null)) { Begin(tierScan, item.m_biome, "vegetation " + ((Object)item.m_prefab).name); AddSource(tierScan, item.m_prefab, 0); } } foreach (SpawnSystem item2 in SpawnSystems()) { foreach (SpawnSystemList spawnList in item2.m_spawnLists) { if ((Object)(object)spawnList == (Object)null) { continue; } foreach (SpawnData spawner in spawnList.m_spawners) { if (spawner != null && spawner.m_enabled && !((Object)(object)spawner.m_prefab == (Object)null)) { Begin(tierScan, spawner.m_biome, "creature " + ((Object)spawner.m_prefab).name); AddSource(tierScan, spawner.m_prefab, 0); } } } } foreach (KeyValuePair<string, string> item3 in ParsePairs("Meadows=Eikthyr,BlackForest=gd_king,Swamp=Bonemass,Mountain=Dragon,Plains=GoblinKing,Mistlands=SeekerQueen,AshLands=Fader,DeepNorth=FrozenKing")) { if (TryParseBiome(item3.Key, out var biome)) { Begin(tierScan, biome, "boss " + item3.Value); AddSource(tierScan, ZNetScene.instance.GetPrefab(item3.Value), 0); } } Dictionary<string, int> dictionary = new Dictionary<string, int>(tierScan.Narrow, StringComparer.Ordinal); Dictionary<string, string> dictionary2 = new Dictionary<string, string>(tierScan.NarrowFrom, StringComparer.Ordinal); foreach (KeyValuePair<string, int> item4 in tierScan.Broad) { if (!dictionary.ContainsKey(item4.Key)) { dictionary[item4.Key] = item4.Value; dictionary2[item4.Key] = tierScan.BroadFrom[item4.Key] + " (many biomes)"; } } HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal); foreach (KeyValuePair<string, string> item5 in ParsePairs(SortedCraftingPlugin.BiomeOverrides.Value)) { if (TryParseBiome(item5.Value, out var biome2)) { dictionary[item5.Key] = Rank(biome2); dictionary2[item5.Key] = "BiomeOverrides"; hashSet.Add(item5.Key); } } List<Conversion> list = Conversions(); HashSet<string> hashSet2 = new HashSet<string>(StringComparer.Ordinal); foreach (Conversion item6 in list) { if ((Object)(object)item6.To != (Object)null && !hashSet.Contains(((Object)item6.To).name)) { hashSet2.Add(((Object)item6.To).name); } } foreach (Recipe recipe in db.m_recipes) { if (Usable(recipe) && !hashSet.Contains(((Object)recipe.m_item).name)) { hashSet2.Add(((Object)recipe.m_item).name); } } Dictionary<string, int> dictionary3 = new Dictionary<string, int>(dictionary, StringComparer.Ordinal); bool flag = true; for (int i = 0; i < 20 && flag; i++) { flag = false; Dictionary<string, int> dictionary4 = new Dictionary<string, int>(StringComparer.Ordinal); Dictionary<string, string> dictionary5 = new Dictionary<string, string>(StringComparer.Ordinal); foreach (Conversion item7 in list) { if (!((Object)(object)item7.From == (Object)null) && !((Object)(object)item7.To == (Object)null) && hashSet2.Contains(((Object)item7.To).name) && dictionary.TryGetValue(((Object)item7.From).name, out var value) && (!dictionary4.TryGetValue(((Object)item7.To).name, out var value2) || value < value2)) { dictionary4[((Object)item7.To).name] = value; dictionary5[((Object)item7.To).name] = "made from " + ((Object)item7.From).name; } } foreach (Recipe recipe2 in db.m_recipes) { if (!Usable(recipe2) || !hashSet2.Contains(((Object)recipe2.m_item).name)) { continue; } int num = -1; string text = null; Requirement[] resources = recipe2.m_resources; foreach (Requirement val in resources) { if (val != null && !((Object)(object)val.m_resItem == (Object)null) && val.GetAmount(1) > 0 && dictionary.TryGetValue(((Object)val.m_resItem).name, out var value3) && value3 > num) { num = value3; text = ((Object)val.m_resItem).name; } } if (num >= 0 && (!dictionary4.TryGetValue(((Object)recipe2.m_item).name, out var value4) || num < value4)) { dictionary4[((Object)recipe2.m_item).name] = num; dictionary5[((Object)recipe2.m_item).name] = "crafted from " + text; } } foreach (KeyValuePair<string, int> item8 in dictionary4) { int num2 = item8.Value; int value5; bool flag2 = dictionary3.TryGetValue(item8.Key, out value5) && value5 <= num2; if (flag2) { num2 = value5; } if (!dictionary.TryGetValue(item8.Key, out var value6) || value6 != num2) { dictionary[item8.Key] = num2; if (!flag2) { dictionary2[item8.Key] = dictionary5[item8.Key]; } flag = true; } } } origins = dictionary2; return dictionary; } private static bool Usable(Recipe recipe) { if ((Object)(object)recipe != (Object)null && recipe.m_enabled && (Object)(object)recipe.m_item != (Object)null && recipe.m_resources != null) { return recipe.m_resources.Length != 0; } return false; } private static IEnumerable<SpawnSystem> SpawnSystems() { HashSet<SpawnSystem> seen = new HashSet<SpawnSystem>(); foreach (GameObject prefab in ZNetScene.instance.m_prefabs) { SpawnSystem val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<SpawnSystem>() : null); if ((Object)(object)val != (Object)null && seen.Add(val)) { yield return val; } } if (!(AccessTools.Field(typeof(SpawnSystem), "m_instances")?.GetValue(null) is List<SpawnSystem> list)) { yield break; } foreach (SpawnSystem item in list) { if ((Object)(object)item != (Object)null && seen.Add(item)) { yield return item; } } } private static List<Conversion> Conversions() { List<Conversion> list = new List<Conversion>(); foreach (GameObject prefab in ZNetScene.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) { list.Add(new Conversion { From = item.m_from, To = item.m_to }); } } CookingStation component2 = prefab.GetComponent<CookingStation>(); if ((Object)(object)component2 != (Object)null && component2.m_conversion != null) { foreach (ItemConversion item2 in component2.m_conversion) { list.Add(new Conversion { From = item2.m_from, To = item2.m_to }); } } Fermenter component3 = prefab.GetComponent<Fermenter>(); if (!((Object)(object)component3 != (Object)null) || component3.m_conversion == null) { continue; } foreach (ItemConversion item3 in component3.m_conversion) { list.Add(new Conversion { From = item3.m_from, To = item3.m_to }); } } return list; } private static void LogTable() { List<string> list = new List<string>(); foreach (Recipe recipe in builtFor.m_recipes) { if (Usable(recipe)) { string name = ((Object)recipe.m_item).name; int value; string text = (tiers.TryGetValue(name, out value) ? ((object)Unsafe.As<Biome, Biome>(ref BiomeOrder[value])/*cast due to .constrained prefix*/).ToString() : "unknown"); string value2; string text2 = (origins.TryGetValue(name, out value2) ? (" (" + value2 + ")") : ""); list.Add(name + ": " + text + text2); } } list.Sort(StringComparer.Ordinal); SortedCraftingPlugin.Log.LogInfo((object)("Recipe biomes:\n" + string.Join("\n", list.ToArray()))); } static BiomeTable() { Biome[] array = new Biome[9]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); BiomeOrder = (Biome[])(object)array; DisplayNames = new Dictionary<Biome, string> { { (Biome)8, "Black Forest" }, { (Biome)32, "Ashlands" }, { (Biome)64, "Deep North" } }; origins = new Dictionary<string, string>(StringComparer.Ordinal); } } }