using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using InventoryActions.LocalizationManager; using JetBrains.Annotations; using Microsoft.CodeAnalysis; using ServerSync; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Core.ObjectPool; using YamlDotNet.Core.Tokens; using YamlDotNet.Helpers; using YamlDotNet.Serialization; using YamlDotNet.Serialization.BufferedDeserialization; using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators; using YamlDotNet.Serialization.Callbacks; using YamlDotNet.Serialization.Converters; using YamlDotNet.Serialization.EventEmitters; using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization.NodeDeserializers; using YamlDotNet.Serialization.NodeTypeResolvers; using YamlDotNet.Serialization.ObjectFactories; using YamlDotNet.Serialization.ObjectGraphTraversalStrategies; using YamlDotNet.Serialization.ObjectGraphVisitors; using YamlDotNet.Serialization.Schemas; using YamlDotNet.Serialization.TypeInspectors; using YamlDotNet.Serialization.TypeResolvers; using YamlDotNet.Serialization.Utilities; using YamlDotNet.Serialization.ValueDeserializers; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("InventoryActions")] [assembly: AssemblyDescription("Standalone inventory actions for Valheim")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("InventoryActions")] [assembly: AssemblyCopyright("")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("1FBE0C8C-42DE-4C9A-9C7F-74280DC0B9AB")] [assembly: AssemblyFileVersion("1.0.5")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.5.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 InventoryActions { [BepInPlugin("sighsorry.InventoryActions", "InventoryActions", "1.0.5")] [BepInIncompatibility("sighsorry.InventorySlots")] [BepInIncompatibility("goldenrevolver.quick_stack_store")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class InventoryActionsPlugin : BaseUnityPlugin { private enum RestockMode { CurrentContainerMatchingStacks, AreaFavoriteRestock } private enum AreaOwnershipFailure { None, InvalidRequest, NotOwner, Unsupported, Busy, InUse, NoAccess, OutOfRange, Unavailable } private sealed class AreaContainerTransferSession { public Player Player; public Inventory PlayerInventory; public Container Anchor; public ZDOID AnchorId; public AreaContainerActionKind Action; public List Targets; public int NextTargetIndex; public Container? PendingTarget; public AreaOwnershipRequestIdentity PendingIdentity; public long PendingGrantToken; public AreaOwnershipHandoffDecision PendingDecision; public uint GrantDataRevision; public ushort GrantOwnerRevision; public long GrantExpiresAt; public int TotalMoved; public bool PlayerInventoryChanged; public int ChangedContainerVfxCount; public int VfxLimit; } private sealed class ButtonPositionOffsetEditorState { public string LastEntryValue { get; set; } = ""; public string X { get; set; } = "0"; public string Y { get; set; } = "0"; } private sealed class AcceptableShortcuts : AcceptableValueBase { public AcceptableShortcuts() : base(typeof(KeyboardShortcut)) { } public override object Clamp(object value) { return value; } public override bool IsValid(object value) { return true; } public override string ToDescriptionString() { return "# Acceptable values: " + string.Join(", ", UnityInput.Current.SupportedKeyCodes); } } private sealed class ConfigurationManagerAttributes { public int? Order { get; set; } public bool? Browsable { get; set; } public Action? CustomDrawer { get; set; } } public enum Toggle { Off, On } private sealed class RestockTargetLimitEditorRow { public string Item { get; set; } public string Amount { get; set; } public RestockTargetLimitEditorRow(string item, string amount) { Item = item; Amount = amount; } } [CompilerGenerated] private static class <>O { public static Func <0>__TryGetHoverQuickStackContext; public static Func <1>__TryQuickStackFromHoveredContainer; public static Func <2>__TryGetHoverRestockContext; public static Func <3>__TryRestockFromHoveredContainer; public static Action <4>__DrawButtonPositionOffsetConfig; public static Action <5>__DrawRestockTargetStackLimitsConfig; public static Func <6>__GetShortcutKeyDisplayText; public static Action <7>__HandleLocalizationComplete; public static Func <8>__IsDigit; public static UnityAction <9>__TryClickInventoryTrashPanel; } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static Func <>9__5_0; public static Func <>9__5_1; public static Func <>9__5_2; public static Comparison <>9__7_1; public static Func <>9__9_0; public static Func <>9__9_1; public static Comparison <>9__10_1; public static Comparison <>9__14_1; public static Func <>9__23_0; public static Func <>9__25_0; public static Func <>9__26_0; public static Funcf__AnonymousType0> <>9__26_1; public static Funcf__AnonymousType0, ItemData>, List> <>9__26_2; public static Func <>9__26_3; public static Func <>9__44_0; public static Comparison<(Container Container, float DistanceSq)> <>9__48_0; public static Func <>9__53_0; public static Func <>9__61_1; public static Func <>9__61_2; public static Comparison <>9__94_3; public static Comparison <>9__94_1; public static EventHandler <>9__139_0; public static EventHandler <>9__139_1; public static Func <>9__149_0; public static Func <>9__166_0; public static Func <>9__175_0; public static Func <>9__183_0; public static Func <>9__183_1; public static Func <>9__183_2; public static Func <>9__229_0; public static Func <>9__229_1; public static UnityAction <>9__241_0; public static UnityAction <>9__241_1; public static UnityAction <>9__243_0; public static UnityAction <>9__250_0; internal bool b__5_0(ItemData item) { return item?.m_shared != null; } internal int b__5_1(ItemData item) { return item.m_gridPos.y; } internal int b__5_2(ItemData item) { return item.m_gridPos.x; } internal int b__7_1(ItemData a, ItemData b) { //IL_0001: 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) return -CompareGridOrder(a.m_gridPos, b.m_gridPos); } internal bool b__9_0(ItemData item) { return item?.m_shared != null; } internal string b__9_1(ItemData item) { return item.m_shared.m_name; } internal int b__10_1(ItemData a, ItemData b) { //IL_0001: 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) return CompareGridOrder(a.m_gridPos, b.m_gridPos); } internal int b__14_1(ItemData a, ItemData b) { //IL_0001: 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) return -CompareGridOrder(a.m_gridPos, b.m_gridPos); } internal bool b__23_0(ItemData item) { return item?.m_shared != null; } internal ItemData b__25_0(ItemData item) { return item; } internal bool b__26_0(ItemData item) { if (item?.m_shared != null && item.m_stack < item.m_shared.m_maxStackSize) { return CanUseContainerActionStacking(item); } return false; } internal <>f__AnonymousType0 b__26_1(ItemData item) { return new { item.m_shared.m_name, item.m_quality, item.m_worldLevel }; } internal List b__26_2(IGrouping<<>f__AnonymousType0, ItemData> grouping) { return grouping.ToList(); } internal int b__26_3(ItemData item) { return item.m_stack; } internal bool b__44_0(Container target) { if (!IsUnityNull((Object?)(object)target)) { return target.m_inventory != null; } return false; } internal int b__48_0((Container Container, float DistanceSq) left, (Container Container, float DistanceSq) right) { return left.DistanceSq.CompareTo(right.DistanceSq); } internal bool b__53_0(MonoBehaviour component) { if ((Object)(object)component != (Object)null) { return string.Equals(((object)component).GetType().FullName, "OdinShip.ShipContainer", StringComparison.Ordinal); } return false; } internal int b__61_1(ItemData target) { return target.m_gridPos.y; } internal int b__61_2(ItemData target) { return target.m_gridPos.x; } internal int b__94_3(ItemData a, ItemData b) { //IL_0001: 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) return -CompareGridOrder(a.m_gridPos, b.m_gridPos); } internal int b__94_1(ItemData a, ItemData b) { //IL_0001: 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) return -CompareGridOrder(a.m_gridPos, b.m_gridPos); } internal void b__139_0(object _, EventArgs _) { RefreshFavoriteBorders(); } internal void b__139_1(object _, EventArgs _) { RefreshRestockTargetStackLimits(); } internal bool b__149_0(char c) { if (!char.IsDigit(c) && c != '-' && c != '+') { return c == '.'; } return true; } internal bool b__166_0(char ch) { bool flag = char.IsLetterOrDigit(ch); if (!flag) { bool flag2 = ((ch == '-' || ch == '_') ? true : false); flag = flag2; } return flag; } internal bool b__175_0(string part) { return !string.IsNullOrWhiteSpace(part); } internal int b__183_0(Vector2i slot) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return slot.y; } internal int b__183_1(Vector2i slot) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return slot.x; } internal string b__183_2(Vector2i slot) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) return $"{slot.x},{slot.y}"; } internal bool b__229_0(RestockTargetLimitEditorRow row) { if (string.IsNullOrWhiteSpace(row.Item)) { return !string.IsNullOrWhiteSpace(row.Amount); } return true; } internal string b__229_1(RestockTargetLimitEditorRow row) { return row.Item.Trim() + ": " + row.Amount.Trim(); } internal void b__241_0() { StoreAllToCurrentContainer(Player.m_localPlayer); } internal void b__241_1() { RestockFromCurrentContainer(Player.m_localPlayer); } internal void b__243_0() { SortPlayerInventory(Player.m_localPlayer); } internal void b__250_0() { SortCurrentContainer(Player.m_localPlayer); } } private const string AreaOwnershipRequestRpc = "InventoryActions_AreaOwnershipRequestV1"; private const string AreaOwnershipResponseRpc = "InventoryActions_AreaOwnershipResponseV1"; private const string AreaOwnershipLeaseRequesterKey = "InventoryActions_AreaLeaseRequester"; private const string AreaOwnershipLeaseRequestIdKey = "InventoryActions_AreaLeaseRequestId"; private const string AreaOwnershipLeaseActionKey = "InventoryActions_AreaLeaseAction"; private const string AreaOwnershipLeaseExpiryKey = "InventoryActions_AreaLeaseExpiry"; private const string AreaOwnershipLeaseTokenKey = "InventoryActions_AreaLeaseToken"; private const int AreaOwnershipProtocolVersion = 1; private const int AreaOwnershipMaximumPackageBytes = 256; private const float AreaOwnershipResponseTimeout = 2.5f; private const float AreaOwnershipPropagationTimeout = 3f; private const float AreaOwnershipMaximumAnchorDistance = 8f; private static readonly long AreaOwnershipLeaseDurationTicks = TimeSpan.FromSeconds(8.0).Ticks; private static readonly AreaOwnershipHandoffCore AreaOwnershipHandoff = new AreaOwnershipHandoffCore(); private static AreaContainerTransferSession? _areaContainerTransfer; private static int _nextAreaOwnershipRequestId = 1; private static readonly ConfigSync ConfigSync = new ConfigSync("sighsorry.InventoryActions") { DisplayName = "InventoryActions", CurrentVersion = "1.0.5", MinimumRequiredVersion = "1.0.5", ModRequired = true }; private static ConfigEntry _serverConfigLocked = null; private static ConfigEntry _enableInventoryTrashPanel = null; private static ConfigEntry _areaQuickStackRange = null; private static ConfigEntry _areaRestockRange = null; private static ConfigEntry _favoriteBorderColor = null; private static ConfigEntry _containerActionSuccessFx = null; private static ConfigEntry _favoriteModifierKey = null; private static ConfigEntry _containerRestockKey = null; private static ConfigEntry _sortButtonPositionOffset = null; private static ConfigEntry _trashButtonPositionOffset = null; private static ConfigEntry _restockTargetStackLimitsConfig = null; private static readonly Color FavoriteBorderDefaultColor = new Color(0.1f, 0.55f, 1f, 0.95f); private static readonly char[] ButtonPositionOffsetSeparators = new char[12] { ' ', '\t', '\r', '\n', ':', '=', ',', ';', '(', ')', '[', ']' }; private static readonly Dictionary ButtonPositionOffsetEditorStates = new Dictionary(StringComparer.Ordinal); internal const string ModName = "InventoryActions"; internal const string ModVersion = "1.0.5"; internal const string Author = "sighsorry"; internal const string ModGUID = "sighsorry.InventoryActions"; private const string ExternalMultiUserChestGuid = "com.maxsch.valheim.MultiUserChest"; private const int PlayerInventoryWidth = 8; private const int VanillaPlayerRows = 4; private const string FavoriteBorderName = "InventoryActions_FavoriteBorder"; private const float FavoriteBorderThickness = 2f; private const string ClientConfigSection = "2 - Client"; private const string RestockConfigSection = "3 - Restock"; private const string GeneralConfigSection = "1 - General"; private const float ContainerHoverHoldDuration = 0.5f; private const string ContainerActionSuccessFxPrefabName = "fx_HildirChest_Unlock"; private const int ContainerActionSuccessVfxLimit = 10; private const float ContainerActionSuccessSfxLifetime = 5f; internal static readonly ManualLogSource Log = Logger.CreateLogSource("InventoryActions"); private readonly Harmony _harmony = new Harmony("sighsorry.InventoryActions"); private static InventoryActionsPlugin _instance = null; private static readonly InventoryActionRuntimeState Runtime = new InventoryActionRuntimeState(); private static readonly System.Version MinimumSupportedExternalMultiUserChestVersion = new System.Version(0, 6, 1); private static readonly List RestockTargetLimitEditorRows = new List(); private static string _restockTargetLimitEditorLastValue = ""; private const float SortButtonOutsideGap = 1f; private const float TrashPanelGap = 8f; private static readonly Vector2 InventorySortButtonFixedOffset = new Vector2(2f, 2f); private const string PlayerActionPanelName = "InventoryActions_PlayerActionPanel"; private const string TrashPanelName = "InventoryActions_TrashPanel"; private const string TrashButtonName = "InventoryActions_TrashButton"; private const string TrashIconName = "InventoryActions_TrashIcon"; private const string TrashConfirmDialogName = "InventoryActions_TrashConfirmDialog"; internal static bool IsDedicatedServer { get { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 if ((int)SystemInfo.graphicsDeviceType != 4) { if (Application.isBatchMode) { return string.Equals(Paths.ProcessName, "valheim_server", StringComparison.OrdinalIgnoreCase); } return false; } return true; } } private static bool HasExternalMultiUserChestActive { get { if (Chainloader.PluginInfos.TryGetValue("com.maxsch.valheim.MultiUserChest", out var value)) { return (Object)(object)value.Instance != (Object)null; } return false; } } private static bool HasSupportedExternalMultiUserChestActive { get { if (Chainloader.PluginInfos.TryGetValue("com.maxsch.valheim.MultiUserChest", out var value) && (Object)(object)value.Instance != (Object)null) { return value.Metadata.Version.CompareTo(MinimumSupportedExternalMultiUserChestVersion) >= 0; } return false; } } internal static bool TryHandleVanillaPlaceStacks(InventoryGui gui) { if ((Object)(object)gui == (Object)null || (Object)(object)gui.m_currentContainer == (Object)null) { return false; } if (!CanMutateContainerDirectly(gui.m_currentContainer, allowLocalWithoutZNetView: true)) { return false; } QuickStackCurrentContainer(Player.m_localPlayer); return true; } internal static bool TryHandleContainerStackAll(Container container) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || localPlayer.m_isLoading || (Object)(object)container == (Object)null || container.m_inventory == null) { return false; } if (!CanMutateContainerDirectly(container, allowLocalWithoutZNetView: true)) { return false; } Inventory playerInventory = GetPlayerInventory(localPlayer); if (playerInventory == null) { return false; } QuickStackIntoContainers(localPlayer, playerInventory, container, includeArea: true); return true; } internal static bool TryHandleSafeTakeAll(InventoryGui gui) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || localPlayer.m_isLoading || (Object)(object)gui == (Object)null || (Object)(object)gui.m_currentContainer == (Object)null || gui.m_currentContainer.m_inventory == null) { return false; } Container currentContainer = gui.m_currentContainer; if (!CanMutateContainerDirectly(currentContainer, allowLocalWithoutZNetView: true)) { if (CanDelegateTakeAllToExternalMultiUserChest(localPlayer, currentContainer)) { return false; } ((Character)localPlayer).Message((MessageType)2, LocalizeUi("$inventoryactions_container_not_ready", "Container is not ready."), 0, (Sprite)null); return true; } Inventory playerInventory = GetPlayerInventory(localPlayer); Inventory inventory = currentContainer.m_inventory; if (playerInventory == null || inventory == null) { return false; } TombStone component = ((Component)currentContainer).GetComponent(); gui.SetupDragItem((ItemData)null, (Inventory)null, 0); if (SafeTakeAllItems(localPlayer, playerInventory, inventory) > 0) { playerInventory.Changed(); inventory.Changed(); } if ((Object)(object)component != (Object)null && inventory.NrOfItems() == 0) { component.OnTakeAllSuccess(); } return true; } internal static bool TryHandleTopFirstMoveSelectedItem(InventoryGui gui, InventoryGrid grid, ItemData item, Modifier mod) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Invalid comparison between Unknown and I4 //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)gui == (Object)null || (Object)(object)grid == (Object)null || item?.m_shared == null || (int)mod != 2 || item.m_shared.m_questItem || (Object)(object)gui.m_dragGo != (Object)null) { return false; } Player localPlayer = Player.m_localPlayer; Container currentContainer = gui.m_currentContainer; if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsTeleporting() || (Object)(object)currentContainer == (Object)null || currentContainer.m_inventory == null || !CanMutateContainerDirectly(currentContainer, allowLocalWithoutZNetView: true)) { return false; } Inventory playerInventory = GetPlayerInventory(localPlayer); Inventory inventory = grid.GetInventory(); Inventory inventory2 = currentContainer.m_inventory; if (playerInventory == null || inventory == null) { return false; } Inventory val = null; if (inventory == inventory2) { val = playerInventory; } else if (inventory == playerInventory) { val = inventory2; } if (val == null) { return false; } if (!CanMoveItemToInventoryTopFirst(inventory, val, item)) { return true; } if (inventory == playerInventory && ((Humanoid)localPlayer).IsItemEquiped(item)) { ((Humanoid)localPlayer).RemoveEquipAction(item); ((Humanoid)localPlayer).UnequipItem(item, false); } if (MoveItemToInventoryTopFirst(inventory, val, item) > 0) { playerInventory.Changed(); inventory2.Changed(); gui.m_moveItemEffects.Create(((Component)gui).transform.position, Quaternion.identity, (Transform)null, 1f, -1); } return true; } private static int SafeTakeAllItems(Player player, Inventory playerInventory, Inventory containerInventory) { HashSet allowedSlots = new HashSet(GetPlayerActionSlots(player, playerInventory, includeHotbar: false, blockFavorites: true)); List list = (from item in containerInventory.m_inventory where item?.m_shared != null orderby item.m_gridPos.y, item.m_gridPos.x select item).ToList(); int num = 0; foreach (ItemData item in list) { if (containerInventory.m_inventory.Contains(item)) { int stack = item.m_stack; if (MoveItemToInventoryTopFirst(containerInventory, playerInventory, item, allowedSlots) > 0 && (!containerInventory.m_inventory.Contains(item) || item.m_stack < stack)) { num++; } } } return num; } private static void QuickStackCurrentContainer(Player? player) { if (TryGetActionContext(player, out Player localPlayer, out Inventory playerInventory, out Container container, out Inventory _)) { QuickStackIntoContainers(localPlayer, playerInventory, container, includeArea: false); } } private static void QuickStackIntoContainers(Player localPlayer, Inventory playerInventory, Container container, bool includeArea) { if (includeArea) { TryStartAreaContainerTransfer(localPlayer, playerInventory, container, AreaContainerActionKind.QuickStack); return; } List candidates = playerInventory.m_inventory.Where((ItemData item) => ShouldQuickStackItem(localPlayer, playerInventory, item, includeHotbar: false)).ToList(); candidates.Sort((ItemData a, ItemData b) => -CompareGridOrder(a.m_gridPos, b.m_gridPos)); InventoryGui instance = InventoryGui.instance; if (instance != null) { instance.SetupDragItem((ItemData)null, (Inventory)null, 0); } int moved = RunCurrentContainerTransfer(container, (Container targetContainer) => QuickStackItemsIntoContainer(playerInventory, targetContainer.m_inventory, candidates), delegate { playerInventory.Changed(); }); ShowContainerActionResult(localPlayer, "$inventoryactions_action_stack", "Stack", moved); } private static bool ShouldQuickStackItem(Player player, Inventory inventory, ItemData item, bool includeHotbar) { if (item?.m_shared != null && item.m_shared.m_maxStackSize > 1 && IsRegularActionItem(player, inventory, item, includeHotbar) && !IsFavoriteProtected(player, inventory, item)) { return CanUseContainerActionStacking(item); } return false; } private static int QuickStackItemsIntoContainer(Inventory playerInventory, Inventory containerInventory, List candidates) { if (containerInventory == null || candidates.Count == 0) { return 0; } HashSet hashSet = new HashSet(from item in containerInventory.m_inventory where item?.m_shared != null select item.m_shared.m_name, StringComparer.OrdinalIgnoreCase); if (hashSet.Count == 0) { return 0; } int num = 0; foreach (ItemData candidate in candidates) { if (playerInventory.m_inventory.Contains(candidate) && candidate?.m_shared != null && hashSet.Contains(candidate.m_shared.m_name) && MoveItemToInventoryTopFirst(playerInventory, containerInventory, candidate) > 0) { num++; } } if (num > 0) { containerInventory.Changed(); } return num; } private static void StoreAllToCurrentContainer(Player? player) { if (!TryGetActionContext(player, out Player localPlayer, out Inventory playerInventory, out Container _, out Inventory containerInventory)) { return; } List list = playerInventory.m_inventory.Where((ItemData item) => ShouldStoreAllItem(localPlayer, playerInventory, item, includeHotbar: false, includeEquipped: false)).ToList(); list.Sort((ItemData a, ItemData b) => CompareGridOrder(a.m_gridPos, b.m_gridPos)); InventoryGui instance = InventoryGui.instance; if (instance != null) { instance.SetupDragItem((ItemData)null, (Inventory)null, 0); } int num = 0; foreach (ItemData item in list) { if (playerInventory.m_inventory.Contains(item) && MoveItemToInventoryTopFirst(playerInventory, containerInventory, item) > 0) { num++; } } if (num > 0) { playerInventory.Changed(); containerInventory.Changed(); } } private static bool ShouldStoreAllItem(Player player, Inventory inventory, ItemData item, bool includeHotbar, bool includeEquipped) { if (item?.m_shared != null && IsRegularActionItem(player, inventory, item, includeHotbar) && !IsFavoriteProtected(player, inventory, item)) { if (!includeEquipped) { return !item.m_equipped; } return true; } return false; } private static void RestockFromCurrentContainer(Player? player) { if (TryGetActionContext(player, out Player localPlayer, out Inventory playerInventory, out Container container, out Inventory _)) { RestockFromContainer(localPlayer, playerInventory, container, RestockMode.CurrentContainerMatchingStacks); } } private static void RefreshRestockTargetStackLimits() { Runtime.RestockTargetStackLimits = RestockTargetLimitCore.Parse(_restockTargetStackLimitsConfig?.Value); } private static void RestockFromContainer(Player localPlayer, Inventory playerInventory, Container container, RestockMode mode) { if ((Object)(object)localPlayer == (Object)null || playerInventory == null || (Object)(object)container == (Object)null || container.m_inventory == null) { return; } if (mode == RestockMode.AreaFavoriteRestock) { TryStartAreaContainerTransfer(localPlayer, playerInventory, container, AreaContainerActionKind.Restock); return; } List targets = playerInventory.m_inventory.Where((ItemData item) => ShouldTakeStacksTarget(localPlayer, playerInventory, item, includeHotbar: false, mode)).ToList(); targets.Sort((ItemData a, ItemData b) => -CompareGridOrder(a.m_gridPos, b.m_gridPos)); InventoryGui instance = InventoryGui.instance; if (instance != null) { instance.SetupDragItem((ItemData)null, (Inventory)null, 0); } int moved = RunCurrentContainerTransfer(container, (Container sourceContainer) => RestockTargetsFromContainer(playerInventory, sourceContainer.m_inventory, targets, mode), delegate { playerInventory.Changed(); }); ShowContainerActionResult(localPlayer, "$inventoryactions_action_take_stacks", "Take stacks", moved); } private static bool ShouldTakeStacksTarget(Player player, Inventory inventory, ItemData item, bool includeHotbar, RestockMode mode) { if (mode != RestockMode.AreaFavoriteRestock) { return ShouldTakeMatchingStackItem(player, inventory, item, includeHotbar); } return ShouldRestockFavoriteItem(player, inventory, item); } private static bool ShouldRestockFavoriteItem(Player player, Inventory inventory, ItemData item) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (item?.m_shared == null || !CanUseFavoriteRestockTargetCell(inventory, item.m_gridPos) || !IsFavoriteSlot(player, item.m_gridPos) || !CanUseContainerActionStacking(item)) { return false; } int restockTargetStack = GetRestockTargetStack(item); if (item.m_shared.m_maxStackSize > 1) { return item.m_stack < restockTargetStack; } return false; } private static bool ShouldTakeMatchingStackItem(Player player, Inventory inventory, ItemData item, bool includeHotbar) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (item?.m_shared != null && IsRegularActionItem(player, inventory, item, includeHotbar) && !IsFavoriteSlot(player, item.m_gridPos) && CanUseContainerActionStacking(item) && item.m_shared.m_maxStackSize > 1) { return item.m_stack < item.m_shared.m_maxStackSize; } return false; } private static int GetRestockTargetStack(ItemData item) { if (item?.m_shared != null) { return RestockTargetLimitCore.ResolveTargetStackLimit(Runtime.RestockTargetStackLimits, GetRestockTargetLookupTokens(item), item.m_shared.m_maxStackSize); } return 0; } private static IEnumerable GetRestockTargetLookupTokens(ItemData item) { if (item != null) { yield return GetItemPrefabName(item); if (!IsUnityNull((Object?)(object)item.m_dropPrefab)) { yield return ((Object)item.m_dropPrefab).name; } string sharedName = item.m_shared?.m_name ?? ""; yield return sharedName; yield return RestockTargetLimitCore.StripLocalizationToken(sharedName); if (Localization.instance != null && !string.IsNullOrWhiteSpace(sharedName)) { yield return Localization.instance.Localize(sharedName); } } } private static int RestockTargetsFromContainer(Inventory playerInventory, Inventory containerInventory, List targets, RestockMode mode) { if (containerInventory == null || targets.Count == 0) { return 0; } int num = 0; foreach (ItemData target in targets) { if (!playerInventory.m_inventory.Contains(target)) { continue; } int num2 = ((mode == RestockMode.AreaFavoriteRestock) ? GetRestockTargetStack(target) : target.m_shared.m_maxStackSize); int num3 = target.m_stack; int num4 = containerInventory.m_inventory.Count - 1; while (num4 >= 0 && num3 < num2) { ItemData val = containerInventory.m_inventory[num4]; if (CanRestockFromContainerItem(target, val)) { int num5 = Math.Min(num2 - num3, val.m_stack); if (num5 > 0) { int stack = val.m_stack; bool moveSucceeded = playerInventory.MoveItemToThis(containerInventory, val, num5, target.m_gridPos.x, target.m_gridPos.y); int num6 = CountMovedFromContainerSource(containerInventory, val, stack, num5, moveSucceeded); num3 += num6; num += num6; } } num4--; } } if (num > 0) { containerInventory.Changed(); } return num; } private static bool CanRestockFromContainerItem(ItemData target, ItemData source) { if (target?.m_shared != null && source?.m_shared != null && CanUseContainerActionStacking(target) && CanUseContainerActionStacking(source)) { return HasSameStackIdentity(target, source); } return false; } private static void SortCurrentContainer(Player? player) { if ((Object)(object)player == (Object)null || player.m_isLoading || (Object)(object)InventoryGui.instance == (Object)null) { return; } Container currentContainer = InventoryGui.instance.m_currentContainer; if (!((Object)(object)currentContainer == (Object)null) && currentContainer.m_inventory != null) { if (!CanMutateContainerDirectly(currentContainer, allowLocalWithoutZNetView: true)) { ((Character)player).Message((MessageType)2, LocalizeUi("$inventoryactions_container_not_ready", "Container is not ready."), 0, (Sprite)null); } else { SortContainerInventory(currentContainer); } } } private static int SortContainerInventory(Container container) { if ((Object)(object)container == (Object)null || container.m_inventory == null) { return 0; } List allInventorySlots = GetAllInventorySlots(container.m_inventory); return SortInventoryInternal(container.m_inventory, allInventorySlots, (ItemData item) => item?.m_shared != null); } private static void SortPlayerInventory(Player? player) { if ((Object)(object)player == (Object)null || player.m_isLoading) { return; } Inventory inventory = GetPlayerInventory(player); if (inventory != null) { List playerActionSlots = GetPlayerActionSlots(player, inventory, includeHotbar: false, blockFavorites: true); HashSet allowedSet = new HashSet(playerActionSlots); InventoryGui instance = InventoryGui.instance; if (instance != null) { instance.SetupDragItem((ItemData)null, (Inventory)null, 0); } SortInventoryInternal(inventory, playerActionSlots, (ItemData item) => item?.m_shared != null && allowedSet.Contains(item.m_gridPos) && !IsFavoriteProtected(player, inventory, item)); } } private static int SortInventoryInternal(Inventory inventory, List allowedSlots, Func shouldSort) { //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //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) if (inventory == null || allowedSlots.Count == 0) { return 0; } List list = inventory.m_inventory.Where(shouldSort).ToList(); if (list.Count == 0) { return 0; } bool flag = MergeSortableStacks(list, inventory); int inventoryWidth = Mathf.Max(1, inventory.GetWidth()); Dictionary originalIndices = list.ToDictionary((ItemData item) => item, (ItemData item) => item.m_gridPos.y * inventoryWidth + item.m_gridPos.x); list.Sort((ItemData a, ItemData b) => CompareItemsForSort(a, b, originalIndices[a], originalIndices[b])); int num = 0; int num2 = Math.Min(list.Count, allowedSlots.Count); for (int num3 = 0; num3 < num2; num3++) { if (list[num3].m_gridPos != allowedSlots[num3]) { num++; flag = true; list[num3].m_gridPos = allowedSlots[num3]; } } if (flag) { inventory.Changed(); } return num; } private static bool MergeSortableStacks(List toMerge, Inventory inventory) { bool result = false; foreach (List item in (from item in toMerge where item?.m_shared != null && item.m_stack < item.m_shared.m_maxStackSize && CanUseContainerActionStacking(item) group item by new { item.m_shared.m_name, item.m_quality, item.m_worldLevel } into grouping select grouping.ToList()).ToList()) { if (item.Count <= 1) { continue; } int num = item.Sum((ItemData item) => item.m_stack); int maxStackSize = item[0].m_shared.m_maxStackSize; foreach (ItemData item2 in item.ToList()) { if (num <= 0) { if (item2.m_stack != 0) { item2.m_stack = 0; result = true; } inventory.RemoveItem(item2); toMerge.Remove(item2); result = true; } else { int num2 = Math.Min(maxStackSize, num); if (item2.m_stack != num2) { item2.m_stack = num2; result = true; } num -= item2.m_stack; } } } return result; } private static int CompareItemsForSort(ItemData a, ItemData b, int aOriginalIndex, int bOriginalIndex) { int num = GetItemSortCategory(a).CompareTo(GetItemSortCategory(b)); if (num != 0) { return num; } num = string.Compare(GetLocalizedItemName(a), GetLocalizedItemName(b), StringComparison.OrdinalIgnoreCase); if (num != 0) { return num; } num = -a.m_quality.CompareTo(b.m_quality); if (num != 0) { return num; } num = -a.m_stack.CompareTo(b.m_stack); if (num == 0) { return aOriginalIndex.CompareTo(bOriginalIndex); } return num; } private static int GetItemSortCategory(ItemData item) { switch (((object)Unsafe.As(ref item?.m_shared?.m_itemType)/*cast due to .constrained prefix*/).ToString() ?? "") { case "OneHandedWeapon": case "TwoHandedWeapon": case "Torch": case "Tool": case "Shield": case "TwoHandedWeaponLeft": case "Bow": return 10; case "Ammo": case "AmmoNonEquipable": return 20; case "Chest": case "Legs": case "Helmet": case "Shoulder": case "Utility": return 30; case "Fish": case "Consumable": return 40; case "Material": return 50; case "Trophie": return 60; default: return 90; } } private static List GetPlayerActionSlots(Player player, Inventory inventory, bool includeHotbar, bool blockFavorites = false) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) List list = new List(); int num = Math.Min(4, inventory.GetHeight()); EnsureFavoritesLoaded(player); Vector2i val = default(Vector2i); for (int i = 0; i < num; i++) { for (int j = 0; j < inventory.GetWidth(); j++) { ((Vector2i)(ref val))..ctor(j, i); if ((!blockFavorites || !Runtime.FavoriteSlots.Contains(val)) && IsPlayerActionCell(inventory, val, includeHotbar)) { list.Add(val); } } } return list; } private static List GetAllInventorySlots(Inventory inventory) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) List list = new List(); for (int i = 0; i < inventory.GetHeight(); i++) { for (int j = 0; j < inventory.GetWidth(); j++) { list.Add(new Vector2i(j, i)); } } return list; } private static bool TryGetActionContext(Player? player, out Player localPlayer, out Inventory playerInventory, out Container container, out Inventory containerInventory) { localPlayer = null; playerInventory = null; container = null; containerInventory = null; if ((Object)(object)player == (Object)null || player.m_isLoading || (Object)(object)InventoryGui.instance == (Object)null) { return false; } Container currentContainer = InventoryGui.instance.m_currentContainer; if ((Object)(object)currentContainer == (Object)null || currentContainer.m_inventory == null) { return false; } if (!CanMutateContainerDirectly(currentContainer, allowLocalWithoutZNetView: true)) { ((Character)player).Message((MessageType)2, LocalizeUi("$inventoryactions_container_not_ready", "Container is not ready."), 0, (Sprite)null); return false; } Inventory playerInventory2 = GetPlayerInventory(player); if (playerInventory2 == null) { return false; } localPlayer = player; playerInventory = playerInventory2; container = currentContainer; containerInventory = currentContainer.m_inventory; return true; } private static void HandleHoverActions(Player player) { if (InventoryGui.IsVisible() || ShouldBlockGlobalHotkeys(player)) { ResetContainerHold(Runtime.AreaQuickStackHold); ResetContainerHold(Runtime.AreaRestockHold); } else { HandleContainerHoldHotkey(player, Runtime.AreaQuickStackHold, IsContainerQuickStackShortcutHeld() && !IsContainerRestockShortcutHeld(), TryGetHoverQuickStackContext, TryQuickStackFromHoveredContainer); HandleContainerHoldHotkey(player, Runtime.AreaRestockHold, IsContainerRestockShortcutHeld(), TryGetHoverRestockContext, TryRestockFromHoveredContainer); } } private static void HandleContainerHoldHotkey(Player player, ContainerHoldActionState hold, bool shortcutHeld, Func getContext, Func executeAction) { Container val = (shortcutHeld ? getContext(player) : null); if ((Object)(object)val == (Object)null) { ResetContainerHold(hold); return; } if (IsUnityNull((Object?)(object)hold.Container) || (Object)(object)hold.Container != (Object)(object)val) { hold.Container = val; hold.StartTime = Time.time; hold.Triggered = false; } if (!hold.Triggered && !(Time.time - hold.StartTime < 0.5f)) { if (executeAction(player, val)) { hold.Triggered = true; } else { ResetContainerHold(hold); } } } private static void ResetContainerHold(ContainerHoldActionState hold) { hold.Container = null; hold.StartTime = -1f; hold.Triggered = false; } private static Container? TryGetHoverQuickStackContext(Player player) { Container hoveredContainer = GetHoveredContainer(player); if ((Object)(object)hoveredContainer == (Object)null || player.m_isLoading || hoveredContainer.m_inventory == null || !CanHandleContainerAction(player, hoveredContainer, AreaContainerActionKind.QuickStack)) { return null; } return hoveredContainer; } private static Container? TryGetHoverRestockContext(Player player) { Container hoveredContainer = GetHoveredContainer(player); if ((Object)(object)hoveredContainer == (Object)null || !CanHandleContainerAction(player, hoveredContainer, AreaContainerActionKind.Restock)) { return null; } return hoveredContainer; } private static bool TryQuickStackFromHoveredContainer(Player player, Container container) { Inventory playerInventory = GetPlayerInventory(player); if (playerInventory == null || !CanHandleContainerAction(player, container, AreaContainerActionKind.QuickStack)) { return false; } QuickStackIntoContainers(player, playerInventory, container, includeArea: true); return true; } private static bool TryRestockFromHoveredContainer(Player player, Container container) { Inventory playerInventory = GetPlayerInventory(player); if (playerInventory == null || !CanHandleContainerAction(player, container, AreaContainerActionKind.Restock)) { return false; } RestockFromContainer(player, playerInventory, container, RestockMode.AreaFavoriteRestock); return true; } private static Container? GetHoveredContainer(Player player) { GameObject val = (((Object)(object)player != (Object)null) ? ((Humanoid)player).GetHoverObject() : null); if (!IsUnityNull((Object?)(object)val)) { return val.GetComponentInParent(); } return null; } internal static bool ShouldSuppressContainerInteractForRestock(Container container, Humanoid character) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || (Object)(object)character != (Object)(object)localPlayer || InventoryGui.IsVisible() || !IsContainerRestockShortcutHeld()) { return false; } if ((Object)(object)GetHoveredContainer(localPlayer) == (Object)(object)container) { return CanHandleContainerAction(localPlayer, container, AreaContainerActionKind.Restock); } return false; } internal static void AppendContainerActionHoverText(Container container, ref string text) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && !localPlayer.m_isLoading && !string.IsNullOrWhiteSpace(text) && CanHandleContainerAction(localPlayer, container, AreaContainerActionKind.Restock)) { string containerRestockKeyDisplayText = GetContainerRestockKeyDisplayText(); if (!string.IsNullOrWhiteSpace(containerRestockKeyDisplayText)) { text = text + "\n[" + containerRestockKeyDisplayText + "] (" + LocalizeUi("$inventoryactions_hold_to_restock", "Hold to restock") + ")"; } } } internal static void RegisterContainer(Container container) { if (!((Object)(object)container == (Object)null)) { if (!Runtime.KnownContainers.Contains(container)) { Runtime.KnownContainers.Add(container); } RegisterAreaOwnershipRpcs(container); } } internal static void UnregisterContainer(Container container) { if ((Object)(object)container != (Object)null) { UnregisterAreaOwnershipRpcs(container); Runtime.KnownContainers.Remove(container); } } private static int RunCurrentContainerTransfer(Container container, Func transfer, Action onMoved) { if ((Object)(object)container == (Object)null || transfer == null) { return 0; } return ContainerTransferCore.Run((IEnumerable?)(object)new Container[1] { container }, (Container target) => !IsUnityNull((Object?)(object)target) && target.m_inventory != null, transfer, null, onMoved); } private static bool IsContainerQuickStackShortcutHeld() { if (!ZInput.GetButton("Use")) { return ZInput.GetButton("JoyUse"); } return true; } private static bool IsContainerRestockShortcutHeld() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (_containerRestockKey != null) { KeyboardShortcut value = _containerRestockKey.Value; if ((int)((KeyboardShortcut)(ref value)).MainKey != 0) { return IsShortcutHeldAllowingAltPair(_containerRestockKey.Value); } } return false; } private static string GetContainerRestockKeyDisplayText() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (_containerRestockKey == null) { return ""; } return GetShortcutDisplayText(_containerRestockKey.Value); } private static List GetActionContainers(Player player, Container currentContainer, bool areaForQuickStack) { //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_00e3: Unknown result type (might be due to invalid IL or missing references) List list = new List(); HashSet hashSet = new HashSet(); AreaContainerActionKind action = (areaForQuickStack ? AreaContainerActionKind.QuickStack : AreaContainerActionKind.Restock); if ((Object)(object)currentContainer != (Object)null && CanUseAreaContainerNow(player, currentContainer, currentContainer, action, requireDirectOwner: false) && hashSet.Add(currentContainer)) { list.Add(currentContainer); } float num = (areaForQuickStack ? _areaQuickStackRange.Value : _areaRestockRange.Value); if (num <= 0f || (Object)(object)currentContainer == (Object)null || IsUnityNull((Object?)(object)currentContainer)) { return list; } Vector3 position = ((Component)currentContainer).transform.position; float rangeSq = num * num; List<(Container, float)> list2 = new List<(Container, float)>(); for (int num2 = Runtime.KnownContainers.Count - 1; num2 >= 0; num2--) { Container val = Runtime.KnownContainers[num2]; float distanceSq; if ((Object)(object)val == (Object)null || IsUnityNull((Object?)(object)val)) { Runtime.KnownContainers.RemoveAt(num2); } else if (!hashSet.Contains(val) && IsAreaContainerAllowed(player, val, currentContainer, position, rangeSq, action, out distanceSq)) { list2.Add((val, distanceSq)); hashSet.Add(val); } } list2.Sort(((Container Container, float DistanceSq) left, (Container Container, float DistanceSq) right) => left.DistanceSq.CompareTo(right.DistanceSq)); foreach (var item2 in list2) { Container item = item2.Item1; list.Add(item); } return list; } private static bool CanHandleContainerAction(Player player, Container container, AreaContainerActionKind action) { if ((Object)(object)player != (Object)null && !player.m_isLoading && (Object)(object)container != (Object)null && container.m_inventory != null) { return CanUseAreaContainerNow(player, container, container, action, requireDirectOwner: false); } return false; } private static bool IsAreaContainerAllowed(Player player, Container container, Container? currentContainer, Vector3 origin, float rangeSq, AreaContainerActionKind action, out float distanceSq) { //IL_0050: 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_0056: 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) distanceSq = float.MaxValue; if ((Object)(object)player == (Object)null || (Object)(object)container == (Object)null || (Object)(object)container == (Object)(object)currentContainer || container.m_inventory == null || (Object)(object)container.m_nview == (Object)null || !container.m_nview.IsValid()) { return false; } Vector3 val = ((Component)container).transform.position - origin; distanceSq = ((Vector3)(ref val)).sqrMagnitude; if (distanceSq > rangeSq) { return false; } return CanUseAreaContainerNow(player, container, currentContainer, action, requireDirectOwner: false); } private static bool IsAreaContainerEligible(Container container) { if ((Object)(object)container == (Object)null || IsUnityNull((Object?)(object)container) || container.m_inventory == null || (Object)(object)container.m_nview == (Object)null || !container.m_nview.IsValid() || (Object)(object)((Component)container).GetComponent() != (Object)null || (Object)(object)((Component)container).GetComponentInParent() != (Object)null || (Object)(object)((Component)container.m_nview).GetComponent() != (Object)null || (Object)(object)((Component)((Component)container).transform.root).GetComponentInChildren() != (Object)null || (Object)(object)container.m_wagon != (Object)null) { return false; } if (!((Object)(object)container.m_piece == (Object)null)) { return container.m_piece.IsPlacedByPlayer(); } return true; } private static bool CanDelegateTakeAllToExternalMultiUserChest(Player player, Container container) { if (!HasSupportedExternalMultiUserChestActive || (Object)(object)player == (Object)null || (Object)(object)container == (Object)null || (Object)(object)container.m_nview == (Object)null || !container.m_nview.IsValid() || !container.m_nview.HasOwner() || container.m_nview.IsOwner() || !HasContainerPlayerAccess(player, container, flashGuardStone: false) || !IsExternalMultiUserChestTransferContainer(container)) { return false; } ZDO zDO = container.m_nview.GetZDO(); if (zDO != null) { return !zDO.GetBool("MUC_Ignore", false); } return false; } private static bool IsExternalMultiUserChestTransferContainer(Container container) { if ((Object)(object)((Component)container).GetComponent() != (Object)null || (Object)(object)((Component)container).GetComponentInParent() != (Object)null || (Object)(object)((Component)container.m_nview).GetComponent() != (Object)null || (Object)(object)((Component)((Component)container).transform.root).GetComponentInChildren() != (Object)null) { return false; } return !((Component)((Component)container).transform.root).GetComponentsInChildren(true).Any((MonoBehaviour component) => (Object)(object)component != (Object)null && string.Equals(((object)component).GetType().FullName, "OdinShip.ShipContainer", StringComparison.Ordinal)); } private static bool HasContainerPlayerAccess(Player player, Container container, bool flashGuardStone) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || (Object)(object)container == (Object)null) { return false; } if (container.m_checkGuardStone && !PrivateArea.CheckAccess(((Component)container).transform.position, 0f, flashGuardStone, false)) { return false; } return container.CheckAccess(player.GetPlayerID()); } private static bool IsContainerInUse(Container container) { if ((Object)(object)container == (Object)null) { return true; } if (container.IsInUse() || ((Object)(object)container.m_wagon != (Object)null && container.m_wagon.InUse())) { return true; } ZDO val = (((Object)(object)container.m_nview != (Object)null) ? container.m_nview.GetZDO() : null); if (val != null) { return val.GetInt("InUse", 0) == 1; } return false; } private static bool CanMutateContainerDirectly(Container container, bool allowLocalWithoutZNetView = false) { if ((Object)(object)container == (Object)null) { return false; } if ((Object)(object)container.m_nview == (Object)null || !container.m_nview.IsValid()) { return allowLocalWithoutZNetView; } return container.m_nview.IsOwner(); } private static bool IsContainerActionSuccessFxEnabled() { if (_containerActionSuccessFx != null) { return _containerActionSuccessFx.Value == Toggle.On; } return true; } private static int TryPlayChangedContainerActionSuccessVfx(Container container, int limit, int played) { if (limit <= 0 || played >= limit) { return played; } PlayContainerActionSuccessVfx(container); return played + 1; } private static void PlayContainerActionSuccessVfx(Container container) { //IL_0054: 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) if ((Object)(object)container == (Object)null || IsUnityNull((Object?)(object)container) || (Object)(object)ZNetScene.instance == (Object)null) { return; } GameObject prefab = ZNetScene.instance.GetPrefab("fx_HildirChest_Unlock"); if ((Object)(object)prefab == (Object)null || IsUnityNull((Object?)(object)prefab)) { return; } bool forceDisableInit = ZNetView.m_forceDisableInit; GameObject val; try { ZNetView.m_forceDisableInit = true; val = Object.Instantiate(prefab, ((Component)container).transform.position, ((Component)container).transform.rotation); } finally { ZNetView.m_forceDisableInit = forceDisableInit; } Object.Destroy((Object)(object)val, 5f); ZSFX[] componentsInChildren = val.GetComponentsInChildren(true); foreach (ZSFX val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null) && !IsUnityNull((Object?)(object)val2)) { val2.Stop(); ((Component)val2).gameObject.SetActive(false); } } } private static void PlayContainerActionSuccessSfx(Container container) { //IL_0070: 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) if ((Object)(object)container == (Object)null || IsUnityNull((Object?)(object)container) || (Object)(object)ZNetScene.instance == (Object)null) { return; } GameObject prefab = ZNetScene.instance.GetPrefab("fx_HildirChest_Unlock"); if (!((Object)(object)prefab == (Object)null) && !IsUnityNull((Object?)(object)prefab)) { Transform val = prefab.transform.Find("SFX"); if (!((Object)(object)val == (Object)null) && !IsUnityNull((Object?)(object)val)) { Object.Destroy((Object)(object)Object.Instantiate(((Component)val).gameObject, ((Component)container).transform.position, ((Component)container).transform.rotation), 5f); } } } private static int MoveItemToInventoryTopFirst(Inventory sourceInventory, Inventory targetInventory, ItemData source, HashSet? allowedSlots = null) { //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) if (sourceInventory == null || targetInventory == null || source?.m_shared == null || !sourceInventory.m_inventory.Contains(source)) { return 0; } int num = 0; if (CanStackForTopFirstMove(source)) { foreach (ItemData item in (from target in targetInventory.m_inventory where (allowedSlots == null || allowedSlots.Contains(target.m_gridPos)) && CanStackIntoTargetForTopFirstMove(target, source) orderby target.m_gridPos.y, target.m_gridPos.x select target).ToList()) { if (!sourceInventory.m_inventory.Contains(source) || source.m_stack <= 0) { break; } int num2 = Math.Min(item.m_shared.m_maxStackSize - item.m_stack, source.m_stack); if (num2 > 0) { int stack = source.m_stack; bool moveSucceeded = targetInventory.MoveItemToThis(sourceInventory, source, num2, item.m_gridPos.x, item.m_gridPos.y); num += CountMovedFromContainerSource(sourceInventory, source, stack, num2, moveSucceeded); } } } foreach (Vector2i item2 in GetInventorySlotsTopFirst(targetInventory)) { if (!sourceInventory.m_inventory.Contains(source) || source.m_stack <= 0) { break; } if ((allowedSlots == null || allowedSlots.Contains(item2)) && targetInventory.GetItemAt(item2.x, item2.y) == null) { int stack2 = source.m_stack; int stack3 = source.m_stack; bool moveSucceeded2 = targetInventory.MoveItemToThis(sourceInventory, source, stack3, item2.x, item2.y); int num3 = CountMovedFromContainerSource(sourceInventory, source, stack2, stack3, moveSucceeded2); num += num3; if (num3 == 0) { break; } } } return num; } private static bool CanMoveItemToInventoryTopFirst(Inventory sourceInventory, Inventory targetInventory, ItemData source) { if (sourceInventory == null || targetInventory == null || source?.m_shared == null || !sourceInventory.m_inventory.Contains(source)) { return false; } if (CanStackForTopFirstMove(source) && targetInventory.m_inventory.Any((ItemData target) => CanStackIntoTargetForTopFirstMove(target, source))) { return true; } return GetInventorySlotsTopFirst(targetInventory).Any((Vector2i slot) => targetInventory.GetItemAt(slot.x, slot.y) == null); } private static IEnumerable GetInventorySlotsTopFirst(Inventory inventory) { int width = Math.Max(1, inventory.GetWidth()); int height = Math.Max(0, inventory.GetHeight()); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { yield return new Vector2i(x, y); } } } private static bool CanStackForTopFirstMove(ItemData item) { if (item?.m_shared != null && item.m_shared.m_maxStackSize > 1) { return CanUseContainerActionStacking(item); } return false; } private static bool CanStackIntoTargetForTopFirstMove(ItemData target, ItemData source) { if (target?.m_shared != null && source?.m_shared != null && CanStackForTopFirstMove(target) && CanStackForTopFirstMove(source) && HasSameStackIdentity(target, source)) { return target.m_stack < target.m_shared.m_maxStackSize; } return false; } private static bool HasSameStackIdentity(ItemData left, ItemData right) { if (left?.m_shared != null && right?.m_shared != null && string.Equals(left.m_shared.m_name, right.m_shared.m_name, StringComparison.OrdinalIgnoreCase) && left.m_quality == right.m_quality) { return (float)left.m_worldLevel == (float)right.m_worldLevel; } return false; } private static string GetItemPrefabName(ItemData item) { return RestockTargetLimitCore.CleanPrefabNameForLookup(((Object)(object)item?.m_dropPrefab != (Object)null) ? ((Object)item.m_dropPrefab).name : ""); } private static int CountMovedFromContainerSource(Inventory sourceInventory, ItemData sourceItem, int before, int requestedAmount, bool moveSucceeded) { int after = (sourceInventory.m_inventory.Contains(sourceItem) ? sourceItem.m_stack : 0); return ContainerActionCore.CountMovedAmount(before, after, requestedAmount, moveSucceeded, useMoveSucceededFallback: true); } private static int CompareGridOrder(Vector2i a, Vector2i b) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) return ContainerActionCore.CompareGridOrder(a.x, a.y, b.x, b.y); } private static bool TryStartAreaContainerTransfer(Player player, Inventory playerInventory, Container anchor, AreaContainerActionKind action) { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) if (_areaContainerTransfer != null || AreaOwnershipHandoff.Phase != AreaOwnershipHandoffPhase.Idle || (Object)(object)player == (Object)null || playerInventory == null || (Object)(object)anchor == (Object)null || !TryGetContainerId(anchor, out var id)) { return false; } bool areaForQuickStack = action == AreaContainerActionKind.QuickStack; List actionContainers = GetActionContainers(player, anchor, areaForQuickStack); InventoryGui instance = InventoryGui.instance; if (instance != null) { instance.SetupDragItem((ItemData)null, (Inventory)null, 0); } _areaContainerTransfer = new AreaContainerTransferSession { Player = player, PlayerInventory = playerInventory, Anchor = anchor, AnchorId = id, Action = action, Targets = actionContainers, VfxLimit = (IsContainerActionSuccessFxEnabled() ? 10 : 0) }; ContinueAreaContainerTransfer(); return true; } private static void UpdateAreaContainerTransfer(Player player) { //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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) AreaContainerTransferSession areaContainerTransfer = _areaContainerTransfer; if (areaContainerTransfer == null) { return; } Container pendingTarget; bool flag; ZDO val2; AreaOwnershipObservedOwner observedAreaOwnership; int num2; int num3; if (!((Object)(object)player == (Object)null) && !((Object)(object)areaContainerTransfer.Player != (Object)(object)player) && areaContainerTransfer.PlayerInventory == GetPlayerInventory(player) && !player.m_isLoading && !((Character)player).IsDead() && !((Character)player).InCutscene() && !((Character)player).IsTeleporting() && !InventoryGui.IsVisible() && !IsUnityNull((Object?)(object)areaContainerTransfer.Anchor) && IsAreaContainerEligible(areaContainerTransfer.Anchor)) { Vector3 val = ((Component)player).transform.position - ((Component)areaContainerTransfer.Anchor).transform.position; if (!(((Vector3)(ref val)).sqrMagnitude > 64f)) { if (areaContainerTransfer.PendingDecision != AreaOwnershipHandoffDecision.None) { FinishPendingAreaContainerWithoutMutation(areaContainerTransfer); ContinueAreaContainerTransfer(); return; } pendingTarget = areaContainerTransfer.PendingTarget; if ((Object)(object)pendingTarget == (Object)null || AreaOwnershipHandoff.Phase == AreaOwnershipHandoffPhase.Idle) { if ((Object)(object)pendingTarget != (Object)null) { areaContainerTransfer.PendingTarget = null; areaContainerTransfer.NextTargetIndex++; } ContinueAreaContainerTransfer(); return; } flag = !IsUnityNull((Object?)(object)pendingTarget) && (Object)(object)pendingTarget.m_nview != (Object)null && pendingTarget.m_nview.IsValid() && pendingTarget.m_nview.GetZDO() != null; val2 = (flag ? pendingTarget.m_nview.GetZDO() : null); long num = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.GetUID() : 0); observedAreaOwnership = GetObservedAreaOwnership((val2 != null) ? val2.GetOwner() : 0, num, AreaOwnershipHandoff.ExpectedResponderUid); if (val2 != null) { num2 = (HasReachedAreaDataRevision(val2.DataRevision, areaContainerTransfer.GrantDataRevision) ? 1 : 0); if (num2 != 0) { num3 = (int)GetAreaOwnershipGrantTokenStatus(val2, AreaOwnershipHandoff.Identity, AreaOwnershipHandoff.GrantToken, num); goto IL_01b5; } } else { num2 = 0; } num3 = 0; goto IL_01b5; } } CancelAreaContainerTransfer(); return; IL_01b5: AreaOwnershipGrantTokenStatus tokenStatus = (AreaOwnershipGrantTokenStatus)num3; bool canExecute = num2 != 0 && val2 != null && val2.OwnerRevision == areaContainerTransfer.GrantOwnerRevision && GetNetworkTimeTicks() <= areaContainerTransfer.GrantExpiresAt && CanUseAreaContainerNow(areaContainerTransfer.Player, pendingTarget, areaContainerTransfer.Anchor, areaContainerTransfer.Action, requireDirectOwner: true); switch (AreaOwnershipHandoff.Observe(Time.unscaledTime, flag, observedAreaOwnership, flag && pendingTarget.m_nview.IsOwner(), tokenStatus, canExecute)) { case AreaOwnershipHandoffDecision.None: return; case AreaOwnershipHandoffDecision.Execute: ExecuteGrantedAreaContainer(areaContainerTransfer, pendingTarget); break; default: FinishPendingAreaContainerWithoutMutation(areaContainerTransfer); break; } ContinueAreaContainerTransfer(); } private static void ContinueAreaContainerTransfer() { AreaContainerTransferSession areaContainerTransfer = _areaContainerTransfer; if (areaContainerTransfer == null || (Object)(object)areaContainerTransfer.PendingTarget != (Object)null || AreaOwnershipHandoff.Phase != AreaOwnershipHandoffPhase.Idle) { return; } while (_areaContainerTransfer == areaContainerTransfer && areaContainerTransfer.NextTargetIndex < areaContainerTransfer.Targets.Count) { Container val = areaContainerTransfer.Targets[areaContainerTransfer.NextTargetIndex]; if (IsUnityNull((Object?)(object)val) || !CanUseAreaContainerNow(areaContainerTransfer.Player, val, areaContainerTransfer.Anchor, areaContainerTransfer.Action, requireDirectOwner: false)) { areaContainerTransfer.NextTargetIndex++; } else if (CanMutateContainerDirectly(val)) { areaContainerTransfer.NextTargetIndex++; int moved = 0; try { val.CheckForChanges(); if (CanUseAreaContainerNow(areaContainerTransfer.Player, val, areaContainerTransfer.Anchor, areaContainerTransfer.Action, requireDirectOwner: true) && HasLoadedCurrentContainerRevision(val)) { moved = ExecuteAreaContainerTransfer(areaContainerTransfer, val); } } catch (Exception ex) { Log.LogWarning((object)("Direct area container transfer failed safely: " + ex.Message)); FlushAreaTransferInventoriesAfterFailure(areaContainerTransfer, val); } RecordAreaContainerTransfer(areaContainerTransfer, val, moved); } else { if (TryBeginAreaOwnershipRequest(areaContainerTransfer, val)) { return; } areaContainerTransfer.NextTargetIndex++; } } if (_areaContainerTransfer == areaContainerTransfer && areaContainerTransfer.NextTargetIndex >= areaContainerTransfer.Targets.Count) { CompleteAreaContainerTransfer(areaContainerTransfer); } } private static bool TryBeginAreaOwnershipRequest(AreaContainerTransferSession session, Container target) { //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Expected O, but got Unknown //IL_0125: 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) if (HasExternalMultiUserChestActive || (Object)(object)target == (Object)null || (Object)(object)target.m_nview == (Object)null || !target.m_nview.IsValid() || !target.m_nview.HasOwner() || target.m_nview.IsOwner() || (Object)(object)ZNet.instance == (Object)null) { return false; } ZDO zDO = target.m_nview.GetZDO(); if (zDO == null || zDO.GetOwner() == 0L) { return false; } int nextAreaOwnershipRequestId = GetNextAreaOwnershipRequestId(); AreaOwnershipRequestIdentity areaOwnershipRequestIdentity = new AreaOwnershipRequestIdentity(nextAreaOwnershipRequestId, ((ZDOID)(ref zDO.m_uid)).UserID, ((ZDOID)(ref zDO.m_uid)).ID, session.Action); long owner = zDO.GetOwner(); if (!AreaOwnershipHandoff.TryBegin(areaOwnershipRequestIdentity, owner, Time.unscaledTime + 2.5f)) { return false; } session.PendingTarget = target; session.PendingIdentity = areaOwnershipRequestIdentity; session.PendingGrantToken = 0L; session.PendingDecision = AreaOwnershipHandoffDecision.None; session.GrantDataRevision = 0u; session.GrantOwnerRevision = 0; session.GrantExpiresAt = 0L; try { ZPackage val = new ZPackage(); val.Write(1); val.Write(nextAreaOwnershipRequestId); val.Write((int)session.Action); val.Write(session.Player.GetPlayerID()); val.Write(session.AnchorId); val.Write(zDO.m_uid); val.Write(owner); val.Write(zDO.OwnerRevision); target.m_nview.InvokeRPC("InventoryActions_AreaOwnershipRequestV1", new object[1] { val }); return true; } catch (Exception ex) { Log.LogWarning((object)("Area container ownership request failed: " + ex.Message)); AreaOwnershipHandoff.Cancel(); session.PendingTarget = null; return false; } } private static void ExecuteGrantedAreaContainer(AreaContainerTransferSession session, Container target) { AreaOwnershipRequestIdentity identity = AreaOwnershipHandoff.Identity; long grantToken = AreaOwnershipHandoff.GrantToken; session.PendingTarget = null; session.PendingDecision = AreaOwnershipHandoffDecision.None; session.NextTargetIndex++; int moved = 0; try { target.CheckForChanges(); if (CanExecuteGrantedAreaContainer(session, target, identity, grantToken)) { moved = ExecuteAreaContainerTransfer(session, target); } } catch (Exception ex) { Log.LogWarning((object)("Granted area container transfer failed safely: " + ex.Message)); FlushAreaTransferInventoriesAfterFailure(session, target); } finally { ClearAreaOwnershipLeaseIfMatching(target, identity, grantToken, ZNet.GetUID()); AreaOwnershipHandoff.CompleteExecution(); session.PendingIdentity = default(AreaOwnershipRequestIdentity); session.PendingGrantToken = 0L; } RecordAreaContainerTransfer(session, target, moved); } private static bool CanExecuteGrantedAreaContainer(AreaContainerTransferSession session, Container target, AreaOwnershipRequestIdentity identity, long grantToken) { if ((Object)(object)target == (Object)null || IsUnityNull((Object?)(object)target) || (Object)(object)target.m_nview == (Object)null || !target.m_nview.IsValid() || !target.m_nview.IsOwner()) { return false; } ZDO zDO = target.m_nview.GetZDO(); if (zDO != null && zDO.GetOwner() == ZNet.GetUID() && zDO.OwnerRevision == session.GrantOwnerRevision && HasReachedAreaDataRevision(zDO.DataRevision, session.GrantDataRevision) && target.m_lastRevision == zDO.DataRevision && GetNetworkTimeTicks() <= session.GrantExpiresAt && GetAreaOwnershipGrantTokenStatus(zDO, identity, grantToken, ZNet.GetUID()) == AreaOwnershipGrantTokenStatus.Matching) { return CanUseAreaContainerNow(session.Player, target, session.Anchor, session.Action, requireDirectOwner: true); } return false; } private static int ExecuteAreaContainerTransfer(AreaContainerTransferSession session, Container target) { if (session.Action == AreaContainerActionKind.QuickStack) { List list = session.PlayerInventory.m_inventory.Where((ItemData item) => ShouldQuickStackItem(session.Player, session.PlayerInventory, item, includeHotbar: false)).ToList(); list.Sort((ItemData a, ItemData b) => -CompareGridOrder(a.m_gridPos, b.m_gridPos)); return QuickStackItemsIntoContainer(session.PlayerInventory, target.m_inventory, list); } List list2 = session.PlayerInventory.m_inventory.Where((ItemData item) => ShouldTakeStacksTarget(session.Player, session.PlayerInventory, item, includeHotbar: false, RestockMode.AreaFavoriteRestock)).ToList(); list2.Sort((ItemData a, ItemData b) => -CompareGridOrder(a.m_gridPos, b.m_gridPos)); return RestockTargetsFromContainer(session.PlayerInventory, target.m_inventory, list2, RestockMode.AreaFavoriteRestock); } private static void RecordAreaContainerTransfer(AreaContainerTransferSession session, Container target, int moved) { if (moved > 0) { session.TotalMoved += moved; session.PlayerInventoryChanged = true; session.ChangedContainerVfxCount = TryPlayChangedContainerActionSuccessVfx(target, session.VfxLimit, session.ChangedContainerVfxCount); } } private static void FlushAreaTransferInventoriesAfterFailure(AreaContainerTransferSession session, Container target) { try { session.PlayerInventory.Changed(); } catch (Exception ex) { Log.LogWarning((object)("Failed to flush player inventory after an area transfer error: " + ex.Message)); } try { Inventory inventory = target.m_inventory; if (inventory != null) { inventory.Changed(); } } catch (Exception ex2) { Log.LogWarning((object)("Failed to flush container inventory after an area transfer error: " + ex2.Message)); } } private static void CompleteAreaContainerTransfer(AreaContainerTransferSession session) { _areaContainerTransfer = null; if (session.PlayerInventoryChanged) { session.PlayerInventory.Changed(); if (session.VfxLimit > 0) { PlayContainerActionSuccessSfx(session.Anchor); } } if (session.Action == AreaContainerActionKind.QuickStack) { ShowContainerActionResult(session.Player, "$inventoryactions_action_stack", "Stack", session.TotalMoved); } else { ShowContainerActionResult(session.Player, "$inventoryactions_action_take_stacks", "Take stacks", session.TotalMoved); } } private static void FinishPendingAreaContainerWithoutMutation(AreaContainerTransferSession session) { Container pendingTarget = session.PendingTarget; AreaOwnershipRequestIdentity pendingIdentity = session.PendingIdentity; long pendingGrantToken = session.PendingGrantToken; if ((Object)(object)pendingTarget != (Object)null && !IsUnityNull((Object?)(object)pendingTarget)) { ClearAreaOwnershipLeaseIfMatching(pendingTarget, pendingIdentity, pendingGrantToken, ZNet.GetUID()); } AreaOwnershipHandoff.Cancel(); session.PendingTarget = null; session.PendingIdentity = default(AreaOwnershipRequestIdentity); session.PendingGrantToken = 0L; session.PendingDecision = AreaOwnershipHandoffDecision.None; session.NextTargetIndex++; } private static void CancelAreaContainerTransfer() { AreaContainerTransferSession areaContainerTransfer = _areaContainerTransfer; if ((Object)(object)areaContainerTransfer?.PendingTarget != (Object)null) { ClearAreaOwnershipLeaseIfMatching(areaContainerTransfer.PendingTarget, areaContainerTransfer.PendingIdentity, areaContainerTransfer.PendingGrantToken, ((Object)(object)ZNet.instance != (Object)null) ? ZNet.GetUID() : 0); } AreaOwnershipHandoff.Cancel(); if (areaContainerTransfer != null && areaContainerTransfer.PlayerInventoryChanged && areaContainerTransfer.PlayerInventory != null) { areaContainerTransfer.PlayerInventory.Changed(); } _areaContainerTransfer = null; } internal static void RegisterAreaOwnershipRpcs(Container container) { if ((Object)(object)container == (Object)null || IsUnityNull((Object?)(object)container)) { return; } if ((Object)(object)container.m_nview == (Object)null) { container.m_nview = (((Object)(object)container.m_rootObjectOverride != (Object)null) ? ((Component)container.m_rootObjectOverride).GetComponent() : ((Component)container).GetComponent()); } if (!((Object)(object)container.m_nview == (Object)null) && !IsUnityNull((Object?)(object)container.m_nview)) { container.m_nview.Unregister("InventoryActions_AreaOwnershipRequestV1"); container.m_nview.Unregister("InventoryActions_AreaOwnershipResponseV1"); container.m_nview.Register("InventoryActions_AreaOwnershipRequestV1", (Action)delegate(long sender, ZPackage package) { RPC_RequestAreaOwnership(container, sender, package); }); container.m_nview.Register("InventoryActions_AreaOwnershipResponseV1", (Action)delegate(long sender, ZPackage package) { RPC_AreaOwnershipResponse(container, sender, package); }); } } internal static void UnregisterAreaOwnershipRpcs(Container container) { if (!((Object)(object)container == (Object)null) && !IsUnityNull((Object?)(object)container)) { if ((Object)(object)container.m_nview != (Object)null && !IsUnityNull((Object?)(object)container.m_nview)) { container.m_nview.Unregister("InventoryActions_AreaOwnershipRequestV1"); container.m_nview.Unregister("InventoryActions_AreaOwnershipResponseV1"); } if ((Object)(object)_areaContainerTransfer?.PendingTarget == (Object)(object)container) { _areaContainerTransfer.PendingDecision = AreaOwnershipHandoffDecision.Unloaded; } } } private static void RPC_RequestAreaOwnership(Container container, long sender, ZPackage package) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) if (!TryReadAreaOwnershipRequest(package, out var identity, out var requesterPlayerId, out var anchorId, out var targetId, out var expectedOwner, out var expectedOwnerRevision)) { return; } ZDO zdo; AreaOwnershipFailure areaOwnershipFailure = ValidateAreaOwnershipRequest(container, sender, identity, requesterPlayerId, anchorId, targetId, expectedOwner, expectedOwnerRevision, out zdo); long num = 0L; long num2 = 0L; uint grantDataRevision = 0u; ushort grantOwnerRevision = 0; bool flag = false; if (areaOwnershipFailure == AreaOwnershipFailure.None && zdo != null) { num2 = GetNetworkTimeTicks() + AreaOwnershipLeaseDurationTicks; num = CreateAreaOwnershipGrantToken(); try { zdo.Set("InventoryActions_AreaLeaseRequester", sender); zdo.Set("InventoryActions_AreaLeaseRequestId", identity.RequestId); zdo.Set("InventoryActions_AreaLeaseAction", (int)identity.Action); zdo.Set("InventoryActions_AreaLeaseExpiry", num2); zdo.Set("InventoryActions_AreaLeaseToken", num); grantDataRevision = zdo.DataRevision; ZDOMan.instance.ForceSendZDO(sender, zdo.m_uid); zdo.SetOwner(sender); grantOwnerRevision = zdo.OwnerRevision; flag = zdo.GetOwner() == sender; if (!flag) { areaOwnershipFailure = AreaOwnershipFailure.Unavailable; ClearAreaOwnershipLeaseIfMatching(container, identity, num, sender); } } catch (Exception ex) { Log.LogWarning((object)("Area ownership grant failed safely: " + ex.Message)); areaOwnershipFailure = AreaOwnershipFailure.Unavailable; flag = false; ClearAreaOwnershipLeaseIfMatching(container, identity, num, sender); } } SendAreaOwnershipResponse(container, sender, identity, flag, areaOwnershipFailure, num, grantDataRevision, grantOwnerRevision, num2); } private static void RPC_AreaOwnershipResponse(Container container, long sender, ZPackage package) { if (!TryReadAreaOwnershipResponse(package, out var identity, out var granted, out var _, out var token, out var grantDataRevision, out var grantOwnerRevision, out var expiresAt)) { return; } AreaContainerTransferSession areaContainerTransfer = _areaContainerTransfer; if (areaContainerTransfer != null && !((Object)(object)areaContainerTransfer.PendingTarget != (Object)(object)container) && AreaOwnershipHandoff.Identity.Equals(identity)) { AreaOwnershipHandoffPhase phase = AreaOwnershipHandoff.Phase; AreaOwnershipHandoffDecision areaOwnershipHandoffDecision = AreaOwnershipHandoff.ReceiveResponse(identity, sender, granted, token, Time.unscaledTime, Time.unscaledTime + 3f); if (phase == AreaOwnershipHandoffPhase.AwaitingResponse && AreaOwnershipHandoff.Phase == AreaOwnershipHandoffPhase.AwaitingOwnership) { areaContainerTransfer.PendingGrantToken = token; areaContainerTransfer.GrantDataRevision = grantDataRevision; areaContainerTransfer.GrantOwnerRevision = grantOwnerRevision; areaContainerTransfer.GrantExpiresAt = expiresAt; } else if (areaOwnershipHandoffDecision != AreaOwnershipHandoffDecision.None) { areaContainerTransfer.PendingDecision = areaOwnershipHandoffDecision; } } } private static AreaOwnershipFailure ValidateAreaOwnershipRequest(Container container, long sender, AreaOwnershipRequestIdentity identity, long requesterPlayerId, ZDOID anchorId, ZDOID targetId, long expectedOwner, ushort expectedOwnerRevision, out ZDO? zdo) { //IL_0072: 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_012c: 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_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) zdo = null; bool flag = (Object)(object)container == (Object)null || (Object)(object)container.m_nview == (Object)null || sender == 0L || requesterPlayerId == 0L || identity.RequestId <= 0; if (!flag) { AreaContainerActionKind action = identity.Action; bool flag2 = (uint)(action - 1) <= 1u; flag = !flag2; } if (flag) { return AreaOwnershipFailure.InvalidRequest; } zdo = container.m_nview.GetZDO(); if (zdo == null || zdo.m_uid != targetId || identity.ContainerUserId != ((ZDOID)(ref targetId)).UserID || identity.ContainerObjectId != ((ZDOID)(ref targetId)).ID) { return AreaOwnershipFailure.InvalidRequest; } if (HasExternalMultiUserChestActive) { return AreaOwnershipFailure.Unsupported; } if (!container.m_nview.IsValid() || !container.m_nview.IsOwner() || zdo.GetOwner() != ZNet.GetUID() || expectedOwner != ZNet.GetUID() || zdo.OwnerRevision != expectedOwnerRevision) { return AreaOwnershipFailure.NotOwner; } long num = zdo.GetLong("InventoryActions_AreaLeaseToken", 0L); long num2 = zdo.GetLong("InventoryActions_AreaLeaseExpiry", 0L); if (num != 0L && num2 > GetNetworkTimeTicks()) { return AreaOwnershipFailure.Busy; } if (!TryGetRpcSenderPlayer(sender, requesterPlayerId, out Player requester) || (Object)(object)requester == (Object)null) { return AreaOwnershipFailure.InvalidRequest; } Container val = ResolveKnownAreaContainer(anchorId); if (!((Object)(object)val == (Object)null) && IsAreaContainerEligible(val) && HasContainerPlayerAccessForRpc(requesterPlayerId, val)) { Vector3 val2 = ((Component)requester).transform.position - ((Component)val).transform.position; if (!(((Vector3)(ref val2)).sqrMagnitude > 64f)) { if (!IsAreaContainerEligible(container)) { return AreaOwnershipFailure.Unavailable; } if (IsContainerInUse(container) || IsContainerInUse(val)) { return AreaOwnershipFailure.InUse; } if (!HasContainerPlayerAccessForRpc(requesterPlayerId, container)) { return AreaOwnershipFailure.NoAccess; } float areaContainerRange = GetAreaContainerRange(identity.Action); if (!(areaContainerRange <= 0f)) { val2 = ((Component)container).transform.position - ((Component)val).transform.position; if (!(((Vector3)(ref val2)).sqrMagnitude > areaContainerRange * areaContainerRange)) { return AreaOwnershipFailure.None; } } return AreaOwnershipFailure.OutOfRange; } } return AreaOwnershipFailure.OutOfRange; } private static bool TryGetRpcSenderPlayer(long sender, long requesterPlayerId, out Player? requester) { requester = null; foreach (Player allPlayer in Player.GetAllPlayers()) { if (!((Object)(object)allPlayer == (Object)null) && !IsUnityNull((Object?)(object)allPlayer) && allPlayer.GetPlayerID() == requesterPlayerId && !((Object)(object)((Character)allPlayer).m_nview == (Object)null) && ((Character)allPlayer).m_nview.IsValid()) { ZDO zDO = ((Character)allPlayer).m_nview.GetZDO(); if (zDO != null && zDO.GetOwner() == sender) { requester = allPlayer; return true; } } } return false; } private static bool HasContainerPlayerAccessForRpc(long playerId, Container container) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)container == (Object)null || !container.CheckAccess(playerId)) { return false; } if (!container.m_checkGuardStone) { return true; } bool flag = false; foreach (PrivateArea allArea in PrivateArea.m_allAreas) { if (!((Object)(object)allArea == (Object)null) && !IsUnityNull((Object?)(object)allArea) && allArea.IsEnabled() && allArea.IsInside(((Component)container).transform.position, 0f)) { if (((Object)(object)allArea.m_piece != (Object)null && allArea.m_piece.GetCreator() == playerId) || allArea.GetPermittedPlayers().Any((KeyValuePair entry) => entry.Key == playerId)) { return true; } flag = true; } } return !flag; } private static Container? ResolveKnownAreaContainer(ZDOID id) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) for (int num = Runtime.KnownContainers.Count - 1; num >= 0; num--) { Container val = Runtime.KnownContainers[num]; ZDOID id2; if ((Object)(object)val == (Object)null || IsUnityNull((Object?)(object)val)) { Runtime.KnownContainers.RemoveAt(num); } else if (TryGetContainerId(val, out id2) && id2 == id) { return val; } } return null; } private static bool CanUseAreaContainerNow(Player player, Container container, Container anchor, AreaContainerActionKind action, bool requireDirectOwner) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) if (HasExternalMultiUserChestActive || (Object)(object)player == (Object)null || player.m_isLoading || (Object)(object)container == (Object)null || (Object)(object)anchor == (Object)null || !IsAreaContainerEligible(container) || !IsAreaContainerEligible(anchor) || IsContainerInUse(container) || IsContainerInUse(anchor) || !HasContainerPlayerAccess(player, container, flashGuardStone: false) || !HasContainerPlayerAccess(player, anchor, flashGuardStone: false)) { return false; } Vector3 val = ((Component)player).transform.position - ((Component)anchor).transform.position; if (((Vector3)(ref val)).sqrMagnitude > 64f) { return false; } float areaContainerRange = GetAreaContainerRange(action); if (!(areaContainerRange <= 0f)) { val = ((Component)container).transform.position - ((Component)anchor).transform.position; if (!(((Vector3)(ref val)).sqrMagnitude > areaContainerRange * areaContainerRange)) { if (requireDirectOwner) { return CanMutateContainerDirectly(container); } if (!CanMutateContainerDirectly(container)) { return CanRequestAreaOwnership(container); } return true; } } return false; } private static bool HasLoadedCurrentContainerRevision(Container container) { if ((Object)(object)container == (Object)null || (Object)(object)container.m_nview == (Object)null || !container.m_nview.IsValid() || !container.m_nview.IsOwner()) { return false; } ZDO zDO = container.m_nview.GetZDO(); if (zDO != null && zDO.GetOwner() == ZNet.GetUID()) { return container.m_lastRevision == zDO.DataRevision; } return false; } private static bool CanRequestAreaOwnership(Container container) { if (!HasExternalMultiUserChestActive && (Object)(object)container != (Object)null && (Object)(object)container.m_nview != (Object)null && container.m_nview.IsValid() && container.m_nview.HasOwner()) { return !container.m_nview.IsOwner(); } return false; } private static float GetAreaContainerRange(AreaContainerActionKind action) { if (action != AreaContainerActionKind.QuickStack) { return _areaRestockRange.Value; } return _areaQuickStackRange.Value; } private static AreaOwnershipObservedOwner GetObservedAreaOwnership(long observedOwner, long localUid, long expectedResponder) { if (observedOwner == 0L) { return AreaOwnershipObservedOwner.Unknown; } if (observedOwner == localUid) { return AreaOwnershipObservedOwner.LocalRequester; } if (observedOwner != expectedResponder) { return AreaOwnershipObservedOwner.Other; } return AreaOwnershipObservedOwner.ExpectedResponder; } private static AreaOwnershipGrantTokenStatus GetAreaOwnershipGrantTokenStatus(ZDO? zdo, AreaOwnershipRequestIdentity identity, long grantToken, long requesterUid) { if (zdo == null || grantToken == 0L) { return AreaOwnershipGrantTokenStatus.Missing; } long num = zdo.GetLong("InventoryActions_AreaLeaseToken", 0L); if (num == 0L) { return AreaOwnershipGrantTokenStatus.Missing; } if (num != grantToken || zdo.GetLong("InventoryActions_AreaLeaseRequester", 0L) != requesterUid || zdo.GetInt("InventoryActions_AreaLeaseRequestId", 0) != identity.RequestId || zdo.GetInt("InventoryActions_AreaLeaseAction", 0) != (int)identity.Action) { return AreaOwnershipGrantTokenStatus.Other; } return AreaOwnershipGrantTokenStatus.Matching; } private static void ClearAreaOwnershipLeaseIfMatching(Container container, AreaOwnershipRequestIdentity identity, long grantToken, long leaseRequesterUid) { if ((Object)(object)container == (Object)null || IsUnityNull((Object?)(object)container) || leaseRequesterUid == 0L || (Object)(object)container.m_nview == (Object)null || !container.m_nview.IsValid() || !container.m_nview.IsOwner()) { return; } ZDO zDO = container.m_nview.GetZDO(); if (zDO != null) { long num = zDO.GetLong("InventoryActions_AreaLeaseToken", 0L); bool flag = identity.RequestId > 0 && ((ZDOID)(ref zDO.m_uid)).UserID == identity.ContainerUserId && ((ZDOID)(ref zDO.m_uid)).ID == identity.ContainerObjectId && zDO.GetLong("InventoryActions_AreaLeaseRequester", 0L) == leaseRequesterUid && zDO.GetInt("InventoryActions_AreaLeaseRequestId", 0) == identity.RequestId && zDO.GetInt("InventoryActions_AreaLeaseAction", 0) == (int)identity.Action; if (num != 0 && flag && (grantToken == 0L || num == grantToken)) { zDO.Set("InventoryActions_AreaLeaseToken", 0L); } } } private static void SendAreaOwnershipResponse(Container container, long target, AreaOwnershipRequestIdentity identity, bool granted, AreaOwnershipFailure failure, long token, uint grantDataRevision, ushort grantOwnerRevision, long expiresAt) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown if (target == 0L || (Object)(object)container == (Object)null || (Object)(object)container.m_nview == (Object)null || !container.m_nview.IsValid()) { return; } try { ZPackage val = new ZPackage(); val.Write(1); val.Write(identity.RequestId); val.Write(identity.ContainerUserId); val.Write(identity.ContainerObjectId); val.Write((int)identity.Action); val.Write(granted); val.Write((int)failure); val.Write(token); val.Write(grantDataRevision); val.Write(grantOwnerRevision); val.Write(expiresAt); container.m_nview.InvokeRPC(target, "InventoryActions_AreaOwnershipResponseV1", new object[1] { val }); } catch (Exception ex) { Log.LogWarning((object)("Area ownership response failed: " + ex.Message)); } } private static bool TryReadAreaOwnershipRequest(ZPackage package, out AreaOwnershipRequestIdentity identity, out long requesterPlayerId, out ZDOID anchorId, out ZDOID targetId, out long expectedOwner, out ushort expectedOwnerRevision) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //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) //IL_0065: 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_0072: 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_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) identity = default(AreaOwnershipRequestIdentity); requesterPlayerId = 0L; anchorId = ZDOID.None; targetId = ZDOID.None; expectedOwner = 0L; expectedOwnerRevision = 0; if (package == null || package.Size() <= 0 || package.Size() > 256) { return false; } try { int num = package.ReadInt(); int num2 = package.ReadInt(); AreaContainerActionKind action = (AreaContainerActionKind)package.ReadInt(); requesterPlayerId = package.ReadLong(); anchorId = package.ReadZDOID(); targetId = package.ReadZDOID(); expectedOwner = package.ReadLong(); expectedOwnerRevision = package.ReadUShort(); identity = new AreaOwnershipRequestIdentity(num2, ((ZDOID)(ref targetId)).UserID, ((ZDOID)(ref targetId)).ID, action); return num == 1 && num2 > 0 && targetId != ZDOID.None && package.GetPos() == package.Size(); } catch { identity = default(AreaOwnershipRequestIdentity); return false; } } private static bool TryReadAreaOwnershipResponse(ZPackage package, out AreaOwnershipRequestIdentity identity, out bool granted, out AreaOwnershipFailure failure, out long token, out uint grantDataRevision, out ushort grantOwnerRevision, out long expiresAt) { identity = default(AreaOwnershipRequestIdentity); granted = false; failure = AreaOwnershipFailure.InvalidRequest; token = 0L; grantDataRevision = 0u; grantOwnerRevision = 0; expiresAt = 0L; if (package == null || package.Size() <= 0 || package.Size() > 256) { return false; } try { int num = package.ReadInt(); int num2 = package.ReadInt(); long num3 = package.ReadLong(); uint num4 = package.ReadUInt(); AreaContainerActionKind action = (AreaContainerActionKind)package.ReadInt(); granted = package.ReadBool(); failure = (AreaOwnershipFailure)package.ReadInt(); token = package.ReadLong(); grantDataRevision = package.ReadUInt(); grantOwnerRevision = package.ReadUShort(); expiresAt = package.ReadLong(); identity = new AreaOwnershipRequestIdentity(num2, num3, num4, action); return num == 1 && num2 > 0 && num3 != 0L && num4 != 0 && package.GetPos() == package.Size(); } catch { identity = default(AreaOwnershipRequestIdentity); return false; } } private static bool TryGetContainerId(Container container, out ZDOID id) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: 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_005c: Unknown result type (might be due to invalid IL or missing references) id = ZDOID.None; if ((Object)(object)container == (Object)null || IsUnityNull((Object?)(object)container) || (Object)(object)container.m_nview == (Object)null || !container.m_nview.IsValid()) { return false; } ZDO zDO = container.m_nview.GetZDO(); if (zDO == null) { return false; } id = zDO.m_uid; return id != ZDOID.None; } private static int GetNextAreaOwnershipRequestId() { if (_nextAreaOwnershipRequestId <= 0) { _nextAreaOwnershipRequestId = 1; } return _nextAreaOwnershipRequestId++; } private static long CreateAreaOwnershipGrantToken() { long num; do { num = BitConverter.ToInt64(Guid.NewGuid().ToByteArray(), 0); } while (num == 0L); return num; } private static long GetNetworkTimeTicks() { if (!((Object)(object)ZNet.instance != (Object)null)) { return DateTime.UtcNow.Ticks; } return ZNet.instance.GetTime().Ticks; } private static bool HasReachedAreaDataRevision(uint observed, uint required) { return (int)(observed - required) >= 0; } internal static bool TryRejectContainerRequestDuringAreaLease(Container container, long requesterUid, string denialResponseRpc) { if ((Object)(object)container == (Object)null || requesterUid == 0L || string.IsNullOrWhiteSpace(denialResponseRpc) || (Object)(object)container.m_nview == (Object)null || !container.m_nview.IsValid() || !container.m_nview.IsOwner()) { return false; } ZDO zDO = container.m_nview.GetZDO(); if (zDO == null) { return false; } if (zDO.GetLong("InventoryActions_AreaLeaseToken", 0L) == 0L) { return false; } if (zDO.GetLong("InventoryActions_AreaLeaseExpiry", 0L) <= GetNetworkTimeTicks()) { zDO.Set("InventoryActions_AreaLeaseToken", 0L); return false; } container.m_nview.InvokeRPC(requesterUid, denialResponseRpc, new object[1] { false }); return true; } private static void BindConfigs() { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Expected O, but got Unknown //IL_00ca: 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_0102: Expected O, but got Unknown //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Expected O, but got Unknown //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Expected O, but got Unknown //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Expected O, but got Unknown //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Expected O, but got Unknown //IL_02c1: Unknown result type (might be due to invalid IL or missing references) //IL_02cc: Expected O, but got Unknown //IL_0325: Unknown result type (might be due to invalid IL or missing references) //IL_0330: Expected O, but got Unknown _serverConfigLocked = ConfigEntry("1 - General", "Lock Configuration", Toggle.On, "When enabled, only server admins can modify this mod's synced configuration."); ConfigSync.AddLockingConfigEntry(_serverConfigLocked); _enableInventoryTrashPanel = ConfigEntry("1 - General", "Enable Inventory Trash Panel", Toggle.On, "When enabled, shows a trash panel below the player inventory. Dropping a held player-inventory item on it opens a confirmation dialog before deleting the held amount."); _areaQuickStackRange = ConfigEntry("1 - General", "Area Quick Stack Range", 10f, new ConfigDescription("Range in meters for hover Area Quick Stack. Set to 0 to disable area quick stack. The opened-container Place stacks button only uses the current container.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 50f), Array.Empty())); _areaRestockRange = ConfigEntry("1 - General", "Area Take Stacks Range", 10f, new ConfigDescription("Range in meters for hover Area Take Stacks. Set to 0 to disable area take stacks. The opened-container Take stacks button only uses the current container.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 50f), Array.Empty())); _favoriteModifierKey = ConfigEntry("2 - Client", "Favorite Modifier Key", new KeyboardShortcut((KeyCode)308, Array.Empty()), new ConfigDescription("Hold this and left-click a player inventory cell to toggle that favorite slot. Alt accepts both LeftAlt and RightAlt.", (AcceptableValueBase)(object)new AcceptableShortcuts(), new object[1] { new ConfigurationManagerAttributes { Order = 900 } }), synchronizedSetting: false); _containerRestockKey = ConfigEntry("2 - Client", "Container Restock Key", new KeyboardShortcut((KeyCode)101, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), new ConfigDescription("Hold this while hovering a container to take stacks into favorite slots from that container and nearby containers. Alt accepts both LeftAlt and RightAlt.", (AcceptableValueBase)(object)new AcceptableShortcuts(), new object[1] { new ConfigurationManagerAttributes { Order = 890 } }), synchronizedSetting: false); _favoriteBorderColor = ConfigEntry("2 - Client", "Favorite Border Color", FavoriteBorderDefaultColor, new ConfigDescription("Color for favorite slot borders. Uses the same RRGGBBAA color format as InventorySlots color configs. Not synced with server.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 880 } }), synchronizedSetting: false); _favoriteBorderColor.SettingChanged += delegate { RefreshFavoriteBorders(); }; _containerActionSuccessFx = ConfigEntry("2 - Client", "Container Action Success FX", Toggle.On, new ConfigDescription("Enables chest-unlock success effects for hover hold area quick stack/restock. Shows VFX at up to 10 changed containers and plays the SFX once at the interacted container. Opened-container buttons do not spawn effects. Not synced with server.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 870 } }), synchronizedSetting: false); _sortButtonPositionOffset = ConfigEntry("2 - Client", "Sort Button Position", "x: 0 y: 0", new ConfigDescription("Client-only position offset for the player inventory sort button. Format: x: 0 y: 0. Positive x moves right; positive y moves up.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 840, CustomDrawer = DrawButtonPositionOffsetConfig } }), synchronizedSetting: false); _trashButtonPositionOffset = ConfigEntry("2 - Client", "Trash Button Position", "x: 0 y: 0", new ConfigDescription("Client-only position offset for the inventory trash button. Format: x: 0 y: 0. Positive x moves right; positive y moves up.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 830, CustomDrawer = DrawButtonPositionOffsetConfig } }), synchronizedSetting: false); _restockTargetStackLimitsConfig = ConfigEntry("3 - Restock", "Restock Target Stack Limits", "", new ConfigDescription("Client-only per-item target stack caps for Take stacks/restock into favorite slots. Keys may be prefab names, internal item names, or localized item names in the current client language, such as Stone: 10, Coins: 500. Separate entries with commas, semicolons, or new lines. Empty uses each item's normal max stack; 0 prevents restocking that item.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 700, CustomDrawer = DrawRestockTargetStackLimitsConfig } }), synchronizedSetting: false); _restockTargetStackLimitsConfig.SettingChanged += delegate { RefreshRestockTargetStackLimits(); }; RefreshRestockTargetStackLimits(); } private static ConfigEntry ConfigEntry(string group, string name, T value, string description, bool synchronizedSetting = true) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown return ConfigEntry(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty()), synchronizedSetting); } private static ConfigEntry ConfigEntry(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown ConfigDescription val = new ConfigDescription(description.Description + " [" + (synchronizedSetting ? "Synced with Server" : "Not Synced with Server") + "]", description.AcceptableValues, description.Tags); ConfigEntry val2 = ((BaseUnityPlugin)_instance).Config.Bind(group, name, value, val); ConfigSync.AddConfigEntry(val2).SynchronizedConfig = synchronizedSetting; return val2; } private static Vector2 GetSortButtonPositionOffset() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) return GetConfiguredButtonPositionOffset(_sortButtonPositionOffset); } private static Vector2 GetTrashButtonPositionOffset() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) return GetConfiguredButtonPositionOffset(_trashButtonPositionOffset); } private static Vector2 GetConfiguredButtonPositionOffset(ConfigEntry? entry) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) if (entry == null) { return Vector2.zero; } if (TryParseButtonPositionOffset(entry.Value, out var offset)) { return offset; } return Vector2.zero; } private static bool TryParseButtonPositionOffset(string? raw, out Vector2 offset) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: 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_0075: Unknown result type (might be due to invalid IL or missing references) offset = Vector2.zero; if (string.IsNullOrWhiteSpace(raw)) { return true; } string[] array = raw.ToLowerInvariant().Replace('x', ' ').Replace('y', ' ') .Split(ButtonPositionOffsetSeparators, StringSplitOptions.RemoveEmptyEntries); if (array.Length < 2 || !float.TryParse(array[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) || !float.TryParse(array[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2)) { return false; } offset = new Vector2(result, result2); return true; } private static void DrawButtonPositionOffsetConfig(ConfigEntryBase entry) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) string key = entry.Definition.Section + "/" + entry.Definition.Key; if (!ButtonPositionOffsetEditorStates.TryGetValue(key, out ButtonPositionOffsetEditorState value)) { value = new ButtonPositionOffsetEditorState(); ButtonPositionOffsetEditorStates[key] = value; } string text = (entry.BoxedValue as string) ?? ""; if (!string.Equals(text, value.LastEntryValue, StringComparison.Ordinal)) { if (TryParseButtonPositionOffset(text, out var offset)) { value.X = FormatButtonPositionOffsetValue(offset.x); value.Y = FormatButtonPositionOffsetValue(offset.y); } value.LastEntryValue = text; } GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label("x", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(12f) }); string text2 = FilterSignedFloatText(GUILayout.TextField(value.X, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) })); GUILayout.Label("y", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(12f) }); string text3 = FilterSignedFloatText(GUILayout.TextField(value.Y, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) })); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); if (string.Equals(text2, value.X, StringComparison.Ordinal) && string.Equals(text3, value.Y, StringComparison.Ordinal)) { return; } value.X = text2; value.Y = text3; if (TryParseButtonPositionOffsetValue(value.X, out var result) && TryParseButtonPositionOffsetValue(value.Y, out var result2)) { string text4 = (value.LastEntryValue = "x: " + FormatButtonPositionOffsetValue(result) + " y: " + FormatButtonPositionOffsetValue(result2)); if (!string.Equals(text, text4, StringComparison.Ordinal)) { entry.BoxedValue = text4; } } } private static bool TryParseButtonPositionOffsetValue(string value, out float result) { return float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out result); } private static string FormatButtonPositionOffsetValue(float value) { return value.ToString("0.###", CultureInfo.InvariantCulture); } private static string FilterSignedFloatText(string value) { if (string.IsNullOrEmpty(value)) { return ""; } return new string(value.Where((char c) => char.IsDigit(c) || c == '-' || c == '+' || c == '.').ToArray()); } private static bool IsUnityNull(Object? obj) { return obj == (Object)null; } private static bool IsOutOfBounds(Inventory inventory, Vector2i pos) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (inventory != null && pos.x >= 0 && pos.y >= 0 && pos.x < inventory.GetWidth()) { return pos.y >= inventory.GetHeight(); } return true; } private static Inventory? GetPlayerInventory(Player? player) { if (!((Object)(object)player != (Object)null)) { return null; } return ((Humanoid)player).GetInventory(); } private static bool IsPlayerInventory(Player? player, Inventory? inventory) { if ((Object)(object)player != (Object)null && inventory != null) { return inventory == GetPlayerInventory(player); } return false; } private static bool IsPlayerActionCell(Inventory inventory, Vector2i pos, bool includeHotbar) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return InventoryActionCellPolicyCore.CanUseContainerActionSource(GetInventoryCellKind(inventory, pos), includeHotbar); } private static bool CanFavoriteCell(Inventory inventory, Vector2i pos) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return InventoryActionCellPolicyCore.CanFavoriteSlot(GetInventoryCellKind(inventory, pos)); } private static bool CanUseFavoriteRestockTargetCell(Inventory inventory, Vector2i pos) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return InventoryActionCellPolicyCore.CanUseFavoriteRestockTarget(GetInventoryCellKind(inventory, pos)); } private static bool CanTrashCell(Inventory inventory, Vector2i pos) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return InventoryActionCellPolicyCore.CanTrashSlot(GetInventoryCellKind(inventory, pos)); } private static InventoryCellKind GetInventoryCellKind(Inventory inventory, Vector2i pos) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (IsOutOfBounds(inventory, pos) || pos.y >= Math.Min(4, inventory.GetHeight())) { return InventoryCellKind.Outside; } if (pos.y != 0) { return InventoryCellKind.RegularUnlocked; } return InventoryCellKind.Hotbar; } private static bool IsRegularActionItem(Player player, Inventory inventory, ItemData item, bool includeHotbar) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) if (item?.m_shared != null) { return IsPlayerActionCell(inventory, item.m_gridPos, includeHotbar); } return false; } private static bool HasNoCustomData(ItemData item) { if (item.m_customData != null) { return item.m_customData.Count == 0; } return true; } private static bool CanUseContainerActionStacking(ItemData item) { if (item?.m_shared != null) { return HasNoCustomData(item); } return false; } private static string GetPlayerId(Player player) { Game instance = Game.instance; PlayerProfile val = ((instance != null) ? instance.GetPlayerProfile() : null); if (val == null) { return player.GetPlayerID().ToString(); } return val.GetPlayerID().ToString(); } private static string GetFavoriteFilePath(string playerId) { string text = new string(playerId.Where(delegate(char ch) { bool flag = char.IsLetterOrDigit(ch); if (!flag) { bool flag2 = ((ch == '-' || ch == '_') ? true : false); flag = flag2; } return flag; }).ToArray()); if (string.IsNullOrWhiteSpace(text)) { text = "unknown"; } return Path.Combine(Paths.ConfigPath, "InventoryActions.Favorites." + text + ".txt"); } private static string LocalizeUi(string token, string fallback) { if (Localization.instance == null || string.IsNullOrWhiteSpace(token)) { return fallback; } string text = Localization.instance.Localize(token); if (!string.IsNullOrWhiteSpace(text) && !string.Equals(text, token, StringComparison.Ordinal)) { return text; } return fallback; } private static string GetLocalizedItemName(ItemData item) { string text = item?.m_shared?.m_name ?? ""; if (Localization.instance == null) { return text; } return Localization.instance.Localize(text); } private static void ShowContainerActionResult(Player player, string actionToken, string actionFallback, int moved) { if (!((Object)(object)player == (Object)null)) { string newValue = LocalizeUi(actionToken, actionFallback); string text = LocalizeUi("$inventoryactions_action_result_format", "{action}: {count}").Replace("{action}", newValue).Replace("{count}", moved.ToString()); ((Character)player).Message((MessageType)2, text, 0, (Sprite)null); } } private static bool ShouldBlockGlobalHotkeys(Player? player = null) { if ((Object)(object)player != (Object)null && (player.m_isLoading || ((Character)player).InCutscene())) { return true; } if ((Object)(object)Chat.instance != (Object)null && !IsUnityNull((Object?)(object)Chat.instance) && Chat.instance.HasFocus()) { return true; } if (Console.IsVisible() || TextInput.IsVisible() || Menu.IsVisible() || Minimap.IsOpen() || Minimap.InTextInput() || StoreGui.IsVisible() || GameCamera.InFreeFly()) { return true; } if ((Object)(object)TextViewer.instance != (Object)null && !IsUnityNull((Object?)(object)TextViewer.instance) && TextViewer.instance.IsVisible()) { return true; } if ((Object)(object)ZNet.instance != (Object)null && !IsUnityNull((Object?)(object)ZNet.instance)) { return ZNet.instance.InPasswordDialog(); } return false; } private static bool IsShortcutHeldAllowingAltPair(KeyboardShortcut shortcut) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0 || !AreShortcutModifiersHeldAllowingAltPair(shortcut)) { return false; } return IsShortcutMainKeyHeldAllowingAltPair(shortcut); } private static bool AreShortcutModifiersHeldAllowingAltPair(KeyboardShortcut shortcut) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers) { if (!IsShortcutModifierHeldAllowingAltPair(modifier)) { return false; } } return true; } private static bool IsShortcutModifierHeldAllowingAltPair(KeyCode key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_002c: Unknown result type (might be due to invalid IL or missing references) if (key - 307 <= 1) { if (!Input.GetKey((KeyCode)308)) { return Input.GetKey((KeyCode)307); } return true; } return Input.GetKey(key); } private static bool IsShortcutMainKeyHeldAllowingAltPair(KeyboardShortcut shortcut) { //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_0008: 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_0010: Invalid comparison between Unknown and I4 //IL_0036: Unknown result type (might be due to invalid IL or missing references) KeyCode mainKey = ((KeyboardShortcut)(ref shortcut)).MainKey; if (mainKey - 307 <= 1) { if (!Input.GetKey((KeyCode)308)) { return Input.GetKey((KeyCode)307); } return true; } return Input.GetKey(((KeyboardShortcut)(ref shortcut)).MainKey); } private static string GetShortcutDisplayText(KeyboardShortcut shortcut) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0) { return ""; } IEnumerable values = from part in ((KeyboardShortcut)(ref shortcut)).Modifiers.Select(GetShortcutKeyDisplayText).Concat(new string[1] { GetShortcutKeyDisplayText(((KeyboardShortcut)(ref shortcut)).MainKey) }) where !string.IsNullOrWhiteSpace(part) select part; return string.Join("+", values); } private unsafe static string GetShortcutKeyDisplayText(KeyCode key) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Invalid comparison between Unknown and I4 //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Invalid comparison between Unknown and I4 //IL_0032: 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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected I4, but got Unknown //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Invalid comparison between Unknown and I4 //IL_0076: 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_009e: Expected I4, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Invalid comparison between Unknown and I4 string text = ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString(); if (text.StartsWith("Alpha", StringComparison.Ordinal)) { return text.Substring("Alpha".Length); } if ((int)key <= 27) { if ((int)key == 0) { return ""; } if ((int)key == 13) { return "Enter"; } if ((int)key == 27) { return "Esc"; } } else { if ((int)key == 32) { return "Spc"; } switch (key - 303) { case 4: case 5: return "Alt"; case 2: case 3: return "Ctrl"; case 0: case 1: return "Shift"; } switch (key - 323) { case 0: return "M1"; case 1: return "M2"; case 2: return "M3"; case 3: return "M4"; case 4: return "M5"; case 5: return "M6"; case 6: return "M7"; } } return text; } internal static bool HandleFavoriteClick(InventoryGrid grid, UIInputHandler clickHandler) { //IL_002c: 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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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_005b: Unknown result type (might be due to invalid IL or missing references) if (!ShouldHandleFavoriteClick(grid)) { return true; } Player localPlayer = Player.m_localPlayer; Inventory playerInventory = GetPlayerInventory(localPlayer); if (playerInventory == null || grid.m_inventory != playerInventory) { return true; } Vector2i buttonPos = grid.GetButtonPos(((Component)clickHandler).gameObject); if (buttonPos.x < 0 || buttonPos.y < 0 || IsOutOfBounds(playerInventory, buttonPos)) { return true; } if (!CanFavoriteCell(playerInventory, buttonPos)) { return true; } ToggleFavoriteSlot(localPlayer, buttonPos); return false; } private static bool ShouldHandleFavoriteClick(InventoryGrid grid) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)grid == (Object)null || (Object)(object)InventoryGui.instance == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null) { return false; } Player localPlayer = Player.m_localPlayer; if (localPlayer.m_isLoading || ((Character)localPlayer).IsTeleporting()) { return false; } if ((Object)(object)InventoryGui.instance.m_dragGo != (Object)null || (Object)(object)grid != (Object)(object)InventoryGui.instance.m_playerGrid) { return false; } if (_favoriteModifierKey != null) { return IsShortcutHeldAllowingAltPair(_favoriteModifierKey.Value); } return false; } private static void ToggleFavoriteSlot(Player player, Vector2i pos) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) EnsureFavoritesLoaded(player); if (!Runtime.FavoriteSlots.Add(pos)) { Runtime.FavoriteSlots.Remove(pos); } SaveFavorites(player); RefreshFavoriteBorders(); } private static bool IsFavoriteProtected(Player player, Inventory inventory, ItemData item) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (item?.m_shared != null && IsPlayerInventory(player, inventory)) { return IsFavoriteSlot(player, item.m_gridPos); } return false; } private static bool IsFavoriteSlot(Player player, Vector2i pos) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) EnsureFavoritesLoaded(player); return Runtime.FavoriteSlots.Contains(pos); } private static void EnsureFavoritesLoaded(Player player) { //IL_00d7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return; } string playerId = GetPlayerId(player); if (string.Equals(Runtime.LoadedFavoritesPlayerId, playerId, StringComparison.Ordinal)) { return; } Runtime.FavoriteSlots.Clear(); Runtime.LoadedFavoritesPlayerId = playerId; string favoriteFilePath = GetFavoriteFilePath(playerId); if (!File.Exists(favoriteFilePath)) { return; } try { string[] array = File.ReadAllLines(favoriteFilePath); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length != 0 && !text.StartsWith("#", StringComparison.Ordinal)) { string[] array2 = text.Split(new char[1] { ',' }); if (array2.Length == 2 && int.TryParse(array2[0].Trim(), out var result) && int.TryParse(array2[1].Trim(), out var result2) && result >= 0 && result2 >= 0) { Runtime.FavoriteSlots.Add(new Vector2i(result, result2)); } } } } catch (Exception ex) { Log.LogWarning((object)("Failed to load InventoryActions favorites from " + favoriteFilePath + ": " + ex.Message)); } } private static void SaveFavorites(Player player) { if ((Object)(object)player == (Object)null) { return; } string playerId = GetPlayerId(player); Runtime.LoadedFavoritesPlayerId = playerId; string favoriteFilePath = GetFavoriteFilePath(playerId); try { string[] contents = (from slot in Runtime.FavoriteSlots orderby slot.y, slot.x select $"{slot.x},{slot.y}").ToArray(); File.WriteAllLines(favoriteFilePath, contents); } catch (Exception ex) { Log.LogWarning((object)("Failed to save InventoryActions favorites to " + favoriteFilePath + ": " + ex.Message)); } } private static void RefreshFavoriteBorders() { InventoryGui instance = InventoryGui.instance; if (!((Object)(object)instance?.m_playerGrid == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null)) { UpdateFavoriteBorders(instance.m_playerGrid, Player.m_localPlayer); } } private static void UpdateFavoriteBorders(InventoryGrid grid, Player player) { //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) Inventory playerInventory = GetPlayerInventory(player); if (grid?.m_elements == null || playerInventory == null || grid.m_inventory != playerInventory) { return; } EnsureFavoritesLoaded(player); foreach (Element element in grid.m_elements) { if ((Object)(object)element?.m_go == (Object)null || IsUnityNull((Object?)(object)element.m_go)) { continue; } if (!element.m_go.activeSelf) { SetFavoriteBorderActive(element, active: false); continue; } Vector2i buttonPos = grid.GetButtonPos(element.m_go); if (IsOutOfBounds(playerInventory, buttonPos) || !Runtime.FavoriteSlots.Contains(buttonPos)) { SetFavoriteBorderActive(element, active: false); continue; } RectTransform val = EnsureFavoriteBorder(element); if (!((Object)(object)val == (Object)null)) { InventoryGridElementMarker inventoryGridElementMarker = element.m_go.GetComponent() ?? element.m_go.AddComponent(); if (inventoryGridElementMarker.FavoriteBorderImages.Length == 0) { inventoryGridElementMarker.FavoriteBorderImages = ((Component)val).GetComponentsInChildren(true); } Image[] favoriteBorderImages = inventoryGridElementMarker.FavoriteBorderImages; for (int i = 0; i < favoriteBorderImages.Length; i++) { ((Graphic)favoriteBorderImages[i]).color = GetFavoriteBorderColor(); } ((Component)val).gameObject.SetActive(true); ((Transform)val).SetAsLastSibling(); } } } private static Color GetFavoriteBorderColor() { //IL_0012: 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) if (_favoriteBorderColor == null) { return FavoriteBorderDefaultColor; } return _favoriteBorderColor.Value; } private static RectTransform? EnsureFavoriteBorder(Element element) { //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_020a: 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_0220: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Expected O, but got Unknown //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_010b: 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_012a: 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_0148: 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_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)element?.m_go == (Object)null || IsUnityNull((Object?)(object)element.m_go)) { return null; } GameObject go = element.m_go; InventoryGridElementMarker inventoryGridElementMarker = go.GetComponent() ?? go.AddComponent(); RectTransform val = (((Object)(object)inventoryGridElementMarker.FavoriteBorder != (Object)null && !IsUnityNull((Object?)(object)inventoryGridElementMarker.FavoriteBorder)) ? inventoryGridElementMarker.FavoriteBorder : null); if ((Object)(object)val == (Object)null) { Transform val2 = go.transform.Find("InventoryActions_FavoriteBorder"); val = (((Object)(object)val2 != (Object)null) ? ((Component)val2).GetComponent() : null); } if ((Object)(object)val == (Object)null) { val = (RectTransform)new GameObject("InventoryActions_FavoriteBorder", new Type[1] { typeof(RectTransform) }).transform; ((Transform)val).SetParent(go.transform, false); CreateFavoriteBorderSide(val, "Top", new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, 2f), Vector2.zero); CreateFavoriteBorderSide(val, "Bottom", new Vector2(0f, 0f), new Vector2(1f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 2f), Vector2.zero); CreateFavoriteBorderSide(val, "Left", new Vector2(0f, 0f), new Vector2(0f, 1f), new Vector2(0f, 0.5f), new Vector2(2f, 0f), Vector2.zero); CreateFavoriteBorderSide(val, "Right", new Vector2(1f, 0f), new Vector2(1f, 1f), new Vector2(1f, 0.5f), new Vector2(2f, 0f), Vector2.zero); } val.anchorMin = Vector2.zero; val.anchorMax = Vector2.one; val.offsetMin = Vector2.zero; val.offsetMax = Vector2.zero; ((Transform)val).localScale = Vector3.one; ((Transform)val).localRotation = Quaternion.identity; inventoryGridElementMarker.FavoriteBorder = val; if (inventoryGridElementMarker.FavoriteBorderImages.Length == 0) { inventoryGridElementMarker.FavoriteBorderImages = ((Component)val).GetComponentsInChildren(true); } return val; } private static void CreateFavoriteBorderSide(RectTransform parent, string name, Vector2 anchorMin, Vector2 anchorMax, Vector2 pivot, Vector2 sizeDelta, Vector2 anchoredPosition) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: 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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: 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_0047: 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_004f: 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_0057: 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_005f: 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_006a: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[2] { typeof(RectTransform), typeof(Image) }); RectTransform val2 = (RectTransform)val.transform; ((Transform)val2).SetParent((Transform)(object)parent, false); val2.anchorMin = anchorMin; val2.anchorMax = anchorMax; val2.pivot = pivot; val2.sizeDelta = sizeDelta; val2.anchoredPosition = anchoredPosition; ((Transform)val2).localScale = Vector3.one; ((Transform)val2).localRotation = Quaternion.identity; ((Graphic)val.GetComponent()).raycastTarget = false; } private static void SetFavoriteBorderActive(Element element, bool active) { if (!((Object)(object)element?.m_go == (Object)null) && !IsUnityNull((Object?)(object)element.m_go)) { InventoryGridElementMarker component = element.m_go.GetComponent(); Transform val = (Transform)(((Object)(object)component?.FavoriteBorder != (Object)null && !IsUnityNull((Object?)(object)component.FavoriteBorder)) ? ((object)component.FavoriteBorder) : ((object)element.m_go.transform.Find("InventoryActions_FavoriteBorder"))); if ((Object)(object)val != (Object)null && ((Component)val).gameObject.activeSelf != active) { ((Component)val).gameObject.SetActive(active); } } } private void Awake() { _instance = this; Localizer.OnLocalizationComplete += HandleLocalizationComplete; Localizer.Load((BaseUnityPlugin)(object)this); BindConfigs(); _harmony.PatchAll(); Log.LogInfo((object)"InventoryActions loaded."); } private void Update() { if (!IsDedicatedServer) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || IsUnityNull((Object?)(object)localPlayer) || localPlayer.m_isLoading) { CancelAreaContainerTransfer(); ResetContainerHold(Runtime.AreaQuickStackHold); ResetContainerHold(Runtime.AreaRestockHold); } else { UpdateAreaContainerTransfer(localPlayer); HandleHoverActions(localPlayer); } } } private void OnDestroy() { Localizer.OnLocalizationComplete -= HandleLocalizationComplete; CancelAreaContainerTransfer(); ((BaseUnityPlugin)this).Config.Save(); } private static void HandleLocalizationComplete() { Runtime.UiLocalizationVersion++; } private static void DrawRestockTargetStackLimitsConfig(ConfigEntryBase entry) { string text = (entry.BoxedValue as string) ?? ""; if (!string.Equals(text, _restockTargetLimitEditorLastValue, StringComparison.Ordinal)) { RestockTargetLimitEditorRows.Clear(); RestockTargetLimitEditorRows.AddRange(ParseRestockTargetLimitEditorRows(text)); _restockTargetLimitEditorLastValue = text; } GUILayout.BeginVertical(Array.Empty()); for (int i = 0; i < RestockTargetLimitEditorRows.Count; i++) { RestockTargetLimitEditorRow restockTargetLimitEditorRow = RestockTargetLimitEditorRows[i]; GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label("Item", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(44f) }); string text2 = GUILayout.TextField(restockTargetLimitEditorRow.Item, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MinWidth(130f) }); GUILayout.Label("Max", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(28f) }); string text3 = FilterUnsignedIntText(GUILayout.TextField(restockTargetLimitEditorRow.Amount, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(58f) })); bool num = GUILayout.Button("-", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(24f) }); GUILayout.EndHorizontal(); if (num) { RestockTargetLimitEditorRows.RemoveAt(i--); UpdateRestockTargetStackLimitsConfigEntry(entry); } else if (!string.Equals(text2, restockTargetLimitEditorRow.Item, StringComparison.Ordinal) || !string.Equals(text3, restockTargetLimitEditorRow.Amount, StringComparison.Ordinal)) { restockTargetLimitEditorRow.Item = text2; restockTargetLimitEditorRow.Amount = text3; UpdateRestockTargetStackLimitsConfigEntry(entry); } } GUILayout.BeginHorizontal(Array.Empty()); if (GUILayout.Button("+", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(24f) })) { RestockTargetLimitEditorRows.Add(new RestockTargetLimitEditorRow("", "")); UpdateRestockTargetStackLimitsConfigEntry(entry); } GUILayout.Label("Add restock limit", Array.Empty()); GUILayout.EndHorizontal(); GUILayout.EndVertical(); } private static List ParseRestockTargetLimitEditorRows(string raw) { List list = new List(); string[] array = raw.Replace("\r", "\n").Split(new char[3] { '\n', ',', ';' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length == 0) { continue; } int num = text.IndexOf('#'); if (num >= 0) { text = text.Substring(0, num).Trim(); } if (text.Length != 0) { int num2 = FindRestockTargetLimitEditorSeparator(text); if (num2 <= 0) { list.Add(new RestockTargetLimitEditorRow(text, "")); } else { list.Add(new RestockTargetLimitEditorRow(text.Substring(0, num2).Trim(), FilterUnsignedIntText(text.Substring(num2 + 1).Trim()))); } } } return list; } private static int FindRestockTargetLimitEditorSeparator(string entry) { int num = entry.IndexOf(':'); int num2 = entry.IndexOf('='); if (num < 0) { return num2; } if (num2 < 0) { return num; } return Math.Min(num, num2); } private static string FilterUnsignedIntText(string value) { if (!string.IsNullOrWhiteSpace(value)) { return new string(value.Where(char.IsDigit).ToArray()); } return ""; } private static void UpdateRestockTargetStackLimitsConfigEntry(ConfigEntryBase entry) { string text = (_restockTargetLimitEditorLastValue = SerializeRestockTargetLimitEditorRows()); if (!string.Equals((entry.BoxedValue as string) ?? "", text, StringComparison.Ordinal)) { entry.BoxedValue = text; } } private static string SerializeRestockTargetLimitEditorRows() { return string.Join("\n", from row in RestockTargetLimitEditorRows where !string.IsNullOrWhiteSpace(row.Item) || !string.IsNullOrWhiteSpace(row.Amount) select row.Item.Trim() + ": " + row.Amount.Trim()); } internal static void UpdateInventoryActionsUi(InventoryGui gui) { if ((Object)(object)gui == (Object)null || !InventoryGui.IsVisible()) { HideInventoryActionPanels(); return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || localPlayer.m_isLoading || (Object)(object)gui.m_playerGrid == (Object)null) { HideInventoryActionPanels(); return; } UpdateContainerActionButtons(gui); UpdatePlayerActionPanel(gui, gui.m_playerGrid, localPlayer); UpdateTrashPanel(gui, gui.m_playerGrid, localPlayer); UpdateFavoriteBorders(gui.m_playerGrid, localPlayer); } internal static void HideInventoryActionPanels() { SetActionPanelActive(Runtime.PlayerActionPanel, active: false); SetActionPanelActive(Runtime.TrashPanel, active: false); ReleaseContainerActionButtonLayout(); SetButtonActive(Runtime.ContainerStoreAllButton, active: false); SetButtonActive(Runtime.ContainerRestockButton, active: false); SetButtonActive(Runtime.ContainerSortButton, active: false); CloseInventoryTrashConfirmDialog(); } private static void UpdateContainerActionButtons(InventoryGui gui) { //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Expected O, but got Unknown //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Expected O, but got Unknown if ((Object)(object)gui.m_currentContainer == (Object)null || (Object)(object)gui.m_takeAllButton == (Object)null || (Object)(object)gui.m_stackAllButton == (Object)null) { RestoreContainerActionButtonLayout(); HideContainerActionButtons(); return; } Container currentContainer = gui.m_currentContainer; Transform transform = ((Component)gui.m_takeAllButton).transform; RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null); Transform transform2 = ((Component)gui.m_stackAllButton).transform; RectTransform val2 = (RectTransform)(object)((transform2 is RectTransform) ? transform2 : null); Transform obj = ((val != null) ? ((Transform)val).parent : null); RectTransform val3 = (RectTransform)(object)((obj is RectTransform) ? obj : null); Transform obj2 = ((val2 != null) ? ((Transform)val2).parent : null); RectTransform val4 = (RectTransform)(object)((obj2 is RectTransform) ? obj2 : null); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null || (Object)(object)val4 == (Object)null) { RestoreContainerActionButtonLayout(); HideContainerActionButtons(); return; } CaptureRectTransformSnapshot(ref Runtime.TakeAllButtonOriginal, val); CaptureRectTransformSnapshot(ref Runtime.StackAllButtonOriginal, val2); RestoreContainerActionButtonLayout(); SetActionButtonLabel(gui.m_takeAllButton, LocalizeUi("$inventoryactions_button_take_all", "Take all")); SetActionButtonLabel(gui.m_stackAllButton, LocalizeUi("$inventoryactions_button_place_stacks", "Place stacks")); if (!CanMutateContainerDirectly(currentContainer, allowLocalWithoutZNetView: true)) { HideContainerActionButtons(); return; } AlignContainerActionButtonRows(val, val2); float buttonHeight = Mathf.Clamp(Mathf.Max(GetRectHeight(val), GetRectHeight(val2)), 24f, 36f); float rectWidth = GetRectWidth(val); float rectWidth2 = GetRectWidth(val2); InventoryActionRuntimeState runtime = Runtime; Button takeAllButton = gui.m_takeAllButton; string label = LocalizeUi("$inventoryactions_button_place_all", "Place all"); object obj3 = <>c.<>9__241_0; if (obj3 == null) { UnityAction val5 = delegate { StoreAllToCurrentContainer(Player.m_localPlayer); }; <>c.<>9__241_0 = val5; obj3 = (object)val5; } runtime.ContainerStoreAllButton = EnsureActionButton(val3, takeAllButton, "InventoryActions_StoreAllButton", label, (UnityAction)obj3); LayoutButtonPair(val, Runtime.ContainerStoreAllButton, rectWidth, buttonHeight, 4f, addedButtonOnRight: true); SetTooltip(Runtime.ContainerStoreAllButton, LocalizeUi("$inventoryactions_button_place_all", "Place all"), "Move all non-favorited regular inventory items into the current container."); InventoryActionRuntimeState runtime2 = Runtime; Button stackAllButton = gui.m_stackAllButton; string label2 = LocalizeUi("$inventoryactions_button_take_stacks", "Take stacks"); object obj4 = <>c.<>9__241_1; if (obj4 == null) { UnityAction val6 = delegate { RestockFromCurrentContainer(Player.m_localPlayer); }; <>c.<>9__241_1 = val6; obj4 = (object)val6; } runtime2.ContainerRestockButton = EnsureActionButton(val4, stackAllButton, "InventoryActions_RestockButton", label2, (UnityAction)obj4); LayoutButtonPair(val2, Runtime.ContainerRestockButton, rectWidth2, buttonHeight, 4f, addedButtonOnRight: false); SetTooltip(Runtime.ContainerRestockButton, LocalizeUi("$inventoryactions_button_take_stacks", "Take stacks"), "Fill matching non-favorited partial stacks from the current container."); Runtime.ContainerSortButton = EnsureContainerSortButton(val2, gui.m_takeAllButton, buttonHeight); SetTooltip(Runtime.ContainerSortButton, LocalizeUi("$inventoryactions_action_sort", "Sort"), "Sort the current container."); SetButtonActive(Runtime.ContainerStoreAllButton, active: true); SetButtonActive(Runtime.ContainerRestockButton, active: true); SetButtonActive(Runtime.ContainerSortButton, active: true); SetButtonInteractable(Runtime.ContainerStoreAllButton, interactable: true); SetButtonInteractable(Runtime.ContainerRestockButton, interactable: true); SetButtonInteractable(Runtime.ContainerSortButton, interactable: true); } private static void AlignContainerActionButtonRows(RectTransform takeAllRect, RectTransform stackAllRect) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0053: 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_0069: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)takeAllRect == (Object)null) && !((Object)(object)stackAllRect == (Object)null)) { float num = Mathf.Max(((Transform)takeAllRect).localPosition.y, ((Transform)stackAllRect).localPosition.y); ((Transform)takeAllRect).localPosition = new Vector3(((Transform)takeAllRect).localPosition.x, num, ((Transform)takeAllRect).localPosition.z); ((Transform)stackAllRect).localPosition = new Vector3(((Transform)stackAllRect).localPosition.x, num, ((Transform)stackAllRect).localPosition.z); } } private static void UpdatePlayerActionPanel(InventoryGui gui, InventoryGrid playerGrid, Player player) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0092: 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_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: 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) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Expected O, but got Unknown if ((Object)(object)playerGrid.m_gridRoot == (Object)null || (Object)(object)gui.m_takeAllButton == (Object)null) { SetActionPanelActive(Runtime.PlayerActionPanel, active: false); return; } Runtime.PlayerActionPanel = EnsureActionPanel(playerGrid.m_gridRoot, "InventoryActions_PlayerActionPanel", Runtime.PlayerActionPanel); if ((Object)(object)Runtime.PlayerActionPanel == (Object)null) { return; } float containerSortButtonSize = GetContainerSortButtonSize(gui); int displayedPlayerRows = GetDisplayedPlayerRows(playerGrid); Runtime.PlayerActionPanel.sizeDelta = new Vector2(containerSortButtonSize, containerSortButtonSize); ((Transform)Runtime.PlayerActionPanel).localScale = Vector3.one; ((Transform)Runtime.PlayerActionPanel).localRotation = Quaternion.identity; Vector3 localPosition = GetInventorySortPanelPosition(playerGrid, containerSortButtonSize, displayedPlayerRows) + Vector2.op_Implicit(GetSortButtonPositionOffset()); ((Transform)Runtime.PlayerActionPanel).localPosition = localPosition; DisableActionPanelChildren(Runtime.PlayerActionPanel); RectTransform? playerActionPanel = Runtime.PlayerActionPanel; Button takeAllButton = gui.m_takeAllButton; object obj = <>c.<>9__243_0; if (obj == null) { UnityAction val = delegate { SortPlayerInventory(Player.m_localPlayer); }; <>c.<>9__243_0 = val; obj = (object)val; } Button? button = EnsureActionButton(playerActionPanel, takeAllButton, "InventoryActions_PlayerSortButton", "S", (UnityAction)obj); LayoutActionButton(button, 0, containerSortButtonSize, containerSortButtonSize, 6f); SetTooltip(button, "Sort inventory", "Sort non-favorited player inventory slots outside the hotbar."); SetActionPanelActive(Runtime.PlayerActionPanel, active: true); } private static void UpdateTrashPanel(InventoryGui gui, InventoryGrid playerGrid, Player player) { //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: 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) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_014f: 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_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Expected O, but got Unknown if (!_enableInventoryTrashPanel.Value.IsOn() || (Object)(object)gui == (Object)null || (Object)(object)playerGrid == (Object)null || (Object)(object)playerGrid.m_gridRoot == (Object)null || (Object)(object)gui.m_takeAllButton == (Object)null || !InventoryGui.IsVisible()) { SetActionPanelActive(Runtime.TrashPanel, active: false); return; } Runtime.TrashPanel = EnsureActionPanel(playerGrid.m_gridRoot, "InventoryActions_TrashPanel", Runtime.TrashPanel); if (!((Object)(object)Runtime.TrashPanel == (Object)null)) { float num = Mathf.Max(1f, playerGrid.m_elementSpace); float num2 = Mathf.Clamp(num * 0.72f, 42f, 58f); Runtime.TrashPanel.sizeDelta = new Vector2(num2, num2); ((Transform)Runtime.TrashPanel).localScale = Vector3.one; ((Transform)Runtime.TrashPanel).localRotation = Quaternion.identity; int displayedPlayerRows = GetDisplayedPlayerRows(playerGrid); float containerSortButtonSize = GetContainerSortButtonSize(gui); Vector3 inventorySortPanelPosition = GetInventorySortPanelPosition(playerGrid, containerSortButtonSize, displayedPlayerRows); Vector3 gridOrigin = GetGridOrigin(playerGrid); ((Transform)Runtime.TrashPanel).localPosition = gridOrigin + new Vector3(inventorySortPanelPosition.x - gridOrigin.x + (containerSortButtonSize - num2) * 0.5f, (float)(-Mathf.Max(1, displayedPlayerRows)) * num - 8f, 0f) + Vector2.op_Implicit(GetTrashButtonPositionOffset()); DisableActionPanelChildren(Runtime.TrashPanel); RectTransform? trashPanel = Runtime.TrashPanel; Button takeAllButton = gui.m_takeAllButton; object obj = <>O.<9>__TryClickInventoryTrashPanel; if (obj == null) { UnityAction val = TryClickInventoryTrashPanel; <>O.<9>__TryClickInventoryTrashPanel = val; obj = (object)val; } Button val2 = EnsureActionButton(trashPanel, takeAllButton, "InventoryActions_TrashButton", "", (UnityAction)obj); RectTransform val3 = LayoutActionButton(val2, 0, num2, num2, 0f); if ((Object)(object)val2 != (Object)null && (Object)(object)val3 != (Object)null) { ConfigureInventoryTrashButton(val2, num2); bool canTrash = CanStartInventoryTrash(gui, player, showMessage: false); SetButtonInteractable(val2, HasHeldTrashCandidate(gui)); SetInventoryTrashButtonVisual(val2, canTrash); } SetActionPanelActive(Runtime.TrashPanel, active: true); if ((Object)(object)((Transform)Runtime.TrashPanel).parent != (Object)null && ((Transform)Runtime.TrashPanel).GetSiblingIndex() != ((Transform)Runtime.TrashPanel).parent.childCount - 1) { ((Transform)Runtime.TrashPanel).SetAsLastSibling(); } } } private static Vector3 GetGridOrigin(InventoryGrid grid) { //IL_0009: 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) //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_0068: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)grid == (Object)null) { return Vector3.zero; } Transform transform = ((Component)grid).transform; RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null); if (val != null) { float num = ((grid.m_inventory != null) ? grid.m_inventory.GetWidth() : grid.m_width); Rect rect = val.rect; return new Vector3(((Rect)(ref rect)).width / 2f - num * grid.m_elementSpace / 2f, 0f, 0f); } return new Vector3((float)(-(((grid.m_inventory != null) ? grid.m_inventory.GetWidth() : 8) - 1)) * grid.m_elementSpace * 0.5f, 0f, 0f); } private static int GetDisplayedPlayerRows(InventoryGrid playerGrid) { return Mathf.Max(1, Math.Min(4, (playerGrid.m_inventory != null) ? playerGrid.m_inventory.GetHeight() : 4)); } private static int GetInventoryGridWidth(InventoryGrid playerGrid) { return Mathf.Max(1, (playerGrid.m_inventory != null) ? playerGrid.m_inventory.GetWidth() : 8); } private static Vector3 GetInventorySortPanelPosition(InventoryGrid playerGrid, float buttonSize, int rows) { //IL_0012: 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_003d: 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) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Max(1f, playerGrid.m_elementSpace); return GetGridOrigin(playerGrid) + new Vector3((float)GetInventoryGridWidth(playerGrid) * num + 1f, (float)(-Mathf.Max(1, rows)) * num + buttonSize, 0f) + Vector2.op_Implicit(InventorySortButtonFixedOffset); } private static void LayoutButtonPair(RectTransform vanillaButton, Button? addedButton, float originalWidth, float buttonHeight, float gap, bool addedButtonOnRight) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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_0065: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)vanillaButton == (Object)null) && !((Object)(object)addedButton == (Object)null)) { RectTransform val = (RectTransform)((Component)addedButton).transform; CopyRectTransformFrame(vanillaButton, val); float num = Mathf.Max(1f, (originalWidth - gap) * 0.5f); float num2 = (num + gap) * 0.5f; Vector3 localPosition = ((Transform)vanillaButton).localPosition; Vector3 localPosition2 = localPosition + new Vector3(addedButtonOnRight ? (0f - num2) : num2, 0f, 0f); Vector3 localPosition3 = localPosition + new Vector3(addedButtonOnRight ? num2 : (0f - num2), 0f, 0f); LayoutButtonRect(vanillaButton, num, buttonHeight, localPosition2); LayoutButtonRect(val, num, buttonHeight, localPosition3); } } private static Button? EnsureContainerSortButton(RectTransform stackButton, Button template, float buttonHeight) { //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_005c: Expected O, but got Unknown //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown //IL_009a: 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_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) Transform obj = ((stackButton != null) ? ((Transform)stackButton).parent : null); RectTransform val = (RectTransform)(((object)((obj is RectTransform) ? obj : null)) ?? ((object)/*isinst with value type is only supported in some contexts*/)); if ((Object)(object)val == (Object)null) { return null; } object obj2 = <>c.<>9__250_0; if (obj2 == null) { UnityAction val2 = delegate { SortCurrentContainer(Player.m_localPlayer); }; <>c.<>9__250_0 = val2; obj2 = (object)val2; } Button val3 = EnsureActionButton(val, template, "InventoryActions_ContainerSortButton", "S", (UnityAction)obj2); if ((Object)(object)val3 == (Object)null) { return null; } RectTransform val4 = (RectTransform)((Component)val3).transform; RectTransform val5 = (RectTransform)(((object)stackButton) ?? ((object)(RectTransform)((Component)template).transform)); CopyRectTransformFrame(val5, val4); LayoutButtonRect(val4, buttonHeight, buttonHeight, ((Transform)val5).localPosition + new Vector3(GetRectWidth(val5) * 0.5f + 1f + buttonHeight * 0.5f, 0f, 0f)); return val3; } private static void LayoutButtonRect(RectTransform rect, float width, float height, Vector3 localPosition) { //IL_0003: 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_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) rect.sizeDelta = new Vector2(width, height); ((Transform)rect).localPosition = localPosition; ((Transform)rect).localScale = Vector3.one; ((Transform)rect).localRotation = Quaternion.identity; } private static RectTransform? LayoutActionButton(Button? button, int index, float buttonWidth, float buttonHeight, float gap) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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_0040: 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_0055: 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_006f: 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_007a: 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_0085: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Expected O, but got Unknown if ((Object)(object)button == (Object)null) { return null; } RectTransform val = (RectTransform)((Component)button).transform; val.anchorMin = new Vector2(0f, 1f); val.anchorMax = new Vector2(0f, 1f); val.pivot = new Vector2(0f, 1f); val.sizeDelta = new Vector2(buttonWidth, buttonHeight); val.anchoredPosition = new Vector2((float)index * (buttonWidth + gap), 0f); ((Transform)val).localScale = Vector3.one; ((Transform)val).localRotation = Quaternion.identity; ((Component)button).gameObject.SetActive(true); return val; } private static Button? EnsureActionButton(RectTransform panel, Button template, string name, string label, UnityAction action) { Transform val = ((Transform)panel).Find(name); Button val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent