Decompiled source of FixedNestedContainers v2.4.0

FixedNestedContainers.dll

Decompiled 2 months ago
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;
		}
	}
}