Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of InventoryActions v1.0.5
InventoryActions.dll
Decompiled 5 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.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<Container> 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<ConfigEntryBase>? 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<Player, Container?> <0>__TryGetHoverQuickStackContext; public static Func<Player, Container, bool> <1>__TryQuickStackFromHoveredContainer; public static Func<Player, Container?> <2>__TryGetHoverRestockContext; public static Func<Player, Container, bool> <3>__TryRestockFromHoveredContainer; public static Action<ConfigEntryBase> <4>__DrawButtonPositionOffsetConfig; public static Action<ConfigEntryBase> <5>__DrawRestockTargetStackLimitsConfig; public static Func<KeyCode, string> <6>__GetShortcutKeyDisplayText; public static Action <7>__HandleLocalizationComplete; public static Func<char, bool> <8>__IsDigit; public static UnityAction <9>__TryClickInventoryTrashPanel; } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static Func<ItemData, bool> <>9__5_0; public static Func<ItemData, int> <>9__5_1; public static Func<ItemData, int> <>9__5_2; public static Comparison<ItemData> <>9__7_1; public static Func<ItemData, bool> <>9__9_0; public static Func<ItemData, string> <>9__9_1; public static Comparison<ItemData> <>9__10_1; public static Comparison<ItemData> <>9__14_1; public static Func<ItemData, bool> <>9__23_0; public static Func<ItemData, ItemData> <>9__25_0; public static Func<ItemData, bool> <>9__26_0; public static Func<ItemData, <>f__AnonymousType0<string, int, int>> <>9__26_1; public static Func<IGrouping<<>f__AnonymousType0<string, int, int>, ItemData>, List<ItemData>> <>9__26_2; public static Func<ItemData, int> <>9__26_3; public static Func<Container, bool> <>9__44_0; public static Comparison<(Container Container, float DistanceSq)> <>9__48_0; public static Func<MonoBehaviour, bool> <>9__53_0; public static Func<ItemData, int> <>9__61_1; public static Func<ItemData, int> <>9__61_2; public static Comparison<ItemData> <>9__94_3; public static Comparison<ItemData> <>9__94_1; public static EventHandler <>9__139_0; public static EventHandler <>9__139_1; public static Func<char, bool> <>9__149_0; public static Func<char, bool> <>9__166_0; public static Func<string, bool> <>9__175_0; public static Func<Vector2i, int> <>9__183_0; public static Func<Vector2i, int> <>9__183_1; public static Func<Vector2i, string> <>9__183_2; public static Func<RestockTargetLimitEditorRow, bool> <>9__229_0; public static Func<RestockTargetLimitEditorRow, string> <>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 <SafeTakeAllItems>b__5_0(ItemData item) { return item?.m_shared != null; } internal int <SafeTakeAllItems>b__5_1(ItemData item) { return item.m_gridPos.y; } internal int <SafeTakeAllItems>b__5_2(ItemData item) { return item.m_gridPos.x; } internal int <QuickStackIntoContainers>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 <QuickStackItemsIntoContainer>b__9_0(ItemData item) { return item?.m_shared != null; } internal string <QuickStackItemsIntoContainer>b__9_1(ItemData item) { return item.m_shared.m_name; } internal int <StoreAllToCurrentContainer>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 <RestockFromContainer>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 <SortContainerInventory>b__23_0(ItemData item) { return item?.m_shared != null; } internal ItemData <SortInventoryInternal>b__25_0(ItemData item) { return item; } internal bool <MergeSortableStacks>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<string, int, int> <MergeSortableStacks>b__26_1(ItemData item) { return new { item.m_shared.m_name, item.m_quality, item.m_worldLevel }; } internal List<ItemData> <MergeSortableStacks>b__26_2(IGrouping<<>f__AnonymousType0<string, int, int>, ItemData> grouping) { return grouping.ToList(); } internal int <MergeSortableStacks>b__26_3(ItemData item) { return item.m_stack; } internal bool <RunCurrentContainerTransfer>b__44_0(Container target) { if (!IsUnityNull((Object?)(object)target)) { return target.m_inventory != null; } return false; } internal int <GetActionContainers>b__48_0((Container Container, float DistanceSq) left, (Container Container, float DistanceSq) right) { return left.DistanceSq.CompareTo(right.DistanceSq); } internal bool <IsExternalMultiUserChestTransferContainer>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 <MoveItemToInventoryTopFirst>b__61_1(ItemData target) { return target.m_gridPos.y; } internal int <MoveItemToInventoryTopFirst>b__61_2(ItemData target) { return target.m_gridPos.x; } internal int <ExecuteAreaContainerTransfer>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 <ExecuteAreaContainerTransfer>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 <BindConfigs>b__139_0(object _, EventArgs _) { RefreshFavoriteBorders(); } internal void <BindConfigs>b__139_1(object _, EventArgs _) { RefreshRestockTargetStackLimits(); } internal bool <FilterSignedFloatText>b__149_0(char c) { if (!char.IsDigit(c) && c != '-' && c != '+') { return c == '.'; } return true; } internal bool <GetFavoriteFilePath>b__166_0(char ch) { bool flag = char.IsLetterOrDigit(ch); if (!flag) { bool flag2 = ((ch == '-' || ch == '_') ? true : false); flag = flag2; } return flag; } internal bool <GetShortcutDisplayText>b__175_0(string part) { return !string.IsNullOrWhiteSpace(part); } internal int <SaveFavorites>b__183_0(Vector2i slot) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return slot.y; } internal int <SaveFavorites>b__183_1(Vector2i slot) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return slot.x; } internal string <SaveFavorites>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 <SerializeRestockTargetLimitEditorRows>b__229_0(RestockTargetLimitEditorRow row) { if (string.IsNullOrWhiteSpace(row.Item)) { return !string.IsNullOrWhiteSpace(row.Amount); } return true; } internal string <SerializeRestockTargetLimitEditorRows>b__229_1(RestockTargetLimitEditorRow row) { return row.Item.Trim() + ": " + row.Amount.Trim(); } internal void <UpdateContainerActionButtons>b__241_0() { StoreAllToCurrentContainer(Player.m_localPlayer); } internal void <UpdateContainerActionButtons>b__241_1() { RestockFromCurrentContainer(Player.m_localPlayer); } internal void <UpdatePlayerActionPanel>b__243_0() { SortPlayerInventory(Player.m_localPlayer); } internal void <EnsureContainerSortButton>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<Toggle> _serverConfigLocked = null; private static ConfigEntry<Toggle> _enableInventoryTrashPanel = null; private static ConfigEntry<float> _areaQuickStackRange = null; private static ConfigEntry<float> _areaRestockRange = null; private static ConfigEntry<Color> _favoriteBorderColor = null; private static ConfigEntry<Toggle> _containerActionSuccessFx = null; private static ConfigEntry<KeyboardShortcut> _favoriteModifierKey = null; private static ConfigEntry<KeyboardShortcut> _containerRestockKey = null; private static ConfigEntry<string> _sortButtonPositionOffset = null; private static ConfigEntry<string> _trashButtonPositionOffset = null; private static ConfigEntry<string> _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<string, ButtonPositionOffsetEditorState> ButtonPositionOffsetEditorStates = new Dictionary<string, ButtonPositionOffsetEditorState>(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<RestockTargetLimitEditorRow> RestockTargetLimitEditorRows = new List<RestockTargetLimitEditorRow>(); 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<TombStone>(); 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<Vector2i> allowedSlots = new HashSet<Vector2i>(GetPlayerActionSlots(player, playerInventory, includeHotbar: false, blockFavorites: true)); List<ItemData> 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<ItemData> 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<ItemData> candidates) { if (containerInventory == null || candidates.Count == 0) { return 0; } HashSet<string> hashSet = new HashSet<string>(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<ItemData> 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<ItemData> 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<string?> 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<ItemData> 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<Vector2i> 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<Vector2i> playerActionSlots = GetPlayerActionSlots(player, inventory, includeHotbar: false, blockFavorites: true); HashSet<Vector2i> allowedSet = new HashSet<Vector2i>(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<Vector2i> allowedSlots, Func<ItemData, bool> 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<ItemData> 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<ItemData, int> 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<ItemData> toMerge, Inventory inventory) { bool result = false; foreach (List<ItemData> 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<ItemType, ItemType>(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<Vector2i> 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<Vector2i> list = new List<Vector2i>(); 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<Vector2i> GetAllInventorySlots(Inventory inventory) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) List<Vector2i> list = new List<Vector2i>(); 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<Player, Container?> getContext, Func<Player, Container, bool> 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<Container>(); } 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[<color=yellow><b>" + containerRestockKeyDisplayText + "</b></color>] (" + 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<Container, int> transfer, Action onMoved) { if ((Object)(object)container == (Object)null || transfer == null) { return 0; } return ContainerTransferCore.Run((IEnumerable<Container?>?)(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<Container> 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<Container> list = new List<Container>(); HashSet<Container> hashSet = new HashSet<Container>(); 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<TombStone>() != (Object)null || (Object)(object)((Component)container).GetComponentInParent<TombStone>() != (Object)null || (Object)(object)((Component)container.m_nview).GetComponent<Player>() != (Object)null || (Object)(object)((Component)((Component)container).transform.root).GetComponentInChildren<Ship>() != (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<TombStone>() != (Object)null || (Object)(object)((Component)container).GetComponentInParent<TombStone>() != (Object)null || (Object)(object)((Component)container.m_nview).GetComponent<Player>() != (Object)null || (Object)(object)((Component)((Component)container).transform.root).GetComponentInChildren<Ship>() != (Object)null) { return false; } return !((Component)((Component)container).transform.root).GetComponentsInChildren<MonoBehaviour>(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<GameObject>(prefab, ((Component)container).transform.position, ((Component)container).transform.rotation); } finally { ZNetView.m_forceDisableInit = forceDisableInit; } Object.Destroy((Object)(object)val, 5f); ZSFX[] componentsInChildren = val.GetComponentsInChildren<ZSFX>(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<GameObject>(((Component)val).gameObject, ((Component)container).transform.position, ((Component)container).transform.rotation), 5f); } } } private static int MoveItemToInventoryTopFirst(Inventory sourceInventory, Inventory targetInventory, ItemData source, HashSet<Vector2i>? 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<Vector2i> 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<Container> 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<ItemData> 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<ItemData> 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<ZNetView>() : ((Component)container).GetComponent<ZNetView>()); } 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<ZPackage>("InventoryActions_AreaOwnershipRequestV1", (Action<long, ZPackage>)delegate(long sender, ZPackage package) { RPC_RequestAreaOwnership(container, sender, package); }); container.m_nview.Register<ZPackage>("InventoryActions_AreaOwnershipResponseV1", (Action<long, ZPackage>)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<long, string> 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 && pa