Decompiled source of MoreInventorySlots v1.0.3

MoreInventorySlots.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("MoreInventorySlots")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("MoreInventorySlots")]
[assembly: AssemblyTitle("MoreInventorySlots")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace MoreInventorySlots
{
	[BepInPlugin("h4rv.yapyap.moreinventoryslots", "More Inventory Slots", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "h4rv.yapyap.moreinventoryslots";

		public const string PluginName = "More Inventory Slots";

		public const string PluginVersion = "1.0.0";

		internal static ManualLogSource Log;

		internal static ConfigEntry<int> MaxSlotsConfig;

		internal static ConfigEntry<bool> ExpandUI;

		internal static ConfigEntry<float> HorizontalOffset;

		private void Awake()
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			MaxSlotsConfig = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MaxInventorySlots", 6, new ConfigDescription("Maximum number of inventory slots to carry wands/staves. Vanilla = 3. Hard cap = 8.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(3, 8), Array.Empty<object>()));
			ExpandUI = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ExpandInventoryUI", true, "If true, attempts to clone the vanilla inventory UI slot to display the extra slots. If UI breaks, disable this (extra items will still be usable via scroll/cycle).");
			HorizontalOffset = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "HorizontalOffsetPx", 0f, "Horizontal offset (in UI pixels) applied to all inventory slots, the off-hand slot and the prompt container. Negative shifts LEFT, positive shifts RIGHT. Use to align slots with the decorative frame.");
			Log.LogInfo((object)string.Format("{0} v{1} loading. MaxSlots={2}", "More Inventory Slots", "1.0.0", MaxSlotsConfig.Value));
			try
			{
				new Harmony("h4rv.yapyap.moreinventoryslots").PatchAll(typeof(Plugin).Assembly);
				Log.LogInfo((object)"More Inventory Slots patched successfully.");
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Failed to apply Harmony patches: {arg}");
			}
		}

		public static int GetMaxSlots()
		{
			int num = ((MaxSlotsConfig != null) ? MaxSlotsConfig.Value : 3);
			if (num < 1)
			{
				num = 1;
			}
			if (num > 8)
			{
				num = 8;
			}
			return num;
		}

		public static int GetMaxSlotsMinusOne()
		{
			return Mathf.Max(0, GetMaxSlots() - 1);
		}
	}
	internal static class SlotConstTranspiler
	{
		[CompilerGenerated]
		private sealed class <Transpile>d__2 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private CodeInstruction <>2__current;

			private int <>l__initialThreadId;

			private IEnumerable<CodeInstruction> instructions;

			public IEnumerable<CodeInstruction> <>3__instructions;

			private IEnumerator<CodeInstruction> <>7__wrap1;

			CodeInstruction IEnumerator<CodeInstruction>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <Transpile>d__2(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || num == 1)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<>7__wrap1 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				try
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<>7__wrap1 = instructions.GetEnumerator();
						<>1__state = -3;
						break;
					case 1:
						<>1__state = -3;
						break;
					}
					if (<>7__wrap1.MoveNext())
					{
						CodeInstruction current = <>7__wrap1.Current;
						if (IsLdcI4Value(current, 3))
						{
							current.opcode = OpCodes.Call;
							current.operand = GetMax;
						}
						else if (IsLdcI4Value(current, 2))
						{
							current.opcode = OpCodes.Call;
							current.operand = GetMaxMinusOne;
						}
						<>2__current = current;
						<>1__state = 1;
						return true;
					}
					<>m__Finally1();
					<>7__wrap1 = null;
					return false;
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				if (<>7__wrap1 != null)
				{
					<>7__wrap1.Dispose();
				}
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator()
			{
				<Transpile>d__2 <Transpile>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<Transpile>d__ = this;
				}
				else
				{
					<Transpile>d__ = new <Transpile>d__2(0);
				}
				<Transpile>d__.instructions = <>3__instructions;
				return <Transpile>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<CodeInstruction>)this).GetEnumerator();
			}
		}

		private static readonly MethodInfo GetMax = AccessTools.Method(typeof(Plugin), "GetMaxSlots", (Type[])null, (Type[])null);

		private static readonly MethodInfo GetMaxMinusOne = AccessTools.Method(typeof(Plugin), "GetMaxSlotsMinusOne", (Type[])null, (Type[])null);

		[IteratorStateMachine(typeof(<Transpile>d__2))]
		public static IEnumerable<CodeInstruction> Transpile(IEnumerable<CodeInstruction> instructions)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <Transpile>d__2(-2)
			{
				<>3__instructions = instructions
			};
		}

		private static bool IsLdcI4Value(CodeInstruction ins, int value)
		{
			if (ins.opcode == OpCodes.Ldc_I4_3 && value == 3)
			{
				return true;
			}
			if (ins.opcode == OpCodes.Ldc_I4_2 && value == 2)
			{
				return true;
			}
			if (ins.opcode == OpCodes.Ldc_I4 && ins.operand is int num && num == value)
			{
				return true;
			}
			if (ins.opcode == OpCodes.Ldc_I4_S && ins.operand is sbyte b && b == value)
			{
				return true;
			}
			return false;
		}
	}
	[HarmonyPatch]
	internal static class PawnInventory_Patches
	{
		[CompilerGenerated]
		private sealed class <FindTargets>d__3 : IEnumerable<MethodBase>, IEnumerable, IEnumerator<MethodBase>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private MethodBase <>2__current;

			private int <>l__initialThreadId;

			private Type <t>5__2;

			private string[] <>7__wrap2;

			private int <>7__wrap3;

			private string <name>5__5;

			private MethodInfo[] <>7__wrap5;

			private int <>7__wrap6;

			MethodBase IEnumerator<MethodBase>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <FindTargets>d__3(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<t>5__2 = null;
				<>7__wrap2 = null;
				<name>5__5 = null;
				<>7__wrap5 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				int num = <>1__state;
				bool flag;
				if (num != 0)
				{
					if (num != 1)
					{
						return false;
					}
					<>1__state = -1;
					flag = true;
					goto IL_00c8;
				}
				<>1__state = -1;
				<t>5__2 = PawnInventoryType;
				if (<t>5__2 == null)
				{
					Plugin.Log.LogError((object)"YAPYAP.PawnInventory type not found – patches skipped.");
					return false;
				}
				<>7__wrap2 = TargetMethods;
				<>7__wrap3 = 0;
				goto IL_0124;
				IL_00d6:
				if (<>7__wrap6 < <>7__wrap5.Length)
				{
					MethodInfo methodInfo = <>7__wrap5[<>7__wrap6];
					if (methodInfo.Name == <name>5__5)
					{
						<>2__current = methodInfo;
						<>1__state = 1;
						return true;
					}
					goto IL_00c8;
				}
				<>7__wrap5 = null;
				if (!flag)
				{
					Plugin.Log.LogWarning((object)("PawnInventory." + <name>5__5 + " not found – skipping."));
				}
				<name>5__5 = null;
				<>7__wrap3++;
				goto IL_0124;
				IL_00c8:
				<>7__wrap6++;
				goto IL_00d6;
				IL_0124:
				if (<>7__wrap3 < <>7__wrap2.Length)
				{
					<name>5__5 = <>7__wrap2[<>7__wrap3];
					MethodInfo[] methods = <t>5__2.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
					flag = false;
					<>7__wrap5 = methods;
					<>7__wrap6 = 0;
					goto IL_00d6;
				}
				<>7__wrap2 = null;
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<MethodBase> IEnumerable<MethodBase>.GetEnumerator()
			{
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					return this;
				}
				return new <FindTargets>d__3(0);
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<MethodBase>)this).GetEnumerator();
			}
		}

		private static readonly string[] TargetMethods = new string[12]
		{
			"OnStartServer", "OnStartClient", "IsFull", "ServerTryAddItem", "ServerAddItemToSlot", "ServerRemoveFromSlot", "SelectSlotWithMainHand", "ServerSerializeToKvp", "ServerTryRestoreFromKvp", "UserCode_CmdCycleSlot__Boolean",
			"UserCode_CmdMoveItemInInventory__UInt32__Int32", "UserCode_CmdSwapSlotWithRightHand__Int32"
		};

		private static Type PawnInventoryType => AccessTools.TypeByName("YAPYAP.PawnInventory");

		[IteratorStateMachine(typeof(<FindTargets>d__3))]
		[HarmonyTargetMethods]
		private static IEnumerable<MethodBase> FindTargets()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <FindTargets>d__3(-2);
		}

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase original)
		{
			Plugin.Log.LogDebug((object)("Transpiling PawnInventory." + original.Name));
			return SlotConstTranspiler.Transpile(instructions);
		}
	}
	[HarmonyPatch]
	internal static class PawnInventory_NormalizeMainHand
	{
		[HarmonyTargetMethod]
		private static MethodBase Target()
		{
			return AccessTools.TypeByName("YAPYAP.PawnInventory")?.GetMethod("OnStartServer", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		}

		[HarmonyPostfix]
		private static void Postfix(object __instance)
		{
			try
			{
				Type type = __instance.GetType();
				if (!(type.GetProperty("Items", BindingFlags.Instance | BindingFlags.Public)?.GetValue(__instance) is IList list))
				{
					return;
				}
				int num = -1;
				for (int i = 0; i < list.Count; i++)
				{
					object obj = list[i];
					PropertyInfo propertyInfo = obj?.GetType().GetProperty("IsEmpty");
					if (!(propertyInfo != null) || !(bool)propertyInfo.GetValue(obj))
					{
						num = i;
						break;
					}
				}
				PropertyInfo property = type.GetProperty("NetworkCurrentMainHandSlot", BindingFlags.Instance | BindingFlags.Public);
				FieldInfo fieldInfo = AccessTools.Field(type, "CurrentMainHandSlot");
				int num2 = ((fieldInfo != null) ? ((int)fieldInfo.GetValue(__instance)) : 0);
				bool flag = true;
				if (num2 >= 0 && num2 < list.Count)
				{
					PropertyInfo propertyInfo2 = list[num2]?.GetType().GetProperty("IsEmpty");
					flag = propertyInfo2 == null || (bool)propertyInfo2.GetValue(list[num2]);
				}
				if (flag && num >= 0 && num2 != num)
				{
					Plugin.Log.LogInfo((object)$"[MainHand] snapping {num2} -> {num}");
					property?.SetValue(__instance, num);
				}
				else if (num2 >= list.Count)
				{
					Plugin.Log.LogInfo((object)$"[MainHand] out-of-range {num2} -> 0");
					property?.SetValue(__instance, 0);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Normalize main-hand failed: " + ex.Message));
			}
		}
	}
	[HarmonyPatch]
	internal static class PawnInventory_ExtendedPersistence
	{
		[CompilerGenerated]
		private sealed class <Targets>d__2 : IEnumerable<MethodBase>, IEnumerable, IEnumerator<MethodBase>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private MethodBase <>2__current;

			private int <>l__initialThreadId;

			private MethodInfo <restore>5__2;

			MethodBase IEnumerator<MethodBase>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <Targets>d__2(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<restore>5__2 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
				{
					<>1__state = -1;
					Type pawnInventoryType = PawnInventoryType;
					if (pawnInventoryType == null)
					{
						return false;
					}
					MethodInfo method = pawnInventoryType.GetMethod("ServerSerializeToKvp", BindingFlags.Instance | BindingFlags.NonPublic);
					<restore>5__2 = pawnInventoryType.GetMethod("ServerTryRestoreFromKvp", BindingFlags.Instance | BindingFlags.NonPublic);
					if (method != null)
					{
						<>2__current = method;
						<>1__state = 1;
						return true;
					}
					goto IL_0074;
				}
				case 1:
					<>1__state = -1;
					goto IL_0074;
				case 2:
					{
						<>1__state = -1;
						break;
					}
					IL_0074:
					if (<restore>5__2 != null)
					{
						<>2__current = <restore>5__2;
						<>1__state = 2;
						return true;
					}
					break;
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<MethodBase> IEnumerable<MethodBase>.GetEnumerator()
			{
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					return this;
				}
				return new <Targets>d__2(0);
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<MethodBase>)this).GetEnumerator();
			}
		}

		private static Type PawnInventoryType => AccessTools.TypeByName("YAPYAP.PawnInventory");

		[IteratorStateMachine(typeof(<Targets>d__2))]
		[HarmonyTargetMethods]
		private static IEnumerable<MethodBase> Targets()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <Targets>d__2(-2);
		}

		private static string GetKeyPrefix(string playerId)
		{
			return (string)AccessTools.Method(PawnInventoryType, "GetKeyPrefix", new Type[1] { typeof(string) }, (Type[])null)?.Invoke(null, new object[1] { playerId });
		}

		[HarmonyPostfix]
		private static void Postfix(object __instance, object save, string playerId, MethodBase __originalMethod)
		{
			try
			{
				if (save == null || string.IsNullOrEmpty(playerId))
				{
					return;
				}
				string keyPrefix = GetKeyPrefix(playerId);
				if (string.IsNullOrEmpty(keyPrefix))
				{
					return;
				}
				int maxSlots = Plugin.GetMaxSlots();
				Type type = __instance.GetType();
				if (__originalMethod.Name == "ServerSerializeToKvp")
				{
					save.GetType().GetMethod("SetInt", new Type[2]
					{
						typeof(string),
						typeof(int)
					})?.Invoke(save, new object[2]
					{
						keyPrefix + ".SLOT_COUNT",
						maxSlots
					});
					MethodInfo methodInfo = AccessTools.Method(type, "SerializeProp", (Type[])null, (Type[])null);
					if (!(type.GetProperty("Items", BindingFlags.Instance | BindingFlags.Public)?.GetValue(__instance) is IList list) || methodInfo == null)
					{
						return;
					}
					for (int i = 0; i < maxSlots; i++)
					{
						object obj = null;
						if (i < list.Count)
						{
							object obj2 = list[i];
							PropertyInfo propertyInfo = obj2?.GetType().GetProperty("IsEmpty");
							if (!(propertyInfo != null) || !(bool)propertyInfo.GetValue(obj2))
							{
								obj = obj2.GetType().GetProperty("PropInstance")?.GetValue(obj2);
							}
						}
						methodInfo.Invoke(__instance, new object[3]
						{
							save,
							$"{keyPrefix}.S{i}",
							obj
						});
					}
					Plugin.Log.LogDebug((object)$"[Save] wrote SLOT_COUNT={maxSlots} and S0..S{maxSlots - 1}");
					return;
				}
				save.GetType().GetMethod("TryGetInt", new Type[2]
				{
					typeof(string),
					typeof(int).MakeByRefType()
				});
				MethodInfo methodInfo2 = AccessTools.Method(type, "TryRestoreProp", (Type[])null, (Type[])null);
				MethodInfo methodInfo3 = AccessTools.Method(type, "ServerAddItemToSlot", (Type[])null, (Type[])null);
				IList list2 = type.GetProperty("Items", BindingFlags.Instance | BindingFlags.Public)?.GetValue(__instance) as IList;
				if (methodInfo2 == null || methodInfo3 == null || list2 == null)
				{
					return;
				}
				for (int j = 3; j < maxSlots; j++)
				{
					if (j < list2.Count)
					{
						object obj3 = list2[j];
						PropertyInfo propertyInfo2 = obj3?.GetType().GetProperty("IsEmpty");
						if (propertyInfo2 != null && !(bool)propertyInfo2.GetValue(obj3))
						{
							continue;
						}
					}
					object[] array = new object[4]
					{
						save,
						$"{keyPrefix}.S{j}",
						playerId,
						null
					};
					if ((bool)methodInfo2.Invoke(__instance, array) && array[3] != null)
					{
						object obj4 = array[3];
						ConstructorInfo constructorInfo = AccessTools.TypeByName("YAPYAP.InventoryItem")?.GetConstructor(new Type[1] { obj4.GetType() });
						if (!(constructorInfo == null))
						{
							object obj5 = constructorInfo.Invoke(new object[1] { obj4 });
							methodInfo3.Invoke(__instance, new object[2] { j, obj5 });
							Plugin.Log.LogDebug((object)$"[Save] restored extra slot S{j}");
						}
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[Save] extended persistence failed: " + ex.Message));
			}
		}
	}
	[HarmonyPatch]
	internal static class UIInventory_Patches
	{
		private static readonly string[] PromptFieldNames = new string[3] { "scrollCanvasGroup", "switchHandsCanvasGroup", "dropItemCanvasGroup" };

		private static Type UIInventoryType => AccessTools.TypeByName("YAPYAP.UIInventory");

		private static Type UIInventorySlotType => AccessTools.TypeByName("YAPYAP.UIInventorySlot");

		[HarmonyTargetMethod]
		private static MethodBase Target()
		{
			return UIInventoryType?.GetMethod("OnStartPawnAuthorityChanged", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		}

		[HarmonyPrefix]
		private static void Prefix(object __instance)
		{
			if (!Plugin.ExpandUI.Value)
			{
				return;
			}
			try
			{
				EnsureSlots(__instance);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("UI slot expansion failed (safe to ignore): " + ex.Message));
			}
		}

		private static void EnsureSlots(object uiInventoryInstance)
		{
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_041e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0423: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_058c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0591: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d1: 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_03ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0461: Unknown result type (might be due to invalid IL or missing references)
			//IL_045a: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_05eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_05bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_05dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0466: Unknown result type (might be due to invalid IL or missing references)
			//IL_046a: Unknown result type (might be due to invalid IL or missing references)
			//IL_047e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0483: Unknown result type (might be due to invalid IL or missing references)
			//IL_0488: Unknown result type (might be due to invalid IL or missing references)
			//IL_0640: Unknown result type (might be due to invalid IL or missing references)
			//IL_0647: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_050e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0507: Unknown result type (might be due to invalid IL or missing references)
			//IL_0513: Unknown result type (might be due to invalid IL or missing references)
			//IL_0515: Unknown result type (might be due to invalid IL or missing references)
			//IL_051a: Unknown result type (might be due to invalid IL or missing references)
			if (uiInventoryInstance == null)
			{
				return;
			}
			Type uIInventorySlotType = UIInventorySlotType;
			if (uIInventorySlotType == null)
			{
				return;
			}
			FieldInfo fieldInfo = AccessTools.Field(UIInventoryType, "inventorySlots");
			if (fieldInfo == null || !(fieldInfo.GetValue(uiInventoryInstance) is Array array))
			{
				return;
			}
			int maxSlots = Plugin.GetMaxSlots();
			if (array.Length >= maxSlots || array.Length == 0)
			{
				return;
			}
			object? value = array.GetValue(0);
			Component val = (Component)((value is Component) ? value : null);
			if ((Object)(object)val == (Object)null || (Object)(object)val.gameObject == (Object)null)
			{
				return;
			}
			Transform parent = val.transform.parent;
			if ((Object)(object)parent == (Object)null)
			{
				return;
			}
			LayoutGroup[] components = ((Component)parent).GetComponents<LayoutGroup>();
			string arg = ((components.Length == 0) ? "none" : string.Join(",", Array.ConvertAll(components, (LayoutGroup l) => ((object)l).GetType().Name)));
			Plugin.Log.LogDebug((object)$"[UI] parent='{((Object)parent).name}' childCount={parent.childCount} layoutGroups=[{arg}]");
			bool flag = false;
			if (components.Length != 0 && array.Length >= 2)
			{
				object? value2 = array.GetValue(0);
				object? obj = ((value2 is Component) ? value2 : null);
				Transform obj2 = ((obj != null) ? ((Component)obj).transform : null);
				RectTransform val2 = (RectTransform)(object)((obj2 is RectTransform) ? obj2 : null);
				object? value3 = array.GetValue(1);
				object? obj3 = ((value3 is Component) ? value3 : null);
				Transform obj4 = ((obj3 != null) ? ((Component)obj3).transform : null);
				RectTransform val3 = (RectTransform)(object)((obj4 is RectTransform) ? obj4 : null);
				if ((Object)(object)val2 != (Object)null && (Object)(object)val3 != (Object)null && Vector2.Distance(val2.anchoredPosition, val3.anchoredPosition) < 0.01f)
				{
					flag = true;
				}
			}
			bool flag2 = flag;
			if (!flag2 && components.Length != 0)
			{
				LayoutGroup[] array2 = components;
				for (int i = 0; i < array2.Length; i++)
				{
					((Behaviour)array2[i]).enabled = false;
				}
				ContentSizeFitter component = ((Component)parent).GetComponent<ContentSizeFitter>();
				if ((Object)(object)component != (Object)null)
				{
					((Behaviour)component).enabled = false;
				}
				Plugin.Log.LogInfo((object)$"[UI] disabled {components.Length} LayoutGroup(s) on '{((Object)parent).name}' to preserve manual slot positions");
			}
			Vector2 val4 = Vector2.zero;
			RectTransform val5 = null;
			if (!flag2 && array.Length >= 2)
			{
				object? value4 = array.GetValue(array.Length - 2);
				object? obj5 = ((value4 is Component) ? value4 : null);
				Transform obj6 = ((obj5 != null) ? ((Component)obj5).transform : null);
				RectTransform val6 = (RectTransform)(object)((obj6 is RectTransform) ? obj6 : null);
				object? value5 = array.GetValue(array.Length - 1);
				object? obj7 = ((value5 is Component) ? value5 : null);
				Transform obj8 = ((obj7 != null) ? ((Component)obj7).transform : null);
				RectTransform val7 = (RectTransform)(object)((obj8 is RectTransform) ? obj8 : null);
				if ((Object)(object)val6 != (Object)null && (Object)(object)val7 != (Object)null)
				{
					val4 = val7.anchoredPosition - val6.anchoredPosition;
					val5 = val7;
				}
			}
			else if (!flag2 && array.Length == 1)
			{
				Transform transform = val.transform;
				val5 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
				if ((Object)(object)val5 != (Object)null)
				{
					Rect rect = val5.rect;
					float width = ((Rect)(ref rect)).width;
					((Vector2)(ref val4))..ctor((width > 0f) ? width : 80f, 0f);
				}
			}
			Array array3 = Array.CreateInstance(uIInventorySlotType, maxSlots);
			for (int j = 0; j < array.Length; j++)
			{
				array3.SetValue(array.GetValue(j), j);
			}
			for (int k = array.Length; k < maxSlots; k++)
			{
				GameObject val8 = Object.Instantiate<GameObject>(val.gameObject, parent);
				((Object)val8).name = $"InventorySlot_Extra_{k}";
				val8.SetActive(true);
				val8.transform.SetAsLastSibling();
				Component component2 = val8.GetComponent(uIInventorySlotType);
				if ((Object)(object)component2 == (Object)null)
				{
					Object.Destroy((Object)(object)val8);
					Plugin.Log.LogWarning((object)$"Cloned slot {k} is missing UIInventorySlot component – aborting expansion.");
					return;
				}
				if (!flag2 && (Object)(object)val5 != (Object)null)
				{
					RectTransform component3 = val8.GetComponent<RectTransform>();
					if ((Object)(object)component3 != (Object)null)
					{
						component3.anchorMin = val5.anchorMin;
						component3.anchorMax = val5.anchorMax;
						component3.pivot = val5.pivot;
						component3.sizeDelta = val5.sizeDelta;
						((Transform)component3).localScale = ((Transform)val5).localScale;
						((Transform)component3).localRotation = ((Transform)val5).localRotation;
					}
				}
				array3.SetValue(component2, k);
			}
			Vector2 val9 = Vector2.zero;
			if (!flag2 && (Object)(object)val5 != (Object)null)
			{
				object? value6 = array.GetValue(0);
				object? obj9 = ((value6 is Component) ? value6 : null);
				Transform obj10 = ((obj9 != null) ? ((Component)obj9).transform : null);
				Transform obj11 = ((obj10 is RectTransform) ? obj10 : null);
				Vector2 val10 = ((obj11 != null) ? ((RectTransform)obj11).anchoredPosition : Vector2.zero);
				Vector2 val11 = val5.anchoredPosition + new Vector2(Plugin.HorizontalOffset.Value, 0f);
				for (int m = 0; m < maxSlots; m++)
				{
					object? value7 = array3.GetValue(m);
					object? obj12 = ((value7 is Component) ? value7 : null);
					Transform obj13 = ((obj12 != null) ? ((Component)obj12).transform : null);
					RectTransform val12 = (RectTransform)(object)((obj13 is RectTransform) ? obj13 : null);
					if (!((Object)(object)val12 == (Object)null))
					{
						int num = maxSlots - 1 - m;
						val12.anchoredPosition = val11 - val4 * (float)num;
					}
				}
				object? value8 = array3.GetValue(0);
				object? obj14 = ((value8 is Component) ? value8 : null);
				Transform obj15 = ((obj14 != null) ? ((Component)obj14).transform : null);
				Transform obj16 = ((obj15 is RectTransform) ? obj15 : null);
				val9 = ((obj16 != null) ? ((RectTransform)obj16).anchoredPosition : Vector2.zero) - val10;
			}
			fieldInfo.SetValue(uiInventoryInstance, array3);
			for (int n = 0; n < maxSlots; n++)
			{
				object? value9 = array3.GetValue(n);
				Component val13 = (Component)((value9 is Component) ? value9 : null);
				if (!((Object)(object)val13 == (Object)null))
				{
					Image component4 = val13.GetComponent<Image>();
					if ((Object)(object)component4 != (Object)null)
					{
						((Behaviour)component4).enabled = true;
					}
					LayoutElement component5 = val13.GetComponent<LayoutElement>();
					if ((Object)(object)component5 != (Object)null)
					{
						component5.ignoreLayout = true;
					}
				}
			}
			UpdateSlotNumberLabels(array3);
			Vector3 spacingWorld = Vector3.zero;
			object? value10 = array3.GetValue(0);
			object? obj17 = ((value10 is Component) ? value10 : null);
			Transform obj18 = ((obj17 != null) ? ((Component)obj17).transform : null);
			RectTransform val14 = (RectTransform)(object)((obj18 is RectTransform) ? obj18 : null);
			if ((Object)(object)val14 != (Object)null)
			{
				spacingWorld = ((Transform)val14).TransformVector(new Vector3(val4.x, val4.y, 0f));
			}
			Vector3 offHandWorld = ShiftOffHandSlot(uiInventoryInstance, val14, spacingWorld);
			ShiftPrompts(uiInventoryInstance, offHandWorld, spacingWorld, val14);
			if (flag2)
			{
				RectTransform val15 = (RectTransform)(object)((parent is RectTransform) ? parent : null);
				if ((Object)(object)val15 != (Object)null)
				{
					LayoutRebuilder.ForceRebuildLayoutImmediate(val15);
				}
			}
			Plugin.Log.LogInfo((object)($"Expanded inventory UI to {maxSlots} slots (was {array.Length}). " + $"LayoutGroup={flag2}, spacing={val4} slotDelta={val9}"));
		}

		private static void UpdateSlotNumberLabels(Array slotArray)
		{
			Type uIInventorySlotType = UIInventorySlotType;
			FieldInfo fieldInfo = AccessTools.Field(uIInventorySlotType, "quantityText");
			FieldInfo fieldInfo2 = AccessTools.Field(uIInventorySlotType, "itemName");
			for (int i = 0; i < slotArray.Length; i++)
			{
				object? value = slotArray.GetValue(i);
				Component val = (Component)((value is Component) ? value : null);
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				HashSet<int> hashSet = new HashSet<int>();
				try
				{
					object? obj = fieldInfo?.GetValue(val);
					Component val2 = (Component)((obj is Component) ? obj : null);
					if ((Object)(object)val2 != (Object)null)
					{
						hashSet.Add(((Object)val2).GetInstanceID());
					}
					object? obj2 = fieldInfo2?.GetValue(val);
					Component val3 = (Component)((obj2 is Component) ? obj2 : null);
					if ((Object)(object)val3 != (Object)null)
					{
						hashSet.Add(((Object)val3).GetInstanceID());
					}
				}
				catch
				{
				}
				TMP_Text[] componentsInChildren = val.GetComponentsInChildren<TMP_Text>(true);
				foreach (TMP_Text val4 in componentsInChildren)
				{
					if (!((Object)(object)val4 == (Object)null) && !hashSet.Contains(((Object)val4).GetInstanceID()) && int.TryParse((val4.text ?? "").Trim(), out var result) && result >= 1 && result <= 30)
					{
						val4.text = (i + 1).ToString();
					}
				}
			}
		}

		private static Vector3 ShiftOffHandSlot(object uiInventoryInstance, RectTransform firstSlotRT, Vector3 spacingWorld)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: 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_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)firstSlotRT == (Object)null)
			{
				return Vector3.zero;
			}
			FieldInfo fieldInfo = AccessTools.Field(UIInventoryType, "leftHandSlot");
			if (fieldInfo == null)
			{
				return ((Transform)firstSlotRT).position - spacingWorld;
			}
			object? value = fieldInfo.GetValue(uiInventoryInstance);
			object? obj = ((value is Component) ? value : null);
			Transform obj2 = ((obj != null) ? ((Component)obj).transform : null);
			RectTransform val = (RectTransform)(object)((obj2 is RectTransform) ? obj2 : null);
			if ((Object)(object)val == (Object)null)
			{
				return ((Transform)firstSlotRT).position - spacingWorld;
			}
			Vector3 val2 = ((Transform)firstSlotRT).position - spacingWorld;
			val2.y = ((Transform)val).position.y;
			((Transform)val).position = val2;
			Plugin.Log.LogInfo((object)$"[UI] off-hand slot '{((Object)val).name}' moved to {val2}");
			return val2;
		}

		private static void ShiftPrompts(object uiInventoryInstance, Vector3 offHandWorld, Vector3 spacingWorld, RectTransform firstSlotRT)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)firstSlotRT == (Object)null)
			{
				return;
			}
			Vector3 val = offHandWorld - spacingWorld;
			HashSet<RectTransform> hashSet = new HashSet<RectTransform>();
			string[] promptFieldNames = PromptFieldNames;
			foreach (string text in promptFieldNames)
			{
				FieldInfo fieldInfo = AccessTools.Field(UIInventoryType, text);
				if (fieldInfo == null)
				{
					continue;
				}
				object value = fieldInfo.GetValue(uiInventoryInstance);
				RectTransform val2 = null;
				GameObject val3 = (GameObject)((value is GameObject) ? value : null);
				if (val3 == null)
				{
					Component val4 = (Component)((value is Component) ? value : null);
					if (val4 != null)
					{
						val2 = (RectTransform)(((Object)(object)val4 != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
					}
				}
				else
				{
					val2 = (((Object)(object)val3 != (Object)null) ? val3.GetComponent<RectTransform>() : null);
				}
				if ((Object)(object)val2 != (Object)null)
				{
					Transform parent = ((Transform)val2).parent;
					RectTransform val5 = (RectTransform)(object)((parent is RectTransform) ? parent : null);
					if (val5 != null)
					{
						hashSet.Add(val5);
					}
				}
			}
			if (hashSet.Count == 0)
			{
				Plugin.Log.LogWarning((object)"[UI] could not locate prompt container parent – skipping shift");
				return;
			}
			foreach (RectTransform item in hashSet)
			{
				Vector3 position = ((Transform)item).position;
				((Transform)item).position = new Vector3(val.x, position.y, position.z);
				Plugin.Log.LogInfo((object)$"[UI] shifted prompt container '{((Object)item).name}' to worldX={val.x}");
			}
		}
	}
	[HarmonyPatch]
	internal static class UIInventory_RefreshPromptsAlwaysOn
	{
		[HarmonyTargetMethod]
		private static MethodBase Target()
		{
			return AccessTools.TypeByName("YAPYAP.UIInventory")?.GetMethod("RefreshInventoryDisplay", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		}

		[HarmonyPostfix]
		private static void Postfix(object __instance)
		{
			if (!Plugin.ExpandUI.Value)
			{
				return;
			}
			Type type = __instance.GetType();
			string[] array = new string[3] { "useItemInputPromptObj", "dropItemInputPromptObj", "switchHandsInputPromptObj" };
			foreach (string text in array)
			{
				FieldInfo fieldInfo = AccessTools.Field(type, text);
				if (!(fieldInfo == null))
				{
					object? value = fieldInfo.GetValue(__instance);
					GameObject val = (GameObject)((value is GameObject) ? value : null);
					if (val != null && (Object)(object)val != (Object)null)
					{
						val.SetActive(true);
					}
				}
			}
			array = new string[3] { "scrollCanvasGroup", "switchHandsCanvasGroup", "dropItemCanvasGroup" };
			foreach (string text2 in array)
			{
				FieldInfo fieldInfo2 = AccessTools.Field(type, text2);
				if (!(fieldInfo2 == null))
				{
					object? value2 = fieldInfo2.GetValue(__instance);
					CanvasGroup val2 = (CanvasGroup)((value2 is CanvasGroup) ? value2 : null);
					if (val2 != null && (Object)(object)val2 != (Object)null)
					{
						val2.alpha = 1f;
						val2.interactable = true;
						val2.blocksRaycasts = true;
					}
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class UIInventory_CanvasGroupVisibility
	{
		[HarmonyTargetMethod]
		private static MethodBase Target()
		{
			return AccessTools.TypeByName("YAPYAP.UIInventory")?.GetMethod("UpdateCanvasGroupVisibility", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		}

		[HarmonyPostfix]
		private static void Postfix(object __instance)
		{
			if (!Plugin.ExpandUI.Value)
			{
				return;
			}
			Type type = __instance.GetType();
			string[] array = new string[3] { "scrollCanvasGroup", "switchHandsCanvasGroup", "dropItemCanvasGroup" };
			foreach (string text in array)
			{
				FieldInfo fieldInfo = AccessTools.Field(type, text);
				if (!(fieldInfo == null))
				{
					object? value = fieldInfo.GetValue(__instance);
					CanvasGroup val = (CanvasGroup)((value is CanvasGroup) ? value : null);
					if (val != null && (Object)(object)val != (Object)null)
					{
						val.alpha = 1f;
					}
				}
			}
		}
	}
}