Decompiled source of ChestLink v1.0.0

plugins/ChestLink.dll

Decompiled 2 weeks 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.InteropServices;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using ChestLink.Compatibility;
using ChestLink.Debug;
using ChestLink.Networking;
using ChestLink.SharedChests;
using ChestLink.SharedChests.Patches;
using ChestLink.Storage;
using ChestLink.UI;
using HarmonyLib;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("ChestLink")]
[assembly: AssemblyDescription("Nearby Valheim chests in one linked storage view.")]
[assembly: AssemblyCompany("TeamVibes")]
[assembly: AssemblyProduct("ChestLink")]
[assembly: ComVisible(false)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace ChestLink
{
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("com.chestlinkmod.valheim.chestlink", "ChestLink", "1.0.0")]
	public sealed class ChestLinkPlugin : BaseUnityPlugin
	{
		internal const string MucIgnoreZdoKey = "MUC_Ignore";

		internal const string ExcludeZdoKey = "ChestLink_Exclude";

		private Harmony _harmony;

		internal static ChestLinkPlugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Settings.Init();
			MultiUserChestCompat.Refresh();
			ChestLinkTransactions.Initialize();
			ItemClassificationExporter.Initialize();
			ChestLink.SharedChests.Log.Init(Log);
			_harmony = new Harmony("com.chestlinkmod.valheim.chestlink");
			_harmony.PatchAll();
			Log.LogInfo((object)("ChestLink 1.0.0 loaded. owner-request backend=" + SharedTransfers.Backend + "; bulk coordinator=TransactionsV9; build=release-1.0.0."));
		}

		private void OnDestroy()
		{
			StorageSessionManager.End("plugin destroyed");
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	internal static class Settings
	{
		internal static ConfigEntry<bool> Enabled { get; private set; }

		internal static ConfigEntry<float> DiscoveryRadius { get; private set; }

		internal static ConfigEntry<int> MaxContainers { get; private set; }

		internal static ConfigEntry<int> MaxCombinedSlots { get; private set; }

		internal static ConfigEntry<bool> PreferSameBuilding { get; private set; }

		internal static ConfigEntry<float> StructureJoinTolerance { get; private set; }

		internal static ConfigEntry<float> ChestFloorAttachHeight { get; private set; }

		internal static ConfigEntry<float> ChestStructureAttachDistance { get; private set; }

		internal static ConfigEntry<bool> RequireSameBuildingRoof { get; private set; }

		internal static ConfigEntry<float> BuildingRoofSearchHeight { get; private set; }

		internal static ConfigEntry<bool> ShowContainerDividers { get; private set; }

		internal static ConfigEntry<bool> ShowChestLabels { get; private set; }

		internal static ConfigEntry<bool> ColorCodeChestBorders { get; private set; }

		internal static ConfigEntry<float> ChestBorderThickness { get; private set; }

		internal static ConfigEntry<float> FavoriteBorderOpacity { get; private set; }

		internal static ConfigEntry<float> ScrollRowsPerTick { get; private set; }

		internal static ConfigEntry<string> StorageSortCategoryOrder { get; private set; }

		internal static ConfigEntry<bool> DebugLogging { get; private set; }

		internal static void Init()
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Expected O, but got Unknown
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Expected O, but got Unknown
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Expected O, but got Unknown
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Expected O, but got Unknown
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Expected O, but got Unknown
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Expected O, but got Unknown
			//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Expected O, but got Unknown
			//IL_0316: Unknown result type (might be due to invalid IL or missing references)
			//IL_0320: Expected O, but got Unknown
			//IL_0358: Unknown result type (might be due to invalid IL or missing references)
			//IL_0362: Expected O, but got Unknown
			Enabled = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<bool>("General", "Enabled", true, "Enable ChestLink.");
			DiscoveryRadius = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<float>("Discovery", "Radius", 30f, new ConfigDescription("Fallback radius in meters around the chest you opened. Same-building detection takes priority when the opened chest can be assigned to a structure.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f), Array.Empty<object>()));
			MaxContainers = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<int>("Discovery", "MaxContainers", 64, new ConfigDescription("Maximum linked containers in one session. 0 = unlimited.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 512), Array.Empty<object>()));
			MaxCombinedSlots = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<int>("Discovery", "MaxCombinedSlots", 1000, new ConfigDescription("Maximum real physical chest slots exposed by one linked-storage session. 0 = unlimited.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 10000), Array.Empty<object>()));
			PreferSameBuilding = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<bool>("Discovery", "PreferSameBuilding", true, "Prefer containers attached to the same physically connected structure as the opened chest. If the anchor cannot be assigned to a structure, ChestLink falls back to Radius.");
			StructureJoinTolerance = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<float>("Discovery", "StructureJoinTolerance", 0.35f, new ConfigDescription("Maximum gap in meters between structural build-piece bounds for them to count as physically connected to the same building.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 1.5f), Array.Empty<object>()));
			ChestFloorAttachHeight = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<float>("Discovery", "ChestFloorAttachHeight", 1.25f, new ConfigDescription("Maximum vertical distance in meters from the bottom of a chest to a structural floor directly beneath it when assigning the chest to a building.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 3f), Array.Empty<object>()));
			ChestStructureAttachDistance = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<float>("Discovery", "ChestStructureAttachDistance", 0.45f, new ConfigDescription("Fallback distance in meters for attaching a chest to a nearby structural build piece when no floor attachment is found.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 2f), Array.Empty<object>()));
			RequireSameBuildingRoof = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<bool>("Discovery", "RequireSameBuildingRoof", true, "When same-building discovery is active, require the chest to have a Roof-tagged piece from the same structural cluster above it. This prevents outdoor chests next to a wall/floor from joining the building.");
			BuildingRoofSearchHeight = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<float>("Discovery", "BuildingRoofSearchHeight", 15f, new ConfigDescription("Maximum vertical distance in meters above a chest to search for a same-cluster Roof piece.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 30f), Array.Empty<object>()));
			ShowContainerDividers = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<bool>("UI", "ShowContainerDividers", true, "Show a subtle divider between physical source chests in the future linked-storage grid.");
			ShowChestLabels = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<bool>("UI", "ShowChestLabels", false, "Show a very small chest-name tag on the first visible slot of each physical chest group.");
			ColorCodeChestBorders = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<bool>("UI", "ColorCodeChestBorders", true, "Color physical-chest group borders by vanilla chest material/tier. Unknown or modded containers use the nearest vanilla slot-capacity tier.");
			ChestBorderThickness = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<float>("UI", "ChestBorderThickness", 2f, new ConfigDescription("Thickness of the subtle border drawn around physical chest slot groups.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f), Array.Empty<object>()));
			FavoriteBorderOpacity = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<float>("UI", "FavoriteBorderOpacity", 0.3f, new ConfigDescription("Opacity of the dashed ITEM/SLOT favorite border. 0.30 is intentionally subtle.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 1f), Array.Empty<object>()));
			ScrollRowsPerTick = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<float>("UI", "ScrollRowsPerTick", 1f, new ConfigDescription("How many linked-storage rows one mouse-wheel notch moves. 1 = exactly one row per notch.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f), Array.Empty<object>()));
			StorageSortCategoryOrder = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<string>("Sorting", "CategoryOrder", "RawMeat,VegetablesFruit,CookedMeat,PreparedFood,OvenPrep,FoodIngredients,MeadBase,MeadPotions,Weapons,Armor,Ammo,Tools,UtilityGear,BuildingCrafting,RawMaterials,RefinedMetals,HidesLeather,Seeds,RareMaterials,MouldsCasts,Valuables,Trophies,Misc", "Physical SORT category priority. Manual item overrides live in ChestLink.SortOverrides.cfg beside the main config and always win over automatic classification.");
			if (StorageSortCategoryOrder.Value == "FoodMead,Ammo,Weapons,Armor,Tools,Materials,BuildingCrafting,Valuables,Trophies,Misc")
			{
				StorageSortCategoryOrder.Value = "RawMeat,VegetablesFruit,CookedMeat,PreparedFood,OvenPrep,FoodIngredients,MeadBase,MeadPotions,Weapons,Armor,Ammo,Tools,UtilityGear,BuildingCrafting,RawMaterials,RefinedMetals,HidesLeather,Seeds,RareMaterials,MouldsCasts,Valuables,Trophies,Misc";
			}
			if (StorageSortCategoryOrder.Value == "RawMeat,VegetablesFruit,CookedMeat,PreparedFood,FoodIngredients,MeadPotions,Ammo,Weapons,Armor,Tools,BuildingCrafting,RawMaterials,RefinedMetals,HidesLeather,RareMaterials,Valuables,Trophies,Misc")
			{
				StorageSortCategoryOrder.Value = "RawMeat,VegetablesFruit,CookedMeat,PreparedFood,OvenPrep,FoodIngredients,MeadBase,MeadPotions,Weapons,Armor,Ammo,Tools,UtilityGear,BuildingCrafting,RawMaterials,RefinedMetals,HidesLeather,Seeds,RareMaterials,MouldsCasts,Valuables,Trophies,Misc";
			}
			if (StorageSortCategoryOrder.Value == "RawMeat,VegetablesFruit,Seeds,CookedMeat,PreparedFood,OvenPrep,FoodIngredients,MeadBase,MeadPotions,Ammo,Weapons,Armor,Tools,BuildingCrafting,RawMaterials,RefinedMetals,HidesLeather,RareMaterials,MouldsCasts,Valuables,Trophies,Misc")
			{
				StorageSortCategoryOrder.Value = "RawMeat,VegetablesFruit,CookedMeat,PreparedFood,OvenPrep,FoodIngredients,MeadBase,MeadPotions,Weapons,Armor,Ammo,Tools,UtilityGear,BuildingCrafting,RawMaterials,RefinedMetals,HidesLeather,Seeds,RareMaterials,MouldsCasts,Valuables,Trophies,Misc";
			}
			DebugLogging = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<bool>("Debug", "Logging", false, "Log storage scans and correlated shared request registration, owner routing, quantities, replies and completion. Pending/blocked warnings are rate-limited; failures and session readiness always log.");
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "com.chestlinkmod.valheim.chestlink";

		public const string PLUGIN_NAME = "ChestLink";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace ChestLink.SharedChests
{
	public class HumanoidExtend : MonoBehaviour
	{
		private static readonly ConditionalWeakTable<Inventory, HumanoidInventoryOwner> Humanoids = new ConditionalWeakTable<Inventory, HumanoidInventoryOwner>();

		private Inventory inventory;

		private void Awake()
		{
			UpdateInventory();
		}

		private void Start()
		{
			UpdateInventory();
		}

		private void UpdateInventory()
		{
			Humanoid humanoid = default(Humanoid);
			if (!((Component)this).TryGetComponent<Humanoid>(ref humanoid))
			{
				return;
			}
			inventory = humanoid.GetInventory();
			if (inventory == null)
			{
				return;
			}
			foreach (Inventory inventory in inventory.GetInventories())
			{
				Humanoids.TryAdd(inventory, (Inventory i) => new HumanoidInventoryOwner(humanoid, i));
			}
		}

		private void OnDestroy()
		{
			if (inventory == null)
			{
				return;
			}
			foreach (Inventory inventory in inventory.GetInventories())
			{
				Humanoids.Remove(inventory);
			}
		}

		public static bool GetHumanoid(Inventory inventory, out HumanoidInventoryOwner humanoid)
		{
			return Humanoids.TryGetValue(inventory, out humanoid);
		}
	}
	public static class ContainerRPCHandler
	{
		private static readonly Dictionary<string, byte[]> Replies = new Dictionary<string, byte[]>();

		private static ZNet replySession;

		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)
			HandleRPC(containerId, sender, "ChestLink_Shared_RequestItemAddResponse", RequestItemAdd, new RequestChestAdd(package));
		}

		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)
			HandleRPC(containerId, sender, "ChestLink_Shared_RequestItemRemoveResponse", RequestItemRemove, new RequestChestRemove(package));
		}

		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)
			HandleRPC(containerId, sender, "ChestLink_Shared_RequestItemConsumeResponse", RequestItemConsume, new RequestConsume(package));
		}

		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)
			HandleRPC(containerId, sender, "ChestLink_Shared_RequestItemMoveResponse", RequestItemMove, new RequestMove(package));
		}

		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)
			HandleRPC(containerId, sender, "ChestLink_Shared_RequestItemDropResponse", RequestDrop, new RequestDrop(package));
		}

		private unsafe 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_02c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0410: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Expected O, but got Unknown
			//IL_0439: Unknown result type (might be due to invalid IL or missing references)
			//IL_047f: Unknown result type (might be due to invalid IL or missing references)
			//IL_048a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0490: Expected O, but got Unknown
			if ((Object)(object)replySession != (Object)(object)ZNet.instance)
			{
				Replies.Clear();
				replySession = ZNet.instance;
			}
			IRequest request = input as IRequest;
			string[] obj = new string[7]
			{
				target.ToString(),
				":",
				null,
				null,
				null,
				null,
				null
			};
			ZDOID val = containerId;
			obj[2] = ((object)(*(ZDOID*)(&val))/*cast due to .constrained prefix*/).ToString();
			obj[3] = ":";
			obj[4] = rpcInvoke;
			obj[5] = ":";
			obj[6] = (request?.RequestID).ToString();
			string key = string.Concat(obj);
			if (request == null || request.RequestID <= 0)
			{
				return;
			}
			PackageHandler.Trace(request, "owner-receive", containerId, ZDOMan.GetSessionID(), "requester=" + target + " rpc=" + rpcInvoke);
			if (Replies.TryGetValue(key, out var value))
			{
				PackageHandler.Trace(request, "owner-replay", containerId, ZDOMan.GetSessionID(), "requester=" + target);
				ZRoutedRpc.instance.InvokeRoutedRPC(target, rpcInvoke, new object[2]
				{
					containerId,
					(object)new ZPackage(value)
				});
				return;
			}
			ZDO zDO = ZDOMan.instance.GetZDO(containerId);
			ZNetView val2 = ((zDO != null) ? ZNetScene.instance.FindInstance(zDO) : null);
			bool flag = false;
			TResponse val3;
			if (!Object.op_Implicit((Object)(object)val2) || !val2.IsOwner())
			{
				if (!Object.op_Implicit((Object)(object)val2))
				{
					Log.LogWarning(input.GetType().Name + ": not handling RPC, ZNetView instance is null");
				}
				else if (!val2.IsOwner())
				{
					Log.LogWarning(input.GetType().Name + ": not handling RPC, ZNetView instance is not owner");
				}
				val3 = FallbackResponse<TResponse>(input as IRequest);
			}
			else
			{
				Container componentInChildren = ((Component)val2).GetComponentInChildren<Container>();
				if (Object.op_Implicit((Object)(object)componentInChildren))
				{
					try
					{
						if (!ChestState.Refresh(componentInChildren, "owner-request:" + request.RequestID))
						{
							throw new InvalidOperationException("Chest awaiting synchronization");
						}
						ChestLinkTransactions.BeginSharedEvidence(PackageHandler.JournalId(target, request.RequestID), componentInChildren, requester: false);
						flag = true;
					}
					catch (Exception ex)
					{
						Log.LogError($"[Shared] owner-preflight-rejected utc={DateTime.UtcNow:O} peer={ZDOMan.GetSessionID()} requester={target} request={request.RequestID} chest={containerId} noChestMutation=true: {ex}");
					}
					val3 = (flag ? Execute(componentInChildren.GetInventory(), input, message) : FallbackResponse<TResponse>(request));
					if (flag)
					{
						ChestState.VerifyPersisted(componentInChildren, "owner-reply:" + request.RequestID);
					}
				}
				else
				{
					Log.LogWarning(input.GetType().Name + ": not handling RPC, Container component not found on " + ((Object)val2).name);
					val3 = FallbackResponse<TResponse>(input as IRequest);
				}
			}
			input.PrintDebug();
			val3.PrintDebug();
			val3.SourceID = request.RequestID;
			byte[] array = val3.WriteToPackage().GetArray();
			Replies[key] = array;
			if (flag)
			{
				try
				{
					ChestLinkTransactions.SharedReplyEvidence(PackageHandler.JournalId(target, request.RequestID), array);
				}
				catch (Exception ex2)
				{
					Log.LogError($"[Shared] reply-evidence-failed request={request.RequestID} chest={containerId} requester={target}; outcome retained in memory, journal preserved: {ex2}");
					return;
				}
			}
			PackageHandler.Trace(request, "owner-reply", containerId, ZDOMan.GetSessionID(), $"requester={target} success={val3.Success} bytes={array.Length}");
			ZRoutedRpc.instance.InvokeRoutedRPC(target, rpcInvoke, new object[2]
			{
				containerId,
				(object)new ZPackage(array)
			});
		}

		public unsafe static void ReceiptAck(long sender, ZDOID chest, int requestId)
		{
			//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_006e: Unknown result type (might be due to invalid IL or missing references)
			if (Settings.DebugLogging.Value)
			{
				Log.LogInfo($"[Shared] receipt-ack utc={DateTime.UtcNow:O} peer={ZDOMan.GetSessionID()} requester={sender} request={requestId} chest={chest}");
			}
			if (Replies.Keys.Any(delegate(string k)
			{
				//IL_0012: 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)
				string text = sender.ToString();
				ZDOID val = chest;
				return k.StartsWith(text + ":" + ((object)(*(ZDOID*)(&val))/*cast due to .constrained prefix*/).ToString() + ":", StringComparison.Ordinal) && k.EndsWith(":" + requestId, StringComparison.Ordinal);
			}))
			{
				ChestLinkTransactions.FinishSharedEvidence(PackageHandler.JournalId(sender, requestId));
			}
		}

		internal static TResponse Execute<TResponse, TInput>(Inventory inventory, TInput input, Func<Inventory, TInput, TResponse> action) where TResponse : IResponse, new() where TInput : IPackage
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			int num = inventory.GetAllItems().Sum((ItemData x) => x.m_stack);
			Inventory val = new Inventory("ChestLink transit", (Sprite)null, 1, 1);
			ItemData val2 = ((input is RequestChestAdd requestChestAdd) ? requestChestAdd.dragItem : ((input is RequestChestRemove requestChestRemove) ? requestChestRemove.switchItem : null));
			if (val2 != null)
			{
				ItemData val3 = val2.Clone();
				val3.m_gridPos = Vector2i.zero;
				NetworkInventoryCommit.Items(val).Add(val3);
			}
			try
			{
				using NetworkInventoryCommit networkInventoryCommit = new NetworkInventoryCommit((IEnumerable<Inventory>)(object)new Inventory[2] { inventory, val }, "owner-request");
				NetworkInventoryCommit.Items(val).Clear();
				TResponse val4 = action(inventory, input);
				ItemData val5 = ((val4 is RequestChestAddResponse requestChestAddResponse) ? requestChestAddResponse.switchItem : ((val4 is RequestChestRemoveResponse requestChestRemoveResponse) ? requestChestRemoveResponse.responseItem : ((val4 is RequestConsumeResponse requestConsumeResponse) ? requestConsumeResponse.item : ((val4 is RequestDropResponse requestDropResponse) ? requestDropResponse.responseItem : null))));
				if (val5 != null && val5.m_stack > 0)
				{
					ItemData val6 = val5.Clone();
					val6.m_gridPos = Vector2i.zero;
					NetworkInventoryCommit.Items(val).Add(val6);
				}
				networkInventoryCommit.Validate("owner-request");
				val4.WriteToPackage();
				NetworkInventoryCommit.Serialize(inventory);
				networkInventoryCommit.Accept();
				if (Settings.DebugLogging.Value)
				{
					Log.LogInfo(string.Format("[Shared] owner-executed utc={0:O} peer={1} request={2} type={3} success={4} chestBefore={5} chestAfter={6} returned={7} returnedCount={8}", DateTime.UtcNow, ZDOMan.GetSessionID(), (input as IRequest)?.RequestID, input.GetType().Name, val4.Success, num, inventory.GetAllItems().Sum((ItemData x) => x.m_stack), val5?.m_shared.m_name ?? "none", val5?.m_stack ?? 0));
				}
				return val4;
			}
			catch (Exception ex)
			{
				Log.LogError($"[Shared] owner-rollback peer={ZDOMan.GetSessionID()} request={(input as IRequest)?.RequestID} type={input.GetType().Name}: {ex}");
				return FallbackResponse<TResponse>(input as IRequest);
			}
		}

		private static TResponse FallbackResponse<TResponse>(IRequest request) where TResponse : IResponse, new()
		{
			//IL_0065: 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_006a: Unknown result type (might be due to invalid IL or missing references)
			TResponse val = new TResponse
			{
				SourceID = (request?.RequestID ?? 0)
			};
			if (request is RequestChestAdd requestChestAdd && val is RequestChestAddResponse requestChestAddResponse)
			{
				requestChestAddResponse.switchItem = requestChestAdd.dragItem;
				requestChestAddResponse.inventoryPos = requestChestAdd.dragItem?.m_gridPos ?? Vector2i.zero;
			}
			else if (request is RequestChestRemove requestChestRemove && val is RequestChestRemoveResponse requestChestRemoveResponse)
			{
				requestChestRemoveResponse.responseItem = requestChestRemove.switchItem;
			}
			return val;
		}

		public static RequestChestAddResponse RequestItemAdd(this Inventory inventory, RequestChestAdd request)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			if (request.dragItem == null)
			{
				return new RequestChestAddResponse(request.RequestID, success: false, Vector2i.zero, 0, request.dragItem);
			}
			if (request.toPos.x < 0 || request.toPos.y < 0)
			{
				return AddToAnySlot(inventory, request);
			}
			return AddToSlot(inventory, request);
		}

		private static RequestChestAddResponse AddToSlot(Inventory inventory, RequestChestAdd request)
		{
			//IL_0046: 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_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: 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)
			{
				stackSpace = 0;
			}
			if (!flag || stackSpace != request.dragItem.m_stack)
			{
				removedItem = request.dragItem;
				removedItem.m_stack = request.dragItem.m_stack - stackSpace;
			}
			if (removedItem != null)
			{
				removedItem.m_gridPos = request.dragItem.m_gridPos;
			}
			return new RequestChestAddResponse(request.RequestID, flag, request.dragItem.m_gridPos, stackSpace, removedItem);
		}

		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_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: 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)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			int num = request.dragItem.m_stack;
			List<Vector2i> list = new List<Vector2i>();
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (InventoryHelper.CanStack(allItem, request.dragItem))
				{
					list.Add(allItem.m_gridPos);
				}
			}
			for (int i = 0; i < inventory.GetHeight(); i++)
			{
				for (int j = 0; j < inventory.GetWidth(); j++)
				{
					if (inventory.GetItemAt(j, i) == null)
					{
						list.Add(new Vector2i(j, i));
					}
				}
			}
			foreach (Vector2i item in list)
			{
				ItemData itemAt = inventory.GetItemAt(item.x, item.y);
				int val = ((itemAt == null) ? request.dragItem.m_shared.m_maxStackSize : (itemAt.m_shared.m_maxStackSize - itemAt.m_stack));
				int num2 = Math.Min(num, val);
				if (num2 > 0 && inventory.AddItemToInventory(request.dragItem, num2, item))
				{
					num -= num2;
				}
				if (num == 0)
				{
					break;
				}
			}
			ItemData val2 = ((num == 0) ? null : request.dragItem.Clone());
			if (val2 != null)
			{
				val2.m_stack = num;
			}
			int num3 = request.dragItem.m_stack - num;
			return new RequestChestAddResponse(request.RequestID, num3 > 0, request.dragItem.m_gridPos, num3, val2);
		}

		public static RequestChestRemoveResponse RequestItemRemove(this Inventory inventory, RequestChestRemove request)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			Vector2i fromPos = request.fromPos;
			int dragAmount = request.dragAmount;
			ItemData switchItem = request.switchItem;
			ItemData itemAt = inventory.GetItemAt(request.fromPos.x, request.fromPos.y);
			if (itemAt == null || request.dragAmount <= 0 || request.item == null || NetworkInventoryCommit.Identity(itemAt) != NetworkInventoryCommit.Identity(request.item))
			{
				Log.LogDebug("from is null");
				return new RequestChestRemoveResponse(request.RequestID, success: false, 0, hasSwitched: false, request.switchItem);
			}
			int num = 0;
			bool flag = false;
			bool flag2 = false;
			if (switchItem == null)
			{
				num = Mathf.Min(itemAt.m_stack, dragAmount);
				flag = inventory.RemoveItem(itemAt, num);
			}
			else if (InventoryHelper.CanStack(itemAt, switchItem))
			{
				num = Mathf.Min(switchItem.m_shared.m_maxStackSize - switchItem.m_stack, dragAmount);
				flag = inventory.RemoveItem(itemAt, num);
			}
			else
			{
				if (dragAmount < itemAt.m_stack)
				{
					return new RequestChestRemoveResponse(request.RequestID, success: false, 0, hasSwitched: false, request.switchItem);
				}
				flag = inventory.RemoveItem(itemAt, dragAmount);
				num = Mathf.Min(itemAt.m_stack, dragAmount);
				flag2 = inventory.AddItemToInventory(switchItem, switchItem.m_stack, fromPos);
				if (!flag2)
				{
					Log.LogWarning("Could not switch item in Remove Request");
					InventoryHandler.DropItem(switchItem, switchItem.m_stack);
				}
			}
			ItemData val = itemAt.Clone();
			val.m_stack = num;
			return new RequestChestRemoveResponse(request.RequestID, flag, num, flag2, val);
		}

		public static RequestConsumeResponse RequestItemConsume(this Inventory inventory, RequestConsume request)
		{
			ItemData itemAt = inventory.GetItemAt(request.itemPosX, request.itemPosY);
			if (itemAt == null || itemAt.m_stack <= 0 || request.expected == null || NetworkInventoryCommit.Identity(itemAt) != NetworkInventoryCommit.Identity(request.expected))
			{
				return new RequestConsumeResponse(null, success: false, 0);
			}
			inventory.RemoveOneItem(itemAt);
			ItemData val = itemAt.Clone();
			val.m_stack = 1;
			return new RequestConsumeResponse(val, success: true, 1);
		}

		public static RequestMoveResponse RequestItemMove(this Inventory inventory, RequestMove request)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: 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_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			Vector2i fromPos = request.fromPos;
			Vector2i toPos = request.toPos;
			int dragAmount = request.dragAmount;
			ItemData itemAt = inventory.GetItemAt(fromPos.x, fromPos.y);
			if (itemAt == null)
			{
				return new RequestMoveResponse(request.RequestID, success: false, 0);
			}
			if (request.dragAmount <= 0 || request.item == null || NetworkInventoryCommit.Identity(itemAt) != NetworkInventoryCommit.Identity(request.item))
			{
				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_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: 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)
			ItemData itemAt = inventory.GetItemAt(request.targetContainerSlot.x, request.targetContainerSlot.y);
			if (itemAt == null || request.amount <= 0 || request.expected == null || NetworkInventoryCommit.Identity(itemAt) != NetworkInventoryCommit.Identity(request.expected))
			{
				return new RequestDropResponse(null, request.sender, success: false, 0);
			}
			int num = Mathf.Min(itemAt.m_stack, request.amount);
			inventory.RemoveItem(itemAt, num);
			if (num == 0)
			{
				return new RequestDropResponse(null, request.sender, success: false, 0);
			}
			ItemData val = itemAt.Clone();
			val.m_stack = num;
			return new RequestDropResponse(val, request.sender, success: true, num);
		}
	}
	public static class PackageHandler
	{
		private static readonly Dictionary<int, IPackage> Packages = new Dictionary<int, IPackage>();

		private static int nextId;

		private static readonly Dictionary<int, DateTime> Started = new Dictionary<int, DateTime>();

		private static readonly Dictionary<int, string> Context = new Dictionary<int, string>();

		private static int total;

		internal unsafe static void Trace(IRequest request, string phase, ZDOID chest, long owner, string detail = "")
		{
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: 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)
			ItemData val = ((request is RequestChestAdd requestChestAdd) ? requestChestAdd.dragItem : ((request is RequestChestRemove requestChestRemove) ? requestChestRemove.item : ((request is RequestMove requestMove) ? requestMove.item : ((request is RequestConsume requestConsume) ? requestConsume.expected : ((request is RequestDrop requestDrop) ? requestDrop.expected : null)))));
			int num = ((!(request is RequestChestAdd requestChestAdd2)) ? ((request is RequestChestRemove requestChestRemove2) ? requestChestRemove2.dragAmount : ((request is RequestMove requestMove2) ? requestMove2.dragAmount : ((request is RequestConsume) ? 1 : ((request is RequestDrop requestDrop2) ? requestDrop2.amount : (val?.m_stack ?? 0))))) : (requestChestAdd2.dragItem?.m_stack ?? 0));
			string text = ((request is RequestChestAdd { toPos: var toPos }) ? ((object)(*(Vector2i*)(&toPos))/*cast due to .constrained prefix*/).ToString() : ((request is RequestChestRemove { toPos: var toPos2 }) ? ((object)(*(Vector2i*)(&toPos2))/*cast due to .constrained prefix*/).ToString() : ((request is RequestMove { toPos: var toPos3 }) ? ((object)(*(Vector2i*)(&toPos3))/*cast due to .constrained prefix*/).ToString() : "none")));
			string text2 = string.Format("utc={0:O} peer={1} request={2} type={3} chest={4} owner={5} item={6} amount={7} to={8} slot={9} {10}", DateTime.UtcNow, ZDOMan.GetSessionID(), request.RequestID, request.GetType().Name, chest, owner, val?.m_shared.m_name ?? "none", num, text, ((object)Unsafe.As<Vector2i, Vector2i>(ref val?.m_gridPos)/*cast due to .constrained prefix*/).ToString() ?? "none", detail);
			if (phase == "registered" || phase == "send")
			{
				Context[request.RequestID] = text2;
			}
			if (Settings.DebugLogging.Value)
			{
				Log.LogInfo("[Shared] " + phase + " " + text2);
			}
		}

		internal static string PendingSummary()
		{
			DateTime value;
			string value2;
			return string.Join(" | ", Packages.Select((KeyValuePair<int, IPackage> p) => $"id={p.Key} age={(Started.TryGetValue(p.Key, out value) ? (DateTime.UtcNow - value).TotalSeconds : (-1.0)):0.0}s {(Context.TryGetValue(p.Key, out value2) ? value2 : p.Value.GetType().Name)}"));
		}

		public static int AddPackage(IPackage package)
		{
			//IL_0125: 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_013a: Unknown result type (might be due to invalid IL or missing references)
			int randomId = GetRandomId();
			if (package is IRequest request)
			{
				request.RequestID = randomId;
				Container chest = (InventoryOwner.GetOwner(request.SourceInventory) as ContainerInventoryOwner)?.Container ?? (InventoryOwner.GetOwner(request.TargetInventory) as ContainerInventoryOwner)?.Container;
				ChestLinkTransactions.BeginSharedEvidence(JournalId(ZDOMan.GetSessionID(), randomId), chest, requester: true);
			}
			Packages.Add(randomId, package);
			Started[randomId] = DateTime.UtcNow;
			if (package is IRequest request2)
			{
				Container val = (InventoryOwner.GetOwner(request2.SourceInventory) as ContainerInventoryOwner)?.Container ?? (InventoryOwner.GetOwner(request2.TargetInventory) as ContainerInventoryOwner)?.Container;
				ZDOID? obj;
				if (val == null)
				{
					obj = null;
				}
				else
				{
					ZNetView nview = val.m_nview;
					obj = ((nview == null) ? ((ZDOID?)null) : nview.GetZDO()?.m_uid);
				}
				? chest2 = ((??)obj) ?? ZDOID.None;
				long? obj2;
				if (val == null)
				{
					obj2 = null;
				}
				else
				{
					ZNetView nview2 = val.m_nview;
					if (nview2 == null)
					{
						obj2 = null;
					}
					else
					{
						ZDO zDO = nview2.GetZDO();
						obj2 = ((zDO != null) ? new long?(zDO.GetOwner()) : ((long?)null));
					}
				}
				long? num = obj2;
				Trace(request2, "registered", (ZDOID)chest2, num.GetValueOrDefault());
			}
			Log.LogDebug($"PackageHandler: Added package {randomId}, total packages: {++total}");
			return randomId;
		}

		public static void RemovePackage(int id)
		{
			if (Settings.DebugLogging.Value && Packages.ContainsKey(id))
			{
				Log.LogInfo($"[Shared] completed utc={DateTime.UtcNow:O} peer={ZDOMan.GetSessionID()} request={id} elapsedMs={(Started.TryGetValue(id, out var value) ? (DateTime.UtcNow - value).TotalMilliseconds : (-1.0)):0}");
			}
			Packages.Remove(id);
			Started.Remove(id);
			Context.Remove(id);
			Log.LogDebug($"PackageHandler: Removed package {id}, total packages: {--total}");
		}

		private static int GetRandomId()
		{
			if (nextId == int.MaxValue)
			{
				throw new InvalidOperationException("Shared request ID limit reached; reconnect.");
			}
			return ++nextId;
		}

		internal static string JournalId(long peer, int id)
		{
			return peer + ":shared:" + id;
		}

		internal static void CompleteJournal(int id)
		{
			ChestLinkTransactions.FinishSharedEvidence(JournalId(ZDOMan.GetSessionID(), id));
		}

		public static bool GetPackage<T>(int id, out T package) where T : IPackage
		{
			if (Packages.TryGetValue(id, out var value))
			{
				package = (T)value;
				return true;
			}
			package = default(T);
			return false;
		}

		public static T GetPackage<T>(int id) where T : IPackage
		{
			if (Packages.TryGetValue(id, out var value))
			{
				return (T)value;
			}
			return default(T);
		}
	}
	public static class ContainerHandler
	{
		public static RequestChestAdd AddItemToChest(this Container container, ItemData item, Inventory sourceInventory, Vector2i to, ZDOID sender, int dragAmount = -1)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)container) || !Object.op_Implicit((Object)(object)container.m_nview) || !container.m_nview.HasOwner())
			{
				return new RequestChestAdd(Vector2i.zero, 0, null, null, null);
			}
			if (!ChestState.Refresh(container, "deposit-preflight"))
			{
				throw new InvalidOperationException("Chest is awaiting synchronization");
			}
			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());
			InventoryPreview.AddPackage(requestChestAdd);
			InventoryBlock.Get(sourceInventory).BlockSlot(item.m_gridPos);
			sourceInventory.RemoveItem(item, dragAmount);
			if (container.m_nview.IsOwner())
			{
				RequestChestAddResponse response = ContainerRPCHandler.Execute(container.GetInventory(), requestChestAdd, ContainerRPCHandler.RequestItemAdd);
				ChestState.VerifyPersisted(container, "local-deposit:" + requestChestAdd.RequestID);
				InventoryHandler.RPC_RequestItemAddResponse(sourceInventory, response);
				PackageHandler.CompleteJournal(requestChestAdd.RequestID);
				return null;
			}
			GamePatches.InvokeRPC(container.m_nview, "ChestLink_Shared_RequestItemAdd", requestChestAdd);
			return requestChestAdd;
		}

		internal static int PossibleDragAmount(Inventory inventoryTo, ItemData dragItem, Vector2i to, int dragAmount)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: 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)
			dragAmount = ((dragAmount >= 0) ? Mathf.Min(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_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: 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())
			{
				return new RequestChestRemove(Vector2i.zero, Vector2i.zero, 0, null, container.GetInventory(), destinationInventory);
			}
			if (!ChestState.Refresh(container, "withdraw-preflight"))
			{
				throw new InvalidOperationException("Chest is awaiting synchronization");
			}
			if (!container.GetInventory().ContainsItem(item))
			{
				return null;
			}
			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);
			}
			InventoryPreview.AddPackage(requestChestRemove);
			InventoryBlock.Get(destinationInventory).BlockSlot(requestChestRemove.toPos);
			if (switchItem != null && !InventoryHelper.CanStack(item, switchItem))
			{
				destinationInventory.RemoveItem(switchItem);
			}
			if (container.m_nview.IsOwner())
			{
				RequestChestRemoveResponse response = ContainerRPCHandler.Execute(container.GetInventory(), requestChestRemove, ContainerRPCHandler.RequestItemRemove);
				ChestState.VerifyPersisted(container, "local-withdraw:" + requestChestRemove.RequestID);
				InventoryHandler.RPC_RequestItemRemoveResponse(destinationInventory, response);
				PackageHandler.CompleteJournal(requestChestRemove.RequestID);
				return null;
			}
			GamePatches.InvokeRPC(container.m_nview, "ChestLink_Shared_RequestItemRemove", requestChestRemove);
			return requestChestRemove;
		}

		public static void MoveItemInChest(this Container container, ItemData item, Vector2i toPos, int dragAmount)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			RequestMove package = new RequestMove(item, toPos, dragAmount, container.GetInventory());
			InventoryPreview.AddPackage(package);
			GamePatches.InvokeRPC(container.m_nview, "ChestLink_Shared_RequestItemMove", package);
		}
	}
	public static class CodeMatcherExtensions
	{
		public static CodeMatcher GetPosition(this CodeMatcher codeMatcher, out int position)
		{
			position = codeMatcher.Pos;
			return codeMatcher;
		}

		public static CodeMatcher AddLabel(this CodeMatcher codeMatcher, out Label label)
		{
			label = default(Label);
			codeMatcher.AddLabels((IEnumerable<Label>)new Label[1] { label });
			return codeMatcher;
		}

		public static CodeMatcher GetOperand(this CodeMatcher codeMatcher, out object operand)
		{
			operand = codeMatcher.Operand;
			return codeMatcher;
		}

		internal static CodeMatcher Print(this CodeMatcher codeMatcher, int before, int after)
		{
			for (int i = -before; i <= after; i++)
			{
				int num = i;
				int num2 = codeMatcher.Pos + num;
				if (num2 > 0)
				{
					if (num2 >= codeMatcher.Length)
					{
						break;
					}
					try
					{
						CodeInstruction val = codeMatcher.InstructionAt(num);
						Log.LogCodeInstruction($"[{num}] " + ((object)val).ToString());
					}
					catch (Exception ex)
					{
						Log.LogCodeInstruction(ex.Message);
					}
				}
			}
			return codeMatcher;
		}

		public static bool IsVirtCall(this CodeInstruction i, string declaringType, string name)
		{
			return i.opcode == OpCodes.Callvirt && i.operand is MethodInfo methodInfo && methodInfo.DeclaringType?.Name == declaringType && methodInfo.Name == name;
		}
	}
	public abstract class InventoryOwner
	{
		public abstract ZNetView ZNetView { get; }

		public abstract Inventory Inventory { get; }

		public virtual bool IsValid()
		{
			return Object.op_Implicit((Object)(object)ZNetView) && ZNetView.HasOwner() && Inventory != null;
		}

		public static InventoryOwner GetOwner(Inventory inventory)
		{
			if (inventory == null)
			{
				return null;
			}
			if (HumanoidExtend.GetHumanoid(inventory, out var humanoid))
			{
				return humanoid;
			}
			if (ContainerExtend.GetContainer(inventory, out var container))
			{
				return container;
			}
			return null;
		}

		public static InventoryOwner GetOwner(ItemData item)
		{
			if (item == null)
			{
				return null;
			}
			if (InventoryPatch.InventoryOfItem.TryGetValue(item, out var value))
			{
				return GetOwner(value);
			}
			return null;
		}

		public string GetDescription()
		{
			if (!IsValid())
			{
				return "-";
			}
			return $"{Inventory.GetName()} ({GetType().Name}), is owner: {ZNetView.IsOwner()}";
		}
	}
	public class ContainerInventoryOwner : InventoryOwner
	{
		public Container Container { get; }

		public bool IsItemDrawer { get; }

		public override ZNetView ZNetView => Container.m_nview;

		public override Inventory Inventory => Container.GetInventory();

		public ContainerInventoryOwner(Container container)
		{
			Container = container;
			IsItemDrawer = ItemDrawerCompat.IsItemDrawer(Container);
		}
	}
	public class HumanoidInventoryOwner : InventoryOwner
	{
		private readonly Inventory inventory;

		public Humanoid Humanoid { get; }

		public override ZNetView ZNetView => ((Character)Humanoid).m_nview;

		public override Inventory Inventory => inventory;

		public HumanoidInventoryOwner(Humanoid humanoid, Inventory inventory)
		{
			Humanoid = humanoid;
			this.inventory = inventory;
		}
	}
	public class InventoryBlock
	{
		private static readonly Dictionary<Inventory, InventoryBlock> Inventories = new Dictionary<Inventory, InventoryBlock>();

		public bool BlockAllSlots { get; set; }

		public bool BlockConsume { get; set; }

		public Dictionary<Vector2i, int> BlockedSlots { get; } = new Dictionary<Vector2i, int>();

		public static InventoryBlock Get(Inventory inventory)
		{
			if (Inventories.TryGetValue(inventory, out var value))
			{
				return value;
			}
			InventoryBlock inventoryBlock = new InventoryBlock();
			Inventories.Add(inventory, inventoryBlock);
			return inventoryBlock;
		}

		public void BlockSlot(Vector2i slot)
		{
			//IL_0001: 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_0046: 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)
			//IL_0029: 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_0032: Unknown result type (might be due to invalid IL or missing references)
			if (CanBlockSlot(slot))
			{
				if (BlockedSlots.ContainsKey(slot))
				{
					BlockedSlots[slot]++;
				}
				else
				{
					BlockedSlots[slot] = 1;
				}
			}
		}

		public void ReleaseSlot(Vector2i slot)
		{
			//IL_0001: 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_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			if (CanBlockSlot(slot) && BlockedSlots.ContainsKey(slot))
			{
				BlockedSlots[slot]--;
				if (BlockedSlots[slot] <= 0)
				{
					BlockedSlots.Remove(slot);
				}
			}
		}

		public void ReleaseBlockedSlots()
		{
			BlockedSlots.Clear();
			BlockAllSlots = false;
			BlockConsume = false;
		}

		public bool IsSlotBlocked(Vector2i slot)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			return BlockConsume || BlockAllSlots || BlockedSlots.ContainsKey(slot);
		}

		public bool IsAnySlotBlocked()
		{
			return BlockConsume || BlockAllSlots || BlockedSlots.Count > 0;
		}

		private static bool CanBlockSlot(Vector2i slot)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			return slot.x >= 0 && slot.y >= 0;
		}
	}
	public static class InventoryHandler
	{
		public static void RPC_RequestItemAddResponse(long sender, ZDOID containerId, ZPackage package)
		{
			//IL_0046: 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)
			RequestChestAddResponse requestChestAddResponse = new RequestChestAddResponse(package);
			if (Settings.DebugLogging.Value)
			{
				Log.LogInfo($"[Shared] reply-receive utc={DateTime.UtcNow:O} peer={ZDOMan.GetSessionID()} sender={sender} chest={containerId} request={requestChestAddResponse.SourceID} type=RequestChestAddResponse success={requestChestAddResponse.Success} pending={PackageHandler.GetPackage<IPackage>(requestChestAddResponse.SourceID) != null}");
			}
			HandleRPC(requestChestAddResponse, (RequestChestAddResponse p) => GetSourceInventory(p.SourceID), RPC_RequestItemAddResponse);
			PackageHandler.CompleteJournal(requestChestAddResponse.SourceID);
			ZRoutedRpc.instance.InvokeRoutedRPC(sender, "ChestLink_Shared_ReceiptAck", new object[2] { containerId, requestChestAddResponse.SourceID });
		}

		public static void RPC_RequestItemRemoveResponse(long sender, ZDOID containerId, ZPackage package)
		{
			//IL_0046: 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)
			RequestChestRemoveResponse requestChestRemoveResponse = new RequestChestRemoveResponse(package);
			if (Settings.DebugLogging.Value)
			{
				Log.LogInfo($"[Shared] reply-receive utc={DateTime.UtcNow:O} peer={ZDOMan.GetSessionID()} sender={sender} chest={containerId} request={requestChestRemoveResponse.SourceID} type=RequestChestRemoveResponse success={requestChestRemoveResponse.Success} pending={PackageHandler.GetPackage<IPackage>(requestChestRemoveResponse.SourceID) != null}");
			}
			HandleRPC(requestChestRemoveResponse, (RequestChestRemoveResponse p) => GetTargetInventory(p.SourceID), RPC_RequestItemRemoveResponse);
			PackageHandler.CompleteJournal(requestChestRemoveResponse.SourceID);
			ZRoutedRpc.instance.InvokeRoutedRPC(sender, "ChestLink_Shared_ReceiptAck", new object[2] { containerId, requestChestRemoveResponse.SourceID });
		}

		public static void RPC_RequestDropResponse(long sender, ZDOID containerId, ZPackage package)
		{
			//IL_00bc: 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)
			RequestDropResponse requestDropResponse = new RequestDropResponse(package);
			if (Settings.DebugLogging.Value)
			{
				Log.LogInfo($"[Shared] reply-receive utc={DateTime.UtcNow:O} peer={ZDOMan.GetSessionID()} sender={sender} chest={containerId} request={requestDropResponse.SourceID} type=RequestDropResponse success={requestDropResponse.Success} pending={PackageHandler.GetPackage<IPackage>(requestDropResponse.SourceID) != null}");
			}
			HandleRPC(requestDropResponse, RPC_RequestDropResponse);
			PackageHandler.CompleteJournal(requestDropResponse.SourceID);
			ZRoutedRpc.instance.InvokeRoutedRPC(sender, "ChestLink_Shared_ReceiptAck", new object[2] { containerId, requestDropResponse.SourceID });
		}

		public static void RPC_RequestItemConsumeResponse(long sender, ZDOID containerId, ZPackage package)
		{
			//IL_00bc: 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)
			RequestConsumeResponse requestConsumeResponse = new RequestConsumeResponse(package);
			if (Settings.DebugLogging.Value)
			{
				Log.LogInfo($"[Shared] reply-receive utc={DateTime.UtcNow:O} peer={ZDOMan.GetSessionID()} sender={sender} chest={containerId} request={requestConsumeResponse.SourceID} type=RequestConsumeResponse success={requestConsumeResponse.Success} pending={PackageHandler.GetPackage<IPackage>(requestConsumeResponse.SourceID) != null}");
			}
			HandleRPC(requestConsumeResponse, RPC_RequestItemConsumeResponse);
			PackageHandler.CompleteJournal(requestConsumeResponse.SourceID);
			ZRoutedRpc.instance.InvokeRoutedRPC(sender, "ChestLink_Shared_ReceiptAck", new object[2] { containerId, requestConsumeResponse.SourceID });
		}

		public static void RPC_RequestItemMoveResponse(long sender, ZDOID containerId, ZPackage package)
		{
			//IL_00bc: 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)
			RequestMoveResponse requestMoveResponse = new RequestMoveResponse(package);
			if (Settings.DebugLogging.Value)
			{
				Log.LogInfo($"[Shared] reply-receive utc={DateTime.UtcNow:O} peer={ZDOMan.GetSessionID()} sender={sender} chest={containerId} request={requestMoveResponse.SourceID} type=RequestMoveResponse success={requestMoveResponse.Success} pending={PackageHandler.GetPackage<IPackage>(requestMoveResponse.SourceID) != null}");
			}
			HandleRPC(requestMoveResponse, RPC_RequestItemMoveResponse);
			PackageHandler.CompleteJournal(requestMoveResponse.SourceID);
			ZRoutedRpc.instance.InvokeRoutedRPC(sender, "ChestLink_Shared_ReceiptAck", new object[2] { containerId, requestMoveResponse.SourceID });
		}

		private static void HandleRPC<T>(T package, Func<T, Inventory> inventory, Container container, Action<Inventory, Container, T> handle) where T : IPackage
		{
			CallRPC(handle.Method.Name, package, delegate
			{
				handle(inventory(package), container, package);
			});
		}

		private static void HandleRPC<T>(T package, Func<T, Inventory> inventory, Action<Inventory, T> handle) where T : IPackage
		{
			CallRPC(handle.Method.Name, package, delegate
			{
				handle(inventory(package), package);
			});
		}

		private static void HandleRPC<T>(T package, Action<T> handle) where T : IPackage
		{
			CallRPC(handle.Method.Name, package, delegate
			{
				handle(package);
			});
		}

		private static void CallRPC(string timerName, IPackage package, Action action)
		{
			Timer.Stop(timerName);
			package.PrintDebug();
			if (!(package is IResponse response) || PackageHandler.GetPackage<IPackage>(response.SourceID) != null)
			{
				action?.Invoke();
			}
		}

		public static void RPC_RequestItemRemoveResponse(Inventory inventory, RequestChestRemoveResponse response)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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_004b: 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_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Expected O, but got Unknown
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			if (PackageHandler.GetPackage<IPackage>(response.SourceID) == null || inventory == null)
			{
				return;
			}
			Vector2i toPos = PackageHandler.GetPackage<RequestChestRemove>(response.SourceID).toPos;
			InventoryBlock.Get(inventory).ReleaseSlot(toPos);
			InventoryPreview.RemovePackage(response);
			if (response.Success && toPos.x >= 0 && toPos.y >= 0)
			{
				if (!inventory.AddItemToInventory(response.responseItem, response.Amount, toPos))
				{
					int num = response.Amount;
					ItemData itemAt = inventory.GetItemAt(toPos.x, toPos.y);
					if (itemAt != null && InventoryHelper.CanStack(response.responseItem, itemAt))
					{
						int maxStackSize = itemAt.m_shared.m_maxStackSize;
						int stack = itemAt.m_stack;
						int num2 = maxStackSize - stack;
						itemAt.m_stack += num2;
						num -= num2;
					}
					DropItem(response.responseItem, num);
				}
			}
			else if (response.responseItem != null)
			{
				Inventory val = new Inventory("tmp", (Sprite)null, 1, 1);
				val.AddItem(response.responseItem);
				inventory.MoveItemToThis(val, response.responseItem);
				ItemData itemAt2 = val.GetItemAt(0, 0);
				if (itemAt2 != null)
				{
					DropItem(itemAt2, itemAt2.m_stack);
				}
			}
			UpdateGUIAfterPlayerMove(GetTargetInventory(response.SourceID));
		}

		private static void RPC_RequestDropResponse(RequestDropResponse response)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if (PackageHandler.GetPackage<IPackage>(response.SourceID) != null)
			{
				PackageHandler.RemovePackage(response.SourceID);
				DropItem(response.responseItem, response.responseItem?.m_stack ?? 0);
				UpdateGUIAfterPlayerMove(response.sender);
			}
		}

		private static void UpdateGUIAfterPlayerMove(ZDOID sender)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)InventoryGui.instance) && Object.op_Implicit((Object)(object)Player.m_localPlayer) && sender == ((Character)Player.m_localPlayer).GetZDOID())
			{
				InventoryGui.instance.UpdateCraftingPanel(false);
			}
		}

		private static void UpdateGUIAfterPlayerMove(Inventory inventory)
		{
			if (Object.op_Implicit((Object)(object)InventoryGui.instance) && Object.op_Implicit((Object)(object)Player.m_localPlayer) && ((Humanoid)Player.m_localPlayer).GetInventory().GetInventories().Contains(inventory))
			{
				InventoryGui.instance.UpdateCraftingPanel(false);
			}
		}

		public static void DropItem(ItemData item, int amount)
		{
			if (amount > 0 && item != null)
			{
				DropItem(Player.m_localPlayer, item, amount);
			}
		}

		private static void DropItem(Player player, ItemData item, int amount)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: 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_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: 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)
			Transform transform = ((Component)player).transform;
			ItemDrop val = ItemDrop.DropItem(item, amount, transform.position + transform.forward + transform.up, transform.rotation);
			val.OnPlayerDrop();
			((Component)val).GetComponent<Rigidbody>().linearVelocity = (transform.forward + Vector3.up) * 5f;
			((Character)player).m_zanim.SetTrigger("interact");
			((Humanoid)player).m_dropEffects.Create(transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
			ItemData itemData = val.m_itemData;
			((Character)player).Message((MessageType)1, "$msg_dropped " + itemData.m_shared.m_name, itemData.m_stack, itemData.GetIcon(), false);
		}

		public static void RPC_RequestItemAddResponse(Inventory inventory, RequestChestAddResponse response)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: 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)
			if (PackageHandler.GetPackage<IPackage>(response.SourceID) != null && inventory != null)
			{
				Vector2i inventoryPos = response.inventoryPos;
				ItemData switchItem = response.switchItem;
				InventoryBlock.Get(inventory).ReleaseSlot(inventoryPos);
				InventoryPreview.RemovePackage(response);
				if (switchItem != null && !inventory.AddItemToInventory(switchItem, switchItem.m_stack, inventoryPos))
				{
					DropItem(switchItem, switchItem.m_stack);
				}
				UpdateGUIAfterPlayerMove(GetSourceInventory(response.SourceID));
			}
		}

		public static void RPC_RequestItemConsumeResponse(RequestConsumeResponse response)
		{
			if (PackageHandler.GetPackage<IPackage>(response.SourceID) == null)
			{
				return;
			}
			PackageHandler.RemovePackage(response.SourceID);
			Player localPlayer = Player.m_localPlayer;
			InventoryBlock.Get(((Humanoid)localPlayer).GetInventory()).BlockConsume = false;
			if (response.item == null)
			{
				return;
			}
			if (!((Humanoid)localPlayer).CanConsumeItem(response.item, false))
			{
				SharedTransfers.ReturnUnused(response.item);
				return;
			}
			if (Object.op_Implicit((Object)(object)response.item.m_shared.m_consumeStatusEffect))
			{
				((Character)localPlayer).m_seman.AddStatusEffect(response.item.m_shared.m_consumeStatusEffect, true, 0, 0f, (short)(-1));
			}
			if ((double)response.item.m_shared.m_food > 0.0)
			{
				localPlayer.EatFood(response.item);
			}
		}

		public static void RPC_RequestItemMoveResponse(RequestMoveResponse response)
		{
			InventoryPreview.RemovePackage(response);
		}

		internal static Inventory GetSourceInventory(int id)
		{
			return PackageHandler.GetPackage<IRequest>(id)?.SourceInventory;
		}

		internal static Inventory GetTargetInventory(int id)
		{
			return PackageHandler.GetPackage<IRequest>(id)?.TargetInventory;
		}
	}
	public class ContainerExtend : MonoBehaviour
	{
		private static readonly ConditionalWeakTable<Inventory, ContainerInventoryOwner> Containers = new ConditionalWeakTable<Inventory, ContainerInventoryOwner>();

		private Inventory inventory;

		private void Awake()
		{
			Container container = default(Container);
			if (!((Component)this).TryGetComponent<Container>(ref container))
			{
				return;
			}
			inventory = container.GetInventory();
			if (inventory != null)
			{
				Containers.TryAdd(inventory, (Inventory i) => new ContainerInventoryOwner(container));
			}
		}

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

		public static bool GetContainer(Inventory inventory, out ContainerInventoryOwner container)
		{
			return Containers.TryGetValue(inventory, out container);
		}
	}
	public static class InventoryPreview
	{
		public static readonly ConditionalWeakTable<Inventory, List<IRequest>> PackageChanges = new ConditionalWeakTable<Inventory, List<IRequest>>();

		public static readonly ConditionalWeakTable<Inventory, List<IRequest>> ToRemovePackages = new ConditionalWeakTable<Inventory, List<IRequest>>();

		private static WaitForSeconds removeQueuedPackagesDelay = new WaitForSeconds(0.2f);

		public static void AddPackage(IRequest package)
		{
			package.RequestID = PackageHandler.AddPackage(package);
			AppendPackage(package.SourceInventory, package);
			AppendPackage(package.TargetInventory, package);
		}

		private static void AppendPackage(Inventory inventory, IRequest package)
		{
			if (inventory == null)
			{
				return;
			}
			if (PackageChanges.TryGetValue(inventory, out var value))
			{
				if (!value.Contains(package))
				{
					value.Add(package);
				}
				Log.LogDebug($"InventoryPreview: Appended package {package.RequestID} to inventory {inventory.m_name}, total packages: {value.Count}");
				return;
			}
			PackageChanges.Add(inventory, new List<IRequest> { package });
			Inventory obj = inventory;
			obj.m_onChanged = (Action)Delegate.Combine(obj.m_onChanged, (Action)delegate
			{
				RemoveQueuedPackages(inventory);
			});
			Log.LogDebug($"InventoryPreview: Added package {package.RequestID} to inventory {inventory.m_name}, total packages: 1 (new)");
		}

		public static void RemovePackage(IResponse package)
		{
			RemovePackage(InventoryHandler.GetSourceInventory(package.SourceID), package);
			RemovePackage(InventoryHandler.GetTargetInventory(package.SourceID), package);
			PackageHandler.RemovePackage(package.SourceID);
		}

		private static void RemovePackage(Inventory inventory, IResponse package)
		{
			if (inventory == null)
			{
				return;
			}
			InventoryOwner owner = InventoryOwner.GetOwner(inventory);
			IRequest request = null;
			if (PackageChanges.TryGetValue(inventory, out var value))
			{
				request = value.Find((IRequest p) => p.RequestID == package.SourceID);
			}
			if (request != null)
			{
				if (ToRemovePackages.TryGetValue(inventory, out var value2))
				{
					value2.Add(request);
				}
				else
				{
					ToRemovePackages.Add(inventory, new List<IRequest> { request });
				}
				if (owner != null && owner.IsValid() && owner.ZNetView.IsOwner())
				{
					RemoveQueuedPackages(inventory);
				}
				else
				{
					((MonoBehaviour)ThreadingHelper.Instance).StartCoroutine(RemoveQueuedPackagesDelayed(inventory));
				}
			}
		}

		private static void RemoveQueuedPackages(Inventory inventory)
		{
			if (!ToRemovePackages.TryGetValue(inventory, out var value) || value.Count <= 0)
			{
				return;
			}
			foreach (IRequest item in new List<IRequest>(value))
			{
				if (PackageChanges.TryGetValue(inventory, out var value2))
				{
					value2.Remove(item);
				}
				value.Remove(item);
				Log.LogDebug($"InventoryPreview: Removed package {item.RequestID} from inventory {inventory.m_name}, total packages: {value.Count}");
			}
		}

		private static IEnumerator RemoveQueuedPackagesDelayed(Inventory inventory)
		{
			yield return removeQueuedPackagesDelay;
			RemoveQueuedPackages(inventory);
		}

		public static bool GetChanges(Inventory inventory, out SlotPreview preview)
		{
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: 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_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: 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_0334: Unknown result type (might be due to invalid IL or missing references)
			//IL_034c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
			if (inventory == null)
			{
				preview = null;
				return false;
			}
			if (PackageChanges.TryGetValue(inventory, out var value))
			{
				preview = new SlotPreview(inventory);
				foreach (IRequest item3 in value)
				{
					if (item3 is RequestChestAdd requestChestAdd)
					{
						if (requestChestAdd.dragItem != null)
						{
							ItemData item = null;
							if (requestChestAdd.allowSwitch)
							{
								item = item3.TargetInventory.GetItemAt(requestChestAdd.toPos.x, requestChestAdd.toPos.y);
							}
							if (inventory == item3.SourceInventory)
							{
								preview.Add(requestChestAdd.dragItem.m_gridPos, item);
							}
							if (inventory == item3.TargetInventory)
							{
								preview.Remove(requestChestAdd.toPos, item);
								preview.Add(requestChestAdd.toPos, requestChestAdd.dragItem);
							}
						}
					}
					else if (item3 is RequestChestRemove { fromPos: var fromPos, toPos: var toPos } requestChestRemove)
					{
						if (inventory == item3.SourceInventory)
						{
							preview.Remove(fromPos, requestChestRemove.item, requestChestRemove.dragAmount);
							preview.Add(fromPos, requestChestRemove.switchItem);
						}
						if (inventory == item3.TargetInventory)
						{
							preview.Add(toPos, requestChestRemove.item, requestChestRemove.dragAmount);
						}
					}
					else
					{
						if (!(item3 is RequestMove requestMove) || (preview.GetSlot(requestMove.fromPos, out var item2) && requestMove.itemHash != ((item2 != null) ? new int?(StringExtensionMethods.GetStableHashCode(item2.PrefabName())) : ((int?)null))))
						{
							continue;
						}
						ItemData itemAt = requestMove.TargetInventory.GetItemAt(requestMove.toPos.x, requestMove.toPos.y);
						if (itemAt != null && !InventoryHelper.CanStack(requestMove.item, itemAt))
						{
							if (requestMove.dragAmount == requestMove.item.m_stack)
							{
								preview.Remove(requestMove.fromPos, requestMove.item, requestMove.dragAmount);
								preview.Remove(requestMove.toPos, itemAt, itemAt.m_stack);
								preview.Add(requestMove.fromPos, itemAt, itemAt.m_stack);
								preview.Add(requestMove.toPos, requestMove.item, requestMove.dragAmount);
							}
						}
						else
						{
							int amount = Mathf.Max(0, requestMove.dragAmount);
							if (itemAt != null)
							{
								amount = Mathf.Min(itemAt.m_shared.m_maxStackSize - itemAt.m_stack, requestMove.dragAmount);
							}
							preview.Remove(requestMove.fromPos, requestMove.item, amount);
							preview.Add(requestMove.toPos, requestMove.item, amount);
						}
					}
				}
				return preview.HasChanges();
			}
			preview = null;
			return false;
		}
	}
	public static class Compatibility
	{
		private static bool IsExtendedInventory(this Inventory inventory, out List<Inventory> inventories)
		{
			if (inventory.IsType("ExtendedInventory") && inventory.HasField("_inventories"))
			{
				inventories = inventory.GetField<List<Inventory>>("_inventories");
				return true;
			}
			inventories = null;
			return false;
		}

		public static List<Inventory> GetInventories(this Inventory inventory)
		{
			if (inventory.IsExtendedInventory(out var inventories))
			{
				return inventories;
			}
			return new List<Inventory> { inventory };
		}
	}
	public interface IRequest : IPackage
	{
		int RequestID { get; set; }

		Inventory SourceInventory { get; }

		Inventory TargetInventory { get; }
	}
	public class RequestConsume : IRequest, IPackage
	{
		public ItemData expected;

		public readonly int itemPosX;

		public readonly int itemPosY;

		public int RequestID { get; set; }

		public Inventory SourceInventory { get; set; }

		public Inventory TargetInventory { get; set; }

		public RequestConsume(ItemData item)
		{
			expected = item.Clone();
			itemPosX = item.m_gridPos.x;
			itemPosY = item.m_gridPos.y;
		}

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

		public ZPackage WriteToPackage()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			val.Write(RequestID);
			InventoryHelper.WriteItemToPackage(expected, val);
			val.Write(itemPosX);
			val.Write(itemPosY);
			return val;
		}

		public void PrintDebug()
		{
			Log.LogDebug("RequestConsume:");
			Log.LogDebug($"  itemPosX: {itemPosX}");
			Log.LogDebug($"  itemPosY: {itemPosY}");
		}
	}
	public class RequestDrop : IRequest, IPackage
	{
		public ItemData expected;

		public readonly Vector2i targetContainerSlot;

		public readonly int amount;

		public readonly ZDOID sender;

		public int RequestID { get; set; }

		public Inventory SourceInventory { get; set; }

		public Inventory TargetInventory { get; set; }

		public RequestDrop(Vector2i targetContainerSlot, int amount, ZDOID sender)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: 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_0018: Unknown result type (might be due to invalid IL or missing references)
			this.targetContainerSlot = targetContainerSlot;
			this.amount = amount;
			this.sender = sender;
		}

		public RequestDrop(ZPackage package)
		{
			//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)
			//IL_003b: 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)
			RequestID = package.ReadInt();
			expected = InventoryHelper.LoadItemFromPackage(package);
			targetContainerSlot = package.ReadVector2i();
			amount = package.ReadInt();
			sender = package.ReadZDOID();
		}

		public ZPackage WriteToPackage()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			ZPackage val = new ZPackage();
			val.Write(RequestID);
			InventoryHelper.WriteItemToPackage(expected, val);
			val.Write(targetContainerSlot);
			val.Write(amount);
			val.Write(sender);
			return val;
		}

		public void PrintDebug()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			Log.LogDebug("RequestDrop:");
			Log.LogDebug($"  targetContainerSlot: {targetContainerSlot}");
			Log.LogDebug($"  amount: {amount}");
			Log.LogDebug($"  sender: {sender}");
		}
	}
	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)
		{
			SourceID = package.ReadInt();
			item = InventoryHelper.LoadItemFromPackage(package);
			Success = package.ReadBool();
			Amount = package.ReadInt();
		}

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

		public RequestConsumeResponse()
		{
			item = null;
		}

		public ZPackage WriteToPackage()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			val.Write(SourceID);
			InventoryHelper.WriteItemToPackage(item, val);
			val.Write(Success);
			val.Write(Amount);
			return val;
		}

		public void PrintDebug()
		{
			Log.LogDebug("RequestConsumeResponse:");
			Log.LogDebug($"  id: {SourceID}");
			Log.LogDebug($"  success: {Success}");
			Log.LogDebug($"  amount: {Amount}");
			InventoryHelper.PrintItem("item", item);
		}
	}
	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)
		{
			//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)
			this.responseItem = responseItem.ClampStackSize();
			this.sender = sender;
			Success = success;
			Amount = amount;
		}

		public RequestDropResponse(ZPackage package)
		{
			//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)
			SourceID = package.ReadInt();
			responseItem = InventoryHelper.LoadItemFromPackage(package);
			sender = package.ReadZDOID();
			Success = package.ReadBool();
			Amount = package.ReadInt();
		}

		public RequestDropResponse()
		{
			responseItem = null;
		}

		public ZPackage WriteToPackage()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			ZPackage val = new ZPackage();
			val.Write(SourceID);
			InventoryHelper.WriteItemToPackage(responseItem, val);
			val.Write(sender);
			val.Write(Success);
			val.Write(Amount);
			return val;
		}

		public void PrintDebug()
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			Log.LogDebug("RequestDropResponse:");
			Log.LogDebug($"  Success: {Success}");
			Log.LogDebug($"  Amount: {Amount}");
			Log.LogDebug($"  sender: {sender}");
			InventoryHelper.PrintItem("responseItem", responseItem);
		}
	}
	public class RequestChestAdd : IRequest, IPackage
	{
		public readonly Vector2i toPos;

		public readonly ItemData dragItem;

		public readonly bool allowSwitch;

		public int RequestID { get; set; }

		public Inventory SourceInventory { get; }

		public Inventory TargetInventory { get; }

		public RequestChestAdd(Vector2i toPos, int dragAmount, ItemData dragItem, Inventory sourceInventory, Inventory targetInventory)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: 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_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)
			RequestID = package.ReadInt();
			toPos = package.ReadVector2i();
			dragItem = InventoryHelper.LoadItemFromPackage(package);
			allowSwitch = package.ReadBool();
		}

		public ZPackage WriteToPackage()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			ZPackage val = new ZPackage();
			val.Write(RequestID);
			val.Write(toPos);
			InventoryHelper.WriteItemToPackage(dragItem, val);
			val.Write(allowSwitch);
			return val;
		}

		public void PrintDebug()
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			Log.LogDebug("RequestItemAdd:");
			Log.LogDebug($"  id: {RequestID}");
			Log.LogDebug($"  toContainer: {toPos}");
			Log.LogDebug($"  allowSwitch: {allowSwitch}");
			InventoryHelper.PrintItem("dragItem", dragItem);
		}
	}
	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 RequestChestRemoveResponse(int sourceID, bool success, int amount, bool hasSwitched, ItemData responseItem)
		{
			SourceID = sourceID;
			Success = success;
			Amount = amount;
			this.hasSwitched = hasSwitched;
			this.responseItem = responseItem.ClampStackSize();
		}

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

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

		public ZPackage WriteToPackage()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			val.Write(SourceID);
			val.Write(Success);
			val.Write(Amount);
			val.Write(hasSwitched);
			InventoryHelper.WriteItemToPackage(responseItem, val);
			return val;
		}

		public void PrintDebug()
		{
			Log.LogDebug("RequestRemoveResponse:");
			Log.LogDebug($"  id: {SourceID}");
			Log.LogDebug($"  success: {Success}");
			Log.LogDebug($"  amount: {Amount}");
			Log.LogDebug($"  hasSwitched: {hasSwitched}");
			InventoryHelper.PrintItem("responseItem", responseItem);
		}
	}
	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 Inventory SourceInventory { get; }

		public Inventory TargetInventory { get; }

		public RequestChestRemove(Vector2i fromPos, Vector2i toPos, int dragAmount, ItemData switchItem, Inventory sourceInventory, Inventory targetInventory)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: 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_0051: 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_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_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)
			RequestID = package.ReadInt();
			fromPos = package.ReadVector2i();
			toPos = package.ReadVector2i();
			dragAmount = package.ReadInt();
			switchItem = InventoryHelper.LoadItemFromPackage(package);
			item = InventoryHelper.LoadItemFromPackage(package);
		}

		public ZPackage WriteToPackage()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0016: 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)
			ZPackage val = new ZPackage();
			val.Write(RequestID);
			val.Write(fromPos);
			val.Write(toPos);
			val.Write(dragAmount);
			InventoryHelper.WriteItemToPackage(switchItem, val);
			InventoryHelper.WriteItemToPackage(item, val);
			return val;
		}

		public void PrintDebug()
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			Log.LogDebug("RequestItemRemove:");
			Log.LogDebug($"  id: {RequestID}");
			Log.LogDebug($"  fromContainer: {fromPos}");
			Log.LogDebug($"  toInventory: {toPos}");
			Log.LogDebug($"  dragAmount: {dragAmount}");
			InventoryHelper.PrintItem("switchItem", switchItem);
		}
	}
	public interface IResponse : IPackage
	{
		int SourceID { get; set; }

		bool Success { get; set; }

		int Amount { get; set; }
	}
	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 Inventory SourceInventory { get; }

		public Inventory TargetInventory { get; }

		public RequestMove(ItemData itemToMove, Vector2i toPos, int dragAmount, Inventory inventory)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: 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_0064: 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_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			if (itemToMove == null)
			{
				Log.LogWarning("Item is null");
				fromPos = new Vector2i(-1, -1);
				this.toPos = new Vector2i(-1, -1);
				itemHash = 0;
				this.dragAmount = 0;
			}
			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_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_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)
			RequestID = package.ReadInt();
			fromPos = package.ReadVector2i();
			toPos = package.ReadVector2i();
			itemHash = package.ReadInt();
			dragAmount = package.ReadInt();
			item = InventoryHelper.LoadItemFromPackage(package);
		}

		public ZPackage WriteToPackage()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0016: 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)
			ZPackage val = new ZPackage();
			val.Write(RequestID);
			val.Write(fromPos);
			val.Write(toPos);
			val.Write(itemHash);
			val.Write(dragAmount);
			InventoryHelper.WriteItemToPackage(item, val);
			return val;
		}

		public void PrintDebug()
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			Log.LogDebug("RequestMove:");
			Log.LogDebug($"  RequestID: {RequestID}");
			Log.LogDebug($"  fromPos: {fromPos}");
			Log.LogDebug($"  toPos: {toPos}");
			Log.LogDebug($"  itemHash: {itemHash}");
			Log.LogDebug($"  dragAmount: {dragAmount}");
		}
	}
	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_0020: 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_0045: 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)
			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_0002: 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_0002: 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_0018: 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_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			if (item != null && amount != 0)
			{
				ItemData itemAt = inventory.GetItemAt(pos.x, pos.y);
				if (itemAt != null)
				{
					inventory.RemoveItem(inventory.GetItemAt(pos.x, pos.y), amount);
					hasChanges = true;
				}
			}
		}

		public bool GetSlot(Vector2i pos, out ItemData item)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: 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_0026: 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;
			}
			return itemAt.m_shared.m_name != item.m_shared.m_name || itemAt.m_stack != item.m_stack;
		}

		public bool HasChanges()
		{
			return hasChanges;
		}
	}
	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)
		{
			SourceID = package.ReadInt();
			Success = package.ReadBool();
			Amount = package.ReadInt();
		}

		public ZPackage WriteToPackage()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			val.Write(SourceID);
			val.Write(Success);
			val.Write(Amount);
			return val;
		}

		public void PrintDebug()
		{
			Log.LogDebug("RequestMoveResponse:");
			Log.LogDebug($"  SourceID: {SourceID}");
			Log.LogDebug($"  Success: {Success}");
			Log.LogDebug($"  Amount: {Amount}");
		}
	}
	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 RequestChestAddResponse(int sourceID, bool success, Vector2i inventoryPos, int amount, ItemData switchItem)
		{
			//IL_0022: 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)
			SourceID = sourceID;
			Success = success;
			Amount = amount;
			this.inventoryPos = inventoryPos;
			this.switchItem = switchItem.ClampStackSize();
		}

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

		public RequestChestAddResponse()
		{
			//IL_001b: 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)
			SourceID = 0;
			Success = false;
			inventoryPos = new Vector2i(-1, -1);
			Amount = 0;
			switchItem = null;
		}

		public ZPackage WriteToPackage()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			ZPackage val = new ZPackage();
			val.Write(SourceID);
			val.Write(inventoryPos);
			val.Write(Success);
			val.Write(Amount);
			InventoryHelper.WriteItemToPackage(switchItem, val);
			return val;
		}

		public void PrintDebug()
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			Log.LogDebug("RequestChestAddResponse:");
			Log.LogDebug($"  id: {SourceID}");
			Log.LogDebug($"  inventoryPos: {inventoryPos}");
			Log.LogDebug($"  success: {Success}");
			Log.LogDebug($"  amount: {Amount}");
			InventoryHelper.PrintItem("switchItem", switchItem);
		}
	}
	public interface IPackage
	{
		ZPackage WriteToPackage();

		void PrintDebug();
	}
	public static class InventoryHelper
	{
		public delegate void MoveAction(Inventory from, Inventory to);

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

		public static ItemData LoadItemFromPackage(ZPackage pkg)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to