using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace FixedNestedContainers;
public static class PluginInfo
{
public const string PLUGIN_GUID = "com.fixed.nestedcontainers";
public const string PLUGIN_NAME = "FixedNestedContainers";
public const string PLUGIN_VERSION = "2.4.0";
}
[BepInPlugin("com.fixed.nestedcontainers", "FixedNestedContainers", "2.4.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Plugin : BaseUnityPlugin
{
internal static ManualLogSource Log;
private Harmony _harmony;
private void Awake()
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
try
{
_harmony = new Harmony("com.fixed.nestedcontainers");
_harmony.PatchAll(typeof(Plugin).Assembly);
Log.LogInfo((object)string.Format("{0} v{1} loaded.", "FixedNestedContainers", "2.4.0"));
}
catch (Exception ex)
{
Log.LogError((object)("Failed to load: " + ex));
}
}
private void OnDestroy()
{
if (_harmony != null)
{
_harmony.UnpatchSelf();
}
}
}
[HarmonyPatch]
public static class BackpackWheelSlice_canInteract_Patch
{
private static MethodBase TargetMethod()
{
Type type = AccessTools.TypeByName("BackpackWheelSlice");
if (type == null)
{
return null;
}
PropertyInfo propertyInfo = AccessTools.Property(type, "canInteract");
if (propertyInfo != null)
{
MethodInfo getMethod = propertyInfo.GetGetMethod(nonPublic: true);
if (getMethod != null)
{
return getMethod;
}
}
return AccessTools.Method(type, "get_canInteract", (Type[])null, (Type[])null);
}
private static void Postfix(ref bool __result)
{
if (__result)
{
return;
}
try
{
object localCurrentItem = Helpers.GetLocalCurrentItem();
if (localCurrentItem != null && Helpers.IsNestableContainer(localCurrentItem))
{
__result = true;
}
}
catch
{
}
}
}
[HarmonyPatch]
public static class BackpackWheel_Choose_Patch
{
private static MethodBase TargetMethod()
{
Type type = AccessTools.TypeByName("BackpackWheel");
return (!(type == null)) ? AccessTools.Method(type, "Choose", (Type[])null, (Type[])null) : null;
}
private static bool Prefix(object __instance)
{
try
{
FieldInfo fieldInfo = AccessTools.Field(__instance.GetType(), "chosenSlice");
if (fieldInfo == null)
{
return true;
}
object value = fieldInfo.GetValue(__instance);
if (value == null)
{
return true;
}
MethodInfo method = value.GetType().GetMethod("get_IsSome");
if (method == null || !(bool)method.Invoke(value, null))
{
return true;
}
MethodInfo method2 = value.GetType().GetMethod("get_Value");
if (method2 == null)
{
return true;
}
object obj = method2.Invoke(value, null);
if (obj == null)
{
return true;
}
Type type = obj.GetType();
FieldInfo fieldInfo2 = AccessTools.Field(type, "isBackpackWear");
if (fieldInfo2 != null && (bool)fieldInfo2.GetValue(obj))
{
return true;
}
FieldInfo fieldInfo3 = AccessTools.Field(type, "isStashSlice");
if (fieldInfo3 != null && (bool)fieldInfo3.GetValue(obj))
{
return true;
}
FieldInfo fieldInfo4 = AccessTools.Field(type, "isJetpackFuelSlice");
if (fieldInfo4 != null && (bool)fieldInfo4.GetValue(obj))
{
return true;
}
FieldInfo fieldInfo5 = AccessTools.Field(type, "slotID");
if (fieldInfo5 == null)
{
return true;
}
byte b = Convert.ToByte(fieldInfo5.GetValue(obj));
FieldInfo fieldInfo6 = AccessTools.Field(type, "backpackReference");
if (fieldInfo6 == null)
{
return true;
}
object value2 = fieldInfo6.GetValue(obj);
if (value2 == null)
{
return true;
}
MethodInfo methodInfo = AccessTools.Method(value2.GetType(), "GetData", (Type[])null, (Type[])null);
if (methodInfo == null)
{
return true;
}
object obj2 = methodInfo.Invoke(value2, null);
if (obj2 == null)
{
return true;
}
FieldInfo fieldInfo7 = AccessTools.Field(obj2.GetType(), "itemSlots");
if (fieldInfo7 == null)
{
return true;
}
if (!(fieldInfo7.GetValue(obj2) is Array array) || b >= array.Length)
{
return true;
}
object value3 = array.GetValue(b);
if (value3 == null)
{
return true;
}
MethodInfo methodInfo2 = AccessTools.Method(value3.GetType(), "IsEmpty", (Type[])null, (Type[])null);
if (methodInfo2 != null && (bool)methodInfo2.Invoke(value3, null))
{
return true;
}
PropertyInfo propertyInfo = AccessTools.Property(value3.GetType(), "prefab");
object obj3 = ((!(propertyInfo != null)) ? null : propertyInfo.GetValue(value3, null));
if (obj3 == null || !Helpers.IsNestableContainer(obj3))
{
return true;
}
if (Plugin.Log != null)
{
Plugin.Log.LogInfo((object)("Take-out nested container into slot: " + Helpers.GetItemName(obj3)));
}
if (Helpers.TakeOutToHands(value2, value3, b, obj3))
{
return false;
}
if (Plugin.Log != null)
{
Plugin.Log.LogWarning((object)"TakeOutToHands failed");
}
}
catch (Exception ex)
{
if (Plugin.Log != null)
{
Plugin.Log.LogWarning((object)("Choose prefix error: " + ex));
}
}
return true;
}
}
[HarmonyPatch]
public static class Item_ClearDataFromBackpack_Patch
{
private static MethodBase TargetMethod()
{
Type type = AccessTools.TypeByName("Item");
return (!(type == null)) ? AccessTools.Method(type, "ClearDataFromBackpack", (Type[])null, (Type[])null) : null;
}
private static bool Prefix(object __instance)
{
try
{
if (Helpers.IsNestableContainer(__instance))
{
return false;
}
}
catch
{
}
return true;
}
}
[HarmonyPatch]
public static class Player_HasEmptySlot_Patch
{
private static MethodBase TargetMethod()
{
Type type = AccessTools.TypeByName("Player");
if (type == null)
{
return null;
}
return AccessTools.Method(type, "HasEmptySlot", new Type[1] { typeof(ushort) }, (Type[])null);
}
private static void Postfix(object __instance, ref bool __result)
{
if (__result)
{
return;
}
try
{
FieldInfo fieldInfo = AccessTools.Field(__instance.GetType(), "itemSlots");
if (fieldInfo == null || !(fieldInfo.GetValue(__instance) is Array array))
{
return;
}
for (int i = 0; i < array.Length; i++)
{
object value = array.GetValue(i);
if (value != null)
{
MethodInfo methodInfo = AccessTools.Method(value.GetType(), "IsEmpty", (Type[])null, (Type[])null);
if (methodInfo != null && (bool)methodInfo.Invoke(value, null))
{
__result = true;
break;
}
}
}
}
catch
{
}
}
}
[HarmonyPatch]
public static class Player_AddToSlot_Patch
{
private static MethodBase TargetMethod()
{
Type type = AccessTools.TypeByName("Player");
if (type == null)
{
return null;
}
MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (MethodInfo methodInfo in methods)
{
if (methodInfo.Name.Contains("AddToSlot"))
{
return methodInfo;
}
}
return null;
}
private static bool Prefix(object __instance, object __0, ref object __result)
{
try
{
if (__0 == null)
{
return true;
}
FieldInfo fieldInfo = AccessTools.Field(__0.GetType(), "ItemPrefab");
if (fieldInfo == null)
{
return true;
}
object value = fieldInfo.GetValue(__0);
if (value == null || !Helpers.IsNestableContainer(value))
{
return true;
}
FieldInfo fieldInfo2 = AccessTools.Field(__0.GetType(), "instanceData");
object obj = ((!(fieldInfo2 != null)) ? null : fieldInfo2.GetValue(__0));
FieldInfo fieldInfo3 = AccessTools.Field(__instance.GetType(), "backpackSlot");
if (fieldInfo3 != null)
{
object value2 = fieldInfo3.GetValue(__instance);
if (value2 != null)
{
MethodInfo methodInfo = AccessTools.Method(value2.GetType(), "IsEmpty", (Type[])null, (Type[])null);
if (methodInfo != null && (bool)methodInfo.Invoke(value2, null))
{
MethodInfo methodInfo2 = AccessTools.Method(value2.GetType(), "SetItem", (Type[])null, (Type[])null);
if (methodInfo2 != null)
{
try
{
FieldInfo fieldInfo4 = AccessTools.Field(value2.GetType(), "backpackType");
FieldInfo fieldInfo5 = AccessTools.Field(value.GetType(), "backpackType");
if (fieldInfo4 != null && fieldInfo5 != null)
{
fieldInfo4.SetValue(value2, fieldInfo5.GetValue(value));
}
}
catch
{
}
methodInfo2.Invoke(value2, new object[2] { value, obj });
__result = value2;
if (Plugin.Log != null)
{
Plugin.Log.LogInfo((object)"AddToSlot: container → backpack slot (4th)");
}
return false;
}
}
}
}
FieldInfo fieldInfo6 = AccessTools.Field(__instance.GetType(), "itemSlots");
if (fieldInfo6 == null)
{
return true;
}
if (!(fieldInfo6.GetValue(__instance) is Array array))
{
return true;
}
for (int i = 0; i < array.Length; i++)
{
object value3 = array.GetValue(i);
if (value3 == null)
{
continue;
}
MethodInfo methodInfo3 = AccessTools.Method(value3.GetType(), "IsEmpty", (Type[])null, (Type[])null);
if (methodInfo3 == null || !(bool)methodInfo3.Invoke(value3, null))
{
continue;
}
MethodInfo methodInfo4 = AccessTools.Method(value3.GetType(), "SetItem", (Type[])null, (Type[])null);
if (!(methodInfo4 == null))
{
methodInfo4.Invoke(value3, new object[2] { value, obj });
__result = value3;
if (Plugin.Log != null)
{
Plugin.Log.LogInfo((object)("AddToSlot: container → hand slot " + i));
}
return false;
}
}
}
catch (Exception ex)
{
if (Plugin.Log != null)
{
Plugin.Log.LogWarning((object)("AddToSlot prefix: " + ex.Message));
}
}
return true;
}
}
internal static class Helpers
{
public static object GetLocalCurrentItem()
{
Type type = AccessTools.TypeByName("Character");
if (type == null)
{
return null;
}
object value = AccessTools.Field(type, "localCharacter").GetValue(null);
if (value == null)
{
return null;
}
object value2 = AccessTools.Field(value.GetType(), "data").GetValue(value);
if (value2 == null)
{
return null;
}
MethodInfo methodInfo = AccessTools.Method(value2.GetType(), "get_currentItem", (Type[])null, (Type[])null);
return (!(methodInfo != null)) ? null : methodInfo.Invoke(value2, null);
}
public static bool IsNestableContainer(object item)
{
if (item == null)
{
return false;
}
try
{
Type type = AccessTools.TypeByName("Backpack");
if (type != null && type.IsInstanceOfType(item))
{
return true;
}
}
catch
{
}
string itemName = GetItemName(item);
if (string.IsNullOrEmpty(itemName))
{
return false;
}
string text = itemName.ToLowerInvariant();
return text.Contains("backpack") || text.Contains("fanny") || text.Contains("jetpack") || text.Contains("rocketpack");
}
public static string GetItemName(object item)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Expected O, but got Unknown
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
if (item == null)
{
return null;
}
try
{
if (item is Component)
{
Component val = (Component)item;
if ((Object)(object)val.gameObject != (Object)null)
{
return ((Object)val.gameObject).name;
}
}
if (item is GameObject)
{
return ((Object)(GameObject)item).name;
}
MethodInfo methodInfo = AccessTools.Method(item.GetType(), "GetPrefabName", (Type[])null, (Type[])null);
if (methodInfo != null)
{
string text = methodInfo.Invoke(item, null) as string;
if (!string.IsNullOrEmpty(text))
{
return text;
}
}
PropertyInfo propertyInfo = AccessTools.Property(item.GetType(), "name");
if (propertyInfo != null)
{
string text2 = propertyInfo.GetValue(item, null) as string;
if (!string.IsNullOrEmpty(text2))
{
return text2;
}
}
return item.ToString();
}
catch
{
return null;
}
}
public static bool TakeOutToHands(object bpRef, object bpItemSlot, byte bpSlotId, object prefab)
{
try
{
Type type = AccessTools.TypeByName("Character");
object value = AccessTools.Field(type, "localCharacter").GetValue(null);
if (value == null)
{
return false;
}
MethodInfo methodInfo = AccessTools.Method(value.GetType(), "get_player", (Type[])null, (Type[])null);
object obj = ((!(methodInfo != null)) ? null : methodInfo.Invoke(value, null));
if (obj == null)
{
return false;
}
object obj2 = null;
byte b = 3;
FieldInfo fieldInfo = AccessTools.Field(obj.GetType(), "backpackSlot");
if (fieldInfo != null)
{
object value2 = fieldInfo.GetValue(obj);
if (value2 != null)
{
MethodInfo methodInfo2 = AccessTools.Method(value2.GetType(), "IsEmpty", (Type[])null, (Type[])null);
if (methodInfo2 != null && (bool)methodInfo2.Invoke(value2, null))
{
obj2 = value2;
b = 3;
}
}
}
if (obj2 == null)
{
FieldInfo fieldInfo2 = AccessTools.Field(obj.GetType(), "itemSlots");
if (fieldInfo2 == null)
{
return false;
}
if (!(fieldInfo2.GetValue(obj) is Array array))
{
return false;
}
for (int i = 0; i < array.Length; i++)
{
object value3 = array.GetValue(i);
if (value3 != null)
{
MethodInfo methodInfo3 = AccessTools.Method(value3.GetType(), "IsEmpty", (Type[])null, (Type[])null);
if (methodInfo3 != null && (bool)methodInfo3.Invoke(value3, null))
{
obj2 = value3;
FieldInfo fieldInfo3 = AccessTools.Field(value3.GetType(), "itemSlotID");
b = ((!(fieldInfo3 != null)) ? ((byte)i) : Convert.ToByte(fieldInfo3.GetValue(value3)));
break;
}
}
}
}
if (obj2 == null)
{
if (Plugin.Log != null)
{
Plugin.Log.LogWarning((object)"No free slot (backpack or hand) — cannot take out container");
}
return false;
}
object obj3 = null;
PropertyInfo propertyInfo = AccessTools.Property(bpItemSlot.GetType(), "data");
if (propertyInfo != null)
{
obj3 = propertyInfo.GetValue(bpItemSlot, null);
}
object obj4 = null;
MethodInfo methodInfo4 = AccessTools.Method(bpRef.GetType(), "GetVisuals", (Type[])null, (Type[])null);
object obj5 = ((!(methodInfo4 != null)) ? null : methodInfo4.Invoke(bpRef, null));
if (obj5 != null)
{
MethodInfo methodInfo5 = AccessTools.Method(obj5.GetType(), "TryGetSpawnedItem", (Type[])null, (Type[])null);
if (methodInfo5 != null)
{
object[] array2 = new object[2] { bpSlotId, null };
if ((bool)methodInfo5.Invoke(obj5, array2))
{
obj4 = array2[1];
}
}
}
if (obj4 == null)
{
obj4 = prefab;
}
MethodInfo methodInfo6 = AccessTools.Method(obj2.GetType(), "SetItem", (Type[])null, (Type[])null);
if (methodInfo6 == null)
{
return false;
}
try
{
FieldInfo fieldInfo4 = AccessTools.Field(obj2.GetType(), "backpackType");
FieldInfo fieldInfo5 = AccessTools.Field(prefab.GetType(), "backpackType");
if (fieldInfo4 != null && fieldInfo5 != null)
{
fieldInfo4.SetValue(obj2, fieldInfo5.GetValue(prefab));
}
}
catch
{
}
methodInfo6.Invoke(obj2, new object[2] { prefab, obj3 });
MethodInfo methodInfo7 = AccessTools.Method(bpItemSlot.GetType(), "EmptyOut", (Type[])null, (Type[])null);
if (methodInfo7 != null)
{
methodInfo7.Invoke(bpItemSlot, null);
}
if (obj5 != null)
{
try
{
FieldInfo fieldInfo6 = AccessTools.Field(obj5.GetType(), "spawnedVisualItems");
if (fieldInfo6 != null)
{
object value4 = fieldInfo6.GetValue(obj5);
if (value4 != null)
{
MethodInfo method = value4.GetType().GetMethod("Remove", new Type[1] { typeof(byte) });
if (method != null)
{
method.Invoke(value4, new object[1] { bpSlotId });
}
}
}
}
catch
{
}
}
if (obj4 != null)
{
try
{
FieldInfo fieldInfo7 = AccessTools.Field(obj4.GetType(), "backpackReference");
if (fieldInfo7 != null)
{
Type fieldType = fieldInfo7.FieldType;
object obj8 = null;
PropertyInfo propertyInfo2 = AccessTools.Property(fieldType, "None");
if (propertyInfo2 != null)
{
obj8 = propertyInfo2.GetValue(null, null);
}
else
{
MethodInfo methodInfo8 = AccessTools.Method(fieldType, "get_None", (Type[])null, (Type[])null);
if (methodInfo8 != null)
{
obj8 = methodInfo8.Invoke(null, null);
}
}
if (obj8 != null)
{
fieldInfo7.SetValue(obj4, obj8);
}
}
FieldInfo fieldInfo8 = AccessTools.Field(obj4.GetType(), "backpackSlotTransform");
if (fieldInfo8 != null)
{
fieldInfo8.SetValue(obj4, null);
}
}
catch
{
}
}
try
{
object obj10 = null;
FieldInfo fieldInfo9 = AccessTools.Field(value.GetType(), "refs");
if (fieldInfo9 != null)
{
object value5 = fieldInfo9.GetValue(value);
if (value5 != null)
{
FieldInfo fieldInfo10 = AccessTools.Field(value5.GetType(), "items");
if (fieldInfo10 != null)
{
obj10 = fieldInfo10.GetValue(value5);
}
}
}
if (obj10 != null)
{
MethodInfo methodInfo9 = AccessTools.Method(obj10.GetType(), "EquipSlot", (Type[])null, (Type[])null);
if (methodInfo9 != null)
{
Type parameterType = methodInfo9.GetParameters()[0].ParameterType;
MethodInfo methodInfo10 = AccessTools.Method(parameterType, "Some", (Type[])null, (Type[])null);
if (methodInfo10 == null)
{
MethodInfo[] methods = parameterType.GetMethods(BindingFlags.Static | BindingFlags.Public);
foreach (MethodInfo methodInfo11 in methods)
{
if (methodInfo11.Name == "Some" && methodInfo11.GetParameters().Length == 1)
{
methodInfo10 = methodInfo11;
break;
}
}
}
if (methodInfo10 != null)
{
object obj11 = methodInfo10.Invoke(null, new object[1] { b });
methodInfo9.Invoke(obj10, new object[1] { obj11 });
if (Plugin.Log != null)
{
Plugin.Log.LogInfo((object)("Equipped hand slot " + b));
}
}
}
}
}
catch (Exception ex)
{
if (Plugin.Log != null)
{
Plugin.Log.LogWarning((object)("EquipSlot failed: " + ex.Message));
}
}
try
{
if (obj5 != null)
{
MethodInfo methodInfo12 = AccessTools.Method(obj5.GetType(), "RefreshVisuals", (Type[])null, (Type[])null);
if (methodInfo12 != null)
{
methodInfo12.Invoke(obj5, null);
}
}
}
catch
{
}
if (Plugin.Log != null)
{
Plugin.Log.LogInfo((object)("Nested container moved to slot " + b));
}
return true;
}
catch (Exception ex2)
{
if (Plugin.Log != null)
{
Plugin.Log.LogError((object)("TakeOutToHands failed: " + ex2));
}
return false;
}
}
}