Decompiled source of Supermans Auto Storage Craft v1.0.6

SupermansAutoStorageCraft.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ChestLink
{
	internal static class Chests
	{
		[HarmonyPatch(typeof(Container), "Awake")]
		private static class ContainerAwakePatch
		{
			private static void Postfix(Container __instance)
			{
				All.Add(__instance);
			}
		}

		[HarmonyPatch(typeof(Container), "OnDestroyed")]
		private static class ContainerDestroyedPatch
		{
			private static void Postfix(Container __instance)
			{
				All.Remove(__instance);
			}
		}

		private static readonly HashSet<Container> All = new HashSet<Container>();

		private const float CacheSeconds = 0.5f;

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

		private static float _cacheTime = -1f;

		private static float _cacheRange = -1f;

		private static Vector3 _cachePos;

		internal static void Invalidate()
		{
			_cacheTime = -1f;
		}

		internal static List<Container> InRange(Vector3 center, 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)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			All.RemoveWhere((Container c) => (Object)(object)c == (Object)null);
			List<Container> list = new List<Container>();
			float num = range * range;
			long playerId = (((Object)(object)Game.instance != (Object)null) ? Game.instance.GetPlayerProfile().GetPlayerID() : 0);
			foreach (Container item in All)
			{
				Vector3 val = ((Component)item).transform.position - center;
				if (!(((Vector3)(ref val)).sqrMagnitude > num) && IsUsable(item, playerId))
				{
					list.Add(item);
				}
			}
			list.Sort(delegate(Container a, Container b)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				//IL_002d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0032: Unknown result type (might be due to invalid IL or missing references)
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				Vector3 val2 = ((Component)a).transform.position - center;
				float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
				val2 = ((Component)b).transform.position - center;
				return sqrMagnitude.CompareTo(((Vector3)(ref val2)).sqrMagnitude);
			});
			return list;
		}

		private static bool IsUsable(Container c, long playerId)
		{
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)c.m_nview == (Object)null || !c.m_nview.IsValid() || c.GetInventory() == null)
			{
				return false;
			}
			if ((Object)(object)((Component)c).GetComponent<TombStone>() != (Object)null)
			{
				return false;
			}
			if (((Object)(object)c.m_wagon != (Object)null || (Object)(object)((Component)c).GetComponentInParent<Ship>() != (Object)null) && !Plugin.IncludeCartsAndShips.Value)
			{
				return false;
			}
			bool num = (Object)(object)InventoryGui.instance != (Object)null && (Object)(object)InventoryGui.instance.m_currentContainer == (Object)(object)c;
			bool flag = c.IsInUse() || (!c.m_nview.IsOwner() && c.m_nview.GetZDO().GetInt(ZDOVars.s_inUse, 0) == 1);
			if (!num && (flag || ((Object)(object)c.m_wagon != (Object)null && c.m_wagon.InUse())))
			{
				return false;
			}
			if (!c.CheckAccess(playerId))
			{
				return false;
			}
			if (c.m_checkGuardStone && !PrivateArea.CheckAccess(((Component)c).transform.position, 0f, false, false))
			{
				return false;
			}
			return true;
		}

		private static int Spendable(Inventory inv, string itemName, int quality = -1)
		{
			int num = inv.CountItems(itemName, -1, true);
			int num2 = ((quality < 0) ? num : inv.CountItems(itemName, quality, true));
			return Mathf.Max(0, Mathf.Min(num2, num - 1));
		}

		internal static int Count(string itemName, Vector3 center, float range, int quality = -1)
		{
			//IL_004c: 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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			if (!(Time.time - _cacheTime > 0.5f) && Mathf.Approximately(range, _cacheRange))
			{
				Vector3 val = center - _cachePos;
				if (!(((Vector3)(ref val)).sqrMagnitude > 1f))
				{
					goto IL_013f;
				}
			}
			CountCache.Clear();
			HashSet<string> hashSet = new HashSet<string>();
			foreach (Container item in InRange(center, range))
			{
				Inventory inventory = item.GetInventory();
				hashSet.Clear();
				foreach (ItemData allItem in inventory.GetAllItems())
				{
					if (allItem.m_worldLevel >= Game.m_worldLevel)
					{
						string name = allItem.m_shared.m_name;
						if (hashSet.Add(name))
						{
							Add(name, Spendable(inventory, name));
						}
						string text = QualityKey(name, allItem.m_quality);
						if (hashSet.Add(text))
						{
							Add(text, Spendable(inventory, name, allItem.m_quality));
						}
					}
				}
			}
			_cacheTime = Time.time;
			_cacheRange = range;
			_cachePos = center;
			goto IL_013f;
			IL_013f:
			string key = ((quality < 0) ? itemName : QualityKey(itemName, quality));
			if (!CountCache.TryGetValue(key, out var value))
			{
				return 0;
			}
			return value;
		}

		private static string QualityKey(string name, int quality)
		{
			return name + "#" + quality;
		}

		private static void Add(string key, int amount)
		{
			CountCache.TryGetValue(key, out var value);
			CountCache[key] = value + amount;
		}

		internal static ItemData FindItem(string itemName, int quality, Vector3 center, float range)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			foreach (Container item2 in InRange(center, range))
			{
				Inventory inventory = item2.GetInventory();
				if (Spendable(inventory, itemName, quality) > 0)
				{
					ItemData item = inventory.GetItem(itemName, quality, false);
					if (item != null && item.m_worldLevel >= Game.m_worldLevel)
					{
						return item;
					}
				}
			}
			return null;
		}

		internal static int Remove(string itemName, int amount, Vector3 center, float range, int quality = -1)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			foreach (Container item in InRange(center, range))
			{
				if (num >= amount)
				{
					break;
				}
				Inventory inventory = item.GetInventory();
				int num2 = Spendable(inventory, itemName, quality);
				if (num2 > 0)
				{
					int num3 = Mathf.Min(num2, amount - num);
					item.m_nview.ClaimOwnership();
					inventory.RemoveItem(itemName, num3, quality, true);
					num += num3;
				}
			}
			Invalidate();
			return num;
		}
	}
	internal class ConfigWindow : MonoBehaviour
	{
		[HarmonyPatch(typeof(GameCamera), "UpdateMouseCapture")]
		private static class MouseCapturePatch
		{
			private static void Postfix()
			{
				if (IsOpen)
				{
					ZCursor.LockState = (CursorLockMode)0;
					ZCursor.Show();
				}
			}
		}

		[HarmonyPatch(typeof(Player), "TakeInput")]
		private static class TakeInputPatch
		{
			private static void Postfix(ref bool __result)
			{
				if (IsOpen)
				{
					__result = false;
				}
			}
		}

		private const int WindowId = 1128811595;

		private Rect _rect = new Rect(0f, 0f, 440f, 620f);

		private Vector2 _scroll;

		private bool _centered;

		internal static bool IsOpen { get; private set; }

		internal static void Toggle()
		{
			IsOpen = !IsOpen;
		}

		private void Update()
		{
			if (IsOpen && ZInput.instance != null && ZInput.GetKeyDown((KeyCode)27, false))
			{
				IsOpen = false;
			}
		}

		private void OnGUI()
		{
			//IL_0071: 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_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Expected O, but got Unknown
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			if (IsOpen)
			{
				if (!_centered)
				{
					((Rect)(ref _rect)).x = ((float)Screen.width - ((Rect)(ref _rect)).width) / 2f;
					((Rect)(ref _rect)).y = ((float)Screen.height - ((Rect)(ref _rect)).height) / 2f;
					_centered = true;
				}
				GUI.backgroundColor = new Color(0.15f, 0.12f, 0.1f, 1f);
				_rect = GUILayout.Window(1128811595, _rect, new WindowFunction(DrawWindow), "Supermans Auto Storage/Craft settings", Array.Empty<GUILayoutOption>());
			}
		}

		private void DrawWindow(int id)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: 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_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			_scroll = GUILayout.BeginScrollView(_scroll, Array.Empty<GUILayoutOption>());
			Header("General");
			Toggle(Plugin.ModEnabled, "Mod enabled");
			Header("Ranges (meters)");
			Slider(Plugin.DepositRange, "Deposit range");
			Slider(Plugin.CraftingRange, "Crafting / cooking range");
			Slider(Plugin.SmelterRange, "Smelter range");
			Header("Deposit (" + ((object)Plugin.DepositKey.Value/*cast due to .constrained prefix*/).ToString() + ")");
			Toggle(Plugin.SkipEquipped, "Keep equipped items");
			Toggle(Plugin.SkipHotbar, "Keep hotbar (top row)");
			GUILayout.Label("Items only go into chests that already hold at least one of them.", Array.Empty<GUILayoutOption>());
			Toggle(Plugin.IncludeCartsAndShips, "Include carts and ships");
			Header("Crafting, cooking & smelting");
			Toggle(Plugin.CraftFromChests, "Craft / upgrade from nearby chests");
			Toggle(Plugin.RequireStation, "Only while using a crafting station");
			Toggle(Plugin.CookFromChests, "Cooking stations take raw food from chests");
			Toggle(Plugin.SmelterFromChests, "Smelter fill (" + ((object)Plugin.SmelterModifier.Value/*cast due to .constrained prefix*/).ToString() + " + E)");
			Header("Display");
			Toggle(Plugin.ShowRequirementPanel, "Requirement panel while crafting");
			Toggle(Plugin.ShowSmelterPanel, "Smelter panel");
			Toggle(Plugin.ShowLockMarkers, "Lock markers on inventory slots");
			GUILayout.Space(8f);
			GUILayout.Label($"Lock item: hover it in your inventory and press {Plugin.LockModifier.Value} + {Plugin.LockKey.Value}.", Array.Empty<GUILayoutOption>());
			GUILayout.Label("Key bindings can be changed in BepInEx/config/chestlink.valheim.cfg", Array.Empty<GUILayoutOption>());
			GUILayout.EndScrollView();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("Reset ranges to 15 m", Array.Empty<GUILayoutOption>()))
			{
				Plugin.DepositRange.Value = 15f;
				Plugin.CraftingRange.Value = 15f;
				Plugin.SmelterRange.Value = 15f;
			}
			if (GUILayout.Button("Close (" + ((object)Plugin.ConfigMenuKey.Value/*cast due to .constrained prefix*/).ToString() + ")", Array.Empty<GUILayoutOption>()))
			{
				IsOpen = false;
			}
			GUILayout.EndHorizontal();
			GUI.DragWindow(new Rect(0f, 0f, 10000f, 22f));
		}

		private static void Header(string text)
		{
			GUILayout.Space(8f);
			GUILayout.Label("<b><color=#ffd27a>" + text + "</color></b>", Array.Empty<GUILayoutOption>());
		}

		private static void Toggle(ConfigEntry<bool> entry, string label)
		{
			bool flag = GUILayout.Toggle(entry.Value, " " + label, Array.Empty<GUILayoutOption>());
			if (flag != entry.Value)
			{
				entry.Value = flag;
			}
		}

		private static void Slider(ConfigEntry<float> entry, string label)
		{
			AcceptableValueRange<float> obj = ((ConfigEntryBase)entry).Description.AcceptableValues as AcceptableValueRange<float>;
			float num = obj?.MinValue ?? 1f;
			float num2 = obj?.MaxValue ?? 50f;
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label(label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(170f) });
			float num3 = GUILayout.HorizontalSlider(entry.Value, num, num2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(170f) });
			GUILayout.Label(Mathf.Round(num3) + " m", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) });
			GUILayout.EndHorizontal();
			num3 = Mathf.Round(num3);
			if (!Mathf.Approximately(num3, entry.Value))
			{
				entry.Value = num3;
			}
		}
	}
	[HarmonyPatch(typeof(CookingStation), "OnInteract")]
	internal static class Cooking
	{
		private static void Prefix(CookingStation __instance, Humanoid user)
		{
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.ModEnabled.Value || !Plugin.CookFromChests.Value)
			{
				return;
			}
			Player val = (Player)(object)((user is Player) ? user : null);
			if (val == null || (Object)(object)val != (Object)(object)Player.m_localPlayer || __instance.HaveDoneItem() || __instance.FindCookableItem(((Humanoid)val).GetInventory()) != null || __instance.GetFreeSlot() == -1 || (__instance.m_requireFire && !__instance.IsFireLit()))
			{
				return;
			}
			Inventory inventory = ((Humanoid)val).GetInventory();
			foreach (ItemConversion item in __instance.m_conversion)
			{
				if (!((Object)(object)item.m_from == (Object)null) && inventory.CanAddItem(((Component)item.m_from).gameObject, 1) && Chests.Remove(item.m_from.m_itemData.m_shared.m_name, 1, ((Component)val).transform.position, Plugin.CraftingRange.Value) > 0)
				{
					inventory.AddItem(((Component)item.m_from).gameObject, 1);
					break;
				}
			}
		}
	}
	internal static class Crafting
	{
		[HarmonyPatch(typeof(Player), "HaveRequirementItems")]
		private static class HaveRequirementItemsPatch
		{
			private static bool Prefix(Player __instance, Recipe piece, bool discover, int qualityLevel, int amount, ref bool __result)
			{
				if (discover || !Active(__instance))
				{
					return true;
				}
				CraftingStation currentCraftingStation = __instance.GetCurrentCraftingStation();
				Requirement[] resources = piece.m_resources;
				foreach (Requirement val in resources)
				{
					if (!Applies(val, currentCraftingStation))
					{
						continue;
					}
					int num = val.GetAmount(qualityLevel) * amount;
					int num2 = TotalCount(__instance, val.m_resItem.m_itemData.m_shared.m_name);
					if (piece.m_requireOnlyOneIngredient)
					{
						if (num2 >= num)
						{
							__result = true;
							return false;
						}
					}
					else if (num2 < num)
					{
						__result = false;
						return false;
					}
				}
				__result = !piece.m_requireOnlyOneIngredient;
				return false;
			}
		}

		[HarmonyPatch(typeof(Player), "ConsumeResources")]
		private static class ConsumeResourcesPatch
		{
			private static bool Prefix(Player __instance, Requirement[] requirements, int qualityLevel, int itemQuality, int multiplier)
			{
				//IL_009b: Unknown result type (might be due to invalid IL or missing references)
				if (!Active(__instance) || !InventoryGui.IsVisible())
				{
					return true;
				}
				Inventory inventory = ((Humanoid)__instance).GetInventory();
				CraftingStation currentCraftingStation = __instance.GetCurrentCraftingStation();
				foreach (Requirement val in requirements)
				{
					if (!Applies(val, currentCraftingStation))
					{
						continue;
					}
					int num = val.GetAmount(qualityLevel) * multiplier;
					if (num > 0)
					{
						string name = val.m_resItem.m_itemData.m_shared.m_name;
						int num2 = Mathf.Min(num, inventory.CountItems(name, itemQuality, true));
						if (num2 > 0)
						{
							inventory.RemoveItem(name, num2, itemQuality, true);
						}
						int num3 = num - num2;
						if (num3 > 0)
						{
							Chests.Remove(name, num3, ((Component)__instance).transform.position, Plugin.CraftingRange.Value, itemQuality);
						}
					}
				}
				return false;
			}
		}

		[HarmonyPatch(typeof(Player), "GetFirstRequiredItem")]
		private static class GetFirstRequiredItemPatch
		{
			private static void Postfix(Player __instance, Inventory inventory, Recipe recipe, int qualityLevel, ref int amount, ref int extraAmount, int craftMultiplier, ref ItemData __result)
			{
				//IL_001b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0020: Unknown result type (might be due to invalid IL or missing references)
				//IL_0085: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
				if (__result != null || !Active(__instance))
				{
					return;
				}
				CraftingStation currentCraftingStation = __instance.GetCurrentCraftingStation();
				Vector3 position = ((Component)__instance).transform.position;
				float value = Plugin.CraftingRange.Value;
				Requirement[] resources = recipe.m_resources;
				foreach (Requirement val in resources)
				{
					if (!Applies(val, currentCraftingStation))
					{
						continue;
					}
					int num = val.GetAmount(qualityLevel) * craftMultiplier;
					string name = val.m_resItem.m_itemData.m_shared.m_name;
					for (int j = 1; j <= val.m_resItem.m_itemData.m_shared.m_maxQuality; j++)
					{
						if (inventory.CountItems(name, j, true) + Chests.Count(name, position, value, j) >= num)
						{
							ItemData val2 = inventory.GetItem(name, j, false) ?? Chests.FindItem(name, j, position, value);
							if (val2 != null)
							{
								amount = num;
								extraAmount = val.m_extraAmountOnlyOneIngredient;
								__result = val2;
								return;
							}
						}
					}
				}
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "DoCrafting")]
		private static class DoCraftingPatch
		{
			private static void Prefix()
			{
				_inDoCrafting = true;
			}

			private static void Finalizer()
			{
				_inDoCrafting = false;
			}
		}

		[HarmonyPatch(typeof(Inventory), "RemoveItem", new Type[]
		{
			typeof(string),
			typeof(int),
			typeof(int),
			typeof(bool)
		})]
		private static class RemoveItemByNamePatch
		{
			private static void Prefix(Inventory __instance, string name, ref int amount, int itemQuality, bool worldLevelBased)
			{
				//IL_0044: Unknown result type (might be due to invalid IL or missing references)
				Player localPlayer = Player.m_localPlayer;
				if (_inDoCrafting && !((Object)(object)localPlayer == (Object)null) && __instance == ((Humanoid)localPlayer).GetInventory() && Active(localPlayer))
				{
					int num = __instance.CountItems(name, itemQuality, worldLevelBased);
					if (num < amount)
					{
						Chests.Remove(name, amount - num, ((Component)localPlayer).transform.position, Plugin.CraftingRange.Value, itemQuality);
						amount = num;
					}
				}
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "SetupRequirement")]
		private static class SetupRequirementPatch
		{
			private static void Postfix(Transform elementRoot, Requirement req, Player player, bool craft, int quality, int craftMultiplier, bool __result)
			{
				//IL_006b: Unknown result type (might be due to invalid IL or missing references)
				if (!__result || !craft || (Object)(object)req.m_resItem == (Object)null || !Active(player))
				{
					return;
				}
				int num = req.GetAmount(quality) * craftMultiplier;
				if (TotalCount(player, req.m_resItem.m_itemData.m_shared.m_name) >= num)
				{
					Transform obj = elementRoot.Find("res_amount");
					TMP_Text val = ((obj != null) ? ((Component)obj).GetComponent<TMP_Text>() : null);
					if ((Object)(object)val != (Object)null)
					{
						((Graphic)val).color = Color.white;
					}
				}
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "SetupRequirementList")]
		private static class SetupRequirementListPatch
		{
			private static void Postfix(InventoryGui __instance, int quality, int amount)
			{
				ShownRequirements.Clear();
				ShownRequirements.AddRange(__instance.m_reqList);
				ShownQuality = quality;
				ShownMultiplier = Mathf.Max(1, amount);
				ShownTime = Time.time;
			}
		}

		internal static readonly List<Requirement> ShownRequirements = new List<Requirement>();

		internal static int ShownQuality;

		internal static int ShownMultiplier = 1;

		internal static float ShownTime = -10f;

		private static bool _inDoCrafting;

		internal static bool Active(Player player)
		{
			if (Plugin.ModEnabled.Value && Plugin.CraftFromChests.Value && (Object)(object)player != (Object)null && (Object)(object)player == (Object)(object)Player.m_localPlayer)
			{
				if (Plugin.RequireStation.Value)
				{
					return (Object)(object)player.GetCurrentCraftingStation() != (Object)null;
				}
				return true;
			}
			return false;
		}

		internal static int ChestCount(Player player, string itemName)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			return Chests.Count(itemName, ((Component)player).transform.position, Plugin.CraftingRange.Value);
		}

		internal static int TotalCount(Player player, string itemName)
		{
			return ((Humanoid)player).GetInventory().CountItems(itemName, -1, true) + ChestCount(player, itemName);
		}

		private static bool Applies(Requirement req, CraftingStation station)
		{
			if (!Object.op_Implicit((Object)(object)req.m_resItem))
			{
				return false;
			}
			if ((Object)(object)station != (Object)null && station.m_upgrader != req.m_upgraderResource)
			{
				return false;
			}
			if ((Object)(object)station == (Object)null && req.m_upgraderResource)
			{
				return false;
			}
			return true;
		}
	}
	internal static class Deposit
	{
		internal static void Run(Player player)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			Inventory inventory = ((Humanoid)player).GetInventory();
			List<Container> list = Chests.InRange(((Component)player).transform.position, Plugin.DepositRange.Value);
			if (list.Count == 0)
			{
				return;
			}
			ItemData val = (((Object)(object)InventoryGui.instance != (Object)null) ? InventoryGui.instance.m_dragItem : null);
			List<ItemData> list2 = new List<ItemData>();
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (!ItemLock.IsLocked(allItem) && allItem != val && (!Plugin.SkipEquipped.Value || !allItem.m_equipped) && (!Plugin.SkipHotbar.Value || allItem.m_gridPos.y != 0))
				{
					list2.Add(allItem);
				}
			}
			int num = 0;
			foreach (ItemData item in list2)
			{
				foreach (Container item2 in list)
				{
					if (TryMove(inventory, item2, item))
					{
						num++;
						break;
					}
				}
			}
			inventory.Changed(false, false);
			Chests.Invalidate();
			Plugin.Log.LogInfo((object)$"Deposit: {list.Count} chests in range, {list2.Count} candidate stacks, {num} fully deposited");
		}

		private static bool TryMove(Inventory from, Container chest, ItemData item)
		{
			Inventory inventory = chest.GetInventory();
			if (!inventory.ContainsItemByName(item.m_shared.m_name))
			{
				return false;
			}
			if (!inventory.HaveEmptySlot() && inventory.FindFreeStackSpace(item.m_shared.m_name, (float)item.m_worldLevel) <= 0)
			{
				return false;
			}
			chest.m_nview.ClaimOwnership();
			if (inventory.AddItem(item))
			{
				from.RemoveItem(item);
				return true;
			}
			return false;
		}
	}
	internal static class ItemLock
	{
		private const string Key = "ChestLink.Locked";

		internal static bool IsLocked(ItemData item)
		{
			if (item != null && item.m_customData != null)
			{
				return item.m_customData.ContainsKey("ChestLink.Locked");
			}
			return false;
		}

		internal static void ToggleSelected(Player player)
		{
			ItemData selectedItem = GetSelectedItem(player);
			if (selectedItem != null)
			{
				if (IsLocked(selectedItem))
				{
					selectedItem.m_customData.Remove("ChestLink.Locked");
					((Character)player).Message((MessageType)1, Localization.instance.Localize(selectedItem.m_shared.m_name) + " unlocked", 0, (Sprite)null, false);
				}
				else
				{
					selectedItem.m_customData["ChestLink.Locked"] = "1";
					((Character)player).Message((MessageType)1, Localization.instance.Localize(selectedItem.m_shared.m_name) + " locked", 0, (Sprite)null, false);
				}
			}
		}

		private static ItemData GetSelectedItem(Player player)
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			InventoryGui instance = InventoryGui.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return null;
			}
			Inventory inventory = ((Humanoid)player).GetInventory();
			if (instance.m_dragItem != null && instance.m_dragInventory == inventory)
			{
				return instance.m_dragItem;
			}
			InventoryGrid playerGrid = instance.m_playerGrid;
			InventoryElement val = (((Object)(object)playerGrid != (Object)null) ? playerGrid.GetHoveredElement() : null);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Inventory inventory2 = playerGrid.GetInventory();
			if (inventory2 == null)
			{
				return null;
			}
			return inventory2.GetItemAt(val.Position.x, val.Position.y);
		}
	}
	internal class Overlay : MonoBehaviour
	{
		private struct Row
		{
			public Sprite Icon;

			public string Name;

			public string Value;

			public Color Color;

			public bool Selected;
		}

		private const float PanelWidth = 320f;

		private const float RowHeight = 30f;

		private const float IconSize = 26f;

		private GUIStyle _title;

		private GUIStyle _row;

		private GUIStyle _rowRight;

		private GUIStyle _hint;

		private Texture2D _bg;

		private Texture2D _lockTex;

		private readonly Vector3[] _corners = (Vector3[])(object)new Vector3[4];

		private readonly List<Row> _rows = new List<Row>();

		private void InitStyles()
		{
			//IL_001e: 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_005c: 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_0069: 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_007c: Expected O, but got Unknown
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: 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_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Expected O, but got Unknown
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Expected O, but got Unknown
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Expected O, but got Unknown
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			if (_title == null)
			{
				_bg = MakeTex(new Color(0.05f, 0.04f, 0.03f, 0.82f));
				_lockTex = MakeTex(new Color(1f, 0.62f, 0.1f, 0.95f));
				_title = new GUIStyle(GUI.skin.label)
				{
					fontSize = 17,
					fontStyle = (FontStyle)1,
					alignment = (TextAnchor)3
				};
				_title.normal.textColor = new Color(1f, 0.82f, 0.45f);
				_row = new GUIStyle(GUI.skin.label)
				{
					fontSize = 15,
					alignment = (TextAnchor)3,
					clipping = (TextClipping)1
				};
				_rowRight = new GUIStyle(_row)
				{
					alignment = (TextAnchor)5,
					fontStyle = (FontStyle)1
				};
				_hint = new GUIStyle(GUI.skin.label)
				{
					fontSize = 12,
					wordWrap = true
				};
				_hint.normal.textColor = new Color(0.8f, 0.8f, 0.8f);
			}
		}

		private static Texture2D MakeTex(Color c)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			Texture2D val = new Texture2D(1, 1);
			val.SetPixel(0, 0, c);
			val.Apply();
			return val;
		}

		private void OnGUI()
		{
			Player localPlayer = Player.m_localPlayer;
			if (!Plugin.ModEnabled.Value || (Object)(object)localPlayer == (Object)null || ConfigWindow.IsOpen)
			{
				return;
			}
			InitStyles();
			if (InventoryGui.IsVisible())
			{
				if (Plugin.ShowLockMarkers.Value)
				{
					DrawLockMarkers(localPlayer);
				}
				if (Plugin.ShowRequirementPanel.Value)
				{
					DrawRequirementPanel(localPlayer);
				}
			}
			else if (Plugin.ShowSmelterPanel.Value && (Object)(object)SmelterHandler.Hovered != (Object)null)
			{
				DrawSmelterPanel(localPlayer);
			}
		}

		private void DrawRequirementPanel(Player player)
		{
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			InventoryGui instance = InventoryGui.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)((RecipeDataPair)(ref instance.m_selectedRecipe)).Recipe == (Object)null || Time.time - Crafting.ShownTime > 0.5f || Crafting.ShownRequirements.Count == 0)
			{
				return;
			}
			_rows.Clear();
			foreach (Requirement shownRequirement in Crafting.ShownRequirements)
			{
				if (!((Object)(object)shownRequirement.m_resItem == (Object)null))
				{
					int num = shownRequirement.GetAmount(Crafting.ShownQuality) * Crafting.ShownMultiplier;
					if (num > 0)
					{
						string name = shownRequirement.m_resItem.m_itemData.m_shared.m_name;
						int num2 = Crafting.TotalCount(player, name);
						_rows.Add(new Row
						{
							Icon = shownRequirement.m_resItem.m_itemData.GetIcon(),
							Name = Localization.instance.Localize(name),
							Value = $"{num2} / {num}",
							Color = ((num2 >= num) ? new Color(0.55f, 1f, 0.55f) : new Color(1f, 0.45f, 0.4f))
						});
					}
				}
			}
			if (_rows.Count != 0)
			{
				string title = Localization.instance.Localize(((RecipeDataPair)(ref instance.m_selectedRecipe)).Recipe.m_item.m_itemData.m_shared.m_name);
				string hint = (Crafting.Active(player) ? $"In range = inventory + chests within {Plugin.CraftingRange.Value:0} m" : "Use a crafting station to include nearby chests");
				DrawPanel(title, "Have / Need", hint);
			}
		}

		private void DrawSmelterPanel(Player player)
		{
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			Smelter hovered = SmelterHandler.Hovered;
			_rows.Clear();
			if ((Object)(object)hovered.m_fuelItem != (Object)null && hovered.m_maxFuel > 0)
			{
				string name = hovered.m_fuelItem.m_itemData.m_shared.m_name;
				_rows.Add(new Row
				{
					Icon = hovered.m_fuelItem.m_itemData.GetIcon(),
					Name = Localization.instance.Localize(name) + $"  ({Mathf.CeilToInt(hovered.GetFuel())}/{hovered.m_maxFuel})",
					Value = SmelterHandler.InRange(player, name).ToString(),
					Color = Color.white
				});
			}
			int selectedIndex = SmelterHandler.SelectedIndex;
			for (int i = 0; i < SmelterHandler.Options.Count; i++)
			{
				ItemDrop val = SmelterHandler.Options[i];
				string name2 = val.m_itemData.m_shared.m_name;
				int num = SmelterHandler.InRange(player, name2);
				_rows.Add(new Row
				{
					Icon = val.m_itemData.GetIcon(),
					Name = ((i == selectedIndex) ? "> " : "   ") + Localization.instance.Localize(name2),
					Value = num.ToString(),
					Color = (Color)((i == selectedIndex) ? new Color(1f, 0.85f, 0.35f) : ((num > 0) ? Color.white : new Color(0.6f, 0.6f, 0.6f))),
					Selected = (i == selectedIndex)
				});
			}
			if (_rows.Count != 0)
			{
				string text = ((object)Plugin.SmelterModifier.Value/*cast due to .constrained prefix*/).ToString();
				string title = Localization.instance.Localize(hovered.m_name) + $"  ({hovered.GetQueueSize()}/{hovered.m_maxOre})";
				string hint = $"Hold {text} + scroll to choose, {text} + E to fill from chests within {Plugin.SmelterRange.Value:0} m";
				DrawPanel(title, "In range", hint);
			}
		}

		private void DrawPanel(string title, string header, string hint)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Expected O, but got Unknown
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			float num = 56f + (float)_rows.Count * 30f + 44f;
			float num2 = (float)Screen.width - 320f - 24f;
			float num3 = Mathf.Max(20f, (float)Screen.height * 0.28f);
			GUI.DrawTexture(new Rect(num2, num3, 320f, num), (Texture)(object)_bg);
			float num4 = num3 + 6f;
			GUI.Label(new Rect(num2 + 10f, num4, 300f, 26f), title, _title);
			num4 += 30f;
			GUIStyle val = new GUIStyle(_hint)
			{
				alignment = (TextAnchor)5
			};
			GUI.Label(new Rect(num2 + 10f, num4, 300f, 20f), header, val);
			num4 += 22f;
			foreach (Row row in _rows)
			{
				if (row.Selected)
				{
					GUI.DrawTexture(new Rect(num2 + 4f, num4, 312f, 28f), (Texture)(object)_bg);
				}
				if ((Object)(object)row.Icon != (Object)null)
				{
					DrawSprite(new Rect(num2 + 10f, num4 + 2f, 26f, 26f), row.Icon);
				}
				_row.normal.textColor = row.Color;
				_rowRight.normal.textColor = row.Color;
				GUI.Label(new Rect(num2 + 44f, num4, 180f, 30f), row.Name, _row);
				GUI.Label(new Rect(num2 + 320f - 100f, num4, 90f, 30f), row.Value, _rowRight);
				num4 += 30f;
			}
			GUI.Label(new Rect(num2 + 10f, num4 + 4f, 300f, 40f), hint, _hint);
		}

		private static void DrawSprite(Rect rect, Sprite sprite)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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)
			Texture texture = (Texture)(object)sprite.texture;
			if (!((Object)(object)texture == (Object)null))
			{
				Rect textureRect = sprite.textureRect;
				Rect val = default(Rect);
				((Rect)(ref val))..ctor(((Rect)(ref textureRect)).x / (float)texture.width, ((Rect)(ref textureRect)).y / (float)texture.height, ((Rect)(ref textureRect)).width / (float)texture.width, ((Rect)(ref textureRect)).height / (float)texture.height);
				GUI.DrawTextureWithTexCoords(rect, texture, val);
			}
		}

		private void DrawLockMarkers(Player player)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			InventoryGrid val = (((Object)(object)InventoryGui.instance != (Object)null) ? InventoryGui.instance.m_playerGrid : null);
			Inventory val2 = (((Object)(object)val != (Object)null) ? val.GetInventory() : null);
			if (val2 == null || val.m_elements == null)
			{
				return;
			}
			foreach (InventoryElement element in val.m_elements)
			{
				if (!((Object)(object)element == (Object)null) && ItemLock.IsLocked(val2.GetItemAt(element.Position.x, element.Position.y)))
				{
					Rect val3 = ScreenRect(element.GetElementRectTransform());
					if (!(((Rect)(ref val3)).width <= 0f))
					{
						GUI.DrawTexture(new Rect(((Rect)(ref val3)).x, ((Rect)(ref val3)).y, ((Rect)(ref val3)).width, 2f), (Texture)(object)_lockTex);
						GUI.DrawTexture(new Rect(((Rect)(ref val3)).x, ((Rect)(ref val3)).yMax - 2f, ((Rect)(ref val3)).width, 2f), (Texture)(object)_lockTex);
						GUI.DrawTexture(new Rect(((Rect)(ref val3)).x, ((Rect)(ref val3)).y, 2f, ((Rect)(ref val3)).height), (Texture)(object)_lockTex);
						GUI.DrawTexture(new Rect(((Rect)(ref val3)).xMax - 2f, ((Rect)(ref val3)).y, 2f, ((Rect)(ref val3)).height), (Texture)(object)_lockTex);
						GUI.DrawTexture(new Rect(((Rect)(ref val3)).x + 3f, ((Rect)(ref val3)).y + 3f, 9f, 7f), (Texture)(object)_lockTex);
						GUI.DrawTexture(new Rect(((Rect)(ref val3)).x + 5f, ((Rect)(ref val3)).y + 0f, 5f, 3f), (Texture)(object)_lockTex);
					}
				}
			}
		}

		private Rect ScreenRect(RectTransform rt)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)rt == (Object)null)
			{
				return default(Rect);
			}
			Canvas componentInParent = ((Component)rt).GetComponentInParent<Canvas>();
			Camera val = null;
			if ((Object)(object)componentInParent != (Object)null && (int)componentInParent.rootCanvas.renderMode != 0)
			{
				val = componentInParent.rootCanvas.worldCamera;
			}
			rt.GetWorldCorners(_corners);
			Vector2 val2 = RectTransformUtility.WorldToScreenPoint(val, _corners[0]);
			Vector2 val3 = RectTransformUtility.WorldToScreenPoint(val, _corners[2]);
			return new Rect(val2.x, (float)Screen.height - val3.y, val3.x - val2.x, val3.y - val2.y);
		}
	}
	[BepInPlugin("chestlink.valheim", "Supermans Auto Storage/Craft", "1.0.6")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "chestlink.valheim";

		public const string Name = "Supermans Auto Storage/Craft";

		public const string Version = "1.0.6";

		internal static Plugin Instance;

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> ModEnabled;

		internal static ConfigEntry<float> DepositRange;

		internal static ConfigEntry<float> CraftingRange;

		internal static ConfigEntry<float> SmelterRange;

		internal static ConfigEntry<KeyCode> DepositKey;

		internal static ConfigEntry<KeyCode> LockKey;

		internal static ConfigEntry<KeyCode> LockModifier;

		internal static ConfigEntry<KeyCode> SmelterModifier;

		internal static ConfigEntry<KeyCode> ConfigMenuKey;

		internal static ConfigEntry<bool> SkipEquipped;

		internal static ConfigEntry<bool> SkipHotbar;

		internal static ConfigEntry<bool> IncludeCartsAndShips;

		internal static ConfigEntry<bool> CraftFromChests;

		internal static ConfigEntry<bool> RequireStation;

		internal static ConfigEntry<bool> CookFromChests;

		internal static ConfigEntry<bool> SmelterFromChests;

		internal static ConfigEntry<bool> ShowRequirementPanel;

		internal static ConfigEntry<bool> ShowSmelterPanel;

		internal static ConfigEntry<bool> ShowLockMarkers;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Expected O, but got Unknown
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Expected O, but got Unknown
			//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cc: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			ModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Enabled", true, "Master switch for the whole mod.");
			AcceptableValueRange<float> val = new AcceptableValueRange<float>(1f, 50f);
			DepositRange = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Ranges", "DepositRange", 15f, new ConfigDescription("Meters around the player searched for chests when auto-depositing.", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			CraftingRange = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Ranges", "CraftingRange", 15f, new ConfigDescription("Meters around the player searched for chests when crafting, upgrading and cooking.", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			SmelterRange = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Ranges", "SmelterRange", 15f, new ConfigDescription("Meters around the player searched for chests when filling smelters/kilns/furnaces.", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			DepositKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("3 - Keys", "DepositKey", (KeyCode)46, "Deposit unlocked items into nearby chests that already hold at least one of the same item.");
			LockKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("3 - Keys", "LockKey", (KeyCode)102, "With the inventory open, hover or pick up an item and press LockModifier + this key to lock/unlock it.");
			LockModifier = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("3 - Keys", "LockModifier", (KeyCode)304, "Modifier held together with LockKey.");
			SmelterModifier = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("3 - Keys", "SmelterModifier", (KeyCode)304, "Hold while looking at a smelter: scroll to choose the ore, press Use (E) to fill it from nearby chests.");
			ConfigMenuKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("3 - Keys", "ConfigMenuKey", (KeyCode)282, "Opens the in-game Supermans Auto Storage/Craft settings window.");
			SkipEquipped = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Deposit", "SkipEquippedItems", true, "Never deposit items you currently have equipped.");
			SkipHotbar = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Deposit", "SkipHotbar", false, "Never deposit items in the hotbar (top inventory row).");
			IncludeCartsAndShips = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Deposit", "IncludeCartsAndShips", false, "Also use cart and ship storage as nearby chests.");
			CraftFromChests = ((BaseUnityPlugin)this).Config.Bind<bool>("5 - Crafting", "CraftFromChests", true, "Crafting, upgrading and cauldron cooking can use materials from nearby chests.");
			RequireStation = ((BaseUnityPlugin)this).Config.Bind<bool>("5 - Crafting", "RequireStation", true, "Only pull from chests while using a crafting station (workbench, forge, cauldron...).");
			CookFromChests = ((BaseUnityPlugin)this).Config.Bind<bool>("5 - Crafting", "CookFromChests", true, "Cooking stations (spits, iron cooking station, oven) pull raw food from nearby chests when you have none.");
			SmelterFromChests = ((BaseUnityPlugin)this).Config.Bind<bool>("5 - Crafting", "SmelterFromChests", true, "Enable SmelterModifier + Use to fill smelters from nearby chests.");
			ShowRequirementPanel = ((BaseUnityPlugin)this).Config.Bind<bool>("6 - UI", "ShowRequirementPanel", true, "Show the needed items and how many are in range on the right side of the screen while crafting.");
			ShowSmelterPanel = ((BaseUnityPlugin)this).Config.Bind<bool>("6 - UI", "ShowSmelterPanel", true, "Show fuel/ore counts in range on the right side of the screen when looking at a smelter.");
			ShowLockMarkers = ((BaseUnityPlugin)this).Config.Bind<bool>("6 - UI", "ShowLockMarkers", true, "Draw a marker on locked inventory slots.");
			_harmony = new Harmony("chestlink.valheim");
			_harmony.PatchAll(typeof(Plugin).Assembly);
			((Component)this).gameObject.AddComponent<Overlay>();
			((Component)this).gameObject.AddComponent<ConfigWindow>();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Supermans Auto Storage/Craft 1.0.6 loaded");
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private void Update()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			if (ZInput.instance != null && ZInput.GetKeyDown(ConfigMenuKey.Value, false) && !IsTyping())
			{
				ConfigWindow.Toggle();
			}
			Player localPlayer = Player.m_localPlayer;
			if (!ModEnabled.Value || (Object)(object)localPlayer == (Object)null || ConfigWindow.IsOpen || IsTyping())
			{
				SmelterHandler.Hovered = null;
				return;
			}
			if (ZInput.GetKeyDown(DepositKey.Value, false) && !Menu.IsVisible())
			{
				Deposit.Run(localPlayer);
			}
			if (InventoryGui.IsVisible() && ZInput.GetKey(LockModifier.Value, false) && ZInput.GetKeyDown(LockKey.Value, false))
			{
				ItemLock.ToggleSelected(localPlayer);
			}
			SmelterHandler.UpdateHover(localPlayer);
		}

		internal static bool IsTyping()
		{
			if ((!((Object)(object)Chat.instance != (Object)null) || !Chat.instance.HasFocus()) && !Console.IsVisible() && !TextInput.IsVisible() && !Minimap.InTextInput())
			{
				if ((Object)(object)TextViewer.instance != (Object)null)
				{
					return TextViewer.instance.IsVisible();
				}
				return false;
			}
			return true;
		}
	}
	internal static class SmelterHandler
	{
		[HarmonyPatch(typeof(Player), "Interact")]
		private static class PlayerInteractPatch
		{
			private static bool Prefix(Player __instance, GameObject go, bool hold)
			{
				if (!Plugin.ModEnabled.Value || !Plugin.SmelterFromChests.Value || (Object)(object)__instance != (Object)(object)Player.m_localPlayer)
				{
					return true;
				}
				if ((Object)(object)go == (Object)null || !ModifierHeld)
				{
					return true;
				}
				Smelter componentInParent = go.GetComponentInParent<Smelter>();
				if ((Object)(object)componentInParent == (Object)null)
				{
					return true;
				}
				if (!hold)
				{
					Fill(__instance, componentInParent);
				}
				return false;
			}
		}

		internal static Smelter Hovered;

		internal static readonly List<ItemDrop> Options = new List<ItemDrop>();

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

		private static readonly Dictionary<int, float> LastFill = new Dictionary<int, float>();

		private const float FillCooldown = 1.5f;

		internal static int SelectedIndex
		{
			get
			{
				if (!((Object)(object)Hovered != (Object)null) || !SelectedByType.TryGetValue(Hovered.m_name, out var value))
				{
					return 0;
				}
				return Mathf.Clamp(value, 0, Mathf.Max(0, Options.Count - 1));
			}
		}

		internal static bool ModifierHeld => ZInput.GetKey(Plugin.SmelterModifier.Value, false);

		internal static void UpdateHover(Player player)
		{
			Hovered = null;
			Options.Clear();
			if (!Plugin.SmelterFromChests.Value)
			{
				return;
			}
			GameObject hoverObject = ((Humanoid)player).GetHoverObject();
			Smelter val = (((Object)(object)hoverObject != (Object)null) ? hoverObject.GetComponentInParent<Smelter>() : null);
			if ((Object)(object)val == (Object)null || (Object)(object)val.m_nview == (Object)null || !val.m_nview.IsValid())
			{
				return;
			}
			Hovered = val;
			foreach (ItemConversion conv in val.m_conversion)
			{
				if ((Object)(object)conv.m_from != (Object)null && !Options.Exists((ItemDrop o) => o.m_itemData.m_shared.m_name == conv.m_from.m_itemData.m_shared.m_name))
				{
					Options.Add(conv.m_from);
				}
			}
			if (!ModifierHeld || Options.Count == 0)
			{
				return;
			}
			float mouseScrollWheel = ZInput.GetMouseScrollWheel();
			if (!(Mathf.Abs(mouseScrollWheel) < 0.01f))
			{
				int num = SelectedIndex + ((!(mouseScrollWheel > 0f)) ? 1 : (-1));
				if (num < 0)
				{
					num = Options.Count - 1;
				}
				if (num >= Options.Count)
				{
					num = 0;
				}
				SelectedByType[val.m_name] = num;
			}
		}

		internal static int InRange(Player player, string itemName)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			return ((Humanoid)player).GetInventory().CountItems(itemName, -1, true) + Chests.Count(itemName, ((Component)player).transform.position, Plugin.SmelterRange.Value);
		}

		private static int Take(Player player, string itemName, int amount)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			if (amount <= 0)
			{
				return 0;
			}
			int num = Chests.Remove(itemName, amount, ((Component)player).transform.position, Plugin.SmelterRange.Value);
			if (num < amount)
			{
				Inventory inventory = ((Humanoid)player).GetInventory();
				int num2 = Mathf.Min(amount - num, inventory.CountItems(itemName, -1, true));
				if (num2 > 0)
				{
					inventory.RemoveItem(itemName, num2, -1, true);
					num += num2;
				}
			}
			return num;
		}

		private static void Fill(Player player, Smelter smelter)
		{
			int instanceID = ((Object)smelter).GetInstanceID();
			if (LastFill.TryGetValue(instanceID, out var value) && Time.time - value < 1.5f)
			{
				return;
			}
			LastFill[instanceID] = Time.time;
			int num = 0;
			string text = null;
			if ((Object)(object)smelter.m_fuelItem != (Object)null && smelter.m_maxFuel > 0)
			{
				text = smelter.m_fuelItem.m_itemData.m_shared.m_name;
				int amount = smelter.m_maxFuel - Mathf.CeilToInt(smelter.GetFuel());
				num = Take(player, text, amount);
				for (int i = 0; i < num; i++)
				{
					smelter.m_nview.InvokeRPC("RPC_AddFuel", Array.Empty<object>());
				}
			}
			int num2 = 0;
			string text2 = null;
			if (Options.Count > 0)
			{
				ItemDrop val = Options[SelectedIndex];
				text2 = val.m_itemData.m_shared.m_name;
				int amount2 = smelter.m_maxOre - smelter.GetQueueSize();
				num2 = Take(player, text2, amount2);
				for (int j = 0; j < num2; j++)
				{
					smelter.m_nview.InvokeRPC("RPC_AddOre", new object[2]
					{
						((Object)((Component)val).gameObject).name,
						false
					});
				}
			}
			Chests.Invalidate();
			if (num == 0 && num2 == 0)
			{
				((Character)player).Message((MessageType)2, "Nothing to add", 0, (Sprite)null, false);
				return;
			}
			List<string> list = new List<string>();
			if (num2 > 0)
			{
				list.Add($"{num2} {Localization.instance.Localize(text2)}");
			}
			if (num > 0)
			{
				list.Add($"{num} {Localization.instance.Localize(text)}");
			}
			((Character)player).Message((MessageType)2, "Added " + string.Join(", ", list.ToArray()), 0, (Sprite)null, false);
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}