Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of PackRat v2.0.0
PackRat-IL2CPP.dll
Decompiled 5 days 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.Globalization; 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.Connection; using Il2CppFishNet.Object; using Il2CppInterop.Runtime; using Il2CppInterop.Runtime.Attributes; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppNewtonsoft.Json; using Il2CppScheduleOne; using Il2CppScheduleOne.AvatarFramework; using Il2CppScheduleOne.AvatarFramework.Customization; using Il2CppScheduleOne.Core.Items.Framework; using Il2CppScheduleOne.DevUtilities; using Il2CppScheduleOne.Equipping; using Il2CppScheduleOne.ItemFramework; using Il2CppScheduleOne.Levelling; using Il2CppScheduleOne.Money; 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.Quests; using Il2CppScheduleOne.StationFramework; using Il2CppScheduleOne.Storage; using Il2CppScheduleOne.TV; using Il2CppScheduleOne.Tools; using Il2CppScheduleOne.UI; using Il2CppScheduleOne.UI.Handover; using Il2CppScheduleOne.UI.Items; using Il2CppScheduleOne.UI.Phone; using Il2CppScheduleOne.UI.Shop; using Il2CppScheduleOne.UI.Stations; using Il2CppScheduleOne.Variables; 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.Networking; using PackRat.Patches; using PackRat.Routing; using PackRat.Shops; using PackRat.Storage; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [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", "2.0.0", "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("Release IL2CPP")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+25e4203d29b99b673b9b9b648ed0ed7cbe82a075")] [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] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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] [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 = "2.0.0"; } public class PackRat : MelonMod { public override void OnInitializeMelon() { Configuration.Instance.Load(); 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 _equippedTierIndex = -1; private const int TierCheckIntervalFrames = 60; public static PlayerBackpack Instance { get; private set; } public int EquippedTierIndex => _equippedTierIndex; public int HighestPurchasedTierIndex => EquippedTierIndex; public int CurrentTierIndex { get { Configuration instance = Configuration.Instance; if (_equippedTierIndex < 0) { return -1; } for (int num = _equippedTierIndex; num >= 0; num--) { if (num < instance.TierEnabled.Length && instance.TierEnabled[num]) { return num; } } return -1; } } [HideFromIl2Cpp] 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 SetEquippedTierIndex(int tierIndex) { _equippedTierIndex = ((tierIndex < 0) ? (-1) : Math.Min(tierIndex, Configuration.BackpackTiers.Length - 1)); } public void SetHighestPurchasedTierIndex(int tierIndex) { SetEquippedTierIndex(tierIndex); } public void RestorePurchasedTier(int tierIndex) { SetEquippedTierIndex(tierIndex); EnsureCorrectTierApplied(); } 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..."); MelonCoroutines.Start(DeferredConfigureStorage(this)); } private static IEnumerator DeferredConfigureStorage(PlayerBackpack instance) { yield return null; if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance._storage == (Object)null)) { int tierIdx = instance.CurrentTierIndex; int slotCount = ((tierIdx >= 0) ? Configuration.Instance.TierSlotCounts[tierIdx] : Configuration.BackpackTiers[0].DefaultSlotCount); instance.UpdateSize(slotCount); instance.OnStartClient(isOwner: true); } } private void Update() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) if (IsOpen) { StorageMenuPatch.ClearStandaloneBackpackKeyboardFocusOnPointerInput(); } if (IsOpen && StorageMenuPatch.HandleStandaloneBackpackSettingsInput()) { return; } bool keyDown = Input.GetKeyDown(Configuration.Instance.ToggleKey); if (keyDown || Time.frameCount % 60 == 0) { int currentTierIndex = CurrentTierIndex; if (currentTierIndex != _lastTierIndex) { _lastTierIndex = currentTierIndex; ApplyCurrentTier(currentTierIndex); } } if (!_backpackEnabled) { return; } try { if ((IsOpen && StorageMenuPatch.HandleStandaloneBackpackKeyboardNavigation()) || !keyDown || (IsOpen && StorageMenuPatch.IsStandaloneBackpackSearchFocused())) { return; } 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; } } [HideFromIl2Cpp] 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 != _equippedTierIndex) { SetEquippedTierIndex(tierIndex); ApplyTierAfterPurchase(tierIndex); BackpackShopIntegration.RefreshBackpackListingsInAllShops(); 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) { return; } Type type = slot.GetType(); MethodInfo methodInfo = ReflectionUtils.GetMethod(type, "ClearStoredInstance", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? ReflectionUtils.GetMethod(type, "Clear", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? ReflectionUtils.GetMethod(type, "ClearSlot", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (methodInfo != null) { try { methodInfo.Invoke(slot, null); return; } catch { } } ReflectionUtils.TrySetFieldOrProperty(slot, "ItemInstance", null); } 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 || _storage.ItemSlots.Count != 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 EnsureCorrectTierApplied() { _lastTierIndex = CurrentTierIndex; if (!((Object)(object)_storage == (Object)null) && _lastTierIndex >= 0) { ApplyCurrentTier(_lastTierIndex); } } 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}, EquippedTier={_equippedTierIndex}). 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; ModLogger.Info($"[BackpackUI] PlayerBackpack.Open -> StorageMenu.Open: title='{_openTitle}', slots={_storage.ItemSlots.Count}."); BackpackStateSyncManager.BeginLocalBackpackEdit(); instance.SlotGridLayout.constraintCount = 4; instance.Open(((Il2CppObjectBase)_storage).Cast<IItemSlotOwner>(), _openTitle, string.Empty, (Action)null); _storage.SendAccessor(((NetworkBehaviour)Player.Local).NetworkObject); } } public void Close() { if (_backpackEnabled && IsOpen) { Singleton<StorageMenu>.Instance.Close(); _storage.SendAccessor((NetworkObject)null); } } public bool ContainsItemsOfInterest(EStealthLevel maxStealthLevel) { //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: 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; } ItemInstance itemInstance = val.ItemInstance; ProductItemInstance val2 = (ProductItemInstance)(object)((itemInstance is ProductItemInstance) ? itemInstance : null); if (val2 == null) { string a = (ReflectionUtils.TryGetFieldOrProperty(val.ItemInstance.Definition, "legalStatus") ?? ReflectionUtils.TryGetFieldOrProperty(val.ItemInstance.Definition, "LegalStatus"))?.ToString(); if (!string.Equals(a, "Legal", StringComparison.Ordinal)) { 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_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: 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(); int count = _storage.ItemSlots.Count; 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>()); if (_storage.ItemSlots.Count == count) { _storage.ItemSlots.Add(val); } } } 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."); Object.Destroy((Object)(object)this); } else { Instance = this; CameraLockedStateHelper.PrewarmCache(); } } private void OnDestroy() { if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } } } namespace PackRat.Storage { public static class BackpackFavorites { private static readonly HashSet<string> FavoriteDefinitionIds = new HashSet<string>(StringComparer.OrdinalIgnoreCase); public static bool IsFavorite(string definitionId) { return !string.IsNullOrWhiteSpace(definitionId) && FavoriteDefinitionIds.Contains(definitionId.Trim()); } public static bool Toggle(string definitionId) { if (string.IsNullOrWhiteSpace(definitionId)) { return false; } string item = definitionId.Trim(); if (!FavoriteDefinitionIds.Add(item)) { FavoriteDefinitionIds.Remove(item); return false; } return true; } public static void SetFavorites(IEnumerable<string> definitionIds) { FavoriteDefinitionIds.Clear(); if (definitionIds == null) { return; } foreach (string definitionId in definitionIds) { if (!string.IsNullOrWhiteSpace(definitionId)) { FavoriteDefinitionIds.Add(definitionId.Trim()); } } } public static List<string> GetSavedFavoriteIds() { return FavoriteDefinitionIds.OrderBy<string, string>((string id) => id, StringComparer.OrdinalIgnoreCase).ToList(); } } public sealed class BackpackSaveData { public string Contents { get; set; } public int EquippedTierIndex { get; set; } = -1; public int HighestPurchasedTierIndex { get; set; } = -1; public List<string> FavoriteDefinitionIds { get; set; } = new List<string>(); } } namespace PackRat.Shops { public static class BackpackShopIntegration { 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>(); private static StorableItemDefinition _safeBackpackTemplate; private static bool _loggedSafeTemplateUnavailable; private static bool _loggedBackpackDefinitionCreationFailure; private static bool _loggedListingIntegrationFailureSummary; 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(); bool flag = _shopsIntegrated.Add(instanceID); if (AddBackpackListings(shop)) { if (flag) { 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; } private static IEnumerator WaitAndIntegrate() { for (int i = 0; i < 60; i++) { yield return (object)new WaitForSeconds(0.5f); AddToAllHardwareStoresInScene(); } if (_shopsIntegrated.Count == 0) { LogHardwareStoreNotFound(); } } 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.EquippedTierIndex : (-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 (!instance.TierEnabled[i]) { RemoveTierListingFromShop(shop, "PackRat_Backpack_Tier_" + i); continue; } flag2 = true; string itemId = "PackRat_Backpack_Tier_" + i; if (i == num) { RemoveTierListingFromShop(shop, itemId); continue; } if (ShopHasItem(shop, itemId)) { flag3 = true; continue; } Sprite tierSprite = LevelManagerPatch.GetTierSprite(i, sprite, texture); StorableItemDefinition val = GetRegisteredBackpackDefinition(itemId); if ((Object)(object)val != (Object)null) { ConfigureBackpackTierDefinition(val, i, itemId, instance, tierSprite); } else { val = CreateBackpackTierDefinition(shop, i, itemId, instance, tierSprite); } if ((Object)(object)val == (Object)null) { num2++; } else if ((Object)(object)GetRegisteredBackpackDefinition(itemId) == (Object)null && !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) { _loggedListingIntegrationFailureSummary = false; ModLogger.Info("BackpackShopIntegration: Added backpack tier listings to Hardware Store."); } if (!flag2 || flag3 || flag) { _loggedListingIntegrationFailureSummary = false; return true; } if (!_loggedListingIntegrationFailureSummary) { _loggedListingIntegrationFailureSummary = true; ModLogger.Warn($"BackpackShopIntegration: Eligible tiers found but none added. missingDef={num2}, registerFailed={num3}, listingFailed={num4}"); } return false; } public static void RefreshBackpackListingsInAllShops() { AddToAllHardwareStoresInScene(); } 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 && ((BaseItemDefinition)current.Item).ID == itemId) { return true; } } } catch { } return false; } private static StorableItemDefinition CreateBackpackTierDefinition(ShopInterface shop, int tierIndex, string itemId, Configuration cfg, Sprite iconSprite) { try { StorableItemDefinition val = CreateEmptyStorableItemDefinition(); if ((Object)(object)val == (Object)null) { val = CloneSafeBackpackTemplate(shop); } if ((Object)(object)val == (Object)null && !_loggedBackpackDefinitionCreationFailure) { _loggedBackpackDefinitionCreationFailure = true; ModLogger.Warn("BackpackShopIntegration: Could not create a backpack item definition. Skipping backpack listings until a valid template can be created."); } if ((Object)(object)val == (Object)null) { return null; } ConfigureBackpackTierDefinition(val, tierIndex, itemId, cfg, iconSprite); return val; } catch (Exception exception) { ModLogger.Error($"BackpackShopIntegration: CreateBackpackTierDefinition tier {tierIndex}", exception); return null; } } private static void ConfigureBackpackTierDefinition(StorableItemDefinition def, int tierIndex, string itemId, Configuration cfg, Sprite iconSprite) { //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)def == (Object)null) { return; } ApplyBackpackDefinitionDefaults(def); if (!ReflectionUtils.TrySetFieldOrProperty(def, "ID", itemId)) { ReflectionUtils.TrySetFieldOrProperty(def, "id", itemId); } string name = Configuration.BackpackTiers[tierIndex].Name; if (!ReflectionUtils.TrySetFieldOrProperty(def, "Name", name)) { ReflectionUtils.TrySetFieldOrProperty(def, "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(def, memberName, iconSprite)) { break; } } } float num = ((tierIndex < cfg.TierPrices.Length) ? cfg.TierPrices[tierIndex] : (25f + (float)tierIndex * 50f)); ReflectionUtils.TrySetFieldOrProperty(def, "BasePurchasePrice", num); FullRank val = ((tierIndex < cfg.TierUnlockRanks.Length) ? cfg.TierUnlockRanks[tierIndex] : Configuration.BackpackTiers[tierIndex].DefaultUnlockRank); ReflectionUtils.TrySetFieldOrProperty(def, "RequiredRank", val); ReflectionUtils.TrySetFieldOrProperty(def, "RequiresLevelToPurchase", true); string value = ((tierIndex < TierDescriptions.Length) ? TierDescriptions[tierIndex] : null); if (string.IsNullOrEmpty(value)) { return; } string[] array2 = new string[8] { "Description", "description", "TooltipText", "tooltipText", "FlavorText", "flavorText", "ItemDescription", "itemDescription" }; foreach (string memberName2 in array2) { if (ReflectionUtils.TrySetFieldOrProperty(def, memberName2, value)) { break; } } } private static StorableItemDefinition GetRegisteredBackpackDefinition(string itemId) { if (string.IsNullOrWhiteSpace(itemId)) { return null; } try { ItemDefinition registeredItemDefinition = GetRegisteredItemDefinition(itemId); if ((Object)(object)registeredItemDefinition == (Object)null) { return null; } return ((Il2CppObjectBase)registeredItemDefinition).TryCast<StorableItemDefinition>(); } catch (Exception exception) { ModLogger.Error("BackpackShopIntegration: GetRegisteredBackpackDefinition", exception); return null; } } private static ItemDefinition GetRegisteredItemDefinition(string itemId) { if (string.IsNullOrWhiteSpace(itemId)) { return null; } try { if (Registry.ItemExists(itemId)) { return Registry.GetItem(itemId); } } catch { } try { Registry instance = Singleton<Registry>.Instance; if ((Object)(object)instance == (Object)null) { return null; } ItemDefinition val = FindDefinitionInRegistryList(instance.ItemRegistry, itemId); if ((Object)(object)val != (Object)null) { return val; } return FindDefinitionInRegistryList(instance.ItemsAddedAtRuntime, itemId); } catch (Exception exception) { ModLogger.Error("BackpackShopIntegration: GetRegisteredItemDefinition", exception); return null; } } private static ItemDefinition FindDefinitionInRegistryList(List<ItemRegister> registryList, string itemId) { if (registryList == null || string.IsNullOrWhiteSpace(itemId)) { return null; } for (int i = 0; i < registryList.Count; i++) { ItemRegister val = registryList[i]; if (val != null && string.Equals(val.ID, itemId, StringComparison.OrdinalIgnoreCase)) { return val.Definition; } } 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)) { StorableItemDefinition val = ((Il2CppObjectBase)current.Item).TryCast<StorableItemDefinition>(); if (!((Object)(object)val == (Object)null)) { StorableItemDefinition val2 = Object.Instantiate<StorableItemDefinition>(val); return ((Il2CppObjectBase)val2).TryCast<StorableItemDefinition>(); } } } } catch (Exception exception) { ModLogger.Error("BackpackShopIntegration: CloneTemplateStorableItemDefinition", exception); } return null; } private static StorableItemDefinition CloneSafeBackpackTemplate(ShopInterface shop) { if ((Object)(object)_safeBackpackTemplate == (Object)null) { _safeBackpackTemplate = CreateSafeBackpackTemplate(shop); if ((Object)(object)_safeBackpackTemplate == (Object)null) { if (!_loggedSafeTemplateUnavailable) { _loggedSafeTemplateUnavailable = true; ModLogger.Warn("BackpackShopIntegration: Safe backpack template is unavailable in IL2CPP. Backpack listings will retry once the shop can provide a valid storable-item template."); } return null; } } try { StorableItemDefinition val = Object.Instantiate<StorableItemDefinition>(_safeBackpackTemplate); return ((Il2CppObjectBase)val).TryCast<StorableItemDefinition>(); } catch (Exception exception) { ModLogger.Error("BackpackShopIntegration: CloneSafeBackpackTemplate", exception); return null; } } public static StorableItemDefinition CreateSafeBackpackTemplate(ShopInterface shop = null) { if ((Object)(object)_safeBackpackTemplate != (Object)null) { return _safeBackpackTemplate; } try { _safeBackpackTemplate = CreateEmptyStorableItemDefinition(); if ((Object)(object)_safeBackpackTemplate == (Object)null && (Object)(object)shop != (Object)null) { _safeBackpackTemplate = CloneTemplateStorableItemDefinition(shop); } if ((Object)(object)_safeBackpackTemplate == (Object)null) { if (!_loggedSafeTemplateUnavailable) { _loggedSafeTemplateUnavailable = true; ModLogger.Warn("BackpackShopIntegration: Could not create safe backpack template instance yet."); } return null; } ApplyBackpackDefinitionDefaults(_safeBackpackTemplate); ReflectionUtils.TrySetFieldOrProperty(_safeBackpackTemplate, "ID", "PackRat_Template"); ReflectionUtils.TrySetFieldOrProperty(_safeBackpackTemplate, "Name", "Backpack"); ReflectionUtils.TrySetFieldOrProperty(_safeBackpackTemplate, "BasePurchasePrice", 0f); ReflectionUtils.TrySetFieldOrProperty(_safeBackpackTemplate, "RequiredRank", 0); ReflectionUtils.TrySetFieldOrProperty(_safeBackpackTemplate, "RequiresLevelToPurchase", false); ReflectionUtils.TrySetFieldOrProperty(_safeBackpackTemplate, "Description", string.Empty); _loggedSafeTemplateUnavailable = false; _loggedBackpackDefinitionCreationFailure = false; _loggedListingIntegrationFailureSummary = false; ModLogger.Info("BackpackShopIntegration: Safe backpack template created successfully."); return _safeBackpackTemplate; } catch (Exception exception) { ModLogger.Error("BackpackShopIntegration: CreateSafeBackpackTemplate", exception); return null; } } private static void ApplyBackpackDefinitionDefaults(StorableItemDefinition def) { if (!((Object)(object)def == (Object)null)) { ReflectionUtils.TrySetFieldOrProperty(def, "Description", string.Empty); ReflectionUtils.TrySetEnumFieldOrProperty(def, "Category", "Storage"); ReflectionUtils.TrySetFieldOrProperty(def, "StoredItem", null); ReflectionUtils.TrySetFieldOrProperty(def, "StationItem", null); ReflectionUtils.TrySetFieldOrProperty(def, "Equippable", null); ReflectionUtils.TrySetFieldOrProperty(def, "CustomItemUI", null); ReflectionUtils.TrySetFieldOrProperty(def, "CustomInfoContent", null); ReflectionUtils.TrySetEnumFieldOrProperty(def, "legalStatus", "Legal"); ReflectionUtils.TrySetFieldOrProperty(def, "ResellMultiplier", 0.5f); ReflectionUtils.TrySetFieldOrProperty(def, "PickpocketDifficultyMultiplier", 1f); ReflectionUtils.TrySetFieldOrProperty(def, "CombatUtility", 0f); } } private static StorableItemDefinition CreateEmptyStorableItemDefinition() { try { Type val = Il2CppType.Of<StorableItemDefinition>(); if (val != (Type)null) { ScriptableObject val2 = ScriptableObject.CreateInstance(val); StorableItemDefinition val3 = ((Il2CppObjectBase)val2).TryCast<StorableItemDefinition>(); if ((Object)(object)val3 != (Object)null) { return val3; } } ScriptableObject val4 = ScriptableObject.CreateInstance("ScheduleOne.ItemFramework.StorableItemDefinition") ?? ScriptableObject.CreateInstance("Il2CppScheduleOne.ItemFramework.StorableItemDefinition") ?? ScriptableObject.CreateInstance("StorableItemDefinition"); return (val4 != null) ? ((Il2CppObjectBase)val4).TryCast<StorableItemDefinition>() : null; } catch (Exception exception) { ModLogger.Error("BackpackShopIntegration: CreateEmptyStorableItemDefinition", exception); return null; } } private static bool RegisterDefinition(StorableItemDefinition def) { try { if ((Object)(object)def == (Object)null || string.IsNullOrWhiteSpace(((BaseItemDefinition)def).ID)) { return false; } if ((Object)(object)GetRegisteredItemDefinition(((BaseItemDefinition)def).ID) != (Object)null) { ModLogger.Debug("BackpackShopIntegration: Definition '" + ((BaseItemDefinition)def).ID + "' is already registered; reusing existing definition."); return true; } 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 = ((BaseItemDefinition)def).Name }; shop.Listings.Add(val); val.Initialize(shop); if (!TryInvokeShopMethod(shop, "CreateListingUI", val)) { Sprite tierSprite = LevelManagerPatch.GetTierSprite(ParseTierFromItemId(((BaseItemDefinition)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.onAddItem = DelegateSupport.ConvertDelegate<Action>((Delegate)(Action)delegate { shop.AddItem(listingUI); }); listingUI.onRemoveItem = DelegateSupport.ConvertDelegate<Action>((Delegate)(Action)delegate { shop.RemoveItem(listingUI); }); listingUI.onDropdownClicked = DelegateSupport.ConvertDelegate<Action>((Delegate)(Action)delegate { shop.DropdownClicked(listingUI); }); listingUI.hoverStart = DelegateSupport.ConvertDelegate<Action>((Delegate)(Action)delegate { shop.EntryHovered(listingUI); }); listingUI.hoverEnd = DelegateSupport.ConvertDelegate<Action>((Delegate)(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 && ((BaseItemDefinition)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 num = ((obj2 is int num2) ? num2 : 0); if (obj2 is long num3) { num = (int)num3; } for (int num4 = num - 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.Routing { public static class SmartRoutingManager { public static bool IsEnabled => Configuration.Instance.EnableSmartRouting; public static bool ShouldPreferBackpack(ItemInstance item) { if (item == null || !IsEnabled) { return false; } string itemCategory = StorageMenuPatch.GetItemCategory(item); if (1 == 0) { } bool result = itemCategory switch { "Products" => Configuration.Instance.RouteProducts, "Seeds" => Configuration.Instance.RouteSeeds, "Mixers" => Configuration.Instance.RouteMixers, "Reagents" => Configuration.Instance.RouteReagents, _ => false, }; if (1 == 0) { } return result; } } } namespace PackRat.Patches { [HarmonyPatch(typeof(ShopInterface))] public static class BackpackPurchasePatch { [HarmonyPatch("AddItem", new Type[] { typeof(ListingUI) })] [HarmonyPrefix] public static bool AddItem_Prefix(ShopInterface __instance, ListingUI ui) { try { if ((Object)(object)ui == (Object)null) { return true; } object obj = ReflectionUtils.TryGetFieldOrProperty(ui, "Listing") ?? ReflectionUtils.TryGetFieldOrProperty(ui, "listing"); if (obj == null) { return true; } object obj2 = ReflectionUtils.TryGetFieldOrProperty(obj, "Item"); StorableItemDefinition val = null; Object val2 = (Object)((obj2 is Object) ? obj2 : null); val = (StorableItemDefinition)((val2 == null) ? ((obj2 is StorableItemDefinition) ? obj2 : null) : ((Il2CppObjectBase)val2).TryCast<StorableItemDefinition>()); if (val == null || ((BaseItemDefinition)val).ID == null || !((BaseItemDefinition)val).ID.StartsWith("PackRat_Backpack_Tier_", StringComparison.Ordinal)) { return true; } if (BackpackShopIntegration.IsBackpackTierPurchase(((BaseItemDefinition)val).ID, out var tierIndex) && (Object)(object)PlayerBackpack.Instance != (Object)null && tierIndex == PlayerBackpack.Instance.EquippedTierIndex) { ModLogger.Info($"Blocked purchase selection for currently equipped backpack tier {tierIndex}."); return false; } return true; } catch (Exception exception) { ModLogger.Error("BackpackPurchasePatch: AddItem prefix error", exception); return true; } } } [HarmonyPatch(typeof(BodySearchBehaviour))] public static class BodySearchBehaviourPatch { [HarmonyPatch("SearchClean")] [HarmonyPrefix] public static bool SearchClean(BodySearchBehaviour __instance) { if ((Object)(object)PlayerBackpack.Instance == (Object)null || !Configuration.Instance.EnableSearch || !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; } private static IEnumerator CheckForItems(BodySearchBehaviour behaviour) { ((NPC)behaviour.officer).DialogueHandler.ShowWorldspaceDialogue("Hold on, let me see your backpack as well.", 5f); yield return (object)new WaitForSeconds(3f); Singleton<BodySearchScreen>.Instance.IsOpen = false; behaviour.ConcludeSearch(!PlayerBackpack.Instance.ContainsItemsOfInterest(behaviour.MaxStealthLevel)); } } [HarmonyPatch(typeof(Cart))] public static class CartPatch { [HarmonyPatch("GetWarning")] [HarmonyPostfix] public static void GetWarning(Cart __instance, ref bool __result, ref string warning) { PlayerBackpack instance = PlayerBackpack.Instance; if (!((Object)(object)instance == (Object)null) && instance.IsUnlocked && !warning.StartsWith("Vehicle") && __result) { List<ItemSlot> itemSlots = 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(HandoverScreen))] public static class HandoverScreenPatch { private sealed class PanelState { public RectTransform BackpackContainer; public RectTransform BackpackSlotContainer; public RectTransform BackpackHeaderRoot; public RectTransform BackpackVisualRoot; public Canvas DedicatedCanvas; public RectTransform DedicatedCard; public RectTransform DedicatedGrid; public RectTransform CanvasProofMarker; public ItemSlotUI SlotPrefab; public RectTransform PagingRoot; public RectTransform VehicleContainer; public Component SourceTitleLabel; public Component SourceSubtitleLabel; public Component ClonedTitleLabel; public Component ClonedSubtitleLabel; public Component OverlayTitleLabel; public Component OverlaySubtitleLabel; public ItemSlotUI[] SlotUIs; public Button PrevButton; public Button NextButton; public Button ToggleButton; public Button DedicatedToggleButton; public RectTransform DedicatedToggleRoot; public RectTransform TransferRoot; public Button TransferButton; public Button BoundTransferButton; public Text TransferStatusLabel; public Text PageLabel; public Text VisualTitleLabel; public Text VisualMetaLabel; public Action PrevAction; public Action NextAction; public Action ToggleAction; public Action TransferAction; public LandVehicle NearbyVehicle; public Vector2 VehicleOriginalAnchoredPos; public Vector2 DoneButtonOriginalAnchorMin; public Vector2 DoneButtonOriginalAnchorMax; public Vector2 DoneButtonOriginalPivot; public Vector2 DoneButtonOriginalAnchoredPos; public Vector3 DoneButtonOriginalScale; public bool DoneButtonLayoutCaptured; public int CurrentPage; public int SlotsPerPage; public bool ShowingVehicle; public bool IsOpen; public int LastPageInputFrame; public int NextVehicleProbeFrame; public bool Initialized; public string TransferStatus; } private sealed class HandoverRequirement { public string ProductId; public string Quality; public int QualityRank; public int Remaining; } private sealed class HandoverTransferSource { public string Name; public List<ItemSlot> Slots; public int Moved; } private sealed class HeaderCandidate { public Component Label; public float LocalY; public float FontSize; } private const float VehicleMaxDistance = 20f; private const float BackpackGridScale = 0.74f; private const float BackpackContentCenterY = 125f; private static readonly Vector2 BackpackCardSize = new Vector2(380f, 450f); private const string VehicleHeaderTitle = "Vehicle"; private const string VehicleHeaderSubtitle = "This is the vehicle you last drove.\nMust be within 20 meters."; private static readonly Dictionary<int, PanelState> States = new Dictionary<int, PanelState>(); private const int HeaderReapplyFrameCount = 3; private static BackpackUiThemePalette GetCurrentBackpackThemePalette() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) Configuration instance = Configuration.Instance; return BackpackUiThemes.Get(instance.BackpackUiTheme, instance.CustomBackpackUiPrimaryColor); } public static void RefreshActiveLayouts() { try { foreach (PanelState value in States.Values) { if (value == null) { continue; } bool flag = (Object)(object)value.DedicatedCanvas != (Object)null && ((Component)value.DedicatedCanvas).gameObject.activeSelf; bool flag2 = (Object)(object)value.BackpackContainer != (Object)null && ((Component)value.BackpackContainer).gameObject.activeSelf; if (flag || flag2) { if ((Object)(object)value.DedicatedCard != (Object)null) { UpdateDedicatedOverlayLayout(FindOwningScreen(value), value); } else { ConfigureCompactBackpackLayout(FindOwningScreen(value), value); } UpdatePagingLayout(value); } } } catch (Exception exception) { ModLogger.Error("HandoverScreenPatch.RefreshActiveLayouts", exception); } } [HarmonyPatch("Start")] [HarmonyPostfix] public static void Start(HandoverScreen __instance) { try { ModLogger.Info($"[HandoverUI] Start receipt: id={((__instance != null) ? new int?(((Object)__instance).GetInstanceID()) : ((int?)null))}"); PruneDeadStates(); EnsurePanel(__instance); } catch (Exception exception) { ModLogger.Error("HandoverScreenPatch.Start", exception); } } [HarmonyPatch("Open")] [HarmonyPostfix] public static void Open(HandoverScreen __instance) { try { ModLogger.Info($"[HandoverUI] Open receipt: id={((__instance != null) ? new int?(((Object)__instance).GetInstanceID()) : ((int?)null))}, hasBackpack={HasBackpack()}"); PruneDeadStates(); if (!HasBackpack()) { HidePanelAndRestoreVehicle(__instance); return; } PanelState panelState = EnsurePanel(__instance); if (panelState != null && (!((Object)(object)panelState.BackpackContainer == (Object)null) || !((Object)(object)panelState.DedicatedCanvas == (Object)null))) { LandVehicle val = ResolveNearbyVehicleStorage(panelState, forceRefresh: true); bool hasVehicle = (Object)(object)val != (Object)null; LogVehicleSelector(val); EnsureDedicatedVehicleToggle(__instance, panelState, hasVehicle); panelState.CurrentPage = 0; panelState.SlotsPerPage = ((panelState.SlotUIs != null) ? panelState.SlotUIs.Length : 0); panelState.ShowingVehicle = false; panelState.TransferStatus = null; panelState.IsOpen = true; if ((Object)(object)panelState.DedicatedCanvas == (Object)null && (Object)(object)panelState.BackpackContainer != (Object)null) { ((Component)panelState.BackpackContainer).gameObject.SetActive(true); } if ((Object)(object)panelState.PagingRoot != (Object)null) { ((Component)panelState.PagingRoot).gameObject.SetActive((Object)(object)panelState.DedicatedCanvas == (Object)null); } UpdateBackpackHeaderTexts(panelState); ApplyVisibleStorageMode(panelState, hasVehicle); if ((Object)(object)panelState.DedicatedCanvas == (Object)null && (Object)(object)panelState.BackpackContainer != (Object)null) { ((Component)panelState.BackpackContainer).gameObject.SetActive(true); } if ((Object)(object)panelState.DedicatedCanvas == (Object)null && (Object)(object)panelState.BackpackSlotContainer != (Object)null) { ((Component)panelState.BackpackSlotContainer).gameObject.SetActive(true); } if ((Object)(object)panelState.VehicleContainer != (Object)null) { ((Component)panelState.VehicleContainer).gameObject.SetActive(false); } ApplyPrimaryHeaderForMode(__instance, panelState, panelState.ShowingVehicle); MelonCoroutines.Start(ReapplyHeaderNextFrame(__instance, panelState)); if ((Object)(object)panelState.DedicatedCanvas == (Object)null) { ApplyBackpackPage(panelState); } else { UpdateDedicatedOverlayLayout(__instance, panelState); EnsureDedicatedVehicleToggle(__instance, panelState, hasVehicle); UpdateDedicatedVehicleToggle(__instance, panelState, hasVehicle); } RebuildQuickMove(__instance, val); } } catch (Exception exception) { ModLogger.Error("HandoverScreenPatch.Open", exception); } } private static IEnumerator ReapplyHeaderNextFrame(HandoverScreen screen, PanelState panel) { if ((Object)(object)screen == (Object)null || panel == null) { yield break; } for (int i = 0; i < 3; i++) { yield return null; if ((Object)(object)screen == (Object)null || panel == null || (Object)(object)panel.BackpackContainer == (Object)null || !((Component)panel.BackpackContainer).gameObject.activeSelf || panel.ShowingVehicle) { break; } if ((Object)(object)panel.VehicleContainer != (Object)null && ((Component)panel.VehicleContainer).gameObject.activeSelf) { ((Component)panel.VehicleContainer).gameObject.SetActive(false); } ApplyPrimaryHeaderForMode(screen, panel, showingVehicle: false); } } [HarmonyPatch("Update")] [HarmonyPostfix] public static void Update(HandoverScreen __instance) { PruneDeadStates(); if ((Object)(object)__instance == (Object)null || !States.TryGetValue(((Object)__instance).GetInstanceID(), out var value)) { return; } if (value.IsOpen && !__instance.IsOpen) { ModLogger.Info("[HandoverUI] Owner screen closed outside Close(); dismissing dedicated backpack overlay."); HidePanelAndRestoreVehicle(__instance); } else { if (!value.IsOpen) { return; } if ((Object)(object)value.DedicatedCanvas != (Object)null) { if (!value.ShowingVehicle && (Object)(object)value.VehicleContainer != (Object)null && ((Component)value.VehicleContainer).gameObject.activeSelf) { ((Component)value.VehicleContainer).gameObject.SetActive(false); } UpdateDedicatedVehicleToggle(__instance, value, (Object)(object)ResolveNearbyVehicleStorage(value) != (Object)null); } else { if ((Object)(object)value.BackpackContainer == (Object)null || !((Component)value.BackpackContainer).gameObject.activeSelf || value.ShowingVehicle) { return; } if ((Object)(object)value.VehicleContainer != (Object)null && ((Component)value.VehicleContainer).gameObject.activeSelf) { ((Component)value.VehicleContainer).gameObject.SetActive(false); } ConfigureCompactBackpackLayout(__instance, value); ApplyPrimaryHeaderForMode(__instance, value, showingVehicle: false); if ((Object)(object)value.BackpackHeaderRoot != (Object)null && ((Component)value.BackpackHeaderRoot).gameObject.activeSelf) { ((Transform)value.BackpackHeaderRoot).SetAsLastSibling(); Canvas component = ((Component)value.BackpackHeaderRoot).GetComponent<Canvas>(); if ((Object)(object)component != (Object)null && component.overrideSorting && component.sortingOrder != 9999) { component.sortingOrder = 9999; } } } } } [HarmonyPatch("Close")] [HarmonyPostfix] public static void Close(HandoverScreen __instance) { //IL_013d: Unknown result type (might be due to invalid IL or missing references) try { if (States.TryGetValue(((Object)__instance).GetInstanceID(), out var value)) { ClearSlotAssignments(value); value.IsOpen = false; if ((Object)(object)value.BackpackContainer != (Object)null) { ((Component)value.BackpackContainer).gameObject.SetActive(false); } if ((Object)(object)value.PagingRoot != (Object)null) { ((Component)value.PagingRoot).gameObject.SetActive(false); } if ((Object)(object)value.DedicatedToggleRoot != (Object)null) { ((Component)value.DedicatedToggleRoot).gameObject.SetActive(false); } if ((Object)(object)value.TransferRoot != (Object)null) { ((Component)value.TransferRoot).gameObject.SetActive(false); } if ((Object)(object)value.DedicatedCanvas != (Object)null) { ((Component)value.DedicatedCanvas).gameObject.SetActive(false); } if ((Object)(object)value.CanvasProofMarker != (Object)null) { ((Component)value.CanvasProofMarker).gameObject.SetActive(false); } SetBackpackVisualVisible(value, visible: false); HideOverlayHeader(value); SetHeaderPairActive(value.SourceTitleLabel, value.SourceSubtitleLabel, active: true); if ((Object)(object)value.VehicleContainer != (Object)null) { value.VehicleContainer.anchoredPosition = value.VehicleOriginalAnchoredPos; } RestoreDoneButtonLayout(__instance, value); } } catch (Exception exception) { ModLogger.Error("HandoverScreenPatch.Close", exception); } } private static PanelState EnsurePanel(HandoverScreen screen) { //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) PruneDeadStates(); if ((Object)(object)screen == (Object)null) { return null; } int instanceID = ((Object)screen).GetInstanceID(); if (States.TryGetValue(instanceID, out var value) && value.Initialized && IsComponentAlive((Component)(object)value.BackpackContainer) && IsComponentAlive((Component)(object)value.VehicleContainer) && ((Object)(object)value.BackpackHeaderRoot == (Object)null || IsComponentAlive((Component)(object)value.BackpackHeaderRoot)) && IsComponentAlive((Component)(object)value.PagingRoot) && IsComponentAlive((Component)(object)value.PrevButton) && IsComponentAlive((Component)(object)value.NextButton) && IsComponentAlive((Component)(object)value.ToggleButton) && IsComponentAlive((Component)(object)value.PageLabel)) { RefreshHeaderBindings(value, screen); EnsureDedicatedBackpackOverlay(screen, value); return value; } PanelState panelState = value ?? new PanelState(); panelState.VehicleContainer = screen.VehicleContainer; if ((Object)(object)panelState.VehicleContainer == (Object)null) { return null; } panelState.VehicleOriginalAnchoredPos = panelState.VehicleContainer.anchoredPosition; if (!IsComponentAlive((Component)(object)panelState.BackpackContainer)) { panelState.BackpackContainer = null; } if ((Object)(object)panelState.BackpackContainer == (Object)null) { RectTransform val = Object.Instantiate<RectTransform>(panelState.VehicleContainer, ((Transform)panelState.VehicleContainer).parent); ((Object)val).name = "BackpackContainer"; ((Component)val).gameObject.SetActive(false); panelState.BackpackContainer = val; } CenterBackpackContainer(panelState); panelState.BackpackSlotContainer = FindMatchingRectTransform(panelState.BackpackContainer, screen.VehicleSlotContainer); RectTransform val2 = (((Object)(object)panelState.BackpackSlotContainer != (Object)null) ? panelState.BackpackSlotContainer : panelState.BackpackContainer); Il2CppArrayBase<ItemSlotUI> componentsInChildren = ((Component)val2).GetComponentsInChildren<ItemSlotUI>(false); if (componentsInChildren == null || componentsInChildren.Length == 0) { componentsInChildren = ((Component)val2).GetComponentsInChildren<ItemSlotUI>(true); } ItemSlotUI dedicatedSlotTemplate = GetDedicatedSlotTemplate((componentsInChildren != null && componentsInChildren.Length > 0) ? componentsInChildren[0] : null); if ((Object)(object)panelState.DedicatedCanvas == (Object)null) { panelState.SlotUIs = Il2CppArrayBase<ItemSlotUI>.op_Implicit(componentsInChildren); panelState.SlotPrefab = dedicatedSlotTemplate; } else if ((Object)(object)panelState.SlotPrefab == (Object)null) { panelState.SlotPrefab = dedicatedSlotTemplate; } RefreshHeaderBindings(panelState, screen); EnsureCanvasProofMarker(screen, panelState); EnsureDedicatedBackpackOverlay(screen, panelState); if ((Object)(object)panelState.DedicatedCard == (Object)null) { EnsureBackpackVisuals(panelState); ConfigureCompactBackpackLayout(screen, panelState); } EnsurePagingControls(panelState); panelState.Initialized = true; States[instanceID] = panelState; return panelState; } private static void EnsureCanvasProofMarker(HandoverScreen screen, PanelState state) { //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Expected O, but got Unknown //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)((screen != null) ? screen.Canvas : null) == (Object)null || state == null) { ModLogger.Warn("[HandoverUI] Canvas proof skipped: HandoverScreen.Canvas was null."); return; } Transform transform = ((Component)screen.Canvas).transform; RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null); if ((Object)(object)val == (Object)null) { ModLogger.Warn("[HandoverUI] Canvas proof skipped: canvas root was not a RectTransform."); return; } RectTransform val2 = state.CanvasProofMarker; if ((Object)(object)val2 == (Object)null) { GameObject val3 = new GameObject("PackRat_HandoverCanvasProof"); val2 = val3.AddComponent<RectTransform>(); ((Transform)val2).SetParent((Transform)(object)val, false); Image val4 = val3.AddComponent<Image>(); ((Graphic)val4).color = Color32.op_Implicit(new Color32((byte)217, (byte)56, (byte)168, (byte)245)); ((Graphic)val4).raycastTarget = false; GameObject val5 = new GameObject("Label"); RectTransform val6 = val5.AddComponent<RectTransform>(); ((Transform)val6).SetParent((Transform)(object)val2, false); val6.anchorMin = Vector2.zero; val6.anchorMax = Vector2.one; val6.offsetMin = Vector2.zero; val6.offsetMax = Vector2.zero; Text val7 = val5.AddComponent<Text>(); val7.text = "PACKRAT HANDOVER CANVAS RECEIPT"; val7.font = ResolveUiFont((Transform)(object)val); val7.fontSize = 16; val7.fontStyle = (FontStyle)1; val7.alignment = (TextAnchor)4; ((Graphic)val7).color = Color.white; ((Graphic)val7).raycastTarget = false; state.CanvasProofMarker = val2; } val2.anchorMin = new Vector2(0.5f, 0.5f); val2.anchorMax = new Vector2(0.5f, 0.5f); val2.pivot = new Vector2(0.5f, 0.5f); val2.anchoredPosition = new Vector2(0f, 300f); val2.sizeDelta = new Vector2(440f, 42f); ((Transform)val2).SetAsLastSibling(); ((Component)val2).gameObject.SetActive(true); DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(71, 5); defaultInterpolatedStringHandler.AppendLiteral("[HandoverUI] Canvas proof active: canvas="); defaultInterpolatedStringHandler.AppendFormatted(((Object)screen.Canvas).name); defaultInterpolatedStringHandler.AppendLiteral(", mode="); defaultInterpolatedStringHandler.AppendFormatted<RenderMode>(screen.Canvas.renderMode); defaultInterpolatedStringHandler.AppendLiteral(", rect="); Rect rect = val.rect; defaultInterpolatedStringHandler.AppendFormatted(((Rect)(ref rect)).width, "0"); defaultInterpolatedStringHandler.AppendLiteral("x"); rect = val.rect; defaultInterpolatedStringHandler.AppendFormatted(((Rect)(ref rect)).height, "0"); defaultInterpolatedStringHandler.AppendLiteral(", markerParent="); Transform parent = ((Transform)val2).parent; defaultInterpolatedStringHandler.AppendFormatted((parent != null) ? ((Object)parent).name : null); ModLogger.Info(defaultInterpolatedStringHandler.ToStringAndClear()); } private static void PruneDeadStates() { if (States.Count == 0) { return; } List<int> list = new List<int>(); foreach (KeyValuePair<int, PanelState> state in States) { PanelState value = state.Value; if (value == null) { list.Add(state.Key); } else if (!IsComponentAlive((Component)(object)value.VehicleContainer) && !IsComponentAlive((Component)(object)value.BackpackContainer) && !IsComponentAlive((Component)(object)value.PagingRoot) && !IsComponentAlive((Component)(object)value.BackpackHeaderRoot)) { list.Add(state.Key); } } for (int i = 0; i < list.Count; i++) { States.Remove(list[i]); } } private static void RefreshHeaderBindings(PanelState state, HandoverScreen screen) { if (state != null) { ResolveLabels(state, screen); EnsureBackpackHeader(state); } } private static void ResolveLabels(PanelState state, HandoverScreen screen) { ResolveHeaderPairInContainer(state.VehicleContainer, (Transform)(object)((screen != null) ? screen.VehicleSlotContainer : null), null, null, out state.SourceTitleLabel, out state.SourceSubtitleLabel); ResolveHeaderPairInContainer(state.BackpackContainer, (Transform)(object)state.BackpackSlotContainer, (Transform)(object)state.PagingRoot, (Transform)(object)state.BackpackHeaderRoot, out state.ClonedTitleLabel, out state.ClonedSubtitleLabel); if (IsUnderTransform(state.ClonedTitleLabel, (Transform)(object)state.BackpackVisualRoot)) { state.ClonedTitleLabel = null; } if (IsUnderTransform(state.ClonedSubtitleLabel, (Transform)(object)state.BackpackVisualRoot)) { state.ClonedSubtitleLabel = null; } } private static void ResolveHeaderPairInContainer(RectTransform container, Transform slotContainer, Transform pagingRoot, Transform overlayRoot, out Component titleLabel, out Component subtitleLabel) { titleLabel = null; subtitleLabel = null; if ((Object)(object)container == (Object)null) { return; } Il2CppArrayBase<Component> componentsInChildren = ((Component)container).GetComponentsInChildren<Component>(true); List<Component> list = new List<Component>(); for (int i = 0; i < componentsInChildren.Length; i++) { Component val = componentsInChildren[i]; if (!((Object)(object)val == (Object)null) && IsTextLikeComponent(val) && !IsUnderTransform(val, slotContainer) && !IsUnderTransform(val, pagingRoot) && !IsUnderTransform(val, overlayRoot)) { list.Add(val); } } if (list.Count == 0) { return; } titleLabel = FindNamedHeaderLabel(container, slotContainer, pagingRoot, overlayRoot, "Title"); subtitleLabel = FindNamedHeaderLabel(container, slotContainer, pagingRoot, overlayRoot, "Subtitle"); foreach (Component item in list) { string text = NormalizeLabelText(GetLabelText(item)); if ((Object)(object)titleLabel == (Object)null && text.Equals("Vehicle", StringComparison.OrdinalIgnoreCase)) { titleLabel = item; } else if ((Object)(object)subtitleLabel == (Object)null && (text.Contains("vehicle you last drove", StringComparison.OrdinalIgnoreCase) || text.Contains("within 20 meters", StringComparison.OrdinalIgnoreCase))) { subtitleLabel = item; } } if ((Object)(object)titleLabel != (Object)null && (Object)(object)subtitleLabel != (Object)null) { return; } List<HeaderCandidate> list2 = new List<HeaderCandidate>(list.Count); for (int j = 0; j < list.Count; j++) { Component val2 = list[j]; list2.Add(new HeaderCandidate { Label = val2, LocalY = GetLocalY(container, val2), FontSize = GetFontSize(val2) }); } list2.Sort(CompareHeaderCandidates); if ((Object)(object)titleLabel == (Object)null && list2.Count > 0) { titleLabel = list2[0].Label; } if (!((Object)(object)subtitleLabel == (Object)null)) { return; } for (int k = 0; k < list2.Count; k++) { Component label = list2[k].Label; if (!((Object)(object)label == (Object)null) && !((Object)(object)label == (Object)(object)titleLabel)) { subtitleLabel = label; break; } } } private static Component FindNamedHeaderLabel(RectTransform container, Transform slotContainer, Transform pagingRoot, Transform overlayRoot, string targetName) { if ((Object)(object)container == (Object)null || string.IsNullOrEmpty(targetName)) { return null; } Il2CppArrayBase<Transform> componentsInChildren = ((Component)container).GetComponentsInChildren<Transform>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Transform val = componentsInChildren[i]; if (!((Object)(object)val == (Object)null) && string.Equals(((Object)val).name, targetName, StringComparison.OrdinalIgnoreCase) && (!((Object)(object)slotContainer != (Object)null) || (!((Object)(object)val == (Object)(object)slotContainer) && !val.IsChildOf(slotContainer))) && (!((Object)(object)pagingRoot != (Object)null) || (!((Object)(object)val == (Object)(object)pagingRoot) && !val.IsChildOf(pagingRoot))) && (!((Object)(object)overlayRoot != (Object)null) || (!((Object)(object)val == (Object)(object)overlayRoot) && !val.IsChildOf(overlayRoot)))) { Component textLikeComponent = GetTextLikeComponent(((Component)val).gameObject); if ((Object)(object)textLikeComponent != (Object)null) { return textLikeComponent; } Component val2 = FindFirstTextLikeInSubtree(val); if ((Object)(object)val2 != (Object)null) { return val2; } } } return null; } private static Component FindFirstTextLikeInSubtree(Transform root) { if ((Object)(object)root == (Object)null) { return null; } Il2CppArrayBase<Component> componentsInChildren = ((Component)root).GetComponentsInChildren<Component>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Component val = componentsInChildren[i]; if ((Object)(object)val != (Object)null && IsTextLikeComponent(val)) { return val; } } return null; } private static int CompareHeaderCandidates(HeaderCandidate left, HeaderCandidate right) { if (left == right) { return 0; } if (left == null) { return 1; } if (right == null) { return -1; } int num = right.LocalY.CompareTo(left.LocalY); if (num != 0) { return num; } return right.FontSize.CompareTo(left.FontSize); } private static float GetLocalY(RectTransform container, Component component) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)container == (Object)null || (Object)(object)component == (Object)null || (Object)(object)component.transform == (Object)null) { return float.MinValue; } try { Vector3 val = ((Transform)container).InverseTransformPoint(component.transform.position); return val.y; } catch { return float.MinValue; } } private static float GetFontSize(Component label) { if ((Object)(object)label == (Object)null) { return 0f; } TextMeshProUGUI val = (TextMeshProUGUI)(object)((label is TextMeshProUGUI) ? label : null); if (val != null) { try { return ((TMP_Text)val).fontSize; } catch { } } Text val2 = (Text)(object)((label is Text) ? label : null); if (val2 != null) { return val2.fontSize; } object obj2 = ReflectionUtils.TryGetFieldOrProperty(label, "fontSize"); if (obj2 is float result) { return result; } if (obj2 is int num) { return num; } return 0f; } private static Component GetTextLikeComponent(GameObject gameObject) { if ((Object)(object)gameObject == (Object)null) { return null; } TextMeshProUGUI tmpLabel = GetTmpLabel(gameObject); if ((Object)(object)tmpLabel != (Object)null) { return (Component)(object)tmpLabel; } Text componentSafe = Utils.GetComponentSafe<Text>(gameObject); if ((Object)(object)componentSafe != (Object)null) { return (Component)(object)componentSafe; } Il2CppArrayBase<Component> components = gameObject.GetComponents<Component>(); for (int i = 0; i < components.Length; i++) { Component val = components[i]; if ((Object)(object)val != (Object)null && IsTextLikeComponent(val)) { return val; } } return null; } private static void EnsureBackpackHeader(PanelState state) { //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Expected O, but got Unknown if ((Object)(object)state?.BackpackContainer == (Object)null || (Object)(object)state.SourceTitleLabel == (Object)null || (Object)(object)state.SourceSubtitleLabel == (Object)null) { return; } RectTransform backpackContainer = state.BackpackContainer; RectTransform val = null; if ((Object)(object)state.BackpackHeaderRoot != (Object)null && IsComponentAlive((Component)(object)state.BackpackHeaderRoot)) { val = state.BackpackHeaderRoot; } if ((Object)(object)val != (Object)null && (Object)(object)((Transform)val).parent != (Object)(object)backpackContainer) { ((Transform)val).SetParent((Transform)(object)backpackContainer, false); } if ((Object)(object)val == (Object)null) { Transform val2 = ((Transform)backpackContainer).Find("PackRat_BackpackHeader"); val = (RectTransform)(object)((val2 is RectTransform) ? val2 : null); } if ((Object)(object)val == (Object)null) { GameObject val3 = new GameObject("PackRat_BackpackHeader"); val = val3.AddComponent<RectTransform>(); ((Transform)val).SetParent((Transform)(object)backpackContainer, false); } state.BackpackHeaderRoot = val; EnsureIgnoredByLayout(val); ResetHeaderOverlayRoot(val); state.OverlayTitleLabel = EnsureOverlayLabel(val, "PackRat_BackpackTitle", state.SourceTitleLabel); state.OverlaySubtitleLabel = EnsureOverlayLabel(val, "PackRat_BackpackSubtitle", state.SourceSubtitleLabel); UpdateBackpackHeaderLayout(state); if (TryGetGameObject((Component)(object)val, out var gameObject) && TryGetGameObject((Component)(object)backpackContainer, out var gameObject2)) { SetLayerRecursively(gameObject, gameObject2.layer); ((Transform)val).SetAsLastSibling(); Canvas componentInParent = ((Component)backpackContainer).GetComponentInParent<Canvas>(); Canvas val4 = gameObject.GetComponent<Canvas>(); if ((Object)(object)val4 == (Object)null) { val4 = gameObject.AddComponent<Canvas>(); } val4.overrideSorting = true; if ((Object)(object)componentInParent != (Object)null) { val4.sortingLayerID = componentInParent.sortingLayerID; val4.sortingOrder = componentInParent.sortingOrder + 210; } else { val4.sortingOrder = 5010; } } UpdateBackpackHeaderTexts(state); } private static void UpdateBackpackHeaderLayout(PanelState state) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)state?.BackpackHeaderRoot == (Object)null) && !((Object)(object)state.BackpackContainer == (Object)null)) { RectTransform backpackHeaderRoot = state.BackpackHeaderRoot; EnsureIgnoredByLayout(backpackHeaderRoot); backpackHeaderRoot.anchorMin = new Vector2(0.5f, 1f); backpackHeaderRoot.anchorMax = new Vector2(0.5f, 1f); backpackHeaderRoot.pivot = new Vector2(0.5f, 1f); backpackHeaderRoot.anchoredPosition = new Vector2(0f, -8f); ((Transform)backpackHeaderRoot).localScale = Vector3.one; } } private static void ResetHeaderOverlayRoot(RectTransform headerRoot) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0084: 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) if (!((Object)(object)headerRoot == (Object)null)) { headerRoot.anchorMin = new Vector2(0.5f, 0.5f); headerRoot.anchorMax = new Vector2(0.5f, 0.5f); headerRoot.pivot = new Vector2(0.5f, 0.5f); headerRoot.anchoredPosition3D = Vector3.zero; ((Transform)headerRoot).localRotation = Quaternion.identity; ((Transform)headerRoot).localScale = Vector3.one; headerRoot.sizeDelta = Vector2.zero; headerRoot.offsetMin = Vector2.zero; headerRoot.offsetMax = Vector2.zero; } } private static Component EnsureOverlayLabel(RectTransform parent, string name, Component sourceLabel) { if ((Object)(object)parent == (Object)null || (Object)(object)sourceLabel == (Object)null) { return null; } Transform val = ((Transform)parent).Find(name); Component val2 = null; if ((Object)(object)val != (Object)null) { val2 = GetTextLikeComponent(((Component)val).gameObject); } if ((Object)(object)val2 == (Object)null) { GameObject gameObject = sourceLabel.gameObject; if ((Object)(object)gameObject == (Object)null) { return null; } GameObject val3 = Object.Instantiate<GameObject>(gameObject, (Transform)(object)parent); ((Object)val3).name = name; val2 = GetTextLikeComponent(val3); } if ((Object)(object)val2 == (Object)null) { return null; } if (TryGetRectTransform(sourceLabel, out var rectTransform) && TryGetRectTransform(val2, out var rectTransform2)) { CopyRectTransform(rectTransform, rectTransform2); } CopyLabelPresentation(sourceLabel, val2); return val2; } private static void CopyRectTransform(RectTransform source, RectTransform target) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)source == (Object)null) && !((Object)(object)target == (Object)null)) { target.anchorMin = source.anchorMin; target.anchorMax = source.anchorMax; target.pivot = source.pivot; target.anchoredPosition3D = source.anchoredPosition3D; target.sizeDelta = source.sizeDelta; target.offsetMin = source.offsetMin; target.offsetMax = source.offsetMax; ((Transform)target).localRotation = ((Transform)source).localRotation; ((Transform)target).localScale = ((Transform)source).localScale; } } private static void CopyLabelPresentation(Component source, Component target) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)source == (Object)null || (Object)(object)target == (Object)null) { return; } TextMeshProUGUI val = (TextMeshProUGUI)(object)((source is TextMeshProUGUI) ? source : null); if (val != null) { TextMeshProUGUI val2 = (TextMeshProUGUI)(object)((target is TextMeshProUGUI) ? target : null); if (val2 != null) { ((TMP_Text)val2).font = ((TMP_Text)val).font; ((TMP_Text)val2).fontSize = ((TMP_Text)val).fontSize; ((TMP_Text)val2).fontStyle = ((TMP_Text)val).fontStyle; ((TMP_Text)val2).alignment = ((TMP_Text)val).alignment; ((Graphic)val2).color = ((Graphic)val).color; ((Graphic)val2).raycastTarget = false; return; } } Text val3 = (Text)(object)((source is Text) ? source : null); if (val3 != null) { Text val4 = (Text)(object)((target is Text) ? target : null); if (val4 != null) { val4.font = val3.font; val4.fontSize = val3.fontSize; val4.fontStyle = val3.fontStyle; val4.alignment = val3.alignment; ((Graphic)val4).color = ((Graphic)val3).color; ((Graphic)val4).raycastTarget = false; } } } private static void EnsureIgnoredByLayout(RectTransform rectTransform) { if (!((Object)(object)rectTransform == (Object)null)) { LayoutElement orAddComponentSafe = Utils.GetOrAddComponentSafe<LayoutElement>(((Component)rectTransform).gameObject); if ((Object)(object)orAddComponentSafe != (Object)null) { orAddComponentSafe.ignoreLayout = true; } } } private static string GetBackpackDisplayName() { PlayerBackpack instance = PlayerBackpack.Instance; string text = instance?.CurrentTier?.Name; if (!string.IsNullOrEmpty(text)) { return text; } int num = instance?.CurrentTierIndex ?? (-1); if (num >= 0 && num < Configuration.BackpackTiers.Length) { return Configuration.BackpackTiers[num].Name; } return "Backpack"; } private static void ReplaceVehicleTextInContainer(RectTransform container, string backpackTitle) { if ((Object)(object)container == (Object)null || string.IsNullOrEmpty(backpackTitle)) { return; } Il2CppArrayBase<Component> componentsInChildren = ((Component)container).GetComponentsInChildren<Component>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Component val = componentsInChildren[i]; if (!((Object)(object)val == (Object)null) && IsTextLikeComponent(val)) { string text = NormalizeLabelText(GetLabelText(val)); if (text.Equals("Vehicle", StringComparison.OrdinalIgnoreCase)) { SetLabelText(val, backpackTitle); } } } } private static void ReplaceVehicleTextEverywhere(PanelState panel, string backpackTitle) { if (panel != null && !string.IsNullOrEmpty(backpackTitle) && (Object)(object)panel.BackpackContainer != (Object)null) { ReplaceVehicleTextInContainer(panel.BackpackContainer, backpackTitle); } } private static void UpdateBackpackHeaderTexts(PanelState state) { if (state != null) { if ((Object)(object)state.OverlayTitleLabel != (Object)null) { SetLabelText(state.OverlayTitleLabel, GetBackpackDisplayName()); } if ((Object)(object)state.OverlaySubtitleLabel != (Object)null) { SetLabelText(state.OverlaySubtitleLabel, "Items from your backpack."); } UpdateBackpackVisuals(state); } } private static void CenterBackpackContainer(PanelState state) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0063: 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) if (!((Object)(object)state?.BackpackContainer == (Object)null)) { RectTransform backpackContainer = state.BackpackContainer; backpackContainer.anchorMin = new Vector2(0.5f, 0.5f); backpackContainer.anchorMax = new Vector2(0.5f, 0.5f); backpackContainer.pivot = new Vector2(0.5f, 0.5f); ((Transform)backpackContainer).localScale = Vector3.one; backpackContainer.anchoredPosition = GetHandoverBackpackPosition(state); } } private static void EnsureDedicatedBackpackOverlay(HandoverScreen screen, PanelState state) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Expected O, but got Unknown //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result ty
PackRat-Mono.dll
Decompiled 5 days 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.Globalization; 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.Connection; 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.Networking; using PackRat.Patches; using PackRat.Routing; using PackRat.Shops; using PackRat.Storage; using ScheduleOne; using ScheduleOne.AvatarFramework; using ScheduleOne.AvatarFramework.Customization; using ScheduleOne.Core.Items.Framework; using ScheduleOne.DevUtilities; using ScheduleOne.Equipping; using ScheduleOne.ItemFramework; using ScheduleOne.Levelling; using ScheduleOne.Money; 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.Quests; using ScheduleOne.StationFramework; using ScheduleOne.Storage; using ScheduleOne.TV; using ScheduleOne.Tools; using ScheduleOne.UI; using ScheduleOne.UI.Handover; using ScheduleOne.UI.Items; using ScheduleOne.UI.Phone; using ScheduleOne.UI.Shop; using ScheduleOne.UI.Stations; using ScheduleOne.Variables; using ScheduleOne.Vehicles; using Steamworks; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [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", "2.0.0", "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("Release Mono")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+25e4203d29b99b673b9b9b648ed0ed7cbe82a075")] [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] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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] [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 = "2.0.0"; } public class PackRat : MelonMod { public override void OnInitializeMelon() { Configuration.Instance.Load(); 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 _equippedTierIndex = -1; private const int TierCheckIntervalFrames = 60; public static PlayerBackpack Instance { get; private set; } public int EquippedTierIndex => _equippedTierIndex; public int HighestPurchasedTierIndex => EquippedTierIndex; public int CurrentTierIndex { get { Configuration instance = Configuration.Instance; if (_equippedTierIndex < 0) { return -1; } for (int num = _equippedTierIndex; 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 SetEquippedTierIndex(int tierIndex) { _equippedTierIndex = ((tierIndex < 0) ? (-1) : Math.Min(tierIndex, Configuration.BackpackTiers.Length - 1)); } public void SetHighestPurchasedTierIndex(int tierIndex) { SetEquippedTierIndex(tierIndex); } public void RestorePurchasedTier(int tierIndex) { SetEquippedTierIndex(tierIndex); EnsureCorrectTierApplied(); } 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..."); MelonCoroutines.Start(DeferredConfigureStorage(this)); } private static IEnumerator DeferredConfigureStorage(PlayerBackpack instance) { yield return null; if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance._storage == (Object)null)) { int tierIdx = instance.CurrentTierIndex; int slotCount = ((tierIdx >= 0) ? Configuration.Instance.TierSlotCounts[tierIdx] : Configuration.BackpackTiers[0].DefaultSlotCount); instance.UpdateSize(slotCount); instance.OnStartClient(isOwner: true); } } private void Update() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) if (IsOpen) { StorageMenuPatch.ClearStandaloneBackpackKeyboardFocusOnPointerInput(); } if (IsOpen && StorageMenuPatch.HandleStandaloneBackpackSettingsInput()) { return; } bool keyDown = Input.GetKeyDown(Configuration.Instance.ToggleKey); if (keyDown || Time.frameCount % 60 == 0) { int currentTierIndex = CurrentTierIndex; if (currentTierIndex != _lastTierIndex) { _lastTierIndex = currentTierIndex; ApplyCurrentTier(currentTierIndex); } } if (!_backpackEnabled) { return; } try { if ((IsOpen && StorageMenuPatch.HandleStandaloneBackpackKeyboardNavigation()) || !keyDown || (IsOpen && StorageMenuPatch.IsStandaloneBackpackSearchFocused())) { return; } 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 != _equippedTierIndex) { SetEquippedTierIndex(tierIndex); ApplyTierAfterPurchase(tierIndex); BackpackShopIntegration.RefreshBackpackListingsInAllShops(); 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) { return; } Type type = slot.GetType(); MethodInfo methodInfo = ReflectionUtils.GetMethod(type, "ClearStoredInstance", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? ReflectionUtils.GetMethod(type, "Clear", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? ReflectionUtils.GetMethod(type, "ClearSlot", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (methodInfo != null) { try { methodInfo.Invoke(slot, null); return; } catch { } } ReflectionUtils.TrySetFieldOrProperty(slot, "ItemInstance", null); } 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 || _storage.ItemSlots.Count != 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 EnsureCorrectTierApplied() { _lastTierIndex = CurrentTierIndex; if (!((Object)(object)_storage == (Object)null) && _lastTierIndex >= 0) { ApplyCurrentTier(_lastTierIndex); } } 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}, EquippedTier={_equippedTierIndex}). 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; ModLogger.Info($"[BackpackUI] PlayerBackpack.Open -> StorageMenu.Open: title='{_openTitle}', slots={_storage.ItemSlots.Count}."); BackpackStateSyncManager.BeginLocalBackpackEdit(); instance.SlotGridLayout.constraintCount = 4; instance.Open((IItemSlotOwner)(object)_storage, _openTitle, string.Empty, (Action)null); _storage.SendAccessor(((NetworkBehaviour)Player.Local).NetworkObject); } } public void Close() { if (_backpackEnabled && IsOpen) { Singleton<StorageMenu>.Instance.Close(); _storage.SendAccessor((NetworkObject)null); } } public bool ContainsItemsOfInterest(EStealthLevel maxStealthLevel) { //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: 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) { string a = (ReflectionUtils.TryGetFieldOrProperty(val.ItemInstance.Definition, "legalStatus") ?? ReflectionUtils.TryGetFieldOrProperty(val.ItemInstance.Definition, "LegalStatus"))?.ToString(); if (!string.Equals(a, "Legal", StringComparison.Ordinal)) { 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_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: 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(); int count = _storage.ItemSlots.Count; val.onItemDataChanged = (Action)Delegate.Combine(val.onItemDataChanged, new Action(_storage.ContentsChanged)); val.SetSlotOwner((IItemSlotOwner)(object)_storage); if (_storage.ItemSlots.Count == count) { _storage.ItemSlots.Add(val); } } } 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."); Object.Destroy((Object)(object)this); } else { Instance = this; CameraLockedStateHelper.PrewarmCache(); } } private void OnDestroy() { if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } } } namespace PackRat.Storage { public static class BackpackFavorites { private static readonly HashSet<string> FavoriteDefinitionIds = new HashSet<string>(StringComparer.OrdinalIgnoreCase); public static bool IsFavorite(string definitionId) { return !string.IsNullOrWhiteSpace(definitionId) && FavoriteDefinitionIds.Contains(definitionId.Trim()); } public static bool Toggle(string definitionId) { if (string.IsNullOrWhiteSpace(definitionId)) { return false; } string item = definitionId.Trim(); if (!FavoriteDefinitionIds.Add(item)) { FavoriteDefinitionIds.Remove(item); return false; } return true; } public static void SetFavorites(IEnumerable<string> definitionIds) { FavoriteDefinitionIds.Clear(); if (definitionIds == null) { return; } foreach (string definitionId in definitionIds) { if (!string.IsNullOrWhiteSpace(definitionId)) { FavoriteDefinitionIds.Add(definitionId.Trim()); } } } public static List<string> GetSavedFavoriteIds() { return FavoriteDefinitionIds.OrderBy<string, string>((string id) => id, StringComparer.OrdinalIgnoreCase).ToList(); } } public sealed class BackpackSaveData { public string Contents { get; set; } public int EquippedTierIndex { get; set; } = -1; public int HighestPurchasedTierIndex { get; set; } = -1; public List<string> FavoriteDefinitionIds { get; set; } = new List<string>(); } } namespace PackRat.Shops { public static class BackpackShopIntegration { 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>(); private static StorableItemDefinition _safeBackpackTemplate; private static bool _loggedSafeTemplateUnavailable; private static bool _loggedBackpackDefinitionCreationFailure; private static bool _loggedListingIntegrationFailureSummary; 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(); bool flag = _shopsIntegrated.Add(instanceID); if (AddBackpackListings(shop)) { if (flag) { 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; } private static IEnumerator WaitAndIntegrate() { for (int i = 0; i < 60; i++) { yield return (object)new WaitForSeconds(0.5f); AddToAllHardwareStoresInScene(); } if (_shopsIntegrated.Count == 0) { LogHardwareStoreNotFound(); } } 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.EquippedTierIndex : (-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 (!instance.TierEnabled[i]) { RemoveTierListingFromShop(shop, "PackRat_Backpack_Tier_" + i); continue; } flag2 = true; string itemId = "PackRat_Backpack_Tier_" + i; if (i == num) { RemoveTierListingFromShop(shop, itemId); continue; } if (ShopHasItem(shop, itemId)) { flag3 = true; continue; } Sprite tierSprite = LevelManagerPatch.GetTierSprite(i, sprite, texture); StorableItemDefinition val = GetRegisteredBackpackDefinition(itemId); if ((Object)(object)val != (Object)null) { ConfigureBackpackTierDefinition(val, i, itemId, instance, tierSprite); } else { val = CreateBackpackTierDefinition(shop, i, itemId, instance, tierSprite); } if ((Object)(object)val == (Object)null) { num2++; } else if ((Object)(object)GetRegisteredBackpackDefinition(itemId) == (Object)null && !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) { _loggedListingIntegrationFailureSummary = false; ModLogger.Info("BackpackShopIntegration: Added backpack tier listings to Hardware Store."); } if (!flag2 || flag3 || flag) { _loggedListingIntegrationFailureSummary = false; return true; } if (!_loggedListingIntegrationFailureSummary) { _loggedListingIntegrationFailureSummary = true; ModLogger.Warn($"BackpackShopIntegration: Eligible tiers found but none added. missingDef={num2}, registerFailed={num3}, listingFailed={num4}"); } return false; } public static void RefreshBackpackListingsInAllShops() { AddToAllHardwareStoresInScene(); } 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 && ((BaseItemDefinition)listing.Item).ID == itemId) { return true; } } } catch { } return false; } private static StorableItemDefinition CreateBackpackTierDefinition(ShopInterface shop, int tierIndex, string itemId, Configuration cfg, Sprite iconSprite) { try { StorableItemDefinition val = CreateEmptyStorableItemDefinition(); if ((Object)(object)val == (Object)null) { val = CloneSafeBackpackTemplate(shop); } if ((Object)(object)val == (Object)null && !_loggedBackpackDefinitionCreationFailure) { _loggedBackpackDefinitionCreationFailure = true; ModLogger.Warn("BackpackShopIntegration: Could not create a backpack item definition. Skipping backpack listings until a valid template can be created."); } if ((Object)(object)val == (Object)null) { return null; } ConfigureBackpackTierDefinition(val, tierIndex, itemId, cfg, iconSprite); return val; } catch (Exception exception) { ModLogger.Error($"BackpackShopIntegration: CreateBackpackTierDefinition tier {tierIndex}", exception); return null; } } private static void ConfigureBackpackTierDefinition(StorableItemDefinition def, int tierIndex, string itemId, Configuration cfg, Sprite iconSprite) { //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)def == (Object)null) { return; } ApplyBackpackDefinitionDefaults(def); if (!ReflectionUtils.TrySetFieldOrProperty(def, "ID", itemId)) { ReflectionUtils.TrySetFieldOrProperty(def, "id", itemId); } string name = Configuration.BackpackTiers[tierIndex].Name; if (!ReflectionUtils.TrySetFieldOrProperty(def, "Name", name)) { ReflectionUtils.TrySetFieldOrProperty(def, "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(def, memberName, iconSprite)) { break; } } } float num = ((tierIndex < cfg.TierPrices.Length) ? cfg.TierPrices[tierIndex] : (25f + (float)tierIndex * 50f)); ReflectionUtils.TrySetFieldOrProperty(def, "BasePurchasePrice", num); FullRank val = ((tierIndex < cfg.TierUnlockRanks.Length) ? cfg.TierUnlockRanks[tierIndex] : Configuration.BackpackTiers[tierIndex].DefaultUnlockRank); ReflectionUtils.TrySetFieldOrProperty(def, "RequiredRank", val); ReflectionUtils.TrySetFieldOrProperty(def, "RequiresLevelToPurchase", true); string value = ((tierIndex < TierDescriptions.Length) ? TierDescriptions[tierIndex] : null); if (string.IsNullOrEmpty(value)) { return; } string[] array2 = new string[8] { "Description", "description", "TooltipText", "tooltipText", "FlavorText", "flavorText", "ItemDescription", "itemDescription" }; foreach (string memberName2 in array2) { if (ReflectionUtils.TrySetFieldOrProperty(def, memberName2, value)) { break; } } } private static StorableItemDefinition GetRegisteredBackpackDefinition(string itemId) { if (string.IsNullOrWhiteSpace(itemId)) { return null; } try { ItemDefinition registeredItemDefinition = GetRegisteredItemDefinition(itemId); if ((Object)(object)registeredItemDefinition == (Object)null) { return null; } return (StorableItemDefinition)(object)((registeredItemDefinition is StorableItemDefinition) ? registeredItemDefinition : null); } catch (Exception exception) { ModLogger.Error("BackpackShopIntegration: GetRegisteredBackpackDefinition", exception); return null; } } private static ItemDefinition GetRegisteredItemDefinition(string itemId) { if (string.IsNullOrWhiteSpace(itemId)) { return null; } try { if (Registry.ItemExists(itemId)) { return Registry.GetItem(itemId); } } catch { } try { Registry instance = Singleton<Registry>.Instance; if ((Object)(object)instance == (Object)null) { return null; } ItemDefinition val = FindDefinitionInRegistryList(instance.ItemRegistry, itemId); if ((Object)(object)val != (Object)null) { return val; } return FindDefinitionInRegistryList(instance.ItemsAddedAtRuntime, itemId); } catch (Exception exception) { ModLogger.Error("BackpackShopIntegration: GetRegisteredItemDefinition", exception); return null; } } private static ItemDefinition FindDefinitionInRegistryList(IEnumerable registryList, string itemId) { if (registryList == null || string.IsNullOrWhiteSpace(itemId)) { return null; } foreach (object registry in registryList) { if (registry != null) { string a = ReflectionUtils.TryGetFieldOrProperty(registry, "ID") as string; if (string.Equals(a, itemId, StringComparison.OrdinalIgnoreCase)) { object obj = ReflectionUtils.TryGetFieldOrProperty(registry, "Definition"); return (ItemDefinition)((obj is ItemDefinition) ? obj : null); } } } 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)) { StorableItemDefinition item = listing.Item; if (!((Object)(object)item == (Object)null)) { return Object.Instantiate<StorableItemDefinition>(item); } } } } catch (Exception exception) { ModLogger.Error("BackpackShopIntegration: CloneTemplateStorableItemDefinition", exception); } return null; } private static StorableItemDefinition CloneSafeBackpackTemplate(ShopInterface shop) { if ((Object)(object)_safeBackpackTemplate == (Object)null) { _safeBackpackTemplate = CreateSafeBackpackTemplate(shop); if ((Object)(object)_safeBackpackTemplate == (Object)null) { if (!_loggedSafeTemplateUnavailable) { _loggedSafeTemplateUnavailable = true; ModLogger.Warn("BackpackShopIntegration: Safe backpack template is unavailable in IL2CPP. Backpack listings will retry once the shop can provide a valid storable-item template."); } return null; } } try { return Object.Instantiate<StorableItemDefinition>(_safeBackpackTemplate); } catch (Exception exception) { ModLogger.Error("BackpackShopIntegration: CloneSafeBackpackTemplate", exception); return null; } } public static StorableItemDefinition CreateSafeBackpackTemplate(ShopInterface shop = null) { if ((Object)(object)_safeBackpackTemplate != (Object)null) { return _safeBackpackTemplate; } try { _safeBackpackTemplate = CreateEmptyStorableItemDefinition(); if ((Object)(object)_safeBackpackTemplate == (Object)null && (Object)(object)shop != (Object)null) { _safeBackpackTemplate = CloneTemplateStorableItemDefinition(shop); } if ((Object)(object)_safeBackpackTemplate == (Object)null) { if (!_loggedSafeTemplateUnavailable) { _loggedSafeTemplateUnavailable = true; ModLogger.Warn("BackpackShopIntegration: Could not create safe backpack template instance yet."); } return null; } ApplyBackpackDefinitionDefaults(_safeBackpackTemplate); ReflectionUtils.TrySetFieldOrProperty(_safeBackpackTemplate, "ID", "PackRat_Template"); ReflectionUtils.TrySetFieldOrProperty(_safeBackpackTemplate, "Name", "Backpack"); ReflectionUtils.TrySetFieldOrProperty(_safeBackpackTemplate, "BasePurchasePrice", 0f); ReflectionUtils.TrySetFieldOrProperty(_safeBackpackTemplate, "RequiredRank", 0); ReflectionUtils.TrySetFieldOrProperty(_safeBackpackTemplate, "RequiresLevelToPurchase", false); ReflectionUtils.TrySetFieldOrProperty(_safeBackpackTemplate, "Description", string.Empty); _loggedSafeTemplateUnavailable = false; _loggedBackpackDefinitionCreationFailure = false; _loggedListingIntegrationFailureSummary = false; ModLogger.Info("BackpackShopIntegration: Safe backpack template created successfully."); return _safeBackpackTemplate; } catch (Exception exception) { ModLogger.Error("BackpackShopIntegration: CreateSafeBackpackTemplate", exception); return null; } } private static void ApplyBackpackDefinitionDefaults(StorableItemDefinition def) { if (!((Object)(object)def == (Object)null)) { ReflectionUtils.TrySetFieldOrProperty(def, "Description", string.Empty); ReflectionUtils.TrySetEnumFieldOrProperty(def, "Category", "Storage"); ReflectionUtils.TrySetFieldOrProperty(def, "StoredItem", null); ReflectionUtils.TrySetFieldOrProperty(def, "StationItem", null); ReflectionUtils.TrySetFieldOrProperty(def, "Equippable", null); ReflectionUtils.TrySetFieldOrProperty(def, "CustomItemUI", null); ReflectionUtils.TrySetFieldOrProperty(def, "CustomInfoContent", null); ReflectionUtils.TrySetEnumFieldOrProperty(def, "legalStatus", "Legal"); ReflectionUtils.TrySetFieldOrProperty(def, "ResellMultiplier", 0.5f); ReflectionUtils.TrySetFieldOrProperty(def, "PickpocketDifficultyMultiplier", 1f); ReflectionUtils.TrySetFieldOrProperty(def, "CombatUtility", 0f); } } private static StorableItemDefinition CreateEmptyStorableItemDefinition() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown try { return (StorableItemDefinition)ScriptableObject.CreateInstance(typeof(StorableItemDefinition)); } catch (Exception exception) { ModLogger.Error("BackpackShopIntegration: CreateEmptyStorableItemDefinition", exception); return null; } } private static bool RegisterDefinition(StorableItemDefinition def) { try { if ((Object)(object)def == (Object)null || string.IsNullOrWhiteSpace(((BaseItemDefinition)def).ID)) { return false; } if ((Object)(object)GetRegisteredItemDefinition(((BaseItemDefinition)def).ID) != (Object)null) { ModLogger.Debug("BackpackShopIntegration: Definition '" + ((BaseItemDefinition)def).ID + "' is already registered; reusing existing definition."); return true; } 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 = ((BaseItemDefinition)def).Name }; shop.Listings.Add(val); val.Initialize(shop); if (!TryInvokeShopMethod(shop, "CreateListingUI", val)) { Sprite tierSprite = LevelManagerPatch.GetTierSprite(ParseTierFromItemId(((BaseItemDefinition)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 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); listingUI.onAddItem = (Action)Delegate.Combine(listingUI.onAddItem, (Action)delegate { shop.AddItem(listingUI); }); listingUI.onRemoveItem = (Action)Delegate.Combine(listingUI.onRemoveItem, (Action)delegate { shop.RemoveItem(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 && ((BaseItemDefinition)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 num = ((obj2 is int num2) ? num2 : 0); if (obj2 is long num3) { num = (int)num3; } for (int num4 = num - 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.Routing { public static class SmartRoutingManager { public static bool IsEnabled => Configuration.Instance.EnableSmartRouting; public static bool ShouldPreferBackpack(ItemInstance item) { if (item == null || !IsEnabled) { return false; } string itemCategory = StorageMenuPatch.GetItemCategory(item); if (1 == 0) { } bool result = itemCategory switch { "Products" => Configuration.Instance.RouteProducts, "Seeds" => Configuration.Instance.RouteSeeds, "Mixers" => Configuration.Instance.RouteMixers, "Reagents" => Configuration.Instance.RouteReagents, _ => false, }; if (1 == 0) { } return result; } } } namespace PackRat.Patches { [HarmonyPatch(typeof(ShopInterface))] public static class BackpackPurchasePatch { [HarmonyPatch("AddItem", new Type[] { typeof(ListingUI) })] [HarmonyPrefix] public static bool AddItem_Prefix(ShopInterface __instance, ListingUI ui) { try { if ((Object)(object)ui == (Object)null) { return true; } object obj = ReflectionUtils.TryGetFieldOrProperty(ui, "Listing") ?? ReflectionUtils.TryGetFieldOrProperty(ui, "listing"); if (obj == null) { return true; } object obj2 = ReflectionUtils.TryGetFieldOrProperty(obj, "Item"); StorableItemDefinition val = (StorableItemDefinition)((obj2 is StorableItemDefinition) ? obj2 : null); if (val == null || ((BaseItemDefinition)val).ID == null || !((BaseItemDefinition)val).ID.StartsWith("PackRat_Backpack_Tier_", StringComparison.Ordinal)) { return true; } if (BackpackShopIntegration.IsBackpackTierPurchase(((BaseItemDefinition)val).ID, out var tierIndex) && (Object)(object)PlayerBackpack.Instance != (Object)null && tierIndex == PlayerBackpack.Instance.EquippedTierIndex) { ModLogger.Info($"Blocked purchase selection for currently equipped backpack tier {tierIndex}."); return false; } return true; } catch (Exception exception) { ModLogger.Error("BackpackPurchasePatch: AddItem prefix error", exception); return true; } } } [HarmonyPatch(typeof(BodySearchBehaviour))] public static class BodySearchBehaviourPatch { [HarmonyPatch("SearchClean")] [HarmonyPrefix] public static bool SearchClean(BodySearchBehaviour __instance) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown if ((Object)(object)PlayerBackpack.Instance == (Object)null || !Configuration.Instance.EnableSearch || !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; } private static IEnumerator CheckForItems(BodySearchBehaviour behaviour) { ((NPC)behaviour.officer).DialogueHandler.ShowWorldspaceDialogue("Hold on, let me see your backpack as well.", 5f); yield return (object)new WaitForSeconds(3f); Singleton<BodySearchScreen>.Instance.IsOpen = false; behaviour.ConcludeSearch(!PlayerBackpack.Instance.ContainsItemsOfInterest(behaviour.MaxStealthLevel)); } } [HarmonyPatch(typeof(Cart))] public static class CartPatch { [HarmonyPatch("GetWarning")] [HarmonyPostfix] public static void GetWarning(Cart __instance, ref bool __result, ref string warning) { PlayerBackpack instance = PlayerBackpack.Instance; if (!((Object)(object)instance == (Object)null) && instance.IsUnlocked && !warning.StartsWith("Vehicle") && __result) { List<ItemSlot> itemSlots = 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(HandoverScreen))] public static class HandoverScreenPatch { private sealed class PanelState { public RectTransform BackpackContainer; public RectTransform BackpackSlotContainer; public RectTransform BackpackHeaderRoot; public RectTransform BackpackVisualRoot; public Canvas DedicatedCanvas; public RectTransform DedicatedCard; public RectTransform DedicatedGrid; public RectTransform CanvasProofMarker; public ItemSlotUI SlotPrefab; public RectTransform PagingRoot; public RectTransform VehicleContainer; public Component SourceTitleLabel; public Component SourceSubtitleLabel; public Component ClonedTitleLabel; public Component ClonedSubtitleLabel; public Component OverlayTitleLabel; public Component OverlaySubtitleLabel; public ItemSlotUI[] SlotUIs; public Button PrevButton; public Button NextButton; public Button ToggleButton; public Button DedicatedToggleButton; public RectTransform DedicatedToggleRoot; public RectTransform TransferRoot; public Button TransferButton; public Button BoundTransferButton; public Text TransferStatusLabel; public Text PageLabel; public Text VisualTitleLabel; public Text VisualMetaLabel; public Action PrevAction; public Action NextAction; public Action ToggleAction; public Action TransferAction; public LandVehicle NearbyVehicle; public Vector2 VehicleOriginalAnchoredPos; public Vector2 DoneButtonOriginalAnchorMin; public Vector2 DoneButtonOriginalAnchorMax; public Vector2 DoneButtonOriginalPivot; public Vector2 DoneButtonOriginalAnchoredPos; public Vector3 DoneButtonOriginalScale; public bool DoneButtonLayoutCaptured; public int CurrentPage; public int SlotsPerPage; public bool ShowingVehicle; public bool IsOpen; public int LastPageInputFrame; public int NextVehicleProbeFrame; public bool Initialized; public string TransferStatus; } private sealed class HandoverRequirement { public string ProductId; public string Quality; public int QualityRank; public int Remaining; } private sealed class HandoverTransferSource { public string Name; public List<ItemSlot> Slots; public int Moved; } private sealed class HeaderCandidate { public Component Label; public float LocalY; public float FontSize; } private const float VehicleMaxDistance = 20f; private const float BackpackGridScale = 0.74f; private const float BackpackContentCenterY = 125f; private static readonly Vector2 BackpackCardSize = new Vector2(380f, 450f); private const string VehicleHeaderTitle = "Vehicle"; private const string VehicleHeaderSubtitle = "This is the vehicle you last drove.\nMust be within 20 meters."; private static readonly Dictionary<int, PanelState> States = new Dictionary<int, PanelState>(); private const int HeaderReapplyFrameCount = 3; private static BackpackUiThemePalette GetCurrentBackpackThemePalette() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) Configuration instance = Configuration.Instance; return BackpackUiThemes.Get(instance.BackpackUiTheme, instance.CustomBackpackUiPrimaryColor); } public static void RefreshActiveLayouts() { try { foreach (PanelState value in States.Values) { if (value == null) { continue; } bool flag = (Object)(object)value.DedicatedCanvas != (Object)null && ((Component)value.DedicatedCanvas).gameObject.activeSelf; bool flag2 = (Object)(object)value.BackpackContainer != (Object)null && ((Component)value.BackpackContainer).gameObject.activeSelf; if (flag || flag2) { if ((Object)(object)value.DedicatedCard != (Object)null) { UpdateDedicatedOverlayLayout(FindOwningScreen(value), value); } else { ConfigureCompactBackpackLayout(FindOwningScreen(value), value); } UpdatePagingLayout(value); } } } catch (Exception exception) { ModLogger.Error("HandoverScreenPatch.RefreshActiveLayouts", exception); } } [HarmonyPatch("Start")] [HarmonyPostfix] public static void Start(HandoverScreen __instance) { try { ModLogger.Info($"[HandoverUI] Start receipt: id={((__instance != null) ? new int?(((Object)__instance).GetInstanceID()) : ((int?)null))}"); PruneDeadStates(); EnsurePanel(__instance); } catch (Exception exception) { ModLogger.Error("HandoverScreenPatch.Start", exception); } } [HarmonyPatch("Open")] [HarmonyPostfix] public static void Open(HandoverScreen __instance) { try { ModLogger.Info($"[HandoverUI] Open receipt: id={((__instance != null) ? new int?(((Object)__instance).GetInstanceID()) : ((int?)null))}, hasBackpack={HasBackpack()}"); PruneDeadStates(); if (!HasBackpack()) { HidePanelAndRestoreVehicle(__instance); return; } PanelState panelState = EnsurePanel(__instance); if (panelState != null && (!((Object)(object)panelState.BackpackContainer == (Object)null) || !((Object)(object)panelState.DedicatedCanvas == (Object)null))) { LandVehicle val = ResolveNearbyVehicleStorage(panelState, forceRefresh: true); bool hasVehicle = (Object)(object)val != (Object)null; LogVehicleSelector(val); EnsureDedicatedVehicleToggle(__instance, panelState, hasVehicle); panelState.CurrentPage = 0; panelState.SlotsPerPage = ((panelState.SlotUIs != null) ? panelState.SlotUIs.Length : 0); panelState.ShowingVehicle = false; panelState.TransferStatus = null; panelState.IsOpen = true; if ((Object)(object)panelState.DedicatedCanvas == (Object)null && (Object)(object)panelState.BackpackContainer != (Object)null) { ((Component)panelState.BackpackContainer).gameObject.SetActive(true); } if ((Object)(object)panelState.PagingRoot != (Object)null) { ((Component)panelState.PagingRoot).gameObject.SetActive((Object)(object)panelState.DedicatedCanvas == (Object)null); } UpdateBackpackHeaderTexts(panelState); ApplyVisibleStorageMode(panelState, hasVehicle); if ((Object)(object)panelState.DedicatedCanvas == (Object)null && (Object)(object)panelState.BackpackContainer != (Object)null) { ((Component)panelState.BackpackContainer).gameObject.SetActive(true); } if ((Object)(object)panelState.DedicatedCanvas == (Object)null && (Object)(object)panelState.BackpackSlotContainer != (Object)null) { ((Component)panelState.BackpackSlotContainer).gameObject.SetActive(true); } if ((Object)(object)panelState.VehicleContainer != (Object)null) { ((Component)panelState.VehicleContainer).gameObject.SetActive(false); } ApplyPrimaryHeaderForMode(__instance, panelState, panelState.ShowingVehicle); MelonCoroutines.Start(ReapplyHeaderNextFrame(__instance, panelState)); if ((Object)(object)panelState.DedicatedCanvas == (Object)null) { ApplyBackpackPage(panelState); } else { UpdateDedicatedOverlayLayout(__instance, panelState); EnsureDedicatedVehicleToggle(__instance, panelState, hasVehicle); UpdateDedicatedVehicleToggle(__instance, panelState, hasVehicle); } RebuildQuickMove(__instance, val); } } catch (Exception exception) { ModLogger.Error("HandoverScreenPatch.Open", exception); } } private static IEnumerator ReapplyHeaderNextFrame(HandoverScreen screen, PanelState panel) { if ((Object)(object)screen == (Object)null || panel == null) { yield break; } for (int i = 0; i < 3; i++) { yield return null; if ((Object)(object)screen == (Object)null || panel == null || (Object)(object)panel.BackpackContainer == (Object)null || !((Component)panel.BackpackContainer).gameObject.activeSelf || panel.ShowingVehicle) { break; } if ((Object)(object)panel.VehicleContainer != (Object)null && ((Component)panel.VehicleContainer).gameObject.activeSelf) { ((Component)panel.VehicleContainer).gameObject.SetActive(false); } ApplyPrimaryHeaderForMode(screen, panel, showingVehicle: false); } } [HarmonyPatch("Update")] [HarmonyPostfix] public static void Update(HandoverScreen __instance) { PruneDeadStates(); if ((Object)(object)__instance == (Object)null || !States.TryGetValue(((Object)__instance).GetInstanceID(), out var value)) { return; } if (value.IsOpen && !__instance.IsOpen) { ModLogger.Info("[HandoverUI] Owner screen closed outside Close(); dismissing dedicated backpack overlay."); HidePanelAndRestoreVehicle(__instance); } else { if (!value.IsOpen) { return; } if ((Object)(object)value.DedicatedCanvas != (Object)null) { if (!value.ShowingVehicle && (Object)(object)value.VehicleContainer != (Object)null && ((Component)value.VehicleContainer).gameObject.activeSelf) { ((Component)value.VehicleContainer).gameObject.SetActive(false); } UpdateDedicatedVehicleToggle(__instance, value, (Object)(object)ResolveNearbyVehicleStorage(value) != (Object)null); } else { if ((Object)(object)value.BackpackContainer == (Object)null || !((Component)value.BackpackContainer).gameObject.activeSelf || value.ShowingVehicle) { return; } if ((Object)(object)value.VehicleContainer != (Object)null && ((Component)value.VehicleContainer).gameObject.activeSelf) { ((Component)value.VehicleContainer).gameObject.SetActive(false); } ConfigureCompactBackpackLayout(__instance, value); ApplyPrimaryHeaderForMode(__instance, value, showingVehicle: false); if ((Object)(object)value.BackpackHeaderRoot != (Object)null && ((Component)value.BackpackHeaderRoot).gameObject.activeSelf) { ((Transform)value.BackpackHeaderRoot).SetAsLastSibling(); Canvas component = ((Component)value.BackpackHeaderRoot).GetComponent<Canvas>(); if ((Object)(object)component != (Object)null && component.overrideSorting && component.sortingOrder != 9999) { component.sortingOrder = 9999; } } } } } [HarmonyPatch("Close")] [HarmonyPostfix] public static void Close(HandoverScreen __instance) { //IL_013d: Unknown result type (might be due to invalid IL or missing references) try { if (States.TryGetValue(((Object)__instance).GetInstanceID(), out var value)) { ClearSlotAssignments(value); value.IsOpen = false; if ((Object)(object)value.BackpackContainer != (Object)null) { ((Component)value.BackpackContainer).gameObject.SetActive(false); } if ((Object)(object)value.PagingRoot != (Object)null) { ((Component)value.PagingRoot).gameObject.SetActive(false); } if ((Object)(object)value.DedicatedToggleRoot != (Object)null) { ((Component)value.DedicatedToggleRoot).gameObject.SetActive(false); } if ((Object)(object)value.TransferRoot != (Object)null) { ((Component)value.TransferRoot).gameObject.SetActive(false); } if ((Object)(object)value.DedicatedCanvas != (Object)null) { ((Component)value.DedicatedCanvas).gameObject.SetActive(false); } if ((Object)(object)value.CanvasProofMarker != (Object)null) { ((Component)value.CanvasProofMarker).gameObject.SetActive(false); } SetBackpackVisualVisible(value, visible: false); HideOverlayHeader(value); SetHeaderPairActive(value.SourceTitleLabel, value.SourceSubtitleLabel, active: true); if ((Object)(object)value.VehicleContainer != (Object)null) { value.VehicleContainer.anchoredPosition = value.VehicleOriginalAnchoredPos; } RestoreDoneButtonLayout(__instance, value); } } catch (Exception exception) { ModLogger.Error("HandoverScreenPatch.Close", exception); } } private static PanelState EnsurePanel(HandoverScreen screen) { //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) PruneDeadStates(); if ((Object)(object)screen == (Object)null) { return null; } int instanceID = ((Object)screen).GetInstanceID(); if (States.TryGetValue(instanceID, out var value) && value.Initialized && IsComponentAlive((Component)(object)value.BackpackContainer) && IsComponentAlive((Component)(object)value.VehicleContainer) && ((Object)(object)value.BackpackHeaderRoot == (Object)null || IsComponentAlive((Component)(object)value.BackpackHeaderRoot)) && IsComponentAlive((Component)(object)value.PagingRoot) && IsComponentAlive((Component)(object)value.PrevButton) && IsComponentAlive((Component)(object)value.NextButton) && IsComponentAlive((Component)(object)value.ToggleButton) && IsComponentAlive((Component)(object)value.PageLabel)) { RefreshHeaderBindings(value, screen); EnsureDedicatedBackpackOverlay(screen, value); return value; } PanelState panelState = value ?? new PanelState(); panelState.VehicleContainer = screen.VehicleContainer; if ((Object)(object)panelState.VehicleContainer == (Object)null) { return null; } panelState.VehicleOriginalAnchoredPos = panelState.VehicleContainer.anchoredPosition; if (!IsComponentAlive((Component)(object)panelState.BackpackContainer)) { panelState.BackpackContainer = null; } if ((Object)(object)panelState.BackpackContainer == (Object)null) { RectTransform val = Object.Instantiate<RectTransform>(panelState.VehicleContainer, ((Transform)panelState.VehicleContainer).parent); ((Object)val).name = "BackpackContainer"; ((Component)val).gameObject.SetActive(false); panelState.BackpackContainer = val; } CenterBackpackContainer(panelState); panelState.BackpackSlotContainer = FindMatchingRectTransform(panelState.BackpackContainer, screen.VehicleSlotContainer); RectTransform val2 = (((Object)(object)panelState.BackpackSlotContainer != (Object)null) ? panelState.BackpackSlotContainer : panelState.BackpackContainer); ItemSlotUI[] componentsInChildren = ((Component)val2).GetComponentsInChildren<ItemSlotUI>(false); if (componentsInChildren == null || componentsInChildren.Length == 0) { componentsInChildren = ((Component)val2).GetComponentsInChildren<ItemSlotUI>(true); } ItemSlotUI dedicatedSlotTemplate = GetDedicatedSlotTemplate((componentsInChildren != null && componentsInChildren.Length != 0) ? componentsInChildren[0] : null); if ((Object)(object)panelState.DedicatedCanvas == (Object)null) { panelState.SlotUIs = componentsInChildren; panelState.SlotPrefab = dedicatedSlotTemplate; } else if ((Object)(object)panelState.SlotPrefab == (Object)null) { panelState.SlotPrefab = dedicatedSlotTemplate; } RefreshHeaderBindings(panelState, screen); EnsureCanvasProofMarker(screen, panelState); EnsureDedicatedBackpackOverlay(screen, panelState); if ((Object)(object)panelState.DedicatedCard == (Object)null) { EnsureBackpackVisuals(panelState); ConfigureCompactBackpackLayout(screen, panelState); } EnsurePagingControls(panelState); panelState.Initialized = true; States[instanceID] = panelState; return panelState; } private static void EnsureCanvasProofMarker(HandoverScreen screen, PanelState state) { //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Expected O, but got Unknown //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)screen?.Canvas == (Object)null || state == null) { ModLogger.Warn("[HandoverUI] Canvas proof skipped: HandoverScreen.Canvas was null."); return; } Transform transform = ((Component)screen.Canvas).transform; RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null); if ((Object)(object)val == (Object)null) { ModLogger.Warn("[HandoverUI] Canvas proof skipped: canvas root was not a RectTransform."); return; } RectTransform val2 = state.CanvasProofMarker; if ((Object)(object)val2 == (Object)null) { GameObject val3 = new GameObject("PackRat_HandoverCanvasProof"); val2 = val3.AddComponent<RectTransform>(); ((Transform)val2).SetParent((Transform)(object)val, false); Image val4 = val3.AddComponent<Image>(); ((Graphic)val4).color = Color32.op_Implicit(new Color32((byte)217, (byte)56, (byte)168, (byte)245)); ((Graphic)val4).raycastTarget = false; GameObject val5 = new GameObject("Label"); RectTransform val6 = val5.AddComponent<RectTransform>(); ((Transform)val6).SetParent((Transform)(object)val2, false); val6.anchorMin = Vector2.zero; val6.anchorMax = Vector2.one; val6.offsetMin = Vector2.zero; val6.offsetMax = Vector2.zero; Text val7 = val5.AddComponent<Text>(); val7.text = "PACKRAT HANDOVER CANVAS RECEIPT"; val7.font = ResolveUiFont((Transform)(object)val); val7.fontSize = 16; val7.fontStyle = (FontStyle)1; val7.alignment = (TextAnchor)4; ((Graphic)val7).color = Color.white; ((Graphic)val7).raycastTarget = false; state.CanvasProofMarker = val2; } val2.anchorMin = new Vector2(0.5f, 0.5f); val2.anchorMax = new Vector2(0.5f, 0.5f); val2.pivot = new Vector2(0.5f, 0.5f); val2.anchoredPosition = new Vector2(0f, 300f); val2.sizeDelta = new Vector2(440f, 42f); ((Transform)val2).SetAsLastSibling(); ((Component)val2).gameObject.SetActive(true); object[] obj = new object[5] { ((Object)screen.Canvas).name, screen.Canvas.renderMode, null, null, null }; Rect rect = val.rect; obj[2] = ((Rect)(ref rect)).width; rect = val.rect; obj[3] = ((Rect)(ref rect)).height; Transform parent = ((Transform)val2).parent; obj[4] = ((parent != null) ? ((Object)parent).name : null); ModLogger.Info(string.Format("[HandoverUI] Canvas proof active: canvas={0}, mode={1}, rect={2:0}x{3:0}, markerParent={4}", obj)); } private static void PruneDeadStates() { if (States.Count == 0) { return; } List<int> list = new List<int>(); foreach (KeyValuePair<int, PanelState> state in States) { PanelState value = state.Value; if (value == null) { list.Add(state.Key); } else if (!IsComponentAlive((Component)(object)value.VehicleContainer) && !IsComponentAlive((Component)(object)value.BackpackContainer) && !IsComponentAlive((Component)(object)value.PagingRoot) && !IsComponentAlive((Component)(object)value.BackpackHeaderRoot)) { list.Add(state.Key); } } for (int i = 0; i < list.Count; i++) { States.Remove(list[i]); } } private static void RefreshHeaderBindings(PanelState state, HandoverScreen screen) { if (state != null) { ResolveLabels(state, screen); EnsureBackpackHeader(state); } } private static void ResolveLabels(PanelState state, HandoverScreen screen) { ResolveHeaderPairInContainer(state.VehicleContainer, (Transform)(object)screen?.VehicleSlotContainer, null, null, out state.SourceTitleLabel, out state.SourceSubtitleLabel); ResolveHeaderPairInContainer(state.BackpackContainer, (Transform)(object)state.BackpackSlotContainer, (Transform)(object)state.PagingRoot, (Transform)(object)state.BackpackHeaderRoot, out state.ClonedTitleLabel, out state.ClonedSubtitleLabel); if (IsUnderTransform(state.ClonedTitleLabel, (Transform)(object)state.BackpackVisualRoot)) { state.ClonedTitleLabel = null; } if (IsUnderTransform(state.ClonedSubtitleLabel, (Transform)(object)state.BackpackVisualRoot)) { state.ClonedSubtitleLabel = null; } } private static void ResolveHeaderPairInContainer(RectTransform container, Transform slotContainer, Transform pagingRoot, Transform overlayRoot, out Component titleLabel, out Component subtitleLabel) { titleLabel = null; subtitleLabel = null; if ((Object)(object)container == (Object)null) { return; } Component[] componentsInChildren = ((Component)container).GetComponentsInChildren<Component>(true); List<Component> list = new List<Component>(); foreach (Component val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && IsTextLikeComponent(val) && !IsUnderTransform(val, slotContainer) && !IsUnderTransform(val, pagingRoot) && !IsUnderTransform(val, overlayRoot)) { list.Add(val); } } if (list.Count == 0) { return; } titleLabel = FindNamedHeaderLabel(container, slotContainer, pagingRoot, overlayRoot, "Title"); subtitleLabel = FindNamedHeaderLabel(container, slotContainer, pagingRoot, overlayRoot, "Subtitle"); foreach (Component item in list) { string text = NormalizeLabelText(GetLabelText(item)); if ((Object)(object)titleLabel == (Object)null && text.Equals("Vehicle", StringComparison.OrdinalIgnoreCase)) { titleLabel = item; } else if ((Object)(object)subtitleLabel == (Object)null && (text.Contains("vehicle you last drove", StringComparison.OrdinalIgnoreCase) || text.Contains("within 20 meters", StringComparison.OrdinalIgnoreCase))) { subtitleLabel = item; } } if ((Object)(object)titleLabel != (Object)null && (Object)(object)subtitleLabel != (Object)null) { return; } List<HeaderCandidate> list2 = new List<HeaderCandidate>(list.Count); for (int j = 0; j < list.Count; j++) { Component val2 = list[j]; list2.Add(new HeaderCandidate { Label = val2, LocalY = GetLocalY(container, val2), FontSize = GetFontSize(val2) }); } list2.Sort(CompareHeaderCandidates); if ((Object)(object)titleLabel == (Object)null && list2.Count > 0) { titleLabel = list2[0].Label; } if (!((Object)(object)subtitleLabel == (Object)null)) { return; } for (int k = 0; k < list2.Count; k++) { Component label = list2[k].Label; if (!((Object)(object)label == (Object)null) && !((Object)(object)label == (Object)(object)titleLabel)) { subtitleLabel = label; break; } } } private static Component FindNamedHeaderLabel(RectTransform container, Transform slotContainer, Transform pagingRoot, Transform overlayRoot, string targetName) { if ((Object)(object)container == (Object)null || string.IsNullOrEmpty(targetName)) { return null; } Transform[] componentsInChildren = ((Component)container).GetComponentsInChildren<Transform>(true); foreach (Transform val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && string.Equals(((Object)val).name, targetName, StringComparison.OrdinalIgnoreCase) && (!((Object)(object)slotContainer != (Object)null) || (!((Object)(object)val == (Object)(object)slotContainer) && !val.IsChildOf(slotContainer))) && (!((Object)(object)pagingRoot != (Object)null) || (!((Object)(object)val == (Object)(object)pagingRoot) && !val.IsChildOf(pagingRoot))) && (!((Object)(object)overlayRoot != (Object)null) || (!((Object)(object)val == (Object)(object)overlayRoot) && !val.IsChildOf(overlayRoot)))) { Component textLikeComponent = GetTextLikeComponent(((Component)val).gameObject); if ((Object)(object)textLikeComponent != (Object)null) { return textLikeComponent; } Component val2 = FindFirstTextLikeInSubtree(val); if ((Object)(object)val2 != (Object)null) { return val2; } } } return null; } private static Component FindFirstTextLikeInSubtree(Transform root) { if ((Object)(object)root == (Object)null) { return null; } Component[] componentsInChildren = ((Component)root).GetComponentsInChildren<Component>(true); foreach (Component val in componentsInChildren) { if ((Object)(object)val != (Object)null && IsTextLikeComponent(val)) { return val; } } return null; } private static int CompareHeaderCandidates(HeaderCandidate left, HeaderCandidate right) { if (left == right) { return 0; } if (left == null) { return 1; } if (right == null) { return -1; } int num = right.LocalY.CompareTo(left.LocalY); if (num != 0) { return num; } return right.FontSize.CompareTo(left.FontSize); } private static float GetLocalY(RectTransform container, Component component) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)container == (Object)null || (Object)(object)component == (Object)null || (Object)(object)component.transform == (Object)null) { return float.MinValue; } try { Vector3 val = ((Transform)container).InverseTransformPoint(component.transform.position); return val.y; } catch { return float.MinValue; } } private static float GetFontSize(Component label) { if ((Object)(object)label == (Object)null) { return 0f; } TextMeshProUGUI val = (TextMeshProUGUI)(object)((label is TextMeshProUGUI) ? label : null); if (val != null) { try { return ((TMP_Text)val).fontSize; } catch { } } Text val2 = (Text)(object)((label is Text) ? label : null); if (val2 != null) { return val2.fontSize; } object obj2 = ReflectionUtils.TryGetFieldOrProperty(label, "fontSize"); if (obj2 is float result) { return result; } if (obj2 is int num) { return num; } return 0f; } private static Component GetTextLikeComponent(GameObject gameObject) { if ((Object)(object)gameObject == (Object)null) { return null; } TextMeshProUGUI tmpLabel = GetTmpLabel(gameObject); if ((Object)(object)tmpLabel != (Object)null) { return (Component)(object)tmpLabel; } Text component = gameObject.GetComponent<Text>(); if ((Object)(object)component != (Object)null) { return (Component)(object)component; } Component[] components = gameObject.GetComponents<Component>(); foreach (Component val in components) { if ((Object)(object)val != (Object)null && IsTextLikeComponent(val)) { return val; } } return null; } private static void EnsureBackpackHeader(PanelState state) { //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Expected O, but got Unknown if ((Object)(object)state?.BackpackContainer == (Object)null || (Object)(object)state.SourceTitleLabel == (Object)null || (Object)(object)state.SourceSubtitleLabel == (Object)null) { return; } RectTransform backpackContainer = state.BackpackContainer; RectTransform val = null; if ((Object)(object)state.BackpackHeaderRoot != (Object)null && IsComponentAlive((Component)(object)state.BackpackHeaderRoot)) { val = state.BackpackHeaderRoot; } if ((Object)(object)val != (Object)null && (Object)(object)((Transform)val).parent != (Object)(object)backpackContainer) { ((Transform)val).SetParent((Transform)(object)backpackContainer, false); } if ((Object)(object)val == (Object)null) { Transform val2 = ((Transform)backpackContainer).Find("PackRat_BackpackHeader"); val = (RectTransform)(object)((val2 is RectTransform) ? val2 : null); } if ((Object)(object)val == (Object)null) { GameObject val3 = new GameObject("PackRat_BackpackHeader"); val = val3.AddComponent<RectTransform>(); ((Transform)val).SetParent((Transform)(object)backpackContainer, false); } state.BackpackHeaderRoot = val; EnsureIgnoredByLayout(val); ResetHeaderOverlayRoot(val); state.OverlayTitleLabel = EnsureOverlayLabel(val, "PackRat_BackpackTitle", state.SourceTitleLabel); state.OverlaySubtitleLabel = EnsureOverlayLabel(val, "PackRat_BackpackSubtitle", state.SourceSubtitleLabel); UpdateBackpackHeaderLayout(state); if (TryGetGameObject((Component)(object)val, out var gameObject) && TryGetGameObject((Component)(object)backpackContainer, out var gameObject2)) { SetLayerRecursively(gameObject, gameObject2.layer); ((Transform)val).SetAsLastSibling(); Canvas componentInParent = ((Component)backpackContainer).GetComponentInParent<Canvas>(); Canvas val4 = gameObject.GetComponent<Canvas>(); if ((Object)(object)val4 == (Object)null) { val4 = gameObject.AddComponent<Canvas>(); } val4.overrideSorting = true; if ((Object)(object)componentInParent != (Object)null) { val4.sortingLayerID = componentInParent.sortingLayerID; val4.sortingOrder = componentInParent.sortingOrder + 210; } else { val4.sortingOrder = 5010; } } UpdateBackpackHeaderTexts(state); } private static void UpdateBackpackHeaderLayout(PanelState state) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)state?.BackpackHeaderRoot == (Object)null) && !((Object)(object)state.BackpackContainer == (Object)null)) { RectTransform backpackHeaderRoot = state.BackpackHeaderRoot; EnsureIgnoredByLayout(backpackHeaderRoot); backpackHeaderRoot.anchorMin = new Vector2(0.5f, 1f); backpackHeaderRoot.anchorMax = new Vector2(0.5f, 1f); backpackHeaderRoot.pivot = new Vector2(0.5f, 1f); backpackHeaderRoot.anchoredPosition = new Vector2(0f, -8f); ((Transform)backpackHeaderRoot).localScale = Vector3.one; } } private static void ResetHeaderOverlayRoot(RectTransform headerRoot) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0084: 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) if (!((Object)(object)headerRoot == (Object)null)) { headerRoot.anchorMin = new Vector2(0.5f, 0.5f); headerRoot.anchorMax = new Vector2(0.5f, 0.5f); headerRoot.pivot = new Vector2(0.5f, 0.5f); headerRoot.anchoredPosition3D = Vector3.zero; ((Transform)headerRoot).localRotation = Quaternion.identity; ((Transform)headerRoot).localScale = Vector3.one; headerRoot.sizeDelta = Vector2.zero; headerRoot.offsetMin = Vector2.zero; headerRoot.offsetMax = Vector2.zero; } } private static Component EnsureOverlayLabel(RectTransform parent, string name, Component sourceLabel) { if ((Object)(object)parent == (Object)null || (Object)(object)sourceLabel == (Object)null) { return null; } Transform val = ((Transform)parent).Find(name); Component val2 = null; if ((Object)(object)val != (Object)null) { val2 = GetTextLikeComponent(((Component)val).gameObject); } if ((Object)(object)val2 == (Object)null) { GameObject gameObject = sourceLabel.gameObject; if ((Object)(object)gameObject == (Object)null) { return null; } GameObject val3 = Object.Instantiate<GameObject>(gameObject, (Transform)(object)parent); ((Object)val3).name = name; val2 = GetTextLikeComponent(val3); } if ((Object)(object)val2 == (Object)null) { return null; } if (TryGetRectTransform(sourceLabel, out var rectTransform) && TryGetRectTransform(val2, out var rectTransform2)) { CopyRectTransform(rectTransform, rectTransform2); } CopyLabelPresentation(sourceLabel, val2); return val2; } private static void CopyRectTransform(RectTransform source, RectTransform target) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)source == (Object)null) && !((Object)(object)target == (Object)null)) { target.anchorMin = source.anchorMin; target.anchorMax = source.anchorMax; target.pivot = source.pivot; target.anchoredPosition3D = source.anchoredPosition3D; target.sizeDelta = source.sizeDelta; target.offsetMin = source.offsetMin; target.offsetMax = source.offsetMax; ((Transform)target).localRotation = ((Transform)source).localRotation; ((Transform)target).localScale = ((Transform)source).localScale; } } private static void CopyLabelPresentation(Component source, Component target) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)source == (Object)null || (Object)(object)target == (Object)null) { return; } TextMeshProUGUI val = (TextMeshProUGUI)(object)((source is TextMeshProUGUI) ? source : null); if (val != null) { TextMeshProUGUI val2 = (TextMeshProUGUI)(object)((target is TextMeshProUGUI) ? target : null); if (val2 != null) { ((TMP_Text)val2).font = ((TMP_Text)val).font; ((TMP_Text)val2).fontSize = ((TMP_Text)val).fontSize; ((TMP_Text)val2).fontStyle = ((TMP_Text)val).fontStyle; ((TMP_Text)val2).alignment = ((TMP_Text)val).alignment; ((Graphic)val2).color = ((Graphic)val).color; ((Graphic)val2).raycastTarget = false; return; } } Text val3 = (Text)(object)((source is Text) ? source : null); if (val3 != null) { Text val4 = (Text)(object)((target is Text) ? target : null); if (val4 != null) { val4.font = val3.font; val4.fontSize = val3.fontSize; val4.fontStyle = val3.fontStyle; val4.alignment = val3.alignment; ((Graphic)val4).color = ((Graphic)val3).color; ((Graphic)val4).raycastTarget = false; } } } private static void EnsureIgnoredByLayout(RectTransform rectTransform) { if (!((Object)(object)rectTransform == (Object)null)) { LayoutElement val = ((Component)rectTransform).GetComponent<LayoutElement>(); if ((Object)(object)val == (Object)null) { val = ((Component)rectTransform).gameObject.AddComponent<LayoutElement>(); } if ((Object)(object)val != (Object)null) { val.ignoreLayout = true; } } } private static string GetBackpackDisplayName() { PlayerBackpack instance = PlayerBackpack.Instance; string text = instance?.CurrentTier?.Name; if (!string.IsNullOrEmpty(text)) { return text; } int num = instance?.CurrentTierIndex ?? (-1); if (num >= 0 && num < Configuration.BackpackTiers.Length) { return Configuration.BackpackTiers[num].Name; } return "Backpack"; } private static void ReplaceVehicleTextInContainer(RectTransform container, string backpackTitle) { if ((Object)(object)container == (Object)null || string.IsNullOrEmpty(backpackTitle)) { return; } Component[] componentsInChildren = ((Component)container).GetComponentsInChildren<Component>(true); foreach (Component val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && IsTextLikeComponent(val)) { string text = NormalizeLabelText(GetLabelText(val)); if (text.Equals("Vehicle", StringComparison.OrdinalIgnoreCase)) { SetLabelText(val, backpackTitle); } } } } private static void ReplaceVehicleTextEverywhere(PanelState panel, string backpackTitle) { if (panel != null && !string.IsNullOrEmpty(backpackTitle) && (Object)(object)panel.BackpackContainer != (Object)null) { ReplaceVehicleTextInContainer(panel.BackpackContainer, backpackTitle); } } private static void UpdateBackpackHeaderTexts(PanelState state) { if (state != null) { if ((Object)(object)state.OverlayTitleLabel != (Object)null) { SetLabelText(state.OverlayTitleLabel, GetBackpackDisplayName()); } if ((Object)(object)state.OverlaySubtitleLabel != (Object)null) { SetLabelText(state.OverlaySubtitleLabel, "Items from your backpack."); } UpdateBackpackVisuals(state); } } private static void CenterBackpackContainer(PanelState state) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0063: 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) if (!((Object)(object)state?.BackpackContainer == (Object)null)) { RectTransform backpackContainer = state.BackpackContainer; backpackContainer.anchorMin = new Vector2(0.5f, 0.5f); backpackContainer.anchorMax = new Vector2(0.5f, 0.5f); backpackContainer.pivot = new Vector2(0.5f, 0.5f); ((Transform)backpackContainer).localScale = Vector3.one; backpackContainer.anchoredPosition = GetHandoverBackpackPosition(state); } } private static void EnsureDedicatedBackpackOverlay(HandoverScreen screen, PanelState state) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Expected O, but got Unknown //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_014a: 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_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Expected O, but got Unknown //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Expected O, but got Unknown //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_02c2: Unknown result type (might be due to invalid IL or missing references) //IL_02e8: Unknown result type (might be due to invalid IL or missing references) //IL_030c: Unknown result type (might be due to invalid IL or missing references) //IL_0331: Unknown result type (might be due to invalid IL or missing references) //IL_0338: Expected O, but got Unknown //IL_0358: Unknown result type (might be due to invalid IL or missing references) //IL_036f: Unknown result type (might be due to invalid IL or missing references) //IL_0386: Unknown result type (might be due to invalid IL or missing references) //IL_039d: Unknown result type (might be due to invalid IL or missing references) //IL_03b4: Unknown result type (might be due to