Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of PackRat v1.0.2
PackRat-IL2CPP.dll
Decompiled 8 hours ago
The result has been truncated due to the large size, download it to view full contents!
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
The result has been truncated due to the large size, download it to view full contents!
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