Decompiled source of PackRat v1.0.2

PackRat-IL2CPP.dll

Decompiled 8 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.Json;
using HarmonyLib;
using Il2CppFishNet;
using Il2CppFishNet.Component.Spawning;
using Il2CppFishNet.Object;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppNewtonsoft.Json;
using Il2CppScheduleOne;
using Il2CppScheduleOne.AvatarFramework;
using Il2CppScheduleOne.AvatarFramework.Customization;
using Il2CppScheduleOne.DevUtilities;
using Il2CppScheduleOne.ItemFramework;
using Il2CppScheduleOne.Levelling;
using Il2CppScheduleOne.NPCs;
using Il2CppScheduleOne.NPCs.Behaviour;
using Il2CppScheduleOne.Networking;
using Il2CppScheduleOne.Persistence;
using Il2CppScheduleOne.Persistence.Datas;
using Il2CppScheduleOne.Persistence.Loaders;
using Il2CppScheduleOne.PlayerScripts;
using Il2CppScheduleOne.Product;
using Il2CppScheduleOne.Product.Packaging;
using Il2CppScheduleOne.Storage;
using Il2CppScheduleOne.TV;
using Il2CppScheduleOne.Tools;
using Il2CppScheduleOne.UI;
using Il2CppScheduleOne.UI.ATM;
using Il2CppScheduleOne.UI.Phone;
using Il2CppScheduleOne.UI.Shop;
using Il2CppScheduleOne.Vehicles;
using Il2CppSteamworks;
using Il2CppSystem;
using Il2CppSystem.Collections;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.Linq;
using Il2CppTMPro;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using PackRat;
using PackRat.Config;
using PackRat.Extensions;
using PackRat.Helpers;
using PackRat.Patches;
using PackRat.Shops;
using PackRat.Storage;
using UnityEngine;
using UnityEngine.Events;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(global::PackRat.PackRat), "PackRat", "1.0.2", "SirTidez", null)]
[assembly: MelonColor(1, 255, 165, 0)]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("PackRat-IL2CPP")]
[assembly: AssemblyConfiguration("Debug IL2CPP")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+bb8cf00e0d4fb3f3e32037aff75ec210ea048a83")]
[assembly: AssemblyProduct("PackRat-IL2CPP")]
[assembly: AssemblyTitle("PackRat-IL2CPP")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 PackRat
{
	public static class BuildInfo
	{
		public const string Name = "PackRat";

		public const string Description = "Portable backpack storage for Schedule One";

		public const string Author = "SirTidez";

		public const string Version = "1.0.2";
	}
	public class PackRat : MelonMod
	{
		public override void OnInitializeMelon()
		{
			Configuration.Instance.Load();
			Configuration.Instance.Save();
			ModLogger.Info("PackRat initialized.");
		}

		public override void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
			Configuration.Instance.Reset();
			if (!(sceneName != "Main"))
			{
				ConfigSyncManager.StartSync();
				BackpackShopIntegration.RunWhenReady();
			}
		}
	}
	[RegisterTypeInIl2Cpp]
	public class PlayerBackpack : MonoBehaviour
	{
		public const string StorageName = "Backpack";

		public const int MaxStorageSlots = 40;

		private bool _backpackEnabled = true;

		private StorageEntity _storage;

		private int _lastTierIndex = -2;

		private string _openTitle;

		private int _highestPurchasedTierIndex = -1;

		public static PlayerBackpack Instance { get; private set; }

		public int HighestPurchasedTierIndex => _highestPurchasedTierIndex;

		public int CurrentTierIndex
		{
			get
			{
				Configuration instance = Configuration.Instance;
				if (_highestPurchasedTierIndex < 0)
				{
					return -1;
				}
				for (int num = _highestPurchasedTierIndex; num >= 0; num--)
				{
					if (num < instance.TierEnabled.Length && instance.TierEnabled[num])
					{
						return num;
					}
				}
				return -1;
			}
		}

		public BackpackTierDefinition CurrentTier
		{
			get
			{
				int currentTierIndex = CurrentTierIndex;
				return (currentTierIndex >= 0) ? Configuration.BackpackTiers[currentTierIndex] : null;
			}
		}

		public bool IsUnlocked => CurrentTierIndex >= 0;

		public bool IsPoliceSearchable => CurrentTierIndex >= 2;

		public bool IsOpen => Singleton<StorageMenu>.Instance.IsOpen && ((TMP_Text)Singleton<StorageMenu>.Instance.TitleLabel).text == _openTitle;

		public List<ItemSlot> ItemSlots => Enumerable.ToList<ItemSlot>(((Il2CppObjectBase)_storage.ItemSlots).Cast<IEnumerable<ItemSlot>>());

		public PlayerBackpack(IntPtr ptr)
			: base(ptr)
		{
		}

		public void SetHighestPurchasedTierIndex(int tierIndex)
		{
			_highestPurchasedTierIndex = ((tierIndex < 0) ? (-1) : Math.Min(tierIndex, Configuration.BackpackTiers.Length - 1));
		}

		private void Awake()
		{
			_storage = ((Component)this).gameObject.GetComponentInParent<StorageEntity>();
			if ((Object)(object)_storage == (Object)null)
			{
				ModLogger.Error("Player does not have a BackpackStorage component!");
				return;
			}
			ModLogger.Info("Configuring backpack storage...");
			int currentTierIndex = CurrentTierIndex;
			int newSize = ((currentTierIndex >= 0) ? Configuration.Instance.TierSlotCounts[currentTierIndex] : Configuration.BackpackTiers[0].DefaultSlotCount);
			UpdateSize(newSize);
			OnStartClient(isOwner: true);
		}

		private void Update()
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			int currentTierIndex = CurrentTierIndex;
			if (currentTierIndex != _lastTierIndex)
			{
				_lastTierIndex = currentTierIndex;
				ApplyCurrentTier(currentTierIndex);
			}
			if (!_backpackEnabled || !Input.GetKeyDown(Configuration.Instance.ToggleKey))
			{
				return;
			}
			try
			{
				if (TryConsumeSelectedHotbarBackpackItem(out var appliedTier))
				{
					if (appliedTier >= 0)
					{
						ModLogger.Info($"Backpack tier {appliedTier} ({Configuration.BackpackTiers[appliedTier].Name}) applied; opening backpack.");
					}
					if (IsOpen)
					{
						Close();
					}
					else
					{
						Open();
					}
				}
				else if (IsUnlocked)
				{
					if (IsOpen)
					{
						Close();
					}
					else
					{
						Open();
					}
				}
			}
			catch (Exception exception)
			{
				ModLogger.Error("Error toggling backpack", exception);
			}
		}

		private bool TryConsumeSelectedHotbarBackpackItem(out int appliedTier)
		{
			appliedTier = -1;
			try
			{
				PlayerInventory instance = PlayerSingleton<PlayerInventory>.Instance;
				if ((Object)(object)instance == (Object)null)
				{
					return false;
				}
				object obj = ReflectionUtils.TryGetFieldOrProperty(instance, "hotbarSlots");
				if (obj == null)
				{
					return false;
				}
				int num = ReflectionUtils.TryGetListCount(obj);
				if (num <= 0)
				{
					return false;
				}
				int selectedHotbarIndex = GetSelectedHotbarIndex(instance);
				if (selectedHotbarIndex >= 0 && selectedHotbarIndex < num && TryConsumeBackpackItemFromSlot(instance, obj, selectedHotbarIndex, out appliedTier))
				{
					return true;
				}
				for (int i = 0; i < num; i++)
				{
					if (TryConsumeBackpackItemFromSlot(instance, obj, i, out appliedTier))
					{
						return true;
					}
				}
				List<object> list = ReflectionUtils.TryGetAllListLikeMembers(instance);
				foreach (object item in list)
				{
					if (item == obj)
					{
						continue;
					}
					int num2 = ReflectionUtils.TryGetListCount(item);
					for (int j = 0; j < num2; j++)
					{
						if (TryConsumeBackpackItemFromSlot(instance, item, j, out appliedTier))
						{
							return true;
						}
					}
				}
				return false;
			}
			catch (Exception exception)
			{
				ModLogger.Error("TryConsumeSelectedHotbarBackpackItem", exception);
				return false;
			}
		}

		private bool TryConsumeBackpackItemFromSlot(object playerInventory, object slotsList, int index, out int appliedTier)
		{
			appliedTier = -1;
			object obj = ReflectionUtils.TryGetListItem(slotsList, index);
			if (obj == null)
			{
				return false;
			}
			object obj2 = ReflectionUtils.TryGetFieldOrProperty(obj, "ItemInstance");
			if (obj2 == null)
			{
				return false;
			}
			object obj3 = ReflectionUtils.TryGetFieldOrProperty(obj2, "Definition");
			if (obj3 == null)
			{
				return false;
			}
			object obj4 = ReflectionUtils.TryGetFieldOrProperty(obj3, "ID") ?? ReflectionUtils.TryGetFieldOrProperty(obj3, "id");
			string text = (obj4 as string) ?? obj4?.ToString();
			if (string.IsNullOrEmpty(text) || !text.StartsWith("PackRat_Backpack_Tier_", StringComparison.Ordinal))
			{
				return false;
			}
			if (!BackpackShopIntegration.IsBackpackTierPurchase(text, out var tierIndex) || tierIndex < 0)
			{
				return false;
			}
			ClearSlotItem(obj);
			RefreshInventoryUIAfterSlotChange(playerInventory, obj);
			if (tierIndex > _highestPurchasedTierIndex)
			{
				SetHighestPurchasedTierIndex(tierIndex);
				ApplyTierAfterPurchase(tierIndex);
				for (int i = 0; i <= tierIndex; i++)
				{
					BackpackShopIntegration.RemoveTierListingFromAllShops(i);
				}
				appliedTier = tierIndex;
			}
			return true;
		}

		private static int GetSelectedHotbarIndex(object playerInventory)
		{
			if (playerInventory == null)
			{
				return -1;
			}
			string[] array = new string[16]
			{
				"selectedSlotIndex", "SelectedSlotIndex", "selectedIndex", "SelectedIndex", "currentSlotIndex", "CurrentSlotIndex", "activeSlotIndex", "ActiveSlotIndex", "activeIndex", "ActiveIndex",
				"equippedSlotIndex", "EquippedSlotIndex", "SelectedSlot", "selectedSlot", "slotIndex", "SlotIndex"
			};
			foreach (string memberName in array)
			{
				object obj = ReflectionUtils.TryGetFieldOrProperty(playerInventory, memberName);
				if (obj != null)
				{
					if (obj is int num && num >= 0)
					{
						return num;
					}
					if (obj is byte result)
					{
						return result;
					}
					if (obj is short num2 && num2 >= 0)
					{
						return num2;
					}
					if (obj is long num3 && num3 >= 0 && num3 <= int.MaxValue)
					{
						return (int)num3;
					}
				}
			}
			return -1;
		}

		private static void ClearSlotItem(object slot)
		{
			if (slot == null || ReflectionUtils.TrySetFieldOrProperty(slot, "ItemInstance", null))
			{
				return;
			}
			Type type = slot.GetType();
			MethodInfo methodInfo = type.GetMethod("Clear", Type.EmptyTypes) ?? type.GetMethod("ClearSlot", Type.EmptyTypes);
			if (!(methodInfo != null))
			{
				return;
			}
			try
			{
				methodInfo.Invoke(slot, null);
			}
			catch
			{
			}
		}

		private static void RefreshInventoryUIAfterSlotChange(object playerInventory, object slotThatChanged)
		{
			if (slotThatChanged != null)
			{
				ReflectionUtils.TryInvokeParameterlessCallback(slotThatChanged, "onItemDataChanged", "OnItemDataChanged", "ItemDataChanged");
			}
			if (playerInventory != null)
			{
				ReflectionUtils.TryInvokeParameterlessCallback(playerInventory, "Refresh", "RefreshUI", "UpdateDisplay", "OnInventoryChanged", "NotifySlotsChanged", "Rebuild");
			}
		}

		private void ApplyCurrentTier(int tierIdx)
		{
			if (tierIdx >= 0)
			{
				int num = Configuration.Instance.TierSlotCounts[tierIdx];
				if (_storage.SlotCount != num)
				{
					ModLogger.Info($"Backpack upgraded to {Configuration.BackpackTiers[tierIdx].Name} ({num} slots).");
					UpdateSize(num);
				}
			}
		}

		public void ApplyTierAfterPurchase(int tierIdx)
		{
			if (tierIdx >= 0)
			{
				_lastTierIndex = tierIdx;
				ApplyCurrentTier(tierIdx);
			}
		}

		public void SetBackpackEnabled(bool state)
		{
			if (!state)
			{
				Close();
			}
			_backpackEnabled = state;
		}

		public void Open()
		{
			if (!_backpackEnabled)
			{
				ModLogger.Debug("Backpack open blocked: backpack disabled.");
			}
			else if (!IsUnlocked)
			{
				ModLogger.Debug($"Backpack open blocked: not unlocked (CurrentTierIndex={CurrentTierIndex}, HighestPurchased={_highestPurchasedTierIndex}). Purchase a tier at the Hardware Store.");
			}
			else if ((Object)(object)_storage == (Object)null)
			{
				ModLogger.Warn("Backpack open blocked: no storage entity.");
			}
			else if (!Singleton<ManagementClipboard>.Instance.IsEquipped && !Singleton<StorageMenu>.Instance.IsOpen && !PlayerSingleton<Phone>.Instance.IsOpen)
			{
				if (CameraLockedStateHelper.IsCameraLockedByUI())
				{
					ModLogger.Debug("Backpack blocked: player is in camera-locked UI (TV, ATM, dialogue, vehicle, etc.).");
					return;
				}
				_openTitle = CurrentTier?.Name ?? "Backpack";
				StorageMenu instance = Singleton<StorageMenu>.Instance;
				instance.SlotGridLayout.constraintCount = _storage.DisplayRowCount;
				instance.Open(_openTitle, string.Empty, ((Il2CppObjectBase)_storage).Cast<IItemSlotOwner>());
				_storage.SendAccessor(((NetworkBehaviour)Player.Local).NetworkObject);
			}
		}

		public void Close()
		{
			if (_backpackEnabled && IsOpen)
			{
				Singleton<StorageMenu>.Instance.CloseMenu();
				_storage.SendAccessor((NetworkObject)null);
			}
		}

		public bool ContainsItemsOfInterest(EStealthLevel maxStealthLevel)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Invalid comparison between Unknown and I4
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < _storage.ItemSlots.Count; i++)
			{
				List<ItemSlot> itemSlots = _storage.ItemSlots;
				ItemSlot val = ((Il2CppObjectBase)itemSlots[new Index(i).GetOffset(itemSlots.Count)]).Cast<ItemSlot>();
				if (((val != null) ? val.ItemInstance : null) == null)
				{
					continue;
				}
				ProductItemInstance val2 = ((Il2CppObjectBase)val.ItemInstance).TryCast<ProductItemInstance>();
				if (val2 == null)
				{
					if ((int)val.ItemInstance.Definition.legalStatus > 0)
					{
						return true;
					}
				}
				else if ((Object)(object)val2.AppliedPackaging == (Object)null || val2.AppliedPackaging.StealthLevel <= maxStealthLevel)
				{
					return true;
				}
			}
			return false;
		}

		public void Upgrade(int slotCount)
		{
			if ((slotCount >= 1 && slotCount <= 40) || 1 == 0)
			{
				int num = _storage.SlotCount + slotCount;
				if (num > 40)
				{
					ModLogger.Warn($"Cannot upgrade backpack to more than {40} slots.");
				}
				else
				{
					UpdateSize(num);
				}
			}
		}

		public void Downgrade(int slotCount, bool force = false)
		{
			if (slotCount < 1)
			{
				return;
			}
			if (!force && slotCount >= _storage.SlotCount)
			{
				ModLogger.Warn("Cannot downgrade backpack to zero slots. A minimum of one must remain.");
				return;
			}
			int num = _storage.SlotCount - slotCount;
			if (num < 1)
			{
				num = 1;
			}
			if (force)
			{
				UpdateSize(num);
				return;
			}
			bool flag = true;
			List<ItemSlot> range = _storage.ItemSlots.GetRange(num, _storage.SlotCount - num);
			for (int i = 0; i < range.Count; i++)
			{
				List<ItemSlot> val = range;
				ItemSlot val2 = ((Il2CppObjectBase)val[new Index(i).GetOffset(val.Count)]).Cast<ItemSlot>();
				if (((val2 != null) ? val2.ItemInstance : null) != null)
				{
					ModLogger.Warn("Downgrading backpack will remove item: " + ((Object)val2.ItemInstance.Definition).name);
					flag = false;
				}
			}
			if (!flag)
			{
				ModLogger.Warn("Cannot downgrade backpack due to items present in removed slots.");
			}
			else
			{
				UpdateSize(num);
			}
		}

		private void UpdateSize(int newSize)
		{
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Expected O, but got Unknown
			_storage.SlotCount = newSize;
			StorageEntity storage = _storage;
			if (1 == 0)
			{
			}
			int displayRowCount = ((newSize <= 20) ? ((int)Math.Ceiling((double)newSize / 5.0)) : ((newSize > 80) ? ((int)Math.Ceiling((double)newSize / 16.0)) : ((int)Math.Ceiling((double)newSize / 10.0))));
			if (1 == 0)
			{
			}
			storage.DisplayRowCount = displayRowCount;
			if (_storage.ItemSlots.Count > newSize)
			{
				_storage.ItemSlots.RemoveRange(newSize, _storage.ItemSlots.Count - newSize);
				return;
			}
			for (int i = _storage.ItemSlots.Count; i < newSize; i++)
			{
				ItemSlot val = new ItemSlot();
				if ((Delegate)(object)val.onItemDataChanged == (Delegate)null)
				{
					val.onItemDataChanged = Action.op_Implicit((Action)_storage.ContentsChanged);
				}
				else
				{
					((Delegate)val.onItemDataChanged).CombineImpl((Delegate)(object)Action.op_Implicit((Action)_storage.ContentsChanged));
				}
				val.SetSlotOwner(((Il2CppObjectBase)_storage).Cast<IItemSlotOwner>());
			}
		}

		private void OnStartClient(bool isOwner)
		{
			if (!isOwner)
			{
				ModLogger.Info("Destroying non-local player backpack on: " + ((Object)this).name);
				Object.Destroy((Object)(object)this);
			}
			else if ((Object)(object)Instance != (Object)null)
			{
				ModLogger.Warn("Multiple instances of " + ((Object)this).name + " exist. Keeping prior instance reference.");
			}
			else
			{
				Instance = this;
				CameraLockedStateHelper.PrewarmCache();
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}
	}
}
namespace PackRat.Storage
{
	public sealed class BackpackSaveData
	{
		public string Contents { get; set; }

		public int HighestPurchasedTierIndex { get; set; } = -1;

	}
}
namespace PackRat.Shops
{
	public static class BackpackShopIntegration
	{
		[CompilerGenerated]
		private sealed class <WaitAndIntegrate>d__6 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			private int <i>5__1;

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

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

			[DebuggerHidden]
			public <WaitAndIntegrate>d__6(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

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

			private bool MoveNext()
			{
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				//IL_003a: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<i>5__1 = 0;
					break;
				case 1:
					<>1__state = -1;
					AddToAllHardwareStoresInScene();
					<i>5__1++;
					break;
				}
				if (<i>5__1 < 60)
				{
					<>2__current = (object)new WaitForSeconds(0.5f);
					<>1__state = 1;
					return true;
				}
				if (_shopsIntegrated.Count == 0)
				{
					LogHardwareStoreNotFound();
				}
				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();
			}
		}

		public const string BackpackItemIdPrefix = "PackRat_Backpack_Tier_";

		private const string HardwareStoreName = "Hardware Store";

		private static readonly string[] TierDescriptions = new string[5] { "A basic 8-slot backpack. Good for starting out.", "A compact 16-slot pack. Stays under the radar.", "24 slots. Police may search this size and above.", "32 slots. Sturdy and roomy; draws more attention.", "The largest option with 40 slots. Maximum capacity." };

		private static readonly HashSet<int> _shopsIntegrated = new HashSet<int>();

		public static void RunWhenReady()
		{
			MelonCoroutines.Start(WaitAndIntegrate());
		}

		public static bool TryAddBackpackListingsToShop(ShopInterface shop)
		{
			if ((Object)(object)shop == (Object)null)
			{
				return false;
			}
			if (!TryMatchHardwareStore(shop, out var _))
			{
				return false;
			}
			int instanceID = ((Object)shop).GetInstanceID();
			if (_shopsIntegrated.Contains(instanceID))
			{
				return true;
			}
			if (AddBackpackListings(shop))
			{
				_shopsIntegrated.Add(instanceID);
				ModLogger.Info($"BackpackShopIntegration: Added backpack tier listings to Hardware Store (instance {instanceID}).");
				return true;
			}
			ModLogger.Warn("BackpackShopIntegration: Hardware Store found but adding listings failed (see tier warnings above).");
			return false;
		}

		[IteratorStateMachine(typeof(<WaitAndIntegrate>d__6))]
		private static IEnumerator WaitAndIntegrate()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitAndIntegrate>d__6(0);
		}

		private static void AddToAllHardwareStoresInScene()
		{
			try
			{
				Type typeFromHandle = typeof(ShopInterface);
				FieldInfo field = typeFromHandle.GetField("AllShops", BindingFlags.Static | BindingFlags.Public);
				if (field != null && field.GetValue(null) is IEnumerable enumerable)
				{
					foreach (object item in enumerable)
					{
						if (item != null && TryMatchHardwareStore(item, out var shop))
						{
							TryAddBackpackListingsToShop(shop);
						}
					}
				}
				ShopInterface[] array = Utils.FindObjectsOfTypeSafe<ShopInterface>();
				if (array == null)
				{
					return;
				}
				for (int i = 0; i < array.Length; i++)
				{
					if ((Object)(object)array[i] != (Object)null && TryMatchHardwareStore(array[i], out var shop2))
					{
						TryAddBackpackListingsToShop(shop2);
					}
				}
			}
			catch (Exception exception)
			{
				ModLogger.Error("BackpackShopIntegration: AddToAllHardwareStoresInScene", exception);
			}
		}

		private static void LogHardwareStoreNotFound()
		{
			List<string> list = new List<string>();
			try
			{
				Type typeFromHandle = typeof(ShopInterface);
				FieldInfo field = typeFromHandle.GetField("AllShops", BindingFlags.Static | BindingFlags.Public);
				if (field != null)
				{
					object value = field.GetValue(null);
					if (value != null && value is IEnumerable enumerable)
					{
						foreach (object item in enumerable)
						{
							if (item != null)
							{
								string shopDisplayName = GetShopDisplayName(item);
								if (!string.IsNullOrEmpty(shopDisplayName) && !list.Contains(shopDisplayName))
								{
									list.Add(shopDisplayName);
								}
							}
						}
					}
				}
				if (list.Count == 0)
				{
					ShopInterface[] array = Utils.FindObjectsOfTypeSafe<ShopInterface>();
					if (array != null)
					{
						for (int i = 0; i < array.Length; i++)
						{
							string shopDisplayName2 = GetShopDisplayName(array[i]);
							if (!string.IsNullOrEmpty(shopDisplayName2) && !list.Contains(shopDisplayName2))
							{
								list.Add(shopDisplayName2);
							}
						}
					}
				}
			}
			catch
			{
			}
			if (list.Count > 0)
			{
				ModLogger.Warn("BackpackShopIntegration: Hardware Store not found after 30s. Shop names in game: [" + string.Join(", ", list) + "]. If your hardware store uses a different name, we can add a match for it.");
			}
			else
			{
				ModLogger.Warn("BackpackShopIntegration: Hardware Store not found after 30s (no ShopInterface instances with a name found). Shops may load later when you open them.");
			}
		}

		private static bool TryGetHardwareStore(out ShopInterface shop)
		{
			shop = null;
			try
			{
				Type typeFromHandle = typeof(ShopInterface);
				FieldInfo field = typeFromHandle.GetField("AllShops", BindingFlags.Static | BindingFlags.Public);
				if (field != null)
				{
					object value = field.GetValue(null);
					if (value != null && value is IEnumerable enumerable)
					{
						int num = 0;
						foreach (object item in enumerable)
						{
							if (item != null)
							{
								num++;
								if (TryMatchHardwareStore(item, out shop))
								{
									return true;
								}
							}
						}
					}
				}
				ShopInterface[] array = Utils.FindObjectsOfTypeSafe<ShopInterface>();
				if (array != null && array.Length != 0)
				{
					foreach (ShopInterface val in array)
					{
						if (!((Object)(object)val == (Object)null) && TryMatchHardwareStore(val, out shop))
						{
							return true;
						}
					}
				}
			}
			catch (Exception exception)
			{
				ModLogger.Error("BackpackShopIntegration: Error finding Hardware Store", exception);
			}
			return false;
		}

		private static bool TryMatchHardwareStore(object shopObj, out ShopInterface shop)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			shop = null;
			if (shopObj == null)
			{
				return false;
			}
			string shopDisplayName = GetShopDisplayName(shopObj);
			if (string.IsNullOrEmpty(shopDisplayName))
			{
				return false;
			}
			if (!string.Equals(shopDisplayName, "Hardware Store", StringComparison.OrdinalIgnoreCase) && shopDisplayName.IndexOf("Hardware", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return false;
			}
			try
			{
				shop = (ShopInterface)shopObj;
				return true;
			}
			catch
			{
				return false;
			}
		}

		private static string GetShopDisplayName(object shopObj)
		{
			if (shopObj == null)
			{
				return null;
			}
			string[] array = new string[5] { "ShopName", "shopName", "Name", "name", "DisplayName" };
			foreach (string memberName in array)
			{
				object obj = ReflectionUtils.TryGetFieldOrProperty(shopObj, memberName);
				if (obj is string text && !string.IsNullOrWhiteSpace(text))
				{
					return text.Trim();
				}
			}
			return null;
		}

		private static bool AddBackpackListings(ShopInterface shop)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			//IL_0062: 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_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)shop == (Object)null)
			{
				return false;
			}
			if (shop.Listings == null)
			{
				ModLogger.Warn("BackpackShopIntegration: Shop.Listings is null; cannot add backpack listings.");
				return false;
			}
			Configuration instance = Configuration.Instance;
			if (!LevelManagerPatch.TryGetFallbackIcon(out var texture, out var sprite))
			{
				texture = new Texture2D(2, 2);
				texture.SetPixel(0, 0, Color.white);
				texture.SetPixel(1, 0, Color.white);
				texture.SetPixel(0, 1, Color.white);
				texture.SetPixel(1, 1, Color.white);
				texture.Apply();
				sprite = Sprite.Create(texture, new Rect(0f, 0f, 2f, 2f), new Vector2(0.5f, 0.5f));
				ModLogger.Warn("BackpackShopIntegration: Fallback icon resource missing; using generated placeholder icon.");
			}
			int num = (((Object)(object)PlayerBackpack.Instance != (Object)null) ? PlayerBackpack.Instance.HighestPurchasedTierIndex : (-1));
			bool flag = false;
			bool flag2 = false;
			bool flag3 = false;
			int num2 = 0;
			int num3 = 0;
			int num4 = 0;
			for (int i = 0; i < Configuration.BackpackTiers.Length; i++)
			{
				if (i <= num || !instance.TierEnabled[i])
				{
					continue;
				}
				flag2 = true;
				string itemId = "PackRat_Backpack_Tier_" + i;
				if (ShopHasItem(shop, itemId))
				{
					flag3 = true;
					continue;
				}
				Sprite tierSprite = LevelManagerPatch.GetTierSprite(i, sprite, texture);
				StorableItemDefinition val = CreateBackpackTierDefinition(shop, i, itemId, instance, tierSprite);
				if ((Object)(object)val == (Object)null)
				{
					num2++;
					ModLogger.Warn($"BackpackShopIntegration: Tier {i} definition creation returned null.");
				}
				else if (!RegisterDefinition(val))
				{
					num3++;
					ModLogger.Warn($"BackpackShopIntegration: Could not register definition for tier {i}.");
				}
				else if (!AddListingToShop(shop, val, sprite, texture))
				{
					num4++;
					ModLogger.Warn($"BackpackShopIntegration: Could not add listing for tier {i}.");
				}
				else
				{
					flag = true;
				}
			}
			if (flag)
			{
				ModLogger.Info("BackpackShopIntegration: Added backpack tier listings to Hardware Store.");
			}
			if (!flag2 || flag3 || flag)
			{
				return true;
			}
			ModLogger.Warn($"BackpackShopIntegration: Eligible tiers found but none added. missingDef={num2}, registerFailed={num3}, listingFailed={num4}");
			return false;
		}

		private static bool ShopHasItem(ShopInterface shop, string itemId)
		{
			try
			{
				if (shop.Listings == null)
				{
					return false;
				}
				Enumerator<ShopListing> enumerator = shop.Listings.GetEnumerator();
				while (enumerator.MoveNext())
				{
					ShopListing current = enumerator.Current;
					if ((Object)(object)((current != null) ? current.Item : null) != (Object)null && ((ItemDefinition)current.Item).ID == itemId)
					{
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		private static StorableItemDefinition CreateBackpackTierDefinition(ShopInterface shop, int tierIndex, string itemId, Configuration cfg, Sprite iconSprite)
		{
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				ScriptableObject val = ScriptableObject.CreateInstance("ScheduleOne.ItemFramework.StorableItemDefinition") ?? ScriptableObject.CreateInstance("Il2CppScheduleOne.ItemFramework.StorableItemDefinition") ?? ScriptableObject.CreateInstance("StorableItemDefinition");
				StorableItemDefinition val2 = ((val != null) ? ((Il2CppObjectBase)val).TryCast<StorableItemDefinition>() : null);
				if ((Object)(object)val2 == (Object)null)
				{
					val2 = CloneTemplateStorableItemDefinition(shop);
				}
				if ((Object)(object)val2 == (Object)null)
				{
					ModLogger.Warn("BackpackShopIntegration: Could not create StorableItemDefinition instance in IL2CPP.");
				}
				if ((Object)(object)val2 == (Object)null)
				{
					return null;
				}
				if (!ReflectionUtils.TrySetFieldOrProperty(val2, "ID", itemId))
				{
					ReflectionUtils.TrySetFieldOrProperty(val2, "id", itemId);
				}
				string name = Configuration.BackpackTiers[tierIndex].Name;
				if (!ReflectionUtils.TrySetFieldOrProperty(val2, "Name", name))
				{
					ReflectionUtils.TrySetFieldOrProperty(val2, "name", name);
				}
				if ((Object)(object)iconSprite != (Object)null)
				{
					string[] array = new string[7] { "Icon", "icon", "Sprite", "sprite", "ItemIcon", "itemIcon", "DisplayIcon" };
					foreach (string memberName in array)
					{
						if (ReflectionUtils.TrySetFieldOrProperty(val2, memberName, iconSprite))
						{
							break;
						}
					}
				}
				float num = ((tierIndex < cfg.TierPrices.Length) ? cfg.TierPrices[tierIndex] : (25f + (float)tierIndex * 50f));
				ReflectionUtils.TrySetFieldOrProperty(val2, "BasePurchasePrice", num);
				FullRank val3 = ((tierIndex < cfg.TierUnlockRanks.Length) ? cfg.TierUnlockRanks[tierIndex] : Configuration.BackpackTiers[tierIndex].DefaultUnlockRank);
				ReflectionUtils.TrySetFieldOrProperty(val2, "RequiredRank", val3);
				ReflectionUtils.TrySetFieldOrProperty(val2, "RequiresLevelToPurchase", true);
				string value = ((tierIndex < TierDescriptions.Length) ? TierDescriptions[tierIndex] : null);
				if (!string.IsNullOrEmpty(value))
				{
					string[] array2 = new string[8] { "Description", "description", "TooltipText", "tooltipText", "FlavorText", "flavorText", "ItemDescription", "itemDescription" };
					foreach (string memberName2 in array2)
					{
						if (ReflectionUtils.TrySetFieldOrProperty(val2, memberName2, value))
						{
							break;
						}
					}
				}
				return val2;
			}
			catch (Exception exception)
			{
				ModLogger.Error($"BackpackShopIntegration: CreateBackpackTierDefinition tier {tierIndex}", exception);
				return null;
			}
		}

		private static StorableItemDefinition CloneTemplateStorableItemDefinition(ShopInterface shop)
		{
			if (((shop != null) ? shop.Listings : null) == null)
			{
				return null;
			}
			try
			{
				Enumerator<ShopListing> enumerator = shop.Listings.GetEnumerator();
				while (enumerator.MoveNext())
				{
					ShopListing current = enumerator.Current;
					if ((Object)(object)((current != null) ? current.Item : null) == (Object)null || !Utils.Is<StorableItemDefinition>((object)current.Item, out StorableItemDefinition result) || (Object)(object)result == (Object)null)
					{
						continue;
					}
					StorableItemDefinition val = Object.Instantiate<StorableItemDefinition>(result);
					return (val != null) ? ((Il2CppObjectBase)val).TryCast<StorableItemDefinition>() : null;
				}
			}
			catch (Exception exception)
			{
				ModLogger.Error("BackpackShopIntegration: CloneTemplateStorableItemDefinition", exception);
			}
			return null;
		}

		private static bool RegisterDefinition(StorableItemDefinition def)
		{
			try
			{
				Registry instance = Singleton<Registry>.Instance;
				if ((Object)(object)instance == (Object)null)
				{
					return false;
				}
				instance.AddToRegistry((ItemDefinition)(object)def);
				return true;
			}
			catch (Exception exception)
			{
				ModLogger.Error("BackpackShopIntegration: RegisterDefinition", exception);
				return false;
			}
		}

		private static bool AddListingToShop(ShopInterface shop, StorableItemDefinition def, Sprite fallbackSprite, Texture2D fallbackTexture)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			try
			{
				ShopListing val = new ShopListing
				{
					Item = def,
					name = ((ItemDefinition)def).Name
				};
				shop.Listings.Add(val);
				val.Initialize(shop);
				if (!TryInvokeShopMethod(shop, "CreateListingUI", val))
				{
					Sprite tierSprite = LevelManagerPatch.GetTierSprite(ParseTierFromItemId(((ItemDefinition)def).ID), fallbackSprite, fallbackTexture);
					CreateListingUI(shop, val, tierSprite);
				}
				TryInvokeShopMethod(shop, "RefreshUnlockStatus");
				TryInvokeShopMethod(shop, "RefreshShownItems");
				return true;
			}
			catch (Exception exception)
			{
				ModLogger.Error("BackpackShopIntegration: AddListingToShop", exception);
				return false;
			}
		}

		private static bool TryInvokeShopMethod(ShopInterface shop, string methodName, params object[] args)
		{
			try
			{
				if ((Object)(object)shop == (Object)null || string.IsNullOrEmpty(methodName))
				{
					return false;
				}
				BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
				MethodInfo[] methods = ((object)shop).GetType().GetMethods(bindingAttr);
				foreach (MethodInfo methodInfo in methods)
				{
					if (!(methodInfo == null) && string.Equals(methodInfo.Name, methodName, StringComparison.Ordinal))
					{
						ParameterInfo[] parameters = methodInfo.GetParameters();
						if (((args != null) ? args.Length : 0) == parameters.Length)
						{
							methodInfo.Invoke(shop, args);
							return true;
						}
					}
				}
			}
			catch (Exception ex)
			{
				ModLogger.Debug("BackpackShopIntegration: " + methodName + " invoke failed: " + ex.Message);
			}
			return false;
		}

		private static int ParseTierFromItemId(string itemId)
		{
			if (string.IsNullOrEmpty(itemId) || !itemId.StartsWith("PackRat_Backpack_Tier_", StringComparison.Ordinal))
			{
				return -1;
			}
			string s = itemId.Substring("PackRat_Backpack_Tier_".Length);
			int result;
			return int.TryParse(s, out result) ? result : (-1);
		}

		private static void CreateListingUI(ShopInterface shop, ShopListing listing, Sprite iconSprite)
		{
			try
			{
				object obj = ReflectionUtils.TryGetFieldOrProperty(shop, "ListingUIPrefab");
				object obj2 = ReflectionUtils.TryGetFieldOrProperty(shop, "ListingContainer");
				if (obj == null || obj2 == null)
				{
					ModLogger.Warn("BackpackShopIntegration: Shop missing ListingUIPrefab or ListingContainer.");
					return;
				}
				object obj3 = ((obj is Component) ? obj : null);
				GameObject val = ((obj3 != null) ? ((Component)obj3).gameObject : null);
				Transform val2 = (Transform)((obj2 is Transform) ? obj2 : null);
				if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
				{
					return;
				}
				GameObject val3 = Object.Instantiate<GameObject>(val, val2);
				ListingUI component = val3.GetComponent<ListingUI>();
				if ((Object)(object)component == (Object)null)
				{
					Object.Destroy((Object)(object)val3);
					return;
				}
				component.Initialize(listing);
				if ((Object)(object)iconSprite != (Object)null && (Object)(object)component.Icon != (Object)null)
				{
					component.Icon.sprite = iconSprite;
				}
				BindListingUIEvents(shop, component);
				AddToListingUICollection(shop, component);
			}
			catch (Exception exception)
			{
				ModLogger.Error("BackpackShopIntegration: CreateListingUI", exception);
			}
		}

		private static void BindListingUIEvents(ShopInterface shop, ListingUI listingUI)
		{
			try
			{
				listingUI.onClicked = Action.op_Implicit((Action)delegate
				{
					shop.ListingClicked(listingUI);
				});
				listingUI.onDropdownClicked = Action.op_Implicit((Action)delegate
				{
					shop.DropdownClicked(listingUI);
				});
				listingUI.hoverStart = Action.op_Implicit((Action)delegate
				{
					shop.EntryHovered(listingUI);
				});
				listingUI.hoverEnd = Action.op_Implicit((Action)delegate
				{
					shop.EntryUnhovered();
				});
			}
			catch (Exception exception)
			{
				ModLogger.Error("BackpackShopIntegration: BindListingUIEvents", exception);
			}
		}

		private static void AddToListingUICollection(ShopInterface shop, ListingUI listingUI)
		{
			try
			{
				FieldInfo field = typeof(ShopInterface).GetField("listingUI", BindingFlags.Instance | BindingFlags.NonPublic);
				if (!(field == null))
				{
					object value = field.GetValue(shop);
					if (value != null && value is List<ListingUI> val)
					{
						val.Add(listingUI);
					}
				}
			}
			catch (Exception exception)
			{
				ModLogger.Error("BackpackShopIntegration: AddToListingUICollection", exception);
			}
		}

		public static bool IsBackpackTierPurchase(string itemId, out int tierIndex)
		{
			tierIndex = ParseTierFromItemId(itemId ?? "");
			return tierIndex >= 0;
		}

		public static void RemoveTierListingFromAllShops(int tierIndex)
		{
			if (tierIndex < 0 || tierIndex >= Configuration.BackpackTiers.Length)
			{
				return;
			}
			string itemId = "PackRat_Backpack_Tier_" + tierIndex;
			List<int> list = new List<int>(_shopsIntegrated);
			foreach (int item in list)
			{
				ShopInterface val = FindShopByInstanceId(item);
				if ((Object)(object)val != (Object)null)
				{
					RemoveTierListingFromShop(val, itemId);
				}
			}
		}

		private static ShopInterface FindShopByInstanceId(int instanceId)
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			try
			{
				Type typeFromHandle = typeof(ShopInterface);
				FieldInfo field = typeFromHandle.GetField("AllShops", BindingFlags.Static | BindingFlags.Public);
				if (field != null && field.GetValue(null) is IEnumerable enumerable)
				{
					foreach (object item in enumerable)
					{
						if (item != null)
						{
							object obj = ((item is Object) ? item : null);
							if (obj != null && ((Object)obj).GetInstanceID() == instanceId)
							{
								return (ShopInterface)item;
							}
						}
					}
				}
				ShopInterface[] array = Utils.FindObjectsOfTypeSafe<ShopInterface>();
				if (array != null)
				{
					for (int i = 0; i < array.Length; i++)
					{
						if ((Object)(object)array[i] != (Object)null && ((Object)array[i]).GetInstanceID() == instanceId)
						{
							return array[i];
						}
					}
				}
			}
			catch (Exception exception)
			{
				ModLogger.Error("BackpackShopIntegration: FindShopByInstanceId", exception);
			}
			return null;
		}

		private static void RemoveTierListingFromShop(ShopInterface shop, string itemId)
		{
			if (((shop != null) ? shop.Listings : null) == null)
			{
				return;
			}
			try
			{
				object obj = null;
				Enumerator<ShopListing> enumerator = shop.Listings.GetEnumerator();
				while (enumerator.MoveNext())
				{
					ShopListing current = enumerator.Current;
					if ((Object)(object)((current != null) ? current.Item : null) != (Object)null && ((ItemDefinition)current.Item).ID == itemId)
					{
						obj = current;
						break;
					}
				}
				if (obj != null)
				{
					RemoveListingFromList(shop.Listings, obj);
					RemoveAndDestroyListingUI(shop, obj);
				}
			}
			catch (Exception exception)
			{
				ModLogger.Error("BackpackShopIntegration: RemoveTierListingFromShop", exception);
			}
		}

		private static int GetListCount(object list)
		{
			if (list == null)
			{
				return 0;
			}
			object obj = ReflectionUtils.TryGetFieldOrProperty(list, "Count") ?? ReflectionUtils.TryGetFieldOrProperty(list, "count");
			if (obj is int result)
			{
				return result;
			}
			if (obj is long num)
			{
				return (int)num;
			}
			return 0;
		}

		private static void RemoveListingFromList(object list, object listing)
		{
			if (list == null || listing == null)
			{
				return;
			}
			try
			{
				IList val = (IList)((list is IList) ? list : null);
				if (val == null)
				{
					return;
				}
				int listCount = GetListCount(val);
				for (int i = 0; i < listCount; i++)
				{
					Object val2 = val[i];
					if (val2 != null && (((object)val2).Equals(listing) || val2 == listing))
					{
						val.RemoveAt(i);
						break;
					}
				}
			}
			catch (Exception exception)
			{
				ModLogger.Error("BackpackShopIntegration: RemoveListingFromList", exception);
			}
		}

		private static void RemoveAndDestroyListingUI(ShopInterface shop, object listing)
		{
			if ((Object)(object)shop == (Object)null || listing == null)
			{
				return;
			}
			try
			{
				object obj = typeof(ShopInterface).GetField("listingUI", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(shop);
				if (obj == null)
				{
					return;
				}
				object obj2 = ReflectionUtils.TryGetFieldOrProperty(obj, "Count") ?? ReflectionUtils.TryGetFieldOrProperty(obj, "count");
				int num2 = ((obj2 is int num) ? num : 0);
				if (obj2 is long num3)
				{
					num2 = (int)num3;
				}
				for (int num4 = num2 - 1; num4 >= 0; num4--)
				{
					object obj3 = (obj.GetType().GetMethod("get_Item", new Type[1] { typeof(int) }) ?? obj.GetType().GetMethod("Get", new Type[1] { typeof(int) }))?.Invoke(obj, new object[1] { num4 });
					if (obj3 != null)
					{
						object obj4 = ReflectionUtils.TryGetFieldOrProperty(obj3, "Listing") ?? ReflectionUtils.TryGetFieldOrProperty(obj3, "listing");
						if (obj4 == listing)
						{
							object obj5 = ((obj3 is Component) ? obj3 : null);
							GameObject val = ((obj5 != null) ? ((Component)obj5).gameObject : null);
							if ((Object)(object)val != (Object)null)
							{
								Object.Destroy((Object)(object)val);
							}
							IList val2 = (IList)((obj is IList) ? obj : null);
							if (val2 != null)
							{
								val2.RemoveAt(num4);
							}
							break;
						}
					}
				}
			}
			catch (Exception exception)
			{
				ModLogger.Error("BackpackShopIntegration: RemoveAndDestroyListingUI", exception);
			}
		}
	}
}
namespace PackRat.Patches
{
	[HarmonyPatch(typeof(ShopInterface))]
	public static class BackpackPurchasePatch
	{
		[HarmonyPatch("ListingClicked", new Type[] { typeof(ListingUI) })]
		[HarmonyPrefix]
		public static bool ListingClicked_Prefix(ShopInterface __instance, ListingUI listingUI)
		{
			try
			{
				if ((Object)(object)listingUI == (Object)null)
				{
					return true;
				}
				object obj = ReflectionUtils.TryGetFieldOrProperty(listingUI, "Listing") ?? ReflectionUtils.TryGetFieldOrProperty(listingUI, "listing");
				if (obj == null)
				{
					return true;
				}
				object obj2 = ReflectionUtils.TryGetFieldOrProperty(obj, "Item");
				StorableItemDefinition val = (StorableItemDefinition)((obj2 is StorableItemDefinition) ? obj2 : null);
				if (val == null || ((ItemDefinition)val).ID == null || !((ItemDefinition)val).ID.StartsWith("PackRat_Backpack_Tier_", StringComparison.Ordinal))
				{
					return true;
				}
				return true;
			}
			catch (Exception exception)
			{
				ModLogger.Error("BackpackPurchasePatch: ListingClicked prefix error", exception);
				return true;
			}
		}
	}
	[HarmonyPatch(typeof(BodySearchBehaviour))]
	public static class BodySearchBehaviourPatch
	{
		[CompilerGenerated]
		private sealed class <CheckForItems>d__1 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public BodySearchBehaviour behaviour;

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

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

			[DebuggerHidden]
			public <CheckForItems>d__1(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

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

			private bool MoveNext()
			{
				//IL_0046: Unknown result type (might be due to invalid IL or missing references)
				//IL_0050: Expected O, but got Unknown
				//IL_007d: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					((NPC)behaviour.officer).DialogueHandler.ShowWorldspaceDialogue("Hold on, let me see your backpack as well.", 5f);
					<>2__current = (object)new WaitForSeconds(3f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					Singleton<BodySearchScreen>.Instance.IsOpen = false;
					behaviour.ConcludeSearch(!PlayerBackpack.Instance.ContainsItemsOfInterest(behaviour.MaxStealthLevel));
					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();
			}
		}

		[HarmonyPatch("SearchClean")]
		[HarmonyPrefix]
		public static bool SearchClean(BodySearchBehaviour __instance)
		{
			if (!PlayerBackpack.Instance.IsUnlocked || !PlayerBackpack.Instance.IsPoliceSearchable)
			{
				return true;
			}
			Singleton<BodySearchScreen>.Instance.onSearchClear.RemoveListener(UnityAction.op_Implicit((Action)__instance.SearchClean));
			Singleton<BodySearchScreen>.Instance.onSearchFail.RemoveListener(UnityAction.op_Implicit((Action)__instance.SearchFail));
			Singleton<BodySearchScreen>.Instance.IsOpen = true;
			MelonCoroutines.Start(CheckForItems(__instance));
			return false;
		}

		[IteratorStateMachine(typeof(<CheckForItems>d__1))]
		private static IEnumerator CheckForItems(BodySearchBehaviour behaviour)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <CheckForItems>d__1(0)
			{
				behaviour = behaviour
			};
		}
	}
	[HarmonyPatch(typeof(Cart))]
	public static class CartPatch
	{
		[HarmonyPatch("GetWarning")]
		[HarmonyPostfix]
		public static void GetWarning(Cart __instance, ref bool __result, ref string warning)
		{
			if (PlayerBackpack.Instance.IsUnlocked && !warning.StartsWith("Vehicle") && __result)
			{
				List<ItemSlot> itemSlots = PlayerBackpack.Instance.ItemSlots;
				itemSlots.InsertRange(0, ((Il2CppObjectBase)PlayerSingleton<PlayerInventory>.Instance.hotbarSlots).Cast<IEnumerable<ItemSlot>>());
				if (__instance.Shop.WillCartFit(itemSlots))
				{
					warning = "Inventory won't fit everything. Some items will be placed in your backpack.";
				}
			}
		}
	}
	[HarmonyPatch(typeof(LevelManager))]
	public static class LevelManagerPatch
	{
		[CompilerGenerated]
		private sealed class <ClientRegisterTimeout>d__9 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

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

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

			[DebuggerHidden]
			public <ClientRegisterTimeout>d__9(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

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

			private bool MoveNext()
			{
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(11f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					if (_clientRegistrationDone || (Object)(object)_pendingLevelManager == (Object)null)
					{
						return false;
					}
					ModLogger.Warn("Config sync from host did not arrive in time; registering backpack unlockables with local config.");
					RegisterBackpackUnlockables(_pendingLevelManager);
					_clientRegistrationDone = true;
					_pendingLevelManager = 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();
			}
		}

		private const string FallbackIconResourceName = "PackRat.assets.icon.png";

		private const string HardwareStoreSuffix = " (Hardware Store)";

		private static readonly string[] TierIconResourceNames = new string[5] { "PackRat.assets.rucksack.png", "PackRat.assets.smallpack.png", "PackRat.assets.duffelbag.png", "PackRat.assets.tacticalpack.png", "PackRat.assets.hikingbackpack.png" };

		private static LevelManager _pendingLevelManager;

		private static bool _clientRegistrationDone;

		private static bool _clientSubscribed;

		private static bool _resourceDiagnosticsLogged;

		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		public static void Awake(LevelManager __instance)
		{
			if ((Object)(object)__instance == (Object)null)
			{
				ModLogger.Error("LevelManager instance is null!");
			}
			else if ((Object)(object)Singleton<Lobby>.Instance != (Object)null && Singleton<Lobby>.Instance.IsInLobby && !Singleton<Lobby>.Instance.IsHost)
			{
				_pendingLevelManager = __instance;
				if (!_clientSubscribed)
				{
					_clientSubscribed = true;
					ConfigSyncManager.OnConfigSynced += OnClientConfigSynced;
				}
				MelonCoroutines.Start(ClientRegisterTimeout());
			}
			else
			{
				RegisterBackpackUnlockables(__instance);
			}
		}

		private static void OnClientConfigSynced()
		{
			if (!_clientRegistrationDone && !((Object)(object)_pendingLevelManager == (Object)null))
			{
				RegisterBackpackUnlockables(_pendingLevelManager);
				_clientRegistrationDone = true;
				_pendingLevelManager = null;
			}
		}

		[IteratorStateMachine(typeof(<ClientRegisterTimeout>d__9))]
		private static IEnumerator ClientRegisterTimeout()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ClientRegisterTimeout>d__9(0);
		}

		private static void RegisterBackpackUnlockables(LevelManager levelManager)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Expected O, but got Unknown
			if ((Object)(object)levelManager == (Object)null)
			{
				return;
			}
			if (!TryLoadTexture("PackRat.assets.icon.png", out var texture))
			{
				ModLogger.Error("Failed to load fallback backpack icon texture.");
				return;
			}
			Sprite fallbackSprite = Sprite.Create(texture, new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), new Vector2(0.5f, 0.5f));
			Configuration instance = Configuration.Instance;
			for (int i = 0; i < Configuration.BackpackTiers.Length; i++)
			{
				if (instance.TierEnabled[i])
				{
					BackpackTierDefinition backpackTierDefinition = Configuration.BackpackTiers[i];
					Sprite tierSprite = GetTierSprite(i, fallbackSprite, texture);
					string text = backpackTierDefinition.Name + " (Hardware Store)";
					Unlockable val = new Unlockable(instance.TierUnlockRanks[i], text, tierSprite);
					levelManager.AddUnlockable(val);
				}
			}
		}

		public static bool TryGetFallbackIcon(out Texture2D texture, out Sprite sprite)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			sprite = null;
			if (!TryLoadTexture("PackRat.assets.icon.png", out texture) || (Object)(object)texture == (Object)null)
			{
				return false;
			}
			sprite = Sprite.Create(texture, new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), new Vector2(0.5f, 0.5f));
			return true;
		}

		public static Sprite GetTierSprite(int tierIndex, Sprite fallbackSprite, Texture2D fallbackTexture)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			if (tierIndex < 0 || tierIndex >= TierIconResourceNames.Length)
			{
				return fallbackSprite;
			}
			if (!TryLoadTexture(TierIconResourceNames[tierIndex], out var texture))
			{
				return fallbackSprite;
			}
			return Sprite.Create(texture, new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), new Vector2(0.5f, 0.5f));
		}

		private static bool TryLoadTexture(string resourceName, out Texture2D texture)
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			texture = null;
			if (!TryGetResourceStream(resourceName, out var stream))
			{
				if (!_resourceDiagnosticsLogged)
				{
					_resourceDiagnosticsLogged = true;
					LogResourceDiagnostics();
				}
				ModLogger.Error("Failed to find embedded resource: " + resourceName);
				return false;
			}
			using (stream)
			{
				byte[] array = new byte[stream.Length];
				stream.Read(array, 0, array.Length);
				texture = new Texture2D(0, 0);
				((Texture)texture).filterMode = (FilterMode)0;
				ImageConversion.LoadImage(texture, Il2CppStructArray<byte>.op_Implicit(array));
				return true;
			}
		}

		private static bool TryGetResourceStream(string resourceName, out Stream stream)
		{
			stream = null;
			if (string.IsNullOrEmpty(resourceName))
			{
				return false;
			}
			Assembly assembly = typeof(PackRat).Assembly;
			stream = assembly.GetManifestResourceStream(resourceName);
			if (stream != null)
			{
				return true;
			}
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly2 in assemblies)
			{
				if (assembly2 == null)
				{
					continue;
				}
				try
				{
					string[] manifestResourceNames = assembly2.GetManifestResourceNames();
					foreach (string text in manifestResourceNames)
					{
						if (string.Equals(text, resourceName, StringComparison.Ordinal))
						{
							stream = assembly2.GetManifestResourceStream(text);
							if (stream != null)
							{
								ModLogger.Warn($"Resolved resource '{resourceName}' from assembly '{assembly2.GetName().Name}'.");
								return true;
							}
						}
					}
				}
				catch
				{
				}
			}
			return false;
		}

		private static void LogResourceDiagnostics()
		{
			try
			{
				Assembly assembly = typeof(PackRat).Assembly;
				string[] manifestResourceNames = assembly.GetManifestResourceNames();
				ModLogger.Warn($"PackRat assembly '{assembly.FullName}' resource count: {manifestResourceNames.Length}");
				for (int i = 0; i < manifestResourceNames.Length; i++)
				{
					ModLogger.Warn("PackRat resource: " + manifestResourceNames[i]);
				}
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly2 in assemblies)
				{
					if (assembly2 == null)
					{
						continue;
					}
					string[] manifestResourceNames2;
					try
					{
						manifestResourceNames2 = assembly2.GetManifestResourceNames();
					}
					catch
					{
						continue;
					}
					if (manifestResourceNames2 == null || manifestResourceNames2.Length == 0)
					{
						continue;
					}
					for (int k = 0; k < manifestResourceNames2.Length; k++)
					{
						if (manifestResourceNames2[k].IndexOf("PackRat.assets", StringComparison.OrdinalIgnoreCase) >= 0)
						{
							ModLogger.Warn($"Found candidate resource '{manifestResourceNames2[k]}' in assembly '{assembly2.GetName().Name}'.");
						}
					}
				}
			}
			catch (Exception exception)
			{
				ModLogger.Error("LevelManagerPatch: resource diagnostics failed", exception);
			}
		}
	}
	[HarmonyPatch(typeof(PlayerManager))]
	public static class PlayerManagerPatch
	{
		[HarmonyPatch("TryGetPlayerData")]
		[HarmonyPostfix]
		public static void TryGetPlayerData(PlayerManager __instance, PlayerData data, ref string inventoryString)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			if (data != null)
			{
				List<string> loadedPlayerDataPaths = __instance.loadedPlayerDataPaths;
				String val = String.op_Implicit(loadedPlayerDataPaths[new Index(__instance.loadedPlayerData.IndexOf(data)).GetOffset(loadedPlayerDataPaths.Count)]);
				PlayerLoader val2 = new PlayerLoader();
				string text = default(string);
				if (!((Loader)val2).TryLoadFile(String.op_Implicit(val), "Backpack", ref text))
				{
					ModLogger.Warn($"Failed to load player backpack data under: {val}");
				}
				else
				{
					inventoryString = inventoryString + "|||" + text;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Player))]
	public static class PlayerPatch
	{
		[HarmonyPatch("Awake")]
		[HarmonyPrefix]
		public static void Awake(Player __instance)
		{
			if (!__instance.LocalExtraFiles.Contains("Backpack"))
			{
				ModLogger.Info("Registering backpack save file for player.");
				__instance.LocalExtraFiles.Add("Backpack");
			}
		}

		[HarmonyPatch("WriteData")]
		[HarmonyPostfix]
		public static void WriteData(Player __instance, string parentFolderPath)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			StorageEntity backpackStorage = __instance.GetBackpackStorage();
			string jSON = new ItemSet(backpackStorage.ItemSlots).GetJSON();
			int tierIndex = -1;
			if (((NetworkBehaviour)__instance).IsOwner && (Object)(object)PlayerBackpack.Instance != (Object)null)
			{
				tierIndex = PlayerBackpack.Instance.HighestPurchasedTierIndex;
			}
			else
			{
				TryReadExistingTier(parentFolderPath, out tierIndex);
			}
			BackpackSaveData value = new BackpackSaveData
			{
				Contents = jSON,
				HighestPurchasedTierIndex = tierIndex
			};
			string text = JsonHelper.SerializeObject(value);
			((Il2CppObjectBase)__instance).Cast<ISaveable>().WriteSubfile(parentFolderPath, "Backpack", text);
		}

		private static void TryReadExistingTier(string parentFolderPath, out int tierIndex)
		{
			tierIndex = -1;
			try
			{
				string path = Path.Combine(parentFolderPath, "Backpack");
				if (File.Exists(path))
				{
					string json = File.ReadAllText(path);
					BackpackSaveData backpackSaveData = JsonHelper.DeserializeObject<BackpackSaveData>(json);
					if (backpackSaveData != null)
					{
						tierIndex = backpackSaveData.HighestPurchasedTierIndex;
					}
				}
			}
			catch
			{
			}
		}

		[HarmonyPatch("Load", new Type[]
		{
			typeof(PlayerData),
			typeof(string)
		})]
		[HarmonyPrefix]
		public static void Load(Player __instance, PlayerData data, string containerPath)
		{
			string text = default(string);
			if (!__instance.Loader.TryLoadFile(containerPath, "Backpack", ref text))
			{
				return;
			}
			ModLogger.Info("Loading local backpack data.");
			try
			{
				StorageEntity backpackStorage = __instance.GetBackpackStorage();
				string text2 = text;
				int highestPurchasedTierIndex = -1;
				BackpackSaveData backpackSaveData = JsonHelper.DeserializeObject<BackpackSaveData>(text);
				if (backpackSaveData != null && backpackSaveData.Contents != null)
				{
					text2 = backpackSaveData.Contents;
					highestPurchasedTierIndex = backpackSaveData.HighestPurchasedTierIndex;
				}
				DeserializedItemSet val = default(DeserializedItemSet);
				if (!ItemSet.TryDeserialize(text2, ref val))
				{
					ModLogger.Error("Failed to deserialize backpack data.");
					return;
				}
				val.LoadTo(backpackStorage.ItemSlots);
				if (((NetworkBehaviour)__instance).IsOwner && (Object)(object)PlayerBackpack.Instance != (Object)null)
				{
					PlayerBackpack.Instance.SetHighestPurchasedTierIndex(highestPurchasedTierIndex);
				}
			}
			catch (Exception exception)
			{
				ModLogger.Error("Error loading backpack data", exception);
			}
		}

		[HarmonyPatch("LoadInventory")]
		[HarmonyPrefix]
		public static void LoadInventory(Player __instance, ref string contentsString)
		{
			if (string.IsNullOrEmpty(contentsString))
			{
				return;
			}
			if (!((NetworkBehaviour)__instance).IsOwner)
			{
				ModLogger.Info("Not the owner, skipping network backpack data load.");
				return;
			}
			string[] array = contentsString.Split(new string[1] { "|||" }, StringSplitOptions.None);
			if (array.Length < 2)
			{
				return;
			}
			contentsString = array[0];
			string text = array[1];
			ModLogger.Info("Loading backpack data from network payload.");
			try
			{
				StorageEntity backpackStorage = __instance.GetBackpackStorage();
				string text2 = text;
				int highestPurchasedTierIndex = -1;
				BackpackSaveData backpackSaveData = JsonHelper.DeserializeObject<BackpackSaveData>(text);
				if (backpackSaveData != null && backpackSaveData.Contents != null)
				{
					text2 = backpackSaveData.Contents;
					highestPurchasedTierIndex = backpackSaveData.HighestPurchasedTierIndex;
				}
				DeserializedItemSet val = default(DeserializedItemSet);
				if (!ItemSet.TryDeserialize(text2, ref val))
				{
					ModLogger.Error("Failed to deserialize network backpack data.");
					return;
				}
				val.LoadTo(backpackStorage.ItemSlots);
				if ((Object)(object)PlayerBackpack.Instance != (Object)null)
				{
					PlayerBackpack.Instance.SetHighestPurchasedTierIndex(highestPurchasedTierIndex);
				}
			}
			catch (Exception exception)
			{
				ModLogger.Error("Error loading network backpack data", exception);
			}
		}

		[HarmonyPatch("Activate")]
		[HarmonyPrefix]
		public static void Activate()
		{
			ModLogger.Info("Activating backpack.");
			PlayerBackpack.Instance?.SetBackpackEnabled(state: true);
		}

		[HarmonyPatch("Deactivate")]
		[HarmonyPrefix]
		public static void Deactivate()
		{
			ModLogger.Info("Deactivating backpack.");
			PlayerBackpack.Instance?.SetBackpackEnabled(state: false);
		}

		[HarmonyPatch("ExitAll")]
		[HarmonyPrefix]
		public static void ExitAll()
		{
			ModLogger.Info("ExitAll: disabling backpack.");
			PlayerBackpack.Instance?.SetBackpackEnabled(state: false);
		}

		[HarmonyPatch("OnDied")]
		[HarmonyPrefix]
		public static void OnDied(Player __instance)
		{
			if (((NetworkBehaviour)__instance).Owner.IsLocalClient)
			{
				ModLogger.Info("Player died, disabling backpack.");
				PlayerBackpack.Instance?.SetBackpackEnabled(state: false);
			}
		}
	}
	[HarmonyPatch(typeof(PlayerSpawner))]
	public static class PlayerSpawnerPatch
	{
		[HarmonyPatch("InitializeOnce")]
		[HarmonyPostfix]
		public static void InitializeOnce(PlayerSpawner __instance)
		{
			NetworkObject playerPrefab = __instance._playerPrefab;
			if (!Object.op_Implicit((Object)(object)playerPrefab))
			{
				ModLogger.Error("Player prefab is null!");
				return;
			}
			Player component = ((Component)playerPrefab).GetComponent<Player>();
			if ((Object)(object)component == (Object)null)
			{
				ModLogger.Error("Player prefab does not have a Player component!");
				return;
			}
			ModLogger.Info("Adding backpack storage to player prefab...");
			StorageEntity orAddComponentSafe = Utils.GetOrAddComponentSafe<StorageEntity>(((Component)component).gameObject);
			if ((Object)(object)orAddComponentSafe == (Object)null)
			{
				ModLogger.Error("Failed to get or add StorageEntity to player prefab!");
				return;
			}
			orAddComponentSafe.SlotCount = 40;
			orAddComponentSafe.DisplayRowCount = 8;
			orAddComponentSafe.StorageEntityName = "Backpack";
			orAddComponentSafe.MaxAccessDistance = float.PositiveInfinity;
			Utils.GetOrAddComponentSafe<PlayerBackpack>(component.LocalGameObject);
		}
	}
	[HarmonyPatch(typeof(ShopInterface))]
	public static class ShopInterfacePatch
	{
		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		public static void Awake(ShopInterface __instance)
		{
			BackpackShopIntegration.TryAddBackpackListingsToShop(__instance);
		}

		[HarmonyPatch("GetAvailableSlots")]
		[HarmonyPostfix]
		public static void GetAvailableSlots(ShopInterface __instance, ref List<ItemSlot> __result)
		{
			if (!PlayerBackpack.Instance.IsUnlocked)
			{
				return;
			}
			LandVehicle loadingBayVehicle = __instance.GetLoadingBayVehicle();
			if ((Object)(object)loadingBayVehicle != (Object)null && __instance.Cart.LoadVehicleToggle.isOn)
			{
				return;
			}
			int count = PlayerSingleton<PlayerInventory>.Instance.hotbarSlots.Count;
			List<ItemSlot> itemSlots = PlayerBackpack.Instance.ItemSlots;
			for (int i = 0; i < itemSlots.Count; i++)
			{
				List<ItemSlot> val = itemSlots;
				ItemSlot val2 = ((Il2CppObjectBase)val[new Index(i).GetOffset(val.Count)]).TryCast<ItemSlot>();
				if (val2 != null)
				{
					__result.Insert(i + count, val2);
				}
			}
		}
	}
	[HarmonyPatch(typeof(StorageMenu))]
	public static class StorageMenuPatch
	{
		[HarmonyPatch("Awake")]
		[HarmonyPrefix]
		public static void Awake(StorageMenu __instance)
		{
			if (((Il2CppArrayBase<ItemSlotUI>)(object)__instance.SlotsUIs).Length >= 40)
			{
				return;
			}
			RectTransform slotContainer = __instance.SlotContainer;
			ItemSlotUI obj = ((Il2CppArrayBase<ItemSlotUI>)(object)__instance.SlotsUIs)[0];
			GameObject val = ((obj != null) ? ((Component)obj).gameObject : null);
			if ((Object)(object)val == (Object)null)
			{
				ModLogger.Error("StorageMenu prefab is null. Cannot create additional slots.");
				return;
			}
			ItemSlotUI[] array = (ItemSlotUI[])(object)new ItemSlotUI[40];
			for (int i = 0; i < 40; i++)
			{
				if (i < ((Il2CppArrayBase<ItemSlotUI>)(object)__instance.SlotsUIs).Length)
				{
					array[i] = ((Il2CppArrayBase<ItemSlotUI>)(object)__instance.SlotsUIs)[i];
					continue;
				}
				GameObject val2 = Object.Instantiate<GameObject>(val, (Transform)(object)slotContainer);
				((Object)val2).name = $"{((Object)val).name} ({i})";
				val2.gameObject.SetActive(true);
				array[i] = val2.GetComponent<ItemSlotUI>();
			}
			__instance.SlotsUIs = Il2CppReferenceArray<ItemSlotUI>.op_Implicit(array);
		}

		[HarmonyPatch("Open", new Type[]
		{
			typeof(string),
			typeof(string),
			typeof(IItemSlotOwner)
		})]
		[HarmonyPostfix]
		public static void Open(StorageMenu __instance, string title, string subtitle, IItemSlotOwner owner)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			float num = __instance.SlotGridLayout.cellSize.y + __instance.SlotGridLayout.spacing.y;
			__instance.CloseButton.anchoredPosition = new Vector2(0f, (float)__instance.SlotGridLayout.constraintCount * (0f - num) - __instance.CloseButton.sizeDelta.y);
			if (__instance.SlotGridLayout.constraintCount > 4)
			{
				((Transform)__instance.Container).localPosition = new Vector3(0f, (float)(__instance.SlotGridLayout.constraintCount - 4) * num, 0f);
			}
		}

		[HarmonyPatch("CloseMenu")]
		[HarmonyPrefix]
		public static void CloseMenu(StorageMenu __instance)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			((Transform)__instance.Container).localPosition = Vector3.zero;
		}
	}
}
namespace PackRat.Helpers
{
	internal static class CameraLockedStateHelper
	{
		private static Type _dialogueManagerType;

		private static Type _dialogueHandlerType;

		private static FieldInfo _dialogueHandlerActiveDialogueField;

		private static FieldInfo _shopInterfaceAllShopsField;

		private static Type[] _dealWindowTypes;

		private static bool _typesResolved;

		private static void EnsureTypesResolved()
		{
			if (_typesResolved)
			{
				return;
			}
			_typesResolved = true;
			_dialogueManagerType = ReflectionUtils.GetTypeByName("ScheduleOne.Dialogue.DialogueManager");
			_dialogueHandlerType = ReflectionUtils.GetTypeByName("ScheduleOne.Dialogue.DialogueHandler");
			if (_dialogueHandlerType != null)
			{
				_dialogueHandlerActiveDialogueField = _dialogueHandlerType.GetField("activeDialogue", BindingFlags.Static | BindingFlags.Public);
			}
			Type typeFromHandle = typeof(ShopInterface);
			_shopInterfaceAllShopsField = typeFromHandle.GetField("AllShops", BindingFlags.Static | BindingFlags.Public);
			string[] array = new string[4] { "ScheduleOne.Economy.DealWindow", "ScheduleOne.UI.DealCanvas", "ScheduleOne.UI.FreeSampleCanvas", "ScheduleOne.Economy.DealInterface" };
			List<Type> list = new List<Type>();
			string[] array2 = array;
			foreach (string typeName in array2)
			{
				Type typeByName = ReflectionUtils.GetTypeByName(typeName);
				if (typeByName != null)
				{
					list.Add(typeByName);
				}
			}
			_dealWindowTypes = list.ToArray();
		}

		public static void PrewarmCache()
		{
			EnsureTypesResolved();
		}

		public static bool IsCameraLockedByUI()
		{
			try
			{
				if (Cursor.visible)
				{
					ModLogger.Debug("Camera locked: Cursor visible (UI with mouse).");
					return true;
				}
				if (IsATMOpen())
				{
					ModLogger.Debug("Camera locked: ATM screen open.");
					return true;
				}
				if (IsCharacterCreatorOpen())
				{
					ModLogger.Debug("Camera locked: Appearance/Character Creator open.");
					return true;
				}
				if (IsCharacterCustomizationShopOpen())
				{
					ModLogger.Debug("Camera locked: Tattoo/customization shop open.");
					return true;
				}
				if (IsTVInterfaceOpen())
				{
					ModLogger.Debug("Camera locked: TV screen open.");
					return true;
				}
				if (IsShopInterfaceOpen())
				{
					ModLogger.Debug("Camera locked: Shop screen open.");
					return true;
				}
				if (IsDialogueActive())
				{
					ModLogger.Debug("Camera locked: Dialogue active.");
					return true;
				}
				if (IsInVehicle())
				{
					ModLogger.Debug("Camera locked: Player in vehicle.");
					return true;
				}
				if (IsDealOrFreeSampleOpen())
				{
					ModLogger.Debug("Camera locked: Deal or free sample screen open.");
					return true;
				}
				return false;
			}
			catch (Exception exception)
			{
				ModLogger.Error("Error checking camera-locked UI state", exception);
				return false;
			}
		}

		private static bool IsATMOpen()
		{
			try
			{
				ATMInterface val = Utils.FindObjectOfTypeSafe<ATMInterface>();
				if ((Object)(object)val == (Object)null)
				{
					return false;
				}
				object obj = ReflectionUtils.TryGetFieldOrProperty(val, "isOpen");
				bool flag = default(bool);
				int num;
				if (obj is bool)
				{
					flag = (bool)obj;
					num = 1;
				}
				else
				{
					num = 0;
				}
				return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
			}
			catch
			{
				return false;
			}
		}

		private static bool IsCharacterCreatorOpen()
		{
			try
			{
				if (Singleton<CharacterCreator>.InstanceExists)
				{
					CharacterCreator instance = Singleton<CharacterCreator>.Instance;
					if ((Object)(object)instance != (Object)null && instance.IsOpen)
					{
						return true;
					}
				}
				CharacterCreator[] array = Utils.FindObjectsOfTypeSafe<CharacterCreator>();
				if (array == null)
				{
					return false;
				}
				foreach (CharacterCreator val in array)
				{
					if ((Object)(object)val != (Object)null && val.IsOpen)
					{
						return true;
					}
				}
				return false;
			}
			catch
			{
				return false;
			}
		}

		private static bool IsCharacterCustomizationShopOpen()
		{
			try
			{
				CharacterCustomizationShop[] array = Utils.FindObjectsOfTypeSafe<CharacterCustomizationShop>();
				if (array == null)
				{
					return false;
				}
				foreach (CharacterCustomizationShop val in array)
				{
					if ((Object)(object)val == (Object)null || !((Component)val).gameObject.activeInHierarchy)
					{
						continue;
					}
					List<Canvas> allComponentsInChildrenRecursive = Utils.GetAllComponentsInChildrenRecursive<Canvas>(((Component)val).gameObject);
					if (allComponentsInChildrenRecursive == null)
					{
						continue;
					}
					for (int j = 0; j < allComponentsInChildrenRecursive.Count; j++)
					{
						Canvas val2 = allComponentsInChildrenRecursive[j];
						if ((Object)(object)val2 != (Object)null && ((Behaviour)val2).enabled && ((Component)val2).gameObject.activeInHierarchy)
						{
							return true;
						}
					}
				}
				return false;
			}
			catch
			{
				return false;
			}
		}

		private static bool IsTVInterfaceOpen()
		{
			try
			{
				TVInterface val = Utils.FindObjectOfTypeSafe<TVInterface>();
				return (Object)(object)val != (Object)null && val.IsOpen;
			}
			catch
			{
				return false;
			}
		}

		private static bool IsShopInterfaceOpen()
		{
			try
			{
				if (_shopInterfaceAllShopsField != null)
				{
					object value = _shopInterfaceAllShopsField.GetValue(null);
					if (value != null && value is IEnumerable enumerable)
					{
						bool flag = default(bool);
						foreach (object item in enumerable)
						{
							if (item != null)
							{
								object obj = ReflectionUtils.TryGetFieldOrProperty(item, "IsOpen");
								int num;
								if (obj is bool)
								{
									flag = (bool)obj;
									num = 1;
								}
								else
								{
									num = 0;
								}
								if (((uint)num & (flag ? 1u : 0u)) != 0)
								{
									return true;
								}
							}
						}
					}
				}
				ShopInterface val = Utils.FindObjectOfTypeSafe<ShopInterface>();
				if ((Object)(object)val == (Object)null)
				{
					return false;
				}
				if (ReflectionUtils.TryGetFieldOrProperty(val, "IsOpen") is bool result)
				{
					return result;
				}
				object obj2 = ReflectionUtils.TryGetFieldOrProperty(val, "isOpen");
				bool flag2 = default(bool);
				int num2;
				if (obj2 is bool)
				{
					flag2 = (bool)obj2;
					num2 = 1;
				}
				else
				{
					num2 = 0;
				}
				return (byte)((uint)num2 & (flag2 ? 1u : 0u)) != 0;
			}
			catch
			{
				return false;
			}
		}

		private static bool IsDialogueActive()
		{
			try
			{
				EnsureTypesResolved();
				if (_dialogueHandlerActiveDialogueField != null)
				{
					object value = _dialogueHandlerActiveDialogueField.GetValue(null);
					if (value != null)
					{
						return true;
					}
				}
				if (_dialogueManagerType == null)
				{
					return false;
				}
				PropertyInfo property = _dialogueManagerType.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public);
				if (property == null)
				{
					return false;
				}
				object value2 = property.GetValue(null);
				if (value2 == null)
				{
					return false;
				}
				if (ReflectionUtils.TryGetFieldOrProperty(value2, "IsActive") is bool result)
				{
					return result;
				}
				object obj = ReflectionUtils.TryGetFieldOrProperty(value2, "IsOpen");
				bool flag = default(bool);
				int num;
				if (obj is bool)
				{
					flag = (bool)obj;
					num = 1;
				}
				else
				{
					num = 0;
				}
				return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
			}
			catch
			{
				return false;
			}
		}

		private static bool IsInVehicle()
		{
			try
			{
				if ((Object)(object)Player.Local == (Object)null)
				{
					return false;
				}
				if (ReflectionUtils.TryGetFieldOrProperty(Player.Local, "IsInVehicle") is bool result)
				{
					return result;
				}
				object obj = ReflectionUtils.TryGetFieldOrProperty(Player.Local, "CurrentVehicle");
				return obj != null;
			}
			catch
			{
				return false;
			}
		}

		private static bool IsDealOrFreeSampleOpen()
		{
			try
			{
				EnsureTypesResolved();
				if (_dealWindowTypes == null || _dealWindowTypes.Length == 0)
				{
					return false;
				}
				Type[] dealWindowTypes = _dealWindowTypes;
				bool flag = default(bool);
				bool flag2 = default(bool);
				foreach (Type type in dealWindowTypes)
				{
					PropertyInfo property = type.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public);
					if (property == null)
					{
						continue;
					}
					object value = property.GetValue(null);
					if (value != null)
					{
						object obj = ReflectionUtils.TryGetFieldOrProperty(value, "IsOpen");
						int num;
						if (obj is bool)
						{
							flag = (bool)obj;
							num = 1;
						}
						else
						{
							num = 0;
						}
						if (((uint)num & (flag ? 1u : 0u)) != 0)
						{
							return true;
						}
						obj = ReflectionUtils.TryGetFieldOrProperty(value, "isOpen");
						int num2;
						if (obj is bool)
						{
							flag2 = (bool)obj;
							num2 = 1;
						}
						else
						{
							num2 = 0;
						}
						if (((uint)num2 & (flag2 ? 1u : 0u)) != 0)
						{
							return true;
						}
					}
				}
				return false;
			}
			catch
			{
				return false;
			}
		}
	}
	public static class EventHelper
	{
		private static readonly Dictionary<Action, Delegate> SubscribedActions = new Dictionary<Action, Delegate>();

		private static readonly Dictionary<Delegate, Delegate> SubscribedGenericActions = new Dictionary<Delegate, Delegate>();

		public static void AddListener(Action listener, UnityEvent unityEvent)
		{
			if (listener != null && unityEvent != null && !SubscribedActions.ContainsKey(listener))
			{
				Action action = listener.Invoke;
				unityEvent.AddListener(UnityAction.op_Implicit(action));
				SubscribedActions.Add(listener, action);
			}
		}

		public static void RemoveListener(Action listener, UnityEvent unityEvent)
		{
			if (listener != null && unityEvent != null && SubscribedActions.TryGetValue(listener, out var value))
			{
				SubscribedActions.Remove(listener);
				if ((object)value != null && value is Action action)
				{
					unityEvent.RemoveListener(UnityAction.op_Implicit(action));
				}
			}
		}

		public static void AddListener<T>(Action<T> listener, UnityEvent<T> unityEvent)
		{
			if (listener != null && unityEvent != null && !SubscribedGenericActions.ContainsKey(listener))
			{
				Action<T> action = listener.Invoke;
				unityEvent.AddListener(UnityAction<T>.op_Implicit(action));
				SubscribedGenericActions.Add(listener, action);
			}
		}

		public static void RemoveListener<T>(Action<T> listener, UnityEvent<T> unityEvent)
		{
			if (listener != null && unityEvent != null && SubscribedGenericActions.TryGetValue(listener, out var value))
			{
				if (value is Action<T> action)
				{
					unityEvent.RemoveListener(UnityAction<T>.op_Implicit(action));
				}
				SubscribedGenericActions.Remove(listener);
			}
		}
	}
	public static class JsonHelper
	{
		private static JsonSerializerSettings _cachedSettings;

		private static JsonSerializerSettings _cachedSettingsFormatted;

		private static bool _initializationAttempted;

		public static JsonSerializerSettings GetDefaultSettings()
		{
			//IL_002a: 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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			if (_cachedSettings != null)
			{
				return _cachedSettings;
			}
			if (!_initializationAttempted)
			{
				_initializationAttempted = true;
				try
				{
					_cachedSettings = new JsonSerializerSettings
					{
						MissingMemberHandling = (MissingMemberHandling)0,
						NullValueHandling = (NullValueHandling)1
					};
				}
				catch (Exception ex)
				{
					MelonLogger.Warning("[PackRat] Error creating JsonSerializerSettings: " + ex.Message);
					_cachedSettings = null;
				}
			}
			return _cachedSettings;
		}

		public static string SerializeObject<T>(T value)
		{
			try
			{
				return JsonSerializer.Serialize(value);
			}
			catch (Exception ex)
			{
				MelonLogger.Error("[PackRat] Error serializing object to JSON: " + ex.Message);
				throw;
			}
		}

		public static T DeserializeObject<T>(string json)
		{
			try
			{
				return JsonSerializer.Deserialize<T>(json);
			}
			catch (Exception ex)
			{
				MelonLogger.Error("[PackRat] Error deserializing JSON to " + typeof(T).Name + ": " + ex.Message);
				throw;
			}
		}

		public static void PopulateObject(string json, object target)
		{
			if (target == null)
			{
				return;
			}
			Type type = target.GetType();
			object obj = JsonSerializer.Deserialize(json, type);
			if (obj == null)
			{
				return;
			}
			PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
			foreach (PropertyInfo propertyInfo in properties)
			{
				if (!propertyInfo.CanRead || !propertyInfo.CanWrite)
				{
					continue;
				}
				try
				{
					object value = propertyInfo.GetValue(obj);
					if (value != null)
					{
						propertyInfo.SetValue(target, value);
					}
				}
				catch
				{
				}
			}
			FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public);
			foreach (FieldInfo fieldInfo in fields)
			{
				try
				{
					object value2 = fieldInfo.GetValue(obj);
					if (value2 != null)
					{
						fieldInfo.SetValue(target, value2);
					}
				}
				catch
				{
				}
			}
		}
	}
	public static class ModLogger
	{
		public static void Info(string message)
		{
			MelonLogger.Msg(message);
		}

		public static void Debug(string message)
		{
			MelonLogger.Msg("[DEBUG] " + message);
		}

		public static void Warn(string message)
		{
			MelonLogger.Warning(message);
		}

		public static void Error(string message)
		{
			MelonLogger.Error(message);
		}

		public static void Error(string message, Exception exception)
		{
			MelonLogger.Error(message + ": " + exception.Message);
			MelonLogger.Error("Stack trace: " + exception.StackTrace);
		}
	}
	public static class NetworkHelper
	{
		public static int GetPlayerNetworkId(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				ModLogger.Warn("Cannot get network ID - player is null");
				return -1;
			}
			if ((Object)(object)((NetworkBehaviour)player).NetworkObject == (Object)null)
			{
				ModLogger.Warn("Cannot get network ID - player " + ((Object)player).name + " has null NetworkObject");
				return -1;
			}
			return ((NetworkBehaviour)player).NetworkObject.ObjectId;
		}

		public static string GetPlayerNetworkIdString(Player player)
		{
			int playerNetworkId = GetPlayerNetworkId(player);
			if (playerNetworkId == -1)
			{
				return "";
			}
			return playerNetworkId.ToString();
		}

		public static bool HasValidNetworkObject(Player player)
		{
			return (Object)(object)player != (Object)null && (Object)(object)((NetworkBehaviour)player).NetworkObject != (Object)null;
		}
	}
	internal static class ReflectionUtils
	{
		internal static List<Type> GetDerivedClasses<TBaseClass>()
		{
			List<Type> list = new List<Type>();
			Assembly[] array = (from assembly in AppDomain.CurrentDomain.GetAssemblies()
				where !ShouldSkipAssembly(assembly)
				select assembly).ToArray();
			Assembly[] array2 = array;
			foreach (Assembly asm in array2)
			{
				foreach (Type item in SafeGetTypes(asm))
				{
					try
					{
						if (!(item == null) && typeof(TBaseClass).IsAssignableFrom(item) && item != typeof(TBaseClass) && !item.IsAbstract)
						{
							list.Add(item);
						}
					}
					catch (TypeLoadException)
					{
					}
					catch (Exception)
					{
					}
				}
			}
			return list;
		}

		internal static Type GetTypeByName(string typeName)
		{
			try
			{
				Type type = Type.GetType(typeName, throwOnError: false, ignoreCase: false);
				if (type != null)
				{
					return type;
				}
			}
			catch
			{
			}
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly item in assemblies.Where((Assembly a) => !ShouldSkipAssembly(a)))
			{
				foreach (Type item2 in SafeGetTypes(item))
				{
					if (item2 == null || (!(item2.Name == typeName) && !(item2.FullName == typeName)))
					{
						continue;
					}
					return item2;
				}
			}
			Assembly[] array = assemblies;
			foreach (Assembly asm in array)
			{
				foreach (Type item3 in SafeGetTypes(asm))
				{
					if (item3 == null || (!(item3.Name == typeName) && !(item3.FullName == typeName) && (item3.FullName == null || !item3.FullName.EndsWith("." + typeName))))
					{
						continue;
					}
					return item3;
				}
			}
			return null;
		}

		internal static bool ShouldSkipAssembly(Assembly assembly)
		{
			string fullName = assembly.FullName;
			if (string.IsNullOrEmpty(fullName))
			{
				return false;
			}
			return fullName.StartsWith("System") || fullName.StartsWith("Unity") || fullName.StartsWith("Il2Cpp") || fullName.StartsWith("mscorlib") || fullName.StartsWith("Mono.") || fullName.StartsWith("netstandard") || fullName.StartsWith("com.rlabrecque") || fullName.StartsWith("__Generated");
		}

		internal static IEnumerable<Type> SafeGetTypes(Assembly asm)
		{
			try
			{
				return asm.GetTypes();
			}
			catch (ReflectionTypeLoadException ex)
			{
				return ex.Types.Where((Type t) => t != null).Cast<Type>();
			}
			catch
			{
				return Array.Empty<Type>();
			}
		}

		internal static FieldInfo[] GetAllFields(Type type, BindingFlags bindingFlags)
		{
			List<FieldInfo> list = new List<FieldInfo>();
			while (type != null && type != typeof(object))
			{
				list.AddRange(type.GetFields(bindingFlags | BindingFlags.DeclaredOnly));
				type = type.BaseType;
			}
			return list.ToArray();
		}

		internal static MethodInfo GetMethod(Type type, string methodName, BindingFlags bindingFlags)
		{
			while (type != null && type != typeof(object))
			{
				MethodInfo method = type.GetMethod(methodName, bindingFlags);
				if (method != null)
				{
					return method;
				}
				type = type.BaseType;
			}
			return null;
		}

		internal static bool TrySetFieldOrProperty(object target, string memberName, object value)
		{
			if (target == null)
			{
				return false;
			}
			Type type = target.GetType();
			FieldInfo field = type.GetField(memberName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null)
			{
				try
				{
					if (value == null || field.FieldType.IsInstanceOfType(value))
					{
						field.SetValue(target, value);
						return true;
					}
				}
				catch
				{
				}
			}
			PropertyInfo property = type.GetProperty(memberName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (property != null && property.CanWrite)
			{
				try
				{
					if (value == null || property.PropertyType.IsInstanceOfType(value))
					{
						property.SetValue(target, value);
						return true;
					}
				}
				catch
				{
				}
			}
			return false;
		}

		internal static object TryGetFieldOrProperty(object target, string memberName)
		{
			if (target == null)
			{
				return null;
			}
			Type type = target.GetType();
			FieldInfo field = type.GetField(memberName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null)
			{
				try
				{
					return field.GetValue(target);
				}
				catch
				{
				}
			}
			PropertyInfo property = type.GetProperty(memberName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (property != null && property.CanRead)
			{
				try
				{
					return property.GetValue(target);
				}
				catch
				{
				}
			}
			return null;
		}

		internal static int TryGetListCount(object list)
		{
			if (list == null)
			{
				return 0;
			}
			Type type = list.GetType();
			PropertyInfo property = type.GetProperty("Count", BindingFlags.Instance | BindingFlags.Public);
			if (property != null && property.PropertyType == typeof(int))
			{
				try
				{
					return (int)property.GetValue(list);
				}
				catch
				{
				}
			}
			if (list is ICollection collection)
			{
				try
				{
					return collection.Count;
				}
				catch
				{
				}
			}
			return 0;
		}

		internal static object TryGetListItem(object list, int index)
		{
			if (list == null)
			{
				return null;
			}
			if (list is IList list2)
			{
				try
				{
					return list2[index];
				}
				catch
				{
					return null;
				}
			}
			Type type = list.GetType();
			MethodInfo methodInfo = type.GetMethod("get_Item", new Type[1] { typeof(int) }) ?? type.GetMethod("Get", new Type[1] { typeof(int) });
			if (methodInfo != null)
			{
				try
				{
					return methodInfo.Invoke(list, new object[1] { index });
				}
				catch
				{
				}
			}
			return null;
		}

		internal static List<object> TryGetAllListLikeMembers(object target)
		{
			List<object> list = new List<object>();
			if (target == null)
			{
				return list;
			}
			Type type = target.GetType();
			FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (FieldInfo fieldInfo in fields)
			{
				try
				{
					object value = fieldInfo.GetValue(target);
					if (value != null && TryGetListCount(value) >= 0)
					{
						list.Add(value);
					}
				}
				catch
				{
				}
			}
			PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (PropertyInfo propertyInfo in properties)
			{
				if (!propertyInfo.CanRead)
				{
					continue;
				}
				try
				{
					object value2 = propertyInfo.GetValue(target);
					if (value2 != null && TryGetListCount(value2) >= 0)
					{
						list.Add(value2);
					}
				}
				catch
				{
				}
			}
			return list;
		}

		internal static void TryInvokeParameterlessCallback(object target, params string[] possibleNames)
		{
			if (target == null)
			{
				return;
			}
			foreach (string memberName in possibleNames)
			{
				object obj = TryGetFieldOrProperty(target, memberName);
				if (obj == null)
				{
					continue;
				}
				if (obj is Delegate @delegate)
				{
					try
					{
						@delegate.DynamicInvoke(null);
						break;
					}
					catch
					{
					}
				}
				MethodInfo method = obj.GetType().GetMethod("Invoke", BindingFlags.Instance | BindingFlags.Public);
				if (method != null && method.GetParameters().Length == 0)
				{
					try
					{
						method.Invoke(obj, null);
						break;
					}
					catch
					{
					}
				}
			}
		}
	}
	public static class Il2CppListExtensions
	{
		public static IEnumerable<T> AsEnumerable<T>(this List<T> list)
		{
			return list ?? new List<T>();
		}

		public static List<T> ToIl2CppList<T>(this IEnumerable<T> source)
		{
			List<T> val = new List<T>();
			foreach (T item in source)
			{
				val.Add(item);
			}
			return val;
		}

		public static List<T> ConvertToList<T>(List<T> il2CppList)
		{
			List<T> list = new List<T>();
			T[] collection = Il2CppArrayBase<T>.op_Implicit(il2CppList.ToArray());
			list.AddRange(collection);
			return list;
		}

		public static IEnumerable<T> AsEnumerable<T>(this List<T> list)
		{
			IEnumerable<T> result;
			if (list != null)
			{
				result = ((IEnumerable<T>)list._items).Take(list._size);
			}
			else
			{
				IEnumerable<T> enumerable = Array.Empty<T>();
				result = enumerable;
			}
			return result;
		}
	}
	public static class Utils
	{
		[CompilerGenerated]
		private sealed class <WaitForNetwork>d__14 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public IEnumerator routine;

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

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

			[DebuggerHidden]
			public <WaitForNetwork>d__14(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

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

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (!InstanceFinder.IsServer && !InstanceFinder.IsClient)
				{
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				MelonCoroutines.Start(routine);
				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 <WaitForNetworkSingleton>d__16<T> : IEnumerator<object>, IEnumerator, IDisposable where T : notnull, NetworkSingleton<T>
		{
			private int <>1__state;

			private object <>2__current;

			public IEnumerator coroutine;

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

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

			[DebuggerHidden]
			public <WaitForNetworkSingleton>d__16(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

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

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					goto IL_0044;
				case 1:
					<>1__state = -1;
					goto IL_0044;
				case 2:
					{
						<>1__state = -1;
						return false;
					}
					IL_0044:
					if (!NetworkSingleton<T>.InstanceExists)
					{
						<>2__current = null;
						<>1__state = 1;
						return true;
					}
					<>2__current = coroutine;
					<>1__state = 2;
					return true;
				}
			}

			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 <WaitForNotNull>d__15 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public object obj;

			public float timeout;

			public Action onTimeout;

			public Action onFinish;

			private float <startTime>5__1;

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

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

			[DebuggerHidden]
			public <WaitForNotNull>d__15(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

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

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<startTime>5__1 = Time.time;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (obj == null)
				{
					if (!float.IsNaN(timeout) && Time.time - <startTime>5__1 > timeout)
					{
						onTimeout?.Invoke();
						return false;
					}
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				onFinish?.Invoke();
				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 <WaitForPlayer>d__13 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public IEnumerator routine;

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

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

			[DebuggerHidden]
			public <WaitForPlayer>d__13(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

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

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if ((Object)(object)Player.Local == (Object)null || (Object)(object)((Component)Player.Local).gameObject == (Object)null)
				{
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				MelonCoroutines.Start(routine);
				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 readonly HashSet<string> _typeResolutionFailuresLogged = new HashSet<string>();

		private static readonly object _typeResolutionLock = new object();

		private static void LogTypeResolutionFailureOnce(string typeName, string reason)
		{
			lock (_typeResolutionLock)
			{
				if (_typeResolutionFailuresLogged.Add(typeName))
				{
					ModLogger.Error("[IL2CPP] Failed to resolve type '" + typeName + "': " + reason);
				}
			}
		}

		private static bool TryResolveIl2CppType<T>(out Type il2CppType) where T : Object
		{
			il2CppType = null;
			Type typeFromHandle = typeof(T);
			string typeName = typeFromHandle.FullName ?? typeFromHandle.Name;
			try
			{
				il2CppType = Il2CppType.Of<T>();
				return il2CppType != (Type)null;
			}
			catch (Exception ex)
			{
				LogTypeResolutionFailureOnce(typeName, ex.Message);
				return false;
			}
		}

		public static T GetComponentSafe<T>(GameObject gameObject) where T : Component
		{
			if ((Object)(object)gameObject == (Object)null)
			{
				return default(T);
			}
			if (!TryResolveIl2CppType<T>(out Type il2CppType))
			{
				return default(T);
			}
			Component component = gameObject.GetComponent(il2CppType);
			return (component != null) ? ((Il2CppObjectBase)component).TryCast<T>() : default(T);
		}

		public static T AddComponentSafe<T>(GameObject gameObject) where T : Component
		{
			if ((Object)(object)gameObject == (Object)null)
			{
				return default(T);
			}
			if (!TryResolveIl2CppType<T>(out Type il2CppType))
			{
				return default(T);
			}
			Component val = gameObject.AddComponent(il2CppType);
			return (val != null) ? ((Il2CppObjectBase)val).TryCast<T>() : default(T);
		}

		public static T GetOrAddComponentSafe<T>(GameObject gameObject) where T : Component
		{
			T componentSafe = GetComponentSafe<T>(gameObject);
			return componentSafe ?? AddComponentSafe<T>(gameObject);
		}

		public static T FindObjectOfTypeSafe<T>() where T : Object
		{
			if (!TryResolveIl2CppType<T>(out Type il2CppType))
			{
				return default(T);
			}
			Object val = Object.FindObjectOfType(il2CppType);
			return (val !=

PackRat-Mono.dll

Decompiled 8 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using FishNet;
using FishNet.Component.Spawning;
using FishNet.Object;
using HarmonyLib;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using PackRat;
using PackRat.Config;
using PackRat.Extensions;
using PackRat.Helpers;
using PackRat.Patches;
using PackRat.Shops;
using PackRat.Storage;
using ScheduleOne;
using ScheduleOne.AvatarFramework;
using ScheduleOne.AvatarFramework.Customization;
using ScheduleOne.DevUtilities;
using ScheduleOne.ItemFramework;
using ScheduleOne.Levelling;
using ScheduleOne.NPCs;
using ScheduleOne.NPCs.Behaviour;
using ScheduleOne.Networking;
using ScheduleOne.Persistence;
using ScheduleOne.Persistence.Datas;
using ScheduleOne.Persistence.Loaders;
using ScheduleOne.PlayerScripts;
using ScheduleOne.Product;
using ScheduleOne.Product.Packaging;
using ScheduleOne.Storage;
using ScheduleOne.TV;
using ScheduleOne.Tools;
using ScheduleOne.UI;
using ScheduleOne.UI.ATM;
using ScheduleOne.UI.Phone;
using ScheduleOne.UI.Shop;
using ScheduleOne.Vehicles;
using Steamworks;
using TMPro;
using UnityEngine;
using UnityEngine.Events;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(global::PackRat.PackRat), "PackRat", "1.0.2", "SirTidez", null)]
[assembly: MelonColor(1, 255, 165, 0)]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("PackRat-Mono")]
[assembly: AssemblyConfiguration("Debug Mono")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+bb8cf00e0d4fb3f3e32037aff75ec210ea048a83")]
[assembly: AssemblyProduct("PackRat-Mono")]
[assembly: AssemblyTitle("PackRat-Mono")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 PackRat
{
	public static class BuildInfo
	{
		public const string Name = "PackRat";

		public const string Description = "Portable backpack storage for Schedule One";

		public const string Author = "SirTidez";

		public const string Version = "1.0.2";
	}
	public class PackRat : MelonMod
	{
		public override void OnInitializeMelon()
		{
			Configuration.Instance.Load();
			Configuration.Instance.Save();
			ModLogger.Info("PackRat initialized.");
		}

		public override void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
			Configuration.Instance.Reset();
			if (!(sceneName != "Main"))
			{
				ConfigSyncManager.StartSync();
				BackpackShopIntegration.RunWhenReady();
			}
		}
	}
	public class PlayerBackpack : MonoBehaviour
	{
		public const string StorageName = "Backpack";

		public const int MaxStorageSlots = 40;

		private bool _backpackEnabled = true;

		private StorageEntity _storage;

		private int _lastTierIndex = -2;

		private string _openTitle;

		private int _highestPurchasedTierIndex = -1;

		public static PlayerBackpack Instance { get; private set; }

		public int HighestPurchasedTierIndex => _highestPurchasedTierIndex;

		public int CurrentTierIndex
		{
			get
			{
				Configuration instance = Configuration.Instance;
				if (_highestPurchasedTierIndex < 0)
				{
					return -1;
				}
				for (int num = _highestPurchasedTierIndex; num >= 0; num--)
				{
					if (num < instance.TierEnabled.Length && instance.TierEnabled[num])
					{
						return num;
					}
				}
				return -1;
			}
		}

		public BackpackTierDefinition CurrentTier
		{
			get
			{
				int currentTierIndex = CurrentTierIndex;
				return (currentTierIndex >= 0) ? Configuration.BackpackTiers[currentTierIndex] : null;
			}
		}

		public bool IsUnlocked => CurrentTierIndex >= 0;

		public bool IsPoliceSearchable => CurrentTierIndex >= 2;

		public bool IsOpen => Singleton<StorageMenu>.Instance.IsOpen && ((TMP_Text)Singleton<StorageMenu>.Instance.TitleLabel).text == _openTitle;

		public List<ItemSlot> ItemSlots => _storage.ItemSlots.ToList();

		public void SetHighestPurchasedTierIndex(int tierIndex)
		{
			_highestPurchasedTierIndex = ((tierIndex < 0) ? (-1) : Math.Min(tierIndex, Configuration.BackpackTiers.Length - 1));
		}

		private void Awake()
		{
			_storage = ((Component)this).gameObject.GetComponentInParent<StorageEntity>();
			if ((Object)(object)_storage == (Object)null)
			{
				ModLogger.Error("Player does not have a BackpackStorage component!");
				return;
			}
			ModLogger.Info("Configuring backpack storage...");
			int currentTierIndex = CurrentTierIndex;
			int newSize = ((currentTierIndex >= 0) ? Configuration.Instance.TierSlotCounts[currentTierIndex] : Configuration.BackpackTiers[0].DefaultSlotCount);
			UpdateSize(newSize);
			OnStartClient(isOwner: true);
		}

		private void Update()
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			int currentTierIndex = CurrentTierIndex;
			if (currentTierIndex != _lastTierIndex)
			{
				_lastTierIndex = currentTierIndex;
				ApplyCurrentTier(currentTierIndex);
			}
			if (!_backpackEnabled || !Input.GetKeyDown(Configuration.Instance.ToggleKey))
			{
				return;
			}
			try
			{
				if (TryConsumeSelectedHotbarBackpackItem(out var appliedTier))
				{
					if (appliedTier >= 0)
					{
						ModLogger.Info($"Backpack tier {appliedTier} ({Configuration.BackpackTiers[appliedTier].Name}) applied; opening backpack.");
					}
					if (IsOpen)
					{
						Close();
					}
					else
					{
						Open();
					}
				}
				else if (IsUnlocked)
				{
					if (IsOpen)
					{
						Close();
					}
					else
					{
						Open();
					}
				}
			}
			catch (Exception exception)
			{
				ModLogger.Error("Error toggling backpack", exception);
			}
		}

		private bool TryConsumeSelectedHotbarBackpackItem(out int appliedTier)
		{
			appliedTier = -1;
			try
			{
				PlayerInventory instance = PlayerSingleton<PlayerInventory>.Instance;
				if ((Object)(object)instance == (Object)null)
				{
					return false;
				}
				object obj = ReflectionUtils.TryGetFieldOrProperty(instance, "hotbarSlots");
				if (obj == null)
				{
					return false;
				}
				int num = ReflectionUtils.TryGetListCount(obj);
				if (num <= 0)
				{
					return false;
				}
				int selectedHotbarIndex = GetSelectedHotbarIndex(instance);
				if (selectedHotbarIndex >= 0 && selectedHotbarIndex < num && TryConsumeBackpackItemFromSlot(instance, obj, selectedHotbarIndex, out appliedTier))
				{
					return true;
				}
				for (int i = 0; i < num; i++)
				{
					if (TryConsumeBackpackItemFromSlot(instance, obj, i, out appliedTier))
					{
						return true;
					}
				}
				List<object> list = ReflectionUtils.TryGetAllListLikeMembers(instance);
				foreach (object item in list)
				{
					if (item == obj)
					{
						continue;
					}
					int num2 = ReflectionUtils.TryGetListCount(item);
					for (int j = 0; j < num2; j++)
					{
						if (TryConsumeBackpackItemFromSlot(instance, item, j, out appliedTier))
						{
							return true;
						}
					}
				}
				return false;
			}
			catch (Exception exception)
			{
				ModLogger.Error("TryConsumeSelectedHotbarBackpackItem", exception);
				return false;
			}
		}

		private bool TryConsumeBackpackItemFromSlot(object playerInventory, object slotsList, int index, out int appliedTier)
		{
			appliedTier = -1;
			object obj = ReflectionUtils.TryGetListItem(slotsList, index);
			if (obj == null)
			{
				return false;
			}
			object obj2 = ReflectionUtils.TryGetFieldOrProperty(obj, "ItemInstance");
			if (obj2 == null)
			{
				return false;
			}
			object obj3 = ReflectionUtils.TryGetFieldOrProperty(obj2, "Definition");
			if (obj3 == null)
			{
				return false;
			}
			object obj4 = ReflectionUtils.TryGetFieldOrProperty(obj3, "ID") ?? ReflectionUtils.TryGetFieldOrProperty(obj3, "id");
			string text = (obj4 as string) ?? obj4?.ToString();
			if (string.IsNullOrEmpty(text) || !text.StartsWith("PackRat_Backpack_Tier_", StringComparison.Ordinal))
			{
				return false;
			}
			if (!BackpackShopIntegration.IsBackpackTierPurchase(text, out var tierIndex) || tierIndex < 0)
			{
				return false;
			}
			ClearSlotItem(obj);
			RefreshInventoryUIAfterSlotChange(playerInventory, obj);
			if (tierIndex > _highestPurchasedTierIndex)
			{
				SetHighestPurchasedTierIndex(tierIndex);
				ApplyTierAfterPurchase(tierIndex);
				for (int i = 0; i <= tierIndex; i++)
				{
					BackpackShopIntegration.RemoveTierListingFromAllShops(i);
				}
				appliedTier = tierIndex;
			}
			return true;
		}

		private static int GetSelectedHotbarIndex(object playerInventory)
		{
			if (playerInventory == null)
			{
				return -1;
			}
			string[] array = new string[16]
			{
				"selectedSlotIndex", "SelectedSlotIndex", "selectedIndex", "SelectedIndex", "currentSlotIndex", "CurrentSlotIndex", "activeSlotIndex", "ActiveSlotIndex", "activeIndex", "ActiveIndex",
				"equippedSlotIndex", "EquippedSlotIndex", "SelectedSlot", "selectedSlot", "slotIndex", "SlotIndex"
			};
			foreach (string memberName in array)
			{
				object obj = ReflectionUtils.TryGetFieldOrProperty(playerInventory, memberName);
				if (obj != null)
				{
					if (obj is int num && num >= 0)
					{
						return num;
					}
					if (obj is byte result)
					{
						return result;
					}
					if (obj is short num2 && num2 >= 0)
					{
						return num2;
					}
					if (obj is long num3 && num3 >= 0 && num3 <= int.MaxValue)
					{
						return (int)num3;
					}
				}
			}
			return -1;
		}

		private static void ClearSlotItem(object slot)
		{
			if (slot == null || ReflectionUtils.TrySetFieldOrProperty(slot, "ItemInstance", null))
			{
				return;
			}
			Type type = slot.GetType();
			MethodInfo methodInfo = type.GetMethod("Clear", Type.EmptyTypes) ?? type.GetMethod("ClearSlot", Type.EmptyTypes);
			if (!(methodInfo != null))
			{
				return;
			}
			try
			{
				methodInfo.Invoke(slot, null);
			}
			catch
			{
			}
		}

		private static void RefreshInventoryUIAfterSlotChange(object playerInventory, object slotThatChanged)
		{
			if (slotThatChanged != null)
			{
				ReflectionUtils.TryInvokeParameterlessCallback(slotThatChanged, "onItemDataChanged", "OnItemDataChanged", "ItemDataChanged");
			}
			if (playerInventory != null)
			{
				ReflectionUtils.TryInvokeParameterlessCallback(playerInventory, "Refresh", "RefreshUI", "UpdateDisplay", "OnInventoryChanged", "NotifySlotsChanged", "Rebuild");
			}
		}

		private void ApplyCurrentTier(int tierIdx)
		{
			if (tierIdx >= 0)
			{
				int num = Configuration.Instance.TierSlotCounts[tierIdx];
				if (_storage.SlotCount != num)
				{
					ModLogger.Info($"Backpack upgraded to {Configuration.BackpackTiers[tierIdx].Name} ({num} slots).");
					UpdateSize(num);
				}
			}
		}

		public void ApplyTierAfterPurchase(int tierIdx)
		{
			if (tierIdx >= 0)
			{
				_lastTierIndex = tierIdx;
				ApplyCurrentTier(tierIdx);
			}
		}

		public void SetBackpackEnabled(bool state)
		{
			if (!state)
			{
				Close();
			}
			_backpackEnabled = state;
		}

		public void Open()
		{
			if (!_backpackEnabled)
			{
				ModLogger.Debug("Backpack open blocked: backpack disabled.");
			}
			else if (!IsUnlocked)
			{
				ModLogger.Debug($"Backpack open blocked: not unlocked (CurrentTierIndex={CurrentTierIndex}, HighestPurchased={_highestPurchasedTierIndex}). Purchase a tier at the Hardware Store.");
			}
			else if ((Object)(object)_storage == (Object)null)
			{
				ModLogger.Warn("Backpack open blocked: no storage entity.");
			}
			else if (!Singleton<ManagementClipboard>.Instance.IsEquipped && !Singleton<StorageMenu>.Instance.IsOpen && !PlayerSingleton<Phone>.Instance.IsOpen)
			{
				if (CameraLockedStateHelper.IsCameraLockedByUI())
				{
					ModLogger.Debug("Backpack blocked: player is in camera-locked UI (TV, ATM, dialogue, vehicle, etc.).");
					return;
				}
				_openTitle = CurrentTier?.Name ?? "Backpack";
				StorageMenu instance = Singleton<StorageMenu>.Instance;
				instance.SlotGridLayout.constraintCount = _storage.DisplayRowCount;
				instance.Open(_openTitle, string.Empty, (IItemSlotOwner)(object)_storage);
				_storage.SendAccessor(((NetworkBehaviour)Player.Local).NetworkObject);
			}
		}

		public void Close()
		{
			if (_backpackEnabled && IsOpen)
			{
				Singleton<StorageMenu>.Instance.CloseMenu();
				_storage.SendAccessor((NetworkObject)null);
			}
		}

		public bool ContainsItemsOfInterest(EStealthLevel maxStealthLevel)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Invalid comparison between Unknown and I4
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < _storage.ItemSlots.Count; i++)
			{
				ItemSlot val = _storage.ItemSlots[i];
				if (((val != null) ? val.ItemInstance : null) == null)
				{
					continue;
				}
				ItemInstance itemInstance = val.ItemInstance;
				ProductItemInstance val2 = (ProductItemInstance)(object)((itemInstance is ProductItemInstance) ? itemInstance : null);
				if (val2 == null)
				{
					if ((int)val.ItemInstance.Definition.legalStatus > 0)
					{
						return true;
					}
				}
				else if ((Object)(object)val2.AppliedPackaging == (Object)null || val2.AppliedPackaging.StealthLevel <= maxStealthLevel)
				{
					return true;
				}
			}
			return false;
		}

		public void Upgrade(int slotCount)
		{
			if ((slotCount >= 1 && slotCount <= 40) || 1 == 0)
			{
				int num = _storage.SlotCount + slotCount;
				if (num > 40)
				{
					ModLogger.Warn($"Cannot upgrade backpack to more than {40} slots.");
				}
				else
				{
					UpdateSize(num);
				}
			}
		}

		public void Downgrade(int slotCount, bool force = false)
		{
			if (slotCount < 1)
			{
				return;
			}
			if (!force && slotCount >= _storage.SlotCount)
			{
				ModLogger.Warn("Cannot downgrade backpack to zero slots. A minimum of one must remain.");
				return;
			}
			int num = _storage.SlotCount - slotCount;
			if (num < 1)
			{
				num = 1;
			}
			if (force)
			{
				UpdateSize(num);
				return;
			}
			bool flag = true;
			List<ItemSlot> range = _storage.ItemSlots.GetRange(num, _storage.SlotCount - num);
			for (int i = 0; i < range.Count; i++)
			{
				List<ItemSlot> list = range;
				ItemSlot val = list[new Index(i).GetOffset(list.Count)];
				if (((val != null) ? val.ItemInstance : null) != null)
				{
					ModLogger.Warn("Downgrading backpack will remove item: " + ((Object)val.ItemInstance.Definition).name);
					flag = false;
				}
			}
			if (!flag)
			{
				ModLogger.Warn("Cannot downgrade backpack due to items present in removed slots.");
			}
			else
			{
				UpdateSize(num);
			}
		}

		private void UpdateSize(int newSize)
		{
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Expected O, but got Unknown
			_storage.SlotCount = newSize;
			StorageEntity storage = _storage;
			if (1 == 0)
			{
			}
			int displayRowCount = ((newSize <= 20) ? ((int)Math.Ceiling((double)newSize / 5.0)) : ((newSize > 80) ? ((int)Math.Ceiling((double)newSize / 16.0)) : ((int)Math.Ceiling((double)newSize / 10.0))));
			if (1 == 0)
			{
			}
			storage.DisplayRowCount = displayRowCount;
			if (_storage.ItemSlots.Count > newSize)
			{
				_storage.ItemSlots.RemoveRange(newSize, _storage.ItemSlots.Count - newSize);
				return;
			}
			for (int i = _storage.ItemSlots.Count; i < newSize; i++)
			{
				ItemSlot val = new ItemSlot();
				val.onItemDataChanged = (Action)Delegate.Combine(val.onItemDataChanged, new Action(_storage.ContentsChanged));
				val.SetSlotOwner((IItemSlotOwner)(object)_storage);
			}
		}

		private void OnStartClient(bool isOwner)
		{
			if (!isOwner)
			{
				ModLogger.Info("Destroying non-local player backpack on: " + ((Object)this).name);
				Object.Destroy((Object)(object)this);
			}
			else if ((Object)(object)Instance != (Object)null)
			{
				ModLogger.Warn("Multiple instances of " + ((Object)this).name + " exist. Keeping prior instance reference.");
			}
			else
			{
				Instance = this;
				CameraLockedStateHelper.PrewarmCache();
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}
	}
}
namespace PackRat.Storage
{
	public sealed class BackpackSaveData
	{
		public string Contents { get; set; }

		public int HighestPurchasedTierIndex { get; set; } = -1;

	}
}
namespace PackRat.Shops
{
	public static class BackpackShopIntegration
	{
		[CompilerGenerated]
		private sealed class <WaitAndIntegrate>d__6 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			private int <i>5__1;

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

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

			[DebuggerHidden]
			public <WaitAndIntegrate>d__6(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

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

			private bool MoveNext()
			{
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				//IL_003a: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<i>5__1 = 0;
					break;
				case 1:
					<>1__state = -1;
					AddToAllHardwareStoresInScene();
					<i>5__1++;
					break;
				}
				if (<i>5__1 < 60)
				{
					<>2__current = (object)new WaitForSeconds(0.5f);
					<>1__state = 1;
					return true;
				}
				if (_shopsIntegrated.Count == 0)
				{
					LogHardwareStoreNotFound();
				}
				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();
			}
		}

		public const string BackpackItemIdPrefix = "PackRat_Backpack_Tier_";

		private const string HardwareStoreName = "Hardware Store";

		private static readonly string[] TierDescriptions = new string[5] { "A basic 8-slot backpack. Good for starting out.", "A compact 16-slot pack. Stays under the radar.", "24 slots. Police may search this size and above.", "32 slots. Sturdy and roomy; draws more attention.", "The largest option with 40 slots. Maximum capacity." };

		private static readonly HashSet<int> _shopsIntegrated = new HashSet<int>();

		public static void RunWhenReady()
		{
			MelonCoroutines.Start(WaitAndIntegrate());
		}

		public static bool TryAddBackpackListingsToShop(ShopInterface shop)
		{
			if ((Object)(object)shop == (Object)null)
			{
				return false;
			}
			if (!TryMatchHardwareStore(shop, out var _))
			{
				return false;
			}
			int instanceID = ((Object)shop).GetInstanceID();
			if (_shopsIntegrated.Contains(instanceID))
			{
				return true;
			}
			if (AddBackpackListings(shop))
			{
				_shopsIntegrated.Add(instanceID);
				ModLogger.Info($"BackpackShopIntegration: Added backpack tier listings to Hardware Store (instance {instanceID}).");
				return true;
			}
			ModLogger.Warn("BackpackShopIntegration: Hardware Store found but adding listings failed (see tier warnings above).");
			return false;
		}

		[IteratorStateMachine(typeof(<WaitAndIntegrate>d__6))]
		private static IEnumerator WaitAndIntegrate()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitAndIntegrate>d__6(0);
		}

		private static void AddToAllHardwareStoresInScene()
		{
			try
			{
				Type typeFromHandle = typeof(ShopInterface);
				FieldInfo field = typeFromHandle.GetField("AllShops", BindingFlags.Static | BindingFlags.Public);
				if (field != null && field.GetValue(null) is IEnumerable enumerable)
				{
					foreach (object item in enumerable)
					{
						if (item != null && TryMatchHardwareStore(item, out var shop))
						{
							TryAddBackpackListingsToShop(shop);
						}
					}
				}
				ShopInterface[] array = Utils.FindObjectsOfTypeSafe<ShopInterface>();
				if (array == null)
				{
					return;
				}
				for (int i = 0; i < array.Length; i++)
				{
					if ((Object)(object)array[i] != (Object)null && TryMatchHardwareStore(array[i], out var shop2))
					{
						TryAddBackpackListingsToShop(shop2);
					}
				}
			}
			catch (Exception exception)
			{
				ModLogger.Error("BackpackShopIntegration: AddToAllHardwareStoresInScene", exception);
			}
		}

		private static void LogHardwareStoreNotFound()
		{
			List<string> list = new List<string>();
			try
			{
				Type typeFromHandle = typeof(ShopInterface);
				FieldInfo field = typeFromHandle.GetField("AllShops", BindingFlags.Static | BindingFlags.Public);
				if (field != null)
				{
					object value = field.GetValue(null);
					if (value != null && value is IEnumerable enumerable)
					{
						foreach (object item in enumerable)
						{
							if (item != null)
							{
								string shopDisplayName = GetShopDisplayName(item);
								if (!string.IsNullOrEmpty(shopDisplayName) && !list.Contains(shopDisplayName))
								{
									list.Add(shopDisplayName);
								}
							}
						}
					}
				}
				if (list.Count == 0)
				{
					ShopInterface[] array = Utils.FindObjectsOfTypeSafe<ShopInterface>();
					if (array != null)
					{
						for (int i = 0; i < array.Length; i++)
						{
							string shopDisplayName2 = GetShopDisplayName(array[i]);
							if (!string.IsNullOrEmpty(shopDisplayName2) && !list.Contains(shopDisplayName2))
							{
								list.Add(shopDisplayName2);
							}
						}
					}
				}
			}
			catch
			{
			}
			if (list.Count > 0)
			{
				ModLogger.Warn("BackpackShopIntegration: Hardware Store not found after 30s. Shop names in game: [" + string.Join(", ", list) + "]. If your hardware store uses a different name, we can add a match for it.");
			}
			else
			{
				ModLogger.Warn("BackpackShopIntegration: Hardware Store not found after 30s (no ShopInterface instances with a name found). Shops may load later when you open them.");
			}
		}

		private static bool TryGetHardwareStore(out ShopInterface shop)
		{
			shop = null;
			try
			{
				Type typeFromHandle = typeof(ShopInterface);
				FieldInfo field = typeFromHandle.GetField("AllShops", BindingFlags.Static | BindingFlags.Public);
				if (field != null)
				{
					object value = field.GetValue(null);
					if (value != null && value is IEnumerable enumerable)
					{
						int num = 0;
						foreach (object item in enumerable)
						{
							if (item != null)
							{
								num++;
								if (TryMatchHardwareStore(item, out shop))
								{
									return true;
								}
							}
						}
					}
				}
				ShopInterface[] array = Utils.FindObjectsOfTypeSafe<ShopInterface>();
				if (array != null && array.Length != 0)
				{
					foreach (ShopInterface val in array)
					{
						if (!((Object)(object)val == (Object)null) && TryMatchHardwareStore(val, out shop))
						{
							return true;
						}
					}
				}
			}
			catch (Exception exception)
			{
				ModLogger.Error("BackpackShopIntegration: Error finding Hardware Store", exception);
			}
			return false;
		}

		private static bool TryMatchHardwareStore(object shopObj, out ShopInterface shop)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			shop = null;
			if (shopObj == null)
			{
				return false;
			}
			string shopDisplayName = GetShopDisplayName(shopObj);
			if (string.IsNullOrEmpty(shopDisplayName))
			{
				return false;
			}
			if (!string.Equals(shopDisplayName, "Hardware Store", StringComparison.OrdinalIgnoreCase) && shopDisplayName.IndexOf("Hardware", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return false;
			}
			try
			{
				shop = (ShopInterface)shopObj;
				return true;
			}
			catch
			{
				return false;
			}
		}

		private static string GetShopDisplayName(object shopObj)
		{
			if (shopObj == null)
			{
				return null;
			}
			string[] array = new string[5] { "ShopName", "shopName", "Name", "name", "DisplayName" };
			foreach (string memberName in array)
			{
				object obj = ReflectionUtils.TryGetFieldOrProperty(shopObj, memberName);
				if (obj is string text && !string.IsNullOrWhiteSpace(text))
				{
					return text.Trim();
				}
			}
			return null;
		}

		private static bool AddBackpackListings(ShopInterface shop)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			//IL_0062: 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_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)shop == (Object)null)
			{
				return false;
			}
			if (shop.Listings == null)
			{
				ModLogger.Warn("BackpackShopIntegration: Shop.Listings is null; cannot add backpack listings.");
				return false;
			}
			Configuration instance = Configuration.Instance;
			if (!LevelManagerPatch.TryGetFallbackIcon(out var texture, out var sprite))
			{
				texture = new Texture2D(2, 2);
				texture.SetPixel(0, 0, Color.white);
				texture.SetPixel(1, 0, Color.white);
				texture.SetPixel(0, 1, Color.white);
				texture.SetPixel(1, 1, Color.white);
				texture.Apply();
				sprite = Sprite.Create(texture, new Rect(0f, 0f, 2f, 2f), new Vector2(0.5f, 0.5f));
				ModLogger.Warn("BackpackShopIntegration: Fallback icon resource missing; using generated placeholder icon.");
			}
			int num = (((Object)(object)PlayerBackpack.Instance != (Object)null) ? PlayerBackpack.Instance.HighestPurchasedTierIndex : (-1));
			bool flag = false;
			bool flag2 = false;
			bool flag3 = false;
			int num2 = 0;
			int num3 = 0;
			int num4 = 0;
			for (int i = 0; i < Configuration.BackpackTiers.Length; i++)
			{
				if (i <= num || !instance.TierEnabled[i])
				{
					continue;
				}
				flag2 = true;
				string itemId = "PackRat_Backpack_Tier_" + i;
				if (ShopHasItem(shop, itemId))
				{
					flag3 = true;
					continue;
				}
				Sprite tierSprite = LevelManagerPatch.GetTierSprite(i, sprite, texture);
				StorableItemDefinition val = CreateBackpackTierDefinition(shop, i, itemId, instance, tierSprite);
				if ((Object)(object)val == (Object)null)
				{
					num2++;
					ModLogger.Warn($"BackpackShopIntegration: Tier {i} definition creation returned null.");
				}
				else if (!RegisterDefinition(val))
				{
					num3++;
					ModLogger.Warn($"BackpackShopIntegration: Could not register definition for tier {i}.");
				}
				else if (!AddListingToShop(shop, val, sprite, texture))
				{
					num4++;
					ModLogger.Warn($"BackpackShopIntegration: Could not add listing for tier {i}.");
				}
				else
				{
					flag = true;
				}
			}
			if (flag)
			{
				ModLogger.Info("BackpackShopIntegration: Added backpack tier listings to Hardware Store.");
			}
			if (!flag2 || flag3 || flag)
			{
				return true;
			}
			ModLogger.Warn($"BackpackShopIntegration: Eligible tiers found but none added. missingDef={num2}, registerFailed={num3}, listingFailed={num4}");
			return false;
		}

		private static bool ShopHasItem(ShopInterface shop, string itemId)
		{
			try
			{
				if (shop.Listings == null)
				{
					return false;
				}
				foreach (ShopListing listing in shop.Listings)
				{
					if ((Object)(object)listing?.Item != (Object)null && ((ItemDefinition)listing.Item).ID == itemId)
					{
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		private static StorableItemDefinition CreateBackpackTierDefinition(ShopInterface shop, int tierIndex, string itemId, Configuration cfg, Sprite iconSprite)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				StorableItemDefinition val = (StorableItemDefinition)ScriptableObject.CreateInstance(typeof(StorableItemDefinition));
				if ((Object)(object)val == (Object)null)
				{
					return null;
				}
				if (!ReflectionUtils.TrySetFieldOrProperty(val, "ID", itemId))
				{
					ReflectionUtils.TrySetFieldOrProperty(val, "id", itemId);
				}
				string name = Configuration.BackpackTiers[tierIndex].Name;
				if (!ReflectionUtils.TrySetFieldOrProperty(val, "Name", name))
				{
					ReflectionUtils.TrySetFieldOrProperty(val, "name", name);
				}
				if ((Object)(object)iconSprite != (Object)null)
				{
					string[] array = new string[7] { "Icon", "icon", "Sprite", "sprite", "ItemIcon", "itemIcon", "DisplayIcon" };
					foreach (string memberName in array)
					{
						if (ReflectionUtils.TrySetFieldOrProperty(val, memberName, iconSprite))
						{
							break;
						}
					}
				}
				float num = ((tierIndex < cfg.TierPrices.Length) ? cfg.TierPrices[tierIndex] : (25f + (float)tierIndex * 50f));
				ReflectionUtils.TrySetFieldOrProperty(val, "BasePurchasePrice", num);
				FullRank val2 = ((tierIndex < cfg.TierUnlockRanks.Length) ? cfg.TierUnlockRanks[tierIndex] : Configuration.BackpackTiers[tierIndex].DefaultUnlockRank);
				ReflectionUtils.TrySetFieldOrProperty(val, "RequiredRank", val2);
				ReflectionUtils.TrySetFieldOrProperty(val, "RequiresLevelToPurchase", true);
				string value = ((tierIndex < TierDescriptions.Length) ? TierDescriptions[tierIndex] : null);
				if (!string.IsNullOrEmpty(value))
				{
					string[] array2 = new string[8] { "Description", "description", "TooltipText", "tooltipText", "FlavorText", "flavorText", "ItemDescription", "itemDescription" };
					foreach (string memberName2 in array2)
					{
						if (ReflectionUtils.TrySetFieldOrProperty(val, memberName2, value))
						{
							break;
						}
					}
				}
				return val;
			}
			catch (Exception exception)
			{
				ModLogger.Error($"BackpackShopIntegration: CreateBackpackTierDefinition tier {tierIndex}", exception);
				return null;
			}
		}

		private static StorableItemDefinition CloneTemplateStorableItemDefinition(ShopInterface shop)
		{
			if (shop?.Listings == null)
			{
				return null;
			}
			try
			{
				foreach (ShopListing listing in shop.Listings)
				{
					if ((Object)(object)listing?.Item == (Object)null || !Utils.Is<StorableItemDefinition>(listing.Item, out var result) || (Object)(object)result == (Object)null)
					{
						continue;
					}
					return Object.Instantiate<StorableItemDefinition>(result);
				}
			}
			catch (Exception exception)
			{
				ModLogger.Error("BackpackShopIntegration: CloneTemplateStorableItemDefinition", exception);
			}
			return null;
		}

		private static bool RegisterDefinition(StorableItemDefinition def)
		{
			try
			{
				Registry instance = Singleton<Registry>.Instance;
				if ((Object)(object)instance == (Object)null)
				{
					return false;
				}
				MethodInfo method = ((object)instance).GetType().GetMethod("AddToRegistry", BindingFlags.Instance | BindingFlags.Public);
				if (method == null)
				{
					return false;
				}
				method.Invoke(instance, new object[1] { def });
				return true;
			}
			catch (Exception exception)
			{
				ModLogger.Error("BackpackShopIntegration: RegisterDefinition", exception);
				return false;
			}
		}

		private static bool AddListingToShop(ShopInterface shop, StorableItemDefinition def, Sprite fallbackSprite, Texture2D fallbackTexture)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			try
			{
				ShopListing val = new ShopListing
				{
					Item = def,
					name = ((ItemDefinition)def).Name
				};
				shop.Listings.Add(val);
				val.Initialize(shop);
				if (!TryInvokeShopMethod(shop, "CreateListingUI", val))
				{
					Sprite tierSprite = LevelManagerPatch.GetTierSprite(ParseTierFromItemId(((ItemDefinition)def).ID), fallbackSprite, fallbackTexture);
					CreateListingUI(shop, val, tierSprite);
				}
				TryInvokeShopMethod(shop, "RefreshUnlockStatus");
				TryInvokeShopMethod(shop, "RefreshShownItems");
				return true;
			}
			catch (Exception exception)
			{
				ModLogger.Error("BackpackShopIntegration: AddListingToShop", exception);
				return false;
			}
		}

		private static bool TryInvokeShopMethod(ShopInterface shop, string methodName, params object[] args)
		{
			try
			{
				if ((Object)(object)shop == (Object)null || string.IsNullOrEmpty(methodName))
				{
					return false;
				}
				BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
				MethodInfo[] methods = ((object)shop).GetType().GetMethods(bindingAttr);
				foreach (MethodInfo methodInfo in methods)
				{
					if (!(methodInfo == null) && string.Equals(methodInfo.Name, methodName, StringComparison.Ordinal))
					{
						ParameterInfo[] parameters = methodInfo.GetParameters();
						if (((args != null) ? args.Length : 0) == parameters.Length)
						{
							methodInfo.Invoke(shop, args);
							return true;
						}
					}
				}
			}
			catch (Exception ex)
			{
				ModLogger.Debug("BackpackShopIntegration: " + methodName + " invoke failed: " + ex.Message);
			}
			return false;
		}

		private static int ParseTierFromItemId(string itemId)
		{
			if (string.IsNullOrEmpty(itemId) || !itemId.StartsWith("PackRat_Backpack_Tier_", StringComparison.Ordinal))
			{
				return -1;
			}
			string s = itemId.Substring("PackRat_Backpack_Tier_".Length);
			int result;
			return int.TryParse(s, out result) ? result : (-1);
		}

		private static void CreateListingUI(ShopInterface shop, ShopListing listing, Sprite iconSprite)
		{
			try
			{
				object obj = ReflectionUtils.TryGetFieldOrProperty(shop, "ListingUIPrefab");
				object obj2 = ReflectionUtils.TryGetFieldOrProperty(shop, "ListingContainer");
				if (obj == null || obj2 == null)
				{
					ModLogger.Warn("BackpackShopIntegration: Shop missing ListingUIPrefab or ListingContainer.");
					return;
				}
				object obj3 = ((obj is Component) ? obj : null);
				GameObject val = ((obj3 != null) ? ((Component)obj3).gameObject : null);
				Transform val2 = (Transform)((obj2 is Transform) ? obj2 : null);
				if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
				{
					return;
				}
				GameObject val3 = Object.Instantiate<GameObject>(val, val2);
				ListingUI component = val3.GetComponent<ListingUI>();
				if ((Object)(object)component == (Object)null)
				{
					Object.Destroy((Object)(object)val3);
					return;
				}
				component.Initialize(listing);
				if ((Object)(object)iconSprite != (Object)null && (Object)(object)component.Icon != (Object)null)
				{
					component.Icon.sprite = iconSprite;
				}
				BindListingUIEvents(shop, component);
				AddToListingUICollection(shop, component);
			}
			catch (Exception exception)
			{
				ModLogger.Error("BackpackShopIntegration: CreateListingUI", exception);
			}
		}

		private static void BindListingUIEvents(ShopInterface shop, ListingUI listingUI)
		{
			try
			{
				Type typeFromHandle = typeof(ShopInterface);
				MethodInfo listingClicked = typeFromHandle.GetMethod("ListingClicked", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				MethodInfo dropdownClicked = typeFromHandle.GetMethod("DropdownClicked", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				MethodInfo entryHovered = typeFromHandle.GetMethod("EntryHovered", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				MethodInfo entryUnhovered = typeFromHandle.GetMethod("EntryUnhovered", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (listingClicked != null)
				{
					listingUI.onClicked = (Action)Delegate.Combine(listingUI.onClicked, (Action)delegate
					{
						listingClicked.Invoke(shop, new object[1] { listingUI });
					});
				}
				if (dropdownClicked != null)
				{
					listingUI.onDropdownClicked = (Action)Delegate.Combine(listingUI.onDropdownClicked, (Action)delegate
					{
						dropdownClicked.Invoke(shop, new object[1] { listingUI });
					});
				}
				if (entryHovered != null)
				{
					listingUI.hoverStart = (Action)Delegate.Combine(listingUI.hoverStart, (Action)delegate
					{
						entryHovered.Invoke(shop, new object[1] { listingUI });
					});
				}
				if (entryUnhovered != null)
				{
					listingUI.hoverEnd = (Action)Delegate.Combine(listingUI.hoverEnd, (Action)delegate
					{
						entryUnhovered.Invoke(shop, null);
					});
				}
			}
			catch (Exception exception)
			{
				ModLogger.Error("BackpackShopIntegration: BindListingUIEvents", exception);
			}
		}

		private static void AddToListingUICollection(ShopInterface shop, ListingUI listingUI)
		{
			try
			{
				FieldInfo field = typeof(ShopInterface).GetField("listingUI", BindingFlags.Instance | BindingFlags.NonPublic);
				if (!(field == null))
				{
					object value = field.GetValue(shop);
					value?.GetType().GetMethod("Add", new Type[1] { typeof(ListingUI) })?.Invoke(value, new object[1] { listingUI });
				}
			}
			catch (Exception exception)
			{
				ModLogger.Error("BackpackShopIntegration: AddToListingUICollection", exception);
			}
		}

		public static bool IsBackpackTierPurchase(string itemId, out int tierIndex)
		{
			tierIndex = ParseTierFromItemId(itemId ?? "");
			return tierIndex >= 0;
		}

		public static void RemoveTierListingFromAllShops(int tierIndex)
		{
			if (tierIndex < 0 || tierIndex >= Configuration.BackpackTiers.Length)
			{
				return;
			}
			string itemId = "PackRat_Backpack_Tier_" + tierIndex;
			List<int> list = new List<int>(_shopsIntegrated);
			foreach (int item in list)
			{
				ShopInterface val = FindShopByInstanceId(item);
				if ((Object)(object)val != (Object)null)
				{
					RemoveTierListingFromShop(val, itemId);
				}
			}
		}

		private static ShopInterface FindShopByInstanceId(int instanceId)
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			try
			{
				Type typeFromHandle = typeof(ShopInterface);
				FieldInfo field = typeFromHandle.GetField("AllShops", BindingFlags.Static | BindingFlags.Public);
				if (field != null && field.GetValue(null) is IEnumerable enumerable)
				{
					foreach (object item in enumerable)
					{
						if (item != null)
						{
							object obj = ((item is Object) ? item : null);
							if (obj != null && ((Object)obj).GetInstanceID() == instanceId)
							{
								return (ShopInterface)item;
							}
						}
					}
				}
				ShopInterface[] array = Utils.FindObjectsOfTypeSafe<ShopInterface>();
				if (array != null)
				{
					for (int i = 0; i < array.Length; i++)
					{
						if ((Object)(object)array[i] != (Object)null && ((Object)array[i]).GetInstanceID() == instanceId)
						{
							return array[i];
						}
					}
				}
			}
			catch (Exception exception)
			{
				ModLogger.Error("BackpackShopIntegration: FindShopByInstanceId", exception);
			}
			return null;
		}

		private static void RemoveTierListingFromShop(ShopInterface shop, string itemId)
		{
			if (shop?.Listings == null)
			{
				return;
			}
			try
			{
				object obj = null;
				foreach (ShopListing listing in shop.Listings)
				{
					if ((Object)(object)listing?.Item != (Object)null && ((ItemDefinition)listing.Item).ID == itemId)
					{
						obj = listing;
						break;
					}
				}
				if (obj != null)
				{
					RemoveListingFromList(shop.Listings, obj);
					RemoveAndDestroyListingUI(shop, obj);
				}
			}
			catch (Exception exception)
			{
				ModLogger.Error("BackpackShopIntegration: RemoveTierListingFromShop", exception);
			}
		}

		private static int GetListCount(object list)
		{
			if (list == null)
			{
				return 0;
			}
			object obj = ReflectionUtils.TryGetFieldOrProperty(list, "Count") ?? ReflectionUtils.TryGetFieldOrProperty(list, "count");
			if (obj is int result)
			{
				return result;
			}
			if (obj is long num)
			{
				return (int)num;
			}
			return 0;
		}

		private static void RemoveListingFromList(object list, object listing)
		{
			if (list == null || listing == null)
			{
				return;
			}
			try
			{
				list.GetType().GetMethod("Remove", new Type[1] { listing.GetType() })?.Invoke(list, new object[1] { listing });
			}
			catch (Exception exception)
			{
				ModLogger.Error("BackpackShopIntegration: RemoveListingFromList", exception);
			}
		}

		private static void RemoveAndDestroyListingUI(ShopInterface shop, object listing)
		{
			if ((Object)(object)shop == (Object)null || listing == null)
			{
				return;
			}
			try
			{
				object obj = typeof(ShopInterface).GetField("listingUI", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(shop);
				if (obj == null)
				{
					return;
				}
				object obj2 = ReflectionUtils.TryGetFieldOrProperty(obj, "Count") ?? ReflectionUtils.TryGetFieldOrProperty(obj, "count");
				int num2 = ((obj2 is int num) ? num : 0);
				if (obj2 is long num3)
				{
					num2 = (int)num3;
				}
				for (int num4 = num2 - 1; num4 >= 0; num4--)
				{
					object obj3 = (obj.GetType().GetMethod("get_Item", new Type[1] { typeof(int) }) ?? obj.GetType().GetMethod("Get", new Type[1] { typeof(int) }))?.Invoke(obj, new object[1] { num4 });
					if (obj3 != null)
					{
						object obj4 = ReflectionUtils.TryGetFieldOrProperty(obj3, "Listing") ?? ReflectionUtils.TryGetFieldOrProperty(obj3, "listing");
						if (obj4 == listing)
						{
							object obj5 = ((obj3 is Component) ? obj3 : null);
							GameObject val = ((obj5 != null) ? ((Component)obj5).gameObject : null);
							if ((Object)(object)val != (Object)null)
							{
								Object.Destroy((Object)(object)val);
							}
							obj.GetType().GetMethod("RemoveAt", new Type[1] { typeof(int) })?.Invoke(obj, new object[1] { num4 });
							break;
						}
					}
				}
			}
			catch (Exception exception)
			{
				ModLogger.Error("BackpackShopIntegration: RemoveAndDestroyListingUI", exception);
			}
		}
	}
}
namespace PackRat.Patches
{
	[HarmonyPatch(typeof(ShopInterface))]
	public static class BackpackPurchasePatch
	{
		[HarmonyPatch("ListingClicked", new Type[] { typeof(ListingUI) })]
		[HarmonyPrefix]
		public static bool ListingClicked_Prefix(ShopInterface __instance, ListingUI listingUI)
		{
			try
			{
				if ((Object)(object)listingUI == (Object)null)
				{
					return true;
				}
				object obj = ReflectionUtils.TryGetFieldOrProperty(listingUI, "Listing") ?? ReflectionUtils.TryGetFieldOrProperty(listingUI, "listing");
				if (obj == null)
				{
					return true;
				}
				object obj2 = ReflectionUtils.TryGetFieldOrProperty(obj, "Item");
				StorableItemDefinition val = (StorableItemDefinition)((obj2 is StorableItemDefinition) ? obj2 : null);
				if (val == null || ((ItemDefinition)val).ID == null || !((ItemDefinition)val).ID.StartsWith("PackRat_Backpack_Tier_", StringComparison.Ordinal))
				{
					return true;
				}
				return true;
			}
			catch (Exception exception)
			{
				ModLogger.Error("BackpackPurchasePatch: ListingClicked prefix error", exception);
				return true;
			}
		}
	}
	[HarmonyPatch(typeof(BodySearchBehaviour))]
	public static class BodySearchBehaviourPatch
	{
		[CompilerGenerated]
		private sealed class <CheckForItems>d__1 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public BodySearchBehaviour behaviour;

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

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

			[DebuggerHidden]
			public <CheckForItems>d__1(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

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

			private bool MoveNext()
			{
				//IL_0046: Unknown result type (might be due to invalid IL or missing references)
				//IL_0050: Expected O, but got Unknown
				//IL_007d: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					((NPC)behaviour.officer).DialogueHandler.ShowWorldspaceDialogue("Hold on, let me see your backpack as well.", 5f);
					<>2__current = (object)new WaitForSeconds(3f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					Singleton<BodySearchScreen>.Instance.IsOpen = false;
					behaviour.ConcludeSearch(!PlayerBackpack.Instance.ContainsItemsOfInterest(behaviour.MaxStealthLevel));
					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();
			}
		}

		[HarmonyPatch("SearchClean")]
		[HarmonyPrefix]
		public static bool SearchClean(BodySearchBehaviour __instance)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Expected O, but got Unknown
			if (!PlayerBackpack.Instance.IsUnlocked || !PlayerBackpack.Instance.IsPoliceSearchable)
			{
				return true;
			}
			Singleton<BodySearchScreen>.Instance.onSearchClear.RemoveListener(new UnityAction(__instance.SearchClean));
			Singleton<BodySearchScreen>.Instance.onSearchFail.RemoveListener(new UnityAction(__instance.SearchFail));
			Singleton<BodySearchScreen>.Instance.IsOpen = true;
			MelonCoroutines.Start(CheckForItems(__instance));
			return false;
		}

		[IteratorStateMachine(typeof(<CheckForItems>d__1))]
		private static IEnumerator CheckForItems(BodySearchBehaviour behaviour)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <CheckForItems>d__1(0)
			{
				behaviour = behaviour
			};
		}
	}
	[HarmonyPatch(typeof(Cart))]
	public static class CartPatch
	{
		[HarmonyPatch("GetWarning")]
		[HarmonyPostfix]
		public static void GetWarning(Cart __instance, ref bool __result, ref string warning)
		{
			if (PlayerBackpack.Instance.IsUnlocked && !warning.StartsWith("Vehicle") && __result)
			{
				List<ItemSlot> itemSlots = PlayerBackpack.Instance.ItemSlots;
				itemSlots.InsertRange(0, (IEnumerable<ItemSlot>)PlayerSingleton<PlayerInventory>.Instance.hotbarSlots);
				if (__instance.Shop.WillCartFit(itemSlots))
				{
					warning = "Inventory won't fit everything. Some items will be placed in your backpack.";
				}
			}
		}
	}
	[HarmonyPatch(typeof(LevelManager))]
	public static class LevelManagerPatch
	{
		[CompilerGenerated]
		private sealed class <ClientRegisterTimeout>d__9 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

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

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

			[DebuggerHidden]
			public <ClientRegisterTimeout>d__9(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

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

			private bool MoveNext()
			{
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(11f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					if (_clientRegistrationDone || (Object)(object)_pendingLevelManager == (Object)null)
					{
						return false;
					}
					ModLogger.Warn("Config sync from host did not arrive in time; registering backpack unlockables with local config.");
					RegisterBackpackUnlockables(_pendingLevelManager);
					_clientRegistrationDone = true;
					_pendingLevelManager = 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();
			}
		}

		private const string FallbackIconResourceName = "PackRat.assets.icon.png";

		private const string HardwareStoreSuffix = " (Hardware Store)";

		private static readonly string[] TierIconResourceNames = new string[5] { "PackRat.assets.rucksack.png", "PackRat.assets.smallpack.png", "PackRat.assets.duffelbag.png", "PackRat.assets.tacticalpack.png", "PackRat.assets.hikingbackpack.png" };

		private static LevelManager _pendingLevelManager;

		private static bool _clientRegistrationDone;

		private static bool _clientSubscribed;

		private static bool _resourceDiagnosticsLogged;

		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		public static void Awake(LevelManager __instance)
		{
			if ((Object)(object)__instance == (Object)null)
			{
				ModLogger.Error("LevelManager instance is null!");
			}
			else if ((Object)(object)Singleton<Lobby>.Instance != (Object)null && Singleton<Lobby>.Instance.IsInLobby && !Singleton<Lobby>.Instance.IsHost)
			{
				_pendingLevelManager = __instance;
				if (!_clientSubscribed)
				{
					_clientSubscribed = true;
					ConfigSyncManager.OnConfigSynced += OnClientConfigSynced;
				}
				MelonCoroutines.Start(ClientRegisterTimeout());
			}
			else
			{
				RegisterBackpackUnlockables(__instance);
			}
		}

		private static void OnClientConfigSynced()
		{
			if (!_clientRegistrationDone && !((Object)(object)_pendingLevelManager == (Object)null))
			{
				RegisterBackpackUnlockables(_pendingLevelManager);
				_clientRegistrationDone = true;
				_pendingLevelManager = null;
			}
		}

		[IteratorStateMachine(typeof(<ClientRegisterTimeout>d__9))]
		private static IEnumerator ClientRegisterTimeout()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ClientRegisterTimeout>d__9(0);
		}

		private static void RegisterBackpackUnlockables(LevelManager levelManager)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Expected O, but got Unknown
			if ((Object)(object)levelManager == (Object)null)
			{
				return;
			}
			if (!TryLoadTexture("PackRat.assets.icon.png", out var texture))
			{
				ModLogger.Error("Failed to load fallback backpack icon texture.");
				return;
			}
			Sprite fallbackSprite = Sprite.Create(texture, new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), new Vector2(0.5f, 0.5f));
			Configuration instance = Configuration.Instance;
			for (int i = 0; i < Configuration.BackpackTiers.Length; i++)
			{
				if (instance.TierEnabled[i])
				{
					BackpackTierDefinition backpackTierDefinition = Configuration.BackpackTiers[i];
					Sprite tierSprite = GetTierSprite(i, fallbackSprite, texture);
					string text = backpackTierDefinition.Name + " (Hardware Store)";
					Unlockable val = new Unlockable(instance.TierUnlockRanks[i], text, tierSprite);
					levelManager.AddUnlockable(val);
				}
			}
		}

		public static bool TryGetFallbackIcon(out Texture2D texture, out Sprite sprite)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			sprite = null;
			if (!TryLoadTexture("PackRat.assets.icon.png", out texture) || (Object)(object)texture == (Object)null)
			{
				return false;
			}
			sprite = Sprite.Create(texture, new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), new Vector2(0.5f, 0.5f));
			return true;
		}

		public static Sprite GetTierSprite(int tierIndex, Sprite fallbackSprite, Texture2D fallbackTexture)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			if (tierIndex < 0 || tierIndex >= TierIconResourceNames.Length)
			{
				return fallbackSprite;
			}
			if (!TryLoadTexture(TierIconResourceNames[tierIndex], out var texture))
			{
				return fallbackSprite;
			}
			return Sprite.Create(texture, new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), new Vector2(0.5f, 0.5f));
		}

		private static bool TryLoadTexture(string resourceName, out Texture2D texture)
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			texture = null;
			if (!TryGetResourceStream(resourceName, out var stream))
			{
				if (!_resourceDiagnosticsLogged)
				{
					_resourceDiagnosticsLogged = true;
					LogResourceDiagnostics();
				}
				ModLogger.Error("Failed to find embedded resource: " + resourceName);
				return false;
			}
			using (stream)
			{
				byte[] array = new byte[stream.Length];
				stream.Read(array, 0, array.Length);
				texture = new Texture2D(0, 0);
				((Texture)texture).filterMode = (FilterMode)0;
				ImageConversion.LoadImage(texture, array);
				return true;
			}
		}

		private static bool TryGetResourceStream(string resourceName, out Stream stream)
		{
			stream = null;
			if (string.IsNullOrEmpty(resourceName))
			{
				return false;
			}
			Assembly assembly = typeof(PackRat).Assembly;
			stream = assembly.GetManifestResourceStream(resourceName);
			if (stream != null)
			{
				return true;
			}
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly2 in assemblies)
			{
				if (assembly2 == null)
				{
					continue;
				}
				try
				{
					string[] manifestResourceNames = assembly2.GetManifestResourceNames();
					foreach (string text in manifestResourceNames)
					{
						if (string.Equals(text, resourceName, StringComparison.Ordinal))
						{
							stream = assembly2.GetManifestResourceStream(text);
							if (stream != null)
							{
								ModLogger.Warn("Resolved resource '" + resourceName + "' from assembly '" + assembly2.GetName().Name + "'.");
								return true;
							}
						}
					}
				}
				catch
				{
				}
			}
			return false;
		}

		private static void LogResourceDiagnostics()
		{
			try
			{
				Assembly assembly = typeof(PackRat).Assembly;
				string[] manifestResourceNames = assembly.GetManifestResourceNames();
				ModLogger.Warn($"PackRat assembly '{assembly.FullName}' resource count: {manifestResourceNames.Length}");
				for (int i = 0; i < manifestResourceNames.Length; i++)
				{
					ModLogger.Warn("PackRat resource: " + manifestResourceNames[i]);
				}
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly2 in assemblies)
				{
					if (assembly2 == null)
					{
						continue;
					}
					string[] manifestResourceNames2;
					try
					{
						manifestResourceNames2 = assembly2.GetManifestResourceNames();
					}
					catch
					{
						continue;
					}
					if (manifestResourceNames2 == null || manifestResourceNames2.Length == 0)
					{
						continue;
					}
					for (int k = 0; k < manifestResourceNames2.Length; k++)
					{
						if (manifestResourceNames2[k].IndexOf("PackRat.assets", StringComparison.OrdinalIgnoreCase) >= 0)
						{
							ModLogger.Warn("Found candidate resource '" + manifestResourceNames2[k] + "' in assembly '" + assembly2.GetName().Name + "'.");
						}
					}
				}
			}
			catch (Exception exception)
			{
				ModLogger.Error("LevelManagerPatch: resource diagnostics failed", exception);
			}
		}
	}
	[HarmonyPatch(typeof(PlayerManager))]
	public static class PlayerManagerPatch
	{
		[HarmonyPatch("TryGetPlayerData")]
		[HarmonyPostfix]
		public static void TryGetPlayerData(PlayerManager __instance, PlayerData data, ref string inventoryString)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			if (data != null)
			{
				string text = __instance.loadedPlayerDataPaths[__instance.loadedPlayerData.IndexOf(data)];
				PlayerLoader val = new PlayerLoader();
				string text2 = default(string);
				if (!((Loader)val).TryLoadFile(text, "Backpack", ref text2))
				{
					ModLogger.Warn("Failed to load player backpack data under: " + text);
				}
				else
				{
					inventoryString = inventoryString + "|||" + text2;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Player))]
	public static class PlayerPatch
	{
		[HarmonyPatch("Awake")]
		[HarmonyPrefix]
		public static void Awake(Player __instance)
		{
			if (!__instance.LocalExtraFiles.Contains("Backpack"))
			{
				ModLogger.Info("Registering backpack save file for player.");
				__instance.LocalExtraFiles.Add("Backpack");
			}
		}

		[HarmonyPatch("WriteData")]
		[HarmonyPostfix]
		public static void WriteData(Player __instance, string parentFolderPath)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			StorageEntity backpackStorage = __instance.GetBackpackStorage();
			string jSON = new ItemSet(backpackStorage.ItemSlots).GetJSON();
			int tierIndex = -1;
			if (((NetworkBehaviour)__instance).IsOwner && (Object)(object)PlayerBackpack.Instance != (Object)null)
			{
				tierIndex = PlayerBackpack.Instance.HighestPurchasedTierIndex;
			}
			else
			{
				TryReadExistingTier(parentFolderPath, out tierIndex);
			}
			BackpackSaveData value = new BackpackSaveData
			{
				Contents = jSON,
				HighestPurchasedTierIndex = tierIndex
			};
			string text = JsonHelper.SerializeObject(value);
			((ISaveable)__instance).WriteSubfile(parentFolderPath, "Backpack", text);
		}

		private static void TryReadExistingTier(string parentFolderPath, out int tierIndex)
		{
			tierIndex = -1;
			try
			{
				string path = Path.Combine(parentFolderPath, "Backpack");
				if (File.Exists(path))
				{
					string json = File.ReadAllText(path);
					BackpackSaveData backpackSaveData = JsonHelper.DeserializeObject<BackpackSaveData>(json);
					if (backpackSaveData != null)
					{
						tierIndex = backpackSaveData.HighestPurchasedTierIndex;
					}
				}
			}
			catch
			{
			}
		}

		[HarmonyPatch("Load", new Type[]
		{
			typeof(PlayerData),
			typeof(string)
		})]
		[HarmonyPrefix]
		public static void Load(Player __instance, PlayerData data, string containerPath)
		{
			string text = default(string);
			if (!__instance.Loader.TryLoadFile(containerPath, "Backpack", ref text))
			{
				return;
			}
			ModLogger.Info("Loading local backpack data.");
			try
			{
				StorageEntity backpackStorage = __instance.GetBackpackStorage();
				string text2 = text;
				int highestPurchasedTierIndex = -1;
				BackpackSaveData backpackSaveData = JsonHelper.DeserializeObject<BackpackSaveData>(text);
				if (backpackSaveData != null && backpackSaveData.Contents != null)
				{
					text2 = backpackSaveData.Contents;
					highestPurchasedTierIndex = backpackSaveData.HighestPurchasedTierIndex;
				}
				DeserializedItemSet val = default(DeserializedItemSet);
				if (!ItemSet.TryDeserialize(text2, ref val))
				{
					ModLogger.Error("Failed to deserialize backpack data.");
					return;
				}
				val.LoadTo(backpackStorage.ItemSlots);
				if (((NetworkBehaviour)__instance).IsOwner && (Object)(object)PlayerBackpack.Instance != (Object)null)
				{
					PlayerBackpack.Instance.SetHighestPurchasedTierIndex(highestPurchasedTierIndex);
				}
			}
			catch (Exception exception)
			{
				ModLogger.Error("Error loading backpack data", exception);
			}
		}

		[HarmonyPatch("LoadInventory")]
		[HarmonyPrefix]
		public static void LoadInventory(Player __instance, ref string contentsString)
		{
			if (string.IsNullOrEmpty(contentsString))
			{
				return;
			}
			if (!((NetworkBehaviour)__instance).IsOwner)
			{
				ModLogger.Info("Not the owner, skipping network backpack data load.");
				return;
			}
			string[] array = contentsString.Split(new string[1] { "|||" }, StringSplitOptions.None);
			if (array.Length < 2)
			{
				return;
			}
			contentsString = array[0];
			string text = array[1];
			ModLogger.Info("Loading backpack data from network payload.");
			try
			{
				StorageEntity backpackStorage = __instance.GetBackpackStorage();
				string text2 = text;
				int highestPurchasedTierIndex = -1;
				BackpackSaveData backpackSaveData = JsonHelper.DeserializeObject<BackpackSaveData>(text);
				if (backpackSaveData != null && backpackSaveData.Contents != null)
				{
					text2 = backpackSaveData.Contents;
					highestPurchasedTierIndex = backpackSaveData.HighestPurchasedTierIndex;
				}
				DeserializedItemSet val = default(DeserializedItemSet);
				if (!ItemSet.TryDeserialize(text2, ref val))
				{
					ModLogger.Error("Failed to deserialize network backpack data.");
					return;
				}
				val.LoadTo(backpackStorage.ItemSlots);
				if ((Object)(object)PlayerBackpack.Instance != (Object)null)
				{
					PlayerBackpack.Instance.SetHighestPurchasedTierIndex(highestPurchasedTierIndex);
				}
			}
			catch (Exception exception)
			{
				ModLogger.Error("Error loading network backpack data", exception);
			}
		}

		[HarmonyPatch("Activate")]
		[HarmonyPrefix]
		public static void Activate()
		{
			ModLogger.Info("Activating backpack.");
			PlayerBackpack.Instance?.SetBackpackEnabled(state: true);
		}

		[HarmonyPatch("Deactivate")]
		[HarmonyPrefix]
		public static void Deactivate()
		{
			ModLogger.Info("Deactivating backpack.");
			PlayerBackpack.Instance?.SetBackpackEnabled(state: false);
		}

		[HarmonyPatch("ExitAll")]
		[HarmonyPrefix]
		public static void ExitAll()
		{
			ModLogger.Info("ExitAll: disabling backpack.");
			PlayerBackpack.Instance?.SetBackpackEnabled(state: false);
		}

		[HarmonyPatch("OnDied")]
		[HarmonyPrefix]
		public static void OnDied(Player __instance)
		{
			if (((NetworkBehaviour)__instance).Owner.IsLocalClient)
			{
				ModLogger.Info("Player died, disabling backpack.");
				PlayerBackpack.Instance?.SetBackpackEnabled(state: false);
			}
		}
	}
	[HarmonyPatch(typeof(PlayerSpawner))]
	public static class PlayerSpawnerPatch
	{
		[HarmonyPatch("InitializeOnce")]
		[HarmonyPostfix]
		public static void InitializeOnce(PlayerSpawner __instance)
		{
			NetworkObject playerPrefab = __instance._playerPrefab;
			if (!Object.op_Implicit((Object)(object)playerPrefab))
			{
				ModLogger.Error("Player prefab is null!");
				return;
			}
			Player component = ((Component)playerPrefab).GetComponent<Player>();
			if ((Object)(object)component == (Object)null)
			{
				ModLogger.Error("Player prefab does not have a Player component!");
				return;
			}
			ModLogger.Info("Adding backpack storage to player prefab...");
			StorageEntity orAddComponentSafe = Utils.GetOrAddComponentSafe<StorageEntity>(((Component)component).gameObject);
			if ((Object)(object)orAddComponentSafe == (Object)null)
			{
				ModLogger.Error("Failed to get or add StorageEntity to player prefab!");
				return;
			}
			orAddComponentSafe.SlotCount = 40;
			orAddComponentSafe.DisplayRowCount = 8;
			orAddComponentSafe.StorageEntityName = "Backpack";
			orAddComponentSafe.MaxAccessDistance = float.PositiveInfinity;
			Utils.GetOrAddComponentSafe<PlayerBackpack>(component.LocalGameObject);
		}
	}
	[HarmonyPatch(typeof(ShopInterface))]
	public static class ShopInterfacePatch
	{
		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		public static void Awake(ShopInterface __instance)
		{
			BackpackShopIntegration.TryAddBackpackListingsToShop(__instance);
		}

		[HarmonyPatch("GetAvailableSlots")]
		[HarmonyPostfix]
		public static void GetAvailableSlots(ShopInterface __instance, ref List<ItemSlot> __result)
		{
			if (!PlayerBackpack.Instance.IsUnlocked)
			{
				return;
			}
			LandVehicle loadingBayVehicle = __instance.GetLoadingBayVehicle();
			if ((Object)(object)loadingBayVehicle != (Object)null && __instance.Cart.LoadVehicleToggle.isOn)
			{
				return;
			}
			int count = PlayerSingleton<PlayerInventory>.Instance.hotbarSlots.Count;
			List<ItemSlot> itemSlots = PlayerBackpack.Instance.ItemSlots;
			for (int i = 0; i < itemSlots.Count; i++)
			{
				ItemSlot val = itemSlots[i];
				if (val != null)
				{
					__result.Insert(i + count, val);
				}
			}
		}
	}
	[HarmonyPatch(typeof(StorageMenu))]
	public static class StorageMenuPatch
	{
		[HarmonyPatch("Awake")]
		[HarmonyPrefix]
		public static void Awake(StorageMenu __instance)
		{
			if (__instance.SlotsUIs.Length >= 40)
			{
				return;
			}
			RectTransform slotContainer = __instance.SlotContainer;
			ItemSlotUI obj = __instance.SlotsUIs[0];
			GameObject val = ((obj != null) ? ((Component)obj).gameObject : null);
			if ((Object)(object)val == (Object)null)
			{
				ModLogger.Error("StorageMenu prefab is null. Cannot create additional slots.");
				return;
			}
			ItemSlotUI[] array = (ItemSlotUI[])(object)new ItemSlotUI[40];
			for (int i = 0; i < 40; i++)
			{
				if (i < __instance.SlotsUIs.Length)
				{
					array[i] = __instance.SlotsUIs[i];
					continue;
				}
				GameObject val2 = Object.Instantiate<GameObject>(val, (Transform)(object)slotContainer);
				((Object)val2).name = $"{((Object)val).name} ({i})";
				val2.gameObject.SetActive(true);
				array[i] = val2.GetComponent<ItemSlotUI>();
			}
			__instance.SlotsUIs = array;
		}

		[HarmonyPatch("Open", new Type[]
		{
			typeof(string),
			typeof(string),
			typeof(IItemSlotOwner)
		})]
		[HarmonyPostfix]
		public static void Open(StorageMenu __instance, string title, string subtitle, IItemSlotOwner owner)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			float num = __instance.SlotGridLayout.cellSize.y + __instance.SlotGridLayout.spacing.y;
			__instance.CloseButton.anchoredPosition = new Vector2(0f, (float)__instance.SlotGridLayout.constraintCount * (0f - num) - __instance.CloseButton.sizeDelta.y);
			if (__instance.SlotGridLayout.constraintCount > 4)
			{
				((Transform)__instance.Container).localPosition = new Vector3(0f, (float)(__instance.SlotGridLayout.constraintCount - 4) * num, 0f);
			}
		}

		[HarmonyPatch("CloseMenu")]
		[HarmonyPrefix]
		public static void CloseMenu(StorageMenu __instance)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			((Transform)__instance.Container).localPosition = Vector3.zero;
		}
	}
}
namespace PackRat.Helpers
{
	internal static class CameraLockedStateHelper
	{
		private static Type _dialogueManagerType;

		private static Type _dialogueHandlerType;

		private static FieldInfo _dialogueHandlerActiveDialogueField;

		private static FieldInfo _shopInterfaceAllShopsField;

		private static Type[] _dealWindowTypes;

		private static bool _typesResolved;

		private static void EnsureTypesResolved()
		{
			if (_typesResolved)
			{
				return;
			}
			_typesResolved = true;
			_dialogueManagerType = ReflectionUtils.GetTypeByName("ScheduleOne.Dialogue.DialogueManager");
			_dialogueHandlerType = ReflectionUtils.GetTypeByName("ScheduleOne.Dialogue.DialogueHandler");
			if (_dialogueHandlerType != null)
			{
				_dialogueHandlerActiveDialogueField = _dialogueHandlerType.GetField("activeDialogue", BindingFlags.Static | BindingFlags.Public);
			}
			Type typeFromHandle = typeof(ShopInterface);
			_shopInterfaceAllShopsField = typeFromHandle.GetField("AllShops", BindingFlags.Static | BindingFlags.Public);
			string[] array = new string[4] { "ScheduleOne.Economy.DealWindow", "ScheduleOne.UI.DealCanvas", "ScheduleOne.UI.FreeSampleCanvas", "ScheduleOne.Economy.DealInterface" };
			List<Type> list = new List<Type>();
			string[] array2 = array;
			foreach (string typeName in array2)
			{
				Type typeByName = ReflectionUtils.GetTypeByName(typeName);
				if (typeByName != null)
				{
					list.Add(typeByName);
				}
			}
			_dealWindowTypes = list.ToArray();
		}

		public static void PrewarmCache()
		{
			EnsureTypesResolved();
		}

		public static bool IsCameraLockedByUI()
		{
			try
			{
				if (Cursor.visible)
				{
					ModLogger.Debug("Camera locked: Cursor visible (UI with mouse).");
					return true;
				}
				if (IsATMOpen())
				{
					ModLogger.Debug("Camera locked: ATM screen open.");
					return true;
				}
				if (IsCharacterCreatorOpen())
				{
					ModLogger.Debug("Camera locked: Appearance/Character Creator open.");
					return true;
				}
				if (IsCharacterCustomizationShopOpen())
				{
					ModLogger.Debug("Camera locked: Tattoo/customization shop open.");
					return true;
				}
				if (IsTVInterfaceOpen())
				{
					ModLogger.Debug("Camera locked: TV screen open.");
					return true;
				}
				if (IsShopInterfaceOpen())
				{
					ModLogger.Debug("Camera locked: Shop screen open.");
					return true;
				}
				if (IsDialogueActive())
				{
					ModLogger.Debug("Camera locked: Dialogue active.");
					return true;
				}
				if (IsInVehicle())
				{
					ModLogger.Debug("Camera locked: Player in vehicle.");
					return true;
				}
				if (IsDealOrFreeSampleOpen())
				{
					ModLogger.Debug("Camera locked: Deal or free sample screen open.");
					return true;
				}
				return false;
			}
			catch (Exception exception)
			{
				ModLogger.Error("Error checking camera-locked UI state", exception);
				return false;
			}
		}

		private static bool IsATMOpen()
		{
			try
			{
				ATMInterface val = Utils.FindObjectOfTypeSafe<ATMInterface>();
				if ((Object)(object)val == (Object)null)
				{
					return false;
				}
				object obj = ReflectionUtils.TryGetFieldOrProperty(val, "isOpen");
				bool flag = default(bool);
				int num;
				if (obj is bool)
				{
					flag = (bool)obj;
					num = 1;
				}
				else
				{
					num = 0;
				}
				return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
			}
			catch
			{
				return false;
			}
		}

		private static bool IsCharacterCreatorOpen()
		{
			try
			{
				if (Singleton<CharacterCreator>.InstanceExists)
				{
					CharacterCreator instance = Singleton<CharacterCreator>.Instance;
					if ((Object)(object)instance != (Object)null && instance.IsOpen)
					{
						return true;
					}
				}
				CharacterCreator[] array = Utils.FindObjectsOfTypeSafe<CharacterCreator>();
				if (array == null)
				{
					return false;
				}
				foreach (CharacterCreator val in array)
				{
					if ((Object)(object)val != (Object)null && val.IsOpen)
					{
						return true;
					}
				}
				return false;
			}
			catch
			{
				return false;
			}
		}

		private static bool IsCharacterCustomizationShopOpen()
		{
			try
			{
				CharacterCustomizationShop[] array = Utils.FindObjectsOfTypeSafe<CharacterCustomizationShop>();
				if (array == null)
				{
					return false;
				}
				foreach (CharacterCustomizationShop val in array)
				{
					if ((Object)(object)val == (Object)null || !((Component)val).gameObject.activeInHierarchy)
					{
						continue;
					}
					List<Canvas> allComponentsInChildrenRecursive = Utils.GetAllComponentsInChildrenRecursive<Canvas>(((Component)val).gameObject);
					if (allComponentsInChildrenRecursive == null)
					{
						continue;
					}
					for (int j = 0; j < allComponentsInChildrenRecursive.Count; j++)
					{
						Canvas val2 = allComponentsInChildrenRecursive[j];
						if ((Object)(object)val2 != (Object)null && ((Behaviour)val2).enabled && ((Component)val2).gameObject.activeInHierarchy)
						{
							return true;
						}
					}
				}
				return false;
			}
			catch
			{
				return false;
			}
		}

		private static bool IsTVInterfaceOpen()
		{
			try
			{
				TVInterface val = Utils.FindObjectOfTypeSafe<TVInterface>();
				return (Object)(object)val != (Object)null && val.IsOpen;
			}
			catch
			{
				return false;
			}
		}

		private static bool IsShopInterfaceOpen()
		{
			try
			{
				if (_shopInterfaceAllShopsField != null)
				{
					object value = _shopInterfaceAllShopsField.GetValue(null);
					if (value != null && value is IEnumerable enumerable)
					{
						bool flag = default(bool);
						foreach (object item in enumerable)
						{
							if (item != null)
							{
								object obj = ReflectionUtils.TryGetFieldOrProperty(item, "IsOpen");
								int num;
								if (obj is bool)
								{
									flag = (bool)obj;
									num = 1;
								}
								else
								{
									num = 0;
								}
								if (((uint)num & (flag ? 1u : 0u)) != 0)
								{
									return true;
								}
							}
						}
					}
				}
				ShopInterface val = Utils.FindObjectOfTypeSafe<ShopInterface>();
				if ((Object)(object)val == (Object)null)
				{
					return false;
				}
				if (ReflectionUtils.TryGetFieldOrProperty(val, "IsOpen") is bool result)
				{
					return result;
				}
				object obj2 = ReflectionUtils.TryGetFieldOrProperty(val, "isOpen");
				bool flag2 = default(bool);
				int num2;
				if (obj2 is bool)
				{
					flag2 = (bool)obj2;
					num2 = 1;
				}
				else
				{
					num2 = 0;
				}
				return (byte)((uint)num2 & (flag2 ? 1u : 0u)) != 0;
			}
			catch
			{
				return false;
			}
		}

		private static bool IsDialogueActive()
		{
			try
			{
				EnsureTypesResolved();
				if (_dialogueHandlerActiveDialogueField != null)
				{
					object value = _dialogueHandlerActiveDialogueField.GetValue(null);
					if (value != null)
					{
						return true;
					}
				}
				if (_dialogueManagerType == null)
				{
					return false;
				}
				PropertyInfo property = _dialogueManagerType.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public);
				if (property == null)
				{
					return false;
				}
				object value2 = property.GetValue(null);
				if (value2 == null)
				{
					return false;
				}
				if (ReflectionUtils.TryGetFieldOrProperty(value2, "IsActive") is bool result)
				{
					return result;
				}
				object obj = ReflectionUtils.TryGetFieldOrProperty(value2, "IsOpen");
				bool flag = default(bool);
				int num;
				if (obj is bool)
				{
					flag = (bool)obj;
					num = 1;
				}
				else
				{
					num = 0;
				}
				return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
			}
			catch
			{
				return false;
			}
		}

		private static bool IsInVehicle()
		{
			try
			{
				if ((Object)(object)Player.Local == (Object)null)
				{
					return false;
				}
				if (ReflectionUtils.TryGetFieldOrProperty(Player.Local, "IsInVehicle") is bool result)
				{
					return result;
				}
				object obj = ReflectionUtils.TryGetFieldOrProperty(Player.Local, "CurrentVehicle");
				return obj != null;
			}
			catch
			{
				return false;
			}
		}

		private static bool IsDealOrFreeSampleOpen()
		{
			try
			{
				EnsureTypesResolved();
				if (_dealWindowTypes == null || _dealWindowTypes.Length == 0)
				{
					return false;
				}
				Type[] dealWindowTypes = _dealWindowTypes;
				bool flag = default(bool);
				bool flag2 = default(bool);
				foreach (Type type in dealWindowTypes)
				{
					PropertyInfo property = type.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public);
					if (property == null)
					{
						continue;
					}
					object value = property.GetValue(null);
					if (value != null)
					{
						object obj = ReflectionUtils.TryGetFieldOrProperty(value, "IsOpen");
						int num;
						if (obj is bool)
						{
							flag = (bool)obj;
							num = 1;
						}
						else
						{
							num = 0;
						}
						if (((uint)num & (flag ? 1u : 0u)) != 0)
						{
							return true;
						}
						obj = ReflectionUtils.TryGetFieldOrProperty(value, "isOpen");
						int num2;
						if (obj is bool)
						{
							flag2 = (bool)obj;
							num2 = 1;
						}
						else
						{
							num2 = 0;
						}
						if (((uint)num2 & (flag2 ? 1u : 0u)) != 0)
						{
							return true;
						}
					}
				}
				return false;
			}
			catch
			{
				return false;
			}
		}
	}
	public static class EventHelper
	{
		private static readonly Dictionary<Action, Delegate> SubscribedActions = new Dictionary<Action, Delegate>();

		private static readonly Dictionary<Delegate, Delegate> SubscribedGenericActions = new Dictionary<Delegate, Delegate>();

		public static void AddListener(Action listener, UnityEvent unityEvent)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			if (listener != null && unityEvent != null && !SubscribedActions.ContainsKey(listener))
			{
				UnityAction val = new UnityAction(listener.Invoke);
				unityEvent.AddListener(val);
				SubscribedActions.Add(listener, (Delegate)(object)val);
			}
		}

		public static void RemoveListener(Action listener, UnityEvent unityEvent)
		{
			if (listener == null || unityEvent == null || !SubscribedActions.TryGetValue(listener, out var value))
			{
				return;
			}
			SubscribedActions.Remove(listener);
			if ((object)value != null)
			{
				UnityAction val = (UnityAction)(object)((value is UnityAction) ? value : null);
				if (val != null)
				{
					unityEvent.RemoveListener(val);
				}
			}
		}

		public static void AddListener<T>(Action<T> listener, UnityEvent<T> unityEvent)
		{
			if (listener != null && unityEvent != null && !SubscribedGenericActions.ContainsKey(listener))
			{
				UnityAction<T> val = listener.Invoke;
				unityEvent.AddListener(val);
				SubscribedGenericActions.Add(listener, (Delegate)(object)val);
			}
		}

		public static void RemoveListener<T>(Action<T> listener, UnityEvent<T> unityEvent)
		{
			if (listener != null && unityEvent != null && SubscribedGenericActions.TryGetValue(listener, out var value))
			{
				if (value is UnityAction<T> val)
				{
					unityEvent.RemoveListener(val);
				}
				SubscribedGenericActions.Remove(listener);
			}
		}
	}
	public static class JsonHelper
	{
		private static object _cachedSettings;

		private static object _cachedSettingsFormatted;

		private static bool _initializationAttempted;

		public static object GetDefaultSettings()
		{
			if (_cachedSettings != null)
			{
				return null;
			}
			if (!_initializationAttempted)
			{
				_initializationAttempted = true;
				_cachedSettings = null;
			}
			return null;
		}

		public static string SerializeObject<T>(T value)
		{
			try
			{
				return JsonConvert.SerializeObject((object)value);
			}
			catch (Exception ex)
			{
				MelonLogger.Error("[PackRat] Error serializing object to JSON: " + ex.Message);
				throw;
			}
		}

		public static T DeserializeObject<T>(string json)
		{
			try
			{
				return JsonConvert.DeserializeObject<T>(json);
			}
			catch (Exception ex)
			{
				MelonLogger.Error("[PackRat] Error deserializing JSON to " + typeof(T).Name + ": " + ex.Message);
				throw;
			}
		}

		public static void PopulateObject(string json, object target)
		{
			try
			{
				JsonConvert.PopulateObject(json, target);
			}
			catch (Exception ex)
			{
				MelonLogger.Error("[PackRat] Error populating object from JSON: " + ex.Message);
				throw;
			}
		}
	}
	public static class ModLogger
	{
		public static void Info(string message)
		{
			MelonLogger.Msg(message);
		}

		public static void Debug(string message)
		{
			MelonLogger.Msg("[DEBUG] " + message);
		}

		public static void Warn(string message)
		{
			MelonLogger.Warning(message);
		}

		public static void Error(string message)
		{
			MelonLogger.Error(message);
		}

		public static void Error(string message, Exception exception)
		{
			MelonLogger.Error(message + ": " + exception.Message);
			MelonLogger.Error("Stack trace: " + exception.StackTrace);
		}
	}
	public static class NetworkHelper
	{
		public static int GetPlayerNetworkId(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				ModLogger.Warn("Cannot get network ID - player is null");
				return -1;
			}
			if ((Object)(object)((NetworkBehaviour)player).NetworkObject == (Object)null)
			{
				ModLogger.Warn("Cannot get network ID - player " + ((Object)player).name + " has null NetworkObject");
				return -1;
			}
			return ((NetworkBehaviour)player).NetworkObject.ObjectId;
		}

		public static string GetPlayerNetworkIdString(Player player)
		{
			int playerNetworkId = GetPlayerNetworkId(player);
			if (playerNetworkId == -1)
			{
				return "";
			}
			return playerNetworkId.ToString();
		}

		public static bool HasValidNetworkObject(Player player)
		{
			return (Object)(object)player != (Object)null && (Object)(object)((NetworkBehaviour)player).NetworkObject != (Object)null;
		}
	}
	internal static class ReflectionUtils
	{
		internal static List<Type> GetDerivedClasses<TBaseClass>()
		{
			List<Type> list = new List<Type>();
			Assembly[] array = (from assembly in AppDomain.CurrentDomain.GetAssemblies()
				where !ShouldSkipAssembly(assembly)
				select assembly).ToArray();
			Assembly[] array2 = array;
			foreach (Assembly asm in array2)
			{
				foreach (Type item in SafeGetTypes(asm))
				{
					try
					{
						if (!(item == null) && typeof(TBaseClass).IsAssignableFrom(item) && item != typeof(TBaseClass) && !item.IsAbstract)
						{
							list.Add(item);
						}
					}
					catch (TypeLoadException)
					{
					}
					catch (Exception)
					{
					}
				}
			}
			return list;
		}

		internal static Type GetTypeByName(string typeName)
		{
			try
			{
				Type type = Type.GetType(typeName, throwOnError: false, ignoreCase: false);
				if (type != null)
				{
					return type;
				}
			}
			catch
			{
			}
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly item in assemblies.Where((Assembly a) => !ShouldSkipAssembly(a)))
			{
				foreach (Type item2 in SafeGetTypes(item))
				{
					if (item2 == null || (!(item2.Name == typeName) && !(item2.FullName == typeName)))
					{
						continue;
					}
					return item2;
				}
			}
			Assembly[] array = assemblies;
			foreach (Assembly asm in array)
			{
				foreach (Type item3 in SafeGetTypes(asm))
				{
					if (item3 == null || (!(item3.Name == typeName) && !(item3.FullName == typeName) && (item3.FullName == null || !item3.FullName.EndsWith("." + typeName))))
					{
						continue;
					}
					return item3;
				}
			}
			return null;
		}

		internal static bool ShouldSkipAssembly(Assembly assembly)
		{
			string fullName = assembly.FullName;
			if (string.IsNullOrEmpty(fullName))
			{
				return false;
			}
			return fullName.StartsWith("System") || fullName.StartsWith("Unity") || fullName.StartsWith("Il2Cpp") || fullName.StartsWith("mscorlib") || fullName.StartsWith("Mono.") || fullName.StartsWith("netstandard") || fullName.StartsWith("com.rlabrecque") || fullName.StartsWith("__Generated");
		}

		internal static IEnumerable<Type> SafeGetTypes(Assembly asm)
		{
			try
			{
				return asm.GetTypes();
			}
			catch (ReflectionTypeLoadException ex)
			{
				return ex.Types.Where((Type t) => t != null).Cast<Type>();
			}
			catch
			{
				return Array.Empty<Type>();
			}
		}

		internal static FieldInfo[] GetAllFields(Type type, BindingFlags bindingFlags)
		{
			List<FieldInfo> list = new List<FieldInfo>();
			while (type != null && type != typeof(object))
			{
				list.AddRange(type.GetFields(bindingFlags | BindingFlags.DeclaredOnly));
				type = type.BaseType;
			}
			return list.ToArray();
		}

		internal static MethodInfo GetMethod(Type type, string methodName, BindingFlags bindingFlags)
		{
			while (type != null && type != typeof(object))
			{
				MethodInfo method = type.GetMethod(methodName, bindingFlags);
				if (method != null)
				{
					return method;
				}
				type = type.BaseType;
			}
			return null;
		}

		internal static bool TrySetFieldOrProperty(object target, string memberName, object value)
		{
			if (target == null)
			{
				return false;
			}
			Type type = target.GetType();
			FieldInfo field = type.GetField(memberName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null)
			{
				try
				{
					if (value == null || field.FieldType.IsInstanceOfType(value))
					{
						field.SetValue(target, value);
						return true;
					}
				}
				catch
				{
				}
			}
			PropertyInfo property = type.GetProperty(memberName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (property != null && property.CanWrite)
			{
				try
				{
					if (value == null || property.PropertyType.IsInstanceOfType(value))
					{
						property.SetValue(target, value);
						return true;
					}
				}
				catch
				{
				}
			}
			return false;
		}

		internal static object TryGetFieldOrProperty(object target, string memberName)
		{
			if (target == null)
			{
				return null;
			}
			Type type = target.GetType();
			FieldInfo field = type.GetField(memberName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null)
			{
				try
				{
					return field.GetValue(target);
				}
				catch
				{
				}
			}
			PropertyInfo property = type.GetProperty(memberName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (property != null && property.CanRead)
			{
				try
				{
					return property.GetValue(target);
				}
				catch
				{
				}
			}
			return null;
		}

		internal static int TryGetListCount(object list)
		{
			if (list == null)
			{
				return 0;
			}
			Type type = list.GetType();
			PropertyInfo property = type.GetProperty("Count", BindingFlags.Instance | BindingFlags.Public);
			if (property != null && property.PropertyType == typeof(int))
			{
				try
				{
					return (int)property.GetValue(list);
				}
				catch
				{
				}
			}
			if (list is ICollection collection)
			{
				try
				{
					return collection.Count;
				}
				catch
				{
				}
			}
			return 0;
		}

		internal static object TryGetListItem(object list, int index)
		{
			if (list == null)
			{
				return null;
			}
			if (list is IList list2)
			{
				try
				{
					return list2[index];
				}
				catch
				{
					return null;
				}
			}
			Type type = list.GetType();
			MethodInfo methodInfo = type.GetMethod("get_Item", new Type[1] { typeof(int) }) ?? type.GetMethod("Get", new Type[1] { typeof(int) });
			if (methodInfo != null)
			{
				try
				{
					return methodInfo.Invoke(list, new object[1] { index });
				}
				catch
				{
				}
			}
			return null;
		}

		internal static List<object> TryGetAllListLikeMembers(object target)
		{
			List<object> list = new List<object>();
			if (target == null)
			{
				return list;
			}
			Type type = target.GetType();
			FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (FieldInfo fieldInfo in fields)
			{
				try
				{
					object value = fieldInfo.GetValue(target);
					if (value != null && TryGetListCount(value) >= 0)
					{
						list.Add(value);
					}
				}
				catch
				{
				}
			}
			PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (PropertyInfo propertyInfo in properties)
			{
				if (!propertyInfo.CanRead)
				{
					continue;
				}
				try
				{
					object value2 = propertyInfo.GetValue(target);
					if (value2 != null && TryGetListCount(value2) >= 0)
					{
						list.Add(value2);
					}
				}
				catch
				{
				}
			}
			return list;
		}

		internal static void TryInvokeParameterlessCallback(object target, params string[] possibleNames)
		{
			if (target == null)
			{
				return;
			}
			foreach (string memberName in possibleNames)
			{
				object obj = TryGetFieldOrProperty(target, memberName);
				if (obj == null)
				{
					continue;
				}
				if (obj is Delegate @delegate)
				{
					try
					{
						@delegate.DynamicInvoke(null);
						break;
					}
					catch
					{
					}
				}
				MethodInfo method = obj.GetType().GetMethod("Invoke", BindingFlags.Instance | BindingFlags.Public);
				if (method != null && method.GetParameters().Length == 0)
				{
					try
					{
						method.Invoke(obj, null);
						break;
					}
					catch
					{
					}
				}
			}
		}
	}
	public static class Il2CppListExtensions
	{
		public static IEnumerable<T> AsEnumerable<T>(this List<T> list)
		{
			return list ?? new List<T>();
		}
	}
	public static class Utils
	{
		[CompilerGenerated]
		private sealed class <WaitForNetwork>d__10 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public IEnumerator routine;

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

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

			[DebuggerHidden]
			public <WaitForNetwork>d__10(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

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

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (!InstanceFinder.IsServer && !InstanceFinder.IsClient)
				{
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				MelonCoroutines.Start(routine);
				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 <WaitForNetworkSingleton>d__12<T> : IEnumerator<object>, IEnumerator, IDisposable where T : notnull, NetworkSingleton<T>
		{
			private int <>1__state;

			private object <>2__current;

			public IEnumerator coroutine;

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

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

			[DebuggerHidden]
			public <WaitForNetworkSingleton>d__12(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

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

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					goto IL_0044;
				case 1:
					<>1__state = -1;
					goto IL_0044;
				case 2:
					{
						<>1__state = -1;
						return false;
					}
					IL_0044:
					if (!NetworkSingleton<T>.InstanceExists)
					{
						<>2__current = null;
						<>1__state = 1;
						return true;
					}
					<>2__current = coroutine;
					<>1__state = 2;
					return true;
				}
			}

			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 <WaitForNotNull>d__11 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public object obj;

			public float timeout;

			public Action onTimeout;

			public Action onFinish;

			private float <startTime>5__1;

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

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

			[DebuggerHidden]
			public <WaitForNotNull>d__11(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

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

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<startTime>5__1 = Time.time;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (obj == null)
				{
					if (!float.IsNaN(timeout) && Time.time - <startTime>5__1 > timeout)
					{
						onTimeout?.Invoke();
						return false;
					}
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				onFinish?.Invoke();
				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 <WaitForPlayer>d__9 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public IEnumerator routine;

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

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

			[DebuggerHidden]
			public <WaitForPlayer>d__9(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

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

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if ((Object)(object)Player.Local == (Object)null || (Object)(object)((Component)Player.Local).gameObject == (Object)null)
				{
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				MelonCoroutines.Start(routine);
				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();
			}
		}

		public static T GetComponentSafe<T>(GameObject gameObject) where T : Component
		{
			if ((Object)(object)gameObject == (Object)null)
			{
				return default(T);
			}
			return gameObject.GetComponent<T>();
		}

		public static T AddComponentSafe<T>(GameObject gameObject) where T : Component
		{
			if ((Object)(object)gameObject == (Object)null)
			{
				return default(T);
			}
			return gameObject.AddComponent<T>();
		}

		public static T GetOrAddComponentSafe<T>(GameObject gameObject) where T : Component
		{
			T componentSafe = GetComponentSafe<T>(gameObject);
			return componentSafe ?? AddComponentSafe<T>(gameObject);
		}

		public static T FindObjectOfTypeSafe<T>() where T : Object
		{
			return Object.FindObjectOfType<T>();
		}

		public static T[] FindObjectsOfTypeSafe<T>() where T : Object
		{
			return Object.FindObjectsOfType<T>();
		}

		public static T FindObjectByName<T>(string objectName) where T : Object
		{
			try
			{
				T[] array = Resources.FindObjectsOfTypeAll<T>();
				foreach (T val in array)
				{
					if (!(((Object)val).name != objectName))
					{
						ModLogger.Debug("Found " + typeof(T).Name + " '" + objectName + "' directly in loaded objects");
						return val;
					}
				}
				return default(T);
			}
			catch (Exception ex)
			{
				ModLogger.Error("Error finding " + typeof(T).Name + " '" + objectName + "': " + ex.Message);
				return default(T);
			}
		}

		public static List<T> GetAllComponentsInChildrenRecursive<T>(GameObject obj) where T : Component
		{
			List<T> list = new List<T>();
			if ((Object)(object)obj == (Object)null)
			{
				return list;
			}
			T[] components = obj.GetComponents<T>();
			if (components.Length != 0)
			{
				list.AddRange(components);
			}
			for (int i = 0; i < obj.transform.childCount; i++)
			{
				Transform child = obj.transform.GetChild(i);
				list.AddRange(GetAllComponentsInChildrenRecursive<T>(((Component)child).gameObject));
			}
			return list;
		}

		public static bool Is<T>(object obj, out T result) where T : class
		{
			if (obj is T val)
			{
				result = val;
				return true;
			}
			result = null;
			return false;
		}

		public static List<StorableItemDefinition> GetAllStorableItemDefinitions()
		{
			List<ItemRegister> list = Singleton<Registry>.Instance.ItemRegistry.ToList();
			List<StorableItemDefinition> list2 = new List<StorableItemDefinition>();
			foreach (ItemRegister item in list)
			{
				if (Is<StorableItemDefinition>(item.Definition, out var result))
				{
					list2.Add(result);
				}
				else
				{
					ModLogger.Warn("Definition " + ((object)item.Definition)?.GetType().FullName + " is not a StorableItemDefinition");
				}
			}
			return list2.ToList();
		}

		[IteratorStateMachine(typeof(<WaitForPlayer>d__9))]
		public static IEnumerator WaitForPlayer(IEnumerator routine)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitForPlayer>d__9(0)
			{
				routine = routine
			};
		}

		[IteratorStateMachine(typeof(<WaitForNetwork>d__10))]
		public static IEnumerator WaitForNetwork(IEnumerator routine)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitForNetwork>d__10(0)
			{
				routine = routine
			};
		}

		[IteratorStateMachine(typeof(<WaitForNotNull>d__11))]
		public static IEnumerator WaitForNotNull(object? obj, float timeout = float.NaN, Action onTimeout = null, Action onFinish = null)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitForNotNull>d__11(0)
			{
				obj = obj,
				timeout = timeout,
				onTimeout = onTimeout,
				onFinish = onFinish
			};
		}

		[IteratorStateMachine(typeof(<WaitForNetworkSingleton>d__12<>))]
		public static IEnumerator WaitForNetworkSingleton<T>(IEnumerator coroutine) where T : NetworkSingleton<T>
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitForNetworkSingleton>d__12<T>(0)
			{
				coroutine = coroutine
			};
		}
	}
}
namespace PackRat.Extensions
{
	public static class PlayerExtensions
	{
		public static StorageEntity GetBackpackStorage(this Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				throw new ArgumentNullException("player");
			}
			StorageEntity component = ((Component)player).gameObject.GetComponent<StorageEntity>();
			if ((Object)(object)component == (Object)null)
			{
				throw new InvalidOperationException("Player does not have a BackpackStorage component.");
			}
			return component;
		}
	}
}
namespace PackRat.Config
{
	public sealed class BackpackTierDefinition
	{
		public string Name { get; }

		public int DefaultSlotCount { get; }

		public bool HasPoliceSearch { get; }

		public FullRank DefaultUnlockRank { get; }

		public BackpackTierDefinition(string name, int defaultSlotCount, bool hasPoliceSearch, FullRank defaultUnlockRank)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			Name = name;
			DefaultSlotCount = defaultSlotCount;
			HasPoliceSearch = hasPoliceSearch;
			DefaultUnlockRank = defaultUnloc