using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using HarmonyLib;
using InventoryExpansion;
using InventoryExpansion.Config;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using Mimic.Actors;
using ReluProtocol;
using ReluProtocol.Enum;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Core), "InventoryExpansion", "1.1.0", "DooDesch", null)]
[assembly: MelonGame("ReLUGames", "MIMESIS")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("InventoryExpansion")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0+8a961a15c0078692f8e3a84d4442b4ba77ac6e3d")]
[assembly: AssemblyProduct("InventoryExpansion")]
[assembly: AssemblyTitle("InventoryExpansion")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.0.0")]
[module: UnverifiableCode]
[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 InventoryExpansion
{
public sealed class Core : MelonMod
{
public override void OnInitializeMelon()
{
InventoryExpansionPreferences.Initialize();
((MelonBase)this).HarmonyInstance.PatchAll();
MelonLogger.Msg("InventoryExpansion initialized. Enabled={0}", new object[1] { InventoryExpansionPreferences.Enabled });
}
}
}
namespace InventoryExpansion.Patches
{
[HarmonyPatch(typeof(Hub))]
internal static class GameConfigPatches
{
private static bool _slotsAlreadyExpanded;
[HarmonyPostfix]
[HarmonyPatch("Awake")]
private static void Hub_Awake_Postfix(Hub __instance)
{
try
{
if (!InventoryExpansionPreferences.Enabled || _slotsAlreadyExpanded)
{
return;
}
object obj = typeof(Hub).GetField("gameConfig", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(__instance);
if (obj == null)
{
MelonLogger.Warning("InventoryExpansion: gameConfig is null, cannot adjust inventory slot count.");
return;
}
object obj2 = obj.GetType().GetField("playerActor", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj);
if (obj2 == null)
{
MelonLogger.Warning("InventoryExpansion: gameConfig.playerActor is null, cannot adjust inventory slot count.");
return;
}
FieldInfo field = obj2.GetType().GetField("maxGenericInventorySlot", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (field == null)
{
MelonLogger.Warning("InventoryExpansion: PlayerActor.maxGenericInventorySlot field not found.");
return;
}
int num = (int)(field.GetValue(obj2) ?? ((object)4));
int additionalSlots = InventoryExpansionPreferences.AdditionalSlots;
if (additionalSlots <= 0)
{
MelonLogger.Msg($"InventoryExpansion: keeping base inventory slots = {num}.");
return;
}
int num2 = num + additionalSlots;
field.SetValue(obj2, num2);
_slotsAlreadyExpanded = true;
MelonLogger.Msg($"InventoryExpansion: expanded inventory slots from {num} to {num2}.");
}
catch (Exception arg)
{
MelonLogger.Error($"InventoryExpansion: failed to adjust inventory slot size: {arg}");
}
}
}
[HarmonyPatch(typeof(InventoryController))]
internal static class InventoryControllerPatches
{
[HarmonyPostfix]
[HarmonyPatch("Initialize")]
private static void Initialize_Postfix(InventoryController __instance)
{
try
{
if (!InventoryExpansionPreferences.Enabled)
{
return;
}
Hub s = Hub.s;
object obj = typeof(Hub).GetField("gameConfig", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(s);
if (obj == null)
{
return;
}
object obj2 = obj.GetType().GetField("playerActor", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj);
if (obj2 == null)
{
return;
}
FieldInfo field = obj2.GetType().GetField("maxGenericInventorySlot", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (field == null)
{
return;
}
int num = (int)(field.GetValue(obj2) ?? ((object)4));
if (num <= 4)
{
return;
}
FieldInfo field2 = typeof(InventoryController).GetField("_inventorySlots", BindingFlags.Instance | BindingFlags.NonPublic);
if (field2 == null)
{
MelonLogger.Warning("InventoryExpansion: failed to find InventoryController._inventorySlots field.");
return;
}
if (!(field2.GetValue(__instance) is IDictionary dictionary))
{
MelonLogger.Warning("InventoryExpansion: InventoryController._inventorySlots is not an IDictionary.");
return;
}
for (int i = 5; i <= num; i++)
{
if (!dictionary.Contains(i))
{
dictionary[i] = null;
}
}
MelonLogger.Msg($"InventoryExpansion: InventoryController extended to {num} slots.");
}
catch (Exception arg)
{
MelonLogger.Error($"InventoryExpansion: failed to extend InventoryController slots: {arg}");
}
}
[HarmonyPrefix]
[HarmonyPatch("InvenFull")]
private static bool InvenFull_Prefix(InventoryController __instance, ref bool __result)
{
try
{
if (!InventoryExpansionPreferences.Enabled)
{
return true;
}
Hub s = Hub.s;
if ((Object)(object)s == (Object)null)
{
return true;
}
object obj = typeof(Hub).GetField("gameConfig", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(s);
object obj2 = (obj?.GetType().GetField("playerActor", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))?.GetValue(obj);
int num = (int)((obj2?.GetType().GetField("maxGenericInventorySlot", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))?.GetValue(obj2) ?? ((object)4));
if (!(typeof(InventoryController).GetField("_inventorySlots", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(__instance) is IDictionary dictionary))
{
return true;
}
int num2 = 0;
foreach (DictionaryEntry item in dictionary)
{
if (item.Value != null)
{
num2++;
}
}
__result = num2 >= num;
return false;
}
catch (Exception arg)
{
MelonLogger.Error($"InventoryExpansion: InvenFull prefix failed, falling back to original. {arg}");
return true;
}
}
}
[HarmonyPatch(typeof(UIPrefab_Inventory))]
internal static class InventoryUiPatches
{
[HarmonyPostfix]
[HarmonyPatch("Awake")]
private static void Awake_Postfix(UIPrefab_Inventory __instance)
{
//IL_029a: Unknown result type (might be due to invalid IL or missing references)
//IL_0286: Unknown result type (might be due to invalid IL or missing references)
//IL_025d: Unknown result type (might be due to invalid IL or missing references)
//IL_0269: Unknown result type (might be due to invalid IL or missing references)
//IL_0372: Unknown result type (might be due to invalid IL or missing references)
//IL_0379: Expected O, but got Unknown
//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
//IL_03bf: Unknown result type (might be due to invalid IL or missing references)
//IL_03d3: Unknown result type (might be due to invalid IL or missing references)
//IL_03e0: 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_03fa: Unknown result type (might be due to invalid IL or missing references)
//IL_042c: Unknown result type (might be due to invalid IL or missing references)
//IL_043b: Unknown result type (might be due to invalid IL or missing references)
//IL_045f: Unknown result type (might be due to invalid IL or missing references)
//IL_0486: Unknown result type (might be due to invalid IL or missing references)
//IL_048b: Unknown result type (might be due to invalid IL or missing references)
//IL_04b7: Unknown result type (might be due to invalid IL or missing references)
//IL_04c5: Unknown result type (might be due to invalid IL or missing references)
//IL_04f0: Unknown result type (might be due to invalid IL or missing references)
//IL_04fd: Unknown result type (might be due to invalid IL or missing references)
//IL_050a: Unknown result type (might be due to invalid IL or missing references)
//IL_0517: Unknown result type (might be due to invalid IL or missing references)
//IL_0523: Unknown result type (might be due to invalid IL or missing references)
//IL_054a: Unknown result type (might be due to invalid IL or missing references)
//IL_054f: 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_05e0: Unknown result type (might be due to invalid IL or missing references)
//IL_05fd: Unknown result type (might be due to invalid IL or missing references)
//IL_060a: Unknown result type (might be due to invalid IL or missing references)
//IL_0617: Unknown result type (might be due to invalid IL or missing references)
//IL_0624: Unknown result type (might be due to invalid IL or missing references)
//IL_0630: Unknown result type (might be due to invalid IL or missing references)
//IL_0657: Unknown result type (might be due to invalid IL or missing references)
//IL_065c: Unknown result type (might be due to invalid IL or missing references)
//IL_068d: Unknown result type (might be due to invalid IL or missing references)
//IL_069b: Unknown result type (might be due to invalid IL or missing references)
//IL_06a9: Unknown result type (might be due to invalid IL or missing references)
//IL_06b7: Unknown result type (might be due to invalid IL or missing references)
//IL_06c5: Unknown result type (might be due to invalid IL or missing references)
try
{
if (!InventoryExpansionPreferences.Enabled)
{
return;
}
int val = 4;
try
{
Hub s = Hub.s;
if ((Object)(object)s != (Object)null)
{
object obj = typeof(Hub).GetField("gameConfig", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(s);
object obj2 = (obj?.GetType().GetField("playerActor", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))?.GetValue(obj);
FieldInfo fieldInfo = obj2?.GetType().GetField("maxGenericInventorySlot", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (fieldInfo != null)
{
val = (int)(fieldInfo.GetValue(obj2) ?? ((object)4));
}
}
}
catch
{
val = 4;
}
int num = Math.Min(val, 4 + InventoryExpansionPreferences.AdditionalSlots);
FieldInfo field = typeof(UIPrefab_Inventory).GetField("inventorySlots", BindingFlags.Instance | BindingFlags.NonPublic);
if (field == null || !(field.GetValue(__instance) is IList list))
{
return;
}
int count = list.Count;
if (count == 0 || count >= num)
{
return;
}
Type type = list[0].GetType();
FieldInfo field2 = type.GetField("frame", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
FieldInfo field3 = type.GetField("image", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
FieldInfo field4 = type.GetField("stackCount", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
FieldInfo field5 = type.GetField("waitEvent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (field2 == null || field3 == null || field4 == null || field5 == null)
{
return;
}
object? value = field2.GetValue(list[0]);
Image val2 = (Image)((value is Image) ? value : null);
object? value2 = field3.GetValue(list[0]);
Image val3 = (Image)((value2 is Image) ? value2 : null);
object? value3 = field4.GetValue(list[0]);
TMP_Text val4 = (TMP_Text)((value3 is TMP_Text) ? value3 : null);
object? value4 = field5.GetValue(list[0]);
Transform val5 = (Transform)((value4 is Transform) ? value4 : null);
if ((Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null || (Object)(object)val4 == (Object)null || (Object)(object)val5 == (Object)null)
{
return;
}
RectTransform rectTransform = ((Graphic)val2).rectTransform;
_ = ((Graphic)val3).rectTransform;
_ = val4.rectTransform;
float num2 = 0f;
if (count > 1)
{
object? value5 = field2.GetValue(list[1]);
Image val6 = (Image)((value5 is Image) ? value5 : null);
if ((Object)(object)val6 != (Object)null)
{
num2 = ((Graphic)val6).rectTransform.anchoredPosition.x - rectTransform.anchoredPosition.x;
}
}
if (Mathf.Approximately(num2, 0f))
{
num2 = rectTransform.sizeDelta.x + 10f;
}
float num3 = rectTransform.sizeDelta.y + 10f;
Transform parent = ((Transform)rectTransform).parent;
RectTransform val7 = (RectTransform)(object)((parent is RectTransform) ? parent : null);
for (int i = count; i < num; i++)
{
int index = count - 1;
object obj4 = list[index];
object? value6 = field2.GetValue(obj4);
Image val8 = (Image)((value6 is Image) ? value6 : null);
object? value7 = field3.GetValue(obj4);
Image val9 = (Image)((value7 is Image) ? value7 : null);
object? value8 = field4.GetValue(obj4);
TMP_Text val10 = (TMP_Text)((value8 is TMP_Text) ? value8 : null);
object? value9 = field5.GetValue(obj4);
Transform val11 = (Transform)((value9 is Transform) ? value9 : null);
if ((Object)(object)val8 == (Object)null || (Object)(object)val9 == (Object)null || (Object)(object)val10 == (Object)null || (Object)(object)val11 == (Object)null)
{
continue;
}
int num4 = i - count;
int num5 = num4 / 8;
int num6 = num4 % 8;
GameObject val12 = new GameObject(((Object)((Component)val8).gameObject).name + "_Extra" + i);
val12.transform.SetParent((Transform)(object)val7, false);
Image val13 = val12.AddComponent<Image>();
val13.sprite = val8.sprite;
val13.type = val8.type;
((Graphic)val13).material = ((Graphic)val8).material;
((Graphic)val13).color = ((Graphic)val8).color;
RectTransform rectTransform2 = ((Graphic)val13).rectTransform;
rectTransform2.anchorMin = rectTransform.anchorMin;
rectTransform2.anchorMax = rectTransform.anchorMax;
rectTransform2.pivot = rectTransform.pivot;
rectTransform2.sizeDelta = rectTransform.sizeDelta;
object? value10 = field2.GetValue(list[count - 1]);
object? obj5 = ((value10 is Image) ? value10 : null);
float num7 = (((obj5 != null) ? ((Graphic)obj5).rectTransform : null) ?? rectTransform).anchoredPosition.x + num2;
float y = rectTransform.anchoredPosition.y;
float num8 = num7 - (float)num6 * num2;
float num9 = y + (float)num5 * num3;
rectTransform2.anchoredPosition = new Vector2(num8, num9);
GameObject val14 = new GameObject(((Object)((Component)val9).gameObject).name + "_Extra" + i);
val14.transform.SetParent(val12.transform, false);
Image val15 = val14.AddComponent<Image>();
val15.sprite = val9.sprite;
val15.type = val9.type;
((Graphic)val15).color = ((Graphic)val9).color;
((Graphic)val15).material = ((Graphic)val9).material;
RectTransform rectTransform3 = ((Graphic)val15).rectTransform;
RectTransform rectTransform4 = ((Graphic)val9).rectTransform;
rectTransform3.anchorMin = rectTransform4.anchorMin;
rectTransform3.anchorMax = rectTransform4.anchorMax;
rectTransform3.pivot = rectTransform4.pivot;
rectTransform3.sizeDelta = rectTransform4.sizeDelta;
rectTransform3.anchoredPosition = rectTransform4.anchoredPosition;
GameObject val16 = new GameObject(((Object)((Component)val10).gameObject).name + "_Extra" + i);
val16.transform.SetParent(val12.transform, false);
Component obj6 = val16.AddComponent(((object)val10).GetType());
TMP_Text val17 = (TMP_Text)(object)((obj6 is TMP_Text) ? obj6 : null);
if ((Object)(object)val17 == (Object)null)
{
MelonLogger.Error("[InventoryExpansion][UI] Failed to create TMP_Text for extra slot " + i + "; skipping this slot.");
Object.Destroy((Object)(object)val12);
continue;
}
val17.text = string.Empty;
val17.font = val10.font;
val17.fontSize = val10.fontSize;
val17.alignment = val10.alignment;
((Graphic)val17).color = ((Graphic)val10).color;
RectTransform rectTransform5 = val10.rectTransform;
RectTransform rectTransform6 = val17.rectTransform;
rectTransform6.anchorMin = rectTransform5.anchorMin;
rectTransform6.anchorMax = rectTransform5.anchorMax;
rectTransform6.pivot = rectTransform5.pivot;
rectTransform6.sizeDelta = rectTransform5.sizeDelta;
rectTransform6.anchoredPosition = rectTransform5.anchoredPosition;
GameObject val18 = new GameObject(((Object)((Component)val11).gameObject).name + "_Extra" + i);
val18.transform.SetParent(val12.transform, false);
RectTransform val19 = val18.AddComponent<RectTransform>();
RectTransform val20 = (RectTransform)(object)((val11 is RectTransform) ? val11 : null);
if ((Object)(object)val20 != (Object)null)
{
val19.anchorMin = val20.anchorMin;
val19.anchorMax = val20.anchorMax;
val19.pivot = val20.pivot;
val19.sizeDelta = val20.sizeDelta;
val19.anchoredPosition = val20.anchoredPosition;
}
object obj7 = Activator.CreateInstance(type);
field2.SetValue(obj7, val13);
field3.SetValue(obj7, val15);
field4.SetValue(obj7, val17);
field5.SetValue(obj7, ((Component)val19).transform);
list.Add(obj7);
}
MelonLogger.Msg("[InventoryExpansion][UI] Extended inventorySlots from " + count + " to " + list.Count + " visual slots.");
}
catch (Exception ex)
{
MelonLogger.Error("[InventoryExpansion][UI] Awake postfix failed while extending slots: " + ex);
}
}
}
[HarmonyPatch]
internal static class InventoryDebugControllerPatches
{
[HarmonyPostfix]
[HarmonyPatch(typeof(InventoryController), "Initialize")]
private static void InventoryController_Initialize_Postfix(InventoryController __instance)
{
try
{
if (typeof(InventoryController).GetField("_inventorySlots", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(__instance) is IDictionary dictionary)
{
string text = string.Join(",", dictionary.Keys.Cast<object>());
MelonLogger.Msg("[InventoryExpansion][Debug] InventoryController.Initialize: slot dict count = " + dictionary.Count + ", keys = [" + text + "]");
}
}
catch (Exception arg)
{
MelonLogger.Error($"[InventoryExpansion][Debug] InventoryController.Initialize debug failed: {arg}");
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(InventoryController), "GetInventoryInfos")]
private static void InventoryController_GetInventoryInfos_Postfix(Dictionary<int, ItemInfo> __result)
{
try
{
if (__result == null)
{
MelonLogger.Msg("[InventoryExpansion][Debug] GetInventoryInfos: result is null.");
return;
}
int count = __result.Count;
int num = ((__result.Count > 0) ? __result.Keys.Max() : 0);
MelonLogger.Msg($"[InventoryExpansion][Debug] GetInventoryInfos: {count} entries, max key = {num}.");
}
catch (Exception arg)
{
MelonLogger.Error($"[InventoryExpansion][Debug] GetInventoryInfos debug failed: {arg}");
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(InventoryController), "HandleAddItem")]
private static void InventoryController_HandleAddItem_Postfix(InventoryController __instance, MsgErrorCode __result, int addedSlotIndex)
{
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Invalid comparison between Unknown and I4
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
try
{
IDictionary dictionary = typeof(InventoryController).GetField("_inventorySlots", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(__instance) as IDictionary;
int num = dictionary?.Count ?? (-1);
string text = ((dictionary != null) ? string.Join(",", dictionary.Keys.Cast<object>()) : "null");
if ((int)__result == 20000012)
{
MelonLogger.Msg("[InventoryExpansion][Debug] HandleAddItem: INVENTORY FULL. slotCount=" + num + ", keys=[" + text + "]");
}
else if ((int)__result == 0)
{
MelonLogger.Msg("[InventoryExpansion][Debug] HandleAddItem: Success, addedSlotIndex=" + addedSlotIndex + ", slotCount=" + num + ".");
}
else
{
MelonLogger.Msg("[InventoryExpansion][Debug] HandleAddItem: Result=" + ((object)(MsgErrorCode)(ref __result)).ToString() + ", addedSlotIndex=" + addedSlotIndex + ", slotCount=" + num + ".");
}
}
catch (Exception arg)
{
MelonLogger.Error($"[InventoryExpansion][Debug] HandleAddItem debug failed: {arg}");
}
}
}
[HarmonyPatch]
internal static class InventoryDebugClientPatches
{
private static MethodBase TargetMethod()
{
try
{
Type nestedType = typeof(ProtoActor).GetNestedType("Inventory", BindingFlags.Public | BindingFlags.NonPublic);
if (nestedType == null)
{
MelonLogger.Error("[InventoryExpansion][Debug] Failed to find nested type ProtoActor.Inventory for ResolveInventoryInfos debug patch.");
return null;
}
MethodInfo? method = nestedType.GetMethod("ResolveInventoryInfos", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (method == null)
{
MelonLogger.Error("[InventoryExpansion][Debug] Failed to find ResolveInventoryInfos method on ProtoActor.Inventory.");
}
return method;
}
catch (Exception ex)
{
MelonLogger.Error("[InventoryExpansion][Debug] TargetMethod for ResolveInventoryInfos failed: " + ex);
return null;
}
}
[HarmonyPostfix]
private static void Inventory_ResolveInventoryInfos_Postfix(object __instance, Dictionary<int, ItemInfo> serverItemInfos, int? currentServerSlotIndex)
{
try
{
if (__instance == null)
{
return;
}
Type type = __instance.GetType();
int num = (int)(type.GetField("slotSize", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(__instance) ?? ((object)0));
IList list = type.GetField("slotItems", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(__instance) as IList;
int num2 = 0;
if (list != null)
{
foreach (object item in list)
{
if (item != null)
{
num2++;
}
}
}
int num3 = serverItemInfos?.Count ?? 0;
int num4 = ((num3 > 0) ? serverItemInfos.Keys.Max() : 0);
string text = (currentServerSlotIndex.HasValue ? currentServerSlotIndex.Value.ToString() : "null");
MelonLogger.Msg("[InventoryExpansion][Debug] ResolveInventoryInfos: slotSize=" + num + ", serverItems=" + num3 + ", serverMaxKey=" + num4 + ", localNonNullItems=" + num2 + ", currentServerSlotIndex=" + text + ".");
}
catch (Exception ex)
{
MelonLogger.Error("[InventoryExpansion][Debug] ResolveInventoryInfos debug failed: " + ex);
}
}
}
[HarmonyPatch]
internal static class BackpackPanelPatch
{
[CompilerGenerated]
private sealed class <AnimateBackpackVisibility>d__21 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public bool targetVisible;
private Vector2 <startPos>5__2;
private Vector2 <targetPos>5__3;
private float <elapsed>5__4;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <AnimateBackpackVisibility>d__21(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_0082: 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_009c: Unknown result type (might be due to invalid IL or missing references)
//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
//IL_0177: Unknown result type (might be due to invalid IL or missing references)
//IL_017d: Unknown result type (might be due to invalid IL or missing references)
//IL_0183: Unknown result type (might be due to invalid IL or missing references)
//IL_01de: Unknown result type (might be due to invalid IL or missing references)
switch (<>1__state)
{
default:
return false;
case 0:
{
<>1__state = -1;
if ((Object)(object)_backpackPanel == (Object)null)
{
return false;
}
if (_panelHeight == 0f)
{
_panelHeight = _backpackPanel.sizeDelta.y;
}
if (_initialPanelY == 0f)
{
_initialPanelY = 40f;
}
float num = _initialPanelY - _panelHeight * 0.75f;
float initialPanelY = _initialPanelY;
<startPos>5__2 = _backpackPanel.anchoredPosition;
<targetPos>5__3 = (targetVisible ? new Vector2(<startPos>5__2.x, initialPanelY) : new Vector2(<startPos>5__2.x, num));
if (Mathf.Abs(<startPos>5__2.y - <targetPos>5__3.y) < 1f)
{
_backpackFullyVisible = targetVisible;
UpdateKeyHintVisibility();
_animationCoroutine = null;
return false;
}
<elapsed>5__4 = 0f;
((Component)_backpackPanel).gameObject.SetActive(true);
break;
}
case 1:
<>1__state = -1;
break;
}
if (<elapsed>5__4 < 0.3f)
{
if ((Object)(object)_backpackPanel == (Object)null || (Object)(object)((Component)_backpackPanel).gameObject == (Object)null)
{
return false;
}
<elapsed>5__4 += Time.deltaTime;
float num2 = Mathf.Clamp01(<elapsed>5__4 / 0.3f);
num2 = 1f - Mathf.Pow(1f - num2, 3f);
_backpackPanel.anchoredPosition = Vector2.Lerp(<startPos>5__2, <targetPos>5__3, num2);
UpdateKeyHintVisibility();
<>2__current = null;
<>1__state = 1;
return true;
}
if ((Object)(object)_backpackPanel != (Object)null && (Object)(object)((Component)_backpackPanel).gameObject != (Object)null)
{
_backpackPanel.anchoredPosition = <targetPos>5__3;
_backpackFullyVisible = targetVisible;
UpdateKeyHintVisibility();
}
_animationCoroutine = 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();
}
}
[CompilerGenerated]
private sealed class <MoveSlotsToPanelCoroutine>d__26 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public UIPrefab_Inventory inventoryUI;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <MoveSlotsToPanelCoroutine>d__26(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0114: Unknown result type (might be due to invalid IL or missing references)
//IL_0121: Unknown result type (might be due to invalid IL or missing references)
//IL_0259: Unknown result type (might be due to invalid IL or missing references)
//IL_0824: Unknown result type (might be due to invalid IL or missing references)
//IL_0866: Unknown result type (might be due to invalid IL or missing references)
//IL_0872: Unknown result type (might be due to invalid IL or missing references)
//IL_08a3: Unknown result type (might be due to invalid IL or missing references)
//IL_0335: Unknown result type (might be due to invalid IL or missing references)
//IL_033c: Expected O, but got Unknown
//IL_036f: Unknown result type (might be due to invalid IL or missing references)
//IL_0384: Unknown result type (might be due to invalid IL or missing references)
//IL_0399: Unknown result type (might be due to invalid IL or missing references)
//IL_03dd: Unknown result type (might be due to invalid IL or missing references)
//IL_03eb: Unknown result type (might be due to invalid IL or missing references)
//IL_0552: Unknown result type (might be due to invalid IL or missing references)
//IL_0568: Unknown result type (might be due to invalid IL or missing references)
//IL_0576: Unknown result type (might be due to invalid IL or missing references)
//IL_0584: Unknown result type (might be due to invalid IL or missing references)
//IL_058e: Unknown result type (might be due to invalid IL or missing references)
//IL_059a: Unknown result type (might be due to invalid IL or missing references)
//IL_05c4: 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_05ee: Unknown result type (might be due to invalid IL or missing references)
//IL_0413: Unknown result type (might be due to invalid IL or missing references)
//IL_0418: Unknown result type (might be due to invalid IL or missing references)
//IL_044d: 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_0474: Unknown result type (might be due to invalid IL or missing references)
//IL_04dd: Unknown result type (might be due to invalid IL or missing references)
//IL_04ea: Unknown result type (might be due to invalid IL or missing references)
//IL_04f7: Unknown result type (might be due to invalid IL or missing references)
//IL_0504: 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_051a: Unknown result type (might be due to invalid IL or missing references)
//IL_0524: Unknown result type (might be due to invalid IL or missing references)
//IL_07a1: Unknown result type (might be due to invalid IL or missing references)
//IL_07ae: Unknown result type (might be due to invalid IL or missing references)
//IL_07bb: Unknown result type (might be due to invalid IL or missing references)
//IL_07c8: Unknown result type (might be due to invalid IL or missing references)
//IL_07d2: Unknown result type (might be due to invalid IL or missing references)
//IL_07de: Unknown result type (might be due to invalid IL or missing references)
//IL_07e8: Unknown result type (might be due to invalid IL or missing references)
//IL_069d: Unknown result type (might be due to invalid IL or missing references)
//IL_06ab: Unknown result type (might be due to invalid IL or missing references)
//IL_06c7: Unknown result type (might be due to invalid IL or missing references)
//IL_070d: Unknown result type (might be due to invalid IL or missing references)
//IL_071b: Unknown result type (might be due to invalid IL or missing references)
//IL_0729: Unknown result type (might be due to invalid IL or missing references)
//IL_0737: Unknown result type (might be due to invalid IL or missing references)
//IL_0741: Unknown result type (might be due to invalid IL or missing references)
//IL_074f: Unknown result type (might be due to invalid IL or missing references)
//IL_0759: Unknown result type (might be due to invalid IL or missing references)
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<>2__current = null;
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
try
{
if ((Object)(object)_backpackPanel == (Object)null || _slotsMoved)
{
return false;
}
FieldInfo field = typeof(UIPrefab_Inventory).GetField("inventorySlots", BindingFlags.Instance | BindingFlags.NonPublic);
if (field == null)
{
MelonLogger.Error("[InventoryExpansion][BackpackPanel] Could not find inventorySlots field!");
return false;
}
if (!(field.GetValue(inventoryUI) is IList list) || list.Count <= 4)
{
return false;
}
Type type = list[0].GetType();
FieldInfo field2 = type.GetField("frame", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (field2 == null)
{
MelonLogger.Error("[InventoryExpansion][BackpackPanel] Could not find frame field in slot!");
return false;
}
object obj = list[0];
object? value = field2.GetValue(obj);
Image val = (Image)((value is Image) ? value : null);
if ((Object)(object)val == (Object)null)
{
MelonLogger.Error("[InventoryExpansion][BackpackPanel] Could not get first frame!");
return false;
}
RectTransform rectTransform = ((Graphic)val).rectTransform;
float x = rectTransform.sizeDelta.x;
float y = rectTransform.sizeDelta.y;
x *= 0.5f;
y *= 0.5f;
Image val2 = null;
Transform parent = ((Transform)rectTransform).parent;
if ((Object)(object)parent != (Object)null)
{
for (int i = 0; i < parent.childCount; i++)
{
Transform child = parent.GetChild(i);
if (((Object)child).name.Contains("InvenBG") || ((Object)child).name.Contains("BG"))
{
val2 = ((Component)child).GetComponent<Image>();
if ((Object)(object)val2 != (Object)null)
{
break;
}
}
}
}
float num = 10f;
int num2 = list.Count - 4;
int num3 = num2 switch
{
4 => 2,
9 => 3,
16 => 4,
_ => Mathf.CeilToInt(Mathf.Sqrt((float)num2)),
};
int num4 = Mathf.CeilToInt((float)num2 / (float)num3);
float num5 = (float)num3 * x + (float)(num3 + 1) * num;
float num6 = (float)num4 * y + (float)(num4 + 1) * num;
(float padding, float paddingTop, float paddingBottom) paddingForSlotCount = GetPaddingForSlotCount(num2);
float item = paddingForSlotCount.padding;
float item2 = paddingForSlotCount.paddingTop;
float item3 = paddingForSlotCount.paddingBottom;
float num7 = num5 + item * 2f;
float num8 = num6 + item2 + item3;
_backpackPanel.sizeDelta = new Vector2(num7, num8);
FieldInfo field3 = type.GetField("image", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
FieldInfo field4 = type.GetField("stackCount", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
object? obj2 = field3?.GetValue(obj);
Image val3 = (Image)((obj2 is Image) ? obj2 : null);
object? obj3 = field4?.GetValue(obj);
TMP_Text val4 = (TMP_Text)((obj3 is TMP_Text) ? obj3 : null);
RectTransform val5 = ((val3 != null) ? ((Graphic)val3).rectTransform : null);
RectTransform val6 = ((val4 != null) ? val4.rectTransform : null);
for (int j = 4; j < list.Count; j++)
{
object obj4 = list[j];
object? value2 = field2.GetValue(obj4);
Image val7 = (Image)((value2 is Image) ? value2 : null);
if ((Object)(object)val7 == (Object)null)
{
continue;
}
RectTransform rectTransform2 = ((Graphic)val7).rectTransform;
if (!((Object)((Component)val7).gameObject).name.Contains("_Extra"))
{
continue;
}
GameObject val8 = new GameObject("InventoryExpansion_SlotContainer_" + j);
val8.transform.SetParent((Transform)(object)_backpackPanel, false);
RectTransform obj5 = val8.AddComponent<RectTransform>();
int num9 = j - 4;
int num10 = num9 / num3;
int num11 = num9 % num3;
obj5.anchorMin = new Vector2(0f, 1f);
obj5.anchorMax = new Vector2(0f, 1f);
obj5.pivot = new Vector2(0f, 1f);
(float horizontal, float top) slotPaddingForSlotCount = GetSlotPaddingForSlotCount(num2);
float item4 = slotPaddingForSlotCount.horizontal;
float item5 = slotPaddingForSlotCount.top;
float num12 = item4 + num + (float)num11 * (x + num);
float num13 = 0f - (item5 + num + (float)num10 * (y + num));
obj5.anchoredPosition = new Vector2(num12, num13);
obj5.sizeDelta = new Vector2(x, y);
if ((Object)(object)val2 != (Object)null)
{
GameObject val9 = new GameObject("InvenBG_Extra" + j);
val9.transform.SetParent(val8.transform, false);
Image obj6 = val9.AddComponent<Image>();
obj6.sprite = val2.sprite;
((Graphic)obj6).material = ((Graphic)val2).material;
((Graphic)obj6).color = ((Graphic)val2).color;
obj6.type = val2.type;
obj6.preserveAspect = val2.preserveAspect;
obj6.fillMethod = val2.fillMethod;
obj6.fillAmount = val2.fillAmount;
obj6.fillCenter = val2.fillCenter;
obj6.fillClockwise = val2.fillClockwise;
obj6.fillOrigin = val2.fillOrigin;
((Graphic)obj6).raycastTarget = ((Graphic)val2).raycastTarget;
((MaskableGraphic)obj6).maskable = ((MaskableGraphic)val2).maskable;
RectTransform rectTransform3 = ((Graphic)obj6).rectTransform;
RectTransform rectTransform4 = ((Graphic)val2).rectTransform;
rectTransform3.anchorMin = rectTransform4.anchorMin;
rectTransform3.anchorMax = rectTransform4.anchorMax;
rectTransform3.pivot = rectTransform4.pivot;
rectTransform3.sizeDelta = rectTransform4.sizeDelta * 0.5f;
rectTransform3.anchoredPosition = rectTransform4.anchoredPosition * 0.5f;
}
((Transform)rectTransform2).SetParent(val8.transform, false);
RectTransform rectTransform5 = ((Graphic)val).rectTransform;
rectTransform2.anchorMin = new Vector2(0.5f, 0.5f);
rectTransform2.anchorMax = new Vector2(0.5f, 0.5f);
rectTransform2.pivot = rectTransform5.pivot;
rectTransform2.sizeDelta = rectTransform5.sizeDelta * 0.5f;
rectTransform2.anchoredPosition = Vector2.zero;
val7.sprite = val.sprite;
((Graphic)val7).material = ((Graphic)val).material;
((Graphic)val7).color = ((Graphic)val).color;
val7.type = val.type;
val7.preserveAspect = val.preserveAspect;
val7.fillMethod = val.fillMethod;
val7.fillAmount = val.fillAmount;
val7.fillCenter = val.fillCenter;
val7.fillClockwise = val.fillClockwise;
val7.fillOrigin = val.fillOrigin;
if (field3 != null && (Object)(object)val3 != (Object)null && (Object)(object)val5 != (Object)null)
{
object? value3 = field3.GetValue(obj4);
Image val10 = (Image)((value3 is Image) ? value3 : null);
if ((Object)(object)val10 != (Object)null)
{
RectTransform rectTransform6 = ((Graphic)val10).rectTransform;
val10.sprite = val3.sprite;
((Graphic)val10).material = ((Graphic)val3).material;
((Graphic)val10).color = ((Graphic)val3).color;
val10.type = val3.type;
val10.preserveAspect = val3.preserveAspect;
val10.fillMethod = val3.fillMethod;
val10.fillAmount = val3.fillAmount;
val10.fillCenter = val3.fillCenter;
val10.fillClockwise = val3.fillClockwise;
val10.fillOrigin = val3.fillOrigin;
rectTransform6.anchorMin = val5.anchorMin;
rectTransform6.anchorMax = val5.anchorMax;
rectTransform6.pivot = val5.pivot;
rectTransform6.sizeDelta = val5.sizeDelta * 0.5f;
rectTransform6.anchoredPosition = val5.anchoredPosition * 0.5f;
}
}
if (field4 != null && (Object)(object)val6 != (Object)null)
{
object? value4 = field4.GetValue(obj4);
TMP_Text val11 = (TMP_Text)((value4 is TMP_Text) ? value4 : null);
if ((Object)(object)val11 != (Object)null)
{
RectTransform rectTransform7 = val11.rectTransform;
rectTransform7.anchorMin = val6.anchorMin;
rectTransform7.anchorMax = val6.anchorMax;
rectTransform7.pivot = val6.pivot;
rectTransform7.sizeDelta = val6.sizeDelta * 0.5f;
rectTransform7.anchoredPosition = val6.anchoredPosition * 0.5f;
val11.fontSize = val4.fontSize * 0.5f;
}
}
}
_slotsMoved = true;
_panelHeight = _backpackPanel.sizeDelta.y;
if (_initialPanelY == 0f)
{
_initialPanelY = 40f;
}
float num14 = _initialPanelY - _panelHeight * 0.75f;
_backpackPanel.anchoredPosition = new Vector2(_backpackPanel.anchoredPosition.x, num14);
_backpackFullyVisible = false;
UpdateKeyHintVisibility();
MelonLogger.Msg("[InventoryExpansion][BackpackPanel] Moved {0} additional slots to panel. Panel size: {1}", new object[2] { num2, _backpackPanel.sizeDelta });
}
catch (Exception ex)
{
MelonLogger.Error("[InventoryExpansion][BackpackPanel] Failed to move slots to panel: " + ex);
}
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();
}
}
private static GameObject _rootObj;
private static GameObject _canvasObj;
private static RectTransform _backpackPanel;
private static bool _slotsMoved;
private static bool _backpackFullyVisible;
private static Sprite _backpackSprite;
private static object _animationCoroutine;
private static float _panelHeight;
private static float _initialPanelY;
private static TMP_Text _keyHintText;
internal static bool IsBackpackFullyVisible => _backpackFullyVisible;
[HarmonyPostfix]
[HarmonyPatch(typeof(UIPrefab_Inventory), "Awake")]
private static void UIPrefab_Inventory_Awake_Postfix(UIPrefab_Inventory __instance)
{
try
{
if (!InventoryExpansionPreferences.Enabled)
{
return;
}
BackpackSceneChangeHandler.Initialize();
if ((Object)(object)_backpackPanel != (Object)null)
{
if (!_slotsMoved)
{
MelonCoroutines.Start(MoveSlotsToPanelCoroutine(__instance));
}
}
else
{
CreateRoot();
CreateUI();
MelonCoroutines.Start(MoveSlotsToPanelCoroutine(__instance));
}
}
catch (Exception ex)
{
MelonLogger.Error("[InventoryExpansion][BackpackPanel] Failed to create backpack panel: " + ex);
}
}
private static void CreateRoot()
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Expected O, but got Unknown
if (!((Object)(object)_rootObj != (Object)null))
{
_rootObj = new GameObject("InventoryExpansion_Root");
Object.DontDestroyOnLoad((Object)(object)_rootObj);
}
}
private static void CreateUI()
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Expected O, but got Unknown
//IL_008e: Unknown result type (might be due to invalid IL or missing references)
//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
//IL_00fb: Expected O, but got Unknown
//IL_015a: Unknown result type (might be due to invalid IL or missing references)
//IL_0185: Unknown result type (might be due to invalid IL or missing references)
//IL_019e: Unknown result type (might be due to invalid IL or missing references)
//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)_canvasObj != (Object)null)
{
return;
}
if ((Object)(object)_rootObj == (Object)null)
{
CreateRoot();
}
_canvasObj = new GameObject("InventoryExpansion_Canvas");
_canvasObj.transform.SetParent(_rootObj.transform, false);
Canvas val = _canvasObj.AddComponent<Canvas>();
val.renderMode = (RenderMode)0;
CanvasScaler obj = _canvasObj.AddComponent<CanvasScaler>();
obj.uiScaleMode = (ScaleMode)0;
obj.scaleFactor = 1f;
Canvas val2 = null;
Canvas[] array = Object.FindObjectsByType<Canvas>((FindObjectsSortMode)0);
foreach (Canvas val3 in array)
{
if ((int)val3.renderMode == 0 && ((Object)val3).name.Contains("Canvas") && !((Object)val3).name.Contains("InventoryExpansion"))
{
val2 = val3;
break;
}
}
if ((Object)(object)val2 != (Object)null)
{
val.sortingOrder = val2.sortingOrder + 1;
}
_canvasObj.AddComponent<GraphicRaycaster>();
GameObject val4 = new GameObject("InventoryExpansion_BackpackPanel");
val4.transform.SetParent(_canvasObj.transform, false);
Image val5 = val4.AddComponent<Image>();
LoadBackpackSprite();
if ((Object)(object)_backpackSprite != (Object)null)
{
val5.sprite = _backpackSprite;
val5.type = (Type)0;
val5.preserveAspect = false;
}
else
{
((Graphic)val5).color = new Color(0f, 0f, 0f, 0.8f);
}
((Graphic)val5).raycastTarget = false;
_backpackPanel = val4.GetComponent<RectTransform>();
_backpackPanel.anchorMin = new Vector2(1f, 0f);
_backpackPanel.anchorMax = new Vector2(1f, 0f);
_backpackPanel.pivot = new Vector2(1f, 0f);
_backpackPanel.sizeDelta = new Vector2(450f, 200f);
_backpackPanel.anchoredPosition = new Vector2(-40f, 40f);
_initialPanelY = 40f;
try
{
CreateKeyHintText(val4);
}
catch (Exception arg)
{
MelonLogger.Warning($"[InventoryExpansion][BackpackPanel] Failed to create key hint text during UI creation: {arg}");
}
_backpackFullyVisible = false;
((Component)_backpackPanel).gameObject.SetActive(true);
}
private static void LoadBackpackSprite()
{
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Expected O, but got Unknown
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
try
{
string text = Path.Combine(Path.GetDirectoryName(typeof(BackpackPanelPatch).Assembly.Location), "Assets", "Backpack.png");
if (!File.Exists(text))
{
MelonLogger.Warning("[InventoryExpansion][BackpackPanel] Backpack asset not found at: " + text);
return;
}
byte[] array = File.ReadAllBytes(text);
Texture2D val = new Texture2D(2, 2);
bool flag = false;
try
{
flag = ImageConversion.LoadImage(val, array);
}
catch
{
try
{
flag = ImageConversion.LoadImage(val, array);
}
catch
{
}
}
if (!flag)
{
MelonLogger.Error("[InventoryExpansion][BackpackPanel] Failed to load Backpack.png as texture");
Object.Destroy((Object)(object)val);
}
else
{
_backpackSprite = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
MelonLogger.Msg($"[InventoryExpansion][BackpackPanel] Loaded Backpack sprite: {((Texture)val).width}x{((Texture)val).height}");
}
}
catch (Exception arg)
{
MelonLogger.Error($"[InventoryExpansion][BackpackPanel] Failed to load Backpack sprite: {arg}");
}
}
internal static void ToggleBackpack()
{
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)_backpackPanel == (Object)null) && !IsInLoadingScreen() && !IsGamePaused())
{
bool targetVisible = !_backpackFullyVisible;
if (_animationCoroutine != null)
{
MelonCoroutines.Stop(_animationCoroutine);
_animationCoroutine = null;
}
((Component)_backpackPanel).gameObject.SetActive(true);
if (_panelHeight == 0f)
{
_panelHeight = _backpackPanel.sizeDelta.y;
}
if (_initialPanelY == 0f)
{
_initialPanelY = 40f;
}
_animationCoroutine = MelonCoroutines.Start(AnimateBackpackVisibility(targetVisible));
}
}
internal static bool IsGamePaused()
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
try
{
if (Time.timeScale <= 0.01f)
{
return true;
}
if ((int)Cursor.lockState == 0 && Cursor.visible && IsInGame())
{
return true;
}
return false;
}
catch
{
return false;
}
}
internal static bool IsInGame()
{
try
{
Hub s = Hub.s;
if ((Object)(object)s == (Object)null)
{
return false;
}
FieldInfo field = typeof(Hub).GetField("protoActor", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
ProtoActor val = null;
if (field == null)
{
FieldInfo[] fields = typeof(Hub).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (FieldInfo fieldInfo in fields)
{
if (fieldInfo.FieldType == typeof(ProtoActor) || fieldInfo.FieldType.IsSubclassOf(typeof(ProtoActor)))
{
object? value = fieldInfo.GetValue(s);
val = (ProtoActor)((value is ProtoActor) ? value : null);
if ((Object)(object)val != (Object)null && val.AmIAvatar())
{
return true;
}
}
}
return false;
}
object? value2 = field.GetValue(s);
val = (ProtoActor)((value2 is ProtoActor) ? value2 : null);
if ((Object)(object)val == (Object)null)
{
return false;
}
return val.AmIAvatar();
}
catch (Exception arg)
{
MelonLogger.Warning($"[InventoryExpansion][BackpackPanel] IsInGame check failed: {arg}");
return false;
}
}
private static bool IsInLoadingScreen()
{
try
{
Hub s = Hub.s;
if ((Object)(object)s == (Object)null)
{
return true;
}
FieldInfo field = typeof(Hub).GetField("protoActor", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (field == null)
{
return false;
}
object? value = field.GetValue(s);
ProtoActor val = (ProtoActor)((value is ProtoActor) ? value : null);
if ((Object)(object)val == (Object)null)
{
return true;
}
return !val.AmIAvatar();
}
catch
{
return false;
}
}
internal static void HideBackpackCompletely()
{
if ((Object)(object)_backpackPanel != (Object)null && (Object)(object)((Component)_backpackPanel).gameObject != (Object)null)
{
((Component)_backpackPanel).gameObject.SetActive(false);
}
}
[IteratorStateMachine(typeof(<AnimateBackpackVisibility>d__21))]
private static IEnumerator AnimateBackpackVisibility(bool targetVisible)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <AnimateBackpackVisibility>d__21(0)
{
targetVisible = targetVisible
};
}
private static void CreateKeyHintText(GameObject parent)
{
//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
//IL_00b6: Expected O, but got Unknown
//IL_0156: Unknown result type (might be due to invalid IL or missing references)
//IL_015b: Unknown result type (might be due to invalid IL or missing references)
//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
//IL_0235: Unknown result type (might be due to invalid IL or missing references)
//IL_024a: Unknown result type (might be due to invalid IL or missing references)
//IL_025f: Unknown result type (might be due to invalid IL or missing references)
//IL_0274: Unknown result type (might be due to invalid IL or missing references)
//IL_0288: Unknown result type (might be due to invalid IL or missing references)
try
{
if ((Object)(object)parent == (Object)null)
{
MelonLogger.Warning("[InventoryExpansion][BackpackPanel] Cannot create key hint text: parent is null");
return;
}
Type type = null;
TMP_FontAsset val = null;
try
{
TMP_Text[] array = Object.FindObjectsByType<TMP_Text>((FindObjectsSortMode)0);
if (array != null && array.Length != 0)
{
TMP_Text[] array2 = array;
foreach (TMP_Text val2 in array2)
{
if ((Object)(object)val2 != (Object)null && !((object)val2).Equals((object?)null) && (Object)(object)val2.font != (Object)null)
{
type = ((object)val2).GetType();
val = val2.font;
break;
}
}
}
}
catch (Exception arg)
{
MelonLogger.Warning($"[InventoryExpansion][BackpackPanel] Error finding TMP_Text type: {arg}");
}
if (type == null)
{
type = typeof(TMP_Text);
}
GameObject val3 = new GameObject("InventoryExpansion_KeyHint");
if ((Object)(object)val3 == (Object)null)
{
MelonLogger.Warning("[InventoryExpansion][BackpackPanel] Failed to create key hint GameObject");
return;
}
val3.transform.SetParent(parent.transform, false);
val3.transform.SetAsLastSibling();
Component obj = val3.AddComponent(type);
_keyHintText = (TMP_Text)(object)((obj is TMP_Text) ? obj : null);
if ((Object)(object)_keyHintText == (Object)null)
{
MelonLogger.Warning("[InventoryExpansion][BackpackPanel] Failed to add TMP_Text component");
Object.Destroy((Object)(object)val3);
return;
}
if ((Object)(object)val != (Object)null)
{
_keyHintText.font = val;
}
else
{
TMP_FontAsset defaultFontAsset = TMP_Settings.defaultFontAsset;
if ((Object)(object)defaultFontAsset != (Object)null)
{
_keyHintText.font = defaultFontAsset;
}
}
TMP_Text keyHintText = _keyHintText;
KeyCode backpackKey = InventoryExpansionPreferences.BackpackKey;
keyHintText.text = ((object)(KeyCode)(ref backpackKey)).ToString();
_keyHintText.fontSize = 24f;
_keyHintText.alignment = (TextAlignmentOptions)514;
((Graphic)_keyHintText).color = new Color(1f, 1f, 1f, 1f);
_keyHintText.fontStyle = (FontStyles)1;
Outline val4 = val3.AddComponent<Outline>();
if ((Object)(object)val4 != (Object)null)
{
((Shadow)val4).effectColor = new Color(0f, 0f, 0f, 1f);
((Shadow)val4).effectDistance = new Vector2(2f, 2f);
}
if ((Object)(object)_keyHintText.rectTransform == (Object)null)
{
MelonLogger.Warning("[InventoryExpansion][BackpackPanel] Key hint text has no RectTransform");
return;
}
RectTransform rectTransform = _keyHintText.rectTransform;
rectTransform.anchorMin = new Vector2(0.5f, 1f);
rectTransform.anchorMax = new Vector2(0.5f, 1f);
rectTransform.pivot = new Vector2(0.5f, 0.5f);
rectTransform.sizeDelta = new Vector2(60f, 35f);
rectTransform.anchoredPosition = new Vector2(0f, -95f);
((Graphic)_keyHintText).raycastTarget = false;
((Component)_keyHintText).gameObject.SetActive(true);
MelonLogger.Msg("[InventoryExpansion][BackpackPanel] Key hint text created successfully");
}
catch (Exception arg2)
{
MelonLogger.Error($"[InventoryExpansion][BackpackPanel] Failed to create key hint text: {arg2}");
_keyHintText = null;
}
}
private static void UpdateKeyHintVisibility()
{
if ((Object)(object)_keyHintText == (Object)null || (Object)(object)((Component)_keyHintText).gameObject == (Object)null)
{
return;
}
try
{
((Component)_keyHintText).gameObject.SetActive(true);
}
catch
{
}
}
private static (float padding, float paddingTop, float paddingBottom) GetPaddingForSlotCount(int additionalSlots)
{
return additionalSlots switch
{
4 => (90f, 130f, 90f),
9 => (160f, 200f, 140f),
_ => (200f, 240f, 180f),
};
}
private static (float horizontal, float top) GetSlotPaddingForSlotCount(int additionalSlots)
{
return additionalSlots switch
{
4 => (90f, 170f),
9 => (160f, 260f),
_ => (200f, 320f),
};
}
[IteratorStateMachine(typeof(<MoveSlotsToPanelCoroutine>d__26))]
private static IEnumerator MoveSlotsToPanelCoroutine(UIPrefab_Inventory inventoryUI)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <MoveSlotsToPanelCoroutine>d__26(0)
{
inventoryUI = inventoryUI
};
}
}
[HarmonyPatch(typeof(ProtoActor), "Update")]
internal static class BackpackInputUpdatePatch
{
private static bool wasKeyPressedLastFrame;
[HarmonyPostfix]
private static void Update_Postfix(ProtoActor __instance)
{
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
try
{
if (!InventoryExpansionPreferences.Enabled || !__instance.AmIAvatar())
{
return;
}
if (BackpackPanelPatch.IsGamePaused())
{
if (BackpackPanelPatch.IsBackpackFullyVisible)
{
BackpackPanelPatch.ToggleBackpack();
}
else
{
BackpackPanelPatch.HideBackpackCompletely();
}
wasKeyPressedLastFrame = false;
return;
}
Keyboard current = Keyboard.current;
if (current == null)
{
wasKeyPressedLastFrame = false;
return;
}
KeyCode backpackKey = InventoryExpansionPreferences.BackpackKey;
Key val = (Key)0;
try
{
val = (Key)Enum.Parse(typeof(Key), ((object)(KeyCode)(ref backpackKey)).ToString());
}
catch
{
MelonLogger.Warning($"[InventoryExpansion][BackpackPanel] Could not convert KeyCode {backpackKey} to Input System Key");
return;
}
bool isPressed = ((ButtonControl)current[val]).isPressed;
bool num = isPressed && !wasKeyPressedLastFrame;
wasKeyPressedLastFrame = isPressed;
if (num)
{
BackpackPanelPatch.ToggleBackpack();
}
}
catch (Exception arg)
{
MelonLogger.Error($"[InventoryExpansion][BackpackPanel] Update postfix failed: {arg}");
}
}
}
[HarmonyPatch(typeof(ProtoActor))]
internal static class BackpackMovementSpeedPatch
{
private static FieldInfo _netSyncActorDataField;
private static bool _fieldInitialized;
private static long _originalMoveSpeedWalk;
private static long _originalMoveSpeedRun;
private static bool _speedReduced;
[HarmonyPostfix]
[HarmonyPatch("Update")]
private static void Update_Postfix(ProtoActor __instance)
{
try
{
if (!InventoryExpansionPreferences.Enabled)
{
RestoreMoveSpeed(__instance);
}
else
{
if (!__instance.AmIAvatar())
{
return;
}
if (!_fieldInitialized)
{
_netSyncActorDataField = typeof(ProtoActor).GetField("netSyncActorData", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
_fieldInitialized = true;
}
if (_netSyncActorDataField == null)
{
return;
}
object value = _netSyncActorDataField.GetValue(__instance);
if (value == null)
{
return;
}
FieldInfo field = value.GetType().GetField("MoveSpeedWalk", BindingFlags.Instance | BindingFlags.Public);
FieldInfo field2 = value.GetType().GetField("MoveSpeedRun", BindingFlags.Instance | BindingFlags.Public);
if (field == null || field2 == null)
{
return;
}
if (BackpackPanelPatch.IsBackpackFullyVisible && InventoryExpansionPreferences.ReduceMovementSpeed)
{
if (!_speedReduced)
{
_originalMoveSpeedWalk = (long)(field.GetValue(value) ?? ((object)350L));
_originalMoveSpeedRun = (long)(field2.GetValue(value) ?? ((object)700L));
_speedReduced = true;
}
field.SetValue(value, (long)((float)_originalMoveSpeedWalk * 0.5f));
field2.SetValue(value, (long)((float)_originalMoveSpeedRun * 0.5f));
}
else
{
RestoreMoveSpeed(value, field, field2);
}
}
}
catch (Exception arg)
{
MelonLogger.Error($"[InventoryExpansion][Movement] Movement speed patch failed: {arg}");
}
}
private static void RestoreMoveSpeed(ProtoActor instance)
{
if (!_speedReduced || _netSyncActorDataField == null)
{
return;
}
object value = _netSyncActorDataField.GetValue(instance);
if (value != null)
{
FieldInfo field = value.GetType().GetField("MoveSpeedWalk", BindingFlags.Instance | BindingFlags.Public);
FieldInfo field2 = value.GetType().GetField("MoveSpeedRun", BindingFlags.Instance | BindingFlags.Public);
if (field != null && field2 != null)
{
RestoreMoveSpeed(value, field, field2);
}
}
}
private static void RestoreMoveSpeed(object netSyncActorData, FieldInfo moveSpeedWalkField, FieldInfo moveSpeedRunField)
{
if (_speedReduced && _originalMoveSpeedWalk > 0 && _originalMoveSpeedRun > 0)
{
moveSpeedWalkField.SetValue(netSyncActorData, _originalMoveSpeedWalk);
moveSpeedRunField.SetValue(netSyncActorData, _originalMoveSpeedRun);
_speedReduced = false;
}
}
}
[HarmonyPatch(typeof(ProtoActor), "OnDestroy")]
internal static class BackpackProtoActorDestroyPatch
{
[HarmonyPostfix]
private static void OnDestroy_Postfix(ProtoActor __instance)
{
try
{
if (InventoryExpansionPreferences.Enabled && __instance.AmIAvatar())
{
BackpackSceneChangeHandler.HideBackpack();
}
}
catch (Exception arg)
{
MelonLogger.Error($"[InventoryExpansion][BackpackPanel] ProtoActor OnDestroy patch failed: {arg}");
}
}
}
internal static class BackpackSceneChangeHandler
{
private static bool _initialized;
internal static void Initialize()
{
if (!_initialized)
{
SceneManager.activeSceneChanged += OnActiveSceneChanged;
_initialized = true;
}
}
private static void OnActiveSceneChanged(Scene previousScene, Scene newScene)
{
try
{
if (InventoryExpansionPreferences.Enabled && !IsInGame())
{
HideBackpack();
}
}
catch (Exception arg)
{
MelonLogger.Error($"[InventoryExpansion][BackpackPanel] Scene change handler failed: {arg}");
}
}
private static bool IsInGame()
{
try
{
Hub s = Hub.s;
if ((Object)(object)s == (Object)null)
{
return false;
}
FieldInfo field = typeof(Hub).GetField("protoActor", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
ProtoActor val = null;
if (field == null)
{
FieldInfo[] fields = typeof(Hub).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (FieldInfo fieldInfo in fields)
{
if (fieldInfo.FieldType == typeof(ProtoActor) || fieldInfo.FieldType.IsSubclassOf(typeof(ProtoActor)))
{
object? value = fieldInfo.GetValue(s);
val = (ProtoActor)((value is ProtoActor) ? value : null);
if ((Object)(object)val != (Object)null && val.AmIAvatar())
{
return true;
}
}
}
return false;
}
object? value2 = field.GetValue(s);
val = (ProtoActor)((value2 is ProtoActor) ? value2 : null);
if ((Object)(object)val == (Object)null)
{
return false;
}
return val.AmIAvatar();
}
catch
{
return false;
}
}
internal static void HideBackpack()
{
if (BackpackPanelPatch.IsBackpackFullyVisible)
{
BackpackPanelPatch.ToggleBackpack();
}
else
{
BackpackPanelPatch.HideBackpackCompletely();
}
}
}
internal static class InventorySelectionHelper
{
internal static Type GetInventoryType()
{
return typeof(ProtoActor).GetNestedType("Inventory", BindingFlags.Public | BindingFlags.NonPublic);
}
internal static FieldInfo GetSelectedSlotIndexField(Type inventoryType)
{
return inventoryType?.GetField("selectedSlotIndex", BindingFlags.Instance | BindingFlags.NonPublic);
}
internal static FieldInfo GetSlotSizeField(Type inventoryType)
{
return inventoryType?.GetField("slotSize", BindingFlags.Instance | BindingFlags.NonPublic);
}
}
[HarmonyPatch]
internal static class InventorySelectionNextPatches
{
private static MethodBase TargetMethod()
{
return InventorySelectionHelper.GetInventoryType()?.GetMethod("SelectNextSlot", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
}
[HarmonyPrefix]
private static bool SelectNextSlot_Prefix(object __instance)
{
return InventorySelectionCommon.HandleSlotSelection(__instance, forward: true);
}
}
[HarmonyPatch]
internal static class InventorySelectionPreviousPatches
{
private static MethodBase TargetMethod()
{
return InventorySelectionHelper.GetInventoryType()?.GetMethod("SelectPreviousSlot", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
}
[HarmonyPrefix]
private static bool SelectPreviousSlot_Prefix(object __instance)
{
return InventorySelectionCommon.HandleSlotSelection(__instance, forward: false);
}
}
internal static class InventorySelectionCommon
{
internal static bool HandleSlotSelection(object __instance, bool forward)
{
try
{
if (!InventoryExpansionPreferences.Enabled)
{
return true;
}
if (__instance == null)
{
return true;
}
Type type = __instance.GetType();
FieldInfo selectedSlotIndexField = InventorySelectionHelper.GetSelectedSlotIndexField(type);
FieldInfo slotSizeField = InventorySelectionHelper.GetSlotSizeField(type);
if (selectedSlotIndexField == null || slotSizeField == null)
{
return true;
}
int num = (int)(selectedSlotIndexField.GetValue(__instance) ?? ((object)0));
int num2 = (int)(slotSizeField.GetValue(__instance) ?? ((object)4));
int num3;
int num4;
if (BackpackPanelPatch.IsBackpackFullyVisible)
{
num3 = 4;
num4 = num2 - 1;
}
else
{
num3 = 0;
num4 = 3;
}
if (num3 > num4 || num < num3 || num > num4)
{
MethodInfo method = type.GetMethod("SelectSlot", BindingFlags.Instance | BindingFlags.NonPublic);
if (method != null)
{
method.Invoke(__instance, new object[1] { num3 });
return false;
}
return true;
}
int num5;
if (forward)
{
num5 = num + 1;
if (num5 > num4)
{
num5 = num3;
}
}
else
{
num5 = num - 1;
if (num5 < num3)
{
num5 = num4;
}
}
MethodInfo method2 = type.GetMethod("SelectSlot", BindingFlags.Instance | BindingFlags.NonPublic);
if (method2 != null)
{
method2.Invoke(__instance, new object[1] { num5 });
return false;
}
return true;
}
catch (Exception arg)
{
MelonLogger.Error($"[InventoryExpansion][Selection] Slot selection prefix failed: {arg}");
return true;
}
}
}
}
namespace InventoryExpansion.Config
{
internal static class InventoryExpansionPreferences
{
private const string CategoryId = "InventoryExpansion";
private static MelonPreferences_Category _category;
private static MelonPreferences_Entry<bool> _enabled;
private static MelonPreferences_Entry<int> _additionalSlots;
private static MelonPreferences_Entry<string> _backpackKey;
private static MelonPreferences_Entry<bool> _reduceMovementSpeed;
internal static bool Enabled => _enabled.Value;
internal static int AdditionalSlots
{
get
{
if (_additionalSlots == null)
{
return 4;
}
int value = _additionalSlots.Value;
int num = ClampToValidBackpackSize(value);
if (num != value)
{
_additionalSlots.Value = num;
}
return num;
}
}
internal static KeyCode BackpackKey
{
get
{
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
if (_backpackKey == null)
{
return (KeyCode)99;
}
string value = _backpackKey.Value;
if (string.IsNullOrEmpty(value))
{
return (KeyCode)99;
}
if (Enum.TryParse<KeyCode>(value, ignoreCase: true, out KeyCode result))
{
return result;
}
return (KeyCode)99;
}
}
internal static bool ReduceMovementSpeed => _reduceMovementSpeed?.Value ?? true;
internal static void Initialize()
{
if (_category == null)
{
_category = MelonPreferences.CreateCategory("InventoryExpansion", "InventoryExpansion");
_enabled = CreateEntry("Enabled", defaultValue: true, "Enabled", "Enable InventoryExpansion functionality. When disabled, the mod will not modify game behavior.");
_additionalSlots = CreateEntry("AdditionalSlots", 4, "Additional Inventory Slots", "Number of extra inventory slots to add on top of the game's default inventory size. Valid values: 4, 9, or 16 (for square grids: 2x2, 3x3, or 4x4). Other values will be rounded to the nearest valid option.");
_backpackKey = CreateEntry("BackpackKey", "C", "Backpack Toggle Key", "Key to toggle backpack visibility. Press to switch between standard inventory and backpack.");
_reduceMovementSpeed = CreateEntry("ReduceMovementSpeed", defaultValue: true, "Reduce Movement Speed", "When enabled, player movement speed is reduced to 50% while the backpack is fully open.");
}
}
private static MelonPreferences_Entry<T> CreateEntry<T>(string identifier, T defaultValue, string displayName, string description = null)
{
if (_category == null)
{
throw new InvalidOperationException("Preference category not initialized.");
}
return _category.CreateEntry<T>(identifier, defaultValue, displayName, description, false, false, (ValueValidator)null, (string)null);
}
private static int ClampToValidBackpackSize(int value)
{
if (value <= 0)
{
return 4;
}
if (value <= 6)
{
return 4;
}
if (value <= 12)
{
return 9;
}
return 16;
}
}
}