Decompiled source of EnchantingPouch v1.2.11

plugins/EnchantingPouch.dll

Decompiled 7 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
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.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("Valheim Overhaul")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("EpicLoot enchanting pouch with JamesJones progression, magic-blue world glow, no AzuEPI slot.")]
[assembly: AssemblyFileVersion("1.2.0.0")]
[assembly: AssemblyInformationalVersion("1.2.0")]
[assembly: AssemblyProduct("EnchantingPouch")]
[assembly: AssemblyTitle("EnchantingPouch")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.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 EnchantingPouch
{
	internal static class MatFilter
	{
		private static readonly HashSet<string> Exact = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "ForestToken", "IronBountyToken", "GoldBountyToken", "EtchedRunestoneMagic", "EtchedRunestoneRare", "EtchedRunestoneEpic", "EtchedRunestoneLegendary", "EtchedRunestoneMythic" };

		internal static bool IsEnchantingMat(ItemData item)
		{
			if (item == null)
			{
				return false;
			}
			string text = null;
			if ((Object)(object)item.m_dropPrefab != (Object)null)
			{
				text = Utils.GetPrefabName(item.m_dropPrefab);
			}
			if (string.IsNullOrEmpty(text) && item.m_shared != null)
			{
				text = item.m_shared.m_name;
			}
			return IsEnchantingMatName(text);
		}

		internal static bool IsEnchantingMatName(string prefabOrToken)
		{
			if (string.IsNullOrEmpty(prefabOrToken))
			{
				return false;
			}
			string text = prefabOrToken;
			if (text.StartsWith("$item_", StringComparison.OrdinalIgnoreCase))
			{
				text = text.Substring(6);
			}
			if (Exact.Contains(text))
			{
				return true;
			}
			if (text.StartsWith("Dust", StringComparison.OrdinalIgnoreCase) || text.StartsWith("Essence", StringComparison.OrdinalIgnoreCase) || text.StartsWith("Reagent", StringComparison.OrdinalIgnoreCase) || text.StartsWith("Shard", StringComparison.OrdinalIgnoreCase) || text.StartsWith("Runestone", StringComparison.OrdinalIgnoreCase) || text.StartsWith("EtchedRunestone", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			if (text.IndexOf("_Unidentified", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(Humanoid), "UseItem")]
	internal static class Humanoid_UseItem_Patch
	{
		private static bool Prefix(Humanoid __instance, ItemData item)
		{
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if (val == null || (Object)(object)val != (Object)(object)Player.m_localPlayer)
			{
				return true;
			}
			if (!PouchItem.IsPouch(item))
			{
				return true;
			}
			PouchItem.ToggleEquip(val, item);
			return false;
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "Update")]
	internal static class InventoryGui_Update_OpenPouch_Patch
	{
		internal static bool SuppressHideOnce;

		internal static int BlockShowFrames;

		private static void Prefix(InventoryGui __instance)
		{
			if (!Plugin.OpenWithE.Value || (Object)(object)__instance == (Object)null || !InventoryGui.IsVisible() || (Object)(object)__instance.m_dragGo != (Object)null || (!ZInput.GetButtonDown("Use") && !ZInput.GetButtonDown("JoyUse")))
			{
				return;
			}
			ItemData val = GetHoveredItem(__instance.m_playerGrid) ?? GetHoveredItem(__instance.m_containerGrid);
			if (val != null && PouchItem.IsPouch(val))
			{
				Player localPlayer = Player.m_localPlayer;
				if (!((Object)(object)localPlayer == (Object)null))
				{
					ZInput.ResetButtonStatus("Use");
					ZInput.ResetButtonStatus("JoyUse");
					SuppressHideOnce = true;
					PouchContainer.Toggle(localPlayer, val);
				}
			}
		}

		private static void Postfix()
		{
			SuppressHideOnce = false;
			if (BlockShowFrames > 0)
			{
				BlockShowFrames--;
			}
		}

		private static ItemData GetHoveredItem(InventoryGrid grid)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: 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_009e: Unknown result type (might be due to invalid IL or missing references)
			if (grid?.m_elements == null || grid.m_inventory == null)
			{
				return null;
			}
			Vector2 val = Vector2.op_Implicit(ZInput.mousePosition);
			foreach (Element element in grid.m_elements)
			{
				if ((Object)(object)element?.m_go == (Object)null || !element.m_go.activeInHierarchy)
				{
					continue;
				}
				Transform transform = element.m_go.transform;
				RectTransform val2 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
				if (val2 != null)
				{
					Canvas componentInParent = element.m_go.GetComponentInParent<Canvas>();
					Camera val3 = (((Object)(object)componentInParent != (Object)null && (int)componentInParent.renderMode != 0) ? componentInParent.worldCamera : null);
					if (RectTransformUtility.RectangleContainsScreenPoint(val2, val, val3))
					{
						return grid.m_inventory.GetItemAt(element.m_pos.x, element.m_pos.y);
					}
				}
			}
			return null;
		}
	}
	[HarmonyPatch(typeof(Container), "IsOwner")]
	internal static class Container_IsOwner_Patch
	{
		private static void Postfix(Container __instance, ref bool __result)
		{
			if (!__result && PouchContainer.IsOurContainer(__instance))
			{
				__result = true;
			}
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "Hide")]
	internal static class InventoryGui_Hide_Patch
	{
		private static bool Prefix()
		{
			bool flag = ZInput.GetKeyDown((KeyCode)27, true) || ZInput.GetButtonDown("Inventory") || ZInput.GetButtonDown("JoyButtonB") || ZInput.GetButtonDown("JoyButtonY");
			if (InventoryGui_Update_OpenPouch_Patch.SuppressHideOnce)
			{
				InventoryGui_Update_OpenPouch_Patch.SuppressHideOnce = false;
				if (!flag)
				{
					return false;
				}
			}
			if (PouchContainer.IsOpen || PouchContainer.BoundItem != null)
			{
				PouchContainer.Close(save: true);
			}
			PouchCloseButton.SetVisible(visible: false);
			InventoryGui_Update_OpenPouch_Patch.BlockShowFrames = 5;
			return true;
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "Show")]
	internal static class InventoryGui_Show_Patch
	{
		private static bool Prefix(InventoryGui __instance, Container container)
		{
			if (PouchContainer.OpeningGuarded)
			{
				return true;
			}
			if (InventoryGui_Update_OpenPouch_Patch.BlockShowFrames <= 0)
			{
				return true;
			}
			if (InventoryGui.IsVisible())
			{
				return true;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "CloseContainer")]
	internal static class InventoryGui_CloseContainer_Patch
	{
		private static void Prefix(InventoryGui __instance)
		{
			if (PouchContainer.IsBoundContainer(((Object)(object)__instance != (Object)null) ? __instance.m_currentContainer : null))
			{
				PouchContainer.OnContainerClosing();
			}
		}
	}
	[HarmonyPatch(typeof(Player), "GetAvailableRecipes")]
	internal static class Player_GetAvailableRecipes_Patch
	{
		private static void Postfix(Player __instance, ref List<Recipe> available)
		{
			PouchItem.EnsureAvailable(__instance, available);
		}
	}
	[HarmonyPatch(typeof(Player), "UpdateKnownRecipesList")]
	internal static class Player_UpdateKnownRecipesList_Patch
	{
		private static void Postfix(Player __instance)
		{
			PouchItem.UnlockKnownRecipe(__instance);
		}
	}
	[HarmonyPatch(typeof(Player), "OnSpawned")]
	internal static class Player_OnSpawned_Patch
	{
		private static void Postfix(Player __instance)
		{
			PouchItem.UnlockKnownRecipe(__instance);
			if ((Object)(object)ObjectDB.instance != (Object)null)
			{
				PouchItem.TryRegister(ObjectDB.instance);
			}
			PouchItem.FixDropPrefabs(((Humanoid)__instance).GetInventory());
		}
	}
	internal static class WorldPickupGuard
	{
		[ThreadStatic]
		private static int _depth;

		internal static bool IsWorldPickup => _depth > 0;

		internal static void Enter()
		{
			_depth++;
		}

		internal static void Exit()
		{
			if (_depth > 0)
			{
				_depth--;
			}
		}
	}
	[HarmonyPatch(typeof(ItemDrop), "Pickup")]
	internal static class ItemDrop_Pickup_Patch
	{
		private static void Prefix()
		{
			WorldPickupGuard.Enter();
		}

		private static void Finally()
		{
			WorldPickupGuard.Exit();
		}
	}
	[HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData) })]
	internal static class Inventory_AddItem_Patch
	{
		[ThreadStatic]
		private static bool _busy;

		private static bool Prefix(Inventory __instance, ItemData item, ref bool __result)
		{
			if (_busy || !Plugin.AutoDeposit.Value || !WorldPickupGuard.IsWorldPickup || item == null || !MatFilter.IsEnchantingMat(item))
			{
				return true;
			}
			if (PouchContainer.IsOpen && PouchContainer.GetInventory() == __instance)
			{
				return true;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || __instance != ((Humanoid)localPlayer).GetInventory())
			{
				return true;
			}
			ItemData val = PouchItem.FindEquipped(localPlayer);
			if (val == null)
			{
				return true;
			}
			return TryDeposit(localPlayer, val, item, ref __result);
		}

		private static bool TryDeposit(Player player, ItemData pouch, ItemData item, ref bool __result)
		{
			Inventory val = ((PouchContainer.IsOpen && PouchContainer.BoundItem == pouch) ? PouchContainer.GetInventory() : null);
			_busy = true;
			try
			{
				if (val != null)
				{
					if (!val.CanAddItem(item, -1))
					{
						return true;
					}
					val.AddItem(item);
					__result = true;
					return false;
				}
				Inventory val2 = PouchContainer.PeekInventory(pouch);
				if (!val2.CanAddItem(item, -1))
				{
					return true;
				}
				val2.AddItem(item);
				PouchContainer.CommitPeek(pouch, val2);
				__result = true;
				return false;
			}
			finally
			{
				_busy = false;
			}
		}
	}
	[HarmonyPatch(typeof(Inventory), "AddItem", new Type[]
	{
		typeof(string),
		typeof(int),
		typeof(int),
		typeof(int),
		typeof(long),
		typeof(string),
		typeof(bool)
	})]
	internal static class Inventory_AddItem_Prefab_Patch
	{
		[ThreadStatic]
		private static bool _busy;

		private static bool Prefix(Inventory __instance, string name, int stack, int quality, int variant, long crafterID, string crafterName, ref ItemData __result)
		{
			if (_busy || !Plugin.AutoDeposit.Value || !WorldPickupGuard.IsWorldPickup || !MatFilter.IsEnchantingMatName(name))
			{
				return true;
			}
			if (PouchContainer.IsOpen && PouchContainer.GetInventory() == __instance)
			{
				return true;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || __instance != ((Humanoid)localPlayer).GetInventory())
			{
				return true;
			}
			ItemData val = PouchItem.FindEquipped(localPlayer);
			if (val == null)
			{
				return true;
			}
			GameObject val2 = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(name) : null);
			if ((Object)(object)val2 == (Object)null)
			{
				return true;
			}
			ItemData val3 = val2.GetComponent<ItemDrop>().m_itemData.Clone();
			val3.m_stack = stack;
			val3.m_quality = quality;
			val3.m_variant = variant;
			val3.m_crafterID = crafterID;
			val3.m_crafterName = crafterName;
			val3.m_dropPrefab = val2;
			Inventory val4 = ((PouchContainer.IsOpen && PouchContainer.BoundItem == val) ? PouchContainer.GetInventory() : null);
			_busy = true;
			try
			{
				if (val4 != null)
				{
					if (!val4.CanAddItem(val3, -1))
					{
						return true;
					}
					val4.AddItem(val3);
					__result = val3;
					return false;
				}
				Inventory val5 = PouchContainer.PeekInventory(val);
				if (!val5.CanAddItem(val3, -1))
				{
					return true;
				}
				val5.AddItem(val3);
				PouchContainer.CommitPeek(val, val5);
				__result = val3;
				return false;
			}
			finally
			{
				_busy = false;
			}
		}
	}
	[BepInPlugin("valheimoverhaul.enchantingpouch", "Enchanting Pouch", "1.2.11")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "valheimoverhaul.enchantingpouch";

		public const string PluginName = "Enchanting Pouch";

		public const string PluginVersion = "1.2.11";

		internal const string PrefabName = "VO_EnchantingPouch";

		internal const string ItemToken = "$item_vo_enchantingpouch";

		internal const string DescToken = "$item_vo_enchantingpouch_desc";

		internal const string CustomDataKey = "valheimoverhaul.enchantingpouch.inv";

		internal const string WeightCacheKey = "valheimoverhaul.enchantingpouch.weight";

		internal static Plugin Instance;

		internal static ManualLogSource Log;

		internal static ConfigEntry<int> Columns;

		internal static ConfigEntry<int> Rows;

		internal static ConfigEntry<bool> AutoDeposit;

		internal static ConfigEntry<bool> OpenWithE;

		internal static ConfigEntry<bool> OpenOnInventory;

		private void Awake()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Expected O, but got Unknown
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Columns = ((BaseUnityPlugin)this).Config.Bind<int>("Storage", "Columns", 2, new ConfigDescription("Fallback columns if quality size fails (normal size comes from upgrade level).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(2, 8), Array.Empty<object>()));
			Rows = ((BaseUnityPlugin)this).Config.Bind<int>("Storage", "Rows", 4, new ConfigDescription("Fallback rows if quality size fails (normal size comes from upgrade level).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(2, 8), Array.Empty<object>()));
			AutoDeposit = ((BaseUnityPlugin)this).Config.Bind<bool>("Storage", "Auto Deposit", true, "While the pouch is equipped, auto-store EpicLoot mats picked up from the ground only.");
			OpenWithE = ((BaseUnityPlugin)this).Config.Bind<bool>("Controls", "Open With E", true, "Press E (Use) while hovering the pouch in the inventory to open it. Vanilla E closes inventory; this intercepts that when the pouch is under the cursor.");
			OpenOnInventory = ((BaseUnityPlugin)this).Config.Bind<bool>("Controls", "Open With Inventory", false, "Unused/legacy. Opening is via E hover; right-click equips.");
			Harmony val = new Harmony("valheimoverhaul.enchantingpouch");
			Type[] types = typeof(Plugin).Assembly.GetTypes();
			foreach (Type type in types)
			{
				try
				{
					val.CreateClassProcessor(type).Patch();
				}
				catch (Exception ex)
				{
					Log.LogError((object)("Failed to patch " + type.Name + ": " + ex.Message));
				}
			}
			Log.LogInfo((object)"Enchanting Pouch 1.2.11 loaded.");
		}
	}
	internal static class PouchCloseButton
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__OnClicked;
		}

		private static GameObject _root;

		private static Button _button;

		internal static void Ensure(InventoryGui gui)
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: 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_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Expected O, but got Unknown
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Expected O, but got Unknown
			if (!((Object)(object)gui?.m_container == (Object)null) && !((Object)(object)gui.m_tabUpgrade == (Object)null) && (!((Object)(object)_root != (Object)null) || ((object)_root).Equals((object?)null)))
			{
				_root = Object.Instantiate<GameObject>(((Component)gui.m_tabUpgrade).gameObject, (Transform)(object)gui.m_container, false);
				((Object)_root).name = "VO_PouchCloseX";
				RectTransform component = _root.GetComponent<RectTransform>();
				if ((Object)(object)component != (Object)null)
				{
					component.anchorMin = new Vector2(1f, 1f);
					component.anchorMax = new Vector2(1f, 1f);
					component.pivot = new Vector2(1f, 1f);
					component.anchoredPosition = new Vector2(-6f, -6f);
					component.sizeDelta = new Vector2(36f, 36f);
					((Transform)component).localScale = Vector3.one;
					((Transform)component).SetAsLastSibling();
				}
				TMP_Text[] componentsInChildren = _root.GetComponentsInChildren<TMP_Text>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					componentsInChildren[i].text = "X";
				}
				Text[] componentsInChildren2 = _root.GetComponentsInChildren<Text>(true);
				for (int i = 0; i < componentsInChildren2.Length; i++)
				{
					componentsInChildren2[i].text = "X";
				}
				_button = _root.GetComponent<Button>();
				if ((Object)(object)_button == (Object)null)
				{
					_button = _root.AddComponent<Button>();
				}
				_button.onClick = new ButtonClickedEvent();
				ButtonClickedEvent onClick = _button.onClick;
				object obj = <>O.<0>__OnClicked;
				if (obj == null)
				{
					UnityAction val = OnClicked;
					<>O.<0>__OnClicked = val;
					obj = (object)val;
				}
				((UnityEvent)onClick).AddListener((UnityAction)obj);
				_root.SetActive(false);
			}
		}

		internal static void SetVisible(bool visible)
		{
			if (((Object)(object)_root == (Object)null || ((object)_root).Equals((object?)null)) && visible && (Object)(object)InventoryGui.instance != (Object)null)
			{
				Ensure(InventoryGui.instance);
			}
			if ((Object)(object)_root != (Object)null && !((object)_root).Equals((object?)null))
			{
				_root.SetActive(visible);
			}
		}

		private static void OnClicked()
		{
			if (PouchContainer.IsOpen)
			{
				PouchContainer.Close(save: true);
			}
			SetVisible(visible: false);
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "Awake")]
	internal static class InventoryGui_Awake_PouchClose_Patch
	{
		private static void Postfix(InventoryGui __instance)
		{
			PouchCloseButton.Ensure(__instance);
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "UpdateContainer")]
	internal static class InventoryGui_UpdateContainer_PouchClose_Patch
	{
		private static void Postfix()
		{
			PouchCloseButton.SetVisible(PouchContainer.IsOpen);
		}
	}
	internal static class PouchContainer
	{
		private static Container _container;

		private static ItemData _boundItem;

		private static bool _suppressSave;

		internal static bool OpeningGuarded { get; private set; }

		internal static bool IsOpen
		{
			get
			{
				if (_boundItem != null && (Object)(object)InventoryGui.instance != (Object)null)
				{
					return (Object)(object)InventoryGui.instance.m_currentContainer == (Object)(object)_container;
				}
				return false;
			}
		}

		internal static ItemData BoundItem => _boundItem;

		internal static Inventory GetInventory()
		{
			if (!((Object)(object)_container != (Object)null))
			{
				return null;
			}
			return _container.GetInventory();
		}

		internal static bool IsOurContainer(Container container)
		{
			if ((Object)(object)container != (Object)null && (Object)(object)_container != (Object)null)
			{
				return container == _container;
			}
			return false;
		}

		internal static bool IsBoundContainer(Container container)
		{
			return IsOurContainer(container);
		}

		internal static void Toggle(Player player, ItemData pouch)
		{
			if (!((Object)(object)player == (Object)null) && pouch != null)
			{
				if (IsOpen && _boundItem == pouch)
				{
					Close(save: true);
				}
				else
				{
					Open(player, pouch);
				}
			}
		}

		internal static void Open(Player player, ItemData pouch)
		{
			if ((Object)(object)player == (Object)null || pouch == null || (Object)(object)InventoryGui.instance == (Object)null)
			{
				return;
			}
			EnsureContainer(player, pouch);
			if ((Object)(object)_container == (Object)null)
			{
				Plugin.Log.LogError((object)"Enchanting Pouch: failed to create container.");
				return;
			}
			if (_boundItem != null && _boundItem != pouch)
			{
				SaveBound();
			}
			_suppressSave = true;
			try
			{
				Inventory inventory = _container.GetInventory();
				inventory.RemoveAll();
				LoadInto(inventory, pouch);
			}
			finally
			{
				_suppressSave = false;
			}
			_boundItem = pouch;
			InventoryGui instance = InventoryGui.instance;
			bool flag = InventoryGui.IsVisible();
			OpeningGuarded = true;
			try
			{
				if (flag)
				{
					if ((Object)(object)instance.m_currentContainer != (Object)null && instance.m_currentContainer != _container)
					{
						instance.CloseContainer();
					}
					instance.m_currentContainer = _container;
					_container.SetInUse(true);
				}
				else
				{
					instance.Show(_container, 1);
				}
			}
			finally
			{
				OpeningGuarded = false;
			}
			PouchCloseButton.SetVisible(visible: true);
		}

		internal static void Close(bool save)
		{
			if (save)
			{
				SaveBound();
			}
			InventoryGui instance = InventoryGui.instance;
			bool num = (Object)(object)instance != (Object)null && (Object)(object)instance.m_currentContainer == (Object)(object)_container;
			_boundItem = null;
			PouchCloseButton.SetVisible(visible: false);
			if (num)
			{
				instance.CloseContainer();
			}
		}

		internal static void OnContainerClosing()
		{
			SaveBound();
			_boundItem = null;
			PouchCloseButton.SetVisible(visible: false);
		}

		internal static void SaveBound()
		{
			if (_boundItem != null && !((Object)(object)_container == (Object)null) && !_suppressSave)
			{
				SaveFrom(_container.GetInventory(), _boundItem);
			}
		}

		internal static void OnInventoryChanged()
		{
			if (!_suppressSave && IsOpen)
			{
				SaveBound();
			}
		}

		private static void EnsureContainer(Player player, ItemData pouch)
		{
			//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_0095: 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_00ac: 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_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Expected O, but got Unknown
			Vector2i size = PouchProgression.GetSize(pouch?.m_quality ?? 1);
			int x = size.x;
			int y = size.y;
			if ((Object)(object)_container != (Object)null && ((object)_container).Equals((object?)null))
			{
				_container = null;
			}
			if ((Object)(object)_container != (Object)null)
			{
				Inventory inventory = _container.GetInventory();
				if (inventory == null || inventory.GetWidth() != x || inventory.GetHeight() != y)
				{
					Object.Destroy((Object)(object)((Component)_container).gameObject);
					_container = null;
				}
			}
			if ((Object)(object)_container == (Object)null)
			{
				GameObject val = new GameObject("VO_EnchantingPouch_Container");
				val.transform.SetParent(((Component)player).transform, false);
				val.transform.localPosition = Vector3.zero;
				val.SetActive(false);
				val.AddComponent<ZNetView>();
				_container = val.AddComponent<Container>();
				_container.m_name = "Enchanting Pouch";
				_container.m_width = x;
				_container.m_height = y;
				_container.m_privacy = (PrivacySetting)2;
				_container.m_checkGuardStone = false;
				_container.m_autoDestroyEmpty = false;
				val.SetActive(true);
				Inventory val2 = _container.GetInventory();
				if (val2 == null)
				{
					FieldInfo? field = typeof(Container).GetField("m_inventory", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					val2 = new Inventory("Enchanting Pouch", (Sprite)null, x, y);
					field?.SetValue(_container, val2);
				}
				Inventory obj = val2;
				obj.m_onChanged = (Action)Delegate.Remove(obj.m_onChanged, new Action(OnInventoryChanged));
				Inventory obj2 = val2;
				obj2.m_onChanged = (Action)Delegate.Combine(obj2.m_onChanged, new Action(OnInventoryChanged));
			}
			else
			{
				if ((Object)(object)((Component)_container).transform.parent != (Object)(object)((Component)player).transform)
				{
					((Component)_container).transform.SetParent(((Component)player).transform, false);
				}
				((Component)_container).transform.localPosition = Vector3.zero;
			}
		}

		internal static float GetContentsWeight(ItemData pouch)
		{
			if (pouch == null)
			{
				return 0f;
			}
			Inventory val = PeekInventory(pouch);
			float num = ((val != null) ? (val.GetTotalWeight() * 0.5f) : 0f);
			SetCachedWeight(pouch, num);
			return num;
		}

		internal static float GetCachedContentsWeight(ItemData pouch)
		{
			if (pouch?.m_customData != null && pouch.m_customData.TryGetValue("valheimoverhaul.enchantingpouch.weight", out var value) && float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
			{
				return result;
			}
			return GetContentsWeight(pouch);
		}

		private static void SetCachedWeight(ItemData pouch, float weight)
		{
			if (pouch.m_customData == null)
			{
				pouch.m_customData = new Dictionary<string, string>();
			}
			pouch.m_customData["valheimoverhaul.enchantingpouch.weight"] = weight.ToString(CultureInfo.InvariantCulture);
		}

		private static void SaveFrom(Inventory inv, ItemData pouch)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			if (inv != null && pouch != null)
			{
				if (pouch.m_customData == null)
				{
					pouch.m_customData = new Dictionary<string, string>();
				}
				ZPackage val = new ZPackage();
				inv.Save(val);
				pouch.m_customData["valheimoverhaul.enchantingpouch.inv"] = Convert.ToBase64String(val.GetArray());
				SetCachedWeight(pouch, inv.GetTotalWeight() * 0.5f);
			}
		}

		private static void LoadInto(Inventory inv, ItemData pouch)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			if (inv == null || pouch?.m_customData == null || !pouch.m_customData.TryGetValue("valheimoverhaul.enchantingpouch.inv", out var value) || string.IsNullOrEmpty(value))
			{
				return;
			}
			try
			{
				ZPackage val = new ZPackage(Convert.FromBase64String(value));
				inv.Load(val);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Failed to load pouch inventory: " + ex.Message));
			}
		}

		internal static Inventory PeekInventory(ItemData pouch)
		{
			//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_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			//IL_0031: Expected O, but got Unknown
			Vector2i size = PouchProgression.GetSize(pouch?.m_quality ?? 1);
			Inventory val = new Inventory("Enchanting Pouch Temp", (Sprite)null, size.x, size.y);
			LoadInto(val, pouch);
			return val;
		}

		internal static void CommitPeek(ItemData pouch, Inventory inv)
		{
			SaveFrom(inv, pouch);
			if (IsOpen && _boundItem == pouch && (Object)(object)_container != (Object)null)
			{
				_suppressSave = true;
				try
				{
					_container.GetInventory().RemoveAll();
					LoadInto(_container.GetInventory(), pouch);
				}
				finally
				{
					_suppressSave = false;
				}
			}
		}
	}
	internal static class PouchItem
	{
		internal static GameObject Prefab;

		internal static Recipe Recipe;

		private static readonly string[] MeshPrefabCandidates = new string[9] { "LeatherScraps", "DeerHide", "Coins", "SurtlingCore", "Wood", "Stone", "Flint", "Resin", "TrophyBoar" };

		private static bool _loggedCloneFailure;

		internal static bool IsPouch(ItemData item)
		{
			if (item?.m_shared == null)
			{
				return false;
			}
			if ((Object)(object)item.m_dropPrefab != (Object)null && Utils.GetPrefabName(item.m_dropPrefab) == "VO_EnchantingPouch")
			{
				return true;
			}
			return item.m_shared.m_name == "$item_vo_enchantingpouch";
		}

		internal static void FixDropPrefab(ItemData item)
		{
			if (item != null && IsPouch(item) && (Object)(object)Prefab != (Object)null && !((object)Prefab).Equals((object?)null))
			{
				item.m_dropPrefab = Prefab;
			}
		}

		internal static void FixDropPrefabs(Inventory inventory)
		{
			if (inventory == null)
			{
				return;
			}
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				FixDropPrefab(allItem);
			}
		}

		internal static ItemData FindInInventory(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return null;
			}
			foreach (ItemData allItem in ((Humanoid)player).GetInventory().GetAllItems())
			{
				if (IsPouch(allItem))
				{
					return allItem;
				}
			}
			return null;
		}

		internal static ItemData FindEquipped(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return null;
			}
			foreach (ItemData allItem in ((Humanoid)player).GetInventory().GetAllItems())
			{
				if (IsPouch(allItem) && allItem.m_equipped)
				{
					return allItem;
				}
			}
			return null;
		}

		internal static void ToggleEquip(Player player, ItemData pouch)
		{
			if ((Object)(object)player == (Object)null || pouch == null)
			{
				return;
			}
			if (pouch.m_equipped)
			{
				pouch.m_equipped = false;
				((Character)player).Message((MessageType)2, "Enchanting Pouch unequipped", 0, (Sprite)null);
				return;
			}
			foreach (ItemData allItem in ((Humanoid)player).GetInventory().GetAllItems())
			{
				if (IsPouch(allItem))
				{
					allItem.m_equipped = false;
				}
			}
			pouch.m_equipped = true;
			((Character)player).Message((MessageType)2, "Enchanting Pouch equipped", 0, (Sprite)null);
		}

		internal static void TryRegister(ObjectDB odb)
		{
			if ((Object)(object)odb == (Object)null)
			{
				return;
			}
			SanitizeObjectDb(odb);
			if (CreatePrefab(odb))
			{
				RegisterInLookups(odb);
				EnsureRecipe(odb);
				Localization instance = Localization.instance;
				if (instance != null)
				{
					instance.AddWord("item_vo_enchantingpouch", "Enchanting Pouch");
				}
				Localization instance2 = Localization.instance;
				if (instance2 != null)
				{
					instance2.AddWord("item_vo_enchantingpouch_desc", "EpicLoot enchanting pouch. Right-click to equip/unequip. Hover it and press E to open. Use the X on the pouch panel to close it; Esc closes inventory. While equipped, ground mats auto-store here (50% weight).");
				}
			}
		}

		private static bool CreatePrefab(ObjectDB odb)
		{
			if ((Object)(object)Prefab != (Object)null && !((object)Prefab).Equals((object?)null) && (Object)(object)odb.GetItemPrefab("VO_EnchantingPouch") == (Object)(object)Prefab)
			{
				return true;
			}
			GameObject itemPrefab = odb.GetItemPrefab("VO_EnchantingPouch");
			if ((Object)(object)itemPrefab != (Object)null)
			{
				Prefab = itemPrefab;
				ApplyStats(Prefab.GetComponent<ItemDrop>());
				PouchVisuals.ApplyWorldVisual(Prefab, odb);
				return true;
			}
			GameObject val = null;
			string[] meshPrefabCandidates = MeshPrefabCandidates;
			foreach (string text in meshPrefabCandidates)
			{
				val = odb.GetItemPrefab(text);
				if ((Object)(object)val != (Object)null)
				{
					break;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				if (!_loggedCloneFailure)
				{
					_loggedCloneFailure = true;
					Plugin.Log.LogWarning((object)"Enchanting Pouch: ObjectDB not ready to clone yet (will retry).");
				}
				return false;
			}
			_loggedCloneFailure = false;
			bool activeSelf = val.activeSelf;
			val.SetActive(false);
			Prefab = Object.Instantiate<GameObject>(val);
			val.SetActive(activeSelf);
			((Object)Prefab).name = "VO_EnchantingPouch";
			Prefab.SetActive(false);
			Object.DontDestroyOnLoad((Object)(object)Prefab);
			ItemDrop component = Prefab.GetComponent<ItemDrop>();
			if ((Object)(object)component == (Object)null)
			{
				Object.Destroy((Object)(object)Prefab);
				Prefab = null;
				return false;
			}
			EnsureUniqueShared(component);
			ApplyStats(component);
			PouchVisuals.ApplyWorldVisual(Prefab, odb);
			component.m_itemData.m_dropPrefab = Prefab;
			component.m_autoPickup = true;
			((Object)component).name = "VO_EnchantingPouch";
			Piece component2 = Prefab.GetComponent<Piece>();
			if ((Object)(object)component2 != (Object)null)
			{
				Object.Destroy((Object)(object)component2);
			}
			if (!odb.m_items.Contains(Prefab))
			{
				odb.m_items.Add(Prefab);
			}
			Plugin.Log.LogInfo((object)"Enchanting Pouch prefab registered.");
			return true;
		}

		private static void ApplyStats(ItemDrop drop)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			if (drop?.m_itemData?.m_shared != null)
			{
				SharedData shared = drop.m_itemData.m_shared;
				shared.m_name = "$item_vo_enchantingpouch";
				shared.m_description = "$item_vo_enchantingpouch_desc";
				shared.m_itemType = (ItemType)16;
				shared.m_maxStackSize = 1;
				shared.m_weight = 0.1f;
				shared.m_maxQuality = 7;
				shared.m_useDurability = false;
				shared.m_teleportable = true;
				shared.m_questItem = false;
				drop.m_itemData.m_stack = 1;
				drop.m_itemData.m_quality = 1;
				drop.m_itemData.m_equipped = false;
				PouchVisuals.ApplyIcon(shared);
			}
		}

		private static void EnsureUniqueShared(ItemDrop itemDrop)
		{
			object? obj = typeof(object).GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic)?.Invoke(itemDrop.m_itemData.m_shared, null);
			SharedData val = (SharedData)((obj is SharedData) ? obj : null);
			if (val != null)
			{
				itemDrop.m_itemData.m_shared = val;
			}
		}

		private static void RegisterInLookups(ObjectDB odb)
		{
			if (!((Object)(object)Prefab == (Object)null))
			{
				int stableHashCode = StringExtensionMethods.GetStableHashCode("VO_EnchantingPouch");
				if (odb.m_itemByHash != null)
				{
					odb.m_itemByHash[stableHashCode] = Prefab;
				}
				ItemDrop component = Prefab.GetComponent<ItemDrop>();
				if (component?.m_itemData?.m_shared != null && odb.m_itemByData != null)
				{
					odb.m_itemByData[component.m_itemData.m_shared] = Prefab;
				}
			}
		}

		private static void EnsureRecipe(ObjectDB odb)
		{
			GameObject prefab = Prefab;
			ItemDrop val = ((prefab != null) ? prefab.GetComponent<ItemDrop>() : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			string text = "Recipe_VO_EnchantingPouch";
			Recipe val2 = Recipe;
			if ((Object)(object)val2 == (Object)null)
			{
				foreach (Recipe recipe in odb.m_recipes)
				{
					if ((Object)(object)recipe != (Object)null && ((Object)recipe).name == text)
					{
						val2 = recipe;
						break;
					}
				}
			}
			if ((Object)(object)val2 == (Object)null)
			{
				val2 = ScriptableObject.CreateInstance<Recipe>();
				((Object)val2).name = text;
			}
			val2.m_item = val;
			val2.m_amount = 1;
			val2.m_enabled = true;
			val2.m_craftingStation = FindWorkbench(odb);
			val2.m_minStationLevel = 1;
			val2.m_resources = PouchProgression.GetCraftRequirements();
			if (!odb.m_recipes.Contains(val2))
			{
				odb.m_recipes.Add(val2);
			}
			Recipe = val2;
		}

		private static CraftingStation FindWorkbench(ObjectDB odb)
		{
			foreach (Recipe recipe in odb.m_recipes)
			{
				if ((Object)(object)recipe?.m_craftingStation != (Object)null && recipe.m_craftingStation.m_name.IndexOf("workbench", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return recipe.m_craftingStation;
				}
			}
			GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab("piece_workbench") : null);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return val.GetComponent<CraftingStation>();
		}

		private static void SanitizeObjectDb(ObjectDB odb)
		{
			if (odb?.m_items != null)
			{
				odb.m_items.RemoveAll((GameObject x) => (Object)(object)x == (Object)null);
			}
		}

		internal static void UnlockKnownRecipe(Player player)
		{
			if (player?.m_knownRecipes != null && !player.m_knownRecipes.Contains("$item_vo_enchantingpouch"))
			{
				player.m_knownRecipes.Add("$item_vo_enchantingpouch");
			}
		}

		internal static void EnsureAvailable(Player player, List<Recipe> available)
		{
			if ((Object)(object)player == (Object)null || available == null || (Object)(object)Recipe == (Object)null)
			{
				return;
			}
			UnlockKnownRecipe(player);
			if ((Object)(object)Recipe.m_craftingStation == (Object)null && (Object)(object)ObjectDB.instance != (Object)null)
			{
				EnsureRecipe(ObjectDB.instance);
			}
			for (int i = 0; i < available.Count; i++)
			{
				if ((Object)(object)available[i] == (Object)(object)Recipe)
				{
					return;
				}
			}
			available.Add(Recipe);
		}
	}
	[HarmonyPatch(typeof(ObjectDB), "Awake")]
	internal static class ObjectDB_Awake_Patch
	{
		private static void Postfix(ObjectDB __instance)
		{
			PouchItem.TryRegister(__instance);
		}
	}
	[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
	internal static class ObjectDB_CopyOtherDB_Patch
	{
		private static void Postfix(ObjectDB __instance)
		{
			PouchItem.TryRegister(__instance);
		}
	}
	[HarmonyPatch(typeof(ZNetScene), "Awake")]
	internal static class ZNetScene_Awake_Patch
	{
		private static void Postfix(ZNetScene __instance)
		{
			if ((Object)(object)ObjectDB.instance != (Object)null)
			{
				PouchItem.TryRegister(ObjectDB.instance);
			}
			if ((Object)(object)PouchItem.Prefab != (Object)null && !__instance.m_namedPrefabs.ContainsKey(StringExtensionMethods.GetStableHashCode("VO_EnchantingPouch")))
			{
				__instance.m_prefabs.Add(PouchItem.Prefab);
				__instance.m_namedPrefabs[StringExtensionMethods.GetStableHashCode("VO_EnchantingPouch")] = PouchItem.Prefab;
			}
		}
	}
	[HarmonyPatch(typeof(Inventory), "Save")]
	internal static class Inventory_Save_Patch
	{
		private static void Prefix(Inventory __instance)
		{
			PouchItem.FixDropPrefabs(__instance);
		}
	}
	[HarmonyPatch(typeof(Inventory), "Load")]
	internal static class Inventory_Load_Patch
	{
		private static void Prefix()
		{
			if ((Object)(object)ObjectDB.instance != (Object)null)
			{
				PouchItem.TryRegister(ObjectDB.instance);
			}
		}

		private static void Postfix(Inventory __instance)
		{
			PouchItem.FixDropPrefabs(__instance);
		}
	}
	internal static class PouchProgression
	{
		internal const int MaxQuality = 7;

		internal const float WeightFactor = 0.5f;

		internal static Vector2i GetSize(int quality)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			return new Vector2i(Mathf.Clamp(quality, 1, 7) + 1, 4);
		}

		internal static Requirement[] GetCraftRequirements()
		{
			return Build(("DustMagic", 5), ("ReagentMagic", 5), ("EssenceMagic", 5), ("ShardMagic", 1));
		}

		internal static Requirement[] GetRequirementsForQualityLevel(int qualityLevel)
		{
			if (qualityLevel <= 1)
			{
				return GetCraftRequirements();
			}
			return Mathf.Clamp(qualityLevel, 2, 7) switch
			{
				2 => Build(("DustRare", 5), ("ReagentRare", 5), ("EssenceRare", 5), ("ShardRare", 1)), 
				3 => Build(("DustRare", 10), ("ReagentRare", 10), ("ShardRare", 5), ("RunestoneRare", 1)), 
				4 => Build(("DustEpic", 5), ("ReagentEpic", 5), ("EssenceEpic", 5), ("ShardEpic", 1)), 
				5 => Build(("DustEpic", 10), ("ReagentEpic", 10), ("ShardEpic", 5), ("RunestoneEpic", 1)), 
				6 => Build(("DustLegendary", 10), ("ReagentLegendary", 10), ("ShardLegendary", 5), ("RunestoneLegendary", 1)), 
				_ => Build(("DustMythic", 10), ("ReagentMythic", 10), ("ShardMythic", 5), ("RunestoneMythic", 1)), 
			};
		}

		internal static void SyncRecipeResources(int qualityLevel)
		{
			if (!((Object)(object)PouchItem.Recipe == (Object)null))
			{
				PouchItem.Recipe.m_resources = GetRequirementsForQualityLevel(qualityLevel);
				PouchItem.Recipe.m_minStationLevel = 1;
			}
		}

		private static Requirement[] Build(params (string prefab, int amount)[] entries)
		{
			//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_008a: 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)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Expected O, but got Unknown
			List<Requirement> list = new List<Requirement>(entries.Length);
			ObjectDB instance = ObjectDB.instance;
			for (int i = 0; i < entries.Length; i++)
			{
				(string prefab, int amount) tuple = entries[i];
				string item = tuple.prefab;
				int item2 = tuple.amount;
				GameObject val = (((Object)(object)instance != (Object)null) ? instance.GetItemPrefab(item) : null);
				ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null);
				if ((Object)(object)val2 == (Object)null)
				{
					Plugin.Log.LogWarning((object)("Missing upgrade/craft ingredient prefab: " + item));
					continue;
				}
				list.Add(new Requirement
				{
					m_resItem = val2,
					m_amount = item2,
					m_amountPerLevel = 0,
					m_recover = true
				});
			}
			return list.ToArray();
		}

		internal static bool IsPouchRequirement(Requirement requirement)
		{
			if (requirement == null || PouchItem.Recipe?.m_resources == null)
			{
				return false;
			}
			Requirement[] resources = PouchItem.Recipe.m_resources;
			for (int i = 0; i < resources.Length; i++)
			{
				if (resources[i] == requirement)
				{
					return true;
				}
			}
			return false;
		}
	}
	internal static class PouchVisuals
	{
		private static Sprite _icon;

		private static MethodInfo _loadImage;

		private static readonly Color MagicBlue = new Color(0.25f, 0.55f, 1f, 1f);

		private static readonly string[] PreferredDonors = new string[5] { "DustMagic", "EssenceMagic", "ShardMagic", "ReagentMagic", "RunestoneMagic" };

		private static readonly string[] FallbackMeshDonors = new string[5] { "Softtissue", "GreydwarfEye", "SurtlingCore", "CrystalFrag", "Ruby" };

		internal static void ApplyIcon(SharedData shared)
		{
			Sprite icon = GetIcon();
			if (shared != null && !((Object)(object)icon == (Object)null))
			{
				shared.m_icons = (Sprite[])(object)new Sprite[1] { icon };
			}
		}

		internal static void ApplyWorldVisual(GameObject pouch, ObjectDB odb)
		{
			if ((Object)(object)pouch == (Object)null)
			{
				return;
			}
			Transform val = pouch.transform.Find("VO_PouchGlow");
			if ((Object)(object)val != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)val).gameObject);
			}
			Renderer[] componentsInChildren = pouch.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val2 in componentsInChildren)
			{
				if ((Object)(object)val2 != (Object)null)
				{
					val2.enabled = false;
				}
			}
			GameObject val3 = FindDonor(odb);
			GameObject val4 = (((Object)(object)val3 != (Object)null) ? CloneDonorVisual(val3, pouch.transform) : null);
			if ((Object)(object)val4 == (Object)null)
			{
				val4 = CreateFallbackOrb(pouch.transform, odb);
			}
			if ((Object)(object)val4 != (Object)null)
			{
				EnsureBlueLight(val4);
			}
		}

		private static GameObject FindDonor(ObjectDB odb)
		{
			if (odb?.m_items == null)
			{
				return null;
			}
			string[] preferredDonors = PreferredDonors;
			foreach (string text in preferredDonors)
			{
				GameObject itemPrefab = odb.GetItemPrefab(text);
				if ((Object)(object)itemPrefab != (Object)null)
				{
					return itemPrefab;
				}
			}
			foreach (GameObject item in odb.m_items)
			{
				if (!((Object)(object)item == (Object)null))
				{
					string prefabName = Utils.GetPrefabName(item);
					if (prefabName.IndexOf("_Unidentified", StringComparison.OrdinalIgnoreCase) >= 0 || prefabName.IndexOf("Unidentified", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return item;
					}
				}
			}
			preferredDonors = FallbackMeshDonors;
			foreach (string text2 in preferredDonors)
			{
				GameObject itemPrefab2 = odb.GetItemPrefab(text2);
				if ((Object)(object)itemPrefab2 != (Object)null)
				{
					return itemPrefab2;
				}
			}
			return null;
		}

		private static GameObject CloneDonorVisual(GameObject donor, Transform parent)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: 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_00d2: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: 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)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			bool activeSelf = donor.activeSelf;
			donor.SetActive(false);
			GameObject val = Object.Instantiate<GameObject>(donor, parent);
			donor.SetActive(activeSelf);
			((Object)val).name = "VO_PouchGlow";
			val.transform.localPosition = Vector3.zero;
			val.transform.localRotation = Quaternion.identity;
			val.transform.localScale = Vector3.one;
			val.SetActive(false);
			StripGameplayComponents(val);
			Bounds val2 = default(Bounds);
			bool flag = false;
			Renderer[] componentsInChildren = val.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val3 in componentsInChildren)
			{
				if (!((Object)(object)val3 == (Object)null))
				{
					val3.enabled = true;
					if (!flag)
					{
						val2 = val3.bounds;
						flag = true;
					}
					else
					{
						((Bounds)(ref val2)).Encapsulate(val3.bounds);
					}
				}
			}
			if (flag)
			{
				float num = Mathf.Max(((Bounds)(ref val2)).size.x, Mathf.Max(((Bounds)(ref val2)).size.y, ((Bounds)(ref val2)).size.z));
				if (num > 0.6f)
				{
					float num2 = 0.35f / num;
					val.transform.localScale = Vector3.one * num2;
				}
			}
			TintRenderersBlue(val);
			val.SetActive(true);
			return val;
		}

		private static void StripGameplayComponents(GameObject root)
		{
			DestroyAllOfType(root, "ZNetView");
			DestroyAllOfType(root, "ZSyncTransform");
			DestroyAllOfType(root, "ItemDrop");
			DestroyAllOfType(root, "Rigidbody");
			DestroyAllOfType(root, "Floating");
			DestroyAllOfType(root, "WearNTear");
			DestroyAllOfType(root, "Piece");
			DestroyAllOfType(root, "CraftingStation");
			DestroyAllOfType(root, "Container");
			DestroyAllOfType(root, "Character");
			DestroyAllOfType(root, "Humanoid");
			DestroyAllOfType(root, "MonsterAI");
			DestroyAllOfType(root, "AnimalAI");
			Collider[] componentsInChildren = root.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
		}

		private static void DestroyAllOfType(GameObject root, string typeName)
		{
			Component[] componentsInChildren = root.GetComponentsInChildren<Component>(true);
			foreach (Component val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && ((object)val).GetType().Name == typeName)
				{
					Object.DestroyImmediate((Object)(object)val);
				}
			}
		}

		private static GameObject CreateFallbackOrb(Transform parent, ObjectDB odb)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Expected O, but got Unknown
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("VO_PouchGlow");
			val.transform.SetParent(parent, false);
			val.transform.localPosition = new Vector3(0f, 0.05f, 0f);
			val.transform.localScale = Vector3.one * 0.18f;
			GameObject val2 = null;
			string[] fallbackMeshDonors = FallbackMeshDonors;
			foreach (string text in fallbackMeshDonors)
			{
				val2 = (((Object)(object)odb != (Object)null) ? odb.GetItemPrefab(text) : null);
				if ((Object)(object)val2 != (Object)null)
				{
					break;
				}
			}
			if ((Object)(object)val2 != (Object)null)
			{
				MeshFilter componentInChildren = val2.GetComponentInChildren<MeshFilter>(true);
				MeshRenderer componentInChildren2 = val2.GetComponentInChildren<MeshRenderer>(true);
				if ((Object)(object)componentInChildren != (Object)null && (Object)(object)componentInChildren2 != (Object)null)
				{
					GameObject val3 = new GameObject("Mesh");
					val3.transform.SetParent(val.transform, false);
					val3.AddComponent<MeshFilter>().sharedMesh = componentInChildren.sharedMesh;
					MeshRenderer val4 = val3.AddComponent<MeshRenderer>();
					if (((Renderer)componentInChildren2).sharedMaterials != null && ((Renderer)componentInChildren2).sharedMaterials.Length != 0)
					{
						Material[] array = (Material[])(object)new Material[((Renderer)componentInChildren2).sharedMaterials.Length];
						for (int j = 0; j < array.Length; j++)
						{
							array[j] = (((Object)(object)((Renderer)componentInChildren2).sharedMaterials[j] != (Object)null) ? new Material(((Renderer)componentInChildren2).sharedMaterials[j]) : ((Material)null));
						}
						((Renderer)val4).sharedMaterials = array;
					}
					TintRenderersBlue(val3);
					return val;
				}
			}
			GameObject obj = GameObject.CreatePrimitive((PrimitiveType)0);
			((Object)obj).name = "Orb";
			obj.transform.SetParent(val.transform, false);
			Object.DestroyImmediate((Object)(object)obj.GetComponent<Collider>());
			TintRenderersBlue(obj);
			return val;
		}

		private static void TintRenderersBlue(GameObject root)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				Material[] materials = val.materials;
				foreach (Material val2 in materials)
				{
					if (!((Object)(object)val2 == (Object)null))
					{
						if (val2.HasProperty("_Color"))
						{
							val2.color = Color.Lerp(val2.color, MagicBlue, 0.55f);
						}
						if (val2.HasProperty("_EmissionColor"))
						{
							val2.EnableKeyword("_EMISSION");
							val2.SetColor("_EmissionColor", MagicBlue * 1.4f);
						}
					}
				}
				val.materials = materials;
			}
		}

		private static void EnsureBlueLight(GameObject glowRoot)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			Light val = glowRoot.GetComponentInChildren<Light>(true);
			if ((Object)(object)val == (Object)null)
			{
				GameObject val2 = new GameObject("MagicLight");
				val2.transform.SetParent(glowRoot.transform, false);
				val = val2.AddComponent<Light>();
			}
			val.type = (LightType)2;
			val.color = MagicBlue;
			val.range = 2.5f;
			val.intensity = 1.35f;
			val.shadows = (LightShadows)0;
			((Behaviour)val).enabled = true;
		}

		internal static Sprite GetIcon()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_icon != (Object)null)
			{
				return _icon;
			}
			byte[] array = LoadEmbeddedPng();
			if (array == null || array.Length == 0)
			{
				Plugin.Log.LogWarning((object)"Enchanting Pouch icon resource missing.");
				return null;
			}
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			if (!TryLoadImage(val, array))
			{
				Plugin.Log.LogWarning((object)"Failed to LoadImage Enchanting Pouch icon.");
				return null;
			}
			((Texture)val).wrapMode = (TextureWrapMode)1;
			((Texture)val).filterMode = (FilterMode)1;
			((Object)val).name = "VO_EnchantingPouch_Icon";
			_icon = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
			((Object)_icon).name = "VO_EnchantingPouch_Icon";
			return _icon;
		}

		private static bool TryLoadImage(Texture2D tex, byte[] bytes)
		{
			if (_loadImage == null)
			{
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				for (int i = 0; i < assemblies.Length; i++)
				{
					Type type = assemblies[i].GetType("UnityEngine.ImageConversion");
					if (!(type == null))
					{
						_loadImage = type.GetMethod("LoadImage", BindingFlags.Static | BindingFlags.Public, null, new Type[2]
						{
							typeof(Texture2D),
							typeof(byte[])
						}, null);
						if (_loadImage != null)
						{
							break;
						}
					}
				}
			}
			if (_loadImage == null)
			{
				return false;
			}
			object obj = _loadImage.Invoke(null, new object[2] { tex, bytes });
			bool flag = default(bool);
			int num;
			if (obj is bool)
			{
				flag = (bool)obj;
				num = 1;
			}
			else
			{
				num = 0;
			}
			return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
		}

		private static byte[] LoadEmbeddedPng()
		{
			Assembly assembly = typeof(PouchVisuals).Assembly;
			string text = null;
			string[] manifestResourceNames = assembly.GetManifestResourceNames();
			foreach (string text2 in manifestResourceNames)
			{
				if (text2.EndsWith("enchanting_pouch_icon.png", StringComparison.OrdinalIgnoreCase))
				{
					text = text2;
					break;
				}
			}
			if (text == null)
			{
				return null;
			}
			using Stream stream = assembly.GetManifestResourceStream(text);
			if (stream == null)
			{
				return null;
			}
			using MemoryStream memoryStream = new MemoryStream();
			stream.CopyTo(memoryStream);
			return memoryStream.ToArray();
		}
	}
	internal static class ProgressionPatches
	{
		[HarmonyPatch(typeof(InventoryGui), "UpdateCraftingPanel")]
		private static class InventoryGui_UpdateCraftingPanel_Patch
		{
			private static void Prefix(InventoryGui __instance)
			{
				SyncFromGui(__instance);
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "SetupRequirementList")]
		private static class InventoryGui_SetupRequirementList_Patch
		{
			private static void Prefix(InventoryGui __instance)
			{
				SyncFromGui(__instance);
			}
		}

		[HarmonyPatch(typeof(Player), "HaveRequirementItems")]
		private static class Player_HaveRequirementItems_Patch
		{
			private static bool Prefix(Player __instance, Recipe piece, bool discover, int qualityLevel, int amount, ref bool __result)
			{
				if ((Object)(object)piece == (Object)null || (Object)(object)piece != (Object)(object)PouchItem.Recipe)
				{
					return true;
				}
				Requirement[] requirementsForQualityLevel = PouchProgression.GetRequirementsForQualityLevel(qualityLevel);
				PouchItem.Recipe.m_resources = requirementsForQualityLevel;
				__result = HaveAll(__instance, requirementsForQualityLevel, discover, amount);
				return false;
			}
		}

		[HarmonyPatch(typeof(Player), "ConsumeResources")]
		private static class Player_ConsumeResources_Patch
		{
			private static bool Prefix(Player __instance, Requirement[] requirements, int qualityLevel, int itemQuality, int multiplier)
			{
				if ((Object)(object)PouchItem.Recipe == (Object)null || requirements == null)
				{
					return true;
				}
				if (!IsLikelyPouchRequirementList(requirements))
				{
					return true;
				}
				Requirement[] requirementsForQualityLevel = PouchProgression.GetRequirementsForQualityLevel(qualityLevel);
				ConsumeAll(__instance, requirementsForQualityLevel, Mathf.Max(1, multiplier));
				return false;
			}
		}

		private static readonly FieldInfo SelectedRecipeField = AccessTools.Field(typeof(InventoryGui), "m_selectedRecipe") ?? AccessTools.Field(typeof(InventoryGui), "m_craftRecipe");

		private static readonly FieldInfo CraftUpgradeItemField = AccessTools.Field(typeof(InventoryGui), "m_craftUpgradeItem") ?? AccessTools.Field(typeof(InventoryGui), "craftUpgradeItem");

		private static void SyncFromGui(InventoryGui gui)
		{
			if (!((Object)(object)gui == (Object)null) && !((Object)(object)PouchItem.Recipe == (Object)null) && (!((Object)/*isinst with value type is only supported in some contexts*/ != (Object)(object)PouchItem.Recipe) || IsOurRecipeSelected(gui)))
			{
				object? obj = CraftUpgradeItemField?.GetValue(gui);
				ItemData val = (ItemData)((obj is ItemData) ? obj : null);
				int qualityLevel = 1;
				if (val != null && PouchItem.IsPouch(val))
				{
					qualityLevel = val.m_quality + 1;
				}
				PouchProgression.SyncRecipeResources(qualityLevel);
			}
		}

		private static bool IsOurRecipeSelected(InventoryGui gui)
		{
			if (SelectedRecipeField == null)
			{
				return false;
			}
			object value = SelectedRecipeField.GetValue(gui);
			if (value == null)
			{
				return false;
			}
			Recipe val = (Recipe)((value is Recipe) ? value : null);
			if (val != null)
			{
				return (Object)(object)val == (Object)(object)PouchItem.Recipe;
			}
			object? obj = value.GetType().GetProperty("Key")?.GetValue(value);
			Recipe val2 = (Recipe)((obj is Recipe) ? obj : null);
			if (val2 != null)
			{
				return (Object)(object)val2 == (Object)(object)PouchItem.Recipe;
			}
			object? obj2 = (value.GetType().GetField("m_recipe") ?? value.GetType().GetField("Recipe"))?.GetValue(value);
			Recipe val3 = (Recipe)((obj2 is Recipe) ? obj2 : null);
			if (val3 != null)
			{
				return (Object)(object)val3 == (Object)(object)PouchItem.Recipe;
			}
			return false;
		}

		private static bool IsLikelyPouchRequirementList(Requirement[] requirements)
		{
			if (requirements.Length == 0)
			{
				return false;
			}
			for (int i = 0; i < requirements.Length; i++)
			{
				ItemDrop val = requirements[i]?.m_resItem;
				string text = (((Object)(object)val != (Object)null) ? ((Object)val).name : null);
				if (!string.IsNullOrEmpty(text) && (text.StartsWith("Dust") || text.StartsWith("Essence") || text.StartsWith("Reagent") || text.StartsWith("Shard") || text.StartsWith("Runestone")))
				{
					return true;
				}
			}
			return false;
		}

		private static bool HaveAll(Player player, Requirement[] reqs, bool discover, int amountMul)
		{
			if (reqs == null || reqs.Length == 0)
			{
				return false;
			}
			int num = Mathf.Max(1, amountMul);
			Inventory inventory = ((Humanoid)player).GetInventory();
			bool result = false;
			foreach (Requirement val in reqs)
			{
				if (!((Object)(object)val?.m_resItem == (Object)null) && val.m_amount > 0)
				{
					result = true;
					int num2 = val.m_amount * num;
					int num3 = inventory.CountItems(val.m_resItem.m_itemData.m_shared.m_name, -1, true);
					if (discover)
					{
						player.AddKnownItem(val.m_resItem.m_itemData);
					}
					if (num3 < num2)
					{
						return false;
					}
				}
			}
			return result;
		}

		private static void ConsumeAll(Player player, Requirement[] reqs, int multiplier)
		{
			Inventory inventory = ((Humanoid)player).GetInventory();
			foreach (Requirement val in reqs)
			{
				if (!((Object)(object)val?.m_resItem == (Object)null) && val.m_amount > 0)
				{
					inventory.RemoveItem(val.m_resItem.m_itemData.m_shared.m_name, val.m_amount * multiplier, -1, true);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Inventory), "GetTotalWeight")]
	internal static class Inventory_GetTotalWeight_Patch
	{
		private static void Postfix(Inventory __instance, ref float __result)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || __instance != ((Humanoid)localPlayer).GetInventory())
			{
				return;
			}
			List<ItemData> allItems = __instance.GetAllItems();
			for (int i = 0; i < allItems.Count; i++)
			{
				ItemData val = allItems[i];
				if (PouchItem.IsPouch(val))
				{
					__result += PouchContainer.GetCachedContentsWeight(val);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Requirement), "GetAmount")]
	internal static class Piece_Requirement_GetAmount_Patch
	{
		private static void Postfix(Requirement __instance, int qualityLevel, ref int __result)
		{
			if (PouchProgression.IsPouchRequirement(__instance))
			{
				__result = Mathf.Max(0, __instance.m_amount);
			}
		}
	}
	[HarmonyPatch(typeof(Recipe), "GetRequiredStationLevel")]
	internal static class Recipe_GetRequiredStationLevel_Patch
	{
		private static void Postfix(Recipe __instance, int quality, ref int __result)
		{
			if ((Object)(object)__instance == (Object)(object)PouchItem.Recipe)
			{
				__result = 1;
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}