Decompiled source of AutoSmelter v1.0.0

BepInEx\plugins\AutoSmelter\AutoSmelter.dll

Decompiled 12 hours ago
using System;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("AutoSmelter")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AutoSmelter")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("17d61898-8ea4-42c2-97ed-b4c8b98278e7")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace AutoSmelter;

[BepInPlugin("com.autosmelter.valheim", "AutoSmelter", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class AutoSmelterPlugin : BaseUnityPlugin
{
	public const string PluginGUID = "com.autosmelter.valheim";

	public const string PluginName = "AutoSmelter";

	public const string PluginVersion = "1.0.0";

	internal static ManualLogSource Log;

	private GameObject automationObject;

	private void Awake()
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		Log.LogInfo((object)"Loading AutoSmelter v1.0.0");
		ConfigManager.Initialize(((BaseUnityPlugin)this).Config);
		automationObject = new GameObject("AutoSmelterAutomation");
		automationObject.AddComponent<SmelterAutomation>();
		Object.DontDestroyOnLoad((Object)(object)automationObject);
		Log.LogInfo((object)"AutoSmelter loaded successfully!");
	}

	private void OnDestroy()
	{
		if ((Object)(object)automationObject != (Object)null)
		{
			Object.Destroy((Object)(object)automationObject);
		}
	}
}
public static class ConfigManager
{
	public static ConfigEntry<float> ChestRange;

	public static ConfigEntry<float> UpdateInterval;

	public static ConfigEntry<bool> EnableKilnAutomation;

	public static ConfigEntry<bool> EnableSmelterAutomation;

	public static void Initialize(ConfigFile config)
	{
		ChestRange = config.Bind<float>("General", "ChestRange", 10f, "Maximum distance (meters) to search for chests");
		UpdateInterval = config.Bind<float>("General", "UpdateInterval", 2f, "Seconds between automation checks");
		EnableKilnAutomation = config.Bind<bool>("Automation", "EnableKilnAutomation", true, "Enable automatic charcoal kiln management");
		EnableSmelterAutomation = config.Bind<bool>("Automation", "EnableSmelterAutomation", true, "Enable automatic smelter management");
	}
}
public static class ItemTransferHelper
{
	public static Container FindNearestChest(Vector3 position, float range)
	{
		//IL_0022: 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)
		Container result = null;
		float num = float.MaxValue;
		Container[] array = Object.FindObjectsByType<Container>((FindObjectsSortMode)0);
		foreach (Container val in array)
		{
			if (!((Object)(object)val == (Object)null))
			{
				float num2 = Vector3.Distance(position, ((Component)val).transform.position);
				if (num2 <= range && num2 < num)
				{
					result = val;
					num = num2;
				}
			}
		}
		return result;
	}

	public static Container FindNearestChestWithItem(Vector3 position, string itemName, float range)
	{
		//IL_0022: 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)
		Container result = null;
		float num = float.MaxValue;
		Container[] array = Object.FindObjectsByType<Container>((FindObjectsSortMode)0);
		foreach (Container val in array)
		{
			if (!((Object)(object)val == (Object)null))
			{
				float num2 = Vector3.Distance(position, ((Component)val).transform.position);
				if (num2 <= range && num2 < num && HasItem(val, itemName))
				{
					result = val;
					num = num2;
				}
			}
		}
		return result;
	}

	public static Container FindNearestChestWithOre(Vector3 position, float range)
	{
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		string[] array = new string[5] { "CopperOre", "TinOre", "IronOre", "SilverOre", "BlackMetalScrap" };
		Container result = null;
		float num = float.MaxValue;
		Container[] array2 = Object.FindObjectsByType<Container>((FindObjectsSortMode)0);
		foreach (Container val in array2)
		{
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			float num2 = Vector3.Distance(position, ((Component)val).transform.position);
			if (!(num2 <= range) || !(num2 < num))
			{
				continue;
			}
			string[] array3 = array;
			foreach (string itemName in array3)
			{
				if (HasItem(val, itemName))
				{
					result = val;
					num = num2;
					break;
				}
			}
		}
		return result;
	}

	public static bool HasItem(Container container, string itemName)
	{
		if ((Object)(object)container == (Object)null)
		{
			return false;
		}
		Inventory inventory = container.GetInventory();
		if (inventory == null)
		{
			return false;
		}
		return inventory.GetAllItems()?.Any((ItemData item) => item != null && (Object)(object)item.m_dropPrefab != (Object)null && ((Object)item.m_dropPrefab).name == itemName) ?? false;
	}

	public static ItemData GetItemFromContainer(Container container, string itemName)
	{
		if ((Object)(object)container == (Object)null)
		{
			return null;
		}
		Inventory inventory = container.GetInventory();
		if (inventory == null)
		{
			return null;
		}
		return inventory.GetAllItems()?.FirstOrDefault((Func<ItemData, bool>)((ItemData item) => item != null && (Object)(object)item.m_dropPrefab != (Object)null && ((Object)item.m_dropPrefab).name == itemName));
	}

	public static bool HasSpace(Container container, ItemData item)
	{
		if ((Object)(object)container == (Object)null || item == null)
		{
			return false;
		}
		Inventory inventory = container.GetInventory();
		if (inventory == null)
		{
			return false;
		}
		return inventory.CanAddItem(item, 1);
	}

	public static bool TransferItem(Container source, Container destination, string itemName, int amount)
	{
		if ((Object)(object)source == (Object)null || (Object)(object)destination == (Object)null)
		{
			return false;
		}
		Inventory inventory = source.GetInventory();
		Inventory inventory2 = destination.GetInventory();
		if (inventory == null || inventory2 == null)
		{
			return false;
		}
		ItemData itemFromContainer = GetItemFromContainer(source, itemName);
		if (itemFromContainer == null)
		{
			return false;
		}
		int num = Mathf.Min(amount, itemFromContainer.m_stack);
		if (num <= 0)
		{
			return false;
		}
		if (!inventory2.CanAddItem(itemFromContainer, num))
		{
			return false;
		}
		inventory.RemoveItem(itemFromContainer, num);
		ItemData val = itemFromContainer.Clone();
		val.m_stack = num;
		inventory2.AddItem(val);
		return true;
	}
}
public class SmelterAutomation : MonoBehaviour
{
	private float lastUpdateTime;

	private static Type kilnType;

	private static FieldInfo kilnFuelField;

	private static FieldInfo kilnMaxFuelField;

	private static FieldInfo kilnProductField;

	private static Type smelterType;

	private static FieldInfo smelterFuelField;

	private static FieldInfo smelterMaxFuelField;

	private static FieldInfo smelterProductField;

	private static FieldInfo smelterMaxOreField;

	private static MethodInfo smelterGetQueueSizeMethod;

	private static MethodInfo smelterCanAddOreMethod;

	private static MethodInfo smelterAddOreMethod;

	private void Start()
	{
		AutoSmelterPlugin.Log.LogInfo((object)"SmelterAutomation started");
		InitializeReflection();
	}

	private void InitializeReflection()
	{
		try
		{
			Assembly assembly = null;
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly2 in assemblies)
			{
				string name = assembly2.GetName().Name;
				if (name == "assembly_valheim" || name == "Assembly-CSharp")
				{
					assembly = assembly2;
					break;
				}
			}
			if (assembly == null)
			{
				AutoSmelterPlugin.Log.LogError((object)"Could not find assembly_valheim or Assembly-CSharp assembly");
				return;
			}
			kilnType = assembly.GetType("CharcoalKiln");
			if (kilnType == null)
			{
				AutoSmelterPlugin.Log.LogError((object)"Could not find CharcoalKiln type");
				return;
			}
			kilnFuelField = kilnType.GetField("m_fuel", BindingFlags.Instance | BindingFlags.NonPublic);
			kilnMaxFuelField = kilnType.GetField("m_maxFuel", BindingFlags.Instance | BindingFlags.NonPublic);
			kilnProductField = kilnType.GetField("m_product", BindingFlags.Instance | BindingFlags.NonPublic);
			smelterType = assembly.GetType("Smelter");
			if (smelterType == null)
			{
				AutoSmelterPlugin.Log.LogError((object)"Could not find Smelter type");
				return;
			}
			smelterFuelField = smelterType.GetField("m_fuel", BindingFlags.Instance | BindingFlags.NonPublic);
			smelterMaxFuelField = smelterType.GetField("m_maxFuel", BindingFlags.Instance | BindingFlags.NonPublic);
			smelterProductField = smelterType.GetField("m_product", BindingFlags.Instance | BindingFlags.NonPublic);
			smelterMaxOreField = smelterType.GetField("m_maxOre", BindingFlags.Instance | BindingFlags.NonPublic);
			smelterGetQueueSizeMethod = smelterType.GetMethod("GetQueueSize", BindingFlags.Instance | BindingFlags.NonPublic);
			smelterCanAddOreMethod = smelterType.GetMethod("CanAddOre", BindingFlags.Instance | BindingFlags.NonPublic);
			smelterAddOreMethod = smelterType.GetMethod("AddOre", BindingFlags.Instance | BindingFlags.NonPublic);
			AutoSmelterPlugin.Log.LogInfo((object)"Reflection initialized successfully");
		}
		catch (Exception ex)
		{
			AutoSmelterPlugin.Log.LogError((object)("Failed to initialize reflection: " + ex.Message));
		}
	}

	private void Update()
	{
		if (Time.time - lastUpdateTime >= ConfigManager.UpdateInterval.Value)
		{
			lastUpdateTime = Time.time;
			ProcessAutomation();
		}
	}

	private void ProcessAutomation()
	{
		if (ConfigManager.EnableKilnAutomation.Value)
		{
			ProcessCharcoalKilns();
		}
		if (ConfigManager.EnableSmelterAutomation.Value)
		{
			ProcessSmelters();
		}
	}

	private void ProcessCharcoalKilns()
	{
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Expected O, but got Unknown
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0174: Unknown result type (might be due to invalid IL or missing references)
		if (kilnType == null)
		{
			return;
		}
		Object[] array = Object.FindObjectsByType(kilnType, (FindObjectsSortMode)0);
		if (array == null || array.Length == 0)
		{
			return;
		}
		Object[] array2 = array;
		foreach (Object val in array2)
		{
			if (val == (Object)null)
			{
				continue;
			}
			try
			{
				float num = (float)kilnFuelField.GetValue(val);
				float num2 = (float)kilnMaxFuelField.GetValue(val);
				ItemData val2 = (ItemData)kilnProductField.GetValue(val);
				if (!(num < num2))
				{
					goto IL_013b;
				}
				Object obj = ((val is MonoBehaviour) ? val : null);
				Transform val3 = ((obj != null) ? ((Component)obj).transform : null);
				if ((Object)(object)val3 == (Object)null)
				{
					continue;
				}
				Container val4 = ItemTransferHelper.FindNearestChestWithItem(val3.position, "Wood", ConfigManager.ChestRange.Value);
				if ((Object)(object)val4 != (Object)null)
				{
					int num3 = (int)(num2 - num);
					if (ItemTransferHelper.TransferItem(val4, null, "Wood", num3))
					{
						float num4 = Mathf.Min(num + (float)num3, num2);
						kilnFuelField.SetValue(val, num4);
						AutoSmelterPlugin.Log.LogDebug((object)$"Added {num3} wood to kiln");
					}
				}
				goto IL_013b;
				IL_013b:
				if (val2 == null || val2.m_stack <= 0)
				{
					continue;
				}
				Object obj2 = ((val is MonoBehaviour) ? val : null);
				Transform val5 = ((obj2 != null) ? ((Component)obj2).transform : null);
				if ((Object)(object)val5 == (Object)null)
				{
					continue;
				}
				Container val6 = ItemTransferHelper.FindNearestChest(val5.position, ConfigManager.ChestRange.Value);
				if ((Object)(object)val6 != (Object)null && ItemTransferHelper.HasSpace(val6, val2))
				{
					ItemData val7 = val2.Clone();
					int stack = val7.m_stack;
					if (val6.GetInventory().AddItem(val7))
					{
						kilnProductField.SetValue(val, null);
						AutoSmelterPlugin.Log.LogDebug((object)$"Transferred {stack} coal to chest");
					}
				}
			}
			catch (Exception ex)
			{
				AutoSmelterPlugin.Log.LogError((object)("Error processing kiln: " + ex.Message));
			}
		}
	}

	private void ProcessSmelters()
	{
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Expected O, but got Unknown
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_018e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0323: Unknown result type (might be due to invalid IL or missing references)
		if (smelterType == null)
		{
			return;
		}
		Object[] array = Object.FindObjectsByType(smelterType, (FindObjectsSortMode)0);
		if (array == null || array.Length == 0)
		{
			return;
		}
		Object[] array2 = array;
		foreach (Object val in array2)
		{
			if (val == (Object)null)
			{
				continue;
			}
			try
			{
				float num = (float)smelterFuelField.GetValue(val);
				float num2 = (float)smelterMaxFuelField.GetValue(val);
				int num3 = (int)smelterMaxOreField.GetValue(val);
				int num4 = (int)smelterGetQueueSizeMethod.Invoke(val, null);
				ItemData val2 = (ItemData)smelterProductField.GetValue(val);
				if (!(num < num2))
				{
					goto IL_0160;
				}
				Object obj = ((val is MonoBehaviour) ? val : null);
				Transform val3 = ((obj != null) ? ((Component)obj).transform : null);
				if ((Object)(object)val3 == (Object)null)
				{
					continue;
				}
				Container val4 = ItemTransferHelper.FindNearestChestWithItem(val3.position, "Coal", ConfigManager.ChestRange.Value);
				if ((Object)(object)val4 != (Object)null)
				{
					int num5 = (int)(num2 - num);
					if (ItemTransferHelper.TransferItem(val4, null, "Coal", num5))
					{
						float num6 = Mathf.Min(num + (float)num5, num2);
						smelterFuelField.SetValue(val, num6);
						AutoSmelterPlugin.Log.LogDebug((object)$"Added {num5} coal to smelter");
					}
				}
				goto IL_0160;
				IL_0160:
				if (num4 >= num3)
				{
					goto IL_02ea;
				}
				Object obj2 = ((val is MonoBehaviour) ? val : null);
				Transform val5 = ((obj2 != null) ? ((Component)obj2).transform : null);
				if ((Object)(object)val5 == (Object)null)
				{
					continue;
				}
				Container val6 = ItemTransferHelper.FindNearestChestWithOre(val5.position, ConfigManager.ChestRange.Value);
				if ((Object)(object)val6 != (Object)null)
				{
					string[] array3 = new string[5] { "CopperOre", "TinOre", "IronOre", "SilverOre", "BlackMetalScrap" };
					foreach (string text in array3)
					{
						if (!ItemTransferHelper.HasItem(val6, text))
						{
							continue;
						}
						ItemData itemFromContainer = ItemTransferHelper.GetItemFromContainer(val6, text);
						if (itemFromContainer != null && (bool)smelterCanAddOreMethod.Invoke(val, new object[1] { itemFromContainer.m_dropPrefab }))
						{
							int num7 = Mathf.Min(itemFromContainer.m_stack, num3 - num4);
							val6.GetInventory().RemoveItem(itemFromContainer, num7);
							for (int k = 0; k < num7; k++)
							{
								smelterAddOreMethod.Invoke(val, new object[1] { itemFromContainer.m_dropPrefab });
							}
							AutoSmelterPlugin.Log.LogDebug((object)$"Added {num7} {text} to smelter");
							break;
						}
					}
				}
				goto IL_02ea;
				IL_02ea:
				if (val2 == null || val2.m_stack <= 0)
				{
					continue;
				}
				Object obj3 = ((val is MonoBehaviour) ? val : null);
				Transform val7 = ((obj3 != null) ? ((Component)obj3).transform : null);
				if ((Object)(object)val7 == (Object)null)
				{
					continue;
				}
				Container val8 = ItemTransferHelper.FindNearestChest(val7.position, ConfigManager.ChestRange.Value);
				if ((Object)(object)val8 != (Object)null && ItemTransferHelper.HasSpace(val8, val2))
				{
					ItemData val9 = val2.Clone();
					int stack = val9.m_stack;
					if (val8.GetInventory().AddItem(val9))
					{
						smelterProductField.SetValue(val, null);
						AutoSmelterPlugin.Log.LogDebug((object)$"Transferred {stack} ingots to chest");
					}
				}
			}
			catch (Exception ex)
			{
				AutoSmelterPlugin.Log.LogError((object)("Error processing smelter: " + ex.Message));
			}
		}
	}
}