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 MaxSlotsConfig; internal static ConfigEntry ExpandUI; internal static ConfigEntry 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("General", "MaxInventorySlots", 6, new ConfigDescription("Maximum number of inventory slots to carry wands/staves. Vanilla = 3. Hard cap = 8.", (AcceptableValueBase)(object)new AcceptableValueRange(3, 8), Array.Empty())); ExpandUI = ((BaseUnityPlugin)this).Config.Bind("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("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 d__2 : IEnumerable, IEnumerable, IEnumerator, IEnumerator, IDisposable { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; private IEnumerable instructions; public IEnumerable <>3__instructions; private IEnumerator <>7__wrap1; CodeInstruction IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public 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 IEnumerable.GetEnumerator() { d__2 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__2(0); } d__.instructions = <>3__instructions; return d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)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(d__2))] public static IEnumerable Transpile(IEnumerable instructions) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new 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 d__3 : IEnumerable, IEnumerable, IEnumerator, IEnumerator, IDisposable { private int <>1__state; private MethodBase <>2__current; private int <>l__initialThreadId; private Type 5__2; private string[] <>7__wrap2; private int <>7__wrap3; private string 5__5; private MethodInfo[] <>7__wrap5; private int <>7__wrap6; MethodBase IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__3(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { 5__2 = null; <>7__wrap2 = null; 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; 5__2 = PawnInventoryType; if (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 == 5__5) { <>2__current = methodInfo; <>1__state = 1; return true; } goto IL_00c8; } <>7__wrap5 = null; if (!flag) { Plugin.Log.LogWarning((object)("PawnInventory." + 5__5 + " not found – skipping.")); } 5__5 = null; <>7__wrap3++; goto IL_0124; IL_00c8: <>7__wrap6++; goto IL_00d6; IL_0124: if (<>7__wrap3 < <>7__wrap2.Length) { 5__5 = <>7__wrap2[<>7__wrap3]; MethodInfo[] methods = 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 IEnumerable.GetEnumerator() { if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; return this; } return new d__3(0); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)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(d__3))] [HarmonyTargetMethods] private static IEnumerable FindTargets() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__3(-2); } [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable 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 d__2 : IEnumerable, IEnumerable, IEnumerator, IEnumerator, IDisposable { private int <>1__state; private MethodBase <>2__current; private int <>l__initialThreadId; private MethodInfo 5__2; MethodBase IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__2(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { 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); 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 (5__2 != null) { <>2__current = 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 IEnumerable.GetEnumerator() { if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; return this; } return new d__2(0); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } private static Type PawnInventoryType => AccessTools.TypeByName("YAPYAP.PawnInventory"); [IteratorStateMachine(typeof(d__2))] [HarmonyTargetMethods] private static IEnumerable Targets() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new 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(); 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(); 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(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(); 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(); if ((Object)(object)component4 != (Object)null) { ((Behaviour)component4).enabled = true; } LayoutElement component5 = val13.GetComponent(); 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 hashSet = new HashSet(); 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(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 hashSet = new HashSet(); 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() : 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; } } } } } }