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 Shack Blast Furnace Ascended v1.0.0
ShackBlastFurnace.dll
Decompiled 6 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using UnityEngine; [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("ShackBlastFurnace")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("ShackBlastFurnace")] [assembly: AssemblyTitle("ShackBlastFurnace")] [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 TheShack.BlastFurnace { [BepInPlugin("theshack.blastfurnace", "Shack Blast Furnace Ascended", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] [SynchronizationMode(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "theshack.blastfurnace"; public const string PluginName = "Shack Blast Furnace Ascended"; public const string PluginVersion = "1.0.0"; internal static ManualLogSource Log; private void Awake() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Settings.Bind(((BaseUnityPlugin)this).Config); if (!Furnaces.Ready) { Log.LogError((object)"Shack Blast Furnace Ascended can't find Smelter.GetQueuedOre in this game version; the blast furnace stays as the game has it."); return; } Harmony val = new Harmony("theshack.blastfurnace"); try { val.PatchAll(Assembly.GetExecutingAssembly()); } catch (Exception arg) { val.UnpatchSelf(); Log.LogError((object)string.Format("{0} could not hook into this game version; the blast furnace stays as the game has it. {1}", "Shack Blast Furnace Ascended", arg)); return; } ((BaseUnityPlugin)this).Config.SettingChanged += delegate { Furnaces.ApplyToLoaded(); }; SynchronizationManager.OnConfigurationSynchronized += delegate { Furnaces.ApplyToLoaded(); }; Log.LogInfo((object)string.Format("{0} {1} ready ({2:0.##}x speed, {3:0.##}x coal).", "Shack Blast Furnace Ascended", "1.0.0", Settings.Speed.Value, Settings.Coal.Value)); } } internal static class Settings { public static ConfigEntry<bool> Enabled; public static ConfigEntry<float> Speed; public static ConfigEntry<float> Coal; public static ConfigEntry<int> OreCapacity; public static ConfigEntry<int> CoalCapacity; public static readonly Dictionary<string, ConfigEntry<bool>> Ores = new Dictionary<string, ConfigEntry<bool>>(); public static void Bind(ConfigFile config) { int order = 100; Enabled = Bind<bool>("1 - General", "Enabled", value: true, "The blast furnace takes the ores ticked under \"2 - Ores\" and smelts them at the speed below. Off: the blast furnace works as in the base game (any of those ores already in it still finish)."); Speed = Bind<float>("1 - General", "Speed", 4f, "How many times faster than the regular furnace the blast furnace smelts those ores. 4 = four times as fast; 1 = as slow as the regular furnace.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 20f)); Coal = Bind<float>("1 - General", "Coal per ore", 1f, "Coal those ores burn, compared with the regular furnace. 1 = the same coal per ore (it just burns faster), 0.5 = half, 0 = none (it still needs some coal in it to run).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f)); OreCapacity = Bind<int>("1 - General", "Ore capacity", 0, "How much ore the blast furnace holds, all kinds together (black metal and flametal too). 0 = the game's own.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100)); CoalCapacity = Bind<int>("1 - General", "Coal capacity", 0, "How much coal the blast furnace holds. 0 = the game's own.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 200)); Ores["CopperOre"] = Bind<bool>("2 - Ores", "Copper ore", value: true, "The blast furnace smelts copper ore into copper."); Ores["TinOre"] = Bind<bool>("2 - Ores", "Tin ore", value: true, "The blast furnace smelts tin ore into tin."); Ores["IronScrap"] = Bind<bool>("2 - Ores", "Scrap iron", value: true, "The blast furnace smelts scrap iron into iron."); Ores["SilverOre"] = Bind<bool>("2 - Ores", "Silver ore", value: true, "The blast furnace smelts silver ore into silver."); ConfigEntry<T> Bind<T>(string section, string key, T value, string description, AcceptableValueBase range = null) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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_0040: Expected O, but got Unknown //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown return config.Bind<T>(section, key, value, new ConfigDescription(description, range, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, Order = order-- } })); } } } internal static class Furnaces { private const string BlastFurnaceName = "$piece_blastfurnace"; private static readonly MethodInfo GetQueuedOre = AccessTools.Method(typeof(Smelter), "GetQueuedOre", (Type[])null, (Type[])null); private static readonly Func<Smelter, string> QueuedOre = ((GetQueuedOre != null) ? AccessTools.MethodDelegate<Func<Smelter, string>>(GetQueuedOre, (object)null, true) : null); private static Smelter regular; private static Smelter blast; public static bool Ready => QueuedOre != null; public static bool IsBlastFurnace(Smelter smelter) { return smelter.m_name == "$piece_blastfurnace"; } private static Smelter Regular() { return Prefab(ref regular, "smelter"); } private static Smelter Blast() { return Prefab(ref blast, "blastfurnace"); } private static Smelter Prefab(ref Smelter cache, string name) { if ((Object)(object)cache == (Object)null && (Object)(object)ZNetScene.instance != (Object)null) { GameObject prefab = ZNetScene.instance.GetPrefab(name); cache = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<Smelter>() : null); } return cache; } public static ItemConversion RegularConversion(string ore) { Smelter val = Regular(); if ((Object)(object)val == (Object)null || !Settings.Ores.ContainsKey(ore)) { return null; } return val.m_conversion.Find((ItemConversion c) => (Object)(object)c.m_from != (Object)null && ((Object)((Component)c.m_from).gameObject).name == ore); } public static void Apply(Smelter furnace) { Smelter val = Blast(); if ((Object)(object)Regular() == (Object)null || (Object)(object)val == (Object)null) { return; } furnace.m_conversion.RemoveAll((ItemConversion c) => (Object)(object)c.m_from != (Object)null && Settings.Ores.ContainsKey(((Object)((Component)c.m_from).gameObject).name)); if (Settings.Enabled.Value) { foreach (KeyValuePair<string, ConfigEntry<bool>> ore in Settings.Ores) { ItemConversion val2 = RegularConversion(ore.Key); if (ore.Value.Value && val2 != null) { furnace.m_conversion.Add(val2); } } } bool value = Settings.Enabled.Value; furnace.m_maxOre = ((value && Settings.OreCapacity.Value > 0) ? Settings.OreCapacity.Value : val.m_maxOre); furnace.m_maxFuel = ((value && Settings.CoalCapacity.Value > 0) ? Settings.CoalCapacity.Value : val.m_maxFuel); } public static void ApplyToLoaded() { Smelter[] array = Object.FindObjectsByType<Smelter>((FindObjectsSortMode)0); foreach (Smelter val in array) { if (IsBlastFurnace(val)) { Apply(val); } } } public static float SecPerProduct(Smelter smelter) { if (!IsFast(smelter)) { return smelter.m_secPerProduct; } return Regular().m_secPerProduct / Settings.Speed.Value; } public static float CoalPerOre(Smelter smelter) { if (!IsFast(smelter)) { return smelter.m_fuelPerProduct; } return (float)Regular().m_fuelPerProduct * Settings.Coal.Value; } public static bool IsFast(Smelter smelter) { if (Settings.Enabled.Value && IsBlastFurnace(smelter) && (Object)(object)Regular() != (Object)null) { return Settings.Ores.ContainsKey(QueuedOre(smelter)); } return false; } public static void LogRates() { Smelter val = Regular(); Smelter val2 = Blast(); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { Plugin.Log.LogWarning((object)"Can't find the regular furnace or the blast furnace (the game changed); the blast furnace stays as the game has it."); return; } string[] array = Settings.Ores.Keys.Where((string ore) => RegularConversion(ore) == null).ToArray(); if (array.Length != 0) { Plugin.Log.LogWarning((object)("The regular furnace doesn't take " + string.Join(", ", array) + " (the game changed); the blast furnace won't either.")); } Plugin.Log.LogInfo((object)($"Regular furnace: {val.m_secPerProduct:0.#} s and {val.m_fuelPerProduct} coal per ore. " + $"Blast furnace: {val2.m_secPerProduct:0.#} s and {val2.m_fuelPerProduct} coal per ore, holds " + $"{val2.m_maxOre} ore and {val2.m_maxFuel} coal; the regular furnace's ores take " + $"{val.m_secPerProduct / Settings.Speed.Value:0.##} s and {(float)val.m_fuelPerProduct * Settings.Coal.Value:0.##} coal there.")); } } [HarmonyPatch(typeof(ZNetScene), "Awake")] internal static class ZNetScene_Awake { private static void Postfix() { Furnaces.LogRates(); } } [HarmonyPatch(typeof(Smelter), "Awake")] internal static class Smelter_Awake { private static void Postfix(Smelter __instance) { if (Furnaces.IsBlastFurnace(__instance)) { Furnaces.Apply(__instance); } } } [HarmonyPatch(typeof(Smelter), "GetItemConversion")] internal static class Smelter_GetItemConversion { private static void Postfix(Smelter __instance, string itemName, ref ItemConversion __result) { if (__result == null && Furnaces.IsBlastFurnace(__instance)) { __result = Furnaces.RegularConversion(itemName); } } } [HarmonyPatch] internal static class Smelter_Hover { private static Smelter swapped; private static float savedSecs; private static int savedCoal; private static IEnumerable<MethodBase> TargetMethods() { return from method in ((IEnumerable<string>)new string[3] { "OnHoverAddOre", "OnHoverAddFuel", "OnHoverEmptyOre" }).Select((Func<string, MethodBase>)((string name) => AccessTools.Method(typeof(Smelter), name, (Type[])null, (Type[])null))) where method != null select method; } [HarmonyPriority(800)] private static void Prefix(Smelter __instance) { if (!((Object)(object)swapped != (Object)null) && Furnaces.IsFast(__instance)) { swapped = __instance; savedSecs = __instance.m_secPerProduct; savedCoal = __instance.m_fuelPerProduct; float secPerProduct = Furnaces.SecPerProduct(__instance); int fuelPerProduct = Mathf.RoundToInt(Furnaces.CoalPerOre(__instance)); __instance.m_secPerProduct = secPerProduct; __instance.m_fuelPerProduct = fuelPerProduct; } } private static void Finalizer() { if (!((Object)(object)swapped == (Object)null)) { if (Object.op_Implicit((Object)(object)swapped)) { swapped.m_secPerProduct = savedSecs; swapped.m_fuelPerProduct = savedCoal; } swapped = null; } } } [HarmonyPatch(typeof(Smelter), "UpdateSmelter")] internal static class Smelter_UpdateSmelter { private static readonly FieldInfo SecField = AccessTools.Field(typeof(Smelter), "m_secPerProduct"); private static readonly FieldInfo FuelField = AccessTools.Field(typeof(Smelter), "m_fuelPerProduct"); private static readonly MethodInfo SecCall = AccessTools.Method(typeof(Furnaces), "SecPerProduct", (Type[])null, (Type[])null); private static readonly MethodInfo CoalCall = AccessTools.Method(typeof(Furnaces), "CoalPerOre", (Type[])null, (Type[])null); private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> list = new List<CodeInstruction>(instructions); List<CodeInstruction> list2 = new List<CodeInstruction>(list); int num = 0; int num2 = 0; for (int i = 0; i < list2.Count; i++) { if (list2[i].opcode != OpCodes.Ldfld) { continue; } FieldInfo fieldInfo = list2[i].operand as FieldInfo; MethodInfo methodInfo = ((fieldInfo == SecField) ? SecCall : ((fieldInfo == FuelField) ? CoalCall : null)); if (!(methodInfo == null)) { CodeInstruction val = list2[i].Clone(); val.opcode = OpCodes.Call; val.operand = methodInfo; list2[i] = val; if (methodInfo == SecCall) { num++; } else { num2++; } } } if (num != 3 || num2 != 1) { Plugin.Log.LogWarning((object)($"Smelter.UpdateSmelter reads the smelting time {num} times and the coal {num2} times instead of " + "3 and 1 (the game changed); the regular furnace's ores smelt at the blast furnace's own speed.")); return list; } return list2; } } }