using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using API;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("CraftFromContainers")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("CraftFromContainers")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("2f3d602e-4db9-4a28-81de-829b79641141")]
[assembly: AssemblyFileVersion("3.5.8.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("3.5.8.0")]
namespace CraftFromContainers;
[BepInPlugin("aedenthorn.CraftFromContainers", "Craft From Containers", "3.5.7")]
public class CraftFromContainers : BaseUnityPlugin
{
public class ConnectionParams
{
public GameObject connection = null;
public Vector3 stationPos;
}
[HarmonyPatch(typeof(FejdStartup), "Awake")]
private static class FejdStartup_Awake_Patch
{
private static void Postfix(FejdStartup __instance)
{
if (modEnabled.Value)
{
CheckOdinsQOLConfig();
}
}
}
[HarmonyPatch(typeof(Container), "Awake")]
private static class Container_Awake_Patch
{
private static void Postfix(Container __instance, ZNetView ___m_nview)
{
((MonoBehaviour)context).StartCoroutine(AddContainer(__instance, ___m_nview));
}
}
[HarmonyPatch(typeof(Container), "OnDestroyed")]
private static class Container_OnDestroyed_Patch
{
private static void Prefix(Container __instance)
{
containerList.Remove(__instance);
}
}
[HarmonyPatch(typeof(InventoryGui), "Update")]
private static class InventoryGui_Update_Patch
{
private static void Prefix(InventoryGui __instance, Animator ___m_animator)
{
if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && wasAllowed != AllowByKey() && ___m_animator.GetBool("visible"))
{
AccessTools.Method(typeof(InventoryGui), "UpdateCraftingPanel", (Type[])null, (Type[])null).Invoke(__instance, new object[1] { false });
}
}
}
[HarmonyPatch(typeof(Fireplace), "Interact")]
private static class Fireplace_Interact_Patch
{
private static bool Prefix(Fireplace __instance, Humanoid user, bool hold, ref bool __result, ZNetView ___m_nview)
{
//IL_0366: Unknown result type (might be due to invalid IL or missing references)
//IL_041f: Unknown result type (might be due to invalid IL or missing references)
//IL_04a1: Unknown result type (might be due to invalid IL or missing references)
//IL_0207: Unknown result type (might be due to invalid IL or missing references)
//IL_0291: Unknown result type (might be due to invalid IL or missing references)
__result = true;
bool flag = CheckKeyHeld(fillAllModKey.Value);
Inventory inventory = user.GetInventory();
if (!AllowByKey() || hold || inventory == null || (inventory.HaveItem(__instance.m_fuelItem.m_itemData.m_shared.m_name, true) && !flag))
{
return true;
}
if (!___m_nview.HasOwner())
{
___m_nview.ClaimOwnership();
}
if (flag && inventory.HaveItem(__instance.m_fuelItem.m_itemData.m_shared.m_name, true))
{
int num = (int)Mathf.Min(__instance.m_maxFuel - (float)Mathf.CeilToInt(___m_nview.GetZDO().GetFloat("fuel", 0f)), (float)inventory.CountItems(__instance.m_fuelItem.m_itemData.m_shared.m_name, -1, true));
inventory.RemoveItem(__instance.m_fuelItem.m_itemData.m_shared.m_name, num, -1, true);
typeof(Inventory).GetMethod("Changed", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(inventory, new object[0]);
for (int i = 0; i < num; i++)
{
___m_nview.InvokeRPC("RPC_AddFuel", Array.Empty<object>());
}
((Character)user).Message((MessageType)2, Localization.instance.Localize("$msg_fireadding", new string[1] { __instance.m_fuelItem.m_itemData.m_shared.m_name }), 0, (Sprite)null);
__result = false;
}
if (!inventory.HaveItem(__instance.m_fuelItem.m_itemData.m_shared.m_name, true) && (double)Mathf.CeilToInt(___m_nview.GetZDO().GetFloat("fuel", 0f)) < (double)__instance.m_maxFuel)
{
if (KG_ItemDrawer)
{
try
{
string text = ItemDrawer_Patch.HaveRequiredItem(((Object)__instance.m_fuelItem).name, ((Component)Player.m_localPlayer).transform.position, m_range.Value);
if (!string.IsNullOrEmpty(text) && !fuelDisallowTypes.Value.Split(new char[1] { ',' }).Contains(text))
{
int amount = ((!flag) ? 1 : ((int)(__instance.m_maxFuel - (float)Mathf.CeilToInt(___m_nview.GetZDO().GetFloat("fuel", 0f)))));
int num2 = ItemDrawer_Patch.PullResource(text, amount, ((Component)Player.m_localPlayer).transform.position, m_range.Value);
if (num2 > 0)
{
((Character)user).Message((MessageType)2, Localization.instance.Localize("$msg_fireadding", new string[1] { __instance.m_fuelItem.m_itemData.m_shared.m_name }), 0, (Sprite)null);
for (int j = 0; j < num2; j++)
{
___m_nview.InvokeRPC("RPC_AddFuel", Array.Empty<object>());
}
__result = false;
if (!flag || (double)Mathf.CeilToInt(___m_nview.GetZDO().GetFloat("fuel", 0f)) >= (double)__instance.m_maxFuel)
{
return false;
}
}
}
}
catch
{
}
}
foreach (Container nearbyContainer in GetNearbyContainers(((Component)__instance).transform.position))
{
ItemData item = nearbyContainer.GetInventory().GetItem(__instance.m_fuelItem.m_itemData.m_shared.m_name, -1, false);
if (item == null || !((double)Mathf.CeilToInt(___m_nview.GetZDO().GetFloat("fuel", 0f)) < (double)__instance.m_maxFuel))
{
continue;
}
if (fuelDisallowTypes.Value.Split(new char[1] { ',' }).Contains(((Object)item.m_dropPrefab).name))
{
Dbgl($"container at {((Component)nearbyContainer).transform.position} has {item.m_stack} {((Object)item.m_dropPrefab).name} but it's forbidden by config");
continue;
}
int num3 = ((!flag) ? 1 : ((int)Mathf.Min(__instance.m_maxFuel - (float)Mathf.CeilToInt(___m_nview.GetZDO().GetFloat("fuel", 0f)), (float)item.m_stack)));
Dbgl($"container at {((Component)nearbyContainer).transform.position} has {item.m_stack} {((Object)item.m_dropPrefab).name}, taking {num3}");
nearbyContainer.GetInventory().RemoveItem(__instance.m_fuelItem.m_itemData.m_shared.m_name, num3, -1, true);
typeof(Container).GetMethod("Save", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(nearbyContainer, new object[0]);
if (__result)
{
((Character)user).Message((MessageType)2, Localization.instance.Localize("$msg_fireadding", new string[1] { __instance.m_fuelItem.m_itemData.m_shared.m_name }), 0, (Sprite)null);
}
for (int k = 0; k < num3; k++)
{
___m_nview.InvokeRPC("RPC_AddFuel", Array.Empty<object>());
}
__result = false;
if (flag && !((double)Mathf.CeilToInt(___m_nview.GetZDO().GetFloat("fuel", 0f)) >= (double)__instance.m_maxFuel))
{
continue;
}
return false;
}
}
return __result;
}
}
[HarmonyPatch(typeof(CookingStation), "OnAddFuelSwitch")]
private static class CookingStation_OnAddFuelSwitch_Patch
{
private static bool Prefix(CookingStation __instance, ref bool __result, Humanoid user, ItemData item, ZNetView ___m_nview)
{
//IL_017a: Unknown result type (might be due to invalid IL or missing references)
//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
//IL_024d: Unknown result type (might be due to invalid IL or missing references)
//IL_020c: Unknown result type (might be due to invalid IL or missing references)
//IL_0106: Unknown result type (might be due to invalid IL or missing references)
Dbgl("looking for fuel");
if (!modEnabled.Value || !AllowByKey() || item != null || (double)(float)((object)__instance).GetType().GetMethod("GetFuel", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(__instance, new object[0]) > (double)(__instance.m_maxFuel - 1) || user.GetInventory().HaveItem(__instance.m_fuelItem.m_itemData.m_shared.m_name, true))
{
return true;
}
Dbgl("missing fuel in player inventory");
if (KG_ItemDrawer)
{
try
{
string text = ItemDrawer_Patch.HaveRequiredItem(((Object)__instance.m_fuelItem).name, ((Component)Player.m_localPlayer).transform.position, m_range.Value);
if (!string.IsNullOrEmpty(text) && !fuelDisallowTypes.Value.Split(new char[1] { ',' }).Contains(text) && ItemDrawer_Patch.PullResource(text, 1, ((Component)Player.m_localPlayer).transform.position, m_range.Value) == 1)
{
((Character)user).Message((MessageType)2, "$msg_added " + __instance.m_fuelItem.m_itemData.m_shared.m_name, 0, (Sprite)null);
___m_nview.InvokeRPC("RPC_AddFuel", Array.Empty<object>());
__result = true;
return false;
}
}
catch
{
}
}
foreach (Container nearbyContainer in GetNearbyContainers(((Component)__instance).transform.position))
{
ItemData item2 = nearbyContainer.GetInventory().GetItem(__instance.m_fuelItem.m_itemData.m_shared.m_name, -1, false);
if (item2 != null)
{
if (!fuelDisallowTypes.Value.Split(new char[1] { ',' }).Contains(((Object)item2.m_dropPrefab).name))
{
Dbgl($"container at {((Component)nearbyContainer).transform.position} has {item2.m_stack} {((Object)item2.m_dropPrefab).name}, taking one");
nearbyContainer.GetInventory().RemoveItem(__instance.m_fuelItem.m_itemData.m_shared.m_name, 1, -1, true);
typeof(Container).GetMethod("Save", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(nearbyContainer, new object[0]);
((Character)user).Message((MessageType)2, "$msg_added " + __instance.m_fuelItem.m_itemData.m_shared.m_name, 0, (Sprite)null);
___m_nview.InvokeRPC("RPC_AddFuel", Array.Empty<object>());
__result = true;
return false;
}
Dbgl($"container at {((Component)nearbyContainer).transform.position} has {item2.m_stack} {((Object)item2.m_dropPrefab).name} but it's forbidden by config");
}
}
return true;
}
}
[HarmonyPatch(typeof(CookingStation), "FindCookableItem")]
private static class CookingStation_FindCookableItem_Patch
{
private static void Postfix(CookingStation __instance, ref ItemData __result)
{
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
//IL_0247: Unknown result type (might be due to invalid IL or missing references)
//IL_0206: Unknown result type (might be due to invalid IL or missing references)
//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
//IL_0142: Unknown result type (might be due to invalid IL or missing references)
Dbgl("looking for cookable");
if (!modEnabled.Value || !AllowByKey() || __result != null || (__instance.m_requireFire && !(bool)typeof(CookingStation).GetMethod("IsFireLit", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(__instance, new object[0])) || (int)typeof(CookingStation).GetMethod("GetFreeSlot", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(__instance, new object[0]) == -1)
{
return;
}
Dbgl("missing cookable in player inventory");
List<Container> nearbyContainers = GetNearbyContainers(((Component)__instance).transform.position);
foreach (ItemConversion item2 in __instance.m_conversion)
{
if (KG_ItemDrawer)
{
try
{
string text = ItemDrawer_Patch.HaveRequiredItem(((Object)item2.m_from).name, ((Component)Player.m_localPlayer).transform.position, m_range.Value);
if (!string.IsNullOrEmpty(text) && !oreDisallowTypes.Value.Split(new char[1] { ',' }).Contains(text) && ItemDrawer_Patch.PullResource(text, 1, ((Component)Player.m_localPlayer).transform.position, m_range.Value) == 1)
{
__result = item2.m_from.m_itemData;
break;
}
}
catch
{
}
}
foreach (Container item3 in nearbyContainers)
{
ItemData item = item3.GetInventory().GetItem(item2.m_from.m_itemData.m_shared.m_name, -1, false);
if (item != null)
{
if (!oreDisallowTypes.Value.Split(new char[1] { ',' }).Contains(((Object)item.m_dropPrefab).name))
{
Dbgl($"container at {((Component)item3).transform.position} has {item.m_stack} {((Object)item.m_dropPrefab).name}, taking one");
__result = item;
item3.GetInventory().RemoveItem(item2.m_from.m_itemData.m_shared.m_name, 1, -1, true);
typeof(Container).GetMethod("Save", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(item3, new object[0]);
return;
}
Dbgl($"container at {((Component)item3).transform.position} has {item.m_stack} {((Object)item.m_dropPrefab).name} but it's forbidden by config");
}
}
}
}
}
[HarmonyPatch(typeof(Smelter), "OnHoverAddFuel")]
private static class Smelter_OnHoverAddFuel_Patch
{
private static void Postfix(Smelter __instance, ref string __result)
{
if (modEnabled.Value)
{
string value = fillAllModKey.Value;
if (value != null && value.Length > 0)
{
__result += Localization.instance.Localize("\n[<color=yellow><b>" + fillAllModKey.Value + "+$KEY_Use</b></color>] $piece_smelter_add max");
}
}
}
}
[HarmonyPatch(typeof(Smelter), "OnHoverAddOre")]
private static class Smelter_OnHoverAddOre_Patch
{
private static void Postfix(Smelter __instance, ref string __result)
{
if (modEnabled.Value)
{
string value = fillAllModKey.Value;
if (value != null && value.Length > 0)
{
__result += Localization.instance.Localize("\n[<color=yellow><b>" + fillAllModKey.Value + "+$KEY_Use</b></color>] " + __instance.m_addOreTooltip + " max");
}
}
}
}
[HarmonyPatch(typeof(Smelter), "OnAddOre")]
private static class Smelter_OnAddOre_Patch
{
private static bool Prefix(Smelter __instance, Humanoid user, ItemData item, ZNetView ___m_nview)
{
//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
//IL_0550: Unknown result type (might be due to invalid IL or missing references)
//IL_060f: Unknown result type (might be due to invalid IL or missing references)
//IL_0319: Unknown result type (might be due to invalid IL or missing references)
//IL_03d8: Unknown result type (might be due to invalid IL or missing references)
bool flag = CheckKeyHeld(fillAllModKey.Value);
if (!modEnabled.Value || (!AllowByKey() && !flag) || item != null || Traverse.Create((object)__instance).Method("GetQueueSize", Array.Empty<object>()).GetValue<int>() >= __instance.m_maxOre)
{
return true;
}
Inventory inventory = user.GetInventory();
foreach (ItemConversion item4 in __instance.m_conversion)
{
if (inventory.HaveItem(item4.m_from.m_itemData.m_shared.m_name, true) && !flag)
{
return true;
}
}
Dictionary<string, int> dictionary = new Dictionary<string, int>();
List<Container> nearbyContainers = GetNearbyContainers(((Component)__instance).transform.position);
foreach (ItemConversion item5 in __instance.m_conversion)
{
if (Traverse.Create((object)__instance).Method("GetQueueSize", Array.Empty<object>()).GetValue<int>() >= __instance.m_maxOre || !(!dictionary.Any() || flag))
{
break;
}
string name = item5.m_from.m_itemData.m_shared.m_name;
if (flag && inventory.HaveItem(name, true))
{
ItemData item2 = inventory.GetItem(name, -1, false);
if (oreDisallowTypes.Value.Split(new char[1] { ',' }).Contains(((Object)item2.m_dropPrefab).name))
{
Dbgl($"player has {item2.m_stack} {((Object)item2.m_dropPrefab).name} but it's forbidden by config");
continue;
}
int num = ((!flag) ? 1 : Mathf.Min(__instance.m_maxOre - Traverse.Create((object)__instance).Method("GetQueueSize", Array.Empty<object>()).GetValue<int>(), inventory.CountItems(name, -1, true)));
if (!dictionary.ContainsKey(name))
{
dictionary[name] = 0;
}
dictionary[name] += num;
inventory.RemoveItem(item5.m_from.m_itemData.m_shared.m_name, num, -1, true);
for (int i = 0; i < num; i++)
{
___m_nview.InvokeRPC("RPC_AddOre", new object[1] { ((Object)item2.m_dropPrefab).name });
}
((Character)user).Message((MessageType)1, $"$msg_added {num} {name}", 0, (Sprite)null);
if (Traverse.Create((object)__instance).Method("GetQueueSize", Array.Empty<object>()).GetValue<int>() >= __instance.m_maxOre)
{
break;
}
}
if (KG_ItemDrawer)
{
try
{
string text = ItemDrawer_Patch.HaveRequiredItem(((Object)item5.m_from).name, ((Component)Player.m_localPlayer).transform.position, m_range.Value);
if (text != "")
{
Dbgl("OnAddOre oreDisallowTypes " + oreDisallowTypes.Value);
Dbgl("OnAddOre itemData " + text);
if (!oreDisallowTypes.Value.Split(new char[1] { ',' }).Contains(name))
{
int amount = ((!flag) ? 1 : (__instance.m_maxOre - Traverse.Create((object)__instance).Method("GetQueueSize", Array.Empty<object>()).GetValue<int>()));
int num2 = ItemDrawer_Patch.PullResource(text, amount, ((Component)Player.m_localPlayer).transform.position, m_range.Value);
if (num2 > 0)
{
if (!dictionary.ContainsKey(name))
{
dictionary[name] = 0;
}
dictionary[name] += num2;
for (int j = 0; j < num2; j++)
{
___m_nview.InvokeRPC("RPC_AddOre", new object[1] { text });
}
((Character)user).Message((MessageType)1, $"$msg_added {num2} {text}", 0, (Sprite)null);
if (Traverse.Create((object)__instance).Method("GetQueueSize", Array.Empty<object>()).GetValue<int>() >= __instance.m_maxOre || !flag)
{
break;
}
}
}
}
}
catch (Exception ex)
{
Dbgl("OnAddOre PullResource ex " + ex.Message);
}
}
foreach (Container item6 in nearbyContainers)
{
ItemData item3 = item6.GetInventory().GetItem(name, -1, false);
if (item3 == null)
{
continue;
}
if (oreDisallowTypes.Value.Split(new char[1] { ',' }).Contains(((Object)item3.m_dropPrefab).name))
{
Dbgl($"container at {((Component)item6).transform.position} has {item3.m_stack} {((Object)item3.m_dropPrefab).name} but it's forbidden by config");
continue;
}
int num3 = ((!flag) ? 1 : Mathf.Min(__instance.m_maxOre - Traverse.Create((object)__instance).Method("GetQueueSize", Array.Empty<object>()).GetValue<int>(), item6.GetInventory().CountItems(name, -1, true)));
if (!dictionary.ContainsKey(name))
{
dictionary[name] = 0;
}
dictionary[name] += num3;
Dbgl($"container at {((Component)item6).transform.position} has {item3.m_stack} {((Object)item3.m_dropPrefab).name}, taking {num3}");
item6.GetInventory().RemoveItem(name, num3, -1, true);
typeof(Container).GetMethod("Save", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(item6, new object[0]);
for (int k = 0; k < num3; k++)
{
___m_nview.InvokeRPC("RPC_AddOre", new object[1] { ((Object)item3.m_dropPrefab).name });
}
((Character)user).Message((MessageType)1, $"$msg_added {num3} {name}", 0, (Sprite)null);
if (Traverse.Create((object)__instance).Method("GetQueueSize", Array.Empty<object>()).GetValue<int>() < __instance.m_maxOre && flag)
{
continue;
}
break;
}
}
if (!dictionary.Any())
{
((Character)user).Message((MessageType)2, "$msg_noprocessableitems", 0, (Sprite)null);
}
else
{
List<string> list = new List<string>();
foreach (KeyValuePair<string, int> item7 in dictionary)
{
list.Add($"$msg_added {item7.Value} {item7.Key}");
}
((Character)user).Message((MessageType)2, string.Join("\n", list), 0, (Sprite)null);
}
return false;
}
}
[HarmonyPatch(typeof(Smelter), "OnAddFuel")]
private static class Smelter_OnAddFuel_Patch
{
private static bool Prefix(Smelter __instance, ref bool __result, ZNetView ___m_nview, Humanoid user, ItemData item)
{
//IL_034d: Unknown result type (might be due to invalid IL or missing references)
//IL_03df: Unknown result type (might be due to invalid IL or missing references)
//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
//IL_046d: Unknown result type (might be due to invalid IL or missing references)
//IL_027b: Unknown result type (might be due to invalid IL or missing references)
bool flag = CheckKeyHeld(fillAllModKey.Value);
Inventory inventory = user.GetInventory();
if (!modEnabled.Value || (!AllowByKey() && !flag) || item != null || inventory == null || (inventory.HaveItem(__instance.m_fuelItem.m_itemData.m_shared.m_name, true) && !flag))
{
return true;
}
__result = true;
int num = 0;
if ((double)(float)typeof(Smelter).GetMethod("GetFuel", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(__instance, new object[0]) > (double)(__instance.m_maxFuel - 1))
{
((Character)user).Message((MessageType)2, "$msg_itsfull", 0, (Sprite)null);
__result = false;
return false;
}
if (flag && inventory.HaveItem(__instance.m_fuelItem.m_itemData.m_shared.m_name, true))
{
int num2 = (int)Mathf.Min((float)__instance.m_maxFuel - (float)typeof(Smelter).GetMethod("GetFuel", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(__instance, new object[0]), (float)inventory.CountItems(__instance.m_fuelItem.m_itemData.m_shared.m_name, -1, true));
inventory.RemoveItem(__instance.m_fuelItem.m_itemData.m_shared.m_name, num2, -1, true);
for (int i = 0; i < num2; i++)
{
___m_nview.InvokeRPC("RPC_AddFuel", Array.Empty<object>());
}
num += num2;
((Character)user).Message((MessageType)1, Localization.instance.Localize("$msg_fireadding", new string[1] { __instance.m_fuelItem.m_itemData.m_shared.m_name }), 0, (Sprite)null);
__result = false;
}
if (KG_ItemDrawer)
{
try
{
string text = ItemDrawer_Patch.HaveRequiredItem(((Object)__instance.m_fuelItem).name, ((Component)Player.m_localPlayer).transform.position, m_range.Value);
if (!string.IsNullOrEmpty(text) && !fuelDisallowTypes.Value.Split(new char[1] { ',' }).Contains(text))
{
int amount = ((!flag) ? 1 : ((int)((float)__instance.m_maxFuel - (float)Mathf.CeilToInt(___m_nview.GetZDO().GetFloat("fuel", 0f)))));
int num3 = ItemDrawer_Patch.PullResource(text, amount, ((Component)Player.m_localPlayer).transform.position, m_range.Value);
for (int j = 0; j < num3; j++)
{
___m_nview.InvokeRPC("RPC_AddFuel", Array.Empty<object>());
}
num += num3;
((Character)user).Message((MessageType)1, "$msg_added " + __instance.m_fuelItem.m_itemData.m_shared.m_name, 0, (Sprite)null);
__result = false;
if (!flag || Mathf.CeilToInt(___m_nview.GetZDO().GetFloat("fuel", 0f)) >= __instance.m_maxFuel)
{
return false;
}
}
}
catch (Exception ex)
{
Dbgl("OnAddFuel PullResource ex " + ex.Message);
}
}
foreach (Container nearbyContainer in GetNearbyContainers(((Component)__instance).transform.position))
{
ItemData item2 = nearbyContainer.GetInventory().GetItem(__instance.m_fuelItem.m_itemData.m_shared.m_name, -1, false);
if (item2 == null)
{
continue;
}
if (fuelDisallowTypes.Value.Split(new char[1] { ',' }).Contains(((Object)item2.m_dropPrefab).name))
{
Dbgl($"container at {((Component)nearbyContainer).transform.position} has {item2.m_stack} {((Object)item2.m_dropPrefab).name} but it's forbidden by config");
continue;
}
int num4 = ((!flag) ? 1 : ((int)Mathf.Min((float)__instance.m_maxFuel - (float)typeof(Smelter).GetMethod("GetFuel", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(__instance, new object[0]), (float)item2.m_stack)));
Dbgl($"container at {((Component)nearbyContainer).transform.position} has {item2.m_stack} {((Object)item2.m_dropPrefab).name}, taking {num4}");
nearbyContainer.GetInventory().RemoveItem(__instance.m_fuelItem.m_itemData.m_shared.m_name, num4, -1, true);
typeof(Container).GetMethod("Save", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(nearbyContainer, new object[0]);
for (int k = 0; k < num4; k++)
{
___m_nview.InvokeRPC("RPC_AddFuel", Array.Empty<object>());
}
num += num4;
((Character)user).Message((MessageType)1, "$msg_added " + __instance.m_fuelItem.m_itemData.m_shared.m_name, 0, (Sprite)null);
__result = false;
if (flag && Mathf.CeilToInt(___m_nview.GetZDO().GetFloat("fuel", 0f)) < __instance.m_maxFuel)
{
continue;
}
return false;
}
if (num == 0)
{
((Character)user).Message((MessageType)2, "$msg_noprocessableitems", 0, (Sprite)null);
}
else
{
((Character)user).Message((MessageType)2, $"$msg_added {num} {__instance.m_fuelItem.m_itemData.m_shared.m_name}", 0, (Sprite)null);
}
return __result;
}
}
[HarmonyPatch(typeof(InventoryGui), "SetupRequirement")]
private static class InventoryGui_SetupRequirement_Patch
{
private static void Postfix(InventoryGui __instance, Transform elementRoot, Requirement req, Player player, bool craft, int quality, int craftMultiplier = 1)
{
//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
//IL_0178: Unknown result type (might be due to invalid IL or missing references)
//IL_016c: Unknown result type (might be due to invalid IL or missing references)
if (!modEnabled.Value || !AllowByKey() || !((Object)(object)req.m_resItem != (Object)null))
{
return;
}
int num = ((Humanoid)player).GetInventory().CountItems(req.m_resItem.m_itemData.m_shared.m_name, -1, true);
int num2 = req.GetAmount(quality) * craftMultiplier;
if (num2 <= 0)
{
return;
}
TMP_Text component = ((Component)((Component)elementRoot).transform.Find("res_amount")).GetComponent<TMP_Text>();
if (num < num2)
{
if (KG_ItemDrawer)
{
try
{
num += ItemDrawer_Patch.HaveRequiredItemCount(((Object)req.m_resItem).name, ((Component)Player.m_localPlayer).transform.position, m_range.Value);
}
catch
{
}
}
foreach (Container nearbyContainer in GetNearbyContainers(((Component)Player.m_localPlayer).transform.position))
{
num += nearbyContainer.GetInventory().CountItems(req.m_resItem.m_itemData.m_shared.m_name, -1, true);
}
if (num >= num2)
{
((Graphic)component).color = (((double)Mathf.Sin(Time.time * 10f) > 0.0) ? flashColor.Value : unFlashColor.Value);
}
}
component.text = ((resourceString.Value.Trim().Length <= 0) ? num2.ToString() : string.Format(resourceString.Value, num, num2));
}
}
private static class InventoryGui_UpdateRecipeList_Patch
{
private static void Postfix(InventoryGui __instance, List<GameObject> ___m_recipeList)
{
if (!modEnabled.Value || !AllowByKey() || ___m_recipeList.Count == 0)
{
return;
}
foreach (GameObject ___m_recipe in ___m_recipeList)
{
}
}
}
[HarmonyPatch(typeof(Player), "HaveRequirementItems", new Type[]
{
typeof(Recipe),
typeof(bool),
typeof(int),
typeof(int)
})]
private static class HaveRequirementItems_Patch
{
private static void Postfix(Player __instance, ref bool __result, Recipe piece, bool discover, int qualityLevel, int amount, HashSet<string> ___m_knownMaterial)
{
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
if ((!modEnabled.Value | __result) || discover || !AllowByKey())
{
return;
}
List<Container> nearbyContainers = GetNearbyContainers(((Component)__instance).transform.position);
Requirement[] resources = piece.m_resources;
foreach (Requirement val in resources)
{
if (!Object.op_Implicit((Object)(object)val.m_resItem))
{
continue;
}
int num = val.GetAmount(qualityLevel) * amount;
int num2 = ((Humanoid)__instance).GetInventory().CountItems(val.m_resItem.m_itemData.m_shared.m_name, -1, true);
if (KG_ItemDrawer)
{
try
{
num2 += ItemDrawer_Patch.HaveRequiredItemCount(((Object)val.m_resItem).name, ((Component)Player.m_localPlayer).transform.position, m_range.Value);
}
catch
{
}
}
if (num2 >= num)
{
continue;
}
foreach (Container item in nearbyContainers)
{
num2 += item.GetInventory().CountItems(val.m_resItem.m_itemData.m_shared.m_name, -1, true);
}
if (num2 < num)
{
return;
}
}
__result = true;
}
}
[HarmonyPatch(typeof(Player), "UpdateKnownRecipesList")]
private static class UpdateKnownRecipesList_Patch
{
private static void Prefix()
{
skip = true;
}
private static void Postfix()
{
skip = false;
}
}
[HarmonyPatch(typeof(Player), "HaveRequirements", new Type[]
{
typeof(Piece),
typeof(RequirementMode)
})]
private static class HaveRequirements_Patch
{
private static void Postfix(Player __instance, ref bool __result, Piece piece, RequirementMode mode, HashSet<string> ___m_knownMaterial, Dictionary<string, int> ___m_knownStations)
{
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Invalid comparison between Unknown and I4
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: Invalid comparison between Unknown and I4
//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
//IL_013e: Unknown result type (might be due to invalid IL or missing references)
//IL_013f: Unknown result type (might be due to invalid IL or missing references)
//IL_0141: Unknown result type (might be due to invalid IL or missing references)
//IL_0143: Unknown result type (might be due to invalid IL or missing references)
//IL_0145: Unknown result type (might be due to invalid IL or missing references)
//IL_0158: Expected I4, but got Unknown
//IL_0219: Unknown result type (might be due to invalid IL or missing references)
//IL_032f: Unknown result type (might be due to invalid IL or missing references)
if ((!modEnabled.Value | __result) || skip || !((Object)(object)__instance != (Object)null) || (((Object)(object)((Component)__instance).transform == (Object)null) ? true : false) || !AllowByKey())
{
return;
}
if (Object.op_Implicit((Object)(object)piece.m_craftingStation))
{
if ((int)mode == 1 || (int)mode == 2)
{
if (!___m_knownStations.ContainsKey(piece.m_craftingStation.m_name))
{
return;
}
}
else if (!Object.op_Implicit((Object)(object)CraftingStation.HaveBuildStationInRange(piece.m_craftingStation.m_name, ((Component)__instance).transform.position)))
{
return;
}
}
if (piece.m_dlc.Length > 0 && !DLCMan.instance.IsDLCInstalled(piece.m_dlc))
{
return;
}
List<Container> nearbyContainers = GetNearbyContainers(((Component)__instance).transform.position);
Requirement[] resources = piece.m_resources;
foreach (Requirement val in resources)
{
if (!Object.op_Implicit((Object)(object)val.m_resItem) || val.m_amount <= 0)
{
continue;
}
int num;
switch ((int)mode)
{
case 0:
num = ((((Humanoid)__instance).GetInventory().CountItems(val.m_resItem.m_itemData.m_shared.m_name, -1, true) < val.m_amount) ? 1 : 0);
break;
case 1:
if (!___m_knownMaterial.Contains(val.m_resItem.m_itemData.m_shared.m_name))
{
return;
}
continue;
case 2:
{
if (((Humanoid)__instance).GetInventory().HaveItem(val.m_resItem.m_itemData.m_shared.m_name, true))
{
continue;
}
bool flag = false;
if (KG_ItemDrawer)
{
try
{
if (ItemDrawer_Patch.HaveRequiredItem(((Object)val.m_resItem).name, ((Component)Player.m_localPlayer).transform.position, m_range.Value) != "")
{
flag = true;
}
}
catch
{
}
}
if (!flag)
{
foreach (Container item in nearbyContainers)
{
if (item.GetInventory().HaveItem(val.m_resItem.m_itemData.m_shared.m_name, true))
{
flag = true;
break;
}
}
}
if (!flag)
{
return;
}
continue;
}
default:
num = 0;
break;
}
if (num == 0)
{
continue;
}
int num2 = ((Humanoid)__instance).GetInventory().CountItems(val.m_resItem.m_itemData.m_shared.m_name, -1, true);
if (KG_ItemDrawer)
{
try
{
num2 += ItemDrawer_Patch.HaveRequiredItemCount(((Object)val.m_resItem).name, ((Component)Player.m_localPlayer).transform.position, m_range.Value);
}
catch
{
}
}
foreach (Container item2 in nearbyContainers)
{
try
{
num2 += item2.GetInventory().CountItems(val.m_resItem.m_itemData.m_shared.m_name, -1, true);
if (num2 >= val.m_amount)
{
break;
}
}
catch
{
}
}
if (num2 < val.m_amount)
{
return;
}
}
__result = true;
}
}
[HarmonyPatch(typeof(Player), "ConsumeResources")]
private static class ConsumeResources_Patch
{
private static bool Prefix(Player __instance, Requirement[] requirements, int qualityLevel = -1, int multiplier = 1)
{
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_019e: Unknown result type (might be due to invalid IL or missing references)
//IL_0110: Unknown result type (might be due to invalid IL or missing references)
if (!modEnabled.Value || !AllowByKey())
{
return true;
}
Inventory inventory = ((Humanoid)__instance).GetInventory();
List<Container> nearbyContainers = GetNearbyContainers(((Component)__instance).transform.position);
foreach (Requirement val in requirements)
{
if (!Object.op_Implicit((Object)(object)val.m_resItem))
{
continue;
}
int num = val.GetAmount(qualityLevel) * multiplier;
if (num <= 0)
{
continue;
}
string name = val.m_resItem.m_itemData.m_shared.m_name;
int num2 = inventory.CountItems(name, -1, true);
Dbgl($"have {num2}/{num} {name} in player inventory");
inventory.RemoveItem(name, Math.Min(num2, num), -1, true);
if (num2 >= num)
{
continue;
}
if (KG_ItemDrawer)
{
try
{
num2 += ItemDrawer_Patch.PullResource(((Object)val.m_resItem).name, num, ((Component)Player.m_localPlayer).transform.position, m_range.Value);
if (num2 >= num)
{
continue;
}
}
catch
{
}
}
foreach (Container item2 in nearbyContainers)
{
Inventory val2 = ((item2 != null) ? item2.GetInventory() : null);
if (val2 == null)
{
continue;
}
int num3 = Mathf.Min(val2.CountItems(name, -1, true), num - num2);
Dbgl($"Container at {((Component)item2).transform.position} has {val2.CountItems(name, -1, true)}");
if (num3 == 0)
{
continue;
}
for (int j = 0; j < val2.GetAllItems().Count; j++)
{
ItemData item = val2.GetItem(j);
if (item?.m_shared?.m_name == name)
{
Dbgl($"Container has a total items count of {val2.GetAllItems().Count}");
Dbgl($"Got stack of {item.m_stack} {name}");
int num4 = Mathf.Min(item.m_stack, num - num2);
if (num4 == item.m_stack)
{
val2.RemoveItem(j);
j--;
}
else
{
item.m_stack -= num4;
}
num2 += num4;
Dbgl($"total amount is now {num2}/{num} {name}");
if (num2 >= num)
{
Dbgl("Got enough, breaking");
break;
}
}
}
Dbgl("Saving container");
typeof(Container).GetMethod("Save", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(item2, new object[0]);
Dbgl("Setting inventory changed");
typeof(Inventory).GetMethod("Changed", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(val2, new object[0]);
if (num2 >= num)
{
Dbgl("consumed enough " + name);
break;
}
}
}
return false;
}
}
[HarmonyPatch(typeof(Player), "UpdatePlacementGhost")]
private static class UpdatePlacementGhost_Patch
{
private static void Postfix(Player __instance, bool flashGuardStone)
{
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0166: Unknown result type (might be due to invalid IL or missing references)
//IL_0171: Unknown result type (might be due to invalid IL or missing references)
//IL_0198: Unknown result type (might be due to invalid IL or missing references)
//IL_019d: Unknown result type (might be due to invalid IL or missing references)
//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
//IL_01be: Unknown result type (might be due to invalid IL or missing references)
//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
//IL_0223: Unknown result type (might be due to invalid IL or missing references)
//IL_0225: Unknown result type (might be due to invalid IL or missing references)
//IL_0227: Unknown result type (might be due to invalid IL or missing references)
//IL_022c: Unknown result type (might be due to invalid IL or missing references)
//IL_0230: Unknown result type (might be due to invalid IL or missing references)
//IL_0235: Unknown result type (might be due to invalid IL or missing references)
//IL_023a: Unknown result type (might be due to invalid IL or missing references)
//IL_0248: Unknown result type (might be due to invalid IL or missing references)
//IL_025c: Unknown result type (might be due to invalid IL or missing references)
//IL_0281: Unknown result type (might be due to invalid IL or missing references)
if (!modEnabled.Value || !showGhostConnections.Value)
{
return;
}
FieldInfo field = typeof(Player).GetField("m_placementGhost", BindingFlags.Instance | BindingFlags.NonPublic);
GameObject val = ((!(field != null)) ? ((GameObject)null) : ((GameObject)field.GetValue(__instance)));
if ((Object)(object)val == (Object)null || (Object)(object)val.GetComponent<Container>() == (Object)null)
{
return;
}
FieldInfo field2 = typeof(CraftingStation).GetField("m_allStations", BindingFlags.Static | BindingFlags.NonPublic);
List<CraftingStation> list = ((field2 != null) ? ((List<CraftingStation>)field2.GetValue(null)) : null);
if ((Object)(object)connectionVfxPrefab == (Object)null)
{
GameObject[] array = Resources.FindObjectsOfTypeAll(typeof(GameObject)) as GameObject[];
foreach (GameObject val2 in array)
{
if (((Object)val2).name == "vfx_ExtensionConnection")
{
connectionVfxPrefab = val2;
break;
}
}
}
if ((Object)(object)connectionVfxPrefab == (Object)null || list == null)
{
return;
}
bool flag = false;
foreach (CraftingStation item in list)
{
int num = ConnectionExists(item);
bool flag2 = num != -1;
if ((double)Vector3.Distance(((Component)item).transform.position, val.transform.position) < (double)m_range.Value)
{
flag = true;
Vector3 connectionEffectPoint = item.GetConnectionEffectPoint();
Vector3 val3 = val.transform.position + Vector3.up * ghostConnectionStartOffset.Value;
ConnectionParams connectionParams;
if (!flag2)
{
connectionParams = new ConnectionParams();
connectionParams.stationPos = item.GetConnectionEffectPoint();
connectionParams.connection = Object.Instantiate<GameObject>(connectionVfxPrefab, connectionEffectPoint, Quaternion.identity);
}
else
{
connectionParams = containerConnections[num];
}
if ((Object)(object)connectionParams.connection != (Object)null)
{
Vector3 val4 = val3 - connectionEffectPoint;
Quaternion rotation = Quaternion.LookRotation(((Vector3)(ref val4)).normalized);
connectionParams.connection.transform.position = connectionEffectPoint;
connectionParams.connection.transform.rotation = rotation;
connectionParams.connection.transform.localScale = new Vector3(1f, 1f, ((Vector3)(ref val4)).magnitude);
}
if (!flag2)
{
containerConnections.Add(connectionParams);
}
}
else if (flag2)
{
Object.Destroy((Object)(object)containerConnections[num].connection);
containerConnections.RemoveAt(num);
}
}
if (flag && (Object)(object)context != (Object)null)
{
((MonoBehaviour)context).CancelInvoke("StopConnectionEffects");
((MonoBehaviour)context).Invoke("StopConnectionEffects", ghostConnectionRemovalDelay.Value);
}
}
}
[HarmonyPatch(typeof(InventoryGui), "OnCraftPressed")]
private static class DoCrafting_Patch
{
private static bool Prefix(InventoryGui __instance, KeyValuePair<Recipe, ItemData> ___m_selectedRecipe, ItemData ___m_craftUpgradeItem)
{
if (!modEnabled.Value || !AllowByKey() || !CheckKeyHeld(pullItemsKey.Value) || (Object)(object)___m_selectedRecipe.Key == (Object)null)
{
return true;
}
int num = ((___m_craftUpgradeItem == null) ? 1 : (___m_craftUpgradeItem.m_quality + 1));
if (num > ___m_selectedRecipe.Key.m_item.m_itemData.m_shared.m_maxQuality)
{
return true;
}
Dbgl("pulling resources to player inventory for crafting item " + ___m_selectedRecipe.Key.m_item.m_itemData.m_shared.m_name);
PullResources(Player.m_localPlayer, ___m_selectedRecipe.Key.m_resources, num);
return false;
}
}
[HarmonyPatch(typeof(Player), "UpdatePlacement")]
private static class UpdatePlacement_Patch
{
private static bool Prefix(Player __instance, bool takeInput, float dt, PieceTable ___m_buildPieces, GameObject ___m_placementGhost)
{
if (!modEnabled.Value || !AllowByKey() || !CheckKeyHeld(pullItemsKey.Value) || !((Character)__instance).InPlaceMode() || !takeInput || Hud.IsPieceSelectionVisible() || (!ZInput.GetButtonDown("Attack") && !ZInput.GetButtonDown("JoyPlace")))
{
return true;
}
Piece selectedPiece = ___m_buildPieces.GetSelectedPiece();
if ((Object)(object)selectedPiece != (Object)null)
{
if (selectedPiece.m_repairPiece)
{
return true;
}
if ((Object)(object)___m_placementGhost != (Object)null && (int)typeof(Player).GetField("m_placementStatus", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance) == 0)
{
Dbgl("pulling resources to player inventory for piece " + ((Object)selectedPiece).name);
PullResources(__instance, selectedPiece.m_resources, 0);
}
}
return false;
}
}
[HarmonyPatch(typeof(Turret), "UseItem")]
private static class Turret_UseItem_Patch
{
private static void Prefix(Turret __instance, Humanoid user, ref ItemData item)
{
//IL_0112: Unknown result type (might be due to invalid IL or missing references)
//IL_0117: Unknown result type (might be due to invalid IL or missing references)
//IL_011e: Unknown result type (might be due to invalid IL or missing references)
//IL_012b: Expected O, but got Unknown
if (!modEnabled.Value || !AllowByKey() || item != null || !(user is Player))
{
Dbgl($"Not allowed {AllowByKey()} {item == null} {user is Player}");
return;
}
item = user.GetInventory().GetAmmoItem(__instance.m_ammoType, (__instance.GetAmmo() > 0) ? __instance.GetAmmoType() : null);
if (item == null)
{
Dbgl("No item found in inventory, checking containers for " + __instance.GetAmmoType());
GameObject prefab = ZNetScene.instance.GetPrefab(__instance.GetAmmoType());
if (!Object.op_Implicit((Object)(object)prefab))
{
Dbgl("No prefab found for " + __instance.GetAmmoType());
ZLog.LogWarning((object)("Turret '" + ((Object)__instance).name + "' is trying to fire but has no ammo or default ammo!"));
return;
}
PullResources((Player)(object)((user is Player) ? user : null), (Requirement[])(object)new Requirement[1]
{
new Requirement
{
m_amount = 1,
m_resItem = prefab.GetComponent<ItemDrop>()
}
}, prefab.GetComponent<ItemDrop>().m_itemData.m_quality);
}
}
}
private static class HaveRequirements_Patch2_broken
{
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
//IL_00da: 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_00f4: Unknown result type (might be due to invalid IL or missing references)
//IL_00fe: Expected O, but got Unknown
//IL_0106: Unknown result type (might be due to invalid IL or missing references)
//IL_0110: Expected O, but got Unknown
//IL_012b: Unknown result type (might be due to invalid IL or missing references)
//IL_0135: Expected O, but got Unknown
//IL_013d: Unknown result type (might be due to invalid IL or missing references)
//IL_0147: Expected O, but got Unknown
//IL_0162: Unknown result type (might be due to invalid IL or missing references)
//IL_016c: Expected O, but got Unknown
//IL_0189: Unknown result type (might be due to invalid IL or missing references)
//IL_0193: Expected O, but got Unknown
//IL_019b: Unknown result type (might be due to invalid IL or missing references)
//IL_01a5: Expected O, but got Unknown
List<CodeInstruction> list = new List<CodeInstruction>(instructions);
for (int i = 0; i < list.Count; i++)
{
CodeInstruction val = list[i];
if (!(val.opcode == OpCodes.Callvirt) || !((object)val).ToString().Contains("IsDLCInstalled"))
{
continue;
}
int num = -1;
for (int j = i + 1; j < i + 5; j++)
{
if (list[j].opcode == OpCodes.Ret)
{
num = j;
break;
}
}
if (num != -1)
{
int num2 = num + 1;
List<Label> labels = list[num2].labels;
list.RemoveRange(num2, list.Count - num2);
list.Add(new CodeInstruction(OpCodes.Ldarg_0, (object)null)
{
labels = labels
});
list.Add(new CodeInstruction(OpCodes.Ldarg_1, (object)null));
list.Add(new CodeInstruction(OpCodes.Ldarg_2, (object)null));
list.Add(new CodeInstruction(OpCodes.Ldarg_0, (object)null));
list.Add(new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(Humanoid), "m_inventory")));
list.Add(new CodeInstruction(OpCodes.Ldarg_0, (object)null));
list.Add(new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(Player), "m_knownMaterial")));
list.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(CraftFromContainers), "HaveRequiredItemCount", (Type[])null, (Type[])null)));
list.Add(new CodeInstruction(OpCodes.Ret, (object)null));
break;
}
Dbgl(">>> FAILED to find targeted code for HaveRequirements transpiler patch!!! Mod will not work!");
}
return list;
}
}
[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("craftfromcontainers reset"))
{
return true;
}
((BaseUnityPlugin)context).Config.Reload();
((BaseUnityPlugin)context).Config.Save();
__instance.AddString(text);
__instance.AddString("Craft From Containers config reloaded");
((TMP_InputField)__instance.m_input).text = "";
return false;
}
}
private static bool wasAllowed;
private static List<ConnectionParams> containerConnections = new List<ConnectionParams>();
private static GameObject connectionVfxPrefab = null;
public static ConfigEntry<bool> showGhostConnections;
public static ConfigEntry<float> ghostConnectionStartOffset;
public static ConfigEntry<float> ghostConnectionRemovalDelay;
public static ConfigEntry<float> m_range;
public static ConfigEntry<Color> flashColor;
public static ConfigEntry<Color> unFlashColor;
public static ConfigEntry<string> resourceString;
public static ConfigEntry<string> pulledMessage;
public static ConfigEntry<string> fuelDisallowTypes;
public static ConfigEntry<string> oreDisallowTypes;
public static ConfigEntry<string> pullItemsKey;
public static ConfigEntry<string> preventModKey;
public static ConfigEntry<string> fillAllModKey;
public static ConfigEntry<bool> switchPrevent;
public static ConfigEntry<bool> ignoreShipContainers;
public static ConfigEntry<bool> ignoreWagonContainers;
public static ConfigEntry<bool> ignoreWoodChests;
public static ConfigEntry<bool> ignorePrivateChests;
public static ConfigEntry<bool> ignoreBlackMetalChests;
public static ConfigEntry<bool> ignoreReinforcedChests;
public static ConfigEntry<bool> modEnabled;
public static ConfigEntry<bool> isDebug;
public static ConfigEntry<int> nexusID;
public static List<Container> containerList = new List<Container>();
public static bool odinsQolInstalled;
public static float itemStackSizeMultiplier;
public static float itemWeightReduction;
public static Vector3 lastPosition = Vector3.positiveInfinity;
public static List<Container> cachedContainerList = new List<Container>();
private static CraftFromContainers context = null;
private static bool skip;
private static bool KG_ItemDrawer = false;
public static void Dbgl(string str = "", bool pref = true)
{
if (isDebug.Value)
{
((BaseUnityPlugin)context).Logger.Log((LogLevel)32, (object)((pref ? (typeof(CraftFromContainers).Namespace + " ") : "") + str));
}
}
private void Awake()
{
//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
context = this;
modEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable this mod");
isDebug = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "IsDebug", true, "Show debug messages in log");
nexusID = ((BaseUnityPlugin)this).Config.Bind<int>("General", "NexusID", 40, "Nexus mod ID for updates");
m_range = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ContainerRange", 10f, "The maximum range from which to pull items from");
resourceString = ((BaseUnityPlugin)this).Config.Bind<string>("General", "ResourceCostString", "{0}/{1}", "String used to show required and available resources. {0} is replaced by how much is available, and {1} is replaced by how much is required. Set to nothing to leave it as default.");
flashColor = ((BaseUnityPlugin)this).Config.Bind<Color>("General", "FlashColor", Color.yellow, "Resource amounts will flash to this colour when coming from containers");
unFlashColor = ((BaseUnityPlugin)this).Config.Bind<Color>("General", "UnFlashColor", Color.white, "Resource amounts will flash from this colour when coming from containers (set both colors to the same color for no flashing)");
pulledMessage = ((BaseUnityPlugin)this).Config.Bind<string>("General", "PulledMessage", "Pulled items to inventory", "Message to show after pulling items to player inventory");
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).");
showGhostConnections = ((BaseUnityPlugin)this).Config.Bind<bool>("Station Connections", "ShowConnections", false, "If true, will display connections to nearby workstations within range when building containers");
ghostConnectionStartOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Station Connections", "ConnectionStartOffset", 1.25f, "Height offset for the connection VFX start position");
ghostConnectionRemovalDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Station Connections", "ConnectionRemoveDelay", 0.05f, "");
switchPrevent = ((BaseUnityPlugin)this).Config.Bind<bool>("Hot Keys", "SwitchPrevent", false, "if true, holding down the PreventModKey modifier key will allow this mod's behaviour; if false, holding down the key will prevent it.");
preventModKey = ((BaseUnityPlugin)this).Config.Bind<string>("Hot Keys", "PreventModKey", "left alt", "Modifier key to toggle fuel and ore filling behaviour when down. Use https://docs.unity3d.com/Manual/ConventionalGameInput.html");
pullItemsKey = ((BaseUnityPlugin)this).Config.Bind<string>("Hot Keys", "PullItemsKey", "left ctrl", "Holding down this key while crafting or building will pull resources into your inventory instead of building. Use https://docs.unity3d.com/Manual/ConventionalGameInput.html");
fillAllModKey = ((BaseUnityPlugin)this).Config.Bind<string>("Hot Keys", "FillAllModKey", "left shift", "Modifier key to pull all available fuel or ore when down. Use https://docs.unity3d.com/Manual/ConventionalGameInput.html");
ignoreShipContainers = ((BaseUnityPlugin)this).Config.Bind<bool>("Container Types", "IgnoreShipContainers", false, "If true, will ignore this type of container.");
ignoreWagonContainers = ((BaseUnityPlugin)this).Config.Bind<bool>("Container Types", "IgnoreWagonContainers", false, "If true, will ignore this type of container.");
ignoreWoodChests = ((BaseUnityPlugin)this).Config.Bind<bool>("Container Types", "IgnoreWoodChests", false, "If true, will ignore this type of container.");
ignorePrivateChests = ((BaseUnityPlugin)this).Config.Bind<bool>("Container Types", "IgnorePrivateChests", false, "If true, will ignore this type of container.");
ignoreBlackMetalChests = ((BaseUnityPlugin)this).Config.Bind<bool>("Container Types", "IgnoreBlackMetalChests", false, "If true, will ignore this type of container.");
ignoreReinforcedChests = ((BaseUnityPlugin)this).Config.Bind<bool>("Container Types", "IgnoreReinforcedChests", false, "If true, will ignore this type of container.");
wasAllowed = !switchPrevent.Value;
string path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "kg_ItemDrawers.dll");
KG_ItemDrawer = File.Exists(path);
Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null);
Dbgl("Mod awake");
}
private void LateUpdate()
{
wasAllowed = AllowByKey();
skip = false;
}
private static bool AllowByKey()
{
return CheckKeyHeld(preventModKey.Value) ? switchPrevent.Value : (!switchPrevent.Value);
}
private void OnDestroy()
{
StopConnectionEffects();
}
private static bool CheckKeyHeld(string value, bool req = true)
{
try
{
return Input.GetKey(value.ToLower());
}
catch
{
return !req;
}
}
public static List<Container> GetNearbyContainers(Vector3 center)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0193: Unknown result type (might be due to invalid IL or missing references)
//IL_0194: Unknown result type (might be due to invalid IL or missing references)
//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
//IL_00af: Unknown result type (might be due to invalid IL or missing references)
//IL_013e: Unknown result type (might be due to invalid IL or missing references)
List<Container> list = new List<Container>();
if ((Object)(object)Player.m_localPlayer == (Object)null)
{
return list;
}
if ((double)Vector3.Distance(center, lastPosition) < 0.5)
{
return cachedContainerList;
}
MethodInfo methodInfo = AccessTools.Method(typeof(Container), "CheckAccess", (Type[])null, (Type[])null);
foreach (Container container in containerList)
{
if ((Object)(object)container != (Object)null && (Object)(object)((Component)container).transform != (Object)null && ((double)m_range.Value <= 0.0 || (double)Vector3.Distance(center, ((Component)container).transform.position) < (double)m_range.Value) && AllowContainerType(container) && (bool)methodInfo.Invoke(container, new object[1] { Player.m_localPlayer.GetPlayerID() }) && !container.IsInUse() && (Object)(object)((Component)container).GetComponentInParent<Piece>() != (Object)null && container.GetInventory() != null && (!container.m_checkGuardStone || (PrivateArea.CheckAccess(((Component)container).transform.position, 0f, false, false) ? true : false)))
{
list.Add(container);
}
}
lastPosition = center;
cachedContainerList = list;
return list;
}
private static bool AllowContainerType(Container __instance)
{
Transform parent = ((Component)__instance).gameObject.transform.parent;
Ship val = ((parent != null) ? ((Component)parent).GetComponent<Ship>() : null);
return (!ignoreShipContainers.Value || (Object)(object)val == (Object)null) && (!ignoreWagonContainers.Value || (Object)(object)__instance.m_wagon == (Object)null) && (!ignoreWoodChests.Value || !((Object)__instance).name.StartsWith("piece_chest_wood(")) && (!ignorePrivateChests.Value || !((Object)__instance).name.StartsWith("piece_chest_private(")) && (!ignoreBlackMetalChests.Value || !((Object)__instance).name.StartsWith("piece_chest_blackmetal(")) && (!ignoreReinforcedChests.Value || !((Object)__instance).name.StartsWith("piece_chest("));
}
public static IEnumerator AddContainer(Container container, ZNetView nview)
{
yield return null;
try
{
int num;
if (container.GetInventory() != null)
{
if (((nview != null) ? nview.GetZDO() : null) != null)
{
num = ((((Object)container).name.StartsWith("piece_") || ((Object)container).name.StartsWith("Container") || nview.GetZDO().GetLong(StringExtensionMethods.GetStableHashCode("creator"), 0L) != 0) ? 1 : 0);
goto IL_00ad;
}
}
num = 0;
goto IL_00ad;
IL_00ad:
if (num != 0)
{
Dbgl("Adding " + ((Object)container).name);
containerList.Add(container);
}
}
catch
{
}
}
public static int ConnectionExists(CraftingStation station)
{
//IL_0019: 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)
foreach (ConnectionParams containerConnection in containerConnections)
{
if ((double)Vector3.Distance(containerConnection.stationPos, station.GetConnectionEffectPoint()) < 0.10000000149011612)
{
return containerConnections.IndexOf(containerConnection);
}
}
return -1;
}
public void StopConnectionEffects()
{
if (containerConnections.Count > 0)
{
foreach (ConnectionParams containerConnection in containerConnections)
{
Object.Destroy((Object)(object)containerConnection.connection);
}
}
containerConnections.Clear();
}
private static void PullResources(Player player, Requirement[] resources, int qualityLevel)
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0130: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
Inventory inventory = ((Humanoid)Player.m_localPlayer).GetInventory();
List<Container> nearbyContainers = GetNearbyContainers(((Component)Player.m_localPlayer).transform.position);
foreach (Requirement val in resources)
{
if (Object.op_Implicit((Object)(object)val.m_resItem))
{
int amount = val.GetAmount(qualityLevel);
if (amount <= 0)
{
continue;
}
string name = val.m_resItem.m_itemData.m_shared.m_name;
int num = 0;
if (KG_ItemDrawer)
{
try
{
num = ItemDrawer_Patch.PullResource(((Object)val.m_resItem).name, amount, ((Component)Player.m_localPlayer).transform.position, m_range.Value);
if (num >= amount)
{
continue;
}
}
catch (Exception ex)
{
Dbgl("ItemDrawer_Patch.PullResource ex " + ex.Message);
}
}
foreach (Container item2 in nearbyContainers)
{
Inventory inventory2 = item2.GetInventory();
int num2 = Mathf.Min(inventory2.CountItems(name, -1, true), amount - num);
Dbgl($"Container at {((Component)item2).transform.position} has {inventory2.CountItems(name, -1, true)}");
if (num2 == 0)
{
continue;
}
for (int j = 0; j < inventory2.GetAllItems().Count; j++)
{
ItemData item = inventory2.GetItem(j);
if (!(item.m_shared.m_name == name))
{
continue;
}
Dbgl($"Got stack of {item.m_stack} {name}");
int num3 = Mathf.Min(item.m_stack, amount - num);
if (!inventory.HaveEmptySlot())
{
num3 = Math.Min(Traverse.Create((object)inventory).Method("FindFreeStackSpace", new object[1] { item.m_shared.m_name }).GetValue<int>(), num3);
}
Dbgl($"Sending {num3} {name} to player");
ItemData val2 = item.Clone();
val2.m_stack = num3;
if (odinsQolInstalled)
{
if ((double)itemStackSizeMultiplier > 0.0)
{
val2.m_shared.m_weight = ApplyModifierValue(val2.m_shared.m_weight, itemWeightReduction);
if (val2.m_shared.m_maxStackSize > 1 && (double)itemStackSizeMultiplier >= 1.0)
{
val2.m_shared.m_maxStackSize = (int)ApplyModifierValue(val.m_resItem.m_itemData.m_shared.m_maxStackSize, itemStackSizeMultiplier);
}
}
}
else
{
val2.m_shared.m_maxStackSize = val.m_resItem.m_itemData.m_shared.m_maxStackSize;
}
inventory.AddItem(val2);
if (num3 == item.m_stack)
{
inventory2.RemoveItem(j);
}
else
{
item.m_stack -= num3;
}
num += num3;
Dbgl($"total amount is now {num}/{amount} {name}");
if (num >= amount)
{
break;
}
}
((object)item2).GetType().GetMethod("Save", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(item2, new object[0]);
((object)inventory2).GetType().GetMethod("Changed", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(inventory2, new object[0]);
if (num >= amount)
{
Dbgl("pulled enough " + name);
break;
}
}
}
string value = pulledMessage.Value;
if (value != null && value.Length > 0)
{
((Character)player).Message((MessageType)2, pulledMessage.Value, 0, (Sprite)null);
}
}
}
public static bool HaveRequiredItemCount(Player player, Piece piece, RequirementMode mode, Inventory inventory, HashSet<string> knownMaterial)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Expected I4, but got Unknown
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
//IL_020f: Unknown result type (might be due to invalid IL or missing references)
List<Container> nearbyContainers = GetNearbyContainers(((Component)player).transform.position);
Requirement[] resources = piece.m_resources;
foreach (Requirement val in resources)
{
if (!Object.op_Implicit((Object)(object)val.m_resItem) || val.m_amount <= 0)
{
continue;
}
switch ((int)mode)
{
case 0:
{
int num = inventory.CountItems(val.m_resItem.m_itemData.m_shared.m_name, -1, true);
if (num >= val.m_amount)
{
break;
}
if (KG_ItemDrawer)
{
try
{
num += ItemDrawer_Patch.HaveRequiredItemCount(((Object)val.m_resItem).name, ((Component)Player.m_localPlayer).transform.position, m_range.Value);
if (num >= val.m_amount)
{
break;
}
}
catch
{
}
}
bool flag2 = false;
foreach (Container item in nearbyContainers)
{
try
{
num += item.GetInventory().CountItems(val.m_resItem.m_itemData.m_shared.m_name, -1, true);
if (num >= val.m_amount)
{
flag2 = true;
break;
}
}
catch
{
}
}
if (!flag2)
{
return false;
}
break;
}
case 1:
if (!knownMaterial.Contains(val.m_resItem.m_itemData.m_shared.m_name))
{
return false;
}
break;
case 2:
{
if (inventory.HaveItem(val.m_resItem.m_itemData.m_shared.m_name, true))
{
break;
}
if (KG_ItemDrawer)
{
try
{
if (ItemDrawer_Patch.HaveRequiredItem(((Object)val.m_resItem).name, ((Component)Player.m_localPlayer).transform.position, m_range.Value) != "")
{
break;
}
}
catch
{
}
}
bool flag = false;
foreach (Container item2 in nearbyContainers)
{
if (item2.GetInventory().HaveItem(val.m_resItem.m_itemData.m_shared.m_name, true))
{
flag = true;
break;
}
}
if (!flag)
{
return false;
}
break;
}
}
}
return true;
}
public static void CheckOdinsQOLConfig()
{
itemStackSizeMultiplier = 0f;
itemWeightReduction = 0f;
foreach (PluginInfo value in Chainloader.PluginInfos.Values)
{
if (!(((value != null) ? value.Metadata.GUID : null) == "com.odinplusqol.mod"))
{
continue;
}
odinsQolInstalled = modEnabled.Value;
Debug.Log((object)"Found OdinPlusQoL");
foreach (ConfigDefinition key in value.Instance.Config.Keys)
{
if (key.Key == "Item Stack Increase")
{
itemStackSizeMultiplier = (float)value.Instance.Config[key].BoxedValue;
}
if (key.Key == "Item Weight Increase")
{
itemWeightReduction = (float)value.Instance.Config[key].BoxedValue;
}
}
}
}
public static float ApplyModifierValue(float targetValue, float value)
{
if ((double)value <= -100.0)
{
value = -100f;
}
return ((double)value < 0.0) ? (targetValue - (float)((double)targetValue / 100.0 * ((double)value * -1.0))) : (targetValue + targetValue / 100f * value);
}
}
internal static class ItemDrawer_Patch
{
internal static int HaveRequiredItemCount(string Name, Vector3 Pos, float Range)
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
Name = Name.Replace("$item_", "").ToLower();
List<Drawer> list = ItemDrawers_API.AllDrawersInRange(Pos, Range);
int num = 0;
foreach (Drawer item in list)
{
if (Name == item.Prefab.ToLower())
{
num += item.Amount;
}
}
return num;
}
internal static string HaveRequiredItem(string Name, Vector3 Pos, float Range)
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
Name = Name.Replace("$item_", "").ToLower();
List<Drawer> list = ItemDrawers_API.AllDrawersInRange(Pos, Range);
foreach (Drawer item in list)
{
CraftFromContainers.Dbgl("HaveRequiredItem Drawer: " + item.Prefab);
if (Name == item.Prefab.ToLower())
{
return item.Prefab;
}
}
return "";
}
internal static int PullResource(string Name, int Amount, Vector3 Pos, float Range)
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
Name = Name.Replace("$item_", "").ToLower();
List<Drawer> list = ItemDrawers_API.AllDrawersInRange(Pos, Range);
int num = 0;
foreach (Drawer item in list)
{
if (Name == item.Prefab.ToLower())
{
if (item.Amount - Amount > 0)
{
item.Remove(Amount);
num += Amount;
}
else
{
num += item.Amount;
Amount -= item.Amount;
item.Remove(item.Amount);
}
}
}
return num;
}
}