Decompiled source of AutoFuel v1.2.0

AutoFuel.dll

Decompiled 6 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using TMPro;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyVersion("1.0.0.0")]
public class AedenthornUtils
{
	public static bool IgnoreKeyPresses(bool extra = false)
	{
		if (!extra)
		{
			int result;
			if (!((Object)(object)ZNetScene.instance == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null) && !Minimap.IsOpen() && !Console.IsVisible() && !TextInput.IsVisible() && !ZNet.instance.InPasswordDialog())
			{
				Chat instance = Chat.instance;
				result = ((instance != null && instance.HasFocus()) ? 1 : 0);
			}
			else
			{
				result = 1;
			}
			return (byte)result != 0;
		}
		int result2;
		if (!((Object)(object)ZNetScene.instance == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null) && !Minimap.IsOpen() && !Console.IsVisible() && !TextInput.IsVisible() && !ZNet.instance.InPasswordDialog())
		{
			Chat instance2 = Chat.instance;
			if ((instance2 == null || !instance2.HasFocus()) && !StoreGui.IsVisible() && !InventoryGui.IsVisible() && !Menu.IsVisible())
			{
				TextViewer instance3 = TextViewer.instance;
				result2 = ((instance3 != null && instance3.IsVisible()) ? 1 : 0);
				goto IL_00d2;
			}
		}
		result2 = 1;
		goto IL_00d2;
		IL_00d2:
		return (byte)result2 != 0;
	}

	public static bool CheckKeyDown(string value)
	{
		try
		{
			return Input.GetKeyDown(value.ToLower());
		}
		catch
		{
			return false;
		}
	}

	public static bool CheckKeyHeld(string value, bool req = true)
	{
		try
		{
			return Input.GetKey(value.ToLower());
		}
		catch
		{
			return !req;
		}
	}
}
namespace AutoFuel;

[BepInPlugin("aedenthorn.AutoFuel", "Auto Fuel", "1.2.0")]
public class BepInExPlugin : BaseUnityPlugin
{
	[HarmonyPatch(typeof(Fireplace), "UpdateFireplace")]
	private static class Fireplace_UpdateFireplace_Patch
	{
		private static void Postfix(Fireplace __instance, ZNetView ___m_nview)
		{
			if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && isOn.Value && ___m_nview.IsOwner() && (!((Object)__instance).name.Contains("groundtorch") || refuelStandingTorches.Value) && (!((Object)__instance).name.Contains("walltorch") || refuelWallTorches.Value) && (!((Object)__instance).name.Contains("fire_pit") || refuelFirePits.Value))
			{
				if ((double)(Time.time - lastFuel) < 0.1)
				{
					fuelCount++;
					RefuelTorch(__instance, ___m_nview, fuelCount * 33);
				}
				else
				{
					fuelCount = 0;
					lastFuel = Time.time;
					RefuelTorch(__instance, ___m_nview, 0);
				}
			}
		}
	}

	[HarmonyPatch(typeof(Smelter), "UpdateSmelter")]
	private static class Smelter_FixedUpdate_Patch
	{
		private static void Postfix(Smelter __instance, ZNetView ___m_nview)
		{
			if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && isOn.Value && !((Object)(object)___m_nview == (Object)null) && ___m_nview.IsOwner())
			{
				if ((double)(Time.time - lastFuel) < 0.1)
				{
					fuelCount++;
					RefuelSmelter(__instance, ___m_nview, fuelCount * 33);
				}
				else
				{
					fuelCount = 0;
					lastFuel = Time.time;
					RefuelSmelter(__instance, ___m_nview, 0);
				}
			}
		}
	}

	[HarmonyPatch(typeof(Terminal), "InputText")]
	private static class InputText_Patch
	{
		private static bool Prefix(Terminal __instance)
		{
			if (!modEnabled.Value)
			{
				return true;
			}
			string text = ((TMP_InputField)__instance.m_input).text;
			if (text.ToLower().Equals(typeof(BepInExPlugin).Namespace.ToLower() + " reset"))
			{
				((BaseUnityPlugin)context).Config.Reload();
				((BaseUnityPlugin)context).Config.Save();
				__instance.AddString(text);
				__instance.AddString(((BaseUnityPlugin)context).Info.Metadata.Name + " config reloaded");
				return false;
			}
			return true;
		}
	}

	private static readonly bool isDebug;

	public static ConfigEntry<float> dropRange;

	public static ConfigEntry<float> containerRange;

	public static ConfigEntry<float> fireplaceRange;

	public static ConfigEntry<float> smelterOreRange;

	public static ConfigEntry<float> smelterFuelRange;

	public static ConfigEntry<string> fuelDisallowTypes;

	public static ConfigEntry<string> oreDisallowTypes;

	public static ConfigEntry<string> toggleKey;

	public static ConfigEntry<string> toggleString;

	public static ConfigEntry<bool> refuelStandingTorches;

	public static ConfigEntry<bool> refuelWallTorches;

	public static ConfigEntry<bool> refuelFirePits;

	public static ConfigEntry<bool> restrictKilnOutput;

	public static ConfigEntry<int> restrictKilnOutputAmount;

	public static ConfigEntry<bool> leaveLastItem;

	public static ConfigEntry<bool> isOn;

	public static ConfigEntry<bool> modEnabled;

	public static ConfigEntry<bool> distributedFilling;

	public static ConfigEntry<int> nexusID;

	private static BepInExPlugin context;

	private static float lastFuel;

	private static int fuelCount;

	public static void Dbgl(string str = "", bool pref = true)
	{
		if (isDebug)
		{
			Debug.Log((object)((pref ? (typeof(BepInExPlugin).Namespace + " ") : "") + str));
		}
	}

	private void Awake()
	{
		context = this;
		dropRange = ((BaseUnityPlugin)this).Config.Bind<float>("General", "DropRange", 5f, "The maximum range to pull dropped fuel");
		fireplaceRange = ((BaseUnityPlugin)this).Config.Bind<float>("General", "FireplaceRange", 5f, "The maximum range to pull fuel from containers for fireplaces");
		smelterOreRange = ((BaseUnityPlugin)this).Config.Bind<float>("General", "SmelterOreRange", 5f, "The maximum range to pull fuel from containers for smelters");
		smelterFuelRange = ((BaseUnityPlugin)this).Config.Bind<float>("General", "SmelterFuelRange", 5f, "The maximum range to pull ore from containers for smelters");
		fuelDisallowTypes = ((BaseUnityPlugin)this).Config.Bind<string>("General", "FuelDisallowTypes", "RoundLog,FineWood", "Types of item to disallow as fuel (i.e. anything that is consumed), comma-separated.");
		oreDisallowTypes = ((BaseUnityPlugin)this).Config.Bind<string>("General", "OreDisallowTypes", "RoundLog,FineWood", "Types of item to disallow as ore (i.e. anything that is transformed), comma-separated).");
		toggleString = ((BaseUnityPlugin)this).Config.Bind<string>("General", "ToggleString", "Auto Fuel: {0}", "Text to show on toggle. {0} is replaced with true/false");
		toggleKey = ((BaseUnityPlugin)this).Config.Bind<string>("General", "ToggleKey", "", "Key to toggle behaviour. Leave blank to disable the toggle key. Use https://docs.unity3d.com/Manual/ConventionalGameInput.html");
		refuelStandingTorches = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "RefuelStandingTorches", true, "Refuel standing torches");
		refuelWallTorches = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "RefuelWallTorches", true, "Refuel wall torches");
		refuelFirePits = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "RefuelFirePits", true, "Refuel fire pits");
		restrictKilnOutput = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "RestrictKilnOutput", false, "Restrict kiln output");
		restrictKilnOutputAmount = ((BaseUnityPlugin)this).Config.Bind<int>("General", "RestrictKilnOutputAmount", 10, "Amount of coal to shut off kiln fueling");
		isOn = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "IsOn", true, "Behaviour is currently on or not");
		distributedFilling = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "distributedFueling", false, "If true, refilling will occur one piece of fuel or ore at a time, making filling take longer but be better distributed between objects.");
		leaveLastItem = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "LeaveLastItem", false, "Don't use last of item in chest");
		modEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable this mod");
		nexusID = ((BaseUnityPlugin)this).Config.Bind<int>("General", "NexusID", 159, "Nexus mod ID for updates");
		if (modEnabled.Value)
		{
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null);
		}
	}

	private void Update()
	{
		if (AedenthornUtils.CheckKeyDown(toggleKey.Value) && !AedenthornUtils.IgnoreKeyPresses(extra: true))
		{
			isOn.Value = !isOn.Value;
			((BaseUnityPlugin)this).Config.Save();
			((Character)Player.m_localPlayer).Message((MessageType)2, string.Format(toggleString.Value, isOn.Value), 0, (Sprite)null);
		}
	}

	private static string GetPrefabName(string name)
	{
		char[] anyOf = new char[2] { '(', ' ' };
		int num = name.IndexOfAny(anyOf);
		if (num >= 0)
		{
			return name.Substring(0, num);
		}
		return name;
	}

	public static List<Container> GetNearbyContainers(Vector3 center, float range)
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			List<Container> list = new List<Container>();
			Collider[] array = Physics.OverlapSphere(center, Mathf.Max(range, 0f), LayerMask.GetMask(new string[1] { "piece" }));
			foreach (Collider val in array)
			{
				Container container = GetContainer(((Component)val).transform);
				if (container != null)
				{
					ZNetView component = ((Component)container).GetComponent<ZNetView>();
					if (component != null && component.IsValid() && container.GetInventory() != null)
					{
						list.Add(container);
					}
				}
			}
			return list;
		}
		catch
		{
			return new List<Container>();
		}
	}

	private static Container GetContainer(Transform transform)
	{
		while ((Object)(object)transform != (Object)null)
		{
			Container component = ((Component)transform).GetComponent<Container>();
			if ((Object)(object)component != (Object)null)
			{
				return component;
			}
			transform = transform.parent;
		}
		return null;
	}

	public static async void RefuelTorch(Fireplace fireplace, ZNetView znview, int delay)
	{
		try
		{
			await Task.Delay(delay);
			if (!Object.op_Implicit((Object)(object)fireplace) || !Object.op_Implicit((Object)(object)znview) || !znview.IsValid() || !modEnabled.Value)
			{
				return;
			}
			int maxFuel = (int)(fireplace.m_maxFuel - Mathf.Ceil(znview.GetZDO().GetFloat("fuel", 0f)));
			List<Container> nearbyContainers = GetNearbyContainers(((Component)fireplace).transform.position, fireplaceRange.Value);
			Vector3 position = ((Component)fireplace).transform.position + Vector3.up;
			Collider[] array = Physics.OverlapSphere(position, dropRange.Value, LayerMask.GetMask(new string[1] { "item" }));
			foreach (Collider collider in array)
			{
				if (!Object.op_Implicit((Object)(object)((collider != null) ? collider.attachedRigidbody : null)))
				{
					continue;
				}
				ItemDrop item = ((Component)collider.attachedRigidbody).GetComponent<ItemDrop>();
				int num;
				if (item == null)
				{
					num = 1;
				}
				else
				{
					ZNetView component = ((Component)item).GetComponent<ZNetView>();
					num = ((((component != null) ? new bool?(component.IsValid()) : null) != true) ? 1 : 0);
				}
				if (num != 0)
				{
					continue;
				}
				string name = GetPrefabName(((Object)((Component)item).gameObject).name);
				if (!(item.m_itemData.m_shared.m_name == fireplace.m_fuelItem.m_itemData.m_shared.m_name) || maxFuel <= 0 || fuelDisallowTypes.Value.Split(new char[1] { ',' }).Contains(name))
				{
					continue;
				}
				Dbgl("auto adding fuel " + name + " from ground");
				int amount = Mathf.Min(item.m_itemData.m_stack, maxFuel);
				maxFuel -= amount;
				for (int i = 0; i < amount; i++)
				{
					if (item.m_itemData.m_stack <= 1)
					{
						if (znview.GetZDO() == null)
						{
							Object.Destroy((Object)(object)((Component)item).gameObject);
						}
						else
						{
							ZNetScene.instance.Destroy(((Component)item).gameObject);
						}
						znview.InvokeRPC("AddFuel", new object[0]);
						if (distributedFilling.Value)
						{
							return;
						}
						break;
					}
					ItemData itemData = item.m_itemData;
					itemData.m_stack--;
					znview.InvokeRPC("AddFuel", new object[0]);
					Traverse.Create((object)item).Method("Save", Array.Empty<object>()).GetValue();
					if (distributedFilling.Value)
					{
						return;
					}
				}
			}
			foreach (Container c in nearbyContainers)
			{
				if (!Object.op_Implicit((Object)(object)fireplace.m_fuelItem) || maxFuel <= 0)
				{
					continue;
				}
				List<ItemData> itemList = new List<ItemData>();
				c.GetInventory().GetAllItems(fireplace.m_fuelItem.m_itemData.m_shared.m_name, itemList);
				foreach (ItemData fuelItem in itemList)
				{
					if (fuelItem != null && (!leaveLastItem.Value || fuelItem.m_stack > 1) && !fuelDisallowTypes.Value.Split(new char[1] { ',' }).Contains(((Object)fuelItem.m_dropPrefab).name))
					{
						maxFuel--;
						Dbgl($"container at {((Component)c).transform.position} has {fuelItem.m_stack} {((Object)fuelItem.m_dropPrefab).name}, taking one");
						znview.InvokeRPC("AddFuel", new object[0]);
						c.GetInventory().RemoveItem(fireplace.m_fuelItem.m_itemData.m_shared.m_name, 1, -1, true);
						typeof(Container).GetMethod("Save", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(c, new object[0]);
						typeof(Inventory).GetMethod("Changed", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(c.GetInventory(), new object[0]);
						if (distributedFilling.Value)
						{
							return;
						}
					}
				}
			}
		}
		catch
		{
		}
	}

	public static async void RefuelSmelter(Smelter __instance, ZNetView ___m_nview, int delay)
	{
		await Task.Delay(delay);
		if (!Object.op_Implicit((Object)(object)__instance) || !Object.op_Implicit((Object)(object)___m_nview) || !___m_nview.IsValid() || !modEnabled.Value)
		{
			return;
		}
		int maxOre = __instance.m_maxOre - Traverse.Create((object)__instance).Method("GetQueueSize", Array.Empty<object>()).GetValue<int>();
		int maxFuel = __instance.m_maxFuel - Mathf.CeilToInt(___m_nview.GetZDO().GetFloat("fuel", 0f));
		List<Container> nearbyOreContainers = GetNearbyContainers(((Component)__instance).transform.position, smelterOreRange.Value);
		List<Container> nearbyFuelContainers = GetNearbyContainers(((Component)__instance).transform.position, smelterFuelRange.Value);
		if (((Object)__instance).name.Contains("charcoal_kiln") && restrictKilnOutput.Value)
		{
			string outputName = __instance.m_conversion[0].m_to.m_itemData.m_shared.m_name;
			int maxOutput = restrictKilnOutputAmount.Value - Traverse.Create((object)__instance).Method("GetQueueSize", Array.Empty<object>()).GetValue<int>();
			foreach (Container c in nearbyOreContainers)
			{
				List<ItemData> itemList = new List<ItemData>();
				c.GetInventory().GetAllItems(outputName, itemList);
				foreach (ItemData outputItem in itemList)
				{
					if (outputItem != null)
					{
						maxOutput -= outputItem.m_stack;
					}
				}
			}
			if (maxOutput < 0)
			{
				maxOutput = 0;
			}
			if (maxOre > maxOutput)
			{
				maxOre = maxOutput;
			}
		}
		bool fueled = false;
		bool ored = false;
		Vector3 position = ((Component)__instance).transform.position + Vector3.up;
		Collider[] array = Physics.OverlapSphere(position, dropRange.Value, LayerMask.GetMask(new string[1] { "item" }));
		foreach (Collider collider in array)
		{
			if (!Object.op_Implicit((Object)(object)((collider != null) ? collider.attachedRigidbody : null)))
			{
				continue;
			}
			ItemDrop item = ((Component)collider.attachedRigidbody).GetComponent<ItemDrop>();
			int num;
			if (item == null)
			{
				num = 1;
			}
			else
			{
				ZNetView component = ((Component)item).GetComponent<ZNetView>();
				num = ((((component != null) ? new bool?(component.IsValid()) : null) != true) ? 1 : 0);
			}
			if (num != 0)
			{
				continue;
			}
			string name = GetPrefabName(((Object)((Component)item).gameObject).name);
			foreach (ItemConversion itemConversion in __instance.m_conversion)
			{
				if (ored)
				{
					break;
				}
				if (!(item.m_itemData.m_shared.m_name == itemConversion.m_from.m_itemData.m_shared.m_name) || maxOre <= 0 || oreDisallowTypes.Value.Split(new char[1] { ',' }).Contains(name))
				{
					continue;
				}
				Dbgl("auto adding ore " + name + " from ground");
				int amount2 = Mathf.Min(item.m_itemData.m_stack, maxOre);
				maxOre -= amount2;
				for (int j = 0; j < amount2; j++)
				{
					if (item.m_itemData.m_stack <= 1)
					{
						if (___m_nview.GetZDO() == null)
						{
							Object.Destroy((Object)(object)((Component)item).gameObject);
						}
						else
						{
							ZNetScene.instance.Destroy(((Component)item).gameObject);
						}
						___m_nview.InvokeRPC("AddOre", new object[1] { name });
						if (distributedFilling.Value)
						{
							ored = true;
						}
						break;
					}
					ItemData itemData = item.m_itemData;
					itemData.m_stack--;
					___m_nview.InvokeRPC("AddOre", new object[1] { name });
					Traverse.Create((object)item).Method("Save", Array.Empty<object>()).GetValue();
					if (distributedFilling.Value)
					{
						ored = true;
					}
				}
			}
			if (!Object.op_Implicit((Object)(object)__instance.m_fuelItem) || !(item.m_itemData.m_shared.m_name == __instance.m_fuelItem.m_itemData.m_shared.m_name) || maxFuel <= 0 || fueled || fuelDisallowTypes.Value.Split(new char[1] { ',' }).Contains(name))
			{
				continue;
			}
			Dbgl("auto adding fuel " + name + " from ground");
			int amount = Mathf.Min(item.m_itemData.m_stack, maxFuel);
			maxFuel -= amount;
			for (int i = 0; i < amount; i++)
			{
				if (item.m_itemData.m_stack <= 1)
				{
					if (___m_nview.GetZDO() == null)
					{
						Object.Destroy((Object)(object)((Component)item).gameObject);
					}
					else
					{
						ZNetScene.instance.Destroy(((Component)item).gameObject);
					}
					___m_nview.InvokeRPC("AddFuel", new object[0]);
					if (distributedFilling.Value)
					{
						fueled = true;
					}
					break;
				}
				ItemData itemData2 = item.m_itemData;
				itemData2.m_stack--;
				___m_nview.InvokeRPC("AddFuel", new object[0]);
				Traverse.Create((object)item).Method("Save", Array.Empty<object>()).GetValue();
				if (distributedFilling.Value)
				{
					fueled = true;
					break;
				}
			}
		}
		foreach (Container c3 in nearbyOreContainers)
		{
			foreach (ItemConversion itemConversion2 in __instance.m_conversion)
			{
				if (ored)
				{
					break;
				}
				List<ItemData> itemList3 = new List<ItemData>();
				c3.GetInventory().GetAllItems(itemConversion2.m_from.m_itemData.m_shared.m_name, itemList3);
				foreach (ItemData oreItem in itemList3)
				{
					if (oreItem != null && maxOre > 0 && (!leaveLastItem.Value || oreItem.m_stack > 1) && !oreDisallowTypes.Value.Split(new char[1] { ',' }).Contains(((Object)oreItem.m_dropPrefab).name))
					{
						maxOre--;
						Dbgl($"container at {((Component)c3).transform.position} has {oreItem.m_stack} {((Object)oreItem.m_dropPrefab).name}, taking one");
						object[] array2 = new object[1];
						GameObject dropPrefab = oreItem.m_dropPrefab;
						array2[0] = ((dropPrefab != null) ? ((Object)dropPrefab).name : null);
						___m_nview.InvokeRPC("AddOre", array2);
						c3.GetInventory().RemoveItem(itemConversion2.m_from.m_itemData.m_shared.m_name, 1, -1, true);
						typeof(Container).GetMethod("Save", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(c3, new object[0]);
						typeof(Inventory).GetMethod("Changed", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(c3.GetInventory(), new object[0]);
						if (distributedFilling.Value)
						{
							ored = true;
							break;
						}
					}
				}
			}
		}
		foreach (Container c2 in nearbyFuelContainers)
		{
			if (!Object.op_Implicit((Object)(object)__instance.m_fuelItem) || maxFuel <= 0 || fueled)
			{
				break;
			}
			List<ItemData> itemList2 = new List<ItemData>();
			c2.GetInventory().GetAllItems(__instance.m_fuelItem.m_itemData.m_shared.m_name, itemList2);
			foreach (ItemData fuelItem in itemList2)
			{
				if (fuelItem == null || (leaveLastItem.Value && fuelItem.m_stack <= 1))
				{
					continue;
				}
				maxFuel--;
				if (!fuelDisallowTypes.Value.Split(new char[1] { ',' }).Contains(((Object)fuelItem.m_dropPrefab).name))
				{
					Dbgl($"container at {((Component)c2).transform.position} has {fuelItem.m_stack} {((Object)fuelItem.m_dropPrefab).name}, taking one");
					___m_nview.InvokeRPC("AddFuel", new object[0]);
					c2.GetInventory().RemoveItem(__instance.m_fuelItem.m_itemData.m_shared.m_name, 1, -1, true);
					typeof(Container).GetMethod("Save", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(c2, new object[0]);
					typeof(Inventory).GetMethod("Changed", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(c2.GetInventory(), new object[0]);
					if (distributedFilling.Value)
					{
						fueled = true;
						break;
					}
				}
			}
		}
	}
}