Decompiled source of ItemDrawers v1.0.2

kg_ItemDrawers.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using JetBrains.Annotations;
using Jotunn.Managers;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using kg_ItemDrawers;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("kg_ItemDrawers")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("kg_ItemDrawers")]
[assembly: AssemblyTitle("kg_ItemDrawers")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace kg_ItemDrawers
{
	internal static class BuildBridge
	{
		private const float BuildRange = 20f;

		private static bool _applied;

		internal static void Apply(Harmony harmony)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Expected O, but got Unknown
			if (_applied)
			{
				return;
			}
			_applied = true;
			MethodInfo[] methods = typeof(Player).GetMethods(BindingFlags.Instance | BindingFlags.Public);
			foreach (MethodInfo methodInfo in methods)
			{
				if (!(methodInfo.Name != "HaveRequirements"))
				{
					MethodInfo method = typeof(BuildBridge).GetMethod("HaveRequirementsPostfix", BindingFlags.Static | BindingFlags.NonPublic);
					try
					{
						harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						ItemDrawers.Instance.Log.LogInfo((object)("BuildBridge: patched HaveRequirements(" + string.Join(", ", GetParamTypes(methodInfo)) + ")"));
					}
					catch (Exception ex)
					{
						ItemDrawers.Instance.Log.LogWarning((object)("BuildBridge: failed to patch HaveRequirements: " + ex.Message));
					}
				}
			}
			methods = typeof(Player).GetMethods(BindingFlags.Instance | BindingFlags.Public);
			foreach (MethodInfo methodInfo2 in methods)
			{
				if (!(methodInfo2.Name != "ConsumeResources"))
				{
					MethodInfo method2 = typeof(BuildBridge).GetMethod("ConsumeResourcesPrefix", BindingFlags.Static | BindingFlags.NonPublic);
					try
					{
						harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						ItemDrawers.Instance.Log.LogInfo((object)("BuildBridge: patched ConsumeResources(" + string.Join(", ", GetParamTypes(methodInfo2)) + ")"));
					}
					catch (Exception ex2)
					{
						ItemDrawers.Instance.Log.LogWarning((object)("BuildBridge: failed to patch ConsumeResources: " + ex2.Message));
					}
				}
			}
		}

		private static string[] GetParamTypes(MethodInfo mi)
		{
			ParameterInfo[] parameters = mi.GetParameters();
			string[] array = new string[parameters.Length];
			for (int i = 0; i < parameters.Length; i++)
			{
				array[i] = parameters[i].ParameterType.Name;
			}
			return array;
		}

		[UsedImplicitly]
		private static void HaveRequirementsPostfix(Player __instance, ref bool __result, object[] __args)
		{
			if (__result || (Object)(object)__instance == (Object)null || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return;
			}
			Requirement[] array = null;
			int quality = 0;
			if (__args != null)
			{
				foreach (object obj in __args)
				{
					Piece val = (Piece)((obj is Piece) ? obj : null);
					if (val != null && val?.m_resources != null)
					{
						array = val.m_resources;
						continue;
					}
					Recipe val2 = (Recipe)((obj is Recipe) ? obj : null);
					if (val2 != null && val2?.m_resources != null)
					{
						array = val2.m_resources;
					}
					else if (obj is Requirement[] array2)
					{
						array = array2;
					}
					else if (obj is int num)
					{
						quality = num;
					}
				}
			}
			if (array != null)
			{
				CheckAndSupplement(__instance, array, quality, ref __result);
			}
		}

		private static void CheckAndSupplement(Player player, Requirement[] resources, int quality, ref bool __result)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			if (resources == null || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return;
			}
			List<DrawerComponent> list = FindNearbyDrawers(((Component)player).transform.position);
			if (list.Count == 0)
			{
				return;
			}
			foreach (Requirement val in resources)
			{
				if (!((Object)(object)val?.m_resItem == (Object)null) && val.m_amount > 0)
				{
					int num = val.m_amount * (quality + 1);
					string name = val.m_resItem.m_itemData.m_shared.m_name;
					Inventory inventory = ((Humanoid)player).GetInventory();
					int num2 = ((inventory != null) ? inventory.CountItems(name, -1, true) : 0);
					int num3 = CountInDrawers(list, name);
					if (num2 + num3 < num)
					{
						return;
					}
				}
			}
			__result = true;
		}

		[UsedImplicitly]
		private static void ConsumeResourcesPrefix(Player __instance, object[] __args)
		{
			if ((Object)(object)__instance == (Object)null || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return;
			}
			Requirement[] array = null;
			int quality = 0;
			if (__args != null)
			{
				foreach (object obj in __args)
				{
					Piece val = (Piece)((obj is Piece) ? obj : null);
					if (val != null && val?.m_resources != null)
					{
						array = val.m_resources;
						continue;
					}
					Recipe val2 = (Recipe)((obj is Recipe) ? obj : null);
					if (val2 != null && val2?.m_resources != null)
					{
						array = val2.m_resources;
					}
					else if (obj is Requirement[] array2)
					{
						array = array2;
					}
					else if (obj is int num)
					{
						quality = num;
					}
				}
			}
			if (array != null)
			{
				ConsumeFromDrawers(__instance, array, quality);
			}
		}

		private static void ConsumeFromDrawers(Player player, Requirement[] resources, int quality)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			if (resources == null || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return;
			}
			List<DrawerComponent> list = FindNearbyDrawers(((Component)player).transform.position);
			if (list.Count == 0)
			{
				return;
			}
			foreach (Requirement val in resources)
			{
				if (!((Object)(object)val?.m_resItem == (Object)null) && val.m_amount > 0)
				{
					int num = val.m_amount * (quality + 1);
					string name = val.m_resItem.m_itemData.m_shared.m_name;
					Inventory inventory = ((Humanoid)player).GetInventory();
					int num2 = ((inventory != null) ? inventory.CountItems(name, -1, true) : 0);
					int num3 = num - num2;
					if (num3 > 0)
					{
						WithdrawFromDrawers(list, name, num3);
					}
				}
			}
		}

		private static List<DrawerComponent> FindNearbyDrawers(Vector3 pos)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			List<DrawerComponent> list = new List<DrawerComponent>();
			foreach (DrawerComponent allDrawer in DrawerComponent.AllDrawers)
			{
				if ((Object)(object)allDrawer == (Object)null || (Object)(object)allDrawer._znv == (Object)null || !allDrawer._znv.IsValid())
				{
					continue;
				}
				Component val = (Component)(object)allDrawer;
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				try
				{
					if (Vector3.Distance(val.transform.position, pos) <= 20f)
					{
						list.Add(allDrawer);
					}
				}
				catch
				{
				}
			}
			return list;
		}

		private static int CountInDrawers(List<DrawerComponent> drawers, string itemName)
		{
			if ((Object)(object)ObjectDB.instance == (Object)null)
			{
				return 0;
			}
			int num = 0;
			foreach (DrawerComponent drawer in drawers)
			{
				if ((Object)(object)drawer == (Object)null || (Object)(object)drawer._znv == (Object)null || !drawer._znv.IsValid())
				{
					continue;
				}
				ZDO zDO = drawer._znv.GetZDO();
				if (zDO == null)
				{
					continue;
				}
				string text = zDO.GetString("Prefab", "");
				if (string.IsNullOrEmpty(text))
				{
					continue;
				}
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(text);
				if (!((Object)(object)itemPrefab == (Object)null))
				{
					ItemDrop component = itemPrefab.GetComponent<ItemDrop>();
					if (!((Object)(object)component == (Object)null) && component.m_itemData.m_shared.m_name == itemName)
					{
						num += zDO.GetInt("Amount", 0);
					}
				}
			}
			return num;
		}

		private static int WithdrawFromDrawers(List<DrawerComponent> drawers, string itemName, int needed)
		{
			if ((Object)(object)ObjectDB.instance == (Object)null)
			{
				return 0;
			}
			int num = 0;
			foreach (DrawerComponent drawer in drawers)
			{
				if (num >= needed)
				{
					break;
				}
				if ((Object)(object)drawer == (Object)null || (Object)(object)drawer._znv == (Object)null || !drawer._znv.IsValid())
				{
					continue;
				}
				ZDO zDO = drawer._znv.GetZDO();
				if (zDO == null)
				{
					continue;
				}
				string text = zDO.GetString("Prefab", "");
				if (string.IsNullOrEmpty(text))
				{
					continue;
				}
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(text);
				if ((Object)(object)itemPrefab == (Object)null)
				{
					continue;
				}
				ItemDrop component = itemPrefab.GetComponent<ItemDrop>();
				if ((Object)(object)component == (Object)null || component.m_itemData.m_shared.m_name != itemName)
				{
					continue;
				}
				int num2 = zDO.GetInt("Amount", 0);
				int num3 = Mathf.Min(needed - num, num2);
				if (num3 > 0)
				{
					int num4 = num2 - num3;
					if (!drawer._znv.IsOwner())
					{
						drawer._znv.ClaimOwnership();
					}
					zDO.Set("Amount", num4);
					drawer._znv.InvokeRPC(ZNetView.Everybody, "UpdateIcon", new object[3]
					{
						text,
						num4,
						zDO.GetInt("Quality", 1)
					});
					num += num3;
				}
			}
			return num;
		}
	}
	public class DrawerComponent : MonoBehaviour, Interactable, Hoverable
	{
		private struct DrawerOptions : ISerializableParameter
		{
			public DrawerComponent drawer;

			public Color32 color;

			public int pickupRange;

			public void Serialize(ref ZPackage pkg)
			{
				//IL_0003: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				pkg.Write(Utils.ColorToVec3(color));
				pkg.Write(pickupRange);
			}

			public void Deserialize(ref ZPackage pkg)
			{
				//IL_0003: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				color = Utils.Vec3ToColor(pkg.ReadVector3());
				pickupRange = pkg.ReadInt();
			}
		}

		[HarmonyPatch]
		private static class IsVisible
		{
			[HarmonyTargetMethods]
			[UsedImplicitly]
			private static IEnumerable<MethodInfo> Methods()
			{
				yield return AccessTools.Method(typeof(TextInput), "IsVisible", (Type[])null, (Type[])null);
				yield return AccessTools.Method(typeof(StoreGui), "IsVisible", (Type[])null, (Type[])null);
			}

			[HarmonyPostfix]
			[UsedImplicitly]
			private static void SetTrue(ref bool __result)
			{
				__result |= ShowUI;
			}
		}

		[CompilerGenerated]
		private static class DisplayClassO
		{
			public static WindowFunction CachedWindow;
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static WindowFunction <0>__Window;
		}

		public static readonly List<DrawerComponent> AllDrawers = new List<DrawerComponent>();

		private static readonly FieldInfo F_s_instances = AccessTools.Field(typeof(ItemDrop), "s_instances");

		private static Sprite _defaultSprite;

		private Image _image;

		private TMP_Text _text;

		private Transform _stars;

		private TMP_Text _starsText;

		private Transform _starIcon;

		private static bool ShowUI;

		private static DrawerOptions CurrentOptions;

		private static bool _effectsLogged;

		public ZNetView _znv { get; private set; }

		public string CurrentPrefab
		{
			get
			{
				return _znv.GetZDO().GetString("Prefab", "");
			}
			set
			{
				_znv.GetZDO().Set("Prefab", value);
			}
		}

		public int CurrentAmount
		{
			get
			{
				return _znv.GetZDO().GetInt("Amount", 0);
			}
			set
			{
				_znv.GetZDO().Set("Amount", value);
			}
		}

		public int PickupRange
		{
			get
			{
				return _znv.GetZDO().GetInt("PickupRange", ItemDrawers.DrawerPickupRange.Value);
			}
			set
			{
				_znv.GetZDO().Set("PickupRange", value);
			}
		}

		public int Quality
		{
			get
			{
				return _znv.GetZDO().GetInt("Quality", 1);
			}
			set
			{
				_znv.GetZDO().Set("Quality", value);
			}
		}

		private Color CurrentColor
		{
			get
			{
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_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)
				return Color32.op_Implicit(Utils.Vec3ToColor(_znv.GetZDO().GetVec3("Color", ItemDrawers.DefaultColor.Value)));
			}
			set
			{
				//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_0016: Unknown result type (might be due to invalid IL or missing references)
				_znv.GetZDO().Set("Color", Utils.ColorToVec3(Color32.op_Implicit(value)));
			}
		}

		public bool ItemValid
		{
			get
			{
				if (!string.IsNullOrEmpty(CurrentPrefab))
				{
					return (Object)(object)ObjectDB.instance.GetItemPrefab(CurrentPrefab) != (Object)null;
				}
				return false;
			}
		}

		private int ItemMaxStack => ObjectDB.instance.GetItemPrefab(CurrentPrefab).GetComponent<ItemDrop>().m_itemData.m_shared.m_maxStackSize;

		private string LocalizedName => ObjectDB.instance.GetItemPrefab(CurrentPrefab).GetComponent<ItemDrop>().m_itemData.m_shared.m_name.Localize();

		private bool DoRepeat
		{
			get
			{
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: Expected O, but got Unknown
				if (Object.op_Implicit((Object)Player.m_localPlayer) && ItemValid)
				{
					return PickupRange > 0;
				}
				return false;
			}
		}

		public bool ItemValidCheck(string prefab)
		{
			if (!string.IsNullOrEmpty(prefab))
			{
				return (Object)(object)ObjectDB.instance.GetItemPrefab(prefab) != (Object)null;
			}
			return false;
		}

		private void OnDestroy()
		{
			AllDrawers.Remove(this);
		}

		private void Awake()
		{
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			_znv = ((Component)this).GetComponent<ZNetView>();
			if (_znv.IsValid())
			{
				AllDrawers.Add(this);
				_image = ((Component)((Component)this).transform.Find("Cube/Canvas/Image")).GetComponent<Image>();
				if ((Object)(object)_defaultSprite == (Object)null)
				{
					_defaultSprite = _image.sprite;
				}
				_text = ((Component)((Component)this).transform.Find("Cube/Canvas/Text")).GetComponent<TMP_Text>();
				if ((Object)(object)ItemDrawers.NorseFont != (Object)null)
				{
					_text.font = ItemDrawers.NorseFont;
				}
				_text.fontSize /= 2f;
				((Graphic)_text).color = CurrentColor;
				_stars = ((Component)this).transform.Find("Cube/Canvas/Stars");
				_starsText = ((Component)_stars.Find("Quality")).GetComponent<TMP_Text>();
				_starIcon = _stars.Find("Img");
				ApplyTextEffects(_text);
				ApplyTextEffects(_starsText);
				_znv.Register<string, int, int>("AddItem_Request", (Action<long, string, int, int>)RPC_AddItem);
				_znv.Register<string, int, int>("AddItem_Player", (Action<long, string, int, int>)RPC_AddItem_Player);
				_znv.Register<int>("WithdrawItem_Request", (Action<long, int>)RPC_WithdrawItem_Request);
				_znv.Register<string, int, int>("UpdateIcon", (Action<long, string, int, int>)RPC_UpdateIcon);
				_znv.Register<int>("ForceRemove", (Action<long, int>)RPC_ForceRemove);
				_znv.Register<DrawerOptions>("ApplyOptions", (Action<long, DrawerOptions>)RPC_ApplyOptions);
				RPC_UpdateIcon(0L, CurrentPrefab, CurrentAmount, Quality);
				float num = Random.Range(2.5f, 3f);
				((MonoBehaviour)this).InvokeRepeating("Repeat", num, num);
			}
		}

		private static void ApplyTextEffects(TMP_Text text)
		{
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)text == (Object)null)
			{
				return;
			}
			try
			{
				Material fontMaterial = text.fontMaterial;
				if ((Object)(object)fontMaterial == (Object)null)
				{
					return;
				}
				Shader val = Shader.Find("TextMeshPro/Distance Field") ?? Shader.Find("Hidden/TextMeshPro/Distance Field");
				if ((Object)(object)val != (Object)null && (Object)(object)fontMaterial.shader != (Object)(object)val)
				{
					string text2 = (((Object)(object)fontMaterial.shader != (Object)null) ? ((Object)fontMaterial.shader).name : "null");
					fontMaterial.shader = val;
					if (!_effectsLogged)
					{
						_effectsLogged = true;
						ItemDrawers.Instance.Log.LogInfo((object)("ApplyTextEffects: shader was '" + text2 + "', switched to '" + ((Object)val).name + "'"));
					}
				}
				else if ((Object)(object)val == (Object)null && !_effectsLogged)
				{
					_effectsLogged = true;
					ItemDrawers.Instance.Log.LogInfo((object)"ApplyTextEffects: full SDF shader not found — outline/shadow will not work.");
				}
				if (ItemDrawers.TextOutlineEnabled != null && ItemDrawers.TextOutlineEnabled.Value)
				{
					fontMaterial.EnableKeyword("OUTLINE_ON");
					fontMaterial.SetFloat("_OutlineWidth", ItemDrawers.TextOutlineWidth.Value);
					fontMaterial.SetColor("_OutlineColor", ItemDrawers.TextOutlineColor.Value);
					fontMaterial.SetFloat("_OutlineSoftness", 0f);
				}
				if (ItemDrawers.TextShadowEnabled != null && ItemDrawers.TextShadowEnabled.Value)
				{
					fontMaterial.EnableKeyword("UNDERLAY_ON");
					fontMaterial.SetColor("_UnderlayColor", ItemDrawers.TextShadowColor.Value);
					fontMaterial.SetFloat("_UnderlayOffsetX", ItemDrawers.TextShadowOffset.Value);
					fontMaterial.SetFloat("_UnderlayOffsetY", 0f - ItemDrawers.TextShadowOffset.Value);
					fontMaterial.SetFloat("_UnderlaySoftness", ItemDrawers.TextShadowSoftness.Value);
					fontMaterial.SetFloat("_UnderlayDilate", 0f);
				}
				text.havePropertiesChanged = true;
				((Graphic)text).SetAllDirty();
			}
			catch (Exception ex)
			{
				try
				{
					ItemDrawers.Instance.Log.LogInfo((object)("ApplyTextEffects: " + ex.Message));
				}
				catch
				{
				}
			}
		}

		private void RPC_ApplyOptions(long sender, DrawerOptions options)
		{
			//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_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if (_znv.IsOwner())
			{
				CurrentColor = Color32.op_Implicit(options.color);
				PickupRange = Mathf.Min(ItemDrawers.MaxDrawerPickupRange.Value, options.pickupRange);
			}
			((Graphic)_text).color = Color32.op_Implicit(options.color);
		}

		private void RPC_ForceRemove(long sender, int amount)
		{
			amount = Mathf.Min(amount, CurrentAmount);
			CurrentAmount -= amount;
			_znv.InvokeRPC(ZNetView.Everybody, "UpdateIcon", new object[3] { CurrentPrefab, CurrentAmount, Quality });
		}

		private void RPC_WithdrawItem_Request(long sender, int amount)
		{
			if (CurrentAmount <= 0 || !ItemValid)
			{
				CurrentPrefab = "";
				CurrentAmount = 0;
				Quality = 1;
				_znv.InvokeRPC(ZNetView.Everybody, "UpdateIcon", new object[3] { "", 0, 0 });
			}
			else if (amount > 0)
			{
				amount = Mathf.Min(amount, CurrentAmount);
				CurrentAmount -= amount;
				_znv.InvokeRPC(sender, "AddItem_Player", new object[3] { CurrentPrefab, amount, Quality });
				_znv.InvokeRPC(ZNetView.Everybody, "UpdateIcon", new object[3] { CurrentPrefab, CurrentAmount, Quality });
			}
		}

		private void RPC_AddItem_Player(long _, string prefab, int amount, int quality)
		{
			Utils.InstantiateItem(ZNetScene.instance.GetPrefab(prefab), amount, quality);
		}

		private void RPC_UpdateIcon(long _, string prefab, int amount, int quality)
		{
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			if (!ItemValidCheck(prefab))
			{
				_image.sprite = _defaultSprite;
				((Component)_stars).gameObject.SetActive(false);
				((Component)_text).gameObject.SetActive(false);
				return;
			}
			_image.sprite = ObjectDB.instance.GetItemPrefab(prefab).GetComponent<ItemDrop>().m_itemData.GetIcon();
			_text.text = amount.ToString();
			((Component)_text).gameObject.SetActive(true);
			((Component)_stars).gameObject.SetActive(quality > 1);
			if (quality > 1)
			{
				_starsText.text = quality.ToString();
				((Component)_starIcon).GetComponent<RectTransform>();
				_starIcon.localPosition = new Vector3((quality >= 10) ? 9f : 0f, 5.25f, 0f);
			}
		}

		private void RPC_AddItem(long sender, string prefab, int amount, int quality)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			if (!_znv.IsOwner() || amount <= 0)
			{
				return;
			}
			quality = Math.Max(1, quality);
			string currentPrefab = CurrentPrefab;
			if (ItemValid && (currentPrefab != prefab || Quality != quality))
			{
				Utils.InstantiateAtPos(ZNetScene.instance.GetPrefab(currentPrefab), CurrentAmount, Quality, ((Component)this).transform.position + Vector3.up * 1.5f);
				return;
			}
			int num = (CurrentAmount = (ItemValid ? (CurrentAmount + amount) : amount));
			int num3 = num;
			if (currentPrefab != prefab)
			{
				CurrentPrefab = prefab;
				Quality = quality;
			}
			_znv.InvokeRPC(ZNetView.Everybody, "UpdateIcon", new object[3] { prefab, num3, quality });
		}

		private void Repeat()
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_znv == (Object)null || !_znv.IsValid() || !_znv.IsOwner() || !DoRepeat)
			{
				return;
			}
			string currentPrefab = CurrentPrefab;
			int quality = Quality;
			Vector3 vector = ((Component)this).transform.position + Vector3.up;
			IEnumerable<ItemDrop> enumerable = (IEnumerable<ItemDrop>)F_s_instances.GetValue(null);
			if (enumerable == null)
			{
				return;
			}
			foreach (ItemDrop item in enumerable.Where((ItemDrop drop) => Vector3.Distance(((Component)drop).transform.position, vector) < (float)PickupRange))
			{
				if (((Object)item.m_itemData.m_dropPrefab).name != currentPrefab || item.m_itemData.m_quality != quality)
				{
					continue;
				}
				if (!item.CanPickup(false))
				{
					item.RequestOwn();
					continue;
				}
				Object.Instantiate<GameObject>(ItemDrawers.Explosion, ((Component)item).transform.position, Quaternion.identity);
				int stack = item.m_itemData.m_stack;
				ZNetView component = ((Component)item).GetComponent<ZNetView>();
				if (!((Object)(object)component == (Object)null) && component.IsValid())
				{
					component.ClaimOwnership();
					ZNetScene.instance.Destroy(((Component)item).gameObject);
					CurrentAmount += stack;
					_znv.InvokeRPC(ZNetView.Everybody, "UpdateIcon", new object[3] { currentPrefab, CurrentAmount, quality });
				}
			}
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false))
			{
				return true;
			}
			if (((Character)user).IsCrouching())
			{
				CurrentOptions.drawer = this;
				CurrentOptions.color = Color32.op_Implicit(CurrentColor);
				CurrentOptions.pickupRange = PickupRange;
				ShowUI = true;
				return true;
			}
			if (!ItemValid)
			{
				return false;
			}
			if (Input.GetKey((KeyCode)308))
			{
				_znv.InvokeRPC("WithdrawItem_Request", new object[1] { 1 });
				return true;
			}
			if (Input.GetKey((KeyCode)304))
			{
				int quality = Quality;
				int num = Utils.CustomCountItems(CurrentPrefab, quality);
				if (num <= 0)
				{
					return true;
				}
				Utils.CustomRemoveItems(CurrentPrefab, num, quality);
				_znv.InvokeRPC("AddItem_Request", new object[3] { CurrentPrefab, num, quality });
				return true;
			}
			_znv.InvokeRPC("WithdrawItem_Request", new object[1] { ItemMaxStack });
			return true;
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			GameObject dropPrefab = item.m_dropPrefab;
			string text = (((Object)(object)dropPrefab != (Object)null) ? ((Object)dropPrefab).name : null);
			if (string.IsNullOrEmpty(text))
			{
				return false;
			}
			if (ItemDrawers.ExcludeSet.Contains(text) && !Player.m_debugMode)
			{
				return false;
			}
			if (!string.IsNullOrEmpty(CurrentPrefab) && (CurrentPrefab != text || Quality != item.m_quality))
			{
				return false;
			}
			int stack = item.m_stack;
			if (stack <= 0)
			{
				return false;
			}
			user.GetInventory().RemoveItem(item);
			_znv.InvokeRPC("AddItem_Request", new object[3] { text, stack, item.m_quality });
			return true;
		}

		public string GetHoverText()
		{
			StringBuilder stringBuilder = new StringBuilder();
			if (((Character)Player.m_localPlayer).IsCrouching())
			{
				stringBuilder.AppendLine("[<color=yellow><b>$KEY_Use</b></color>] open settings");
				return stringBuilder.ToString().Localize();
			}
			if (!ItemValid)
			{
				stringBuilder.AppendLine("<color=yellow><b>Use Hotbar to add item</b></color>");
				return stringBuilder.ToString().Localize();
			}
			int quality = Quality;
			string arg = ((quality > 1) ? $" (Quality: {quality})" : "");
			stringBuilder.AppendLine($"<color=yellow><b>{LocalizedName}{arg}</b></color> ({CurrentAmount})");
			stringBuilder.AppendLine("<color=yellow><b>Use Hotbar to add item</b></color>\n");
			if (CurrentAmount <= 0)
			{
				stringBuilder.AppendLine("[<color=yellow><b>$KEY_Use</b></color>] or [<color=yellow><b>Left Alt + $KEY_Use</b></color>] to clear");
				stringBuilder.AppendLine($"[<color=yellow><b>Left Shift + $KEY_Use</b></color>] to deposit all <color=yellow><b>{LocalizedName}</b></color> ({Utils.CustomCountItems(CurrentPrefab, quality)})");
				return stringBuilder.ToString().Localize();
			}
			stringBuilder.AppendLine($"[<color=yellow><b>$KEY_Use</b></color>] to withdraw stack ({ItemMaxStack})");
			stringBuilder.AppendLine("[<color=yellow><b>Left Alt + $KEY_Use</b></color>] to withdraw single item");
			stringBuilder.AppendLine($"[<color=yellow><b>Left Shift + $KEY_Use</b></color>] to deposit all <color=yellow><b>{LocalizedName}{arg}</b></color> ({Utils.CustomCountItems(CurrentPrefab, quality)})");
			return stringBuilder.ToString().Localize();
		}

		public string GetHoverName()
		{
			return "Item Drawer";
		}

		public static void ProcessInput()
		{
			if (Input.GetKeyDown((KeyCode)27) && ShowUI)
			{
				ShowUI = false;
				Menu.instance.OnClose();
			}
		}

		public static void ProcessGUI()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Expected O, but got Unknown
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			if (!ShowUI)
			{
				return;
			}
			GUI.backgroundColor = Color.white;
			Rect val = new Rect((float)Screen.width / 2f - 150f, (float)Screen.height / 2f - 150f, 300f, 300f);
			object obj = DisplayClassO.CachedWindow;
			if (obj == null)
			{
				object obj2 = <>O.<0>__Window;
				if (obj2 == null)
				{
					WindowFunction val2 = Window;
					<>O.<0>__Window = val2;
					obj2 = (object)val2;
				}
				DisplayClassO.CachedWindow = (WindowFunction)obj2;
				obj = obj2;
			}
			GUI.Window(218102318, val, (WindowFunction)obj, "Item Drawer Options");
		}

		private static void Window(int id)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)CurrentOptions.drawer == (Object)null || !CurrentOptions.drawer._znv.IsValid())
			{
				ShowUI = false;
				return;
			}
			GUILayout.Label($"Current Drawer: <color=yellow><b>{CurrentOptions.drawer.LocalizedName}</b></color> ({CurrentOptions.drawer.CurrentAmount})", Array.Empty<GUILayoutOption>());
			byte r = CurrentOptions.color.r;
			byte g = CurrentOptions.color.g;
			byte b = CurrentOptions.color.b;
			GUILayout.Label($"Text Color: <color=#{r:X2}{g:X2}{b:X2}><b>0123456789</b></color>", Array.Empty<GUILayoutOption>());
			GUILayout.Label($"R: {r}", Array.Empty<GUILayoutOption>());
			r = (byte)GUILayout.HorizontalSlider((float)(int)r, 0f, 255f, Array.Empty<GUILayoutOption>());
			GUILayout.Label($"G: {g}", Array.Empty<GUILayoutOption>());
			g = (byte)GUILayout.HorizontalSlider((float)(int)g, 0f, 255f, Array.Empty<GUILayoutOption>());
			GUILayout.Label($"B: {b}", Array.Empty<GUILayoutOption>());
			b = (byte)GUILayout.HorizontalSlider((float)(int)b, 0f, 255f, Array.Empty<GUILayoutOption>());
			CurrentOptions.color = new Color32(r, g, b, byte.MaxValue);
			int pickupRange = CurrentOptions.pickupRange;
			GUILayout.Space(16f);
			GUILayout.Label(string.Format("Pickup Range: <color={0}><b>{1}</b></color>", (pickupRange > 0) ? "lime" : "red", pickupRange), Array.Empty<GUILayoutOption>());
			pickupRange = (int)GUILayout.HorizontalSlider((float)pickupRange, 0f, (float)ItemDrawers.MaxDrawerPickupRange.Value, Array.Empty<GUILayoutOption>());
			CurrentOptions.pickupRange = pickupRange;
			GUILayout.Space(16f);
			if (GUILayout.Button("<color=lime>Apply</color>", Array.Empty<GUILayoutOption>()))
			{
				CurrentOptions.drawer._znv.InvokeRPC(ZNetView.Everybody, "ApplyOptions", new object[1] { CurrentOptions });
				ShowUI = false;
			}
		}
	}
	[BepInPlugin("kg.ItemDrawers", "BROHEIM ItemDrawers", "1.0.0")]
	public class ItemDrawers : BaseUnityPlugin
	{
		public static ItemDrawers Instance;

		private static Harmony _harmony;

		public static ConfigEntry<int> DrawerPickupRange;

		public static ConfigEntry<int> MaxDrawerPickupRange;

		public static ConfigEntry<Vector3> DefaultColor;

		public static ConfigEntry<string> ExcludeList;

		public static HashSet<string> ExcludeSet = new HashSet<string>();

		public static ConfigEntry<bool> TextOutlineEnabled;

		public static ConfigEntry<float> TextOutlineWidth;

		public static ConfigEntry<Color> TextOutlineColor;

		public static ConfigEntry<bool> TextShadowEnabled;

		public static ConfigEntry<Color> TextShadowColor;

		public static ConfigEntry<float> TextShadowOffset;

		public static ConfigEntry<float> TextShadowSoftness;

		public static GameObject Explosion;

		public static TMP_FontAsset NorseFont;

		private static AssetBundle _bundle;

		private static readonly string[] DrawerPrefabNames = new string[7] { "kg_ItemDrawer_Wood", "kg_ItemDrawer_Stone", "kg_ItemDrawer_Marble", "kg_ItemDrawerPanel_Wood", "kg_ItemDrawerPanel_Stone", "kg_ItemDrawerPanel_Marble", "kg_ItemDrawer_NoModel" };

		private static readonly (string name, string item, int amount)[] DrawerRecipes = new(string, string, int)[7]
		{
			("$piece_kg_ItemDrawer_Wood", "Wood", 10),
			("$piece_kg_ItemDrawer_Stone", "Stone", 10),
			("$piece_kg_ItemDrawer_Marble", "BlackMarble", 10),
			("$piece_kg_ItemDrawerPanel_Wood", "Wood", 10),
			("$piece_kg_ItemDrawerPanel_Stone", "Stone", 10),
			("$piece_kg_ItemDrawerPanel_Marble", "BlackMarble", 10),
			("$piece_kg_ItemDrawer_NoModel", "GreydwarfEye", 10)
		};

		internal ManualLogSource Log => ((BaseUnityPlugin)this).Logger;

		internal static IReadOnlyList<string> AllDrawerPrefabNames => DrawerPrefabNames;

		internal static IReadOnlyList<(string name, string item, int amount)> AllDrawerRecipes => DrawerRecipes;

		private void Awake()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Expected O, but got Unknown
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Expected O, but got Unknown
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Expected O, but got Unknown
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Expected O, but got Unknown
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e1: Expected O, but got Unknown
			//IL_03d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03db: Expected O, but got Unknown
			Instance = this;
			PieceManager.Instance.AddPieceCategory("itemdrawers");
			ExcludeList = ((BaseUnityPlugin)this).Config.Bind<string>("General", "ExcludeList", "", "List of items to exclude in the drawer. Leave blank to include all items.");
			ExcludeList.SettingChanged += ResetList;
			ResetList(null, null);
			DrawerPickupRange = ((BaseUnityPlugin)this).Config.Bind<int>("General", "DrawerPickupRange", 4, "Range at which you can pick up items from the drawer.");
			MaxDrawerPickupRange = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MaxDrawerPickupRange", 100, "Maximum range at which you can pick up items from the drawer.");
			DefaultColor = ((BaseUnityPlugin)this).Config.Bind<Vector3>("General", "DefaultColor", new Vector3(0.039f, 0.729f, 0.71f), "Default color of the drawer text.");
			TextOutlineEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("TextEffects", "OutlineEnabled", true, "Draw a black outline around the item-count digits for readability.");
			TextOutlineWidth = ((BaseUnityPlugin)this).Config.Bind<float>("TextEffects", "OutlineWidth", 0.15f, new ConfigDescription("Outline thickness (0.0–1.0).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			TextOutlineColor = ((BaseUnityPlugin)this).Config.Bind<Color>("TextEffects", "OutlineColor", Color.black, "Outline color.");
			TextShadowEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("TextEffects", "ShadowEnabled", true, "Draw a drop shadow under the item-count digits for readability.");
			TextShadowColor = ((BaseUnityPlugin)this).Config.Bind<Color>("TextEffects", "ShadowColor", new Color(0f, 0f, 0f, 0.6f), "Shadow color (alpha controls opacity).");
			TextShadowOffset = ((BaseUnityPlugin)this).Config.Bind<float>("TextEffects", "ShadowOffset", 0.4f, new ConfigDescription("Shadow offset distance (0.0–1.0).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			TextShadowSoftness = ((BaseUnityPlugin)this).Config.Bind<float>("TextEffects", "ShadowSoftness", 0.15f, new ConfigDescription("Shadow softness/blur (0.0–1.0).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			_bundle = LoadAssetBundle("kg_itemdrawers");
			Explosion = _bundle.LoadAsset<GameObject>("kg_ItemDrawer_Explosion");
			NorseFont = NorseFontLoader.Load();
			StationAuto.CfgEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("StationAuto", "Enabled", true, "Master switch for auto-feed/deposit. Off = station integration does nothing.");
			StationAuto.CfgRadius = ((BaseUnityPlugin)this).Config.Bind<float>("StationAuto", "Radius", 8f, new ConfigDescription("Range (m) to search ItemDrawers around a station.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f), Array.Empty<object>()));
			StationAuto.CfgSmelterRadius = ((BaseUnityPlugin)this).Config.Bind<float>("StationAuto", "SmelterRadius", 15f, new ConfigDescription("Range (m) for smelters/kilns pulling from ItemDrawers.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f), Array.Empty<object>()));
			StationAuto.CfgFeed = ((BaseUnityPlugin)this).Config.Bind<bool>("StationAuto", "FeedFromDrawers", true, "Stations pull fuel/materials directly from nearby ItemDrawers.");
			StationAuto.CfgDeposit = ((BaseUnityPlugin)this).Config.Bind<bool>("StationAuto", "DepositToDrawers", true, "Cooking stations/beehives/sap collectors push finished output into matching nearby drawers.");
			StationAuto.CfgDebug = ((BaseUnityPlugin)this).Config.Bind<bool>("StationAuto", "DebugLogs", false, "Verbose logging.");
			StationAuto.VReflect.Init();
			QuickStackBridge.CfgEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("QuickStackBridge", "Enabled", true, "Master switch.");
			QuickStackBridge.CfgQuickStackToDrawers = ((BaseUnityPlugin)this).Config.Bind<bool>("QuickStackBridge", "QuickStackToDrawers", true, "Quick Stack (P) also deposits stackable items into matching nearby ItemDrawers.");
			QuickStackBridge.CfgRestockFromDrawers = ((BaseUnityPlugin)this).Config.Bind<bool>("QuickStackBridge", "RestockFromDrawers", true, "Restock (L) also tops up partially filled stacks from matching nearby ItemDrawers.");
			QuickStackBridge.CfgDebug = ((BaseUnityPlugin)this).Config.Bind<bool>("QuickStackBridge", "DebugLogs", false, "Verbose logging.");
			Harmony val = new Harmony("kg.ItemDrawers");
			_harmony = val;
			val.PatchAll(Assembly.GetExecutingAssembly());
			AppDomain.CurrentDomain.AssemblyLoad += OnAssemblyLoaded;
			TryInitQuickStackBridge();
			Log.LogInfo((object)"BROHEIM ItemDrawers loaded.");
		}

		private static void OnAssemblyLoaded(object sender, AssemblyLoadEventArgs args)
		{
			if (!(args.LoadedAssembly.GetName().Name != "QuickStackStore"))
			{
				TryInitQuickStackBridge();
				AppDomain.CurrentDomain.AssemblyLoad -= OnAssemblyLoaded;
			}
		}

		private static void TryInitQuickStackBridge()
		{
			if (!QuickStackBridge.QssReflect.Ready)
			{
				QuickStackBridge.QssReflect.Init();
				if (QuickStackBridge.QssReflect.Ready)
				{
					QuickStackBridgePatch.Apply(_harmony);
					RestockBridgePatch.Apply(_harmony);
					Instance.Log.LogInfo((object)"QuickStackBridge patches applied (deferred).");
				}
			}
		}

		private void OnGUI()
		{
			DrawerComponent.ProcessGUI();
		}

		private void Update()
		{
			DrawerComponent.ProcessInput();
		}

		private void ResetList(object sender, EventArgs e)
		{
			ExcludeSet = new HashSet<string>(ExcludeList.Value.Replace(" ", "").Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries));
		}

		private static AssetBundle LoadAssetBundle(string filename)
		{
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			string name = executingAssembly.GetManifestResourceNames().First((string s) => s.EndsWith(filename + ".bundle") || s.EndsWith(filename));
			using Stream stream = executingAssembly.GetManifestResourceStream(name);
			return AssetBundle.LoadFromStream(stream);
		}

		internal static GameObject GetDrawerPrefab(string name)
		{
			return _bundle.LoadAsset<GameObject>(name);
		}
	}
	public static class NorseFontLoader
	{
		private static TMP_FontAsset _cached;

		private static bool _tried;

		public static TMP_FontAsset Load()
		{
			if (_tried)
			{
				return _cached;
			}
			_tried = true;
			try
			{
				Assembly executingAssembly = Assembly.GetExecutingAssembly();
				string text = executingAssembly.GetManifestResourceNames().FirstOrDefault((string s) => s.EndsWith("Norse-Bold.ttf") || s.EndsWith("Norse-Bold"));
				if (text == null)
				{
					ItemDrawers.Instance.Log.LogInfo((object)"NorseFontLoader: Norse-Bold.ttf not found in embedded resources.");
					return null;
				}
				using Stream stream = executingAssembly.GetManifestResourceStream(text);
				using MemoryStream memoryStream = new MemoryStream();
				stream.CopyTo(memoryStream);
				byte[] bytes = memoryStream.ToArray();
				string text2 = Path.Combine(Application.temporaryCachePath, "BROHEIM_Norse-Bold.ttf");
				File.WriteAllBytes(text2, bytes);
				try
				{
					MethodInfo methodInfo = (from m in typeof(TMP_FontAsset).GetMethods(BindingFlags.Static | BindingFlags.Public)
						where m.Name == "CreateFontAsset" && m.GetParameters().Length == 7 && m.GetParameters()[0].ParameterType == typeof(string)
						select m).FirstOrDefault();
					if (methodInfo != null)
					{
						ParameterInfo[] parameters = methodInfo.GetParameters();
						object[] array = new object[parameters.Length];
						array[0] = text2;
						array[1] = 0;
						array[2] = 90;
						array[3] = 9;
						Type parameterType = parameters[4].ParameterType;
						array[4] = Enum.ToObject(parameterType, 4165);
						array[5] = 1024;
						array[6] = 1024;
						object? obj = methodInfo.Invoke(null, array);
						TMP_FontAsset val = (TMP_FontAsset)((obj is TMP_FontAsset) ? obj : null);
						if ((Object)(object)val != (Object)null)
						{
							val.atlasPopulationMode = (AtlasPopulationMode)1;
							Object.DontDestroyOnLoad((Object)(object)val);
							_cached = val;
							ItemDrawers.Instance.Log.LogInfo((object)"NorseFontLoader: loaded Norse font via file path (Strategy 1).");
							return _cached;
						}
					}
				}
				catch (Exception ex)
				{
					ItemDrawers.Instance.Log.LogInfo((object)("NorseFontLoader: Strategy 1 failed (" + ex.Message + ")."));
				}
				try
				{
					Font val2 = Font.CreateDynamicFontFromOSFont(text2, 90);
					if ((Object)(object)val2 != (Object)null)
					{
						val2.RequestCharactersInTexture("0123456789", 90);
						MethodInfo method = typeof(TMP_FontAsset).GetMethod("CreateFontAsset", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(Font) }, null);
						if (method != null)
						{
							object? obj2 = method.Invoke(null, new object[1] { val2 });
							TMP_FontAsset val3 = (TMP_FontAsset)((obj2 is TMP_FontAsset) ? obj2 : null);
							if ((Object)(object)val3 != (Object)null)
							{
								val3.atlasPopulationMode = (AtlasPopulationMode)1;
								Object.DontDestroyOnLoad((Object)(object)val3);
								Object.DontDestroyOnLoad((Object)(object)val2);
								_cached = val3;
								ItemDrawers.Instance.Log.LogInfo((object)"NorseFontLoader: loaded Norse font via Unity Font (Strategy 2).");
								return _cached;
							}
						}
					}
				}
				catch (Exception ex2)
				{
					ItemDrawers.Instance.Log.LogInfo((object)("NorseFontLoader: Strategy 2 failed (" + ex2.Message + ")."));
				}
				try
				{
					Font val4 = Font.CreateDynamicFontFromOSFont("Norse-Bold", 90);
					if ((Object)(object)val4 != (Object)null)
					{
						val4.RequestCharactersInTexture("0123456789", 90);
						MethodInfo method2 = typeof(TMP_FontAsset).GetMethod("CreateFontAsset", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(Font) }, null);
						if (method2 != null)
						{
							object? obj3 = method2.Invoke(null, new object[1] { val4 });
							TMP_FontAsset val5 = (TMP_FontAsset)((obj3 is TMP_FontAsset) ? obj3 : null);
							if ((Object)(object)val5 != (Object)null)
							{
								val5.atlasPopulationMode = (AtlasPopulationMode)1;
								Object.DontDestroyOnLoad((Object)(object)val5);
								Object.DontDestroyOnLoad((Object)(object)val4);
								_cached = val5;
								ItemDrawers.Instance.Log.LogInfo((object)"NorseFontLoader: loaded Norse font via OS font name (Strategy 3).");
								return _cached;
							}
						}
					}
				}
				catch (Exception ex3)
				{
					ItemDrawers.Instance.Log.LogInfo((object)("NorseFontLoader: Strategy 3 failed (" + ex3.Message + ")."));
				}
				ItemDrawers.Instance.Log.LogInfo((object)"NorseFontLoader: all strategies failed, using default font with size/color changes only.");
				return null;
			}
			catch (Exception ex4)
			{
				ItemDrawers.Instance.Log.LogInfo((object)("NorseFontLoader: could not load Norse font (" + ex4.Message + "), using default font with size/color changes."));
				return null;
			}
		}
	}
	[HarmonyPatch(typeof(ZNetScene), "Awake")]
	internal static class ZNetScene_Awake_Patch
	{
		private static readonly FieldInfo F_namedPrefabs = AccessTools.Field(typeof(ZNetScene), "m_namedPrefabs");

		private static readonly FieldInfo F_prefabs = AccessTools.Field(typeof(ZNetScene), "m_prefabs");

		[UsedImplicitly]
		private static void Postfix(ZNetScene __instance)
		{
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<int, GameObject> dictionary = (Dictionary<int, GameObject>)F_namedPrefabs.GetValue(__instance);
			List<GameObject> list = (List<GameObject>)F_prefabs.GetValue(__instance);
			dictionary[StringExtensionMethods.GetStableHashCode(((Object)ItemDrawers.Explosion).name)] = ItemDrawers.Explosion;
			foreach (string allDrawerPrefabName in ItemDrawers.AllDrawerPrefabNames)
			{
				GameObject drawerPrefab = ItemDrawers.GetDrawerPrefab(allDrawerPrefabName);
				if ((Object)(object)drawerPrefab == (Object)null)
				{
					ItemDrawers.Instance.Log.LogWarning((object)("Drawer prefab '" + allDrawerPrefabName + "' not found in AssetBundle!"));
					continue;
				}
				Piece val = drawerPrefab.GetComponent<Piece>();
				if ((Object)(object)val == (Object)null)
				{
					val = drawerPrefab.AddComponent<Piece>();
				}
				if (allDrawerPrefabName.Contains("Wood") || allDrawerPrefabName.Contains("NoModel"))
				{
					GameObject prefab = __instance.GetPrefab("woodwall");
					if ((Object)(object)prefab != (Object)null)
					{
						val.m_placeEffect = prefab.GetComponent<Piece>().m_placeEffect;
					}
				}
				else if (allDrawerPrefabName.Contains("Stone"))
				{
					GameObject prefab2 = __instance.GetPrefab("stone_wall_1x1");
					if ((Object)(object)prefab2 != (Object)null)
					{
						val.m_placeEffect = prefab2.GetComponent<Piece>().m_placeEffect;
					}
				}
				else if (allDrawerPrefabName.Contains("Marble"))
				{
					GameObject prefab3 = __instance.GetPrefab("blackmarble_1x1");
					if ((Object)(object)prefab3 != (Object)null)
					{
						val.m_placeEffect = prefab3.GetComponent<Piece>().m_placeEffect;
					}
				}
				if ((Object)(object)drawerPrefab.GetComponent<DrawerComponent>() == (Object)null)
				{
					drawerPrefab.AddComponent<DrawerComponent>();
				}
				int stableHashCode = StringExtensionMethods.GetStableHashCode(allDrawerPrefabName);
				dictionary[stableHashCode] = drawerPrefab;
				if (!list.Contains(drawerPrefab))
				{
					list.Add(drawerPrefab);
				}
			}
			PieceCategory category = (PieceCategory)(((??)PieceManager.Instance.GetPieceCategory("itemdrawers")) ?? 4);
			foreach (string allDrawerPrefabName2 in ItemDrawers.AllDrawerPrefabNames)
			{
				GameObject drawerPrefab2 = ItemDrawers.GetDrawerPrefab(allDrawerPrefabName2);
				if (!((Object)(object)drawerPrefab2 == (Object)null))
				{
					Piece component = drawerPrefab2.GetComponent<Piece>();
					if ((Object)(object)component != (Object)null)
					{
						component.m_category = category;
					}
				}
			}
			ItemDrawers.Instance.Log.LogInfo((object)$"BROHEIM ItemDrawers: registered {ItemDrawers.AllDrawerPrefabNames.Count} drawer prefabs.");
		}
	}
	[HarmonyPatch(typeof(ObjectDB), "Awake")]
	internal static class ObjectDB_Awake_Patch
	{
		[UsedImplicitly]
		private static void Postfix(ObjectDB __instance)
		{
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Expected O, but got Unknown
			if ((Object)(object)__instance.GetItemPrefab("YmirRemains") == (Object)null)
			{
				return;
			}
			GameObject itemPrefab = __instance.GetItemPrefab("Hammer");
			if ((Object)(object)itemPrefab == (Object)null)
			{
				return;
			}
			PieceTable val = itemPrefab.GetComponent<ItemDrop>()?.m_itemData.m_shared.m_buildPieces;
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			IReadOnlyList<(string, string, int)> allDrawerRecipes = ItemDrawers.AllDrawerRecipes;
			IReadOnlyList<string> allDrawerPrefabNames = ItemDrawers.AllDrawerPrefabNames;
			for (int i = 0; i < allDrawerPrefabNames.Count && i < allDrawerRecipes.Count; i++)
			{
				string text = allDrawerPrefabNames[i];
				(string, string, int) tuple = allDrawerRecipes[i];
				string item = tuple.Item1;
				string item2 = tuple.Item2;
				int item3 = tuple.Item3;
				GameObject drawerPrefab = ItemDrawers.GetDrawerPrefab(text);
				if ((Object)(object)drawerPrefab == (Object)null)
				{
					continue;
				}
				Piece component = drawerPrefab.GetComponent<Piece>();
				if ((Object)(object)component == (Object)null)
				{
					continue;
				}
				component.m_name = item;
				GameObject itemPrefab2 = __instance.GetItemPrefab(item2);
				if ((Object)(object)itemPrefab2 != (Object)null)
				{
					component.m_resources = (Requirement[])(object)new Requirement[1]
					{
						new Requirement
						{
							m_resItem = itemPrefab2.GetComponent<ItemDrop>(),
							m_amount = item3,
							m_recover = true
						}
					};
				}
				component.m_craftingStation = null;
				component.m_allowedInDungeons = true;
				int stableHashCode = StringExtensionMethods.GetStableHashCode(text);
				bool flag = false;
				foreach (GameObject piece in val.m_pieces)
				{
					if ((Object)(object)piece != (Object)null && StringExtensionMethods.GetStableHashCode(((Object)piece).name) == stableHashCode)
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					val.m_pieces.Add(drawerPrefab);
				}
			}
			ItemDrawers.Instance.Log.LogInfo((object)"BROHEIM ItemDrawers: added drawer pieces to hammer build table.");
		}
	}
	[HarmonyPatch(typeof(Piece), "DropResources")]
	public static class Piece_OnDestroy_Patch
	{
		[UsedImplicitly]
		private static void Postfix(Piece __instance)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			DrawerComponent component = ((Component)__instance).gameObject.GetComponent<DrawerComponent>();
			if ((Object)(object)component != (Object)null && component.ItemValid && component.CurrentAmount > 0)
			{
				Utils.InstantiateAtPos(ZNetScene.instance.GetPrefab(component.CurrentPrefab), component.CurrentAmount, 1, ((Component)__instance).transform.position + Vector3.up);
			}
		}
	}
	internal static class QuickStackBridge
	{
		internal static class QssReflect
		{
			internal static bool Ready;

			internal static MethodInfo GetPlayerConfig;

			internal static MethodInfo IsItemNameOrSlotFavorited;

			private static Type _qsNested;

			private static Type _rsNested;

			private static FieldInfo _fQuickStackRange;

			private static FieldInfo _fRestockRange;

			private static FieldInfo _fQuickStackHotbar;

			private static FieldInfo _fRestockHotbar;

			private static Type _qssConfigType;

			internal static void Init()
			{
				try
				{
					_qssConfigType = AccessTools.TypeByName("QuickStackStore.QSSConfig");
					if (_qssConfigType == null)
					{
						Ready = false;
						return;
					}
					GetPlayerConfig = AccessTools.Method("QuickStackStore.UserConfig:GetPlayerConfig", (Type[])null, (Type[])null);
					IsItemNameOrSlotFavorited = AccessTools.Method("QuickStackStore.UserConfig:IsItemNameOrSlotFavorited", (Type[])null, (Type[])null);
					_qsNested = AccessTools.Inner(_qssConfigType, "QuickStackConfig");
					_rsNested = AccessTools.Inner(_qssConfigType, "RestockConfig");
					if (_qsNested != null)
					{
						_fQuickStackRange = AccessTools.Field(_qsNested, "QuickStackToNearbyRange");
						_fQuickStackHotbar = AccessTools.Field(_qsNested, "QuickStackIncludesHotkeyBar");
					}
					if (_rsNested != null)
					{
						_fRestockRange = AccessTools.Field(_rsNested, "RestockFromNearbyRange");
						_fRestockHotbar = AccessTools.Field(_rsNested, "RestockIncludesHotkeyBar");
					}
					Ready = GetPlayerConfig != null && IsItemNameOrSlotFavorited != null;
				}
				catch
				{
					Ready = false;
				}
			}

			internal static float QuickStackRange()
			{
				try
				{
					if (_fQuickStackRange == null)
					{
						return 50f;
					}
					object value = _fQuickStackRange.GetValue(null);
					return (float)value.GetType().GetProperty("Value").GetValue(value, null);
				}
				catch
				{
					return 50f;
				}
			}

			internal static float RestockRange()
			{
				try
				{
					if (_fRestockRange == null)
					{
						return 50f;
					}
					object value = _fRestockRange.GetValue(null);
					return (float)value.GetType().GetProperty("Value").GetValue(value, null);
				}
				catch
				{
					return 50f;
				}
			}

			internal static bool QuickStackIncludesHotbar()
			{
				try
				{
					if (_fQuickStackHotbar == null)
					{
						return true;
					}
					object value = _fQuickStackHotbar.GetValue(null);
					return (bool)value.GetType().GetProperty("Value").GetValue(value, null);
				}
				catch
				{
					return true;
				}
			}

			internal static bool RestockIncludesHotbar()
			{
				try
				{
					if (_fRestockHotbar == null)
					{
						return true;
					}
					object value = _fRestockHotbar.GetValue(null);
					return (bool)value.GetType().GetProperty("Value").GetValue(value, null);
				}
				catch
				{
					return true;
				}
			}

			internal static bool IsFavorited(Player player, ItemData item)
			{
				try
				{
					object obj = GetPlayerConfig.Invoke(null, new object[1] { player.GetPlayerID() });
					if (obj == null)
					{
						return false;
					}
					return (bool)IsItemNameOrSlotFavorited.Invoke(obj, new object[1] { item });
				}
				catch
				{
					return false;
				}
			}
		}

		internal static class Drawers
		{
			internal static ZNetView Find(Vector3 pos, float radius, string prefab, int quality)
			{
				//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)
				if (string.IsNullOrEmpty(prefab))
				{
					return null;
				}
				foreach (DrawerComponent allDrawer in DrawerComponent.AllDrawers)
				{
					if (!((Object)(object)allDrawer == (Object)null) && !((Object)(object)allDrawer._znv == (Object)null) && allDrawer._znv.IsValid())
					{
						ZDO zDO = allDrawer._znv.GetZDO();
						if (zDO != null && !(Vector3.Distance(((Component)allDrawer).transform.position, pos) > radius) && !(zDO.GetString("Prefab", "") != prefab) && zDO.GetInt("Quality", 1) == quality)
						{
							return allDrawer._znv;
						}
					}
				}
				return null;
			}

			internal static List<ZNetView> FindWithStock(Vector3 pos, float radius, string prefab, int quality)
			{
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_0073: Unknown result type (might be due to invalid IL or missing references)
				//IL_0079: Unknown result type (might be due to invalid IL or missing references)
				List<ZNetView> list = new List<ZNetView>();
				if (string.IsNullOrEmpty(prefab))
				{
					return list;
				}
				foreach (DrawerComponent allDrawer in DrawerComponent.AllDrawers)
				{
					if (!((Object)(object)allDrawer == (Object)null) && !((Object)(object)allDrawer._znv == (Object)null) && allDrawer._znv.IsValid())
					{
						ZDO zDO = allDrawer._znv.GetZDO();
						if (zDO != null && !(Vector3.Distance(((Component)allDrawer).transform.position, pos) > radius) && !(zDO.GetString("Prefab", "") != prefab) && zDO.GetInt("Quality", 1) == quality && zDO.GetInt("Amount", 0) > 0)
						{
							list.Add(allDrawer._znv);
						}
					}
				}
				list.Sort((ZNetView a, ZNetView b) => Vector3.Distance(((Component)a).transform.position, pos).CompareTo(Vector3.Distance(((Component)b).transform.position, pos)));
				return list;
			}

			internal static void Add(ZNetView znv, string prefab, int quality, int count)
			{
				if ((Object)(object)znv == (Object)null || !znv.IsValid() || count <= 0)
				{
					return;
				}
				ZDO zDO = znv.GetZDO();
				if (zDO != null)
				{
					int num = zDO.GetInt("Amount", 0);
					if (!znv.IsOwner())
					{
						znv.ClaimOwnership();
					}
					zDO.Set("Amount", num + count);
					znv.InvokeRPC(ZNetView.Everybody, "UpdateIcon", new object[3]
					{
						prefab,
						num + count,
						quality
					});
				}
			}

			internal static void Withdraw(ZNetView znv, string prefab, int quality, int count)
			{
				if ((Object)(object)znv == (Object)null || !znv.IsValid() || count <= 0)
				{
					return;
				}
				ZDO zDO = znv.GetZDO();
				if (zDO != null)
				{
					int num = zDO.GetInt("Amount", 0);
					int num2 = Math.Max(0, num - count);
					if (!znv.IsOwner())
					{
						znv.ClaimOwnership();
					}
					zDO.Set("Amount", num2);
					znv.InvokeRPC(ZNetView.Everybody, "UpdateIcon", new object[3] { prefab, num2, quality });
				}
			}
		}

		internal static class Util
		{
			private static MethodInfo _miChanged;

			internal static Inventory GetInventory(Player player)
			{
				if (player == null)
				{
					return null;
				}
				return ((Humanoid)player).GetInventory();
			}

			internal static void MarkChanged(Inventory inv)
			{
				if (inv == null)
				{
					return;
				}
				try
				{
					if (_miChanged == null)
					{
						_miChanged = AccessTools.Method(typeof(Inventory), "Changed", (Type[])null, (Type[])null);
					}
					_miChanged?.Invoke(inv, null);
				}
				catch (Exception ex)
				{
					Dbg("MarkChanged failed: " + ex.Message);
				}
			}

			internal static string PrefabName(ItemData item)
			{
				if (item == null)
				{
					return null;
				}
				if ((Object)(object)item.m_dropPrefab != (Object)null)
				{
					return ((Object)item.m_dropPrefab).name;
				}
				return null;
			}
		}

		internal static ConfigEntry<bool> CfgEnabled;

		internal static ConfigEntry<bool> CfgQuickStackToDrawers;

		internal static ConfigEntry<bool> CfgRestockFromDrawers;

		internal static ConfigEntry<bool> CfgDebug;

		internal static bool Active => CfgEnabled.Value;

		internal static void Dbg(string s)
		{
			if (CfgDebug.Value)
			{
				ItemDrawers.Instance.Log.LogInfo((object)s);
			}
		}
	}
	internal static class QuickStackBridgePatch
	{
		internal static void Apply(Harmony harmony)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method("QuickStackStore.QuickStackModule:ReportQuickStackResult", (Type[])null, (Type[])null);
			if (!(methodInfo == null))
			{
				MethodInfo methodInfo2 = AccessTools.Method(typeof(QuickStackBridgePatch), "Prefix", (Type[])null, (Type[])null);
				harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
		}

		private static void Prefix(Player player, ref int movedCount)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			if (!QuickStackBridge.Active || !QuickStackBridge.CfgQuickStackToDrawers.Value || (Object)(object)player == (Object)null || !((Character)player).IsOwner() || ((Character)player).IsTeleporting())
			{
				return;
			}
			float num = QuickStackBridge.QssReflect.QuickStackRange();
			if (num <= 0f)
			{
				return;
			}
			Inventory inventory = QuickStackBridge.Util.GetInventory(player);
			if (inventory == null)
			{
				return;
			}
			bool flag = QuickStackBridge.QssReflect.QuickStackIncludesHotbar();
			Vector3 position = ((Component)player).transform.position;
			int num2 = 0;
			List<ItemData> allItems = inventory.GetAllItems();
			for (int num3 = allItems.Count - 1; num3 >= 0; num3--)
			{
				ItemData val = allItems[num3];
				if (val != null && val.m_shared != null && val.m_shared.m_maxStackSize >= 1 && !val.m_equipped && !QuickStackBridge.QssReflect.IsFavorited(player, val) && (val.m_gridPos.y != 0 || flag))
				{
					string text = QuickStackBridge.Util.PrefabName(val);
					if (!string.IsNullOrEmpty(text))
					{
						ZNetView val2 = QuickStackBridge.Drawers.Find(position, num, text, val.m_quality);
						if (!((Object)(object)val2 == (Object)null))
						{
							int stack = val.m_stack;
							QuickStackBridge.Drawers.Add(val2, text, val.m_quality, stack);
							inventory.RemoveItem(val);
							num2++;
							QuickStackBridge.Dbg($"QS->drawer: +{stack} {text} q{val.m_quality}");
						}
					}
				}
			}
			if (num2 > 0)
			{
				QuickStackBridge.Util.MarkChanged(inventory);
				movedCount += num2;
				QuickStackBridge.Dbg($"QuickStack bridge moved {num2} stack(s) into drawers.");
			}
		}
	}
	internal static class RestockBridgePatch
	{
		internal static void Apply(Harmony harmony)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method("QuickStackStore.RestockModule:ReportRestockResult", (Type[])null, (Type[])null);
			if (!(methodInfo == null))
			{
				MethodInfo methodInfo2 = AccessTools.Method(typeof(RestockBridgePatch), "Prefix", (Type[])null, (Type[])null);
				harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
		}

		private static void Prefix(Player player, ref int movedCount, ref int partiallyFilledCount, int totalCount)
		{
			//IL_0059: 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_0120: Unknown result type (might be due to invalid IL or missing references)
			if (!QuickStackBridge.Active || !QuickStackBridge.CfgRestockFromDrawers.Value || (Object)(object)player == (Object)null || !((Character)player).IsOwner() || ((Character)player).IsTeleporting() || totalCount <= 0)
			{
				return;
			}
			float num = QuickStackBridge.QssReflect.RestockRange();
			if (num <= 0f)
			{
				return;
			}
			Inventory inventory = QuickStackBridge.Util.GetInventory(player);
			if (inventory == null)
			{
				return;
			}
			bool flag = QuickStackBridge.QssReflect.RestockIncludesHotbar();
			Vector3 position = ((Component)player).transform.position;
			int num2 = 0;
			int num3 = 0;
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (allItem == null || allItem.m_shared == null)
				{
					continue;
				}
				int maxStackSize = allItem.m_shared.m_maxStackSize;
				if (maxStackSize <= 1 || allItem.m_equipped || QuickStackBridge.QssReflect.IsFavorited(player, allItem) || (allItem.m_gridPos.y == 0 && !flag) || allItem.m_stack >= maxStackSize || (allItem.m_customData != null && allItem.m_customData.Count > 0))
				{
					continue;
				}
				string text = QuickStackBridge.Util.PrefabName(allItem);
				if (string.IsNullOrEmpty(text))
				{
					continue;
				}
				int num4 = maxStackSize - allItem.m_stack;
				List<ZNetView> list = QuickStackBridge.Drawers.FindWithStock(position, num, text, allItem.m_quality);
				int num5 = 0;
				foreach (ZNetView item in list)
				{
					if (num4 <= 0)
					{
						break;
					}
					int num6 = item.GetZDO().GetInt("Amount", 0);
					if (num6 > 0)
					{
						int num7 = Math.Min(num4, num6);
						QuickStackBridge.Drawers.Withdraw(item, text, allItem.m_quality, num7);
						num4 -= num7;
						num5 += num7;
					}
				}
				if (num5 > 0)
				{
					allItem.m_stack += num5;
					if (allItem.m_stack >= maxStackSize)
					{
						num2++;
					}
					else
					{
						num3++;
					}
					QuickStackBridge.Dbg($"Restock<-drawer: +{num5} {text} q{allItem.m_quality}");
				}
			}
			if (num2 > 0 || num3 > 0)
			{
				QuickStackBridge.Util.MarkChanged(inventory);
				movedCount += num2;
				partiallyFilledCount += num3;
				if (movedCount > totalCount)
				{
					movedCount = totalCount;
				}
				QuickStackBridge.Dbg($"Restock bridge: +{num2} full, +{num3} partial from drawers.");
			}
		}
	}
	internal static class StationAuto
	{
		internal static class VReflect
		{
			internal static MethodInfo Smelter_GetFuel;

			internal static MethodInfo Smelter_GetQueueSize;

			internal static MethodInfo Cook_GetFuel;

			internal static MethodInfo Cook_GetSlot;

			internal static MethodInfo Cook_IsItemDone;

			internal static MethodInfo Cook_SetSlot;

			internal static MethodInfo Ferm_GetStatus;

			internal static MethodInfo Bee_GetHoneyLevel;

			internal static MethodInfo Sap_GetLevel;

			internal static Type CookStatusType;

			internal static object CookStatusZero;

			internal static void Init()
			{
				Smelter_GetFuel = AccessTools.Method(typeof(Smelter), "GetFuel", (Type[])null, (Type[])null);
				Smelter_GetQueueSize = AccessTools.Method(typeof(Smelter), "GetQueueSize", (Type[])null, (Type[])null);
				Cook_GetFuel = AccessTools.Method(typeof(CookingStation), "GetFuel", (Type[])null, (Type[])null);
				Cook_GetSlot = AccessTools.Method(typeof(CookingStation), "GetSlot", (Type[])null, (Type[])null);
				Cook_IsItemDone = AccessTools.Method(typeof(CookingStation), "IsItemDone", (Type[])null, (Type[])null);
				Cook_SetSlot = AccessTools.Method(typeof(CookingStation), "SetSlot", (Type[])null, (Type[])null);
				Ferm_GetStatus = AccessTools.Method(typeof(Fermenter), "GetStatus", (Type[])null, (Type[])null);
				Bee_GetHoneyLevel = AccessTools.Method(typeof(Beehive), "GetHoneyLevel", (Type[])null, (Type[])null);
				Sap_GetLevel = AccessTools.Method(typeof(SapCollector), "GetLevel", (Type[])null, (Type[])null);
				CookStatusType = AccessTools.Inner(typeof(CookingStation), "Status");
				if (CookStatusType != null)
				{
					CookStatusZero = Enum.ToObject(CookStatusType, 0);
				}
			}
		}

		internal static class Drawers
		{
			internal static int Take(Vector3 pos, float radius, string prefab, int count)
			{
				//IL_0076: Unknown result type (might be due to invalid IL or missing references)
				//IL_007b: Unknown result type (might be due to invalid IL or missing references)
				if (count <= 0 || string.IsNullOrEmpty(prefab))
				{
					return 0;
				}
				int num = 0;
				foreach (DrawerComponent allDrawer in DrawerComponent.AllDrawers)
				{
					if (num >= count)
					{
						break;
					}
					if ((Object)(object)allDrawer == (Object)null || (Object)(object)allDrawer._znv == (Object)null || !allDrawer._znv.IsValid())
					{
						continue;
					}
					ZDO zDO = allDrawer._znv.GetZDO();
					if (zDO == null || Vector3.Distance(((Component)allDrawer).transform.position, pos) > radius || zDO.GetString("Prefab", "") != prefab)
					{
						continue;
					}
					int num2 = zDO.GetInt("Amount", 0);
					if (num2 > 0)
					{
						int num3 = Math.Min(count - num, num2);
						int num4 = zDO.GetInt("Quality", 1);
						if (!allDrawer._znv.IsOwner())
						{
							allDrawer._znv.ClaimOwnership();
						}
						zDO.Set("Amount", num2 - num3);
						allDrawer._znv.InvokeRPC(ZNetView.Everybody, "UpdateIcon", new object[3]
						{
							prefab,
							num2 - num3,
							num4
						});
						num += num3;
					}
				}
				return num;
			}

			internal static ZNetView Find(Vector3 pos, float radius, string prefab, int quality)
			{
				//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)
				if (string.IsNullOrEmpty(prefab))
				{
					return null;
				}
				foreach (DrawerComponent allDrawer in DrawerComponent.AllDrawers)
				{
					if (!((Object)(object)allDrawer == (Object)null) && !((Object)(object)allDrawer._znv == (Object)null) && allDrawer._znv.IsValid())
					{
						ZDO zDO = allDrawer._znv.GetZDO();
						if (zDO != null && !(Vector3.Distance(((Component)allDrawer).transform.position, pos) > radius) && !(zDO.GetString("Prefab", "") != prefab) && zDO.GetInt("Quality", 1) == quality)
						{
							return allDrawer._znv;
						}
					}
				}
				return null;
			}

			internal static void Add(ZNetView znv, string prefab, int quality, int count)
			{
				if ((Object)(object)znv == (Object)null || !znv.IsValid() || count <= 0)
				{
					return;
				}
				ZDO zDO = znv.GetZDO();
				if (zDO != null)
				{
					int num = zDO.GetInt("Amount", 0);
					if (!znv.IsOwner())
					{
						znv.ClaimOwnership();
					}
					zDO.Set("Amount", num + count);
					znv.InvokeRPC(ZNetView.Everybody, "UpdateIcon", new object[3]
					{
						prefab,
						num + count,
						quality
					});
				}
			}
		}

		internal static class Throttle
		{
			private static readonly Dictionary<int, float> _last = new Dictionary<int, float>();

			private const float Interval = 1f;

			internal static bool Ready(GameObject go)
			{
				int instanceID = ((Object)go).GetInstanceID();
				float time = Time.time;
				if (_last.TryGetValue(instanceID, out var value) && time - value < 1f)
				{
					return false;
				}
				_last[instanceID] = time;
				return true;
			}
		}

		internal static ConfigEntry<bool> CfgEnabled;

		internal static ConfigEntry<float> CfgRadius;

		internal static ConfigEntry<float> CfgSmelterRadius;

		internal static ConfigEntry<bool> CfgFeed;

		internal static ConfigEntry<bool> CfgDeposit;

		internal static ConfigEntry<bool> CfgDebug;

		internal static bool Active => CfgEnabled.Value;

		internal static float Radius => Mathf.Clamp(CfgRadius.Value, 1f, 50f);

		internal static float SmelterRadius => Mathf.Clamp(CfgSmelterRadius.Value, 1f, 50f);

		internal static float MaxFeedRadius => Mathf.Max(Radius, SmelterRadius);

		internal static void Dbg(string s)
		{
			if (CfgDebug.Value)
			{
				ItemDrawers.Instance.Log.LogInfo((object)s);
			}
		}

		internal static string PrefabName(ItemDrop drop)
		{
			if (!((Object)(object)drop == (Object)null))
			{
				return ((Object)((Component)drop).gameObject).name;
			}
			return null;
		}

		internal static string ConvFrom(object conversion)
		{
			object? value = AccessTools.Field(conversion.GetType(), "m_from").GetValue(conversion);
			return PrefabName((ItemDrop)((value is ItemDrop) ? value : null));
		}
	}
	[HarmonyPatch(typeof(Player), "OnSpawned")]
	internal static class Player_OnSpawned_Patch
	{
		private static void Postfix()
		{
			DrawerRangeFixer.Run(force: true);
		}
	}
	[HarmonyPatch(typeof(Player), "Update")]
	internal static class Player_Update_Patch
	{
		private static void Postfix()
		{
			DrawerRangeFixer.Run();
		}
	}
	[HarmonyPatch(typeof(Smelter), "UpdateSmelter")]
	internal static class Smelter_Patch
	{
		private static void Prefix(Smelter __instance)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			if (!StationAuto.Active || !StationAuto.CfgFeed.Value || (Object)(object)__instance == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid() || !component.IsOwner() || !StationAuto.Throttle.Ready(((Component)__instance).gameObject))
			{
				return;
			}
			Vector3 position = ((Component)__instance).transform.position;
			float smelterRadius = StationAuto.SmelterRadius;
			float num = (float)StationAuto.VReflect.Smelter_GetFuel.Invoke(__instance, null);
			int num2 = __instance.m_maxFuel - (int)Math.Ceiling(num);
			if ((Object)(object)__instance.m_fuelItem != (Object)null && num2 > 0)
			{
				string prefab = StationAuto.PrefabName(__instance.m_fuelItem);
				int num3 = StationAuto.Drawers.Take(position, smelterRadius, prefab, num2);
				for (int i = 0; i < num3; i++)
				{
					component.InvokeRPC("RPC_AddFuel", Array.Empty<object>());
				}
			}
			int num4 = (int)StationAuto.VReflect.Smelter_GetQueueSize.Invoke(__instance, null);
			int num5 = __instance.m_maxOre - num4;
			if (num5 <= 0 || __instance.m_conversion == null)
			{
				return;
			}
			foreach (object item in (IEnumerable)__instance.m_conversion)
			{
				string text = StationAuto.ConvFrom(item);
				if (!string.IsNullOrEmpty(text))
				{
					int num6 = StationAuto.Drawers.Take(position, smelterRadius, text, num5);
					for (int j = 0; j < num6; j++)
					{
						component.InvokeRPC("RPC_AddOre", new object[1] { text });
					}
					num5 -= num6;
					if (num5 <= 0)
					{
						break;
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(CookingStation), "UpdateCooking")]
	internal static class CookingStation_Patch
	{
		private static void Prefix(CookingStation __instance)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: 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)
			if (!StationAuto.Active || (Object)(object)__instance == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid() || !component.IsOwner() || !StationAuto.Throttle.Ready(((Component)__instance).gameObject))
			{
				return;
			}
			Vector3 position = ((Component)__instance).transform.position;
			float radius = StationAuto.Radius;
			if (StationAuto.CfgFeed.Value)
			{
				float num = (float)StationAuto.VReflect.Cook_GetFuel.Invoke(__instance, null);
				int num2 = __instance.m_maxFuel - (int)Math.Ceiling(num);
				if ((Object)(object)__instance.m_fuelItem != (Object)null && num2 > 0)
				{
					string prefab = StationAuto.PrefabName(__instance.m_fuelItem);
					int num3 = StationAuto.Drawers.Take(position, radius, prefab, num2);
					for (int i = 0; i < num3; i++)
					{
						component.InvokeRPC("RPC_AddFuel", Array.Empty<object>());
					}
				}
				int num4 = CountFreeSlots(__instance);
				if (num4 > 0 && __instance.m_conversion != null)
				{
					foreach (object item in (IEnumerable)__instance.m_conversion)
					{
						string text = StationAuto.ConvFrom(item);
						if (!string.IsNullOrEmpty(text))
						{
							int num5 = StationAuto.Drawers.Take(position, radius, text, num4);
							for (int j = 0; j < num5; j++)
							{
								component.InvokeRPC("RPC_AddItem", new object[1] { text });
							}
							num4 -= num5;
							if (num4 <= 0)
							{
								break;
							}
						}
					}
				}
			}
			if (!StationAuto.CfgDeposit.Value)
			{
				return;
			}
			int length = __instance.m_slots.Length;
			for (int k = 0; k < length; k++)
			{
				object[] array = new object[4] { k, null, null, null };
				StationAuto.VReflect.Cook_GetSlot.Invoke(__instance, array);
				string text2 = array[1] as string;
				if (!string.IsNullOrEmpty(text2) && (bool)StationAuto.VReflect.Cook_IsItemDone.Invoke(__instance, new object[1] { text2 }))
				{
					ZNetView val = StationAuto.Drawers.Find(position, radius, text2, 1);
					if (!((Object)(object)val == (Object)null))
					{
						StationAuto.VReflect.Cook_SetSlot.Invoke(__instance, new object[4]
						{
							k,
							"",
							0f,
							StationAuto.VReflect.CookStatusZero
						});
						component.InvokeRPC(ZNetView.Everybody, "RPC_SetSlotVisual", new object[2] { k, "" });
						StationAuto.Drawers.Add(val, text2, 1, 1);
						break;
					}
				}
			}
		}

		private static int CountFreeSlots(CookingStation cs)
		{
			int length = cs.m_slots.Length;
			int num = 0;
			for (int i = 0; i < length; i++)
			{
				object[] array = new object[4] { i, null, null, null };
				StationAuto.VReflect.Cook_GetSlot.Invoke(cs, array);
				if (string.IsNullOrEmpty(array[1] as string))
				{
					num++;
				}
			}
			return num;
		}
	}
	[HarmonyPatch(typeof(Fireplace), "UpdateFireplace")]
	internal static class Fireplace_Patch
	{
		private static void Prefix(Fireplace __instance)
		{
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			if (!StationAuto.Active || !StationAuto.CfgFeed.Value || (Object)(object)__instance == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid() || !component.IsOwner() || !__instance.m_canRefill || __instance.m_infiniteFuel || !StationAuto.Throttle.Ready(((Component)__instance).gameObject))
			{
				return;
			}
			float num = component.GetZDO().GetFloat("fuel", 0f);
			int num2 = (int)__instance.m_maxFuel - (int)Math.Ceiling(num);
			if (!((Object)(object)__instance.m_fuelItem == (Object)null) && num2 > 0)
			{
				int num3 = StationAuto.Drawers.Take(((Component)__instance).transform.position, prefab: StationAuto.PrefabName(__instance.m_fuelItem), radius: StationAuto.Radius, count: num2);
				for (int i = 0; i < num3; i++)
				{
					component.InvokeRPC("RPC_AddFuel", Array.Empty<object>());
				}
			}
		}
	}
	[HarmonyPatch(typeof(Fermenter), "SlowUpdate")]
	internal static class Fermenter_Patch
	{
		private static void Postfix(Fermenter __instance)
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			if (!StationAuto.Active || !StationAuto.CfgFeed.Value || (Object)(object)__instance == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid() || !component.IsOwner() || (int)StationAuto.VReflect.Ferm_GetStatus.Invoke(__instance, null) != 0 || __instance.m_conversion == null || !StationAuto.Throttle.Ready(((Component)__instance).gameObject))
			{
				return;
			}
			Vector3 position = ((Component)__instance).transform.position;
			float radius = StationAuto.Radius;
			foreach (object item in (IEnumerable)__instance.m_conversion)
			{
				string text = StationAuto.ConvFrom(item);
				if (!string.IsNullOrEmpty(text) && StationAuto.Drawers.Take(position, radius, text, 1) > 0)
				{
					component.InvokeRPC("RPC_AddItem", new object[1] { text });
					break;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Beehive), "UpdateBees")]
	internal static class Beehive_Patch
	{
		private static void Postfix(Beehive __instance)
		{
			//IL_0084: 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_009e: Unknown result type (might be due to invalid IL or missing references)
			if (!StationAuto.Active || !StationAuto.CfgDeposit.Value || (Object)(object)__instance == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid() || !component.IsOwner() || (Object)(object)__instance.m_honeyItem == (Object)null || (int)StationAuto.VReflect.Bee_GetHoneyLevel.Invoke(__instance, null) <= 0 || !StationAuto.Throttle.Ready(((Component)__instance).gameObject))
			{
				return;
			}
			Vector3 position = ((Component)__instance).transform.position;
			float radius = StationAuto.Radius;
			string prefab = StationAuto.PrefabName(__instance.m_honeyItem);
			while ((int)StationAuto.VReflect.Bee_GetHoneyLevel.Invoke(__instance, null) > 0)
			{
				ZNetView val = StationAuto.Drawers.Find(position, radius, prefab, 1);
				if (!((Object)(object)val == (Object)null))
				{
					int num = (int)StationAuto.VReflect.Bee_GetHoneyLevel.Invoke(__instance, null);
					component.GetZDO().Set("level", num - 1);
					StationAuto.Drawers.Add(val, prefab, 1, 1);
					continue;
				}
				break;
			}
		}
	}
	[HarmonyPatch(typeof(SapCollector), "UpdateTick")]
	internal static class SapCollector_Patch
	{
		private static void Postfix(SapCollector __instance)
		{
			//IL_0084: 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_009e: Unknown result type (might be due to invalid IL or missing references)
			if (!StationAuto.Active || !StationAuto.CfgDeposit.Value || (Object)(object)__instance == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid() || !component.IsOwner() || (Object)(object)__instance.m_spawnItem == (Object)null || (int)StationAuto.VReflect.Sap_GetLevel.Invoke(__instance, null) <= 0 || !StationAuto.Throttle.Ready(((Component)__instance).gameObject))
			{
				return;
			}
			Vector3 position = ((Component)__instance).transform.position;
			float radius = StationAuto.Radius;
			string prefab = StationAuto.PrefabName(__instance.m_spawnItem);
			while ((int)StationAuto.VReflect.Sap_GetLevel.Invoke(__instance, null) > 0)
			{
				ZNetView val = StationAuto.Drawers.Find(position, radius, prefab, 1);
				if (!((Object)(object)val == (Object)null))
				{
					int num = (int)StationAuto.VReflect.Sap_GetLevel.Invoke(__instance, null);
					component.GetZDO().Set("level", num - 1);
					StationAuto.Drawers.Add(val, prefab, 1, 1);
					continue;
				}
				break;
			}
		}
	}
	internal static class DrawerRangeFixer
	{
		private static float _lastFix;

		private const float FixInterval = 10f;

		internal static void Run(bool force = false)
		{
			if (!StationAuto.Active)
			{
				return;
			}
			float time = Time.time;
			if (!force && time - _lastFix < 10f)
			{
				return;
			}
			_lastFix = time;
			int num = Mathf.RoundToInt(StationAuto.MaxFeedRadius);
			int num2 = 0;
			foreach (DrawerComponent allDrawer in DrawerComponent.AllDrawers)
			{
				if ((Object)(object)allDrawer == (Object)null || (Object)(object)allDrawer._znv == (Object)null || !allDrawer._znv.IsValid())
				{
					continue;
				}
				ZDO zDO = allDrawer._znv.GetZDO();
				if (zDO != null && zDO.GetInt("PickupRange", 0) < num)
				{
					if (!allDrawer._znv.IsOwner())
					{
						allDrawer._znv.ClaimOwnership();
					}
					zDO.Set("PickupRange", num);
					num2++;
				}
			}
			if (num2 > 0)
			{
				ItemDrawers.Instance.Log.LogInfo((object)$"DrawerAuto: boosted PickupRange to {num} on {num2} drawer(s).");
			}
		}
	}
	public static class Utils
	{
		private static readonly MethodInfo M_ItemDrop_Save = AccessTools.Method(typeof(ItemDrop), "Save", (Type[])null, (Type[])null);

		public static string Localize(this string s)
		{
			return Localization.instance.Localize(s);
		}

		public static Vector3 ColorToVec3(Color32 c)
		{
			//IL_0000: 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_001a: 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)
			return new Vector3((float)(int)c.r / 255f, (float)(int)c.g / 255f, (float)(int)c.b / 255f);
		}

		public static Color32 Vec3ToColor(Vector3 v)
		{
			//IL_0000: 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_001a: 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)
			return new Color32((byte)(v.x * 255f), (byte)(v.y * 255f), (byte)(v.z * 255f), byte.MaxValue);
		}

		public static int CustomCountItems(string prefab, int level)
		{
			int num = 0;
			foreach (ItemData allItem in ((Humanoid)Player.m_localPlayer).GetInventory().GetAllItems())
			{
				if ((Object)(object)allItem.m_dropPrefab != (Object)null && ((Object)allItem.m_dropPrefab).name == prefab && level == allItem.m_quality)
				{
					num += allItem.m_stack;
				}
			}
			return num;
		}

		public static void CustomRemoveItems(string prefab, int amount, int level)
		{
			Inventory inventory = ((Humanoid)Player.m_localPlayer).GetInventory();
			List<ItemData> allItems = inventory.GetAllItems();
			for (int num = allItems.Count - 1; num >= 0; num--)
			{
				ItemData val = allItems[num];
				if ((Object)(object)val.m_dropPrefab != (Object)null && ((Object)val.m_dropPrefab).name == prefab && val.m_quality == level)
				{
					int num2 = Mathf.Min(val.m_stack, amount);
					val.m_stack -= num2;
					amount -= num2;
					if (amount <= 0)
					{
						break;
					}
				}
			}
			allItems.RemoveAll((ItemData x) => x.m_stack <= 0);
			typeof(Inventory).GetMethod("Changed")?.Invoke(inventory, null);
		}

		public static void InstantiateItem(GameObject prefab, int stack, int level)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)localPlayer) || !Object.op_Implicit((Object)prefab))
			{
				return;
			}
			ItemDrop component = prefab.GetComponent<ItemDrop>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			if (component.m_itemData.m_shared.m_maxStackSize > 1)
			{
				while (stack > 0)
				{
					int num = Math.Min(stack, component.m_itemData.m_shared.m_maxStackSize);
					stack -= num;
					ItemDrop component2 = Object.Instantiate<GameObject>(prefab, ((Component)localPlayer).transform.position + Vector3.up * 1.5f, Quaternion.identity).GetComponent<ItemDrop>();
					component2.m_itemData.m_stack = num;
					component2.m_itemData.m_durability = component.m_itemData.GetMaxDurability();
					M_ItemDrop_Save.Invoke(component2, null);
					if (((Humanoid)localPlayer).GetInventory().CanAddItem(((Component)component2).gameObject, -1))
					{
						((Humanoid)localPlayer).GetInventory().AddItem(component2.m_itemData);
						ZNetScene.instance.Destroy(((Component)component2).gameObject);
					}
				}
				return;
			}
			for (int i = 0; i < stack; i++)
			{
				GameObject val = Object.Instantiate<GameObject>(prefab, ((Component)localPlayer).transform.position + Vector3.up * 1.5f, Quaternion.identity);
				ItemDrop component3 = val.GetComponent<ItemDrop>();
				component3.m_itemData.m_quality = level;
				component3.m_itemData.m_durability = component3.m_itemData.GetMaxDurability();
				M_ItemDrop_Save.Invoke(component3, null);
				if (((Humanoid)localPlayer).GetInventory().CanAddItem(val, -1))
				{
					((Humanoid)localPlayer).GetInventory().AddItem(component3.m_itemData);
					ZNetScene.instance.Destroy(val);
				}
			}
		}

		public static void InstantiateAtPos(GameObject prefab, int stack, int level, Vector3 pos)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Expected O, but got Unknown
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			//IL_0044: 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)
			if (Object.op_Implicit((Object)Player.m_localPlayer) && Object.op_Implicit((Object)prefab))
			{
				ItemDrop component = prefab.GetComponent<ItemDrop>();
				while (stack > 0)
				{
					int num = Math.Min(stack, component.m_itemData.m_shared.m_maxStackSize);
					stack -= num;
					ItemDrop component2 = Object.Instantiate<GameObject>(prefab, pos, Quaternion.identity).GetComponent<ItemDrop>();
					component2.m_itemData.m_stack = num;
					float maxDurability = component.m_itemData.GetMaxDurability();
					component2.m_itemData.m_durability = maxDurability;
					M_ItemDrop_Save.Invoke(component2, null);
				}
			}
		}
	}
}
namespace API
{
	public static class ClientSideV2
	{
		public static List<ZNetView> AllDrawers()
		{
			return (from d in DrawerComponent.AllDrawers
				where (Object)(object)d != (Object)null && (Object)(object)d._znv != (Object)null && d._znv.IsValid()
				select d._znv).ToList();
		}
	}
	public static class ItemDrawers_API
	{
		public class Drawer(ZNetView znv)
		{
			public string Prefab = znv.GetZDO().GetString("Prefab", "");

			public int Amount = znv.GetZDO().GetInt("Amount", 0);

			public int Quality = znv.GetZDO().GetInt("Quality", 1);

			public void Remove(int amount)
			{
				znv.ClaimOwnership();
				znv.InvokeRPC("ForceRemove", new object[1] { amount });
			}

			public void Withdraw(int amount)
			{
				znv.InvokeRPC("WithdrawItem_Request", new object[1] { amount });
			}

			public void Add(int amount, int quality)
			{
				znv.InvokeRPC("AddItem_Request", new object[3] { Prefab, amount, quality });
			}
		}

		private static readonly bool _IsInstalled;

		private static readonly MethodInfo MI_GetAllDrawers;

		public static List<Drawer> AllDrawers
		{
			get
			{
				if (!_IsInstalled)
				{
					return new List<Drawer>();
				}
				return ((List<ZNetView>)MI_GetAllDrawers.Invoke(null, null)).Select((ZNetView znv) => new Drawer(znv)).ToList();
			}
		}

		public static List<Drawer> AllDrawersInRange(Vector3 pos, float range)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			if (!_IsInstalled)
			{
				return new List<Drawer>();
			}
			return (from znv in (List<ZNetView>)MI_GetAllDrawers.Invoke(null, null)
				where Vector3.Distance(((Component)znv).transform.position, pos) <= range
				select new Drawer(znv)).ToList();
		}

		static ItemDrawers_API()
		{
			Type type = Type.GetType("API.ClientSideV2, kg_ItemDrawers");
			if ((object)type == null)
			{
				_IsInstalled = false;
				return;
			}
			_IsInstalled = true;
			MI_GetAllDrawers = type.GetMethod("AllDrawers", BindingFlags.Static | BindingFlags.Public);
		}
	}
}