Decompiled source of InventoryActions v1.0.0

InventoryActions.dll

Decompiled 5 hours ago
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.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.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace InventoryActions
{
	[BepInPlugin("sighsorry.InventoryActions", "InventoryActions", "1.0.0")]
	[BepInIncompatibility("sighsorry.InventorySlots")]
	[BepInIncompatibility("goldenrevolver.quick_stack_store")]
	public sealed class InventoryActionsPlugin : BaseUnityPlugin
	{
		public enum Toggle
		{
			Off,
			On
		}

		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; }
		}

		private enum RestockMode
		{
			CurrentContainerMatchingStacks,
			AreaFavoriteRestock
		}

		private readonly struct SfxVolumeMemberCache
		{
			public FieldInfo[] Fields { get; }

			public PropertyInfo[] Properties { get; }

			public SfxVolumeMemberCache(FieldInfo[] fields, PropertyInfo[] properties)
			{
				Fields = fields;
				Properties = properties;
			}
		}

		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 Action <0>__HandleLocalizationComplete;

			public static Action<ConfigEntryBase> <1>__DrawRestockTargetStackLimitsConfig;

			public static Func<KeyCode, string> <2>__GetShortcutKeyDisplayText;

			public static Func<Player, Container?> <3>__TryGetHoverQuickStackContext;

			public static Func<Player, Container, bool> <4>__TryQuickStackFromHoveredContainer;

			public static Func<Player, Container?> <5>__TryGetHoverRestockContext;

			public static Func<Player, Container, bool> <6>__TryRestockFromHoveredContainer;

			public static Func<char, bool> <7>__IsDigit;

			public static UnityAction <8>__TryClickInventoryTrashPanel;
		}

		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static EventHandler <>9__40_0;

			public static EventHandler <>9__40_1;

			public static Func<char, bool> <>9__55_0;

			public static Func<string, bool> <>9__64_0;

			public static Func<Vector2i, int> <>9__72_0;

			public static Func<Vector2i, int> <>9__72_1;

			public static Func<Vector2i, string> <>9__72_2;

			public static Func<ItemData, bool> <>9__85_1;

			public static Func<ItemData, int> <>9__85_2;

			public static Func<ItemData, int> <>9__85_3;

			public static Func<ItemData, int> <>9__86_1;

			public static Func<ItemData, int> <>9__86_2;

			public static Comparison<ItemData> <>9__89_1;

			public static Func<ItemData, bool> <>9__91_0;

			public static Func<ItemData, string> <>9__91_1;

			public static Comparison<ItemData> <>9__92_1;

			public static Comparison<ItemData> <>9__96_1;

			public static Func<ItemData, bool> <>9__105_0;

			public static Func<ItemData, ItemData> <>9__107_0;

			public static Func<ItemData, bool> <>9__108_0;

			public static Func<ItemData, <>f__AnonymousType0<string, int, int>> <>9__108_1;

			public static Func<IGrouping<<>f__AnonymousType0<string, int, int>, ItemData>, List<ItemData>> <>9__108_2;

			public static Func<ItemData, int> <>9__108_3;

			public static Comparison<(Container Container, float DistanceSq)> <>9__130_0;

			public static Func<FieldInfo, bool> <>9__142_0;

			public static Func<PropertyInfo, bool> <>9__142_1;

			public static Func<ItemData, int> <>9__148_1;

			public static Func<ItemData, int> <>9__148_2;

			public static Func<RestockTargetLimitEditorRow, bool> <>9__165_0;

			public static Func<RestockTargetLimitEditorRow, string> <>9__165_1;

			public static UnityAction <>9__177_0;

			public static UnityAction <>9__177_1;

			public static UnityAction <>9__179_0;

			public static UnityAction <>9__186_0;

			internal void <BindConfigs>b__40_0(object _, EventArgs _)
			{
				RefreshFavoriteBorders();
			}

			internal void <BindConfigs>b__40_1(object _, EventArgs _)
			{
				RefreshRestockTargetStackLimits();
			}

			internal bool <GetFavoriteFilePath>b__55_0(char ch)
			{
				bool flag = char.IsLetterOrDigit(ch);
				if (!flag)
				{
					bool flag2 = ((ch == '-' || ch == '_') ? true : false);
					flag = flag2;
				}
				return flag;
			}

			internal bool <GetShortcutDisplayText>b__64_0(string part)
			{
				return !string.IsNullOrWhiteSpace(part);
			}

			internal int <SaveFavorites>b__72_0(Vector2i slot)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				return slot.y;
			}

			internal int <SaveFavorites>b__72_1(Vector2i slot)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				return slot.x;
			}

			internal string <SaveFavorites>b__72_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 <SafeTakeAllItems>b__85_1(ItemData item)
			{
				return item?.m_shared != null;
			}

			internal int <SafeTakeAllItems>b__85_2(ItemData item)
			{
				return item.m_gridPos.y;
			}

			internal int <SafeTakeAllItems>b__85_3(ItemData item)
			{
				return item.m_gridPos.x;
			}

			internal int <MoveContainerItemSafelyToPlayer>b__86_1(ItemData target)
			{
				return target.m_gridPos.y;
			}

			internal int <MoveContainerItemSafelyToPlayer>b__86_2(ItemData target)
			{
				return target.m_gridPos.x;
			}

			internal int <QuickStackIntoContainers>b__89_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__91_0(ItemData item)
			{
				return item?.m_shared != null;
			}

			internal string <QuickStackItemsIntoContainer>b__91_1(ItemData item)
			{
				return item.m_shared.m_name;
			}

			internal int <StoreAllToCurrentContainer>b__92_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__96_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__105_0(ItemData item)
			{
				return item?.m_shared != null;
			}

			internal ItemData <SortInventoryInternal>b__107_0(ItemData item)
			{
				return item;
			}

			internal bool <MergeSortableStacks>b__108_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__108_1(ItemData item)
			{
				return new
				{
					item.m_shared.m_name,
					item.m_quality,
					item.m_worldLevel
				};
			}

			internal List<ItemData> <MergeSortableStacks>b__108_2(IGrouping<<>f__AnonymousType0<string, int, int>, ItemData> grouping)
			{
				return grouping.ToList();
			}

			internal int <MergeSortableStacks>b__108_3(ItemData item)
			{
				return item.m_stack;
			}

			internal int <GetActionContainers>b__130_0((Container Container, float DistanceSq) left, (Container Container, float DistanceSq) right)
			{
				return left.DistanceSq.CompareTo(right.DistanceSq);
			}

			internal bool <GetSfxVolumeMemberCache>b__142_0(FieldInfo field)
			{
				if (field.FieldType == typeof(float) && IsSfxVolumeMemberName(field.Name))
				{
					return !IsUnsupportedSfxVolumeMemberName(field.Name);
				}
				return false;
			}

			internal bool <GetSfxVolumeMemberCache>b__142_1(PropertyInfo property)
			{
				if (property.PropertyType == typeof(float) && property.CanRead && property.CanWrite && property.GetIndexParameters().Length == 0 && IsSfxVolumeMemberName(property.Name))
				{
					return !IsUnsupportedSfxVolumeMemberName(property.Name);
				}
				return false;
			}

			internal int <MoveItemToInventoryTopFirst>b__148_1(ItemData target)
			{
				return target.m_gridPos.y;
			}

			internal int <MoveItemToInventoryTopFirst>b__148_2(ItemData target)
			{
				return target.m_gridPos.x;
			}

			internal bool <SerializeRestockTargetLimitEditorRows>b__165_0(RestockTargetLimitEditorRow row)
			{
				if (string.IsNullOrWhiteSpace(row.Item))
				{
					return !string.IsNullOrWhiteSpace(row.Amount);
				}
				return true;
			}

			internal string <SerializeRestockTargetLimitEditorRows>b__165_1(RestockTargetLimitEditorRow row)
			{
				return row.Item.Trim() + ": " + row.Amount.Trim();
			}

			internal void <UpdateContainerActionButtons>b__177_0()
			{
				StoreAllToCurrentContainer(Player.m_localPlayer);
			}

			internal void <UpdateContainerActionButtons>b__177_1()
			{
				RestockFromCurrentContainer(Player.m_localPlayer);
			}

			internal void <UpdatePlayerActionPanel>b__179_0()
			{
				SortPlayerInventory(Player.m_localPlayer);
			}

			internal void <EnsureContainerSortButton>b__186_0()
			{
				SortCurrentContainer(Player.m_localPlayer);
			}
		}

		[CompilerGenerated]
		private sealed class <GetInventorySlotsTopFirst>d__150 : IEnumerable<Vector2i>, IEnumerable, IEnumerator<Vector2i>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private Vector2i <>2__current;

			private int <>l__initialThreadId;

			private Inventory inventory;

			public Inventory <>3__inventory;

			private int <width>5__2;

			private int <height>5__3;

			private int <y>5__4;

			private int <x>5__5;

			Vector2i IEnumerator<Vector2i>.Current
			{
				[DebuggerHidden]
				get
				{
					//IL_0001: Unknown result type (might be due to invalid IL or missing references)
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					//IL_0001: Unknown result type (might be due to invalid IL or missing references)
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <GetInventorySlotsTopFirst>d__150(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0064: Unknown result type (might be due to invalid IL or missing references)
				//IL_0069: Unknown result type (might be due to invalid IL or missing references)
				int num = <>1__state;
				if (num != 0)
				{
					if (num != 1)
					{
						return false;
					}
					<>1__state = -1;
					<x>5__5++;
					goto IL_008e;
				}
				<>1__state = -1;
				<width>5__2 = Math.Max(1, inventory.GetWidth());
				<height>5__3 = Math.Max(0, inventory.GetHeight());
				<y>5__4 = 0;
				goto IL_00ac;
				IL_008e:
				if (<x>5__5 < <width>5__2)
				{
					<>2__current = new Vector2i(<x>5__5, <y>5__4);
					<>1__state = 1;
					return true;
				}
				<y>5__4++;
				goto IL_00ac;
				IL_00ac:
				if (<y>5__4 < <height>5__3)
				{
					<x>5__5 = 0;
					goto IL_008e;
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<Vector2i> IEnumerable<Vector2i>.GetEnumerator()
			{
				<GetInventorySlotsTopFirst>d__150 <GetInventorySlotsTopFirst>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<GetInventorySlotsTopFirst>d__ = this;
				}
				else
				{
					<GetInventorySlotsTopFirst>d__ = new <GetInventorySlotsTopFirst>d__150(0);
				}
				<GetInventorySlotsTopFirst>d__.inventory = <>3__inventory;
				return <GetInventorySlotsTopFirst>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<Vector2i>)this).GetEnumerator();
			}
		}

		[CompilerGenerated]
		private sealed class <GetRestockTargetLookupTokens>d__101 : IEnumerable<string>, IEnumerable, IEnumerator<string>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private string? <>2__current;

			private int <>l__initialThreadId;

			private ItemData item;

			public ItemData <>3__item;

			private string <sharedName>5__2;

			string IEnumerator<string>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <GetRestockTargetLookupTokens>d__101(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<sharedName>5__2 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					if (item == null)
					{
						return false;
					}
					<>2__current = GetItemPrefabName(item);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					if (!IsUnityNull((Object?)(object)item.m_dropPrefab))
					{
						<>2__current = ((Object)item.m_dropPrefab).name;
						<>1__state = 2;
						return true;
					}
					goto IL_0091;
				case 2:
					<>1__state = -1;
					goto IL_0091;
				case 3:
					<>1__state = -1;
					<>2__current = RestockTargetLimitCore.StripLocalizationToken(<sharedName>5__2);
					<>1__state = 4;
					return true;
				case 4:
					<>1__state = -1;
					if (Localization.instance != null && !string.IsNullOrWhiteSpace(<sharedName>5__2))
					{
						<>2__current = Localization.instance.Localize(<sharedName>5__2);
						<>1__state = 5;
						return true;
					}
					break;
				case 5:
					{
						<>1__state = -1;
						break;
					}
					IL_0091:
					<sharedName>5__2 = item.m_shared?.m_name ?? "";
					<>2__current = <sharedName>5__2;
					<>1__state = 3;
					return true;
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<string> IEnumerable<string>.GetEnumerator()
			{
				<GetRestockTargetLookupTokens>d__101 <GetRestockTargetLookupTokens>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<GetRestockTargetLookupTokens>d__ = this;
				}
				else
				{
					<GetRestockTargetLookupTokens>d__ = new <GetRestockTargetLookupTokens>d__101(0);
				}
				<GetRestockTargetLookupTokens>d__.item = <>3__item;
				return <GetRestockTargetLookupTokens>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<string>)this).GetEnumerator();
			}
		}

		internal const string ModName = "InventoryActions";

		internal const string ModVersion = "1.0.0";

		internal const string Author = "sighsorry";

		internal const string ModGUID = "sighsorry.InventoryActions";

		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 ContainerHoverHoldDurationDefault = 0.5f;

		private const float ContainerHoverHoldDurationMin = 0.1f;

		private const float ContainerHoverHoldDurationMax = 0.5f;

		private const string ContainerActionSuccessFxPrefabName = "fx_HildirChest_Unlock";

		private const int ContainerActionSuccessFxMaxMode = 12;

		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 ConfigSync ConfigSync = new ConfigSync("sighsorry.InventoryActions")
		{
			DisplayName = "InventoryActions",
			CurrentVersion = "1.0.0",
			MinimumRequiredVersion = "1.0.0"
		};

		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<float> _containerHoverHoldDuration = null;

		private static ConfigEntry<int> _containerActionSuccessFxMode = null;

		private static ConfigEntry<float> _containerActionSuccessFxVolume = null;

		private static ConfigEntry<KeyboardShortcut> _favoriteModifierKey = null;

		private static ConfigEntry<KeyboardShortcut> _containerRestockKey = null;

		private static ConfigEntry<string> _restockTargetStackLimitsConfig = null;

		private static readonly Color FavoriteBorderDefaultColor = new Color(0.1f, 0.55f, 1f, 0.95f);

		private static readonly Dictionary<Type, SfxVolumeMemberCache> SfxVolumeMembersByType = new Dictionary<Type, SfxVolumeMemberCache>();

		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 void Awake()
		{
			_instance = this;
			Localizer.OnLocalizationComplete += HandleLocalizationComplete;
			Localizer.Load((BaseUnityPlugin)(object)this);
			BindConfigs();
			_harmony.PatchAll();
			Log.LogInfo((object)"InventoryActions loaded.");
		}

		private void Update()
		{
			if (!IsDedicatedServer)
			{
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer == (Object)null || IsUnityNull((Object?)(object)localPlayer) || localPlayer.m_isLoading)
				{
					ResetContainerHold(Runtime.AreaQuickStackHold);
					ResetContainerHold(Runtime.AreaRestockHold);
				}
				else
				{
					HandleHoverActions(localPlayer);
				}
			}
		}

		private void OnDestroy()
		{
			Localizer.OnLocalizationComplete -= HandleLocalizationComplete;
			_harmony.UnpatchSelf();
			((BaseUnityPlugin)this).Config.Save();
		}

		private static void HandleLocalizationComplete()
		{
			Runtime.UiLocalizationVersion++;
		}

		private static void BindConfigs()
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Expected O, but got Unknown
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Expected O, but got Unknown
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Expected O, but got Unknown
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Expected O, but got Unknown
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Expected O, but got Unknown
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Expected O, but got Unknown
			//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ad: Expected O, but got Unknown
			//IL_0306: Unknown result type (might be due to invalid IL or missing references)
			//IL_0311: Expected O, but got Unknown
			_serverConfigLocked = ConfigEntry("1 - General", "Lock Configuration", Toggle.On, "When enabled, only server admins can modify this mod's synced configuration.");
			ConfigSync.AddLockingConfigEntry<Toggle>(_serverConfigLocked);
			_enableInventoryTrashPanel = ConfigEntry("1 - General", "Enable Inventory Trash Panel", Toggle.On, "When enabled, shows a trash panel below the player inventory. Dropping a held player-inventory item on it opens a confirmation dialog before deleting the held amount.");
			_areaQuickStackRange = ConfigEntry("1 - General", "Area Quick Stack Range", 10f, new ConfigDescription("Range in meters for hover Area Quick Stack. Set to 0 to disable area quick stack. The opened-container Place stacks button only uses the current container.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>()));
			_areaRestockRange = ConfigEntry("1 - General", "Area Take Stacks Range", 10f, new ConfigDescription("Range in meters for hover Area Take Stacks. Set to 0 to disable area take stacks. The opened-container Take stacks button only uses the current container.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>()));
			_favoriteModifierKey = ConfigEntry<KeyboardShortcut>("2 - Client", "Favorite Modifier Key", new KeyboardShortcut((KeyCode)308, Array.Empty<KeyCode>()), new ConfigDescription("Hold this and left-click a player inventory cell to toggle that favorite slot. Alt accepts both LeftAlt and RightAlt.", (AcceptableValueBase)(object)new AcceptableShortcuts(), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 900
				}
			}), synchronizedSetting: false);
			_containerRestockKey = ConfigEntry<KeyboardShortcut>("2 - Client", "Container Restock Key", new KeyboardShortcut((KeyCode)101, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), new ConfigDescription("Hold this while hovering a container to take stacks into favorite slots from that container and nearby containers. Alt accepts both LeftAlt and RightAlt.", (AcceptableValueBase)(object)new AcceptableShortcuts(), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 890
				}
			}), synchronizedSetting: false);
			_favoriteBorderColor = ConfigEntry<Color>("2 - Client", "Favorite Border Color", FavoriteBorderDefaultColor, new ConfigDescription("Color for favorite slot borders. Uses the same RRGGBBAA color format as InventorySlots color configs. Not synced with server.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 880
				}
			}), synchronizedSetting: false);
			_favoriteBorderColor.SettingChanged += delegate
			{
				RefreshFavoriteBorders();
			};
			_containerHoverHoldDuration = ConfigEntry("2 - Client", "Container Hover Hold Duration", 0.5f, new ConfigDescription("Seconds a container must stay hovered while holding E or the Container Restock Key before hover quick stack/restock fires. Lower values make pass-by container actions more responsive. Not synced with server.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 0.5f), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 870
				}
			}), synchronizedSetting: false);
			_containerActionSuccessFxMode = ConfigEntry("2 - Client", "Container Action Success FX Mode", 4, new ConfigDescription("Chest-unlock FX mode for hover hold area actions. 0 disables FX. 1 spawns FX at the interacted container. 2-12 spawns FX at each container whose stack changed, up to this many containers. Opened-container buttons do not spawn FX.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 12), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 860
				}
			}), synchronizedSetting: false);
			_containerActionSuccessFxVolume = ConfigEntry("2 - Client", "Container Action Success FX Volume", 1f, new ConfigDescription("Volume multiplier for InventoryActions container action success FX audio. 0 mutes the FX sound and 1 keeps the original prefab volume.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 850
				}
			}), synchronizedSetting: false);
			_restockTargetStackLimitsConfig = ConfigEntry("3 - Restock", "Restock Target Stack Limits", "", new ConfigDescription("Client-only per-item target stack caps for Take stacks/restock into favorite slots. Keys may be prefab names, internal item names, or localized item names in the current client language, such as Stone: 10, Coins: 500. Separate entries with commas, semicolons, or new lines. Empty uses each item's normal max stack; 0 prevents restocking that item.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 700,
					CustomDrawer = DrawRestockTargetStackLimitsConfig
				}
			}), synchronizedSetting: false);
			_restockTargetStackLimitsConfig.SettingChanged += delegate
			{
				RefreshRestockTargetStackLimits();
			};
			RefreshRestockTargetStackLimits();
		}

		private static ConfigEntry<T> ConfigEntry<T>(string group, string name, T value, string description, bool synchronizedSetting = true)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			return ConfigEntry(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting);
		}

		private static ConfigEntry<T> ConfigEntry<T>(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			ConfigDescription val = new ConfigDescription(description.Description + " [" + (synchronizedSetting ? "Synced with Server" : "Not Synced with Server") + "]", description.AcceptableValues, description.Tags);
			ConfigEntry<T> val2 = ((BaseUnityPlugin)_instance).Config.Bind<T>(group, name, value, val);
			ConfigSync.AddConfigEntry<T>(val2).SynchronizedConfig = synchronizedSetting;
			return val2;
		}

		private static bool IsUnityNull(Object? obj)
		{
			return obj == (Object)null;
		}

		private static bool IsOutOfBounds(Inventory inventory, Vector2i pos)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			if (inventory != null && pos.x >= 0 && pos.y >= 0 && pos.x < inventory.GetWidth())
			{
				return pos.y >= inventory.GetHeight();
			}
			return true;
		}

		private static Inventory? GetPlayerInventory(Player? player)
		{
			if (!((Object)(object)player != (Object)null))
			{
				return null;
			}
			return ((Humanoid)player).GetInventory();
		}

		private static bool IsPlayerInventory(Player? player, Inventory? inventory)
		{
			if ((Object)(object)player != (Object)null && inventory != null)
			{
				return inventory == GetPlayerInventory(player);
			}
			return false;
		}

		private static bool IsPlayerActionCell(Inventory inventory, Vector2i pos, bool includeHotbar)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			if (IsOutOfBounds(inventory, pos) || pos.y >= Math.Min(4, inventory.GetHeight()))
			{
				return false;
			}
			return pos.y > 0 || includeHotbar;
		}

		private static bool IsHotbarCell(Vector2i pos)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return pos.y == 0;
		}

		private static bool IsRegularActionItem(Player player, Inventory inventory, ItemData item, bool includeHotbar)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			if (item?.m_shared != null)
			{
				return IsPlayerActionCell(inventory, item.m_gridPos, includeHotbar);
			}
			return false;
		}

		private static bool HasNoCustomData(ItemData item)
		{
			if (item.m_customData != null)
			{
				return item.m_customData.Count == 0;
			}
			return true;
		}

		private static bool CanUseContainerActionStacking(ItemData item)
		{
			if (item?.m_shared != null)
			{
				return HasNoCustomData(item);
			}
			return false;
		}

		private static string GetPlayerId(Player player)
		{
			Game instance = Game.instance;
			PlayerProfile val = ((instance != null) ? instance.GetPlayerProfile() : null);
			if (val == null)
			{
				return player.GetPlayerID().ToString();
			}
			return val.GetPlayerID().ToString();
		}

		private static string GetFavoriteFilePath(string playerId)
		{
			string text = new string(playerId.Where(delegate(char ch)
			{
				bool flag = char.IsLetterOrDigit(ch);
				if (!flag)
				{
					bool flag2 = ((ch == '-' || ch == '_') ? true : false);
					flag = flag2;
				}
				return flag;
			}).ToArray());
			if (string.IsNullOrWhiteSpace(text))
			{
				text = "unknown";
			}
			return Path.Combine(Paths.ConfigPath, "InventoryActions.Favorites." + text + ".txt");
		}

		private static string LocalizeUi(string token, string fallback)
		{
			if (Localization.instance == null || string.IsNullOrWhiteSpace(token))
			{
				return fallback;
			}
			string text = Localization.instance.Localize(token);
			if (!string.IsNullOrWhiteSpace(text) && !string.Equals(text, token, StringComparison.Ordinal))
			{
				return text;
			}
			return fallback;
		}

		private static string GetLocalizedItemName(ItemData item)
		{
			string text = item?.m_shared?.m_name ?? "";
			if (Localization.instance == null)
			{
				return text;
			}
			return Localization.instance.Localize(text);
		}

		private static void ShowActionResult(Player player, string action, int moved)
		{
			if (!((Object)(object)player == (Object)null))
			{
				string text = LocalizeUi("$inventoryslots_action_result_format", "{action}: {count}").Replace("{action}", action).Replace("{count}", moved.ToString());
				((Character)player).Message((MessageType)2, text, 0, (Sprite)null);
			}
		}

		private static bool ShouldBlockGlobalHotkeys(Player? player = null)
		{
			if ((Object)(object)player != (Object)null && (player.m_isLoading || ((Character)player).InCutscene()))
			{
				return true;
			}
			if ((Object)(object)Chat.instance != (Object)null && !IsUnityNull((Object?)(object)Chat.instance) && Chat.instance.HasFocus())
			{
				return true;
			}
			if (Console.IsVisible() || TextInput.IsVisible() || Menu.IsVisible() || Minimap.IsOpen() || Minimap.InTextInput() || StoreGui.IsVisible() || GameCamera.InFreeFly())
			{
				return true;
			}
			if ((Object)(object)TextViewer.instance != (Object)null && !IsUnityNull((Object?)(object)TextViewer.instance) && TextViewer.instance.IsVisible())
			{
				return true;
			}
			if ((Object)(object)ZNet.instance != (Object)null && !IsUnityNull((Object?)(object)ZNet.instance))
			{
				return ZNet.instance.InPasswordDialog();
			}
			return false;
		}

		private static bool IsShortcutHeldAllowingAltPair(KeyboardShortcut shortcut)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0 || !AreShortcutModifiersHeldAllowingAltPair(shortcut))
			{
				return false;
			}
			return IsShortcutMainKeyHeldAllowingAltPair(shortcut);
		}

		private static bool AreShortcutModifiersHeldAllowingAltPair(KeyboardShortcut shortcut)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers)
			{
				if (!IsShortcutModifierHeldAllowingAltPair(modifier))
				{
					return false;
				}
			}
			return true;
		}

		private static bool IsShortcutModifierHeldAllowingAltPair(KeyCode key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (key - 307 <= 1)
			{
				if (!Input.GetKey((KeyCode)308))
				{
					return Input.GetKey((KeyCode)307);
				}
				return true;
			}
			return Input.GetKey(key);
		}

		private static bool IsShortcutMainKeyHeldAllowingAltPair(KeyboardShortcut shortcut)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between Unknown and I4
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			KeyCode mainKey = ((KeyboardShortcut)(ref shortcut)).MainKey;
			if (mainKey - 307 <= 1)
			{
				if (!Input.GetKey((KeyCode)308))
				{
					return Input.GetKey((KeyCode)307);
				}
				return true;
			}
			return Input.GetKey(((KeyboardShortcut)(ref shortcut)).MainKey);
		}

		private static string GetShortcutDisplayText(KeyboardShortcut shortcut)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0)
			{
				return "";
			}
			IEnumerable<string> values = from part in ((KeyboardShortcut)(ref shortcut)).Modifiers.Select(GetShortcutKeyDisplayText).Concat(new string[1] { GetShortcutKeyDisplayText(((KeyboardShortcut)(ref shortcut)).MainKey) })
				where !string.IsNullOrWhiteSpace(part)
				select part;
			return string.Join("+", values);
		}

		private static string GetShortcutKeyDisplayText(KeyCode key)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Invalid comparison between Unknown and I4
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Invalid comparison between Unknown and I4
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected I4, but got Unknown
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Invalid comparison between Unknown and I4
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected I4, but got Unknown
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Invalid comparison between Unknown and I4
			string text = ((object)(KeyCode)(ref key)).ToString();
			if (text.StartsWith("Alpha", StringComparison.Ordinal))
			{
				return text.Substring("Alpha".Length);
			}
			if ((int)key <= 27)
			{
				if ((int)key == 0)
				{
					return "";
				}
				if ((int)key == 13)
				{
					return "Enter";
				}
				if ((int)key == 27)
				{
					return "Esc";
				}
			}
			else
			{
				if ((int)key == 32)
				{
					return "Spc";
				}
				switch (key - 303)
				{
				case 4:
				case 5:
					return "Alt";
				case 2:
				case 3:
					return "Ctrl";
				case 0:
				case 1:
					return "Shift";
				}
				switch (key - 323)
				{
				case 0:
					return "M1";
				case 1:
					return "M2";
				case 2:
					return "M3";
				case 3:
					return "M4";
				case 4:
					return "M5";
				case 5:
					return "M6";
				case 6:
					return "M7";
				}
			}
			return text;
		}

		internal static bool HandleFavoriteClick(InventoryGrid grid, UIInputHandler clickHandler)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			if (!ShouldHandleFavoriteClick(grid))
			{
				return true;
			}
			Player localPlayer = Player.m_localPlayer;
			Inventory playerInventory = GetPlayerInventory(localPlayer);
			if (playerInventory == null || grid.m_inventory != playerInventory)
			{
				return true;
			}
			Vector2i buttonPos = grid.GetButtonPos(((Component)clickHandler).gameObject);
			if (buttonPos.x < 0 || buttonPos.y < 0 || IsOutOfBounds(playerInventory, buttonPos))
			{
				return true;
			}
			if (!IsPlayerActionCell(playerInventory, buttonPos, includeHotbar: true))
			{
				return true;
			}
			ToggleFavoriteSlot(localPlayer, buttonPos);
			return false;
		}

		private static bool ShouldHandleFavoriteClick(InventoryGrid grid)
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)grid == (Object)null || (Object)(object)InventoryGui.instance == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				return false;
			}
			Player localPlayer = Player.m_localPlayer;
			if (localPlayer.m_isLoading || ((Character)localPlayer).IsTeleporting())
			{
				return false;
			}
			if ((Object)(object)InventoryGui.instance.m_dragGo != (Object)null || (Object)(object)grid != (Object)(object)InventoryGui.instance.m_playerGrid)
			{
				return false;
			}
			if (_favoriteModifierKey != null)
			{
				return IsShortcutHeldAllowingAltPair(_favoriteModifierKey.Value);
			}
			return false;
		}

		private static void ToggleFavoriteSlot(Player player, Vector2i pos)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			EnsureFavoritesLoaded(player);
			if (!Runtime.FavoriteSlots.Add(pos))
			{
				Runtime.FavoriteSlots.Remove(pos);
			}
			SaveFavorites(player);
			RefreshFavoriteBorders();
		}

		private static bool IsFavoriteProtected(Player player, Inventory inventory, ItemData item)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			if (item?.m_shared != null && IsPlayerInventory(player, inventory))
			{
				return IsFavoriteSlot(player, item.m_gridPos);
			}
			return false;
		}

		private static bool IsFavoriteSlot(Player player, Vector2i pos)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			EnsureFavoritesLoaded(player);
			return Runtime.FavoriteSlots.Contains(pos);
		}

		private static void EnsureFavoritesLoaded(Player player)
		{
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null)
			{
				return;
			}
			string playerId = GetPlayerId(player);
			if (string.Equals(Runtime.LoadedFavoritesPlayerId, playerId, StringComparison.Ordinal))
			{
				return;
			}
			Runtime.FavoriteSlots.Clear();
			Runtime.LoadedFavoritesPlayerId = playerId;
			string favoriteFilePath = GetFavoriteFilePath(playerId);
			if (!File.Exists(favoriteFilePath))
			{
				return;
			}
			try
			{
				string[] array = File.ReadAllLines(favoriteFilePath);
				for (int i = 0; i < array.Length; i++)
				{
					string text = array[i].Trim();
					if (text.Length != 0 && !text.StartsWith("#", StringComparison.Ordinal))
					{
						string[] array2 = text.Split(new char[1] { ',' });
						if (array2.Length == 2 && int.TryParse(array2[0].Trim(), out var result) && int.TryParse(array2[1].Trim(), out var result2) && result >= 0 && result2 >= 0)
						{
							Runtime.FavoriteSlots.Add(new Vector2i(result, result2));
						}
					}
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Failed to load InventoryActions favorites from " + favoriteFilePath + ": " + ex.Message));
			}
		}

		private static void SaveFavorites(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return;
			}
			string playerId = GetPlayerId(player);
			Runtime.LoadedFavoritesPlayerId = playerId;
			string favoriteFilePath = GetFavoriteFilePath(playerId);
			try
			{
				string[] contents = (from slot in Runtime.FavoriteSlots
					orderby slot.y, slot.x
					select $"{slot.x},{slot.y}").ToArray();
				File.WriteAllLines(favoriteFilePath, contents);
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Failed to save InventoryActions favorites to " + favoriteFilePath + ": " + ex.Message));
			}
		}

		private static void RefreshFavoriteBorders()
		{
			InventoryGui instance = InventoryGui.instance;
			if (!((Object)(object)instance?.m_playerGrid == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null))
			{
				UpdateFavoriteBorders(instance.m_playerGrid, Player.m_localPlayer);
			}
		}

		private static void UpdateFavoriteBorders(InventoryGrid grid, Player player)
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			Inventory playerInventory = GetPlayerInventory(player);
			if (grid?.m_elements == null || playerInventory == null || grid.m_inventory != playerInventory)
			{
				return;
			}
			EnsureFavoritesLoaded(player);
			foreach (Element element in grid.m_elements)
			{
				if ((Object)(object)element?.m_go == (Object)null || IsUnityNull((Object?)(object)element.m_go))
				{
					continue;
				}
				if (!element.m_go.activeSelf)
				{
					SetFavoriteBorderActive(element, active: false);
					continue;
				}
				Vector2i buttonPos = grid.GetButtonPos(element.m_go);
				if (IsOutOfBounds(playerInventory, buttonPos) || !Runtime.FavoriteSlots.Contains(buttonPos))
				{
					SetFavoriteBorderActive(element, active: false);
					continue;
				}
				RectTransform val = EnsureFavoriteBorder(element);
				if (!((Object)(object)val == (Object)null))
				{
					InventoryGridElementMarker inventoryGridElementMarker = element.m_go.GetComponent<InventoryGridElementMarker>() ?? element.m_go.AddComponent<InventoryGridElementMarker>();
					if (inventoryGridElementMarker.FavoriteBorderImages.Length == 0)
					{
						inventoryGridElementMarker.FavoriteBorderImages = ((Component)val).GetComponentsInChildren<Image>(true);
					}
					Image[] favoriteBorderImages = inventoryGridElementMarker.FavoriteBorderImages;
					for (int i = 0; i < favoriteBorderImages.Length; i++)
					{
						((Graphic)favoriteBorderImages[i]).color = GetFavoriteBorderColor();
					}
					((Component)val).gameObject.SetActive(true);
					((Transform)val).SetAsLastSibling();
				}
			}
		}

		private static Color GetFavoriteBorderColor()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			if (_favoriteBorderColor == null)
			{
				return FavoriteBorderDefaultColor;
			}
			return _favoriteBorderColor.Value;
		}

		private static RectTransform? EnsureFavoriteBorder(Element element)
		{
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Expected O, but got Unknown
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)element?.m_go == (Object)null || IsUnityNull((Object?)(object)element.m_go))
			{
				return null;
			}
			GameObject go = element.m_go;
			InventoryGridElementMarker inventoryGridElementMarker = go.GetComponent<InventoryGridElementMarker>() ?? go.AddComponent<InventoryGridElementMarker>();
			RectTransform val = (((Object)(object)inventoryGridElementMarker.FavoriteBorder != (Object)null && !IsUnityNull((Object?)(object)inventoryGridElementMarker.FavoriteBorder)) ? inventoryGridElementMarker.FavoriteBorder : null);
			if ((Object)(object)val == (Object)null)
			{
				Transform val2 = go.transform.Find("InventoryActions_FavoriteBorder");
				val = (((Object)(object)val2 != (Object)null) ? ((Component)val2).GetComponent<RectTransform>() : null);
			}
			if ((Object)(object)val == (Object)null)
			{
				val = (RectTransform)new GameObject("InventoryActions_FavoriteBorder", new Type[1] { typeof(RectTransform) }).transform;
				((Transform)val).SetParent(go.transform, false);
				CreateFavoriteBorderSide(val, "Top", new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, 2f), Vector2.zero);
				CreateFavoriteBorderSide(val, "Bottom", new Vector2(0f, 0f), new Vector2(1f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 2f), Vector2.zero);
				CreateFavoriteBorderSide(val, "Left", new Vector2(0f, 0f), new Vector2(0f, 1f), new Vector2(0f, 0.5f), new Vector2(2f, 0f), Vector2.zero);
				CreateFavoriteBorderSide(val, "Right", new Vector2(1f, 0f), new Vector2(1f, 1f), new Vector2(1f, 0.5f), new Vector2(2f, 0f), Vector2.zero);
			}
			val.anchorMin = Vector2.zero;
			val.anchorMax = Vector2.one;
			val.offsetMin = Vector2.zero;
			val.offsetMax = Vector2.zero;
			((Transform)val).localScale = Vector3.one;
			((Transform)val).localRotation = Quaternion.identity;
			inventoryGridElementMarker.FavoriteBorder = val;
			if (inventoryGridElementMarker.FavoriteBorderImages.Length == 0)
			{
				inventoryGridElementMarker.FavoriteBorderImages = ((Component)val).GetComponentsInChildren<Image>(true);
			}
			return val;
		}

		private static void CreateFavoriteBorderSide(RectTransform parent, string name, Vector2 anchorMin, Vector2 anchorMax, Vector2 pivot, Vector2 sizeDelta, Vector2 anchoredPosition)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent((Transform)(object)parent, false);
			val2.anchorMin = anchorMin;
			val2.anchorMax = anchorMax;
			val2.pivot = pivot;
			val2.sizeDelta = sizeDelta;
			val2.anchoredPosition = anchoredPosition;
			((Transform)val2).localScale = Vector3.one;
			((Transform)val2).localRotation = Quaternion.identity;
			((Graphic)val.GetComponent<Image>()).raycastTarget = false;
		}

		private static void SetFavoriteBorderActive(Element element, bool active)
		{
			if (!((Object)(object)element?.m_go == (Object)null) && !IsUnityNull((Object?)(object)element.m_go))
			{
				InventoryGridElementMarker component = element.m_go.GetComponent<InventoryGridElementMarker>();
				Transform val = (Transform)(((Object)(object)component?.FavoriteBorder != (Object)null && !IsUnityNull((Object?)(object)component.FavoriteBorder)) ? ((object)component.FavoriteBorder) : ((object)element.m_go.transform.Find("InventoryActions_FavoriteBorder")));
				if ((Object)(object)val != (Object)null && ((Component)val).gameObject.activeSelf != active)
				{
					((Component)val).gameObject.SetActive(active);
				}
			}
		}

		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))
			{
				((Character)localPlayer).Message((MessageType)2, LocalizeUi("$inventoryslots_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);
			int num = SafeTakeAllItems(localPlayer, playerInventory, inventory);
			if (num > 0)
			{
				playerInventory.Changed();
				inventory.Changed();
			}
			if ((Object)(object)component != (Object)null && inventory.NrOfItems() == 0)
			{
				component.OnTakeAllSuccess();
			}
			ShowActionResult(localPlayer, LocalizeUi("$inventoryslots_action_take_all", "Take All"), num);
			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_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: 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)
		{
			Inventory playerInventory2 = playerInventory;
			List<Vector2i> playerActionSlots = GetPlayerActionSlots(player, playerInventory2, includeHotbar: false, blockFavorites: true);
			HashSet<Vector2i> allowedSlots = new HashSet<Vector2i>(playerActionSlots);
			List<Vector2i> emptySlots = playerActionSlots.Where((Vector2i slot) => playerInventory2.GetItemAt(slot.x, slot.y) == null).ToList();
			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 (MoveContainerItemSafelyToPlayer(playerInventory2, containerInventory, item, emptySlots, allowedSlots) > 0 && (!containerInventory.m_inventory.Contains(item) || item.m_stack < stack))
					{
						num++;
					}
				}
			}
			return num;
		}

		private static int MoveContainerItemSafelyToPlayer(Inventory playerInventory, Inventory containerInventory, ItemData source, List<Vector2i> emptySlots, HashSet<Vector2i> allowedSlots)
		{
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			HashSet<Vector2i> allowedSlots2 = allowedSlots;
			ItemData source2 = source;
			int num = 0;
			if (CanMergeForSafeMove(source2))
			{
				foreach (ItemData item in (from target in playerInventory.m_inventory
					where target?.m_shared != null && allowedSlots2.Contains(target.m_gridPos) && CanMergeForSafeMove(target) && HasSameStackIdentity(target, source2) && target.m_stack < target.m_shared.m_maxStackSize
					orderby target.m_gridPos.y, target.m_gridPos.x
					select target).ToList())
				{
					if (!containerInventory.m_inventory.Contains(source2) || source2.m_stack <= 0)
					{
						break;
					}
					int num2 = Math.Min(item.m_shared.m_maxStackSize - item.m_stack, source2.m_stack);
					if (num2 > 0)
					{
						int stack = source2.m_stack;
						bool moveSucceeded = playerInventory.MoveItemToThis(containerInventory, source2, num2, item.m_gridPos.x, item.m_gridPos.y);
						num += CountMovedFromContainerSource(containerInventory, source2, stack, num2, moveSucceeded);
					}
				}
			}
			while (containerInventory.m_inventory.Contains(source2) && source2.m_stack > 0 && emptySlots.Count > 0)
			{
				Vector2i val = emptySlots[0];
				emptySlots.RemoveAt(0);
				int stack2 = source2.m_stack;
				int stack3 = source2.m_stack;
				bool moveSucceeded2 = playerInventory.MoveItemToThis(containerInventory, source2, stack3, val.x, val.y);
				int num3 = CountMovedFromContainerSource(containerInventory, source2, stack2, stack3, moveSucceeded2);
				num += num3;
				if (num3 == 0)
				{
					break;
				}
			}
			return num;
		}

		private static bool CanMergeForSafeMove(ItemData item)
		{
			if (item?.m_shared != null && item.m_shared.m_maxStackSize > 1)
			{
				return CanUseContainerActionStacking(item);
			}
			return false;
		}

		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)
		{
			Player localPlayer2 = localPlayer;
			Inventory playerInventory2 = playerInventory;
			List<ItemData> candidates = playerInventory2.m_inventory.Where((ItemData item) => ShouldQuickStackItem(localPlayer2, playerInventory2, 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 = RunContainerTransferAcrossContainers(localPlayer2, container, includeArea, areaForQuickStack: true, (Container targetContainer) => QuickStackItemsIntoContainer(playerInventory2, targetContainer.m_inventory, candidates), delegate
			{
				playerInventory2.Changed();
			});
			ShowActionResult(localPlayer2, LocalizeUi("$inventoryslots_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();
			}
			ShowActionResult(localPlayer, LocalizeUi("$inventoryslots_action_place_all", "Place All"), num);
		}

		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)
		{
			Player localPlayer2 = localPlayer;
			Inventory playerInventory2 = playerInventory;
			if (!((Object)(object)localPlayer2 == (Object)null) && playerInventory2 != null && !((Object)(object)container == (Object)null) && container.m_inventory != null)
			{
				bool includeArea = mode == RestockMode.AreaFavoriteRestock;
				List<ItemData> targets = playerInventory2.m_inventory.Where((ItemData item) => ShouldTakeStacksTarget(localPlayer2, playerInventory2, 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 = RunContainerTransferAcrossContainers(localPlayer2, container, includeArea, areaForQuickStack: false, (Container sourceContainer) => RestockTargetsFromContainer(playerInventory2, sourceContainer.m_inventory, targets, mode), delegate
				{
					playerInventory2.Changed();
				});
				ShowActionResult(localPlayer2, LocalizeUi("$inventoryslots_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_001f: Unknown result type (might be due to invalid IL or missing references)
			if (item?.m_shared == null || !IsPlayerActionCell(inventory, item.m_gridPos, includeHotbar: true) || !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;
		}

		[IteratorStateMachine(typeof(<GetRestockTargetLookupTokens>d__101))]
		private static IEnumerable<string?> GetRestockTargetLookupTokens(ItemData item)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <GetRestockTargetLookupTokens>d__101(-2)
			{
				<>3__item = item
			};
		}

		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))
			{
				Container currentContainer = InventoryGui.instance.m_currentContainer;
				if ((Object)(object)currentContainer == (Object)null || currentContainer.m_inventory == null)
				{
					ShowActionResult(player, LocalizeUi("$inventoryslots_action_container", "Container"), 0);
					return;
				}
				if (!CanMutateContainerDirectly(currentContainer, allowLocalWithoutZNetView: true))
				{
					((Character)player).Message((MessageType)2, LocalizeUi("$inventoryslots_container_not_ready", "Container is not ready."), 0, (Sprite)null);
					return;
				}
				int moved = SortContainerInventory(currentContainer);
				ShowActionResult(player, LocalizeUi("$inventoryslots_action_sort", "Sort"), moved);
			}
		}

		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)
		{
			Player player2 = player;
			if ((Object)(object)player2 == (Object)null || player2.m_isLoading)
			{
				return;
			}
			Inventory inventory = GetPlayerInventory(player2);
			if (inventory != null)
			{
				List<Vector2i> playerActionSlots = GetPlayerActionSlots(player2, 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);
				}
				int moved = SortInventoryInternal(inventory, playerActionSlots, (ItemData item) => item?.m_shared != null && allowedSet.Contains(item.m_gridPos) && !IsFavoriteProtected(player2, inventory, item));
				ShowActionResult(player2, LocalizeUi("$inventoryslots_action_sort_inventory", "Sort Inv"), moved);
			}
		}

		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 i = 0; i < num2; i++)
			{
				if (list[i].m_gridPos != allowedSlots[i])
				{
					num++;
					flag = true;
					list[i].m_gridPos = allowedSlots[i];
				}
			}
			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)
		{
			object obj;
			if (item == null)
			{
				obj = null;
			}
			else
			{
				SharedData shared = item.m_shared;
				obj = ((shared != null) ? ((object)(ItemType)(ref shared.m_itemType)).ToString() : null);
			}
			if (obj == null)
			{
				obj = "";
			}
			switch ((string)obj)
			{
			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)
			{
				ShowActionResult(player, LocalizeUi("$inventoryslots_action_container", "Container"), 0);
				return false;
			}
			if (!CanMutateContainerDirectly(currentContainer, allowLocalWithoutZNetView: true))
			{
				((Character)player).Message((MessageType)2, LocalizeUi("$inventoryslots_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 < Mathf.Clamp(_containerHoverHoldDuration.Value, 0.1f, 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))
			{
				return null;
			}
			return hoveredContainer;
		}

		private static Container? TryGetHoverRestockContext(Player player)
		{
			Container hoveredContainer = GetHoveredContainer(player);
			if ((Object)(object)hoveredContainer == (Object)null || !CanHandleContainerAction(player, hoveredContainer))
			{
				return null;
			}
			return hoveredContainer;
		}

		private static bool TryQuickStackFromHoveredContainer(Player player, Container container)
		{
			Inventory playerInventory = GetPlayerInventory(player);
			if (playerInventory == null || !CanHandleContainerAction(player, container))
			{
				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))
			{
				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);
			}
			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))
			{
				string containerRestockKeyDisplayText = GetContainerRestockKeyDisplayText();
				if (!string.IsNullOrWhiteSpace(containerRestockKeyDisplayText))
				{
					text = text + "\n[<color=yellow><b>" + containerRestockKeyDisplayText + "</b></color>] (" + LocalizeUi("$inventoryslots_hold_to_restock", "Hold to restock") + ")";
				}
			}
		}

		internal static void RegisterContainer(Container container)
		{
			if ((Object)(object)container != (Object)null && !Runtime.KnownContainers.Contains(container))
			{
				Runtime.KnownContainers.Add(container);
			}
		}

		internal static void UnregisterContainer(Container container)
		{
			if ((Object)(object)container != (Object)null)
			{
				Runtime.KnownContainers.Remove(container);
			}
		}

		private static int RunContainerTransferAcrossContainers(Player localPlayer, Container anchorContainer, bool includeArea, bool areaForQuickStack, Func<Container, int> transfer, Action onMoved)
		{
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)anchorContainer == (Object)null || transfer == null)
			{
				return 0;
			}
			IList obj = (includeArea ? ((IList)GetActionContainers(localPlayer, anchorContainer, areaForQuickStack)) : ((IList)new List<Container> { anchorContainer }));
			int num = (includeArea ? GetContainerActionSuccessFxMode() : 0);
			int played = 0;
			int num2 = 0;
			foreach (Container item in (List<Container>)obj)
			{
				if (!((Object)(object)item == (Object)null) && !IsUnityNull((Object?)(object)item) && item.m_inventory != null)
				{
					int num3 = transfer(item);
					if (num3 > 0)
					{
						num2 += num3;
						played = TryPlayChangedContainerActionSuccessFx(localPlayer, item, num, played);
					}
				}
			}
			if (num2 > 0)
			{
				onMoved?.Invoke();
				if (num == 1)
				{
					PlayContainerActionSuccessFx(localPlayer, anchorContainer);
				}
			}
			return num2;
		}

		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_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			List<Container> list = new List<Container>();
			HashSet<Container> hashSet = new HashSet<Container>();
			if ((Object)(object)currentContainer != (Object)null && currentContainer.m_inventory != null && 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, 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)
		{
			if ((Object)(object)player != (Object)null && !player.m_isLoading && (Object)(object)container != (Object)null && container.m_inventory != null && CanMutateContainerDirectly(container, allowLocalWithoutZNetView: true))
			{
				return HasContainerPlayerAccess(player, container, flashGuardStone: false);
			}
			return false;
		}

		private static bool IsAreaContainerAllowed(Player player, Container container, Container? currentContainer, Vector3 origin, float rangeSq, out float distanceSq)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			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() || !container.m_nview.IsOwner())
			{
				return false;
			}
			Vector3 val = ((Component)container).transform.position - origin;
			distanceSq = ((Vector3)(ref val)).sqrMagnitude;
			if (distanceSq > rangeSq)
			{
				return false;
			}
			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;
			}
			if ((Object)(object)container.m_piece != (Object)null && !container.m_piece.IsPlacedByPlayer())
			{
				return false;
			}
			if (!IsContainerInUse(container))
			{
				return HasContainerPlayerAccess(player, container, flashGuardStone: true);
			}
			return false;
		}

		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 int GetContainerActionSuccessFxMode()
		{
			return Mathf.Clamp((_containerActionSuccessFxMode == null) ? 1 : _containerActionSuccessFxMode.Value, 0, 12);
		}

		private static float GetContainerActionSuccessFxVolume()
		{
			return Mathf.Clamp01((_containerActionSuccessFxVolume != null) ? _containerActionSuccessFxVolume.Value : 1f);
		}

		private static int TryPlayChangedContainerActionSuccessFx(Player player, Container container, int mode, int played)
		{
			if (mode < 2 || played >= mode)
			{
				return played;
			}
			PlayContainerActionSuccessFx(player, container);
			return played + 1;
		}

		private static void PlayContainerActionSuccessFx(Player player, Container container)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)player == (Object)null) && !IsUnityNull((Object?)(object)player) && !((Object)(object)container == (Object)null) && !IsUnityNull((Object?)(object)container) && !((Object)(object)ZNetScene.instance == (Object)null))
			{
				GameObject prefab = ZNetScene.instance.GetPrefab("fx_HildirChest_Unlock");
				if (!((Object)(object)prefab == (Object)null) && !IsUnityNull((Object?)(object)prefab))
				{
					ApplyContainerActionSuccessFxVolume(Object.Instantiate<GameObject>(prefab, ((Component)container).transform.position, ((Component)container).transform.rotation));
				}
			}
		}

		private static void ApplyContainerActionSuccessFxVolume(GameObject instance)
		{
			float containerActionSuccessFxVolume = GetContainerActionSuccessFxVolume();
			if ((Object)(object)instance == (Object)null || IsUnityNull((Object?)(object)instance) || containerActionSuccessFxVolume >= 0.999f)
			{
				return;
			}
			Component[] componentsInChildren = instance.GetComponentsInChildren<Component>(true);
			foreach (Component val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && !IsUnityNull((Object?)(object)val))
				{
					ScaleSfxComponentVolume(val, containerActionSuccessFxVolume);
				}
			}
		}

		private static void ScaleSfxComponentVolume(Component component, float volumeScale)
		{
			Type type = ((object)component).GetType();
			if (IsUnityAudioSource(type))
			{
				ScaleUnityAudioSourceVolume(component, type, volumeScale);
			}
			else
			{
				if (!IsLikelySfxComponent(type))
				{
					return;
				}
				SfxVolumeMemberCache sfxVolumeMemberCache = GetSfxVolumeMemberCache(type);
				FieldInfo[] fields = sfxVolumeMemberCache.Fields;
				foreach (FieldInfo fieldInfo in fields)
				{
					try
					{
						fieldInfo.SetValue(component, Mathf.Max(0f, (float)fieldInfo.GetValue(component) * volumeScale));
					}
					catch
					{
					}
				}
				PropertyInfo[] properties = sfxVolumeMemberCache.Properties;
				foreach (PropertyInfo propertyInfo in properties)
				{
					try
					{
						propertyInfo.SetValue(component, Mathf.Max(0f, (float)propertyInfo.GetValue(component) * volumeScale));
					}
					catch
					{
					}
				}
			}
		}

		private static SfxVolumeMemberCache GetSfxVolumeMemberCache(Type type)
		{
			if (SfxVolumeMembersByType.TryGetValue(type, out var value))
			{
				return value;
			}
			value = new SfxVolumeMemberCache((from field in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
				where field.FieldType == typeof(float) && IsSfxVolumeMemberName(field.Name) && !IsUnsupportedSfxVolumeMemberName(field.Name)
				select field).ToArray(), (from property in type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
				where property.PropertyType == typeof(float) && property.CanRead && property.CanWrite && property.GetIndexParameters().Length == 0 && IsSfxVolumeMemberName(property.Name) && !IsUnsupportedSfxVolumeMemberName(property.Name)
				select property).ToArray());
			SfxVolumeMembersByType[type] = value;
			return value;
		}

		private static bool IsLikelySfxComponent(Type type)
		{
			string name = type.Name;
			if (name.IndexOf("SFX", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return name.IndexOf("Audio", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return true;
		}

		private static bool IsSfxVolumeMemberName(string name)
		{
			if (name.IndexOf("volume", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return name.IndexOf("vol", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return true;
		}

		private static bool IsUnsupportedSfxVolumeMemberName(string name)
		{
			if (!string.Equals(name, "minVolume", StringComparison.OrdinalIgnoreCase))
			{
				return string.Equals(name, "maxVolume", StringComparison.OrdinalIgnoreCase);
			}
			return true;
		}

		private static bool IsUnityAudioSource(Type type)
		{
			return string.Equals(type.FullName, "UnityEngine.AudioSource", StringComparison.Ordinal);
		}

		private static void ScaleUnityAudioSourceVolume(Component component, Type type, float volumeScale)
		{
			PropertyInfo property = type.GetProperty("volume", BindingFlags.Instance | BindingFlags.Public);
			if (property == null || !property.CanRead || !property.CanWrite)
			{
				return;
			}
			try
			{
				property.SetValue(component, Mathf.Max(0f, (float)property.GetValue(component) * volumeScale));
			}
			catch
			{
			}
		}

		private static int MoveItemToInventoryTopFirst(Inventory sourceInventory, Inventory targetInventory, ItemData source)
		{
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing