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;
}
}
}
}
}
}