Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of HotDeposit v1.0.2
HotDeposit.dll
Decompiled a week agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; 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: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("HotDeposit")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.2.0")] [assembly: AssemblyInformationalVersion("1.0.2")] [assembly: AssemblyProduct("HotDeposit")] [assembly: AssemblyTitle("HotDeposit")] [assembly: AssemblyVersion("1.0.2.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [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 HotDeposit { [BepInPlugin("Moopfam.HotDeposit", "HotDeposit", "1.0.2")] [BepInProcess("valheim.exe")] public sealed class Plugin : BaseUnityPlugin { private sealed class InputVisibilityProbe { internal MethodInfo Method; internal PropertyInfo Property; internal FieldInfo InstanceField; internal PropertyInfo InstanceProperty; internal bool Check() { try { MethodInfo methodInfo = ((Property != null) ? Property.GetGetMethod(nonPublic: true) : null); bool flag = ((Method != null) ? Method.IsStatic : (methodInfo != null && methodInfo.IsStatic)); object obj = null; if (!flag) { if (InstanceField != null) { obj = InstanceField.GetValue(null); } else if (InstanceProperty != null) { obj = InstanceProperty.GetValue(null, null); } if (obj == null) { return false; } } object obj2 = ((Method != null) ? Method.Invoke(obj, null) : Property.GetValue(obj, null)); return obj2 is bool && (bool)obj2; } catch { return false; } } } private sealed class PlayerDepositItem { internal ItemData Item; internal string ItemKey; internal string DisplayName; } private sealed class RegisteredContainer { internal Container Container; internal int InstanceId; internal Piece Piece; internal bool IsTombStone; internal bool MetadataInitialized; internal bool PlayerBuiltConfirmed; internal Inventory Inventory; internal Vector3 CachedPosition; internal bool IsDynamic; internal int CellX; internal int CellZ; } private sealed class ItemGridPositionComparer : IComparer<ItemData> { internal static readonly ItemGridPositionComparer Instance = new ItemGridPositionComparer(); public int Compare(ItemData x, ItemData y) { return CompareItemGridPosition(x, y); } } private sealed class ContainerTarget { internal Container Container; internal Inventory Inventory; internal float DistanceSq; internal int OwnershipState; internal Dictionary<string, List<ItemData>> ItemStacksByKey; } public const string PluginGuid = "Moopfam.HotDeposit"; public const string PluginName = "HotDeposit"; public const string PluginVersion = "1.0.2"; internal const string LockDataKey = "Moopfam.HotDeposit.Locked"; internal const string LockIconObjectName = "HotDepositLockIcon"; private const string VanillaInventoryRowsKey = "invrows"; private const int VanillaInventoryBaseRows = 4; private const int VanillaInventoryMaxRows = 9; internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<bool> EnableKeyBinds; internal static ConfigEntry<KeyCode> AllDepositKey; internal static ConfigEntry<KeyCode> HoveredChestKey; internal static ConfigEntry<KeyboardShortcut> LockKeybind; internal static ConfigEntry<float> DepositDistance; internal static ConfigEntry<bool> IgnoreHotbar; internal static ConfigEntry<bool> IgnoreEquipped; internal static ConfigEntry<bool> HoveredChestDepositAll; internal static ConfigEntry<bool> ShowHoverPrompt; internal static ConfigEntry<bool> ShowLockIcon; internal static ConfigEntry<bool> ShowDepositPopup; internal static ManualLogSource Log; private Harmony _harmony; private static readonly MethodInfo ContainerGetInventoryMethod = AccessTools.Method(typeof(Container), "GetInventory", Type.EmptyTypes, (Type[])null); private static readonly MethodInfo ContainerCheckAccessMethod = AccessTools.Method(typeof(Container), "CheckAccess", new Type[1] { typeof(long) }, (Type[])null); private static readonly MethodInfo ContainerIsInUseMethod = AccessTools.Method(typeof(Container), "IsInUse", Type.EmptyTypes, (Type[])null); private static readonly FieldInfo ContainerNViewField = AccessTools.Field(typeof(Container), "m_nview"); private static readonly MethodInfo ZNetViewIsOwnerMethod = AccessTools.Method(typeof(ZNetView), "IsOwner", Type.EmptyTypes, (Type[])null); private static readonly MethodInfo ZNetViewClaimOwnershipMethod = AccessTools.Method(typeof(ZNetView), "ClaimOwnership", Type.EmptyTypes, (Type[])null); private static readonly MethodInfo InventoryGetAllItemsMethod = AccessTools.Method(typeof(Inventory), "GetAllItems", Type.EmptyTypes, (Type[])null); private static readonly MethodInfo InventoryMoveItemToThisMethod = AccessTools.Method(typeof(Inventory), "MoveItemToThis", new Type[2] { typeof(Inventory), typeof(ItemData) }, (Type[])null); private static readonly MethodInfo InventoryChangedMethod = AccessTools.Method(typeof(Inventory), "Changed", new Type[2] { typeof(bool), typeof(bool) }, (Type[])null); private static readonly MethodInfo InventoryFindFreeStackItemMethod = AccessTools.Method(typeof(Inventory), "FindFreeStackItem", new Type[3] { typeof(string), typeof(int), typeof(int) }, (Type[])null); private static readonly MethodInfo InventoryFindEmptySlotMethod = AccessTools.Method(typeof(Inventory), "FindEmptySlot", new Type[1] { typeof(bool) }, (Type[])null); private static readonly MethodInfo InventoryTopFirstMethod = AccessTools.Method(typeof(Inventory), "TopFirst", new Type[1] { typeof(ItemData) }, (Type[])null); private static readonly FieldInfo ItemStackField = AccessTools.Field(typeof(ItemData), "m_stack"); private static readonly FieldInfo ItemEquippedField = AccessTools.Field(typeof(ItemData), "m_equipped"); private static readonly FieldInfo ItemGridPosField = AccessTools.Field(typeof(ItemData), "m_gridPos"); private static readonly FieldInfo ItemDropPrefabField = AccessTools.Field(typeof(ItemData), "m_dropPrefab"); private static readonly FieldInfo ItemSharedField = AccessTools.Field(typeof(ItemData), "m_shared"); private static readonly FieldInfo ItemCustomDataField = AccessTools.Field(typeof(ItemData), "m_customData"); private static readonly FieldInfo InventoryGridElementsField = AccessTools.Field(typeof(InventoryGrid), "m_elements"); private static readonly FieldInfo InventoryGridInventoryField = AccessTools.Field(typeof(InventoryGrid), "m_inventory"); private static readonly MethodInfo InventoryGetWidthMethod = AccessTools.Method(typeof(Inventory), "GetWidth", Type.EmptyTypes, (Type[])null); private static readonly MethodInfo InventoryGetItemAtMethod = AccessTools.Method(typeof(Inventory), "GetItemAt", new Type[2] { typeof(int), typeof(int) }, (Type[])null); private static readonly MethodInfo PlayerGetHoverObjectMethod = AccessTools.Method(typeof(Player), "GetHoverObject", Type.EmptyTypes, (Type[])null); private static readonly MethodInfo PieceGetCreatorMethod = AccessTools.Method(typeof(Piece), "GetCreator", Type.EmptyTypes, (Type[])null); private static Sprite _lockSprite; private static bool _modCompatibilityInitialized; private static bool _supportedSlotModLoaded; private static readonly List<MethodInfo> ModProtectionBoolMethods = new List<MethodInfo>(); private static readonly List<MethodInfo> ModProtectionItemListMethods = new List<MethodInfo>(); private static readonly List<InputVisibilityProbe> InputVisibilityProbes = new List<InputVisibilityProbe>(); private static readonly List<RegisteredContainer> ContainerRegistry = new List<RegisteredContainer>(); private static readonly Dictionary<int, RegisteredContainer> ContainerRegistryById = new Dictionary<int, RegisteredContainer>(); private const float ContainerSpatialCellSize = 32f; private static readonly Dictionary<long, List<RegisteredContainer>> StaticContainerBuckets = new Dictionary<long, List<RegisteredContainer>>(); private static readonly List<RegisteredContainer> DynamicContainers = new List<RegisteredContainer>(); private static readonly Type RigidbodyType = AccessTools.TypeByName("UnityEngine.Rigidbody"); private static bool _containerRegistrySeeded; private void Awake() { //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Expected O, but got Unknown //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Expected O, but got Unknown //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("01 - General", "Enabled", true, "Enable or disable HotDeposit."); EnableKeyBinds = ((BaseUnityPlugin)this).Config.Bind<bool>("02 - Hotkeys", "EnableKeyBinds", true, "Enable or disable all HotDeposit keyboard/mouse shortcuts."); AllDepositKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("02 - Hotkeys", "AllDeposit", (KeyCode)104, "Spread matching inventory items across nearby storage that already contains those item types."); HoveredChestKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("02 - Hotkeys", "HoveredChest", (KeyCode)104, "Hovered-chest action. This key only activates while hovering an eligible player-built chest."); LockKeybind = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("02 - Hotkeys", "LockKeybind", new KeyboardShortcut((KeyCode)323, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Combined shortcut used to lock or unlock a normal inventory item."); DepositDistance = ((BaseUnityPlugin)this).Config.Bind<float>("03 - Storage", "DepositDistance", 10f, new ConfigDescription("Maximum hot-deposit distance in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 300f), Array.Empty<object>())); IgnoreHotbar = ((BaseUnityPlugin)this).Config.Bind<bool>("03 - Storage", "IgnoreHotbar", true, "Do not hot-deposit items located in the hotbar row."); IgnoreEquipped = ((BaseUnityPlugin)this).Config.Bind<bool>("03 - Storage", "IgnoreEquipped", true, "Do not hot-deposit currently equipped items."); HoveredChestDepositAll = ((BaseUnityPlugin)this).Config.Bind<bool>("03 - Storage", "HoveredChestDepositAll", true, "When true, HoveredChest performs Hot Deposit All across matching nearby storage. When false, it uses the hovered chest and only deposits matching item types."); ShowHoverPrompt = ((BaseUnityPlugin)this).Config.Bind<bool>("03 - Storage", "ShowHoverPrompt", true, "Retained for config compatibility. The per-container hover-text hook is disabled in 1.0.1 performance mode to avoid chest-area FPS loss."); ShowLockIcon = ((BaseUnityPlugin)this).Config.Bind<bool>("04 - Item Lock", "ShowLockIcon", true, "Show a visible padlock marker on locked inventory items."); ShowDepositPopup = ((BaseUnityPlugin)this).Config.Bind<bool>("05 - Notifications", "ShowDepositPopup", true, "Show a level-up-style notification after a successful deposit."); EnsureLockSprite(); InitializeInputVisibilityChecks(); _harmony = new Harmony("Moopfam.HotDeposit"); _harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)("HotDeposit 1.0.2 loaded. " + $"AllDeposit={AllDepositKey.Value}, HoveredChest={HoveredChestKey.Value}, " + $"Lock={LockKeybind.Value}, " + $"Distance={DepositDistance.Value:0.#}m.")); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private void Update() { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0064: 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_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) if (Enabled == null || !Enabled.Value || EnableKeyBinds == null || !EnableKeyBinds.Value) { return; } KeyCode val = (KeyCode)((AllDepositKey != null) ? ((int)AllDepositKey.Value) : 0); KeyCode val2 = (KeyCode)((HoveredChestKey != null) ? ((int)HoveredChestKey.Value) : 0); bool flag = (int)val != 0 && (int)val2 != 0 && val == val2; bool flag2 = (int)val != 0 && Input.GetKeyDown(val); bool flag3 = (int)val2 != 0 && Input.GetKeyDown(val2); if (!flag2 && !flag3) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || IsTypingOrConsoleOpen()) { return; } try { ContainerTarget hoveredEligibleTarget = GetHoveredEligibleTarget(localPlayer); if (flag) { if (flag2) { if (hoveredEligibleTarget != null) { HotDepositHoveredChest(localPlayer, hoveredEligibleTarget); } else { HotDepositNearby(localPlayer); } } } else if (flag3 && hoveredEligibleTarget != null) { HotDepositHoveredChest(localPlayer, hoveredEligibleTarget); } else if (flag2) { HotDepositNearby(localPlayer); } } catch (Exception arg) { ManualLogSource log = Log; if (log != null) { log.LogError((object)string.Format("{0}: hot deposit failed: {1}", "HotDeposit", arg)); } ShowMessage(localPlayer, "Hot Deposit failed. Check BepInEx log."); } } private static ContainerTarget GetHoveredEligibleTarget(Player player) { Container hoveredContainer = GetHoveredContainer(player); if ((Object)(object)hoveredContainer == (Object)null) { return null; } return CreateContainerTarget(player, hoveredContainer, enforceDepositDistance: false); } private static void HotDepositNearby(Player player) { List<ContainerTarget> list = FindEligibleContainers(player); if (list.Count == 0) { ShowMessage(player, "No storage nearby"); } else { DepositIntoTargets(player, list, requireExistingMatch: true, "No items to deposit", "All Deposit"); } } private static void HotDepositHoveredChest(Player player, ContainerTarget hoveredTarget) { if (hoveredTarget == null) { return; } if (HoveredChestDepositAll != null && HoveredChestDepositAll.Value) { List<ContainerTarget> list = FindEligibleContainers(player); if (list.Count == 0) { ShowMessage(player, "No storage nearby"); } else { DepositIntoTargets(player, list, requireExistingMatch: true, "No items to deposit", "Hot Deposit All"); } } else { DepositIntoTargets(player, new List<ContainerTarget> { hoveredTarget }, requireExistingMatch: true, "No items to deposit", "Hot Deposit"); } } private static void DepositIntoTargets(Player player, List<ContainerTarget> targets, bool requireExistingMatch, string noMatchMessage, string successTitle) { Inventory inventory = ((Humanoid)player).GetInventory(); if (inventory == null || targets == null || targets.Count == 0) { return; } List<ItemData> list = GetInventoryItems(inventory).ToList(); List<PlayerDepositItem> list2 = new List<PlayerDepositItem>(); HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); foreach (ItemData item2 in list) { if (item2 != null && item2.m_stack > 0 && !IsLocked(item2) && !ShouldSkipPlayerItem(item2)) { string itemKey = GetItemKey(item2); if (!string.IsNullOrEmpty(itemKey)) { list2.Add(new PlayerDepositItem { Item = item2, ItemKey = itemKey, DisplayName = GetItemDisplayName(item2) }); hashSet.Add(itemKey); } } } if (list2.Count == 0) { ShowMessage(player, noMatchMessage); return; } Dictionary<string, List<ContainerTarget>> dictionary = BuildTargetItemIndex(targets, hashSet); int num = 0; HashSet<Container> hashSet2 = new HashSet<Container>(); Dictionary<string, int> dictionary2 = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase); foreach (PlayerDepositItem item3 in list2) { ItemData item = item3.Item; if (item == null || item.m_stack <= 0) { continue; } string itemKey2 = item3.ItemKey; string displayName = item3.DisplayName; List<ContainerTarget> value; if (requireExistingMatch) { if (!dictionary.TryGetValue(itemKey2, out value) || value == null || value.Count == 0) { continue; } } else { value = targets; } int stack = item.m_stack; if (requireExistingMatch) { foreach (ContainerTarget item4 in value) { if (item.m_stack <= 0) { break; } if (EnsureContainerOwnership(item4)) { int num2 = TransferIntoExistingStacksIndexed(item4, item, itemKey2, item.m_stack); if (num2 > 0) { num += num2; hashSet2.Add(item4.Container); } } } bool flag = true; while (item.m_stack > 0 && flag) { flag = false; foreach (ContainerTarget item5 in value) { if (item.m_stack <= 0) { break; } if (EnsureContainerOwnership(item5)) { int num3 = ((item.m_shared != null) ? item.m_shared.m_maxStackSize : item.m_stack); int num4 = TransferIntoNewStacksIndexed(item5, item, itemKey2, Mathf.Min(item.m_stack, num3), 1); if (num4 > 0) { num += num4; hashSet2.Add(item5.Container); flag = true; } } } } if (item.m_stack <= 0) { try { inventory.RemoveItem(item); } catch { } } } else { foreach (ContainerTarget item6 in value) { if (item.m_stack <= 0) { break; } if (EnsureContainerOwnership(item6)) { int num5 = TransferItemAmount(inventory, item6.Inventory, item, item.m_stack); if (num5 > 0) { num += num5; hashSet2.Add(item6.Container); } } } } int num6 = Mathf.Max(0, stack - item.m_stack); if (num6 > 0) { dictionary2.TryGetValue(displayName, out var value2); dictionary2[displayName] = value2 + num6; } } if (num > 0) { NotifyInventoryChanged(inventory); foreach (ContainerTarget target in targets) { if (target != null && target.Inventory != null && (Object)(object)target.Container != (Object)null && hashSet2.Contains(target.Container)) { NotifyInventoryChanged(target.Inventory); } } ShowDepositNotification(player, successTitle, dictionary2); } else { ShowMessage(player, noMatchMessage); } } private static Dictionary<string, List<ContainerTarget>> BuildTargetItemIndex(List<ContainerTarget> targets, HashSet<string> requiredItemKeys) { Dictionary<string, List<ContainerTarget>> dictionary = new Dictionary<string, List<ContainerTarget>>(StringComparer.OrdinalIgnoreCase); foreach (ContainerTarget target in targets) { if (target == null || target.Inventory == null) { continue; } PrepareTargetItemIndex(target, requiredItemKeys); foreach (string key in target.ItemStacksByKey.Keys) { if (!dictionary.TryGetValue(key, out var value)) { value = (dictionary[key] = new List<ContainerTarget>()); } value.Add(target); } } return dictionary; } private static void PrepareTargetItemIndex(ContainerTarget target, HashSet<string> requiredItemKeys) { target.ItemStacksByKey = new Dictionary<string, List<ItemData>>(StringComparer.OrdinalIgnoreCase); foreach (ItemData inventoryItem in GetInventoryItems(target.Inventory)) { if (inventoryItem == null || inventoryItem.m_stack <= 0) { continue; } string itemKey = GetItemKey(inventoryItem); if (!string.IsNullOrEmpty(itemKey) && (requiredItemKeys == null || requiredItemKeys.Contains(itemKey))) { if (!target.ItemStacksByKey.TryGetValue(itemKey, out var value)) { value = new List<ItemData>(); target.ItemStacksByKey[itemKey] = value; } value.Add(inventoryItem); } } foreach (List<ItemData> value2 in target.ItemStacksByKey.Values) { value2.Sort(CompareItemGridPosition); } } private static int CompareItemGridPosition(ItemData a, ItemData b) { if (a == b) { return 0; } if (a == null) { return 1; } if (b == null) { return -1; } int num = a.m_gridPos.y.CompareTo(b.m_gridPos.y); return (num != 0) ? num : a.m_gridPos.x.CompareTo(b.m_gridPos.x); } private static bool EnsureContainerOwnership(ContainerTarget target) { if (target == null || (Object)(object)target.Container == (Object)null) { return false; } if (target.OwnershipState > 0) { return true; } if (target.OwnershipState < 0) { return false; } bool flag = ClaimContainerOwnership(target.Container); target.OwnershipState = (flag ? 1 : (-1)); return flag; } private static int TransferIntoExistingStacksIndexed(ContainerTarget target, ItemData source, string itemKey, int requestedAmount) { if (target == null || target.Inventory == null || target.ItemStacksByKey == null || source == null || source.m_shared == null || requestedAmount <= 0) { return 0; } if (!target.ItemStacksByKey.TryGetValue(itemKey, out var value) || value == null) { return 0; } int num = Mathf.Min(requestedAmount, source.m_stack); int num2 = 0; foreach (ItemData item in value) { if (num <= 0 || source.m_stack <= 0) { break; } if (item != null && item.m_shared != null && item.m_stack > 0 && item.m_stack < item.m_shared.m_maxStackSize && item.m_quality == source.m_quality && item.m_worldLevel == source.m_worldLevel) { int num3 = item.m_shared.m_maxStackSize - item.m_stack; if (num3 > 0) { int num4 = Mathf.Min(num, Mathf.Min(source.m_stack, num3)); item.m_stack += num4; source.m_stack -= num4; num -= num4; num2 += num4; } } } return num2; } private static int TransferIntoNewStacksIndexed(ContainerTarget target, ItemData item, string itemKey, int requestedAmount, int maxNewStacks) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) if (target == null || target.Inventory == null || item == null || item.m_shared == null || requestedAmount <= 0 || maxNewStacks <= 0) { return 0; } int num = Mathf.Min(requestedAmount, item.m_stack); int num2 = 0; int num3 = 0; while (num > 0 && item.m_stack > 0 && num3 < maxNewStacks) { Vector2i val = FindEmptySlot(target.Inventory, item); if (val.x < 0 || val.y < 0) { break; } int num4 = Mathf.Min(num, Mathf.Min(item.m_stack, item.m_shared.m_maxStackSize)); ItemData val2 = item.Clone(); val2.m_stack = num4; val2.m_gridPos = val; target.Inventory.GetAllItems().Add(val2); if (target.ItemStacksByKey == null) { target.ItemStacksByKey = new Dictionary<string, List<ItemData>>(StringComparer.OrdinalIgnoreCase); } if (!target.ItemStacksByKey.TryGetValue(itemKey, out var value)) { value = new List<ItemData>(); target.ItemStacksByKey[itemKey] = value; } int num5 = value.BinarySearch(val2, ItemGridPositionComparer.Instance); if (num5 < 0) { num5 = ~num5; } value.Insert(num5, val2); item.m_stack -= num4; num -= num4; num2 += num4; num3++; } return num2; } private static int TransferItemAmount(Inventory fromInventory, Inventory toInventory, ItemData item, int requestedAmount) { if (fromInventory == null || toInventory == null || item == null || item.m_shared == null || requestedAmount <= 0) { return 0; } int num = Mathf.Min(requestedAmount, GetStack(item)); int num2 = 0; int num3 = TransferIntoExistingStacks(toInventory, item, num); num2 += num3; num -= num3; if (num > 0 && GetStack(item) > 0) { int num4 = TransferIntoNewStacks(toInventory, item, num, int.MaxValue); num2 += num4; } if (GetStack(item) <= 0) { try { fromInventory.RemoveItem(item); } catch { } } return num2; } private static int TransferIntoExistingStacks(Inventory toInventory, ItemData source, int requestedAmount) { if (toInventory == null || source == null || source.m_shared == null || requestedAmount <= 0) { return 0; } int num = Mathf.Min(requestedAmount, GetStack(source)); int num2 = 0; List<ItemData> list = (from destination in GetInventoryItems(toInventory) where IsCompatiblePartialStack(destination, source) orderby destination.m_gridPos.y, destination.m_gridPos.x select destination).ToList(); foreach (ItemData item in list) { if (num <= 0 || GetStack(source) <= 0) { break; } int num3 = item.m_shared.m_maxStackSize - item.m_stack; if (num3 > 0) { int num4 = Mathf.Min(num, Mathf.Min(GetStack(source), num3)); item.m_stack += num4; ItemData obj = source; obj.m_stack -= num4; num -= num4; num2 += num4; } } return num2; } private static bool IsCompatiblePartialStack(ItemData destination, ItemData source) { if (destination == null || source == null || destination.m_shared == null || source.m_shared == null) { return false; } if (destination.m_stack <= 0 || destination.m_stack >= destination.m_shared.m_maxStackSize) { return false; } if (!string.Equals(GetItemKey(destination), GetItemKey(source), StringComparison.OrdinalIgnoreCase)) { return false; } if (destination.m_quality != source.m_quality) { return false; } if (destination.m_worldLevel != source.m_worldLevel) { return false; } return true; } private static int TransferIntoNewStacks(Inventory toInventory, ItemData item, int requestedAmount, int maxNewStacks) { //IL_0043: 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_004a: 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_009d: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) if (toInventory == null || item == null || item.m_shared == null || requestedAmount <= 0 || maxNewStacks <= 0) { return 0; } int num = Mathf.Min(requestedAmount, GetStack(item)); int num2 = 0; int num3 = 0; while (num > 0 && GetStack(item) > 0 && num3 < maxNewStacks) { Vector2i val = FindEmptySlot(toInventory, item); if (val.x < 0 || val.y < 0) { break; } int num4 = Mathf.Min(num, Mathf.Min(GetStack(item), item.m_shared.m_maxStackSize)); ItemData val2 = item.Clone(); val2.m_stack = num4; val2.m_gridPos = val; toInventory.GetAllItems().Add(val2); item.m_stack -= num4; num -= num4; num2 += num4; num3++; } return num2; } private static string GetItemDisplayName(ItemData item) { if (item == null || item.m_shared == null || string.IsNullOrEmpty(item.m_shared.m_name)) { string itemKey = GetItemKey(item); return string.IsNullOrEmpty(itemKey) ? "Item" : itemKey; } return item.m_shared.m_name.TrimStart(new char[1] { '$' }); } private static Vector2i FindEmptySlot(Inventory inventory, ItemData item) { //IL_008f: 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) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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) Vector2i result = default(Vector2i); ((Vector2i)(ref result))..ctor(-1, -1); if (inventory == null || item == null || InventoryFindEmptySlotMethod == null || InventoryTopFirstMethod == null) { return result; } try { bool flag = Convert.ToBoolean(InventoryTopFirstMethod.Invoke(inventory, new object[1] { item })); if (InventoryFindEmptySlotMethod.Invoke(inventory, new object[1] { flag }) is Vector2i result2) { return result2; } } catch { } return result; } private static void NotifyInventoryChanged(Inventory inventory) { if (inventory == null || InventoryChangedMethod == null) { return; } try { InventoryChangedMethod.Invoke(inventory, new object[2] { false, false }); } catch { } } internal static string GetHoveredChestPrompt(Container container) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) if (Enabled == null || !Enabled.Value || EnableKeyBinds == null || !EnableKeyBinds.Value || ShowHoverPrompt == null || !ShowHoverPrompt.Value || HoveredChestKey == null || (int)HoveredChestKey.Value == 0 || (Object)(object)container == (Object)null) { return string.Empty; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return string.Empty; } RegisteredContainer orCreateContainerEntry = GetOrCreateContainerEntry(container); if (orCreateContainerEntry == null) { return string.Empty; } EnsureContainerMetadata(orCreateContainerEntry); if (orCreateContainerEntry.IsTombStone || !IsPlayerBuiltStorage(orCreateContainerEntry)) { return string.Empty; } bool flag = HoveredChestDepositAll != null && HoveredChestDepositAll.Value; string text = $"<color=#FFFF00>{HoveredChestKey.Value}</color>"; return flag ? ("[" + text + "] Hot Deposit All") : ("[" + text + "] Hot Deposit"); } private static Container GetHoveredContainer(Player player) { if ((Object)(object)player == (Object)null) { return null; } GameObject val = null; try { if (PlayerGetHoverObjectMethod != null) { object? obj = PlayerGetHoverObjectMethod.Invoke(player, null); val = (GameObject)((obj is GameObject) ? obj : null); } } catch { return null; } if ((Object)(object)val == (Object)null) { return null; } Container val2 = val.GetComponent<Container>() ?? val.GetComponentInParent<Container>(); if ((Object)(object)val2 != (Object)null) { return val2; } return val.GetComponentInChildren<Container>(); } private static ContainerTarget CreateContainerTarget(Player player, Container container, bool enforceDepositDistance) { RegisteredContainer orCreateContainerEntry = GetOrCreateContainerEntry(container); return CreateContainerTarget(player, orCreateContainerEntry, enforceDepositDistance); } private static ContainerTarget CreateContainerTarget(Player player, RegisteredContainer entry, bool enforceDepositDistance) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0068: 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_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || entry == null || (Object)(object)entry.Container == (Object)null) { return null; } Container container = entry.Container; Vector3 val = entry.CachedPosition; if (entry.IsDynamic) { try { val = (entry.CachedPosition = ((Component)container).transform.position); } catch { return null; } } Vector3 val2 = val - ((Component)player).transform.position; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (enforceDepositDistance) { float num = ((DepositDistance != null) ? Mathf.Max(1f, DepositDistance.Value) : 10f); if (sqrMagnitude > num * num) { return null; } } if (!((Component)container).gameObject.activeInHierarchy) { return null; } EnsureContainerMetadata(entry); if (entry.IsTombStone) { return null; } if (!IsPlayerBuiltStorage(entry)) { return null; } if (!CheckContainerAccess(container, player.GetPlayerID())) { return null; } if (IsContainerInUse(container)) { return null; } Inventory val3 = entry.Inventory; if (val3 == null) { val3 = (entry.Inventory = GetContainerInventory(container)); } if (val3 == null) { return null; } return new ContainerTarget { Container = container, Inventory = val3, DistanceSq = sqrMagnitude }; } internal static void RegisterContainer(Container container) { //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)container == (Object)null) { return; } int instanceID; try { instanceID = ((Object)container).GetInstanceID(); } catch { return; } if (ContainerRegistryById.TryGetValue(instanceID, out var value)) { if (value != null && (Object)(object)value.Container != (Object)null && value.Container == container) { return; } if (value != null) { RemoveFromSpatialIndex(value); ContainerRegistry.Remove(value); } ContainerRegistryById.Remove(instanceID); } RegisteredContainer registeredContainer = new RegisteredContainer { Container = container, InstanceId = instanceID }; try { registeredContainer.CachedPosition = ((Component)container).transform.position; if (RigidbodyType != null) { registeredContainer.IsDynamic = (Object)(object)((Component)container).GetComponentInParent(RigidbodyType) != (Object)null; } } catch { registeredContainer.CachedPosition = Vector3.zero; registeredContainer.IsDynamic = true; } ContainerRegistry.Add(registeredContainer); ContainerRegistryById[instanceID] = registeredContainer; AddToSpatialIndex(registeredContainer); } private static int GetSpatialCell(float coordinate) { return Mathf.FloorToInt(coordinate / 32f); } private static long GetSpatialCellKey(int x, int z) { return ((long)x << 32) ^ (uint)z; } private static void AddToSpatialIndex(RegisteredContainer entry) { if (entry == null) { return; } if (entry.IsDynamic) { DynamicContainers.Add(entry); return; } entry.CellX = GetSpatialCell(entry.CachedPosition.x); entry.CellZ = GetSpatialCell(entry.CachedPosition.z); long spatialCellKey = GetSpatialCellKey(entry.CellX, entry.CellZ); if (!StaticContainerBuckets.TryGetValue(spatialCellKey, out var value)) { value = new List<RegisteredContainer>(); StaticContainerBuckets[spatialCellKey] = value; } value.Add(entry); } private static void RemoveFromSpatialIndex(RegisteredContainer entry) { if (entry == null) { return; } if (entry.IsDynamic) { DynamicContainers.Remove(entry); return; } long spatialCellKey = GetSpatialCellKey(entry.CellX, entry.CellZ); if (StaticContainerBuckets.TryGetValue(spatialCellKey, out var value)) { value.Remove(entry); if (value.Count == 0) { StaticContainerBuckets.Remove(spatialCellKey); } } } private static RegisteredContainer GetOrCreateContainerEntry(Container container) { if ((Object)(object)container == (Object)null) { return null; } int instanceID; try { instanceID = ((Object)container).GetInstanceID(); } catch { return null; } if (ContainerRegistryById.TryGetValue(instanceID, out var value)) { return value; } RegisterContainer(container); ContainerRegistryById.TryGetValue(instanceID, out value); return value; } private static void EnsureContainerRegistrySeeded() { if (_containerRegistrySeeded) { return; } _containerRegistrySeeded = true; if (ContainerRegistry.Count <= 0) { Container[] array = Object.FindObjectsByType<Container>((FindObjectsSortMode)0); Container[] array2 = array; foreach (Container container in array2) { RegisterContainer(container); } } } private static void PruneDestroyedContainers() { for (int num = ContainerRegistry.Count - 1; num >= 0; num--) { RegisteredContainer registeredContainer = ContainerRegistry[num]; if (registeredContainer == null || !((Object)(object)registeredContainer.Container != (Object)null)) { if (registeredContainer != null) { RemoveFromSpatialIndex(registeredContainer); ContainerRegistryById.Remove(registeredContainer.InstanceId); } ContainerRegistry.RemoveAt(num); } } } private static void EnsureContainerMetadata(RegisteredContainer entry) { if (entry == null || (Object)(object)entry.Container == (Object)null || entry.MetadataInitialized) { return; } entry.MetadataInitialized = true; try { entry.Piece = ((Component)entry.Container).GetComponentInParent<Piece>(); entry.IsTombStone = (Object)(object)((Component)entry.Container).GetComponentInParent<TombStone>() != (Object)null; } catch { } } private static bool IsPlayerBuiltStorage(RegisteredContainer entry) { if (entry == null || (Object)(object)entry.Container == (Object)null) { return false; } EnsureContainerMetadata(entry); if (entry.PlayerBuiltConfirmed) { return true; } Piece val = entry.Piece; if ((Object)(object)val == (Object)null) { try { val = (entry.Piece = ((Component)entry.Container).GetComponentInParent<Piece>()); } catch { return false; } } if ((Object)(object)val == (Object)null || PieceGetCreatorMethod == null) { return false; } try { object value = PieceGetCreatorMethod.Invoke(val, null); long num = Convert.ToInt64(value); if (num != 0) { entry.PlayerBuiltConfirmed = true; return true; } return false; } catch { return false; } } private static bool IsPlayerBuiltStorage(Container container) { return IsPlayerBuiltStorage(GetOrCreateContainerEntry(container)); } private static List<ContainerTarget> FindEligibleContainers(Player player) { //IL_004f: 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_0055: 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_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return new List<ContainerTarget>(); } EnsureContainerRegistrySeeded(); List<ContainerTarget> list = new List<ContainerTarget>(); float num = ((DepositDistance != null) ? Mathf.Max(1f, DepositDistance.Value) : 10f); Vector3 position = ((Component)player).transform.position; int spatialCell = GetSpatialCell(position.x - num); int spatialCell2 = GetSpatialCell(position.x + num); int spatialCell3 = GetSpatialCell(position.z - num); int spatialCell4 = GetSpatialCell(position.z + num); for (int i = spatialCell; i <= spatialCell2; i++) { for (int j = spatialCell3; j <= spatialCell4; j++) { if (!StaticContainerBuckets.TryGetValue(GetSpatialCellKey(i, j), out var value) || value == null) { continue; } for (int num2 = value.Count - 1; num2 >= 0; num2--) { RegisteredContainer registeredContainer = value[num2]; if (registeredContainer == null || (Object)(object)registeredContainer.Container == (Object)null) { if (registeredContainer != null) { ContainerRegistryById.Remove(registeredContainer.InstanceId); } value.RemoveAt(num2); } else { ContainerTarget containerTarget = CreateContainerTarget(player, registeredContainer, enforceDepositDistance: true); if (containerTarget != null) { list.Add(containerTarget); } } } if (value.Count == 0) { StaticContainerBuckets.Remove(GetSpatialCellKey(i, j)); } } } for (int num3 = DynamicContainers.Count - 1; num3 >= 0; num3--) { RegisteredContainer registeredContainer2 = DynamicContainers[num3]; if (registeredContainer2 == null || (Object)(object)registeredContainer2.Container == (Object)null) { if (registeredContainer2 != null) { ContainerRegistryById.Remove(registeredContainer2.InstanceId); } DynamicContainers.RemoveAt(num3); } else { ContainerTarget containerTarget2 = CreateContainerTarget(player, registeredContainer2, enforceDepositDistance: true); if (containerTarget2 != null) { list.Add(containerTarget2); } } } list.Sort((ContainerTarget a, ContainerTarget b) => a.DistanceSq.CompareTo(b.DistanceSq)); return list; } private static bool ShouldSkipPlayerItem(ItemData item) { if (item == null) { return true; } if (IsProtectedBySupportedInventoryMods(item)) { return true; } if (IgnoreEquipped != null && IgnoreEquipped.Value && IsItemEquipped(item)) { return true; } if (IgnoreHotbar != null && IgnoreHotbar.Value && IsItemInHotbar(item)) { return true; } return false; } private static bool IsProtectedBySupportedInventoryMods(ItemData item) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (item == null) { return false; } EnsureModCompatibility(); if (_supportedSlotModLoaded) { try { Vector2i gridPos = item.m_gridPos; int nativePlayerInventoryRows = GetNativePlayerInventoryRows(); if (gridPos.y < 0 || gridPos.y >= nativePlayerInventoryRows) { return true; } } catch { } } foreach (MethodInfo modProtectionBoolMethod in ModProtectionBoolMethods) { try { if (!TryBuildCompatibilityArguments(modProtectionBoolMethod.GetParameters(), item, out var args) || !(modProtectionBoolMethod.Invoke(null, args) is int num) || num == 0) { continue; } return true; } catch { } } foreach (MethodInfo modProtectionItemListMethod in ModProtectionItemListMethods) { try { if (!TryBuildCompatibilityArguments(modProtectionItemListMethod.GetParameters(), item, out var args2) || !(modProtectionItemListMethod.Invoke(null, args2) is IEnumerable enumerable)) { continue; } foreach (object item2 in enumerable) { if (item2 == item) { return true; } } } catch { } } return false; } private static int GetNativePlayerInventoryRows() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return 4; } try { string s = null; if (localPlayer.TryGetUniqueKeyValue("invrows", ref s) && int.TryParse(s, out var result)) { return Mathf.Clamp(result, 4, 9); } } catch { } if (!_supportedSlotModLoaded) { try { Inventory inventory = ((Humanoid)localPlayer).GetInventory(); if (inventory != null) { return Mathf.Clamp(inventory.GetHeight(), 4, 9); } } catch { } } return 4; } private static void EnsureModCompatibility() { if (_modCompatibilityInitialized) { return; } _modCompatibilityInitialized = true; string[] source = new string[2] { "EquipmentAndQuickSlots", "BetterArchery" }; string[] source2 = new string[5] { "IsGridPositionASlot", "IsEquipmentSlotItem", "IsItemInEquipmentSlot", "IsCustomSlotItem", "IsQuiverSlot" }; string[] source3 = new string[3] { "GetAllSlotItems", "GetQuickSlotItems", "GetEquipmentSlotItems" }; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { string assemblyName = null; try { assemblyName = assembly.GetName().Name; } catch { } if (!source.Any((string supportedName) => string.Equals(supportedName, assemblyName, StringComparison.OrdinalIgnoreCase))) { continue; } _supportedSlotModLoaded = true; Type[] array; try { array = assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { array = ex.Types.Where((Type type2) => type2 != null).ToArray(); } catch { continue; } Type[] array2 = array; foreach (Type type in array2) { if (type == null) { continue; } MethodInfo[] methods; try { methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } catch { continue; } MethodInfo[] array3 = methods; foreach (MethodInfo methodInfo in array3) { if (methodInfo == null || methodInfo.ContainsGenericParameters) { continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); if (methodInfo.ReturnType == typeof(bool) && source2.Contains(methodInfo.Name) && CanBuildCompatibilityArguments(parameters)) { if (!ModProtectionBoolMethods.Contains(methodInfo)) { ModProtectionBoolMethods.Add(methodInfo); } } else if (source3.Contains(methodInfo.Name) && typeof(IEnumerable).IsAssignableFrom(methodInfo.ReturnType) && CanBuildCompatibilityArguments(parameters) && !ModProtectionItemListMethods.Contains(methodInfo)) { ModProtectionItemListMethods.Add(methodInfo); } } } } ManualLogSource log = Log; if (log != null) { log.LogInfo((object)("HotDeposit: BetterArchery / EquipmentAndQuickSlots " + $"protection hooks: {ModProtectionBoolMethods.Count} checks, " + $"{ModProtectionItemListMethods.Count} item lists.")); } } private static bool CanBuildCompatibilityArguments(ParameterInfo[] parameters) { if (parameters == null) { return true; } foreach (ParameterInfo parameterInfo in parameters) { Type parameterType = parameterInfo.ParameterType; if (parameterType == typeof(ItemData) || parameterType == typeof(Vector2i) || parameterType == typeof(Inventory) || parameterType == typeof(Player)) { continue; } if (parameterType == typeof(int)) { string text = (parameterInfo.Name ?? string.Empty).ToLowerInvariant(); if (text == "x" || text == "y" || text.Contains("row") || text.Contains("column")) { continue; } } if (parameterInfo.HasDefaultValue) { continue; } return false; } return true; } private static bool TryBuildCompatibilityArguments(ParameterInfo[] parameters, ItemData item, out object[] args) { //IL_0043: 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_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) args = new object[(parameters != null) ? parameters.Length : 0]; if (parameters == null || parameters.Length == 0) { return true; } Player localPlayer = Player.m_localPlayer; Inventory val = (((Object)(object)localPlayer != (Object)null) ? ((Humanoid)localPlayer).GetInventory() : null); Vector2i gridPos = item.m_gridPos; for (int i = 0; i < parameters.Length; i++) { ParameterInfo parameterInfo = parameters[i]; Type parameterType = parameterInfo.ParameterType; if (parameterType == typeof(ItemData)) { args[i] = item; continue; } if (parameterType == typeof(Vector2i)) { args[i] = gridPos; continue; } if (parameterType == typeof(Inventory)) { if (val == null) { return false; } args[i] = val; continue; } if (parameterType == typeof(Player)) { if ((Object)(object)localPlayer == (Object)null) { return false; } args[i] = localPlayer; continue; } if (parameterType == typeof(int)) { string text = (parameterInfo.Name ?? string.Empty).ToLowerInvariant(); if (text == "x" || text.Contains("column")) { args[i] = gridPos.x; continue; } if (text == "y" || text.Contains("row")) { args[i] = gridPos.y; continue; } } if (parameterInfo.HasDefaultValue) { args[i] = parameterInfo.DefaultValue; continue; } return false; } return true; } internal static bool TryHandleLockClick(object[] args) { if (Enabled == null || !Enabled.Value || EnableKeyBinds == null || !EnableKeyBinds.Value) { return false; } if (!IsLockHotkeyHeld()) { return false; } ItemData val = FindItemArg(args); if (val == null || !IsPlayerInventoryItem(val)) { return false; } if (IsItemInHotbar(val)) { ShowMessage(Player.m_localPlayer, "Hotbar items are already protected"); return true; } if (IsProtectedBySupportedInventoryMods(val)) { ShowMessage(Player.m_localPlayer, "Equipment / quiver items are already protected"); return true; } bool flag = ToggleLock(val); ShowMessage(Player.m_localPlayer, flag ? "Item locked" : "Item unlocked"); RefreshInventoryGui(); return true; } private static bool IsLockHotkeyHeld() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (LockKeybind == null) { return false; } try { KeyboardShortcut value = LockKeybind.Value; return ((KeyboardShortcut)(ref value)).IsPressed(); } catch { return false; } } private static ItemData FindItemArg(object[] args) { if (args == null) { return null; } foreach (object obj in args) { ItemData val = (ItemData)((obj is ItemData) ? obj : null); if (val != null) { return val; } } return null; } private static bool IsPlayerInventoryItem(ItemData item) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || item == null) { return false; } Inventory inventory = ((Humanoid)localPlayer).GetInventory(); if (inventory == null) { return false; } foreach (ItemData inventoryItem in GetInventoryItems(inventory)) { if (inventoryItem == item) { return true; } } return false; } internal static bool IsLocked(ItemData item) { IDictionary customData = GetCustomData(item); if (customData == null || !customData.Contains("Moopfam.HotDeposit.Locked")) { return false; } object obj = customData["Moopfam.HotDeposit.Locked"]; return obj != null && string.Equals(obj.ToString(), "1", StringComparison.OrdinalIgnoreCase); } private static bool ToggleLock(ItemData item) { IDictionary customData = GetCustomData(item); if (customData == null) { return false; } bool flag = !IsLocked(item); if (flag) { customData["Moopfam.HotDeposit.Locked"] = "1"; } else if (customData.Contains("Moopfam.HotDeposit.Locked")) { customData.Remove("Moopfam.HotDeposit.Locked"); } return flag; } private static IDictionary GetCustomData(ItemData item) { if (item == null || ItemCustomDataField == null) { return null; } try { object value = ItemCustomDataField.GetValue(item); return value as IDictionary; } catch { return null; } } internal static void UpdateLockVisuals(InventoryGrid grid) { if ((Object)(object)grid == (Object)null || ShowLockIcon == null || !ShowLockIcon.Value || InventoryGridElementsField == null) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } Inventory val = null; try { val = grid.GetInventory(); } catch { return; } if (val == null || val != ((Humanoid)localPlayer).GetInventory()) { return; } IList list = null; try { list = InventoryGridElementsField.GetValue(grid) as IList; } catch { } if (list == null) { return; } int width = val.GetWidth(); if (width <= 0) { return; } for (int i = 0; i < list.Count; i++) { object obj3 = list[i]; Component val2 = (Component)((obj3 is Component) ? obj3 : null); if (!((Object)(object)val2 == (Object)null)) { int x = i % width; int y = i / width; ItemData inventoryItemAt = GetInventoryItemAt(val, x, y); SetLockVisual(val2.transform, inventoryItemAt != null && !IsItemInHotbar(inventoryItemAt) && !IsProtectedBySupportedInventoryMods(inventoryItemAt) && IsLocked(inventoryItemAt)); } } } private static ItemData GetInventoryItemAt(Inventory inventory, int x, int y) { if (inventory == null || x < 0 || y < 0 || InventoryGetItemAtMethod == null) { return null; } try { object? obj = InventoryGetItemAtMethod.Invoke(inventory, new object[2] { x, y }); return (ItemData)((obj is ItemData) ? obj : null); } catch { return null; } } private static void SetLockVisual(Transform parent, bool visible) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Expected O, but got Unknown //IL_011b: 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_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0160: 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_01a2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)parent == (Object)null) { return; } Transform val = parent.Find("HotDepositLockBorder"); GameObject val2 = (((Object)(object)val != (Object)null) ? ((Component)val).gameObject : null); if ((Object)(object)val2 == (Object)null && visible) { val2 = CreateLockBorder(parent, new Color(1f, 0.75f, 0f, 1f)); } if ((Object)(object)val2 != (Object)null) { val2.SetActive(visible); if (visible) { val2.transform.SetAsLastSibling(); } } Transform val3 = parent.Find("HotDepositLockIcon"); GameObject val4 = (((Object)(object)val3 != (Object)null) ? ((Component)val3).gameObject : null); if ((Object)(object)val4 == (Object)null && visible) { EnsureLockSprite(); val4 = new GameObject("HotDepositLockIcon", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); RectTransform component = val4.GetComponent<RectTransform>(); ((Transform)component).SetParent(parent, false); component.anchorMin = new Vector2(1f, 1f); component.anchorMax = new Vector2(1f, 1f); component.pivot = new Vector2(1f, 1f); component.anchoredPosition = new Vector2(-4f, -4f); component.sizeDelta = new Vector2(22f, 22f); Image component2 = val4.GetComponent<Image>(); component2.sprite = _lockSprite; ((Graphic)component2).raycastTarget = false; ((Graphic)component2).color = Color.white; } if ((Object)(object)val4 != (Object)null) { val4.SetActive(visible); if (visible) { val4.transform.SetAsLastSibling(); } } } private static GameObject CreateLockBorder(Transform parent, Color color) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_0030: 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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: 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_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0172: 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_017c: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("HotDepositLockBorder", new Type[1] { typeof(RectTransform) }); RectTransform component = val.GetComponent<RectTransform>(); ((Transform)component).SetParent(parent, false); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = new Vector2(0f, -2f); component.offsetMax = new Vector2(0f, -2f); CreateBorderEdge(val.transform, "Top", new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(0f, -3f), Vector2.zero, color); CreateBorderEdge(val.transform, "Bottom", new Vector2(0f, 0f), new Vector2(1f, 0f), Vector2.zero, new Vector2(0f, 3f), color); CreateBorderEdge(val.transform, "Left", new Vector2(0f, 0f), new Vector2(0f, 1f), Vector2.zero, new Vector2(3f, 0f), color); CreateBorderEdge(val.transform, "Right", new Vector2(1f, 0f), new Vector2(1f, 1f), new Vector2(-3f, 0f), Vector2.zero, color); val.transform.SetAsLastSibling(); return val; } private static void CreateBorderEdge(Transform parent, string name, Vector2 anchorMin, Vector2 anchorMax, Vector2 offsetMin, Vector2 offsetMax, Color color) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); RectTransform component = val.GetComponent<RectTransform>(); ((Transform)component).SetParent(parent, false); component.anchorMin = anchorMin; component.anchorMax = anchorMax; component.offsetMin = offsetMin; component.offsetMax = offsetMax; Image component2 = val.GetComponent<Image>(); ((Graphic)component2).color = color; ((Graphic)component2).raycastTarget = false; } private static void EnsureLockSprite() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_0139: 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_016c: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_lockSprite != (Object)null) { return; } Texture2D val = new Texture2D(16, 16, (TextureFormat)4, false); ((Object)val).name = "HotDepositLockTexture"; ((Texture)val).filterMode = (FilterMode)0; ((Texture)val).wrapMode = (TextureWrapMode)1; Color val2 = default(Color); ((Color)(ref val2))..ctor(0f, 0f, 0f, 0f); Color val3 = default(Color); ((Color)(ref val3))..ctor(0.08f, 0.08f, 0.08f, 0.95f); Color val4 = default(Color); ((Color)(ref val4))..ctor(1f, 0.85f, 0.15f, 1f); for (int i = 0; i < 16; i++) { for (int j = 0; j < 16; j++) { val.SetPixel(j, i, val2); } } for (int k = 8; k <= 13; k++) { for (int l = 4; l <= 11; l++) { if (l == 4 || l == 11 || k == 13) { val.SetPixel(l, k, val3); } } } for (int m = 9; m <= 13; m++) { val.SetPixel(5, m, val4); val.SetPixel(10, m, val4); } for (int n = 6; n <= 9; n++) { val.SetPixel(n, 13, val4); } for (int num = 2; num <= 8; num++) { for (int num2 = 3; num2 <= 12; num2++) { bool flag = num2 == 3 || num2 == 12 || num == 2 || num == 8; val.SetPixel(num2, num, flag ? val3 : val4); } } val.SetPixel(7, 5, val3); val.SetPixel(8, 5, val3); val.SetPixel(7, 4, val3); val.SetPixel(8, 4, val3); val.Apply(); _lockSprite = Sprite.Create(val, new Rect(0f, 0f, 16f, 16f), new Vector2(0.5f, 0.5f), 100f); ((Object)_lockSprite).name = "HotDepositLockSprite"; } private static void RefreshInventoryGui() { try { InventoryGui instance = InventoryGui.instance; if (!((Object)(object)instance == (Object)null)) { MethodInfo methodInfo = AccessTools.Method(typeof(InventoryGui), "UpdateInventory", new Type[1] { typeof(Player) }, (Type[])null); if (methodInfo != null && (Object)(object)Player.m_localPlayer != (Object)null) { methodInfo.Invoke(instance, new object[1] { Player.m_localPlayer }); } object? obj = AccessTools.Field(typeof(InventoryGui), "m_playerGrid")?.GetValue(instance); InventoryGrid val = (InventoryGrid)((obj is InventoryGrid) ? obj : null); if ((Object)(object)val != (Object)null) { UpdateLockVisuals(val); } } } catch { } } private static Inventory GetContainerInventory(Container container) { if ((Object)(object)container == (Object)null || ContainerGetInventoryMethod == null) { return null; } try { object? obj = ContainerGetInventoryMethod.Invoke(container, null); return (Inventory)((obj is Inventory) ? obj : null); } catch { return null; } } private static IEnumerable<ItemData> GetInventoryItems(Inventory inventory) { if (inventory == null || InventoryGetAllItemsMethod == null) { yield break; } object value; try { value = InventoryGetAllItemsMethod.Invoke(inventory, null); } catch { yield break; } if (!(value is IEnumerable enumerable)) { yield break; } foreach (object entry in enumerable) { ItemData item = (ItemData)((entry is ItemData) ? entry : null); if (item != null) { yield return item; } } } private static bool InventoryContainsItemKey(Inventory inventory, string key) { foreach (ItemData inventoryItem in GetInventoryItems(inventory)) { if (string.Equals(GetItemKey(inventoryItem), key, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } private static string GetItemKey(ItemData item) { if (item == null) { return string.Empty; } try { object? obj = ItemDropPrefabField?.GetValue(item); GameObject val = (GameObject)((obj is GameObject) ? obj : null); if ((Object)(object)val != (Object)null && !string.IsNullOrEmpty(((Object)val).name)) { return ((Object)val).name; } } catch { } try { object obj3 = ItemSharedField?.GetValue(item); if (obj3 == null) { return string.Empty; } return (AccessTools.Field(obj3.GetType(), "m_name")?.GetValue(obj3) as string) ?? string.Empty; } catch { return string.Empty; } } private static int GetStack(ItemData item) { if (item == null || ItemStackField == null) { return 0; } try { object value = ItemStackField.GetValue(item); return (value != null) ? Convert.ToInt32(value) : 0; } catch { return 0; } } private static bool IsItemEquipped(ItemData item) { if (item == null || ItemEquippedField == null) { return false; } try { object value = ItemEquippedField.GetValue(item); return value is bool && (bool)value; } catch { return false; } } private static bool IsItemInHotbar(ItemData item) { if (item == null || ItemGridPosField == null) { return false; } try { object value = ItemGridPosField.GetValue(item); if (value == null) { return false; } Type type = value.GetType(); FieldInfo fieldInfo = AccessTools.Field(type, "y") ?? AccessTools.Field(type, "Y"); if (fieldInfo != null) { return Convert.ToInt32(fieldInfo.GetValue(value)) == 0; } PropertyInfo propertyInfo = AccessTools.Property(type, "y") ?? AccessTools.Property(type, "Y"); return propertyInfo != null && Convert.ToInt32(propertyInfo.GetValue(value, null)) == 0; } catch { return false; } } private static bool CheckContainerAccess(Container container, long playerId) { if ((Object)(object)container == (Object)null || ContainerCheckAccessMethod == null) { return false; } try { object obj = ContainerCheckAccessMethod.Invoke(container, new object[1] { playerId }); return obj is bool && (bool)obj; } catch { return false; } } private static bool IsContainerInUse(Container container) { if ((Object)(object)container == (Object)null || ContainerIsInUseMethod == null) { return false; } try { object obj = ContainerIsInUseMethod.Invoke(container, null); return obj is bool && (bool)obj; } catch { return true; } } private static bool ClaimContainerOwnership(Container container) { if ((Object)(object)container == (Object)null || ContainerNViewField == null || ZNetViewIsOwnerMethod == null || ZNetViewClaimOwnershipMethod == null) { return false; } try { object? value = ContainerNViewField.GetValue(container); ZNetView val = (ZNetView)((value is ZNetView) ? value : null); if ((Object)(object)val == (Object)null || !val.IsValid()) { return false; } if (!(ZNetViewIsOwnerMethod.Invoke(val, null) is int num) || num == 0) { ZNetViewClaimOwnershipMethod.Invoke(val, null); } object obj = ZNetViewIsOwnerMethod.Invoke(val, null); return obj is bool && (bool)obj; } catch { return false; } } private static void InitializeInputVisibilityChecks() { InputVisibilityProbes.Clear(); AddInputVisibilityProbe("TextInput", "IsVisible"); AddInputVisibilityProbe("TextInput", "HasFocus"); AddInputVisibilityProbe("TextInput", "InTextInput"); AddInputVisibilityProbe("Console", "IsVisible"); AddInputVisibilityProbe("Console", "HasFocus"); AddInputVisibilityProbe("Chat", "HasFocus"); AddInputVisibilityProbe("Chat", "IsChatDialogWindowVisible"); } private static void AddInputVisibilityProbe(string typeName, string memberName) { Type type = FindTypeSilent(typeName); if (type == null) { return; } MethodInfo method = type.GetMethod(memberName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); PropertyInfo propertyInfo = null; if (method == null) { propertyInfo = type.GetProperty(memberName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (propertyInfo != null && propertyInfo.PropertyType != typeof(bool)) { propertyInfo = null; } } if ((method == null && propertyInfo == null) || (method != null && method.ReturnType != typeof(bool))) { return; } MethodInfo methodInfo = ((propertyInfo != null) ? propertyInfo.GetGetMethod(nonPublic: true) : null); bool flag = ((method != null) ? method.IsStatic : (methodInfo != null && methodInfo.IsStatic)); FieldInfo fieldInfo = null; PropertyInfo propertyInfo2 = null; if (!flag) { fieldInfo = type.GetField("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) ?? type.GetField("m_instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); propertyInfo2 = type.GetProperty("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) ?? type.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (fieldInfo == null && propertyInfo2 == null) { return; } } InputVisibilityProbes.Add(new InputVisibilityProbe { Method = method, Property = propertyInfo, InstanceField = fieldInfo, InstanceProperty = propertyInfo2 }); } private static Type FindTypeSilent(string typeName) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { try { Type type = assembly.GetType(typeName, throwOnError: false); if (type != null) { return type; } } catch { } } return null; } private static bool IsTypingOrConsoleOpen() { foreach (InputVisibilityProbe inputVisibilityProbe in InputVisibilityProbes) { if (inputVisibilityProbe != null && inputVisibilityProbe.Check()) { return true; } } return false; } private static void ShowDepositNotification(Player player, string title, Dictionary<string, int> movedByItem) { if ((Object)(object)player == (Object)null || movedByItem == null || movedByItem.Count == 0) { return; } List<string> list = new List<string> { title }; foreach (KeyValuePair<string, int> item in movedByItem.OrderBy((KeyValuePair<string, int> pair) => pair.Key)) { list.Add($"{item.Key} x{item.Value}"); } string text = string.Join("\n", list.ToArray()); if (ShowDepositPopup != null && ShowDepositPopup.Value) { try { ((Character)player).Message((MessageType)1, text, 0, (Sprite)null, false); return; } catch { } } ShowMessage(player, text); } private static void ShowMessage(Player player, string message) { if ((Object)(object)player == (Object)null || string.IsNullOrEmpty(message)) { return; } try { ((Character)player).Message((MessageType)2, message, 0, (Sprite)null, false); } catch { } } } [HarmonyPatch(typeof(Container), "Awake")] internal static class ContainerRegistryAwakePatch { private static void Postfix(Container __instance) { Plugin.RegisterContainer(__instance); } } [HarmonyPatch] internal static class InventoryGuiSelectedItemPatch { private static MethodBase TargetMethod() { return AccessTools.Method(typeof(InventoryGui), "OnSelectedItem", (Type[])null, (Type[])null); } private static bool Prefix(object[] __args) { return !Plugin.TryHandleLockClick(__args); } } [HarmonyPatch] internal static class InventoryGridUpdateGuiPatch { private static IEnumerable<MethodBase> TargetMethods() { return from method in typeof(InventoryGrid).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) where method.Name == "UpdateGui" select method; } private static void Postfix(InventoryGrid __instance) { Plugin.UpdateLockVisuals(__instance); } } }