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 Biome Crafting Tabs v0.3.0
BepInEx/plugins/TieredBlackForge.dll
Decompiled 2 weeks agousing 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.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("TieredBlackForge")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.1.0")] [assembly: AssemblyInformationalVersion("0.1.1")] [assembly: AssemblyProduct("TieredBlackForge")] [assembly: AssemblyTitle("TieredBlackForge")] [assembly: AssemblyVersion("0.1.1.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 TieredBlackForge { [BepInPlugin("fr.dessouille.tieredblackforge", "Tiered Black Forge", "0.3.0")] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "fr.dessouille.tieredblackforge"; public const string PluginName = "Tiered Black Forge"; public const string PluginVersion = "0.3.0"; internal static ManualLogSource Log; internal static ConfigEntry<string> MistlandsTokens; internal static ConfigEntry<string> AshlandsTokens; internal static ConfigEntry<string> DeepNorthTokens; internal static ConfigEntry<string> SwampTokens; internal static ConfigEntry<string> MountainTokens; internal static ConfigEntry<string> PlainsTokens; internal static ConfigEntry<string> MistlandsRecipes; internal static ConfigEntry<string> AshlandsRecipes; internal static ConfigEntry<string> DeepNorthRecipes; internal static ConfigEntry<string> SwampRecipes; internal static ConfigEntry<string> MountainRecipes; internal static ConfigEntry<string> PlainsRecipes; internal static ConfigEntry<string> MeadowsRecipes; internal static ConfigEntry<string> BlackForestRecipes; private Harmony _harmony; private void Awake() { //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; MistlandsTokens = ((BaseUnityPlugin)this).Config.Bind<string>("Classification", "MistlandsTokens", "blackcore,blackmarble,bluejute,sap,softtissue,yggdrasil,wisp,sealbreaker,scalehide,jotunpuff,magecap,royaljelly,bilebag,bloodclot,carapace,mandible,seeker", "Fragments de noms internes de matériaux associés aux Mistlands."); AshlandsTokens = ((BaseUnityPlugin)this).Config.Bind<string>("Classification", "AshlandsTokens", "flametal,grausten,proustite,sulfur,bonemaw,morgen,volture,fiddlehead,smokepuff,celestialfeather,charred,asksvin,askvin,bloodstone,jade,iolite", "Fragments de noms internes de matériaux associés aux Ashlands."); DeepNorthTokens = ((BaseUnityPlugin)this).Config.Bind<string>("Classification", "DeepNorthTokens", "timberwood,liquidfrost,petrifiedtissue,bloodgold,memorialcoal,frostfire,thunderblood,lingonberr,oat,poteitr,kale,moose,sealblubber,sealpel,elaking,longclaw,frozenbranch,leatherstrap,nornathread,deadpulp,frostcore", "Fragments de noms internes de matériaux associés au Deep North."); SwampTokens = ((BaseUnityPlugin)this).Config.Bind<string>("Classification", "SwampTokens", "iron,scrapiron,ancientbark,guck,root,chain,ooze,bloodbag,entrails,witheredbone", "Fragments de noms internes de matériaux associés au Swamp."); MountainTokens = ((BaseUnityPlugin)this).Config.Bind<string>("Classification", "MountainTokens", "silver,wolf,fenring,fenris,drake,freeze,obsidian,crystal,onion", "Fragments de noms internes de matériaux associés au Mountain."); PlainsTokens = ((BaseUnityPlugin)this).Config.Bind<string>("Classification", "PlainsTokens", "blackmetal,linen,flax,barley,lox,needle,tar,goblin,fuling", "Fragments de noms internes de matériaux associés au Plains."); MistlandsRecipes = ((BaseUnityPlugin)this).Config.Bind<string>("Overrides", "MistlandsRecipes", "", "Noms internes exacts de recettes forcées dans Mist Lands, séparés par des virgules."); AshlandsRecipes = ((BaseUnityPlugin)this).Config.Bind<string>("Overrides", "AshlandsRecipes", "", "Noms internes exacts de recettes forcées dans Ash Lands, séparés par des virgules."); DeepNorthRecipes = ((BaseUnityPlugin)this).Config.Bind<string>("Overrides", "DeepNorthRecipes", "", "Noms internes exacts de recettes forcées dans Deep North, séparés par des virgules."); SwampRecipes = ((BaseUnityPlugin)this).Config.Bind<string>("Overrides", "SwampRecipes", "", "Noms internes exacts de recettes forcées dans Swamp, séparés par des virgules."); MountainRecipes = ((BaseUnityPlugin)this).Config.Bind<string>("Overrides", "MountainRecipes", "", "Noms internes exacts de recettes forcées dans Mountain, séparés par des virgules."); PlainsRecipes = ((BaseUnityPlugin)this).Config.Bind<string>("Overrides", "PlainsRecipes", "", "Noms internes exacts de recettes forcées dans Plains, séparés par des virgules."); MeadowsRecipes = ((BaseUnityPlugin)this).Config.Bind<string>("Overrides", "MeadowsRecipes", "", "Noms internes exacts de recettes forcées dans Meadows, séparés par des virgules."); BlackForestRecipes = ((BaseUnityPlugin)this).Config.Bind<string>("Overrides", "BlackForestRecipes", "", "Noms internes exacts de recettes forcées dans Black Forest, séparés par des virgules."); _harmony = new Harmony("fr.dessouille.tieredblackforge"); _harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Tiered Black Forge 0.3.0 charge."); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } internal enum ForgeTier { Mistlands, Ashlands, DeepNorth, Swamp, Mountain, Plains, Meadows, BlackForest } internal enum ForgeStationKind { None, BlackForge, Forge, Workbench } internal static class TierState { internal static ForgeTier? Selected; internal static ForgeStationKind GetOpenStationKind() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return ForgeStationKind.None; } try { object? obj = AccessTools.Method(typeof(Player), "GetCurrentCraftingStation", (Type[])null, (Type[])null)?.Invoke(localPlayer, null); CraftingStation val = (CraftingStation)((obj is CraftingStation) ? obj : null); if ((Object)(object)val == (Object)null) { return ForgeStationKind.None; } string text = NormalizeStationName(((Object)((Component)val).gameObject).name); if (text.StartsWith("pieceblackforge") || text.StartsWith("blackforge")) { return ForgeStationKind.BlackForge; } if (text.StartsWith("pieceforge") || text == "forge" || text.StartsWith("forgeclone")) { return ForgeStationKind.Forge; } if (text.StartsWith("pieceworkbench") || text == "workbench" || text.StartsWith("workbenchclone")) { return ForgeStationKind.Workbench; } return ForgeStationKind.None; } catch (Exception ex) { Plugin.Log.LogDebug((object)("Detection de la forge impossible: " + ex.Message)); return ForgeStationKind.None; } } internal static bool IsTierForStation(ForgeTier tier, ForgeStationKind station) { switch (station) { case ForgeStationKind.BlackForge: if (tier != ForgeTier.Mistlands && tier != ForgeTier.Ashlands) { return tier == ForgeTier.DeepNorth; } return true; case ForgeStationKind.Forge: if (tier != ForgeTier.Swamp && tier != ForgeTier.Mountain) { return tier == ForgeTier.Plains; } return true; case ForgeStationKind.Workbench: if (tier != ForgeTier.Meadows) { return tier == ForgeTier.BlackForest; } return true; default: return false; } } private static string NormalizeStationName(string value) { return new string((value ?? string.Empty).Where(char.IsLetterOrDigit).Select(char.ToLowerInvariant).ToArray()); } internal static bool Matches(Recipe recipe, ForgeStationKind station) { if ((Object)(object)recipe == (Object)null) { return false; } if (!Selected.HasValue) { return true; } return RecipeClassifier.GetTier(recipe, station) == Selected; } } internal static class RecipeClassifier { private const string MistlandsOutputs = "jotunbane,demolisher,spinesnap,mistwalker,himminafl,krom,skollandhati,arbalest,carapace"; private const string AshlandsOutputs = "ashlands,flametal,niedhogg,slayer,ripper,eldner,berzerkr,splitner,dyrnwyn,askhide,armorashlands,helmetashlands"; private const string DeepNorthOutputs = "deepnorth,gold,nord,frostfire,thunderblood,protector,vanguard,caller"; private const string SwampOutputs = "atgeiriron,axeiron,battleaxe,bowhuntsman,armoriron,helmetiron,maceiron,pickaxeiron,shieldbanded,shieldiron,shieldserpentscale,sledgeiron,spearelderbark,swordiron,ironnails"; private const string EarlierForgeOutputs = "bronze"; private const string MountainOutputs = "armorwolf,helmetdrake,bowdraugrfang,battleaxecrystal,knifesilver,macesilver,frostner,shieldsilver,spearwolf,swordsilver,capewolf"; private const string PlainsOutputs = "atgeirblackmetal,axeblackmetal,knifeblackmetal,swordblackmetal,pickaxeblackmetal,maceneedle,porcupine,shieldblackmetal,armorpadded,helmetpadded"; private const string MeadowsOutputs = "axeflint,bow,club,hammer,hoe,knifeflint,spearflint,shieldwood,shieldwoodtower,armorragschest,armorragslegs,armorleatherchest,armorleatherlegs,helmetleather,capedeerhide,arrowwood,arrowflint,arrowfire,pickaxeantler,torch"; private const string BlackForestOutputs = "armortrollleatherchest,armortrollleatherlegs,helmettrollleather,capetrollhide,bowfinewood,sledgestagbreaker,sledgewood,shieldbonetower,arrowbronze"; private const string MistlandsMaterials = "blackcore,blackmarble,bluejute,sap,softtissue,yggdrasilwood,wisp,scalehide,mushroomjotunpuff,mushroommagecap,royaljelly,bilebag,bloodclot,carapace,mandible,seekermeat,eitr,refinedeitr,upgrader5armor,upgrader5weapon"; private const string AshlandsMaterials = "flametal,flametalnew,flametalorenew,grausten,proustitepowder,sulfurstone,bonemawmeat,morgenheart,volturemeat,smokepuff,celestialfeather,charredbone,charredcogwheel,asksvinhide,gemstoneblue,gemstonegreen,gemstonered,bloodstone,jade,iolite,upgrader6armor,upgrader6weapon"; private const string DeepNorthMaterials = "gold,bloodgold,timberwood,frostcore,ice,nornthread,moosehide,sealhide,sealblubber,leatherstraps,crownjewel,faderember,memorialcoal,orbthunderblood,orbfrostfire,upgrader7armor,upgrader7weapon"; private const string SwampMaterials = "iron,ironscrap,scrapiron,elderbark,root,guck,chain,ooze,bloodbag,entrails,witheredbone,trophydraugrelite,upgrader2armor,upgrader2weapon"; private const string MountainMaterials = "silver,silverore,wolfpelt,wolffang,freezegland,obsidian,crystal,onion,trophyhatchling,upgrader3armor,upgrader3weapon"; private const string PlainsMaterials = "blackmetal,blackmetalscrap,linenthread,flax,barley,loxpelt,needle,tar,upgrader4armor,upgrader4weapon"; private const string WorkbenchLaterMaterials = "iron,ironscrap,scrapiron,elderbark,root,guck,chain,silver,wolfpelt,wolffang,freezegland,obsidian,crystal,blackmetal,blackmetalscrap,linenthread,loxpelt,needle,tar,carapace,eitr,refinedeitr,flametal,flametalnew,flametalorenew,asksvinhide,gold,bloodgold,timberwood,nornthread"; private const string BlackForestMaterials = "trollhide,finewood,roundlog,corewood,bronze,surtlingcore,greydwarfeye,ancientseed,upgrader1armor,upgrader1weapon"; private const string MeadowsMaterials = "wood,stone,flint,leatherscraps,deerhide,bonefragments,resin,feathers,hardantler,deertrophy,boarmeat,boarhide,upgrader0armor,upgrader0weapon"; internal static ForgeTier? GetTier(Recipe recipe, ForgeStationKind station) { string normalizedRecipeName = Normalize(((Object)recipe).name); if (station == ForgeStationKind.BlackForge) { if (ContainsExact(Plugin.DeepNorthRecipes.Value, normalizedRecipeName)) { return ForgeTier.DeepNorth; } if (ContainsExact(Plugin.AshlandsRecipes.Value, normalizedRecipeName)) { return ForgeTier.Ashlands; } if (ContainsExact(Plugin.MistlandsRecipes.Value, normalizedRecipeName)) { return ForgeTier.Mistlands; } if (OutputContainsAny(recipe, "deepnorth,gold,nord,frostfire,thunderblood,protector,vanguard,caller")) { return ForgeTier.DeepNorth; } if (OutputContainsAny(recipe, "ashlands,flametal,niedhogg,slayer,ripper,eldner,berzerkr,splitner,dyrnwyn,askhide,armorashlands,helmetashlands")) { return ForgeTier.Ashlands; } if (OutputContainsAny(recipe, "jotunbane,demolisher,spinesnap,mistwalker,himminafl,krom,skollandhati,arbalest,carapace")) { return ForgeTier.Mistlands; } if (HasAnyResource(recipe, "gold,bloodgold,timberwood,frostcore,ice,nornthread,moosehide,sealhide,sealblubber,leatherstraps,crownjewel,faderember,memorialcoal,orbthunderblood,orbfrostfire,upgrader7armor,upgrader7weapon") || HasAnyResource(recipe, Plugin.DeepNorthTokens.Value)) { return ForgeTier.DeepNorth; } if (HasAnyResource(recipe, "flametal,flametalnew,flametalorenew,grausten,proustitepowder,sulfurstone,bonemawmeat,morgenheart,volturemeat,smokepuff,celestialfeather,charredbone,charredcogwheel,asksvinhide,gemstoneblue,gemstonegreen,gemstonered,bloodstone,jade,iolite,upgrader6armor,upgrader6weapon") || HasAnyResource(recipe, Plugin.AshlandsTokens.Value)) { return ForgeTier.Ashlands; } if (HasAnyResource(recipe, "blackcore,blackmarble,bluejute,sap,softtissue,yggdrasilwood,wisp,scalehide,mushroomjotunpuff,mushroommagecap,royaljelly,bilebag,bloodclot,carapace,mandible,seekermeat,eitr,refinedeitr,upgrader5armor,upgrader5weapon") || HasAnyResource(recipe, Plugin.MistlandsTokens.Value)) { return ForgeTier.Mistlands; } } if (station == ForgeStationKind.Forge) { if (OutputContainsAny(recipe, "bronze")) { return null; } if (ContainsExact(Plugin.PlainsRecipes.Value, normalizedRecipeName)) { return ForgeTier.Plains; } if (ContainsExact(Plugin.MountainRecipes.Value, normalizedRecipeName)) { return ForgeTier.Mountain; } if (ContainsExact(Plugin.SwampRecipes.Value, normalizedRecipeName)) { return ForgeTier.Swamp; } if (OutputContainsAny(recipe, "atgeirblackmetal,axeblackmetal,knifeblackmetal,swordblackmetal,pickaxeblackmetal,maceneedle,porcupine,shieldblackmetal,armorpadded,helmetpadded")) { return ForgeTier.Plains; } if (OutputContainsAny(recipe, "armorwolf,helmetdrake,bowdraugrfang,battleaxecrystal,knifesilver,macesilver,frostner,shieldsilver,spearwolf,swordsilver,capewolf")) { return ForgeTier.Mountain; } if (OutputContainsAny(recipe, "atgeiriron,axeiron,battleaxe,bowhuntsman,armoriron,helmetiron,maceiron,pickaxeiron,shieldbanded,shieldiron,shieldserpentscale,sledgeiron,spearelderbark,swordiron,ironnails")) { return ForgeTier.Swamp; } if (HasAnyResource(recipe, "blackmetal,blackmetalscrap,linenthread,flax,barley,loxpelt,needle,tar,upgrader4armor,upgrader4weapon") || HasAnyResource(recipe, Plugin.PlainsTokens.Value)) { return ForgeTier.Plains; } if (HasAnyResource(recipe, "silver,silverore,wolfpelt,wolffang,freezegland,obsidian,crystal,onion,trophyhatchling,upgrader3armor,upgrader3weapon") || HasAnyResource(recipe, Plugin.MountainTokens.Value)) { return ForgeTier.Mountain; } if (HasAnyResource(recipe, "iron,ironscrap,scrapiron,elderbark,root,guck,chain,ooze,bloodbag,entrails,witheredbone,trophydraugrelite,upgrader2armor,upgrader2weapon") || HasAnyResource(recipe, Plugin.SwampTokens.Value)) { return ForgeTier.Swamp; } } if (station == ForgeStationKind.Workbench) { if (ContainsExact(Plugin.BlackForestRecipes.Value, normalizedRecipeName)) { return ForgeTier.BlackForest; } if (ContainsExact(Plugin.MeadowsRecipes.Value, normalizedRecipeName)) { return ForgeTier.Meadows; } if (OutputEqualsAny(recipe, "armortrollleatherchest,armortrollleatherlegs,helmettrollleather,capetrollhide,bowfinewood,sledgestagbreaker,sledgewood,shieldbonetower,arrowbronze") || OutputStartsWithAny(recipe, "armortroll,helmettroll")) { return ForgeTier.BlackForest; } if (OutputEqualsAny(recipe, "axeflint,bow,club,hammer,hoe,knifeflint,spearflint,shieldwood,shieldwoodtower,armorragschest,armorragslegs,armorleatherchest,armorleatherlegs,helmetleather,capedeerhide,arrowwood,arrowflint,arrowfire,pickaxeantler,torch") || OutputStartsWithAny(recipe, "armortunic,armorharvester")) { return ForgeTier.Meadows; } if (HasAnyResource(recipe, "iron,ironscrap,scrapiron,elderbark,root,guck,chain,silver,wolfpelt,wolffang,freezegland,obsidian,crystal,blackmetal,blackmetalscrap,linenthread,loxpelt,needle,tar,carapace,eitr,refinedeitr,flametal,flametalnew,flametalorenew,asksvinhide,gold,bloodgold,timberwood,nornthread")) { return null; } if (HasAnyResource(recipe, "trollhide,finewood,roundlog,corewood,bronze,surtlingcore,greydwarfeye,ancientseed,upgrader1armor,upgrader1weapon")) { return ForgeTier.BlackForest; } if (HasAnyResource(recipe, "wood,stone,flint,leatherscraps,deerhide,bonefragments,resin,feathers,hardantler,deertrophy,boarmeat,boarhide,upgrader0armor,upgrader0weapon")) { return ForgeTier.Meadows; } } return null; } internal static string GetDebugName(Recipe recipe) { if ((Object)(object)recipe == (Object)null) { return "<null>"; } string text = (((Object)(object)recipe.m_item != (Object)null) ? ((Object)recipe.m_item).name : "<no item>"); return ((Object)recipe).name + " -> " + text; } private static bool OutputContainsAny(Recipe recipe, string csv) { object value; if (recipe == null) { value = null; } else { ItemDrop item = recipe.m_item; value = ((item != null) ? ((Object)item).name : null); } string output = Normalize((string)value); if (output.Length > 0) { return Split(csv).Any((string token) => output.Contains(token)); } return false; } private static bool OutputEqualsAny(Recipe recipe, string csv) { object value; if (recipe == null) { value = null; } else { ItemDrop item = recipe.m_item; value = ((item != null) ? ((Object)item).name : null); } string output = Normalize((string)value); if (output.Length > 0) { return Split(csv).Any((string token) => output == token); } return false; } private static bool OutputStartsWithAny(Recipe recipe, string csv) { object value; if (recipe == null) { value = null; } else { ItemDrop item = recipe.m_item; value = ((item != null) ? ((Object)item).name : null); } string output = Normalize((string)value); if (output.Length > 0) { return Split(csv).Any((string token) => output.StartsWith(token)); } return false; } private static bool HasAnyResource(Recipe recipe, string csv) { if (recipe?.m_resources == null) { return false; } HashSet<string> hashSet = new HashSet<string>(Split(csv)); if (hashSet.Count == 0) { return false; } Requirement[] resources = recipe.m_resources; foreach (Requirement obj in resources) { object value; if (obj == null) { value = null; } else { ItemDrop resItem = obj.m_resItem; value = ((resItem != null) ? ((Object)resItem).name : null); } string text = Normalize((string)value); if (text.Length > 0 && hashSet.Contains(text)) { return true; } } return false; } private static bool ContainsExact(string csv, string normalizedRecipeName) { return Split(csv).Any((string value) => value == normalizedRecipeName); } private static IEnumerable<string> Split(string csv) { return from value in (csv ?? string.Empty).Split(new char[4] { ',', ';', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries).Select(Normalize) where value.Length > 0 select value; } private static string Normalize(string value) { return new string((value ?? string.Empty).Where(char.IsLetterOrDigit).Select(char.ToLowerInvariant).ToArray()); } } internal static class ForgeTabs { private static readonly Dictionary<ForgeTier, Button> Buttons = new Dictionary<ForgeTier, Button>(); private static readonly MethodInfo OpenCraftTabMethod = AccessTools.Method(typeof(InventoryGui), "OnTabCraftPressed", Type.EmptyTypes, (Type[])null); private static readonly FieldInfo SelectedRecipeField = AccessTools.Field(typeof(InventoryGui), "m_selectedRecipe"); private static readonly FieldInfo AvailableRecipesField = AccessTools.Field(typeof(InventoryGui), "m_availableRecipes"); private static readonly MethodInfo SetRecipeMethod = AccessTools.Method(typeof(InventoryGui), "SetRecipe", new Type[2] { typeof(int), typeof(bool) }, (Type[])null); private static GameObject _root; private static InventoryGui _gui; private static bool _openingTierTab; private static bool _refreshingPanel; private static Scrollbar _savedRecipeScrollbar; private static float _savedRecipeScrollValue; private static bool _hasSavedRecipeScroll; private static Recipe _savedSelectedRecipe; internal static void Attach(InventoryGui gui) { //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Expected O, but got Unknown //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: 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_0193: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Expected O, but got Unknown //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Expected O, but got Unknown //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Expected O, but got Unknown //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Expected O, but got Unknown if ((Object)(object)gui == (Object)null || (Object)(object)gui.m_tabCraft == (Object)null || (Object)(object)gui.m_tabUpgrade == (Object)null || (Object)(object)_root != (Object)null) { return; } _gui = gui; GameObject gameObject = ((Component)gui.m_tabCraft).gameObject; Transform parent = gameObject.transform.parent; _root = new GameObject("TieredBlackForgeTabs", new Type[1] { typeof(RectTransform) }); RectTransform component = _root.GetComponent<RectTransform>(); ((Transform)component).SetParent(parent, false); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.pivot = new Vector2(0.5f, 0.5f); component.anchoredPosition = Vector2.zero; component.sizeDelta = Vector2.zero; ((Transform)component).SetAsLastSibling(); RectTransform component2 = ((Component)gui.m_tabUpgrade).GetComponent<RectTransform>(); CreateButton(gameObject, component2, ForgeTier.Mistlands, "Mistlands", 0); CreateButton(gameObject, component2, ForgeTier.Ashlands, "Ashlands", 1); CreateButton(gameObject, component2, ForgeTier.DeepNorth, "Deep North", 2); CreateButton(gameObject, component2, ForgeTier.Swamp, "Swamp", 0); CreateButton(gameObject, component2, ForgeTier.Mountain, "Mountain", 1); CreateButton(gameObject, component2, ForgeTier.Plains, "Plains", 2); CreateButton(gameObject, component2, ForgeTier.Meadows, "Meadows", 0); CreateButton(gameObject, component2, ForgeTier.BlackForest, "Black Forest", 1); ButtonClickedEvent originalCraftClick = gui.m_tabCraft.onClick; gui.m_tabCraft.onClick = new ButtonClickedEvent(); ((UnityEvent)gui.m_tabCraft.onClick).AddListener((UnityAction)delegate { if (!_openingTierTab) { ClearTierFilter(); } ((UnityEvent)originalCraftClick).Invoke(); RefreshSelection(); ResetRecipeScrollToTop(gui); }); ButtonClickedEvent originalUpgradeClick = gui.m_tabUpgrade.onClick; gui.m_tabUpgrade.onClick = new ButtonClickedEvent(); ((UnityEvent)gui.m_tabUpgrade.onClick).AddListener((UnityAction)delegate { ClearTierFilter(); ((UnityEvent)originalUpgradeClick).Invoke(); RefreshSelection(); ResetRecipeScrollToTop(gui); }); _root.SetActive(false); RefreshSelection(); } private static void CreateButton(GameObject template, RectTransform upgradeRect, ForgeTier tier, string label, int index) { //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_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: 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_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_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_011d: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Expected O, but got Unknown //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Expected O, but got Unknown //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) GameObject val = Object.Instantiate<GameObject>(template, _root.transform, false); ((Object)val).name = $"TierTab_{tier}"; val.SetActive(true); Component[] components = val.GetComponents<Component>(); foreach (Component val2 in components) { if ((Object)(object)val2 != (Object)null && ((object)val2).GetType().Name.IndexOf("Tab", StringComparison.OrdinalIgnoreCase) >= 0 && !(val2 is Button)) { Object.Destroy((Object)(object)val2); } } RectTransform component = val.GetComponent<RectTransform>(); Rect rect = upgradeRect.rect; float num = Mathf.Max(32f, ((Rect)(ref rect)).height); rect = upgradeRect.rect; float num2 = ((Rect)(ref rect)).width + 6f + (float)index * 106f; component.anchorMin = upgradeRect.anchorMin; component.anchorMax = upgradeRect.anchorMax; component.pivot = upgradeRect.pivot; component.sizeDelta = new Vector2(100f, num); component.anchoredPosition = upgradeRect.anchoredPosition + new Vector2(num2, 0f); CreateUnderline(val, template.transform.parent); TMP_Text componentInChildren = val.GetComponentInChildren<TMP_Text>(true); if ((Object)(object)componentInChildren != (Object)null) { TMP_Text componentInChildren2 = template.GetComponentInChildren<TMP_Text>(true); if ((Object)(object)componentInChildren2 != (Object)null) { componentInChildren.font = componentInChildren2.font; componentInChildren.fontSharedMaterial = componentInChildren2.fontSharedMaterial; componentInChildren.fontStyle = componentInChildren2.fontStyle; componentInChildren.alignment = componentInChildren2.alignment; ((Graphic)componentInChildren).color = ((Graphic)componentInChildren2).color; componentInChildren.characterSpacing = componentInChildren2.characterSpacing; componentInChildren.fontSizeMax = componentInChildren2.fontSize; } componentInChildren.text = label.ToUpperInvariant(); componentInChildren.enableAutoSizing = true; componentInChildren.fontSizeMin = 10f; } Button component2 = val.GetComponent<Button>(); component2.onClick = new ButtonClickedEvent(); ((UnityEvent)component2.onClick).AddListener((UnityAction)delegate { Select(tier); }); Buttons[tier] = component2; } private static void CreateUnderline(GameObject tab, Transform nativeTabsParent) { //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) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_0130: 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_0104: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("TierTabUnderline", new Type[2] { typeof(RectTransform), typeof(Image) }); val.transform.SetParent(tab.transform, false); val.transform.SetAsLastSibling(); RectTransform component = val.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0f, 0f); component.anchorMax = new Vector2(1f, 0f); component.pivot = new Vector2(0.5f, 0f); component.anchoredPosition = new Vector2(0f, -1f); component.sizeDelta = new Vector2(12f, 2f); Image component2 = val.GetComponent<Image>(); ((Graphic)component2).raycastTarget = false; Image val2 = FindNativeUnderline(nativeTabsParent); if ((Object)(object)val2 != (Object)null) { component2.sprite = val2.sprite; component2.overrideSprite = val2.overrideSprite; ((Graphic)component2).material = ((Graphic)val2).material; ((Graphic)component2).color = ((Graphic)val2).color; component2.type = val2.type; component2.preserveAspect = val2.preserveAspect; } else { ((Graphic)component2).color = new Color(0.9f, 0.58f, 0.08f, 1f); } } private static Image FindNativeUnderline(Transform nativeTabsParent) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)nativeTabsParent == (Object)null) { return null; } Image result = null; float num = float.MaxValue; Image[] componentsInChildren = ((Component)nativeTabsParent).GetComponentsInChildren<Image>(true); foreach (Image val in componentsInChildren) { if ((Object)(object)val == (Object)null || (Object)(object)((Graphic)val).rectTransform == (Object)null) { continue; } Rect rect = ((Graphic)val).rectTransform.rect; float num2 = Mathf.Abs(((Rect)(ref rect)).width); rect = ((Graphic)val).rectTransform.rect; float num3 = Mathf.Abs(((Rect)(ref rect)).height); if (!(num3 < 0.5f) && !(num3 > 8f) && !(num2 < 30f) && !(num2 < num3 * 5f) && !(((Graphic)val).color.a < 0.1f)) { float num4 = ((((Graphic)val).color.r >= ((Graphic)val).color.b) ? 0f : 20f); float num5 = num3 + num4 - Mathf.Min(num2, 500f) * 0.001f; if (!(num5 >= num)) { result = val; num = num5; } } } return result; } private static void Select(ForgeTier tier) { ForgeStationKind openStationKind = TierState.GetOpenStationKind(); if (!TierState.IsTierForStation(tier, openStationKind)) { return; } TierState.Selected = tier; _openingTierTab = true; try { if (OpenCraftTabMethod != null) { OpenCraftTabMethod.Invoke(_gui, null); } else { ((UnityEvent)_gui.m_tabCraft.onClick).Invoke(); } } finally { _openingTierTab = false; } RefreshSelection(); ResetRecipeScrollToTop(_gui); } private static void ClearTierFilter() { TierState.Selected = null; RefreshSelection(); } private static void RefreshSelection() { foreach (KeyValuePair<ForgeTier, Button> button in Buttons) { if ((Object)(object)button.Value != (Object)null) { ((Selectable)button.Value).interactable = !TierState.Selected.HasValue || button.Key != TierState.Selected.Value; } } if (!((Object)(object)_gui == (Object)null) && TierState.Selected.HasValue) { if ((Object)(object)_gui.m_tabCraft != (Object)null) { ((Selectable)_gui.m_tabCraft).interactable = !_refreshingPanel; } if ((Object)(object)_gui.m_tabUpgrade != (Object)null) { ((Selectable)_gui.m_tabUpgrade).interactable = true; } } } internal static void SyncVisibility() { if ((Object)(object)_root == (Object)null) { return; } ForgeStationKind openStationKind = TierState.GetOpenStationKind(); bool flag = openStationKind != ForgeStationKind.None; if (TierState.Selected.HasValue && !TierState.IsTierForStation(TierState.Selected.Value, openStationKind)) { TierState.Selected = null; } if (_root.activeSelf != flag) { _root.SetActive(flag); } foreach (KeyValuePair<ForgeTier, Button> button in Buttons) { if ((Object)(object)button.Value != (Object)null) { ((Component)button.Value).gameObject.SetActive(flag && TierState.IsTierForStation(button.Key, openStationKind)); } } if (flag) { RefreshSelection(); } } internal static bool IsBiomeCrafting(InventoryGui gui) { if ((Object)(object)gui != (Object)null && (Object)(object)gui == (Object)(object)_gui && TierState.Selected.HasValue) { return TierState.IsTierForStation(TierState.Selected.Value, TierState.GetOpenStationKind()); } return false; } internal static bool BeginPanelRefresh(InventoryGui gui) { if (!IsBiomeCrafting(gui) || _refreshingPanel) { return false; } CaptureRecipeScrollPosition(gui); _refreshingPanel = true; if ((Object)(object)gui.m_tabCraft != (Object)null) { ((Selectable)gui.m_tabCraft).interactable = false; } if ((Object)(object)gui.m_tabUpgrade != (Object)null) { ((Selectable)gui.m_tabUpgrade).interactable = true; } return true; } internal static void EndPanelRefresh(bool ownsRefresh, bool restore) { if (!ownsRefresh) { return; } try { if (restore && IsBiomeCrafting(_gui)) { RestoreSelectedRecipe(); RestoreRecipeScrollPosition(); } } finally { _hasSavedRecipeScroll = false; _savedSelectedRecipe = null; _savedRecipeScrollbar = null; _refreshingPanel = false; SyncVisibility(); } } internal static void CaptureRecipeScrollPosition(InventoryGui gui) { _hasSavedRecipeScroll = false; _savedRecipeScrollbar = null; _savedSelectedRecipe = null; if ((Object)(object)gui == (Object)null || !TierState.Selected.HasValue) { return; } try { if (SelectedRecipeField != null) { _savedSelectedRecipe = GetRecipeFromEntry(SelectedRecipeField.GetValue(gui)); } } catch (Exception ex) { Plugin.Log.LogDebug((object)("Unable to capture the selected recipe: " + ex.Message)); } Scrollbar val = FindRecipeScrollbar(gui); if (!((Object)(object)val == (Object)null)) { _savedRecipeScrollbar = val; _savedRecipeScrollValue = val.value; _hasSavedRecipeScroll = true; } } private static Scrollbar FindRecipeScrollbar(InventoryGui gui) { //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Invalid comparison between Unknown and I4 //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Invalid comparison between Unknown and I4 if ((Object)(object)gui == (Object)null) { return null; } Scrollbar result = null; int num = int.MinValue; Scrollbar[] componentsInChildren = ((Component)gui).GetComponentsInChildren<Scrollbar>(true); foreach (Scrollbar val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { string text = string.Empty; Transform val2 = ((Component)val).transform; while ((Object)(object)val2 != (Object)null && (Object)(object)val2 != (Object)(object)((Component)gui).transform.parent) { text = text + "/" + ((Object)val2).name.ToLowerInvariant(); val2 = val2.parent; } int num2 = 0; if (text.Contains("recipe")) { num2 += 100; } if (text.Contains("craft")) { num2 += 50; } if (text.Contains("scroll")) { num2 += 10; } if (((Component)val).gameObject.activeInHierarchy) { num2 += 10; } if ((int)val.direction == 2 || (int)val.direction == 3) { num2 += 25; } if (num2 > num) { result = val; num = num2; } } } return result; } private static void ResetRecipeScrollToTop(InventoryGui gui) { //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Invalid comparison between Unknown and I4 if ((Object)(object)gui == (Object)null) { return; } Scrollbar val = FindRecipeScrollbar(gui); if ((Object)(object)val == (Object)null) { return; } ScrollRect[] componentsInChildren = ((Component)gui).GetComponentsInChildren<ScrollRect>(true); foreach (ScrollRect val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2.verticalScrollbar != (Object)(object)val)) { if ((Object)(object)val2.content != (Object)null) { LayoutRebuilder.ForceRebuildLayoutImmediate(val2.content); } val2.StopMovement(); val2.verticalNormalizedPosition = 1f; return; } } val.value = (((int)val.direction == 3) ? 0f : 1f); } private static void RestoreRecipeScrollPosition() { if (_hasSavedRecipeScroll && !((Object)(object)_gui == (Object)null)) { Scrollbar val = _savedRecipeScrollbar; if ((Object)(object)val == (Object)null) { val = FindRecipeScrollbar(_gui); } if (!((Object)(object)val == (Object)null)) { val.value = _savedRecipeScrollValue; } } } private static Recipe GetRecipeFromEntry(object entry) { if (entry == null) { return null; } Recipe val = (Recipe)((entry is Recipe) ? entry : null); if (val != null) { return val; } Type type = entry.GetType(); PropertyInfo propertyInfo = AccessTools.Property(type, "Recipe") ?? AccessTools.Property(type, "Key"); if (propertyInfo != null) { object? value = propertyInfo.GetValue(entry, null); return (Recipe)((value is Recipe) ? value : null); } object? obj = (AccessTools.Field(type, "m_recipe") ?? AccessTools.Field(type, "Recipe"))?.GetValue(entry); return (Recipe)((obj is Recipe) ? obj : null); } private static void RestoreSelectedRecipe() { if ((Object)(object)_gui == (Object)null || (Object)(object)_savedSelectedRecipe == (Object)null) { return; } try { if (SetRecipeMethod == null || AvailableRecipesField == null) { Plugin.Log.LogWarning((object)"Recipe selection API unavailable; leaving the rebuilt recipe list unchanged."); } else { if (!(AvailableRecipesField.GetValue(_gui) is IList list)) { return; } for (int i = 0; i < list.Count; i++) { Recipe recipeFromEntry = GetRecipeFromEntry(list[i]); if (!((Object)(object)recipeFromEntry == (Object)null) && (!((Object)(object)recipeFromEntry != (Object)(object)_savedSelectedRecipe) || string.Equals(((Object)recipeFromEntry).name, ((Object)_savedSelectedRecipe).name, StringComparison.Ordinal))) { SetRecipeMethod.Invoke(_gui, new object[2] { i, false }); return; } } Plugin.Log.LogDebug((object)"Crafted recipe no longer available in the active tab."); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Unable to restore the selected recipe after crafting: " + ex.Message)); } } } [HarmonyPatch(typeof(InventoryGui), "Awake")] internal static class InventoryGuiAwakePatch { private static void Postfix(InventoryGui __instance) { ForgeTabs.Attach(__instance); } } [HarmonyPatch(typeof(InventoryGui), "UpdateCraftingPanel", new Type[] { typeof(bool) })] internal static class UpdateCraftingPanelPatch { private static void Prefix(InventoryGui __instance, out bool __state) { __state = ForgeTabs.BeginPanelRefresh(__instance); } private static void Postfix(ref bool __state) { bool ownsRefresh = __state; __state = false; ForgeTabs.EndPanelRefresh(ownsRefresh, restore: true); ForgeTabs.SyncVisibility(); } private static Exception Finalizer(Exception __exception, bool __state) { ForgeTabs.EndPanelRefresh(__state, restore: false); return __exception; } } [HarmonyPatch] internal static class InventoryGuiBiomeCraftModePatch { private static IEnumerable<MethodBase> TargetMethods() { string[] array = new string[3] { "InCraftTab", "InUpradeTab", "InUpgradeTab" }; foreach (string text in array) { MethodInfo methodInfo = AccessTools.Method(typeof(InventoryGui), text, Type.EmptyTypes, (Type[])null); if (methodInfo != null && methodInfo.ReturnType == typeof(bool)) { yield return methodInfo; } } } private static void Postfix(InventoryGui __instance, MethodBase __originalMethod, ref bool __result) { if (ForgeTabs.IsBiomeCrafting(__instance)) { __result = __originalMethod.Name == "InCraftTab"; } } } [HarmonyPatch(typeof(InventoryGui), "UpdateRecipeList", new Type[] { typeof(List<Recipe>) })] internal static class UpdateRecipeListPatch { [HarmonyPriority(200)] private static void Prefix(ref List<Recipe> recipes) { ForgeStationKind station = TierState.GetOpenStationKind(); if (recipes == null || station == ForgeStationKind.None) { return; } if (TierState.Selected.HasValue && !TierState.IsTierForStation(TierState.Selected.Value, station)) { TierState.Selected = null; } if (!TierState.Selected.HasValue) { return; } int count = recipes.Count; foreach (Recipe recipe in recipes) { ForgeTier? tier = RecipeClassifier.GetTier(recipe, station); Plugin.Log.LogDebug((object)("Classification " + RecipeClassifier.GetDebugName(recipe) + " = " + (tier.HasValue ? tier.Value.ToString() : "non classee"))); } recipes = recipes.Where((Recipe recipe) => TierState.Matches(recipe, station)).ToList(); Plugin.Log.LogInfo((object)$"Onglet {TierState.Selected.Value}: {recipes.Count}/{count} recettes affichees."); } } }