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 SmelterUnlimited v1.0.1
plugins/SmelterUnlimited.dll
Decompiled a month agousing System; 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 HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("SmelterUnlimited")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyInformationalVersion("1.0.1")] [assembly: AssemblyProduct("SmelterUnlimited")] [assembly: AssemblyTitle("SmelterUnlimited")] [assembly: AssemblyVersion("1.0.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 SmelterUnlimited { [BepInPlugin("com.honeymanmods.smelterunlimited", "SmelterUnlimited", "1.0.1")] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "com.honeymanmods.smelterunlimited"; public const string PluginName = "SmelterUnlimited"; public const string PluginVersion = "1.0.1"; internal static ConfigEntry<KeyCode> BatchModifierKey; internal static ConfigEntry<int> BatchSize; internal static ConfigEntry<string> ContainerBlacklist; internal static ConfigEntry<float> ContainerRange; internal static ConfigEntry<int> MaxFuel; internal static ConfigEntry<int> MaxOre; internal static ConfigEntry<bool> PullFromContainers; internal static ConfigEntry<string> Stations; private static HashSet<string> _stations = new HashSet<string>(); private static HashSet<string> _blacklist = new HashSet<string>(); private Harmony _harmony; private void Awake() { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Expected O, but got Unknown //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Expected O, but got Unknown //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Expected O, but got Unknown BatchModifierKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "BatchModifierKey", (KeyCode)304, "Hold this key while pressing Use (E) on a station to add BatchSize items at once."); BatchSize = ((BaseUnityPlugin)this).Config.Bind<int>("General", "BatchSize", 10, new ConfigDescription("How many items one BatchModifierKey + E press adds.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), Array.Empty<object>())); ContainerBlacklist = ((BaseUnityPlugin)this).Config.Bind<string>("General", "ContainerBlacklist", "FineWood,RoundLog", "Comma-separated item prefab names that are never taken from chests (they can still be added from your own inventory). Default protects Fine wood and Core wood from being burned in the kiln."); ContainerRange = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ContainerRange", 10f, new ConfigDescription("Radius in meters around the station in which chests are searched for missing fuel/ore.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f), Array.Empty<object>())); MaxFuel = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MaxFuel", 1000, new ConfigDescription("Fuel (coal) capacity. Vanilla: 20 for the smelter and blast furnace.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10000), Array.Empty<object>())); MaxOre = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MaxOre", 1000, new ConfigDescription("Ore capacity. For the charcoal kiln this is the wood capacity. Vanilla: 10 for the smelter and blast furnace, 25 for the kiln.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10000), Array.Empty<object>())); PullFromContainers = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "PullFromContainers", true, "true = when you don't carry enough fuel/ore, the missing amount is taken from nearby chests."); Stations = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Stations", "smelter,charcoal_kiln,blastfurnace", "Comma-separated prefab names of the smelter-type stations this mod applies to. Other options: eitrrefinery, windmill, piece_spinningwheel."); Stations.SettingChanged += delegate { _stations = ParseList(Stations.Value); }; ContainerBlacklist.SettingChanged += delegate { _blacklist = ParseList(ContainerBlacklist.Value); }; _stations = ParseList(Stations.Value); _blacklist = ParseList(ContainerBlacklist.Value); _harmony = new Harmony("com.honeymanmods.smelterunlimited"); _harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} v{1} loaded - ore cap {2}, fuel cap {3}, batch {4}.", "SmelterUnlimited", "1.0.1", MaxOre.Value, MaxFuel.Value, BatchSize.Value)); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private static HashSet<string> ParseList(string value) { return new HashSet<string>(from s in (value ?? "").Split(new char[1] { ',' }) select s.Trim() into s where s.Length > 0 select s, StringComparer.OrdinalIgnoreCase); } internal static bool IsStation(Smelter smelter) { if ((Object)(object)smelter != (Object)null) { return _stations.Contains(Utils.GetPrefabName(((Component)smelter).gameObject)); } return false; } internal static bool IsBlacklisted(ItemDrop item) { return _blacklist.Contains(((Object)((Component)item).gameObject).name); } } internal static class SmelterLogic { private static readonly MethodInfo OnAddOreMethod = AccessTools.Method(typeof(Smelter), "OnAddOre", (Type[])null, (Type[])null); private static readonly MethodInfo OnAddFuelMethod = AccessTools.Method(typeof(Smelter), "OnAddFuel", (Type[])null, (Type[])null); internal static readonly Func<Smelter, int> GetQueueSize = AccessTools.MethodDelegate<Func<Smelter, int>>(AccessTools.Method(typeof(Smelter), "GetQueueSize", (Type[])null, (Type[])null), (object)null, true); internal static readonly Func<Smelter, float> GetFuel = AccessTools.MethodDelegate<Func<Smelter, float>>(AccessTools.Method(typeof(Smelter), "GetFuel", (Type[])null, (Type[])null), (object)null, true); internal static readonly Action<Smelter, float> SetFuel = AccessTools.MethodDelegate<Action<Smelter, float>>(AccessTools.Method(typeof(Smelter), "SetFuel", (Type[])null, (Type[])null), (object)null, true); internal static readonly Func<Smelter, string> GetQueuedOre = AccessTools.MethodDelegate<Func<Smelter, string>>(AccessTools.Method(typeof(Smelter), "GetQueuedOre", (Type[])null, (Type[])null), (object)null, true); internal static readonly Action<Smelter> RemoveOneOre = AccessTools.MethodDelegate<Action<Smelter>>(AccessTools.Method(typeof(Smelter), "RemoveOneOre", (Type[])null, (Type[])null), (object)null, true); internal static readonly FieldRef<Smelter, ZNetView> SmelterNView = AccessTools.FieldRefAccess<Smelter, ZNetView>("m_nview"); private static readonly Func<Container, long, bool> ContainerCheckAccess = AccessTools.MethodDelegate<Func<Container, long, bool>>(AccessTools.Method(typeof(Container), "CheckAccess", (Type[])null, (Type[])null), (object)null, true); private static readonly FieldRef<Container, ZNetView> ContainerNView = AccessTools.FieldRefAccess<Container, ZNetView>("m_nview"); internal static readonly HashSet<Container> Containers = new HashSet<Container>(); private static bool _busy; internal static void ApplyCaps(Smelter smelter) { smelter.m_maxOre = Plugin.MaxOre.Value; if ((Object)(object)smelter.m_fuelItem != (Object)null) { smelter.m_maxFuel = Plugin.MaxFuel.Value; } } internal static string BatchHint() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) int value = Plugin.BatchSize.Value; if (value <= 1) { return ""; } string text = ((object)Plugin.BatchModifierKey.Value/*cast due to .constrained prefix*/).ToString(); if (text.StartsWith("Left")) { text = text.Substring(4); } else if (text.StartsWith("Right")) { text = text.Substring(5); } return Localization.instance.Localize($"\n[<color=yellow><b>{text} + $KEY_Use</b></color>] Add {value}"); } internal static bool HandleAdd(Smelter smelter, object sw, object user, object item, bool fuel, ref bool result) { //IL_008b: Unknown result type (might be due to invalid IL or missing references) if (_busy || !Plugin.IsStation(smelter)) { return true; } ApplyCaps(smelter); if (item != null) { return true; } Player val = (Player)((user is Player) ? user : null); if ((Object)(object)val == (Object)null || (Object)(object)val != (Object)(object)Player.m_localPlayer) { return true; } if (fuel && (Object)(object)smelter.m_fuelItem == (Object)null) { return true; } int num = (fuel ? Mathf.FloorToInt((float)smelter.m_maxFuel - GetFuel(smelter)) : (smelter.m_maxOre - GetQueueSize(smelter))); if (num <= 0) { return true; } int num2 = Math.Min((!ZInput.GetKey(Plugin.BatchModifierKey.Value, false)) ? 1 : Plugin.BatchSize.Value, num); if (Plugin.PullFromContainers.Value) { if (fuel) { TopUpFuel(smelter, val, num2); } else { TopUpOre(smelter, val, num2); } } MethodInfo methodInfo = (fuel ? OnAddFuelMethod : OnAddOreMethod); object[] parameters = new object[3] { sw, user, null }; int i = 0; _busy = true; try { for (; i < num2; i++) { if (!(bool)methodInfo.Invoke(smelter, parameters)) { break; } } } finally { _busy = false; } result = i > 0; return false; } private static void TopUpFuel(Smelter smelter, Player player, int want) { ItemDrop fuelItem = smelter.m_fuelItem; int num = ((Humanoid)player).GetInventory().CountItems(fuelItem.m_itemData.m_shared.m_name, -1, true); if (num < want) { PullToPlayer(smelter, player, fuelItem, want - num); } } private static void TopUpOre(Smelter smelter, Player player, int want) { Inventory inventory = ((Humanoid)player).GetInventory(); List<ItemDrop> source = (from c in smelter.m_conversion where (Object)(object)c?.m_from != (Object)null select c.m_from).ToList(); int num = source.Sum((ItemDrop o) => inventory.CountItems(o.m_itemData.m_shared.m_name, -1, true)); int num2 = want - num; if (num2 <= 0) { return; } foreach (ItemDrop item in source.OrderByDescending((ItemDrop o) => inventory.CountItems(o.m_itemData.m_shared.m_name, -1, true) > 0)) { num2 -= PullToPlayer(smelter, player, item, num2); if (num2 <= 0) { break; } } } private static int PullToPlayer(Smelter smelter, Player player, ItemDrop item, int needed) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) if (needed <= 0 || Plugin.IsBlacklisted(item)) { return 0; } string name = item.m_itemData.m_shared.m_name; GameObject gameObject = ((Component)item).gameObject; Inventory inventory = ((Humanoid)player).GetInventory(); int num = 0; foreach (Container item2 in NearbyContainers(((Component)smelter).transform.position, player.GetPlayerID())) { Inventory inventory2 = item2.GetInventory(); int num2 = Math.Min(needed - num, inventory2.CountItems(name, -1, true)); while (num2 > 0 && !inventory.CanAddItem(gameObject, num2)) { num2--; } if (num2 > 0) { ZNetView val = ContainerNView.Invoke(item2); if (!val.IsOwner()) { val.ClaimOwnership(); } int num3 = inventory.CountItems(name, -1, true); inventory2.RemoveItem(name, num2, -1, true); AddStacks(inventory, gameObject, num2); int num4 = inventory.CountItems(name, -1, true) - num3; if (num4 < num2) { AddStacks(inventory2, gameObject, num2 - num4); } num += num4; if (num >= needed || num4 < num2) { break; } } } return num; } private static IEnumerable<Container> NearbyContainers(Vector3 center, long playerId) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) float range = Plugin.ContainerRange.Value; Containers.RemoveWhere((Container c) => (Object)(object)c == (Object)null); return (from c in Containers where Vector3.Distance(((Component)c).transform.position, center) <= range && IsUsable(c, playerId) orderby Vector3.Distance(((Component)c).transform.position, center) select c).ToList(); } private static bool IsUsable(Container container, long playerId) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) ZNetView val = ContainerNView.Invoke(container); if ((Object)(object)val == (Object)null || !val.IsValid() || container.GetInventory() == null) { return false; } if (container.IsInUse() || (Object)(object)((Component)container).GetComponent<TombStone>() != (Object)null) { return false; } if (!ContainerCheckAccess(container, playerId)) { return false; } if (container.m_checkGuardStone && !PrivateArea.CheckAccess(((Component)container).transform.position, 0f, false, false)) { return false; } return true; } private static void AddStacks(Inventory inventory, GameObject prefab, int amount) { int val = Math.Max(1, prefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_maxStackSize); while (amount > 0) { int num = Math.Min(amount, val); if (!inventory.AddItem(prefab, num)) { break; } amount -= num; } } internal static void DropStacks(ItemDrop item, int amount, Vector3 position) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) ItemData val = item.m_itemData.Clone(); val.m_dropPrefab = ((Component)item).gameObject; int val2 = Math.Max(1, val.m_shared.m_maxStackSize); while (amount > 0) { int num = Math.Min(amount, val2); ItemDrop.DropItem(val, num, position + Random.insideUnitSphere * 0.3f, Quaternion.Euler(0f, (float)Random.Range(0, 360), 0f)); amount -= num; } } } [HarmonyPatch(typeof(Smelter), "Awake")] internal static class Smelter_Awake_Patch { [HarmonyPostfix] private static void Postfix(Smelter __instance) { if (Plugin.IsStation(__instance)) { SmelterLogic.ApplyCaps(__instance); } } } [HarmonyPatch(typeof(Smelter), "OnAddOre")] internal static class Smelter_OnAddOre_Patch { [HarmonyPrefix] private static bool Prefix(Smelter __instance, object __0, object __1, object __2, ref bool __result) { return SmelterLogic.HandleAdd(__instance, __0, __1, __2, fuel: false, ref __result); } } [HarmonyPatch(typeof(Smelter), "OnAddFuel")] internal static class Smelter_OnAddFuel_Patch { [HarmonyPrefix] private static bool Prefix(Smelter __instance, object __0, object __1, object __2, ref bool __result) { return SmelterLogic.HandleAdd(__instance, __0, __1, __2, fuel: true, ref __result); } } [HarmonyPatch(typeof(Smelter), "OnHoverAddOre")] internal static class Smelter_OnHoverAddOre_Patch { [HarmonyPrefix] private static void Prefix(Smelter __instance) { if (Plugin.IsStation(__instance)) { SmelterLogic.ApplyCaps(__instance); } } [HarmonyPostfix] private static void Postfix(Smelter __instance, ref string __result) { if (Plugin.IsStation(__instance)) { __result += SmelterLogic.BatchHint(); } } } [HarmonyPatch(typeof(Smelter), "OnHoverAddFuel")] internal static class Smelter_OnHoverAddFuel_Patch { [HarmonyPrefix] private static void Prefix(Smelter __instance) { if (Plugin.IsStation(__instance)) { SmelterLogic.ApplyCaps(__instance); } } [HarmonyPostfix] private static void Postfix(Smelter __instance, ref string __result) { if (Plugin.IsStation(__instance)) { __result += SmelterLogic.BatchHint(); } } } [HarmonyPatch(typeof(Smelter), "DropAllItems")] internal static class Smelter_DropAllItems_Patch { [HarmonyPrefix] private static void Prefix(Smelter __instance) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.IsStation(__instance)) { return; } ZNetView val = SmelterLogic.SmelterNView.Invoke(__instance); if ((Object)(object)val == (Object)null || !val.IsValid()) { return; } Vector3 position = ((Component)__instance).transform.position + Vector3.up; if ((Object)(object)__instance.m_fuelItem != (Object)null) { int amount = Mathf.CeilToInt(SmelterLogic.GetFuel(__instance)); SmelterLogic.SetFuel(__instance, 0f); SmelterLogic.DropStacks(__instance.m_fuelItem, amount, position); } Dictionary<string, int> dictionary = new Dictionary<string, int>(); for (int i = 0; i < 100000; i++) { if (SmelterLogic.GetQueueSize(__instance) <= 0) { break; } string key = SmelterLogic.GetQueuedOre(__instance); SmelterLogic.RemoveOneOre(__instance); dictionary.TryGetValue(key, out var value); dictionary[key] = value + 1; } foreach (KeyValuePair<string, int> pair in dictionary) { ItemConversion val2 = ((IEnumerable<ItemConversion>)__instance.m_conversion).FirstOrDefault((Func<ItemConversion, bool>)((ItemConversion c) => (Object)(object)c?.m_from != (Object)null && ((Object)((Component)c.m_from).gameObject).name == pair.Key)); if (val2 != null) { SmelterLogic.DropStacks(val2.m_from, pair.Value, position); } } } } [HarmonyPatch(typeof(Container), "Awake")] internal static class Container_Awake_Patch { [HarmonyPostfix] private static void Postfix(Container __instance) { SmelterLogic.Containers.Add(__instance); } } }