Decompiled source of SwmarlyValheimQOL v2.0.15

SwmarlyValheimQOL.dll

Decompiled 2 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Extensions;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: AssemblyCompany("SwmarlyValheimQOL")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("2.0.15.0")]
[assembly: AssemblyInformationalVersion("2.0.15+6c1c2e7b89df8509a7476311d05186b40cfdb110")]
[assembly: AssemblyProduct("SwmarlyValheimQOL")]
[assembly: AssemblyTitle("SwmarlyValheimQOL")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.0.15.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SwmarlyValheimQOL
{
	[HarmonyPatch(typeof(Game), "Start")]
	internal static class CurrencyRpcRegistrationPatch
	{
		[HarmonyPostfix]
		private static void Postfix()
		{
			CurrencyRpc.Register();
		}
	}
	[HarmonyPatch(typeof(ZNet), "Start")]
	internal static class CurrencyZNetRegistrationPatch
	{
		[HarmonyPostfix]
		private static void Postfix()
		{
			CurrencyRpc.Register();
		}
	}
	[HarmonyPatch(typeof(Player), "Update")]
	internal static class CurrencyRpcRetryPatch
	{
		private static void Postfix(Player __instance)
		{
			if (Plugin.IsLocalPlayer(__instance))
			{
				CurrencyRpc.Update();
			}
		}
	}
	internal static class CurrencyRpc
	{
		private sealed class PendingPickup
		{
			internal int RequestId;

			internal DateTime CreatedUtc;

			internal DateTime LastSentUtc;
		}

		private sealed class PendingPurchase
		{
			internal int RequestId;

			internal DateTime CreatedUtc;

			internal string ItemName;

			internal int Price;

			internal int Stack;
		}

		private sealed class CompletedResponse
		{
			internal bool IsPurchase;

			internal int RequestId;

			internal ZDOID DropId;

			internal bool Success;

			internal int Amount;

			internal int Balance;

			internal string ItemName;

			internal DateTime CompletedUtc;
		}

		private const int ProtocolVersion = 2;

		private const int MaxPackageBytes = 32768;

		private const int MaxItemNameLength = 256;

		private const int PickupRequestMessage = 1;

		private const int PurchaseRequestMessage = 2;

		private const int ResponseMessage = 3;

		private static readonly TimeSpan PendingExpiry = TimeSpan.FromSeconds(30.0);

		private static readonly TimeSpan CompletedExpiry = TimeSpan.FromSeconds(30.0);

		private static readonly Dictionary<ZDOID, PendingPickup> PendingPickups = new Dictionary<ZDOID, PendingPickup>();

		private static PendingPurchase PendingPurchaseRequest;

		private static readonly Dictionary<string, CompletedResponse> CompletedResponses = new Dictionary<string, CompletedResponse>();

		private static readonly object Sync = new object();

		private const string CurrencyRpcName = "SwmarlyValheimQOL.Currency";

		private static ZRoutedRpc RegisteredRoutedRpc;

		private static ZRoutedRpc FailedRoutedRpc;

		internal static bool IsReady => RegisteredRoutedRpc == ZRoutedRpc.instance;

		internal static bool Register()
		{
			ZRoutedRpc instance = ZRoutedRpc.instance;
			if (instance == null)
			{
				return false;
			}
			if (RegisteredRoutedRpc == instance)
			{
				return true;
			}
			try
			{
				instance.Register<ZPackage>("SwmarlyValheimQOL.Currency", (Action<long, ZPackage>)ReceiveRouted);
				RegisteredRoutedRpc = instance;
				FailedRoutedRpc = null;
				return true;
			}
			catch (Exception ex)
			{
				RegisteredRoutedRpc = null;
				if (FailedRoutedRpc != instance)
				{
					FailedRoutedRpc = instance;
					Plugin.LogWarning("Currency RPC registration failed; coin pickup will remain safely on the ground until it is available: " + ex.Message);
				}
				return false;
			}
		}

		internal static void Reset()
		{
			lock (Sync)
			{
				PendingPickups.Clear();
				PendingPurchaseRequest = null;
				CompletedResponses.Clear();
				RegisteredRoutedRpc = null;
				FailedRoutedRpc = null;
			}
		}

		internal static bool TryRequestPickup(ItemDrop drop)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Expected O, but got Unknown
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			if (!Register() || (Object)(object)drop == (Object)null || (Object)(object)drop.m_nview == (Object)null || !drop.m_nview.IsValid() || drop.m_nview.GetZDO() == null || ZRoutedRpc.instance == null || (Object)(object)ZNet.instance == (Object)null)
			{
				return false;
			}
			DateTime utcNow = DateTime.UtcNow;
			ZDOID uid = drop.m_nview.GetZDO().m_uid;
			bool flag = false;
			int num;
			lock (Sync)
			{
				PrunePending(utcNow);
				if (PendingPickups.TryGetValue(uid, out var value))
				{
					num = value.RequestId;
					if (utcNow - value.LastSentUtc >= TimeSpan.FromSeconds(1.0))
					{
						value.LastSentUtc = utcNow;
						flag = true;
					}
				}
				else
				{
					num = ContainerPatch.NextRequestId();
					PendingPickups[uid] = new PendingPickup
					{
						RequestId = num,
						CreatedUtc = utcNow,
						LastSentUtc = utcNow
					};
					flag = true;
				}
			}
			if (!flag)
			{
				return true;
			}
			ZPackage val = new ZPackage();
			val.Write(2);
			val.Write(1);
			val.Write(num);
			val.Write(uid);
			if (SendToServer(val))
			{
				return true;
			}
			lock (Sync)
			{
				if (PendingPickups.TryGetValue(uid, out var value2) && value2.RequestId == num)
				{
					PendingPickups.Remove(uid);
				}
			}
			return false;
		}

		internal static void Update()
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Expected O, but got Unknown
			if (!Register() || ZRoutedRpc.instance == null || (Object)(object)ZNet.instance == (Object)null)
			{
				return;
			}
			DateTime utcNow = DateTime.UtcNow;
			List<KeyValuePair<ZDOID, int>> list = new List<KeyValuePair<ZDOID, int>>();
			lock (Sync)
			{
				PrunePending(utcNow);
				foreach (KeyValuePair<ZDOID, PendingPickup> pendingPickup in PendingPickups)
				{
					if (!(utcNow - pendingPickup.Value.LastSentUtc < TimeSpan.FromSeconds(1.0)))
					{
						pendingPickup.Value.LastSentUtc = utcNow;
						list.Add(new KeyValuePair<ZDOID, int>(pendingPickup.Key, pendingPickup.Value.RequestId));
					}
				}
			}
			foreach (KeyValuePair<ZDOID, int> item in list)
			{
				ZPackage val = new ZPackage();
				val.Write(2);
				val.Write(1);
				val.Write(item.Value);
				val.Write(item.Key);
				SendToServer(val);
			}
		}

		internal static bool TryRequestPurchase(TradeItem item)
		{
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Expected O, but got Unknown
			if (!Register() || item == null || (Object)(object)item.m_prefab == (Object)null || string.IsNullOrEmpty(((Object)item.m_prefab).name) || ((Object)item.m_prefab).name.Length > 256 || item.m_price <= 0 || item.m_stack <= 0 || ZRoutedRpc.instance == null || (Object)(object)ZNet.instance == (Object)null)
			{
				return false;
			}
			DateTime utcNow = DateTime.UtcNow;
			int num;
			lock (Sync)
			{
				PrunePending(utcNow);
				if (PendingPurchaseRequest != null && PendingPurchaseRequest.ItemName == ((Object)item.m_prefab).name && PendingPurchaseRequest.Price == item.m_price && PendingPurchaseRequest.Stack == item.m_stack)
				{
					num = PendingPurchaseRequest.RequestId;
					PendingPurchaseRequest.CreatedUtc = utcNow;
				}
				else
				{
					num = ContainerPatch.NextRequestId();
					PendingPurchaseRequest = new PendingPurchase
					{
						RequestId = num,
						CreatedUtc = utcNow,
						ItemName = ((Object)item.m_prefab).name,
						Price = item.m_price,
						Stack = item.m_stack
					};
				}
			}
			ZPackage val = new ZPackage();
			val.Write(2);
			val.Write(2);
			val.Write(num);
			val.Write(((Object)item.m_prefab).name);
			val.Write(item.m_price);
			val.Write(item.m_stack);
			if (SendToServer(val))
			{
				return true;
			}
			lock (Sync)
			{
				if (PendingPurchaseRequest != null && PendingPurchaseRequest.RequestId == num)
				{
					PendingPurchaseRequest = null;
				}
			}
			return false;
		}

		private static bool SendToServer(ZPackage package)
		{
			try
			{
				if (RegisteredRoutedRpc != ZRoutedRpc.instance || ZRoutedRpc.instance == null)
				{
					return false;
				}
				ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), "SwmarlyValheimQOL.Currency", new object[1] { package });
				return true;
			}
			catch (Exception ex)
			{
				Plugin.LogWarning("Currency request could not be sent: " + ex.Message);
				return false;
			}
		}

		private static void ReceiveRouted(long sender, ZPackage package)
		{
			if (!IsSafePackage(package))
			{
				return;
			}
			int pos = package.GetPos();
			try
			{
				package.SetPos(0);
				if (package.ReadInt() == 2)
				{
					int num = package.ReadInt();
					package.SetPos(0);
					switch (num)
					{
					case 1:
						HandlePickupRequest(sender, package);
						break;
					case 2:
						HandlePurchaseRequest(sender, package);
						break;
					case 3:
						HandleResponse(sender, package);
						break;
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.LogWarning("Currency routed message failed safely: " + ex.Message);
			}
			finally
			{
				package.SetPos(pos);
			}
		}

		private static void HandlePickupRequest(long sender, ZPackage package)
		{
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
			{
				return;
			}
			if (!TryReadPickup(package, out var requestId, out var dropId))
			{
				Respond(sender, purchase: false, requestId, dropId, success: false, 0, 0, null);
				return;
			}
			if (TryGetCompleted(sender, purchase: false, requestId, out var response))
			{
				Respond(sender, response);
				return;
			}
			Player val = ContainerRPCHandler.FindSenderPlayer(sender);
			ItemDrop val2 = FindDrop(dropId);
			bool flag = (Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null && val2.m_itemData?.m_shared != null && val2.m_itemData.m_shared.m_name == "$item_coins" && val2.m_itemData.m_stack > 0 && val2.m_itemData.m_stack <= 99999 && Vector3.SqrMagnitude(((Component)val).transform.position - ((Component)val2).transform.position) <= 16f;
			int amount = (flag ? val2.m_itemData.m_stack : 0);
			int num = ((!((Object)(object)val == (Object)null)) ? Plugin.GetPocketCoins(val) : 0);
			if (flag)
			{
				ZNetView nview = val2.m_nview;
				ZDO val3 = ((nview != null) ? nview.GetZDO() : null);
				int result;
				if (val3 == null || val3.GetBool("SwmarlyValheimQOL_CoinDropConsumed", false))
				{
					flag = false;
					amount = 0;
				}
				else if (!QolCore.TryAddCoins(num, amount, out result) || val.m_customData == null || (Object)(object)ZNetScene.instance == (Object)null)
				{
					flag = false;
					amount = 0;
				}
				else
				{
					int coins = num;
					Plugin.SetPocketCoins(val, result);
					if (Plugin.GetPocketCoins(val) != result)
					{
						Plugin.SetPocketCoins(val, coins);
						flag = false;
						amount = 0;
					}
					else
					{
						try
						{
							val3.Set("SwmarlyValheimQOL_CoinDropConsumed", true);
							ZNetScene.instance.Destroy(((Component)val2).gameObject);
							num = result;
						}
						catch (Exception ex)
						{
							val3.Set("SwmarlyValheimQOL_CoinDropConsumed", false);
							Plugin.SetPocketCoins(val, coins);
							flag = false;
							amount = 0;
							Plugin.LogWarning("Currency pickup rollback completed after the coin drop could not be destroyed: " + ex.Message);
						}
					}
				}
			}
			RespondAndCache(sender, new CompletedResponse
			{
				IsPurchase = false,
				RequestId = requestId,
				DropId = dropId,
				Success = flag,
				Amount = amount,
				Balance = num,
				CompletedUtc = DateTime.UtcNow
			});
		}

		private static void HandlePurchaseRequest(long sender, ZPackage package)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
			{
				return;
			}
			if (!TryReadPurchase(package, out var requestId, out var itemName, out var price, out var stack))
			{
				Respond(sender, purchase: true, requestId, default(ZDOID), success: false, 0, 0, null);
				return;
			}
			if (TryGetCompleted(sender, purchase: true, requestId, out var response))
			{
				Respond(sender, response);
				return;
			}
			Player val = ContainerRPCHandler.FindSenderPlayer(sender);
			Trader trader = null;
			TradeItem trade = null;
			bool num = (Object)(object)val != (Object)null && TryFindTrade(val, itemName, price, stack, out trader, out trade);
			Inventory val2 = ((val != null) ? ((Humanoid)val).GetInventory() : null);
			int num2 = ((!((Object)(object)val == (Object)null)) ? Plugin.GetPocketCoins(val) : 0);
			int num3 = ((val2 != null) ? val2.CountItems("$item_coins", -1, true) : 0);
			object obj;
			if (trade == null)
			{
				obj = null;
			}
			else
			{
				ItemDrop prefab = trade.m_prefab;
				obj = ((prefab != null) ? ((Component)prefab).GetComponent<ItemDrop>() : null);
			}
			ItemDrop val3 = (ItemDrop)obj;
			string text = val3?.m_itemData?.m_shared?.m_name;
			bool flag = num && val2 != null && (Object)(object)trade?.m_prefab != (Object)null && val3?.m_itemData?.m_shared != null && !string.IsNullOrEmpty(text) && price > 0 && stack > 0 && QolCore.AddCoins(num3, num2) >= price && val2.CanAddItem(((Component)val3).gameObject, stack);
			if (flag)
			{
				int num4 = Math.Min(num3, price);
				int amount = price - num4;
				int num5 = RemoveCoinsFromInventory(val2, num4);
				flag = num5 == num4;
				if (flag)
				{
					int num6 = val2.CountItems(text, -1, true);
					ItemData obj2 = val2.AddItem(((Object)trade.m_prefab).name, stack, trade.m_prefab.m_itemData.m_quality, trade.m_prefab.m_itemData.m_variant, 0L, string.Empty, new Vector2i(-1, -1), false, false, true);
					int num7 = Math.Max(0, val2.CountItems(text, -1, true) - num6);
					flag = obj2 != null && num7 == stack;
					if (flag)
					{
						num2 = QolCore.RemoveCoins(num2, amount);
						Plugin.SetPocketCoins(val, num2);
						try
						{
							trader.OnBought(trade);
						}
						catch (Exception ex)
						{
							Plugin.LogWarning("Currency purchase completed but Trader.OnBought failed: " + ex.Message);
						}
					}
					else
					{
						if (num7 > 0)
						{
							val2.RemoveItem(text, num7, -1, true);
						}
						RestoreCurrency(val, val2, num5, num2);
					}
				}
				else
				{
					RestoreCurrency(val, val2, num5, num2);
				}
			}
			if (!flag)
			{
				num2 = ((!((Object)(object)val == (Object)null)) ? Plugin.GetPocketCoins(val) : 0);
			}
			RespondAndCache(sender, new CompletedResponse
			{
				IsPurchase = true,
				RequestId = requestId,
				Success = flag,
				Amount = (flag ? stack : 0),
				Balance = num2,
				ItemName = (flag ? itemName : null),
				CompletedUtc = DateTime.UtcNow
			});
		}

		private static bool TryFindTrade(Player player, string itemName, int price, int stack, out Trader trader, out TradeItem trade)
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			trader = null;
			trade = null;
			if ((Object)(object)player == (Object)null || string.IsNullOrEmpty(itemName) || itemName.Length > 256)
			{
				return false;
			}
			FieldInfo fieldInfo = AccessTools.Field(typeof(Trader), "m_items");
			if (fieldInfo == null)
			{
				Plugin.LogWarning("Currency purchase rejected: Trader.m_items was not found in this Valheim build.");
				return false;
			}
			Trader[] array = Object.FindObjectsOfType<Trader>();
			foreach (Trader val in array)
			{
				if ((Object)(object)val == (Object)null || Vector3.SqrMagnitude(((Component)val).transform.position - ((Component)player).transform.position) > 100f || !(fieldInfo.GetValue(val) is IList list))
				{
					continue;
				}
				foreach (object item in list)
				{
					TradeItem val2 = (TradeItem)((item is TradeItem) ? item : null);
					if (val2 != null && !((Object)(object)val2.m_prefab == (Object)null) && !(((Object)val2.m_prefab).name != itemName) && val2.m_price == price && val2.m_stack == stack)
					{
						trader = val;
						trade = val2;
						return true;
					}
				}
			}
			return false;
		}

		private static int RemoveCoinsFromInventory(Inventory inventory, int amount)
		{
			if (inventory == null || amount <= 0)
			{
				return 0;
			}
			int num = inventory.CountItems("$item_coins", -1, true);
			inventory.RemoveItem("$item_coins", amount, -1, true);
			return Math.Max(0, num - inventory.CountItems("$item_coins", -1, true));
		}

		private static void RestoreCurrency(Player player, Inventory inventory, int inventoryCoins, int originalPocket)
		{
			if (inventory != null && inventoryCoins > 0 && (Object)(object)ObjectDB.instance != (Object)null)
			{
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("Coins");
				if ((Object)(object)itemPrefab != (Object)null)
				{
					inventory.AddItem(itemPrefab, inventoryCoins);
				}
			}
			if ((Object)(object)player != (Object)null)
			{
				Plugin.SetPocketCoins(player, originalPocket);
			}
		}

		private static ItemDrop FindDrop(ZDOID dropId)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			if (ZDOMan.instance == null || (Object)(object)ZNetScene.instance == (Object)null)
			{
				return null;
			}
			ZDO zDO = ZDOMan.instance.GetZDO(dropId);
			ZNetView val = ((zDO == null) ? null : ZNetScene.instance.FindInstance(zDO));
			object obj;
			if (!((Object)(object)val == (Object)null))
			{
				obj = ((Component)val).GetComponent<ItemDrop>();
				if (obj == null)
				{
					return ((Component)val).GetComponentInChildren<ItemDrop>();
				}
			}
			else
			{
				obj = null;
			}
			return (ItemDrop)obj;
		}

		private static bool TryReadPickup(ZPackage package, out int requestId, out ZDOID dropId)
		{
			//IL_0004: 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_003e: Unknown result type (might be due to invalid IL or missing references)
			requestId = 0;
			dropId = default(ZDOID);
			if (!IsSafePackage(package))
			{
				return false;
			}
			try
			{
				if (package.ReadInt() != 2)
				{
					return false;
				}
				if (package.ReadInt() != 1)
				{
					return false;
				}
				requestId = package.ReadInt();
				dropId = package.ReadZDOID();
				return QolCore.IsValidOperationId(requestId);
			}
			catch
			{
				return false;
			}
		}

		private static bool TryReadPurchase(ZPackage package, out int requestId, out string itemName, out int price, out int stack)
		{
			requestId = 0;
			itemName = null;
			price = 0;
			stack = 0;
			if (!IsSafePackage(package))
			{
				return false;
			}
			try
			{
				if (package.ReadInt() != 2)
				{
					return false;
				}
				if (package.ReadInt() != 2)
				{
					return false;
				}
				requestId = package.ReadInt();
				itemName = package.ReadString();
				price = package.ReadInt();
				stack = package.ReadInt();
				return QolCore.IsValidOperationId(requestId) && !string.IsNullOrEmpty(itemName) && itemName.Length <= 256;
			}
			catch
			{
				return false;
			}
		}

		private static bool IsSafePackage(ZPackage package)
		{
			if (package != null && package.GetArray() != null)
			{
				return package.GetArray().Length <= 32768;
			}
			return false;
		}

		private static bool TryGetCompleted(long sender, bool purchase, int requestId, out CompletedResponse response)
		{
			lock (Sync)
			{
				PruneCompleted(DateTime.UtcNow);
				string completedKey = GetCompletedKey(sender, purchase, requestId);
				if (CompletedResponses.TryGetValue(completedKey, out response))
				{
					return true;
				}
			}
			response = null;
			return false;
		}

		private static void RespondAndCache(long sender, CompletedResponse response)
		{
			lock (Sync)
			{
				PruneCompleted(DateTime.UtcNow);
				CompletedResponses[GetCompletedKey(sender, response.IsPurchase, response.RequestId)] = response;
			}
			Respond(sender, response);
		}

		private static string GetCompletedKey(long sender, bool purchase, int requestId)
		{
			return sender + ":" + (purchase ? "purchase" : "pickup") + ":" + requestId;
		}

		private static void PruneCompleted(DateTime now)
		{
			foreach (string item in new List<string>(CompletedResponses.Keys))
			{
				if (QolCore.IsExpired(now, CompletedResponses[item].CompletedUtc, CompletedExpiry))
				{
					CompletedResponses.Remove(item);
				}
			}
		}

		private static void PrunePending(DateTime now)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			foreach (ZDOID item in new List<ZDOID>(PendingPickups.Keys))
			{
				if (PendingPickups.TryGetValue(item, out var value) && QolCore.IsExpired(now, value.CreatedUtc, PendingExpiry))
				{
					PendingPickups.Remove(item);
				}
			}
			if (PendingPurchaseRequest != null && QolCore.IsExpired(now, PendingPurchaseRequest.CreatedUtc, PendingExpiry))
			{
				PendingPurchaseRequest = null;
			}
		}

		private static void Respond(long sender, bool purchase, int requestId, ZDOID dropId, bool success, int amount, int balance, string itemName)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			Respond(sender, new CompletedResponse
			{
				IsPurchase = purchase,
				RequestId = requestId,
				DropId = dropId,
				Success = success,
				Amount = amount,
				Balance = balance,
				ItemName = itemName,
				CompletedUtc = DateTime.UtcNow
			});
		}

		private static void Respond(long sender, CompletedResponse response)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			if (ZRoutedRpc.instance != null)
			{
				ZPackage val = new ZPackage();
				val.Write(2);
				val.Write(3);
				val.Write(response.IsPurchase);
				val.Write(response.RequestId);
				val.Write(response.DropId);
				val.Write(response.Success);
				val.Write(response.Amount);
				val.Write(response.Balance);
				val.Write(response.ItemName ?? string.Empty);
				if (RegisteredRoutedRpc == ZRoutedRpc.instance)
				{
					ZRoutedRpc.instance.InvokeRoutedRPC(sender, "SwmarlyValheimQOL.Currency", new object[1] { val });
				}
			}
		}

		private static void HandleResponse(long sender, ZPackage package)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			if (!IsTrustedServerResponse(sender) || !IsSafePackage(package))
			{
				return;
			}
			try
			{
				if (package.ReadInt() != 2 || package.ReadInt() != 3)
				{
					return;
				}
				bool flag = package.ReadBool();
				int num = package.ReadInt();
				ZDOID val = package.ReadZDOID();
				bool flag2 = package.ReadBool();
				int num2 = package.ReadInt();
				int num3 = package.ReadInt();
				string text = package.ReadString();
				if (!QolCore.IsValidOperationId(num) || num2 < 0 || num3 < 0 || (text?.Length ?? 0) > 256)
				{
					return;
				}
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer == (Object)null)
				{
					return;
				}
				if (flag)
				{
					lock (Sync)
					{
						if (PendingPurchaseRequest == null || PendingPurchaseRequest.RequestId != num)
						{
							return;
						}
						PendingPurchaseRequest = null;
					}
					if (flag2)
					{
						UpdatePurchaseUi(localPlayer, num3);
					}
					return;
				}
				lock (Sync)
				{
					if (!PendingPickups.TryGetValue(val, out var value) || value.RequestId != num)
					{
						return;
					}
					PendingPickups.Remove(val);
				}
				if (!flag2)
				{
					return;
				}
				Plugin.SetPocketCoins(localPlayer, num3);
				ItemDrop val2 = FindDrop(val);
				if ((Object)(object)val2 != (Object)null && (Object)(object)ZNetScene.instance != (Object)null)
				{
					ZNetScene.instance.Destroy(((Component)val2).gameObject);
				}
				if (num2 > 0 && (Object)(object)ObjectDB.instance != (Object)null)
				{
					GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("Coins");
					ItemDrop val3 = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null);
					if (val3?.m_itemData != null)
					{
						((Character)localPlayer).ShowPickupMessage(val3.m_itemData, num2);
					}
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning("Rejected malformed currency response: " + ex.Message);
			}
		}

		private static void UpdatePurchaseUi(Player player, int balance)
		{
			Plugin.SetPocketCoins(player, balance);
			StoreGui val = Object.FindObjectOfType<StoreGui>();
			MethodInfo methodInfo = AccessTools.Method(typeof(StoreGui), "FillList", (Type[])null, (Type[])null);
			if ((Object)(object)val != (Object)null && methodInfo != null)
			{
				try
				{
					methodInfo.Invoke(val, null);
				}
				catch (Exception ex)
				{
					Plugin.LogWarning("Currency purchase UI refresh failed: " + ex.Message);
				}
			}
			InventoryGui instance = InventoryGui.instance;
			if (instance != null)
			{
				instance.UpdateCraftingPanel(false);
			}
		}

		private static bool IsTrustedServerResponse(long sender)
		{
			if ((Object)(object)ZNet.instance == (Object)null)
			{
				return false;
			}
			if (ZNet.instance.IsServer())
			{
				if (sender != 0L)
				{
					return sender == ZNet.GetUID();
				}
				return true;
			}
			if (ZRoutedRpc.instance != null)
			{
				return sender == ZRoutedRpc.instance.GetServerPeerID();
			}
			return false;
		}
	}
	public class ContainerExtend : MonoBehaviour
	{
		private static readonly ConditionalWeakTable<Inventory, ContainerInventoryOwner> Containers = new ConditionalWeakTable<Inventory, ContainerInventoryOwner>();

		private Container container;

		private Inventory inventory;

		private float nextRegistrationAttempt;

		private void Awake()
		{
			if (((Component)this).TryGetComponent<Container>(ref container))
			{
				TryRegister();
				nextRegistrationAttempt = Time.unscaledTime + 0.25f;
			}
		}

		private void Update()
		{
			if (Object.op_Implicit((Object)(object)container) && (inventory == null || !Containers.TryGetValue(inventory, out var value) || value == null || !((Object)(object)value.Container == (Object)(object)container)) && !(Time.unscaledTime < nextRegistrationAttempt))
			{
				nextRegistrationAttempt = Time.unscaledTime + 0.25f;
				TryRegister();
			}
		}

		private bool TryRegister()
		{
			if (!Object.op_Implicit((Object)(object)container))
			{
				return false;
			}
			Inventory val = container.GetInventory();
			if (val == null)
			{
				return false;
			}
			if (inventory != null && inventory != val)
			{
				Containers.Remove(inventory);
			}
			inventory = val;
			if (Containers.TryGetValue(val, out var value))
			{
				if (value != null && (Object)(object)value.Container == (Object)(object)container)
				{
					return true;
				}
				Containers.Remove(val);
			}
			Containers.Add(val, new ContainerInventoryOwner(container));
			return true;
		}

		private void OnDestroy()
		{
			if (inventory != null)
			{
				Containers.Remove(inventory);
				inventory = null;
			}
		}

		internal static bool EnsureRegistered(Container container)
		{
			if (!Object.op_Implicit((Object)(object)container))
			{
				return false;
			}
			ContainerExtend component = ((Component)container).GetComponent<ContainerExtend>();
			if ((Object)(object)component != (Object)null)
			{
				return component.TryRegister();
			}
			return false;
		}

		public static bool GetContainer(Inventory inventory, out ContainerInventoryOwner container)
		{
			if (inventory == null)
			{
				container = null;
				return false;
			}
			return Containers.TryGetValue(inventory, out container);
		}
	}
	public static class ContainerHandler
	{
		public static RequestChestAdd AddItemToChest(this Container container, ItemData item, Inventory sourceInventory, Vector2i to, ZDOID sender, int dragAmount = -1)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)container) || !Object.op_Implicit((Object)(object)container.m_nview) || !container.m_nview.HasOwner() || sourceInventory == null || item == null)
			{
				return new RequestChestAdd(Vector2i.zero, 0, null, null, null);
			}
			dragAmount = PossibleDragAmount(container.GetInventory(), item, to, dragAmount);
			ItemData itemAt = container.GetInventory().GetItemAt(to.x, to.y);
			bool flag = itemAt != null && dragAmount != item.m_stack && !InventoryHelper.CanStack(itemAt, item);
			if (dragAmount <= 0 || flag || !sourceInventory.ContainsItem(item))
			{
				return new RequestChestAdd(Vector2i.zero, 0, null, null, null);
			}
			RequestChestAdd requestChestAdd = new RequestChestAdd(to, dragAmount, item, sourceInventory, container.GetInventory());
			InventoryBlock.Get(sourceInventory).BlockSlot(item.m_gridPos);
			InventoryPreview.AddPackage(requestChestAdd);
			if (container.m_nview.IsOwner())
			{
				RequestChestAddResponse response = container.GetInventory().RequestItemAdd(requestChestAdd);
				InventoryHandler.RPC_RequestItemAddResponse(sourceInventory, response);
				return null;
			}
			GamePatches.InvokeRPC(container.m_nview, "MUC_RequestItemAdd", requestChestAdd);
			return requestChestAdd;
		}

		internal static int PossibleDragAmount(Inventory inventoryTo, ItemData dragItem, Vector2i to, int dragAmount)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			if (inventoryTo == null || dragItem == null || dragItem.m_shared == null || dragItem.m_stack <= 0)
			{
				return 0;
			}
			dragAmount = ((dragAmount >= 0) ? Mathf.Min(Mathf.Max(0, dragAmount), dragItem.m_stack) : dragItem.m_stack);
			if (to.x >= 0 && to.y >= 0)
			{
				ItemData itemAt = inventoryTo.GetItemAt(to.x, to.y);
				if (itemAt != null && dragAmount < dragItem.m_stack)
				{
					if (InventoryHelper.CanStack(itemAt, dragItem))
					{
						return Mathf.Min(dragAmount, itemAt.m_shared.m_maxStackSize - itemAt.m_stack);
					}
					return 0;
				}
			}
			else if (!inventoryTo.HaveEmptySlot())
			{
				int num = inventoryTo.FindFreeStackSpace(dragItem.m_shared.m_name, (float)dragItem.m_worldLevel);
				return Mathf.Min(dragAmount, num);
			}
			return dragAmount;
		}

		public static RequestChestRemove RemoveItemFromChest(this Container container, ItemData item, Inventory destinationInventory, Vector2i to, ZDOID sender, int dragAmount = -1, ItemData switchItem = null)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)container) || !Object.op_Implicit((Object)(object)container.m_nview) || !container.m_nview.HasOwner() || destinationInventory == null || item == null)
			{
				return new RequestChestRemove(Vector2i.zero, Vector2i.zero, 0, null, Object.op_Implicit((Object)(object)container) ? container.GetInventory() : null, destinationInventory);
			}
			dragAmount = PossibleDragAmount(destinationInventory, item, to, dragAmount);
			if (dragAmount <= 0 || InventoryBlock.Get(destinationInventory).IsSlotBlocked(to))
			{
				return new RequestChestRemove(Vector2i.zero, Vector2i.zero, 0, null, container.GetInventory(), destinationInventory);
			}
			RequestChestRemove requestChestRemove = new RequestChestRemove(item.m_gridPos, to, dragAmount, switchItem, container.GetInventory(), destinationInventory);
			if (switchItem != null && !InventoryHelper.CanStack(item, switchItem) && dragAmount != item.m_stack)
			{
				return new RequestChestRemove(Vector2i.zero, Vector2i.zero, 0, null, container.GetInventory(), destinationInventory);
			}
			InventoryBlock.Get(destinationInventory).BlockSlot(requestChestRemove.toPos);
			InventoryPreview.AddPackage(requestChestRemove);
			if (container.m_nview.IsOwner())
			{
				RequestChestRemoveResponse response = container.GetInventory().RequestItemRemove(requestChestRemove);
				InventoryHandler.RPC_RequestItemRemoveResponse(destinationInventory, response);
				return null;
			}
			GamePatches.InvokeRPC(container.m_nview, "MUC_RequestItemRemove", requestChestRemove);
			return requestChestRemove;
		}

		public static void MoveItemInChest(this Container container, ItemData item, Vector2i toPos, int dragAmount)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)container) && Object.op_Implicit((Object)(object)container.m_nview) && item != null && dragAmount > 0)
			{
				RequestMove package = new RequestMove(item, toPos, dragAmount, container.GetInventory());
				InventoryPreview.AddPackage(package);
				GamePatches.InvokeRPC(container.m_nview, "MUC_RequestItemMove", package);
			}
		}
	}
	public static class ContainerRPCHandler
	{
		private sealed class CompletedRequest
		{
			public IResponse Response;

			public DateTime CompletedUtc;
		}

		private static readonly Dictionary<string, CompletedRequest> CompletedRequests = new Dictionary<string, CompletedRequest>();

		private static readonly object CompletedSync = new object();

		private static readonly TimeSpan CompletedExpiry = TimeSpan.FromSeconds(30.0);

		public static void RPC_RequestItemAdd(long sender, ZDOID containerId, ZPackage package)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			TryHandle(sender, containerId, package, "MUC_RequestItemAddResponse", (ZPackage p) => new RequestChestAdd(p), RequestItemAdd);
		}

		public static void RPC_RequestItemRemove(long sender, ZDOID containerId, ZPackage package)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			TryHandle(sender, containerId, package, "MUC_RequestItemRemoveResponse", (ZPackage p) => new RequestChestRemove(p), RequestItemRemove);
		}

		public static void RPC_RequestItemConsume(long sender, ZDOID containerId, ZPackage package)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			TryHandle(sender, containerId, package, "MUC_RequestItemConsumeResponse", (ZPackage p) => new RequestConsume(p), RequestItemConsume);
		}

		public static void RPC_RequestItemMove(long sender, ZDOID containerId, ZPackage package)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			TryHandle(sender, containerId, package, "MUC_RequestItemMoveResponse", (ZPackage p) => new RequestMove(p), RequestItemMove);
		}

		public static void RPC_RequestDrop(long sender, ZDOID containerId, ZPackage package)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			TryHandle(sender, containerId, package, "MUC_RequestItemDropResponse", (ZPackage p) => new RequestDrop(p), RequestDrop);
		}

		private static void TryHandle<TResponse, TInput>(long sender, ZDOID containerId, ZPackage package, string rpcInvoke, Func<ZPackage, TInput> parse, Func<Inventory, TInput, TResponse> message) where TResponse : IResponse, new() where TInput : IPackage
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.QolOwnsMultiUserChests() || !IsSafePackage(package))
			{
				return;
			}
			try
			{
				TInput input = parse(package);
				AttachSender(sender, input);
				HandleRPC(containerId, sender, rpcInvoke, message, input);
			}
			catch (Exception ex)
			{
				Log.LogWarning($"Rejected malformed chest request for {containerId}: {ex.Message}");
				if (ZRoutedRpc.instance != null)
				{
					TResponse val = new TResponse
					{
						SourceID = TryReadRequestId(package)
					};
					ZRoutedRpc.instance.InvokeRoutedRPC(sender, rpcInvoke, new object[2]
					{
						containerId,
						val.WriteToPackage()
					});
				}
			}
		}

		private static int TryReadRequestId(ZPackage package)
		{
			if (package == null)
			{
				return 0;
			}
			int pos = package.GetPos();
			try
			{
				package.SetPos(0);
				if (package.ReadInt() != 2)
				{
					return 0;
				}
				return package.ReadInt();
			}
			catch
			{
				return 0;
			}
			finally
			{
				package.SetPos(pos);
			}
		}

		private static bool IsSafePackage(ZPackage package)
		{
			if (package != null && package.GetArray() != null)
			{
				return package.GetArray().Length <= 131072;
			}
			return false;
		}

		private static void AttachSender<TInput>(long sender, TInput input) where TInput : IPackage
		{
			if (input is IRequest request)
			{
				request.SenderID = sender;
			}
			if (input is RequestConsume requestConsume)
			{
				requestConsume.SenderID = sender;
			}
			if (input is RequestDrop requestDrop)
			{
				requestDrop.SenderID = sender;
			}
		}

		internal static Player FindSenderPlayer(long sender)
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ZNet.instance == (Object)null || (Object)(object)ZNetScene.instance == (Object)null)
			{
				return null;
			}
			if (!ZNet.instance.IsDedicated() && sender == ZNet.GetUID())
			{
				return Player.m_localPlayer;
			}
			foreach (ZNetPeer peer in ZNet.instance.m_peers)
			{
				if (peer != null && peer.m_uid == sender)
				{
					GameObject val = ZNetScene.instance.FindInstance(peer.m_characterID);
					ZNetView val2 = (((Object)(object)val == (Object)null) ? null : val.GetComponent<ZNetView>());
					return Object.op_Implicit((Object)(object)val2) ? ((Component)val2).GetComponent<Player>() : null;
				}
			}
			return null;
		}

		private static bool ValidateSender(long sender, Container container, IPackage input, out Player player)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			player = FindSenderPlayer(sender);
			if ((Object)(object)player == (Object)null || (Object)(object)container == (Object)null || (Object)(object)container.m_nview == (Object)null || !container.m_nview.IsValid() || container.GetInventory() == null || ((Humanoid)player).GetInventory() == null)
			{
				return false;
			}
			if (Vector3.SqrMagnitude(((Component)player).transform.position - ((Component)container).transform.position) > 225f)
			{
				return false;
			}
			if (input is IRequest)
			{
				Inventory inventory = ((Humanoid)player).GetInventory();
				if (input is RequestChestAdd requestChestAdd)
				{
					requestChestAdd.SourceInventory = inventory;
				}
				if (input is RequestChestRemove requestChestRemove)
				{
					requestChestRemove.TargetInventory = inventory;
				}
				if (input is RequestMove requestMove)
				{
					requestMove.SourceInventory = container.GetInventory();
					requestMove.TargetInventory = container.GetInventory();
				}
			}
			if (input is RequestDrop requestDrop)
			{
				requestDrop.sender = ((Character)player).GetZDOID();
			}
			if (input is RequestDrop requestDrop2)
			{
				requestDrop2.ServerPlayer = player;
			}
			return true;
		}

		private static void HandleRPC<TResponse, TInput>(ZDOID containerId, long target, string rpcInvoke, Func<Inventory, TInput, TResponse> message, TInput input) where TResponse : IResponse, new() where TInput : IPackage
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: 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_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || ZDOMan.instance == null || (Object)(object)ZNetScene.instance == (Object)null || ZRoutedRpc.instance == null)
			{
				return;
			}
			int requestId = GetRequestId(input);
			if (requestId != 0 && TryGetCompleted<TResponse>(target, containerId, requestId, out var response))
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(target, rpcInvoke, new object[2]
				{
					containerId,
					response.WriteToPackage()
				});
				return;
			}
			ZDO zDO = ZDOMan.instance.GetZDO(containerId);
			ZNetView val = ((zDO != null) ? ZNetScene.instance.FindInstance(zDO) : null);
			TResponse response2;
			if (!Object.op_Implicit((Object)(object)val))
			{
				response2 = FallbackResponse<TResponse>(input);
			}
			else
			{
				Container componentInChildren = ((Component)val).GetComponentInChildren<Container>();
				if (Object.op_Implicit((Object)(object)componentInChildren) && ValidateSender(target, componentInChildren, input, out var _))
				{
					InventoryPatch.AuthoritativeMutation = true;
					try
					{
						response2 = message(componentInChildren.GetInventory(), input);
					}
					finally
					{
						InventoryPatch.AuthoritativeMutation = false;
					}
				}
				else
				{
					Log.LogWarning($"{input.GetType().Name}: rejected sender {target} or missing Container on {((Object)val).name}");
					response2 = FallbackResponse<TResponse>(input);
				}
			}
			if (requestId != 0)
			{
				CacheCompleted(target, containerId, requestId, response2);
			}
			ZRoutedRpc.instance.InvokeRoutedRPC(target, rpcInvoke, new object[2]
			{
				containerId,
				response2.WriteToPackage()
			});
		}

		private static int GetRequestId(IPackage input)
		{
			if (input is IRequest request)
			{
				return request.RequestID;
			}
			if (input is RequestConsume requestConsume)
			{
				return requestConsume.RequestID;
			}
			if (input is RequestDrop requestDrop)
			{
				return requestDrop.RequestID;
			}
			return 0;
		}

		private unsafe static string GetRequestKey(long sender, ZDOID containerId, int requestId)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			string[] obj = new string[5]
			{
				sender.ToString(),
				":",
				null,
				null,
				null
			};
			ZDOID val = containerId;
			obj[2] = ((object)(*(ZDOID*)(&val))/*cast due to .constrained prefix*/).ToString();
			obj[3] = ":";
			obj[4] = requestId.ToString();
			return string.Concat(obj);
		}

		private static bool TryGetCompleted<TResponse>(long sender, ZDOID containerId, int requestId, out TResponse response) where TResponse : IResponse, new()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			lock (CompletedSync)
			{
				PruneCompleted(DateTime.UtcNow);
				string requestKey = GetRequestKey(sender, containerId, requestId);
				if (CompletedRequests.TryGetValue(requestKey, out var value) && value.Response is TResponse val)
				{
					response = val;
					return true;
				}
			}
			response = default(TResponse);
			return false;
		}

		private static void CacheCompleted<TResponse>(long sender, ZDOID containerId, int requestId, TResponse response) where TResponse : IResponse, new()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			lock (CompletedSync)
			{
				PruneCompleted(DateTime.UtcNow);
				CompletedRequests[GetRequestKey(sender, containerId, requestId)] = new CompletedRequest
				{
					Response = response,
					CompletedUtc = DateTime.UtcNow
				};
			}
		}

		private static void PruneCompleted(DateTime now)
		{
			foreach (string item in new List<string>(CompletedRequests.Keys))
			{
				if (QolCore.IsExpired(now, CompletedRequests[item].CompletedUtc, CompletedExpiry))
				{
					CompletedRequests.Remove(item);
				}
			}
		}

		internal static void ClearCompleted()
		{
			lock (CompletedSync)
			{
				CompletedRequests.Clear();
			}
		}

		private static TResponse FallbackResponse<TResponse>(IPackage input) where TResponse : IResponse, new()
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			TResponse val = new TResponse
			{
				SourceID = GetRequestId(input)
			};
			if (input is RequestChestAdd requestChestAdd && val is RequestChestAddResponse requestChestAddResponse)
			{
				requestChestAddResponse.switchItem = requestChestAdd.dragItem;
				requestChestAddResponse.inventoryPos = requestChestAdd.dragItem?.m_gridPos ?? Vector2i.zero;
			}
			else if (input is RequestChestRemove requestChestRemove && val is RequestChestRemoveResponse requestChestRemoveResponse)
			{
				requestChestRemoveResponse.responseItem = requestChestRemove.switchItem;
			}
			return val;
		}

		public static RequestChestAddResponse RequestItemAdd(this Inventory inventory, RequestChestAdd request)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			if (inventory == null || request == null)
			{
				return new RequestChestAddResponse(0, success: false, Vector2i.zero, 0, null);
			}
			if (request.dragItem == null || request.SourceInventory == null || !ValidateSourceItem(request))
			{
				return new RequestChestAddResponse(request.RequestID, success: false, Vector2i.zero, 0, request.dragItem);
			}
			int stack = request.dragItem.m_stack;
			ItemData itemAt = request.SourceInventory.GetItemAt(request.dragItem.m_gridPos.x, request.dragItem.m_gridPos.y);
			ItemData val = ((itemAt != null) ? itemAt.Clone() : null);
			ItemData itemAt2 = request.SourceInventory.GetItemAt(request.dragItem.m_gridPos.x, request.dragItem.m_gridPos.y);
			if (itemAt2 == null || !request.SourceInventory.RemoveItem(itemAt2, stack))
			{
				return new RequestChestAddResponse(request.RequestID, success: false, request.dragItem.m_gridPos, 0, null);
			}
			RequestChestAddResponse requestChestAddResponse = ((request.toPos.x < 0 || request.toPos.y < 0) ? AddToAnySlot(inventory, request) : AddToSlot(inventory, request));
			int num = (requestChestAddResponse.Success ? Mathf.Max(0, stack - requestChestAddResponse.Amount) : stack);
			if (requestChestAddResponse.Success && requestChestAddResponse.ReturnToSource && requestChestAddResponse.switchItem != null)
			{
				if (!RestoreSource(request.SourceInventory, requestChestAddResponse.switchItem, requestChestAddResponse.switchItem.m_stack))
				{
					DropItemAtOwner(request.SourceInventory, requestChestAddResponse.switchItem, requestChestAddResponse.switchItem.m_stack);
				}
				requestChestAddResponse.ReturnToSource = false;
			}
			if (num > 0 && !RestoreSource(request.SourceInventory, val, num))
			{
				DropItemAtOwner(request.SourceInventory, val, num);
			}
			return requestChestAddResponse;
		}

		private static bool ValidateSourceItem(RequestChestAdd request)
		{
			if (!QolCore.ValidSlot(request.dragItem.m_gridPos.x, request.dragItem.m_gridPos.y, request.SourceInventory.m_width, request.SourceInventory.m_height))
			{
				return false;
			}
			ItemData itemAt = request.SourceInventory.GetItemAt(request.dragItem.m_gridPos.x, request.dragItem.m_gridPos.y);
			if (itemAt == null || itemAt.m_shared == null || request.dragItem.m_shared == null || request.dragItem.m_stack <= 0)
			{
				return false;
			}
			if (request.allowSwitch && request.dragItem.m_stack != itemAt.m_stack)
			{
				return false;
			}
			if (ItemIdentityMatches(itemAt, request.dragItem) && itemAt.m_stack >= request.dragItem.m_stack)
			{
				return QolCore.ValidAmount(request.dragItem.m_stack, itemAt.m_stack, itemAt.m_shared.m_maxStackSize);
			}
			return false;
		}

		private static bool RestoreSource(Inventory sourceInventory, ItemData original, int amount)
		{
			if (sourceInventory == null || original == null || amount <= 0)
			{
				return false;
			}
			original.m_stack = amount;
			return sourceInventory.AddItem(original, amount, original.m_gridPos.x, original.m_gridPos.y, false);
		}

		private static bool DropItemAtOwner(Inventory inventory, ItemData item, int amount)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			if (inventory == null || item == null || amount <= 0)
			{
				return false;
			}
			InventoryOwner owner = InventoryOwner.GetOwner(inventory);
			Transform val = null;
			if (owner is ContainerInventoryOwner containerInventoryOwner)
			{
				Container container = containerInventoryOwner.Container;
				val = ((container != null) ? ((Component)container).transform : null);
			}
			if (owner is HumanoidInventoryOwner humanoidInventoryOwner)
			{
				Humanoid humanoid = humanoidInventoryOwner.Humanoid;
				val = ((humanoid != null) ? ((Component)humanoid).transform : null);
			}
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			ItemDrop val2 = ItemDrop.DropItem(item, amount, val.position + val.forward + val.up, val.rotation);
			if ((Object)(object)val2 == (Object)null)
			{
				return false;
			}
			val2.OnPlayerDrop();
			return true;
		}

		private static RequestChestAddResponse AddToSlot(Inventory inventory, RequestChestAdd request)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: 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)
			if (!CanStack(inventory, request, out var stackSpace, out var removedItem))
			{
				return new RequestChestAddResponse(request.RequestID, success: false, request.dragItem.m_gridPos, 0, request.dragItem);
			}
			bool flag = inventory.AddItemToInventory(request.dragItem, stackSpace, request.toPos);
			if (!flag)
			{
				if (removedItem != null)
				{
					inventory.AddItem(removedItem, removedItem.m_stack, request.toPos.x, request.toPos.y, false);
				}
				stackSpace = 0;
				return new RequestChestAddResponse(request.RequestID, success: false, request.dragItem.m_gridPos, 0, null);
			}
			bool flag2 = removedItem != null;
			if (!flag || stackSpace != request.dragItem.m_stack)
			{
				ItemData val = request.dragItem.Clone();
				val.m_stack = request.dragItem.m_stack - stackSpace;
				removedItem = (flag2 ? removedItem : val);
			}
			if (removedItem != null)
			{
				removedItem.m_gridPos = request.dragItem.m_gridPos;
			}
			return new RequestChestAddResponse(request.RequestID, flag, request.dragItem.m_gridPos, stackSpace, removedItem, flag2);
		}

		private static bool CanStack(Inventory inventory, RequestChestAdd request, out int stackSpace, out ItemData removedItem)
		{
			ItemData itemAt = inventory.GetItemAt(request.toPos.x, request.toPos.y);
			removedItem = null;
			if (itemAt == null)
			{
				stackSpace = request.dragItem.m_stack;
				return true;
			}
			if (InventoryHelper.CanStack(itemAt, request.dragItem))
			{
				stackSpace = Mathf.Min(itemAt.m_shared.m_maxStackSize - itemAt.m_stack, request.dragItem.m_stack);
				return true;
			}
			if (request.allowSwitch)
			{
				inventory.RemoveItem(itemAt, itemAt.m_stack);
				removedItem = itemAt;
				stackSpace = request.dragItem.m_stack;
				return true;
			}
			stackSpace = 0;
			return false;
		}

		private static RequestChestAddResponse AddToAnySlot(Inventory inventory, RequestChestAdd request)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			Inventory val = new Inventory("tmp", (Sprite)null, 1, 1);
			val.AddItem(request.dragItem.Clone(), request.dragItem.m_stack, 0, 0, false);
			inventory.MoveItemToThis(val, val.GetItemAt(0, 0));
			ItemData itemAt = val.GetItemAt(0, 0);
			if (itemAt == null)
			{
				return new RequestChestAddResponse(request.RequestID, success: true, request.dragItem.m_gridPos, request.dragItem.m_stack, null);
			}
			ItemData val2 = request.dragItem.Clone();
			int num = request.dragItem.m_stack - itemAt.m_stack;
			val2.m_stack -= num;
			bool success = itemAt.m_stack != request.dragItem.m_stack;
			return new RequestChestAddResponse(request.RequestID, success, request.dragItem.m_gridPos, num, val2);
		}

		public static RequestChestRemoveResponse RequestItemRemove(this Inventory inventory, RequestChestRemove request)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_032a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_033a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0340: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_036b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0393: Unknown result type (might be due to invalid IL or missing references)
			if (inventory == null || request == null)
			{
				return new RequestChestRemoveResponse(0, success: false, 0, hasSwitched: false, null);
			}
			Vector2i fromPos = request.fromPos;
			int dragAmount = request.dragAmount;
			ItemData itemAt = inventory.GetItemAt(request.fromPos.x, request.fromPos.y);
			if (itemAt == null || request.TargetInventory == null || request.item == null || !ItemIdentityMatches(itemAt, request.item) || !QolCore.ValidSlot(fromPos.x, fromPos.y, inventory.m_width, inventory.m_height) || !QolCore.ValidAmount(dragAmount, itemAt.m_stack, itemAt.m_shared?.m_maxStackSize ?? 0))
			{
				Log.LogDebug("from is null");
				return new RequestChestRemoveResponse(request.RequestID, success: false, 0, hasSwitched: false, null);
			}
			if (!QolCore.ValidSlot(request.toPos.x, request.toPos.y, request.TargetInventory.m_width, request.TargetInventory.m_height))
			{
				return new RequestChestRemoveResponse(request.RequestID, success: false, 0, hasSwitched: false, null);
			}
			ItemData itemAt2 = request.TargetInventory.GetItemAt(request.toPos.x, request.toPos.y);
			if (request.switchItem != null && !ItemsMatch(itemAt2, request.switchItem))
			{
				return new RequestChestRemoveResponse(request.RequestID, success: false, 0, hasSwitched: false, null);
			}
			if (itemAt2 != null && !InventoryHelper.CanStack(itemAt, itemAt2) && request.switchItem == null)
			{
				return new RequestChestRemoveResponse(request.RequestID, success: false, 0, hasSwitched: false, null);
			}
			int num = Mathf.Min(itemAt.m_stack, dragAmount);
			ItemData val = itemAt.Clone();
			val.m_stack = num;
			if (itemAt2 == null || InventoryHelper.CanStack(itemAt, itemAt2))
			{
				if (!inventory.RemoveItem(itemAt, num))
				{
					return new RequestChestRemoveResponse(request.RequestID, success: false, 0, hasSwitched: false, null);
				}
				if (!request.TargetInventory.AddItemToInventory(val, num, request.toPos))
				{
					if (!inventory.AddItemToInventory(itemAt, num, fromPos))
					{
						DropItemAtOwner(inventory, itemAt, num);
					}
					return new RequestChestRemoveResponse(request.RequestID, success: false, 0, hasSwitched: false, null);
				}
				return new RequestChestRemoveResponse(request.RequestID, success: true, num, hasSwitched: false, val, targetApplied: true);
			}
			if (dragAmount != itemAt.m_stack || itemAt2 == null || request.switchItem == null)
			{
				return new RequestChestRemoveResponse(request.RequestID, success: false, 0, hasSwitched: false, null);
			}
			ItemData val2 = itemAt.Clone();
			ItemData val3 = itemAt2.Clone();
			if (!request.TargetInventory.RemoveItem(itemAt2, itemAt2.m_stack) || !inventory.RemoveItem(itemAt, itemAt.m_stack))
			{
				if (request.TargetInventory.GetItemAt(request.toPos.x, request.toPos.y) == null)
				{
					request.TargetInventory.AddItemToInventory(val3, val3.m_stack, request.toPos);
				}
				return new RequestChestRemoveResponse(request.RequestID, success: false, 0, hasSwitched: false, null);
			}
			if (!inventory.AddItemToInventory(val3, val3.m_stack, fromPos))
			{
				if (!inventory.AddItemToInventory(val2, val2.m_stack, fromPos))
				{
					DropItemAtOwner(inventory, val2, val2.m_stack);
				}
				if (!request.TargetInventory.AddItemToInventory(val3, val3.m_stack, request.toPos))
				{
					DropItemAtOwner(request.TargetInventory, val3, val3.m_stack);
				}
				return new RequestChestRemoveResponse(request.RequestID, success: false, 0, hasSwitched: false, null);
			}
			if (!request.TargetInventory.AddItemToInventory(val, num, request.toPos))
			{
				ItemData itemAt3 = inventory.GetItemAt(fromPos.x, fromPos.y);
				if (itemAt3 != null)
				{
					inventory.RemoveItem(itemAt3, itemAt3.m_stack);
				}
				if (!inventory.AddItemToInventory(val2, val2.m_stack, fromPos))
				{
					DropItemAtOwner(inventory, val2, val2.m_stack);
				}
				if (!request.TargetInventory.AddItemToInventory(val3, val3.m_stack, request.toPos))
				{
					DropItemAtOwner(request.TargetInventory, val3, val3.m_stack);
				}
				return new RequestChestRemoveResponse(request.RequestID, success: false, 0, hasSwitched: false, null);
			}
			return new RequestChestRemoveResponse(request.RequestID, success: true, num, hasSwitched: true, val, targetApplied: true);
		}

		private static bool ItemsMatch(ItemData actual, ItemData expected)
		{
			if (actual == null || expected == null || actual.m_shared == null || expected.m_shared == null)
			{
				return false;
			}
			if (ItemIdentityMatches(actual, expected))
			{
				return actual.m_stack == expected.m_stack;
			}
			return false;
		}

		private static bool ItemIdentityMatches(ItemData actual, ItemData expected)
		{
			if (actual == null || expected == null || actual.m_shared == null || expected.m_shared == null)
			{
				return false;
			}
			if (actual.PrefabName() != expected.PrefabName() || actual.m_quality != expected.m_quality || actual.m_variant != expected.m_variant || actual.m_crafterID != expected.m_crafterID || actual.m_crafterName != expected.m_crafterName || actual.m_worldLevel != expected.m_worldLevel || actual.m_pickedUp != expected.m_pickedUp || !Mathf.Approximately(actual.m_durability, expected.m_durability))
			{
				return false;
			}
			if ((actual.m_customData?.Count ?? 0) != (expected.m_customData?.Count ?? 0))
			{
				return false;
			}
			if (actual.m_customData != null)
			{
				foreach (KeyValuePair<string, string> customDatum in actual.m_customData)
				{
					if (customDatum.Key == null || expected.m_customData == null || !expected.m_customData.TryGetValue(customDatum.Key, out var value) || value != customDatum.Value)
					{
						return false;
					}
				}
			}
			return true;
		}

		public static RequestConsumeResponse RequestItemConsume(this Inventory inventory, RequestConsume request)
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Invalid comparison between Unknown and I4
			if (inventory == null || request == null || request.item == null || !QolCore.ValidSlot(request.itemPosX, request.itemPosY, inventory.m_width, inventory.m_height))
			{
				return new RequestConsumeResponse(request?.RequestID ?? 0, null, success: false, 0);
			}
			ItemData itemAt = inventory.GetItemAt(request.itemPosX, request.itemPosY);
			if (itemAt == null || !ItemIdentityMatches(itemAt, request.item) || itemAt.m_shared == null || itemAt.m_stack <= 0 || (int)itemAt.m_shared.m_itemType != 2)
			{
				return new RequestConsumeResponse(request.RequestID, null, success: false, 0);
			}
			inventory.RemoveOneItem(itemAt);
			ItemData val = itemAt.Clone();
			val.m_stack = 1;
			return new RequestConsumeResponse(request.RequestID, val, success: true, 1);
		}

		public static RequestMoveResponse RequestItemMove(this Inventory inventory, RequestMove request)
		{
			//IL_0010: 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_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0059: 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_00e0: Unknown result type (might be due to invalid IL or missing references)
			if (inventory == null || request == null)
			{
				return new RequestMoveResponse(0, success: false, 0);
			}
			Vector2i fromPos = request.fromPos;
			Vector2i toPos = request.toPos;
			int dragAmount = request.dragAmount;
			ItemData itemAt = inventory.GetItemAt(fromPos.x, fromPos.y);
			if (itemAt == null || !QolCore.ValidSlot(fromPos.x, fromPos.y, inventory.m_width, inventory.m_height) || !QolCore.ValidSlot(toPos.x, toPos.y, inventory.m_width, inventory.m_height) || !QolCore.ValidAmount(dragAmount, itemAt.m_stack, itemAt.m_shared?.m_maxStackSize ?? 0))
			{
				return new RequestMoveResponse(request.RequestID, success: false, 0);
			}
			if (request.item == null || !ItemIdentityMatches(itemAt, request.item) || StringExtensionMethods.GetStableHashCode(itemAt.PrefabName()) != request.itemHash)
			{
				return new RequestMoveResponse(request.RequestID, success: false, 0);
			}
			int movedAmount;
			bool success = InventoryHelper.MoveItem(inventory, itemAt, dragAmount, toPos, out movedAmount);
			return new RequestMoveResponse(request.RequestID, success, movedAmount);
		}

		public static RequestDropResponse RequestDrop(this Inventory inventory, RequestDrop request)
		{
			//IL_005d: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: 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)
			if (inventory == null || request == null || request.item == null || request.amount <= 0 || !QolCore.ValidSlot(request.targetContainerSlot.x, request.targetContainerSlot.y, inventory.m_width, inventory.m_height))
			{
				return new RequestDropResponse(request?.RequestID ?? 0, null, (ZDOID)(((??)request?.sender) ?? default(ZDOID)), success: false, 0);
			}
			if ((Object)(object)request.ServerPlayer == (Object)null)
			{
				return new RequestDropResponse(request.RequestID, null, request.sender, success: false, 0);
			}
			ItemData itemAt = inventory.GetItemAt(request.targetContainerSlot.x, request.targetContainerSlot.y);
			if (itemAt == null || !ItemIdentityMatches(itemAt, request.item))
			{
				return new RequestDropResponse(request.RequestID, null, request.sender, success: false, 0);
			}
			if (!QolCore.ValidAmount(request.amount, itemAt.m_stack, itemAt.m_shared?.m_maxStackSize ?? 0))
			{
				return new RequestDropResponse(request.RequestID, null, request.sender, success: false, 0);
			}
			int amount = request.amount;
			ItemData val = itemAt.Clone();
			val.m_stack = amount;
			if (amount == 0 || !inventory.RemoveItem(itemAt, amount))
			{
				return new RequestDropResponse(request.RequestID, null, request.sender, success: false, 0);
			}
			Transform transform = ((Component)request.ServerPlayer).transform;
			ItemDrop val2 = ItemDrop.DropItem(val, amount, transform.position + transform.forward + transform.up, transform.rotation);
			if ((Object)(object)val2 == (Object)null)
			{
				if (!inventory.AddItemToInventory(val, amount, request.targetContainerSlot))
				{
					DropItemAtOwner(inventory, val, amount);
				}
				return new RequestDropResponse(request.RequestID, null, request.sender, success: false, 0);
			}
			val2.OnPlayerDrop();
			if (((Humanoid)request.ServerPlayer).m_dropEffects != null)
			{
				((Humanoid)request.ServerPlayer).m_dropEffects.Create(transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
			}
			return new RequestDropResponse(request.RequestID, null, request.sender, success: true, amount);
		}
	}
	public interface IPackage
	{
		ZPackage WriteToPackage();
	}
	public interface IRequest : IPackage
	{
		int RequestID { get; set; }

		long SenderID { get; set; }

		Inventory SourceInventory { get; }

		Inventory TargetInventory { get; }
	}
	public interface IResponse : IPackage
	{
		int SourceID { get; set; }

		bool Success { get; set; }

		int Amount { get; set; }
	}
	public class RequestChestAdd : IRequest, IPackage
	{
		public readonly Vector2i toPos;

		public readonly ItemData dragItem;

		public readonly bool allowSwitch;

		public int RequestID { get; set; }

		public long SenderID { get; set; }

		public Inventory SourceInventory { get; internal set; }

		public Inventory TargetInventory { get; internal set; }

		public RequestChestAdd(Vector2i toPos, int dragAmount, ItemData dragItem, Inventory sourceInventory, Inventory targetInventory)
		{
			//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)
			this.toPos = toPos;
			if (dragItem != null)
			{
				this.dragItem = dragItem.Clone();
				this.dragItem.m_stack = Mathf.Min(dragAmount, this.dragItem.m_stack);
				allowSwitch = dragAmount == dragItem.m_stack;
			}
			SourceInventory = sourceInventory;
			TargetInventory = targetInventory;
		}

		public RequestChestAdd(ZPackage package)
		{
			//IL_001a: 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)
			ContainerPatch.ReadProtocolVersion(package);
			RequestID = package.ReadInt();
			toPos = package.ReadVector2i();
			dragItem = InventoryHelper.LoadItemFromPackage(package);
			allowSwitch = package.ReadBool();
		}

		public ZPackage WriteToPackage()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			ZPackage val = new ZPackage();
			ContainerPatch.WriteProtocolVersion(val);
			val.Write(RequestID);
			val.Write(toPos);
			InventoryHelper.WriteItemToPackage(dragItem, val);
			val.Write(allowSwitch);
			return val;
		}
	}
	public class RequestChestAddResponse : IPackage, IResponse
	{
		public Vector2i inventoryPos;

		public ItemData switchItem;

		public int SourceID { get; set; }

		public bool Success { get; set; }

		public int Amount { get; set; }

		public bool ReturnToSource { get; set; }

		public RequestChestAddResponse(int sourceID, bool success, Vector2i inventoryPos, int amount, ItemData switchItem)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			SourceID = sourceID;
			Success = success;
			Amount = amount;
			ReturnToSource = false;
			this.inventoryPos = inventoryPos;
			this.switchItem = switchItem.ClampStackSize();
		}

		public RequestChestAddResponse(int sourceID, bool success, Vector2i inventoryPos, int amount, ItemData switchItem, bool returnToSource)
			: this(sourceID, success, inventoryPos, amount, switchItem)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			ReturnToSource = returnToSource;
		}

		public RequestChestAddResponse(ZPackage package)
		{
			//IL_001a: 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)
			ContainerPatch.ReadProtocolVersion(package);
			SourceID = package.ReadInt();
			inventoryPos = package.ReadVector2i();
			Success = package.ReadBool();
			Amount = package.ReadInt();
			ReturnToSource = package.ReadBool();
			switchItem = InventoryHelper.LoadItemFromPackage(package);
		}

		public RequestChestAddResponse()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			SourceID = 0;
			Success = false;
			inventoryPos = new Vector2i(-1, -1);
			Amount = 0;
			ReturnToSource = false;
			switchItem = null;
		}

		public ZPackage WriteToPackage()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			ZPackage val = new ZPackage();
			ContainerPatch.WriteProtocolVersion(val);
			val.Write(SourceID);
			val.Write(inventoryPos);
			val.Write(Success);
			val.Write(Amount);
			val.Write(ReturnToSource);
			InventoryHelper.WriteItemToPackage(switchItem, val);
			return val;
		}
	}
	public class RequestChestRemove : IRequest, IPackage
	{
		public readonly Vector2i fromPos;

		public readonly Vector2i toPos;

		public readonly int dragAmount;

		public readonly ItemData switchItem;

		public readonly ItemData item;

		public int RequestID { get; set; }

		public long SenderID { get; set; }

		public Inventory SourceInventory { get; internal set; }

		public Inventory TargetInventory { get; internal set; }

		public RequestChestRemove(Vector2i fromPos, Vector2i toPos, int dragAmount, ItemData switchItem, Inventory sourceInventory, Inventory targetInventory)
		{
			//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_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: 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)
			this.fromPos = fromPos;
			this.toPos = toPos;
			this.dragAmount = dragAmount;
			this.switchItem = ((switchItem != null) ? switchItem.Clone() : null);
			SourceInventory = sourceInventory;
			TargetInventory = targetInventory;
			object obj;
			if (sourceInventory == null)
			{
				obj = null;
			}
			else
			{
				ItemData itemAt = sourceInventory.GetItemAt(fromPos.x, fromPos.y);
				obj = ((itemAt != null) ? itemAt.Clone() : null);
			}
			item = (ItemData)obj;
		}

		public RequestChestRemove(ZPackage package)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			ContainerPatch.ReadProtocolVersion(package);
			RequestID = package.ReadInt();
			fromPos = package.ReadVector2i();
			toPos = package.ReadVector2i();
			dragAmount = package.ReadInt();
			switchItem = InventoryHelper.LoadItemFromPackage(package);
			item = InventoryHelper.LoadItemFromPackage(package);
		}

		public ZPackage WriteToPackage()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_001a: 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)
			ZPackage val = new ZPackage();
			ContainerPatch.WriteProtocolVersion(val);
			val.Write(RequestID);
			val.Write(fromPos);
			val.Write(toPos);
			val.Write(dragAmount);
			InventoryHelper.WriteItemToPackage(switchItem, val);
			InventoryHelper.WriteItemToPackage(item, val);
			return val;
		}
	}
	public class RequestChestRemoveResponse : IPackage, IResponse
	{
		public ItemData responseItem;

		public bool hasSwitched;

		public int SourceID { get; set; }

		public bool Success { get; set; }

		public int Amount { get; set; }

		public bool TargetApplied { get; set; }

		public RequestChestRemoveResponse(int sourceID, bool success, int amount, bool hasSwitched, ItemData responseItem, bool targetApplied = false)
		{
			SourceID = sourceID;
			Success = success;
			Amount = amount;
			TargetApplied = targetApplied;
			this.hasSwitched = hasSwitched;
			this.responseItem = responseItem.ClampStackSize();
		}

		public RequestChestRemoveResponse(ZPackage package)
		{
			ContainerPatch.ReadProtocolVersion(package);
			SourceID = package.ReadInt();
			Success = package.ReadBool();
			Amount = package.ReadInt();
			TargetApplied = package.ReadBool();
			hasSwitched = package.ReadBool();
			responseItem = InventoryHelper.LoadItemFromPackage(package);
		}

		public RequestChestRemoveResponse()
		{
			Success = false;
			Amount = 0;
			TargetApplied = false;
			hasSwitched = false;
			responseItem = null;
		}

		public ZPackage WriteToPackage()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			ContainerPatch.WriteProtocolVersion(val);
			val.Write(SourceID);
			val.Write(Success);
			val.Write(Amount);
			val.Write(TargetApplied);
			val.Write(hasSwitched);
			InventoryHelper.WriteItemToPackage(responseItem, val);
			return val;
		}
	}
	public class RequestConsume : IPackage
	{
		public readonly int itemPosX;

		public readonly int itemPosY;

		public readonly ItemData item;

		public int RequestID { get; set; }

		public long SenderID { get; set; }

		public RequestConsume(ItemData item)
		{
			RequestID = ContainerPatch.NextRequestId();
			if (item == null)
			{
				itemPosX = -1;
				itemPosY = -1;
				this.item = null;
			}
			else
			{
				itemPosX = item.m_gridPos.x;
				itemPosY = item.m_gridPos.y;
				this.item = item.Clone();
			}
		}

		public RequestConsume(ZPackage package)
		{
			ContainerPatch.ReadProtocolVersion(package);
			RequestID = package.ReadInt();
			itemPosX = package.ReadInt();
			itemPosY = package.ReadInt();
			item = InventoryHelper.LoadItemFromPackage(package);
		}

		public ZPackage WriteToPackage()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			ContainerPatch.WriteProtocolVersion(val);
			val.Write(RequestID);
			val.Write(itemPosX);
			val.Write(itemPosY);
			InventoryHelper.WriteItemToPackage(item, val);
			return val;
		}
	}
	public class RequestConsumeResponse : IPackage, IResponse
	{
		public readonly ItemData item;

		public int SourceID { get; set; }

		public bool Success { get; set; }

		public int Amount { get; set; }

		public RequestConsumeResponse(ZPackage package)
		{
			ContainerPatch.ReadProtocolVersion(package);
			SourceID = package.ReadInt();
			item = InventoryHelper.LoadItemFromPackage(package);
			Success = package.ReadBool();
			Amount = package.ReadInt();
		}

		public RequestConsumeResponse(ItemData item, bool success, int amount)
			: this(0, item, success, amount)
		{
		}

		public RequestConsumeResponse(int sourceID, ItemData item, bool success, int amount)
		{
			SourceID = sourceID;
			this.item = item.ClampStackSize();
			Success = success;
			Amount = amount;
		}

		public RequestConsumeResponse()
		{
			item = null;
		}

		public ZPackage WriteToPackage()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			ContainerPatch.WriteProtocolVersion(val);
			val.Write(SourceID);
			InventoryHelper.WriteItemToPackage(item, val);
			val.Write(Success);
			val.Write(Amount);
			return val;
		}
	}
	public class RequestDrop : IPackage
	{
		public readonly Vector2i targetContainerSlot;

		public readonly int amount;

		public readonly ItemData item;

		public ZDOID sender;

		public int RequestID { get; set; }

		public long SenderID { get; set; }

		internal Player ServerPlayer { get; set; }

		public RequestDrop(Vector2i targetContainerSlot, int amount, ZDOID sender, ItemData item = null)
		{
			//IL_0012: 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)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			RequestID = ContainerPatch.NextRequestId();
			this.targetContainerSlot = targetContainerSlot;
			this.amount = amount;
			this.sender = sender;
			this.item = ((item != null) ? item.Clone() : null);
		}

		public RequestDrop(ZPackage package)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: 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)
			ContainerPatch.ReadProtocolVersion(package);
			RequestID = package.ReadInt();
			targetContainerSlot = package.ReadVector2i();
			amount = package.ReadInt();
			sender = package.ReadZDOID();
			item = InventoryHelper.LoadItemFromPackage(package);
		}

		public ZPackage WriteToPackage()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_001a: 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)
			ZPackage val = new ZPackage();
			ContainerPatch.WriteProtocolVersion(val);
			val.Write(RequestID);
			val.Write(targetContainerSlot);
			val.Write(amount);
			val.Write(sender);
			InventoryHelper.WriteItemToPackage(item, val);
			return val;
		}
	}
	public class RequestDropResponse : IPackage, IResponse
	{
		public readonly ItemData responseItem;

		public readonly ZDOID sender;

		public int SourceID { get; set; }

		public bool Success { get; set; }

		public int Amount { get; set; }

		public RequestDropResponse(ItemData responseItem, ZDOID sender, bool success, int amount)
			: this(0, responseItem, sender, success, amount)
		{
		}//IL_0003: Unknown result type (might be due to invalid IL or missing references)


		public RequestDropResponse(int sourceID, ItemData responseItem, ZDOID sender, bool success, int amount)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			SourceID = sourceID;
			this.responseItem = responseItem.ClampStackSize();
			this.sender = sender;
			Success = success;
			Amount = amount;
		}

		public RequestDropResponse(ZPackage package)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			ContainerPatch.ReadProtocolVersion(package);
			SourceID = package.ReadInt();
			responseItem = InventoryHelper.LoadItemFromPackage(package);
			sender = package.ReadZDOID();
			Success = package.ReadBool();
			Amount = package.ReadInt();
		}

		public RequestDropResponse()
		{
			responseItem = null;
		}

		public ZPackage WriteToPackage()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			ZPackage val = new ZPackage();
			ContainerPatch.WriteProtocolVersion(val);
			val.Write(SourceID);
			InventoryHelper.WriteItemToPackage(responseItem, val);
			val.Write(sender);
			val.Write(Success);
			val.Write(Amount);
			return val;
		}
	}
	public class RequestMove : IRequest, IPackage
	{
		public readonly Vector2i fromPos;

		public readonly Vector2i toPos;

		public readonly int itemHash;

		public readonly int dragAmount;

		public readonly ItemData item;

		public int RequestID { get; set; }

		public long SenderID { get; set; }

		public Inventory SourceInventory { get; internal set; }

		public Inventory TargetInventory { get; internal set; }

		public RequestMove(ItemData itemToMove, Vector2i toPos, int dragAmount, Inventory inventory)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: 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)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if (itemToMove == null)
			{
				Log.LogWarning("Item is null");
				fromPos = new Vector2i(-1, -1);
				this.toPos = new Vector2i(-1, -1);
				itemHash = 0;
				this.dragAmount = 0;
				item = null;
			}
			else
			{
				SourceInventory = inventory;
				TargetInventory = inventory;
				fromPos = itemToMove.m_gridPos;
				this.toPos = toPos;
				itemHash = StringExtensionMethods.GetStableHashCode(itemToMove.PrefabName());
				item = itemToMove.Clone();
				this.dragAmount = dragAmount;
			}
		}

		public RequestMove(ZPackage package)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			ContainerPatch.ReadProtocolVersion(package);
			RequestID = package.ReadInt();
			fromPos = package.ReadVector2i();
			toPos = package.ReadVector2i();
			itemHash = package.ReadInt();
			dragAmount = package.ReadInt();
			item = InventoryHelper.LoadItemFromPackage(package);
		}

		public ZPackage WriteToPackage()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_001a: 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)
			ZPackage val = new ZPackage();
			ContainerPatch.WriteProtocolVersion(val);
			val.Write(RequestID);
			val.Write(fromPos);
			val.Write(toPos);
			val.Write(itemHash);
			val.Write(dragAmount);
			InventoryHelper.WriteItemToPackage(item, val);
			return val;
		}
	}
	public class RequestMoveResponse : IPackage, IResponse
	{
		public int SourceID { get; set; }

		public bool Success { get; set; }

		public int Amount { get; set; }

		public RequestMoveResponse(int sourceID, bool success, int amount)
		{
			SourceID = sourceID;
			Success = success;
			Amount = amount;
		}

		public RequestMoveResponse()
		{
			SourceID = 0;
			Success = false;
			Amount = 0;
		}

		public RequestMoveResponse(ZPackage package)
		{
			ContainerPatch.ReadProtocolVersion(package);
			SourceID = package.ReadInt();
			Success = package.ReadBool();
			Amount = package.ReadInt();
		}

		public ZPackage WriteToPackage()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: 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)
			//IL_0030: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			ContainerPatch.WriteProtocolVersion(val);
			val.Write(SourceID);
			val.Write(Success);
			val.Write(Amount);
			return val;
		}
	}
	public class SlotPreview
	{
		private Inventory originalInventory;

		private Inventory inventory;

		private bool hasChanges;

		public SlotPreview(Inventory inventory)
		{
			originalInventory = inventory;
			this.inventory = InventoryHelper.CopyInventory(inventory);
		}

		public void Add(Vector2i pos, ItemData item, int amount)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			if (item != null && amount != 0)
			{
				ItemData val = item.Clone();
				val.m_stack = amount;
				if (pos.x >= 0 && pos.y >= 0)
				{
					inventory.AddItem(val, amount, pos.x, pos.y, false);
				}
				else
				{
					inventory.AddItem(val);
				}
				hasChanges = true;
			}
		}

		public void Add(Vector2i pos, ItemData item)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			Add(pos, item, item?.m_stack ?? 0);
		}

		public void Remove(Vector2i pos, ItemData item)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			Remove(pos, item, item?.m_stack ?? 0);
		}

		public void Remove(Vector2i pos, ItemData item, int amount)
		{
			//IL_000d: 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)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			if (item != null && amount != 0 && inventory.GetItemAt(pos.x, pos.y) != null)
			{
				inventory.RemoveItem(inventory.GetItemAt(pos.x, pos.y), amount);
				hasChanges = true;
			}
		}

		public bool GetSlot(Vector2i pos, out ItemData item)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			ItemData itemAt = originalInventory.GetItemAt(pos.x, pos.y);
			item = inventory.GetItemAt(pos.x, pos.y);
			if (itemAt == null && item == null)
			{
				return false;
			}
			if (itemAt == null || item == null)
			{
				return true;
			}
			if (!(itemAt.m_shared.m_name != item.m_shared.m_name))
			{
				return itemAt.m_stack != item.m_stack;
			}
			return true;
		}

		public bool HasChanges()
		{
			return hasChanges;
		}
	}
	public static class ConditionalWeakTableExtension
	{
		public static void TryAdd<TKey, TValue>(this ConditionalWeakTable<TKey, TValue> table, TKey key, ConditionalWeakTable<TKey, TValue>.CreateValueCallback createCallback) where TKey : class where TValue : class
		{
			table.GetValue(key, createCallback);
		}
	}
	public static class InventoryHelper
	{
		public delegate void MoveAction(Inventory from, Inventory to);

		private const int MaxCustomDataEntries = 64;

		private const int MaxSerializedStringLength = 4096;

		private static MethodBase memberwiseCloneMethod = AccessTools.Method(typeof(object), "MemberwiseClone", (Type[])null, (Type[])null);

		public static ItemData LoadItemFromPackage(ZPackage pkg)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Expected O, but got Unknown
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			if (pkg == null)
			{
				return null;
			}
			if (!pkg.ReadBool())
			{
				return null;
			}
			string text = pkg.ReadString();
			int num = pkg.ReadInt();
			if (string.IsNullOrEmpty(text) || text.Length > 4096 || num <= 0 || num > 99999)
			{
				throw new InvalidDataException("Item package contains invalid name or stack data.");
			}
			float durability = pkg.ReadSingle();
			Vector2i val = pkg.ReadVector2i();
			int num2 = pkg.ReadInt();
			int num3 = pkg.ReadInt();
			long num4 = pkg.ReadLong();
			string text2 = pkg.ReadString();
			int worldLevel = pkg.ReadInt();
			bool flag = pkg.ReadBool();
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			int num5 = pkg.ReadInt();
			if (num5 < 0 || num5 > 64)
			{
				throw new InvalidDataException("Item package contains too many custom-data entries.");
			}
			for (int i = 0; i < num5; i++)
			{
				string text3 = pkg.ReadString();
				string text4 = pkg.ReadString();
				if (text3 == null || text4 == null || text3.Length > 4096 || text4.Length > 4096)
				{
					throw new InvalidDataException("Item package contains an oversized custom-data value.");
				}
				dictionary[text3] = text4;
			}
			Inventory val2 = new Inventory("tmp", (Sprite)null, Mathf.Max(1, val.x + 1), Mathf.Max(1, val.y + 1));
			ItemData val3 = val2.AddItem(text, num, num2, num3, num4, text2, val, flag, false, true);
			if (val3 != null)
			{
				val3.m_durability = durability;
				val3.m_worldLevel = worldLevel;
				val3.m_customData = dictionary;
			}
			ItemData itemAt = val2.GetItemAt(val.x, val.y);
			if (itemAt != null)
			{
				val2.RemoveItem(itemAt);
			}
			return itemAt;
		}

		public static void WriteItemToPackage(ItemData itemData, ZPackage pkg)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			pkg.Write(itemData != null);
			if (itemData == null)
			{
				return;
			}
			pkg.Write(itemData.PrefabName());
			pkg.Write(itemData.m_stack);
			pkg.Write(itemData.m_durability);
			pkg.Write(itemData.m_gridPos);
			pkg.Write(itemData.m_quality);
			pkg.Write(itemData.m_variant);
			pkg.Write(itemData.m_crafterID);
			pkg.Write(itemData.m_crafterName);
			pkg.Write(itemData.m_worldLevel);
			pkg.Write(itemData.m_pickedUp);
			List<KeyValuePair<string, string>> list = (itemData.m_customData ?? new Dictionary<string, string>()).Where((KeyValuePair<string, string> pair) => pair.Key != null && pair.Value != null && pair.Key.Length <= 4096 && pair.Value.Length <= 4096).Take(64).ToList();
			pkg.Write(list.Count);
			foreach (KeyValuePair<string, string> item in list)
			{
				pkg.Write(item.Key);
				pkg.Write(item.Value);
			}
		}

		public static ItemData ClampStackSize(this ItemData item)
		{
			if (item == null)
			{
				return null;
			}
			if (item.m_shared == null)
			{
				return null;
			}
			object obj;
			if (!((Object)(object)ObjectDB.instance == (Object)null))
			{
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(item.PrefabName());
				obj = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null);
			}
			else
			{
				obj = null;
			}
			ItemDrop val = (ItemDrop)obj;
			if ((Object)(object)val != (Object)null && val.m_itemData?.m_shared != null)
			{
				item.m_stack = Mathf.Clamp(item.m_stack, 0, val.m_itemData.m_shared.m_maxStackSize);
			}
			return item;
		}

		public static string PrefabName(this ItemData item)
		{
			if (item == null)
			{
				return string.Empty;
			}
			if ((Object)(object)item.m_dropPrefab != (Object)null)
			{
				return ((Object)item.m_dropPrefab).name;
			}
			Log.LogWarning("Item missing prefab " + (item.m_shared?.m_name ?? "<unknown>"));
			return item.m_shared?.m_name ?? string.Empty;
		}

		public static bool MoveItem(Inventory inventory, ItemData item, int amount, Vector2i toPos, out int movedAmount)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL