Decompiled source of WiresRecycler v1.0.1

WiresRecycler.dll

Decompiled 4 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
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: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("WiresRecycler")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("WiresRecycler")]
[assembly: AssemblyTitle("WiresRecycler")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace WiresRecycler
{
	[BepInPlugin("wire.valheim.recycler", "Wire's Recycler", "1.0.1")]
	[BepInProcess("valheim.exe")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Guid = "wire.valheim.recycler";

		public const string Name = "Wire's Recycler";

		public const string Version = "1.0.1";

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			_harmony = new Harmony("wire.valheim.recycler");
			_harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Wire's Recycler 1.0.1 loaded.");
		}

		private void OnDestroy()
		{
			RecyclerUi.Shutdown();
			CraftXpDebt.Reset();
			if (_harmony != null)
			{
				_harmony.UnpatchSelf();
			}
		}
	}
	internal sealed class RecycleOutput
	{
		internal ItemDrop Item;

		internal int BaseMin;

		internal int BaseMax;

		internal float BaseHighChance;

		internal int UpgradeMin;

		internal int UpgradeMax;

		internal float UpgradeHighChance;

		internal int MinAmount => BaseMin + UpgradeMin;

		internal int MaxAmount => BaseMax + UpgradeMax;

		internal int Roll()
		{
			int num = BaseMin;
			if (BaseMax > BaseMin && Random.value < BaseHighChance)
			{
				num = BaseMax;
			}
			num += UpgradeMin;
			if (UpgradeMax > UpgradeMin && Random.value < UpgradeHighChance)
			{
				num += UpgradeMax - UpgradeMin;
			}
			return num;
		}
	}
	internal sealed class RecyclePlan
	{
		internal Recipe Recipe;

		internal ItemData Item;

		internal int ConsumeAmount;

		internal int RequiredLevel;

		internal bool SpecialReverse;

		internal readonly List<RecycleOutput> Outputs = new List<RecycleOutput>();
	}
	internal static class GuiAccess
	{
		internal static readonly FieldInfo AvailableRecipes = AccessTools.Field(typeof(InventoryGui), "m_availableRecipes");

		internal static readonly FieldInfo SelectedRecipe = AccessTools.Field(typeof(InventoryGui), "m_selectedRecipe");

		internal static readonly FieldInfo RecipeListBaseSize = AccessTools.Field(typeof(InventoryGui), "m_recipeListBaseSize");

		internal static readonly FieldInfo MinStationBaseColor = AccessTools.Field(typeof(InventoryGui), "m_minStationLevelBasecolor");

		internal static readonly FieldInfo CraftTimer = AccessTools.Field(typeof(InventoryGui), "m_craftTimer");

		internal static readonly FieldInfo MultiCrafting = AccessTools.Field(typeof(InventoryGui), "m_multiCrafting");

		internal static readonly MethodInfo AddRecipeToList = AccessTools.Method(typeof(InventoryGui), "AddRecipeToList", new Type[4]
		{
			typeof(Player),
			typeof(Recipe),
			typeof(ItemData),
			typeof(bool)
		}, (Type[])null);

		internal static readonly MethodInfo UpdateCraftingPanel = AccessTools.Method(typeof(InventoryGui), "UpdateCraftingPanel", new Type[1] { typeof(bool) }, (Type[])null);

		private static readonly Type PairType = AccessTools.Inner(typeof(InventoryGui), "RecipeDataPair");

		private static readonly PropertyInfo PairRecipe = ((PairType != null) ? PairType.GetProperty("Recipe", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) : null);

		private static readonly PropertyInfo PairItem = ((PairType != null) ? PairType.GetProperty("ItemData", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) : null);

		private static readonly PropertyInfo PairElement = ((PairType != null) ? PairType.GetProperty("InterfaceElement", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) : null);

		internal static IList GetAvailable(InventoryGui gui)
		{
			if (!(AvailableRecipes != null))
			{
				return null;
			}
			return AvailableRecipes.GetValue(gui) as IList;
		}

		internal static void GetSelected(InventoryGui gui, out Recipe recipe, out ItemData item)
		{
			recipe = null;
			item = null;
			if (!(SelectedRecipe == null) && !(PairRecipe == null) && !(PairItem == null))
			{
				object value = SelectedRecipe.GetValue(gui);
				if (value != null)
				{
					object? value2 = PairRecipe.GetValue(value, null);
					recipe = (Recipe)((value2 is Recipe) ? value2 : null);
					object? value3 = PairItem.GetValue(value, null);
					item = (ItemData)((value3 is ItemData) ? value3 : null);
				}
			}
		}

		internal static GameObject GetPairElement(object pair)
		{
			if (pair == null || !(PairElement != null))
			{
				return null;
			}
			object? value = PairElement.GetValue(pair, null);
			return (GameObject)((value is GameObject) ? value : null);
		}

		internal static void Refresh(InventoryGui gui, bool focus)
		{
			if (UpdateCraftingPanel != null)
			{
				UpdateCraftingPanel.Invoke(gui, new object[1] { focus });
			}
		}
	}
	internal static class RecyclerUi
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__SelectRecycleTab;
		}

		private static readonly HashSet<string> GaldrReversePrefabs = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "Bronze", "CeramicPlate" };

		private static readonly List<RecyclePlan> Plans = new List<RecyclePlan>();

		private static readonly List<ItemData> TempItems = new List<ItemData>();

		private static InventoryGui _gui;

		private static GameObject _tabObject;

		private static Button _tabButton;

		private static ItemData _armedItem;

		private static Recipe _armedRecipe;

		internal static bool Active { get; private set; }

		internal static void Initialize(InventoryGui gui)
		{
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Expected O, but got Unknown
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Expected O, but got Unknown
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			Shutdown();
			_gui = gui;
			if ((Object)(object)gui == (Object)null || (Object)(object)gui.m_tabUpgrade == (Object)null)
			{
				return;
			}
			_tabObject = Object.Instantiate<GameObject>(((Component)gui.m_tabUpgrade).gameObject, ((Component)gui.m_tabUpgrade).transform.parent, false);
			((Object)_tabObject).name = "WireRecycleTab";
			_tabButton = _tabObject.GetComponent<Button>();
			if ((Object)(object)_tabButton == (Object)null)
			{
				Object.Destroy((Object)(object)_tabObject);
				_tabObject = null;
				return;
			}
			((UnityEventBase)_tabButton.onClick).RemoveAllListeners();
			ButtonClickedEvent onClick = _tabButton.onClick;
			object obj = <>O.<0>__SelectRecycleTab;
			if (obj == null)
			{
				UnityAction val = SelectRecycleTab;
				<>O.<0>__SelectRecycleTab = val;
				obj = (object)val;
			}
			((UnityEvent)onClick).AddListener((UnityAction)obj);
			TMP_Text componentInChildren = _tabObject.GetComponentInChildren<TMP_Text>(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				componentInChildren.text = "RECYCLE";
			}
			Transform transform = _tabObject.transform;
			RectTransform val2 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			Transform transform2 = ((Component)gui.m_tabUpgrade).transform;
			RectTransform val3 = (RectTransform)(object)((transform2 is RectTransform) ? transform2 : null);
			if ((Object)(object)val2 != (Object)null && (Object)(object)val3 != (Object)null)
			{
				Rect rect = val2.rect;
				float width = ((Rect)(ref rect)).width;
				float num = ((Transform)val3).localPosition.x;
				foreach (Transform item in ((Component)gui.m_tabUpgrade).transform.parent)
				{
					Transform val4 = item;
					if (!((Object)(object)val4 == (Object)(object)_tabObject.transform) && ((Component)val4).gameObject.activeSelf && !((Object)(object)((Component)val4).GetComponent<Button>() == (Object)null))
					{
						num = Mathf.Max(num, val4.localPosition.x);
					}
				}
				Vector3 localPosition = ((Transform)val3).localPosition;
				localPosition.x = num + width + 10f;
				((Transform)val2).localPosition = localPosition;
			}
			((Selectable)_tabButton).interactable = true;
			_tabObject.SetActive(false);
		}

		internal static void Shutdown()
		{
			Active = false;
			ClearArmed();
			Plans.Clear();
			if ((Object)(object)_tabObject != (Object)null)
			{
				Object.Destroy((Object)(object)_tabObject);
			}
			_tabObject = null;
			_tabButton = null;
			_gui = null;
		}

		internal static void LeaveRecycleTab()
		{
			if (Active)
			{
				Active = false;
				ClearArmed();
				if ((Object)(object)_tabButton != (Object)null)
				{
					((Selectable)_tabButton).interactable = true;
				}
			}
		}

		internal static void SyncTabVisibility(InventoryGui gui)
		{
			if (!((Object)(object)_tabObject == (Object)null) && !((Object)(object)gui == (Object)null))
			{
				Player localPlayer = Player.m_localPlayer;
				CraftingStation val = (((Object)(object)localPlayer != (Object)null) ? localPlayer.GetCurrentCraftingStation() : null);
				bool flag = (Object)(object)val != (Object)null && !val.m_upgrader && ((Component)gui.m_tabUpgrade).gameObject.activeSelf && StationSupportsRecycler(val);
				_tabObject.SetActive(flag);
				if (!flag && Active)
				{
					LeaveRecycleTab();
				}
			}
		}

		private static void SelectRecycleTab()
		{
			if ((Object)(object)_gui == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			CraftingStation currentCraftingStation = Player.m_localPlayer.GetCurrentCraftingStation();
			if (!((Object)(object)currentCraftingStation == (Object)null) && !currentCraftingStation.m_upgrader && StationSupportsRecycler(currentCraftingStation))
			{
				Active = true;
				ClearArmed();
				((Selectable)_gui.m_tabCraft).interactable = true;
				((Selectable)_gui.m_tabUpgrade).interactable = true;
				if ((Object)(object)_tabButton != (Object)null)
				{
					((Selectable)_tabButton).interactable = false;
				}
				GuiAccess.Refresh(_gui, focus: false);
			}
		}

		internal static void RebuildRecipeList(InventoryGui gui, List<Recipe> vanillaRecipes)
		{
			if (!Active || (Object)(object)gui == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			IList available = GuiAccess.GetAvailable(gui);
			if (available == null || GuiAccess.AddRecipeToList == null)
			{
				return;
			}
			for (int i = 0; i < available.Count; i++)
			{
				GameObject pairElement = GuiAccess.GetPairElement(available[i]);
				if ((Object)(object)pairElement != (Object)null)
				{
					Object.Destroy((Object)(object)pairElement);
				}
			}
			available.Clear();
			Plans.Clear();
			Player localPlayer = Player.m_localPlayer;
			CraftingStation currentCraftingStation = localPlayer.GetCurrentCraftingStation();
			if ((Object)(object)currentCraftingStation == (Object)null)
			{
				return;
			}
			List<Recipe> list = new List<Recipe>();
			if (vanillaRecipes != null)
			{
				for (int j = 0; j < vanillaRecipes.Count; j++)
				{
					Recipe val = vanillaRecipes[j];
					if ((Object)(object)val != (Object)null && !list.Contains(val))
					{
						list.Add(val);
					}
				}
			}
			AddSpecialReverseRecipes(localPlayer, currentCraftingStation, list);
			Inventory inventory = ((Humanoid)localPlayer).GetInventory();
			for (int k = 0; k < list.Count; k++)
			{
				Recipe val2 = list[k];
				bool flag = IsSpecialReverse(currentCraftingStation, val2);
				if (!RecipeCanAppear(val2, currentCraftingStation, flag))
				{
					continue;
				}
				TempItems.Clear();
				inventory.GetAllItems(val2.m_item.m_itemData.m_shared.m_name, TempItems);
				for (int l = 0; l < TempItems.Count; l++)
				{
					ItemData val3 = TempItems[l];
					int consumeAmount = GetConsumeAmount(val3, val2);
					if (consumeAmount <= 0)
					{
						continue;
					}
					RecyclePlan recyclePlan = new RecyclePlan
					{
						Recipe = val2,
						Item = val3,
						ConsumeAmount = consumeAmount,
						RequiredLevel = (flag ? 1 : Mathf.Max(1, val2.GetRequiredStationLevel(1))),
						SpecialReverse = flag
					};
					BuildOutputs(gui, recyclePlan);
					if (recyclePlan.Outputs.Count != 0)
					{
						bool flag2 = IsStationUsableForPlan(localPlayer, currentCraftingStation, recyclePlan);
						GuiAccess.AddRecipeToList.Invoke(gui, new object[4] { localPlayer, val2, val3, flag2 });
						GameObject pairElement2 = GuiAccess.GetPairElement((available.Count > 0) ? available[available.Count - 1] : null);
						if ((Object)(object)pairElement2 != (Object)null)
						{
							PolishListElement(pairElement2, recyclePlan);
						}
						Plans.Add(recyclePlan);
					}
				}
			}
			float num = 0f;
			if (GuiAccess.RecipeListBaseSize != null)
			{
				object value = GuiAccess.RecipeListBaseSize.GetValue(gui);
				if (value is float)
				{
					num = (float)value;
				}
			}
			float num2 = Mathf.Max(num, (float)available.Count * gui.m_recipeListSpace);
			gui.m_recipeListRoot.SetSizeWithCurrentAnchors((Axis)1, num2);
		}

		private static void PolishListElement(GameObject element, RecyclePlan plan)
		{
			if ((Object)(object)element == (Object)null || plan == null || plan.Item == null)
			{
				return;
			}
			Transform val = element.transform.Find("icon");
			if ((Object)(object)val != (Object)null)
			{
				Image component = ((Component)val).GetComponent<Image>();
				if ((Object)(object)component != (Object)null)
				{
					component.sprite = plan.Item.GetIcon();
				}
			}
			Transform val2 = element.transform.Find("name");
			if ((Object)(object)val2 != (Object)null)
			{
				TMP_Text component2 = ((Component)val2).GetComponent<TMP_Text>();
				if ((Object)(object)component2 != (Object)null)
				{
					string text = Localization.instance.Localize(plan.Item.m_shared.m_name);
					if (plan.Item.m_quality > 1)
					{
						text = text + " Q" + plan.Item.m_quality;
					}
					if (plan.ConsumeAmount > 1)
					{
						text = text + " x" + plan.ConsumeAmount;
					}
					component2.text = text;
				}
			}
			Transform val3 = element.transform.Find("QualityLevel");
			if ((Object)(object)val3 != (Object)null)
			{
				((Component)val3).gameObject.SetActive(plan.Item.m_quality > 1);
			}
		}

		internal static void OverrideRecipeDetails(InventoryGui gui, Player player)
		{
			if (!Active || (Object)(object)gui == (Object)null || (Object)(object)player == (Object)null)
			{
				return;
			}
			GuiAccess.GetSelected(gui, out var recipe, out var item);
			RecyclePlan recyclePlan = FindPlan(recipe, item);
			if (recyclePlan == null)
			{
				ClearArmed();
				return;
			}
			if (_armedItem != null && (_armedItem != item || (Object)(object)_armedRecipe != (Object)(object)recipe))
			{
				ClearArmed();
			}
			((Behaviour)gui.m_recipeIcon).enabled = true;
			((Behaviour)gui.m_recipeName).enabled = true;
			((Behaviour)gui.m_recipeDecription).enabled = true;
			((Component)gui.m_qualityPanel).gameObject.SetActive(false);
			((Component)gui.m_variantButton).gameObject.SetActive(false);
			gui.m_recipeIcon.sprite = item.GetIcon();
			string text = Localization.instance.Localize(item.m_shared.m_name);
			gui.m_recipeName.text = ((item.m_quality > 1) ? (text + " Q" + item.m_quality) : text);
			gui.m_recipeDecription.text = BuildRecycleSummary(gui, recyclePlan);
			((Component)gui.m_itemCraftType).gameObject.SetActive(true);
			gui.m_itemCraftType.text = "Recycle " + recyclePlan.ConsumeAmount + ((recyclePlan.ConsumeAmount == 1) ? " item" : " items");
			ShowStationLevel(gui, player, recyclePlan);
			ShowOutputs(gui, recyclePlan);
			bool flag = IsPlanStillValid(player, recyclePlan) && IsStationUsableForPlan(player, player.GetCurrentCraftingStation(), recyclePlan);
			((Selectable)gui.m_craftButton).interactable = flag;
			TMP_Text componentInChildren = ((Component)gui.m_craftButton).GetComponentInChildren<TMP_Text>(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				componentInChildren.text = ((_armedItem == item && (Object)(object)_armedRecipe == (Object)(object)recipe) ? "Confirm Recycle" : "Recycle");
			}
			UITooltip component = ((Component)gui.m_craftButton).GetComponent<UITooltip>();
			if ((Object)(object)component != (Object)null)
			{
				component.m_text = (flag ? "" : "Recycling requirements are not met.");
			}
			if (GuiAccess.CraftTimer != null && (float)GuiAccess.CraftTimer.GetValue(gui) >= 0f && (Object)(object)gui.m_craftProgressPanel != (Object)null)
			{
				TMP_Text componentInChildren2 = ((Component)gui.m_craftProgressPanel).GetComponentInChildren<TMP_Text>(true);
				if ((Object)(object)componentInChildren2 != (Object)null)
				{
					componentInChildren2.text = "Recycling...";
				}
			}
		}

		internal static bool HandleCraftPressed(InventoryGui gui)
		{
			if (!Active)
			{
				return true;
			}
			GuiAccess.GetSelected(gui, out var recipe, out var item);
			RecyclePlan recyclePlan = FindPlan(recipe, item);
			if (recyclePlan == null || !IsPlanStillValid(Player.m_localPlayer, recyclePlan))
			{
				return false;
			}
			if (_armedItem != item || (Object)(object)_armedRecipe != (Object)(object)recipe)
			{
				_armedItem = item;
				_armedRecipe = recipe;
				TMP_Text componentInChildren = ((Component)gui.m_craftButton).GetComponentInChildren<TMP_Text>(true);
				if ((Object)(object)componentInChildren != (Object)null)
				{
					componentInChildren.text = "Confirm Recycle";
				}
				return false;
			}
			ClearArmed();
			return true;
		}

		internal static void HandleCraftCancelled()
		{
			if (Active)
			{
				ClearArmed();
			}
		}

		internal static bool CompleteRecycle(InventoryGui gui, Player player)
		{
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			if (!Active || (Object)(object)gui == (Object)null || (Object)(object)player == (Object)null)
			{
				return false;
			}
			GuiAccess.GetSelected(gui, out var recipe, out var item);
			RecyclePlan recyclePlan = FindPlan(recipe, item);
			if (recyclePlan == null || !IsPlanStillValid(player, recyclePlan) || !IsStationUsableForPlan(player, player.GetCurrentCraftingStation(), recyclePlan))
			{
				return false;
			}
			Inventory inventory = ((Humanoid)player).GetInventory();
			if (recyclePlan.Item.m_equipped)
			{
				((Humanoid)player).UnequipItem(recyclePlan.Item, true);
			}
			bool cheated = recyclePlan.Item.m_cheated;
			inventory.RemoveItem(recyclePlan.Item, recyclePlan.ConsumeAmount);
			long playerID = player.GetPlayerID();
			string playerName = player.GetPlayerName();
			for (int i = 0; i < recyclePlan.Outputs.Count; i++)
			{
				RecycleOutput recycleOutput = recyclePlan.Outputs[i];
				int num = recycleOutput.Roll();
				if (num > 0 && !((Object)(object)recycleOutput.Item == (Object)null))
				{
					inventory.AddItem(((Object)((Component)recycleOutput.Item).gameObject).name, num, recycleOutput.Item.m_itemData.m_quality, recycleOutput.Item.m_itemData.m_variant, playerID, playerName, cheated, false);
				}
			}
			CraftingStation currentCraftingStation = player.GetCurrentCraftingStation();
			if ((Object)(object)currentCraftingStation != (Object)null)
			{
				currentCraftingStation.m_craftItemDoneEffects.Create(((Component)player).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
			}
			else
			{
				gui.m_craftItemDoneEffects.Create(((Component)player).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
			}
			SkillType skill = (SkillType)(((Object)(object)recyclePlan.Recipe != (Object)null && (Object)(object)recyclePlan.Recipe.m_craftingStation != (Object)null) ? ((int)recyclePlan.Recipe.m_craftingStation.m_craftingSkill) : 0);
			CraftXpDebt.Add(player, skill, GetBatches(recyclePlan));
			ClearArmed();
			GuiAccess.Refresh(gui, focus: false);
			return true;
		}

		internal static bool ForceFiveCraftDuration(InventoryGui gui, out bool previous)
		{
			previous = false;
			if (!Active || GuiAccess.MultiCrafting == null)
			{
				return false;
			}
			previous = (bool)GuiAccess.MultiCrafting.GetValue(gui);
			GuiAccess.MultiCrafting.SetValue(gui, true);
			return true;
		}

		internal static void RestoreMultiCrafting(InventoryGui gui, bool changed, bool previous)
		{
			if (changed && GuiAccess.MultiCrafting != null)
			{
				GuiAccess.MultiCrafting.SetValue(gui, previous);
			}
		}

		private static void ClearArmed()
		{
			_armedItem = null;
			_armedRecipe = null;
		}

		private static RecyclePlan FindPlan(Recipe recipe, ItemData item)
		{
			if ((Object)(object)recipe == (Object)null || item == null)
			{
				return null;
			}
			for (int i = 0; i < Plans.Count; i++)
			{
				RecyclePlan recyclePlan = Plans[i];
				if ((Object)(object)recyclePlan.Recipe == (Object)(object)recipe && recyclePlan.Item == item)
				{
					return recyclePlan;
				}
			}
			return null;
		}

		private static bool IsPlanStillValid(Player player, RecyclePlan plan)
		{
			if ((Object)(object)player != (Object)null && plan != null && plan.Item != null && ((Humanoid)player).GetInventory().ContainsItem(plan.Item))
			{
				return plan.Item.m_stack >= plan.ConsumeAmount;
			}
			return false;
		}

		private static bool StationSupportsRecycler(CraftingStation station)
		{
			if ((Object)(object)station == (Object)null || station.m_upgrader || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return false;
			}
			if (IsFoodStation(station))
			{
				return false;
			}
			if (IsGaldrTable(station))
			{
				return true;
			}
			List<Recipe> recipes = ObjectDB.instance.m_recipes;
			for (int i = 0; i < recipes.Count; i++)
			{
				Recipe val = recipes[i];
				if (BasicRecipeAllowed(val) && !((Object)(object)val.m_craftingStation == (Object)null) && string.Equals(val.m_craftingStation.m_name, station.m_name, StringComparison.Ordinal))
				{
					return true;
				}
			}
			return false;
		}

		private static bool RecipeCanAppear(Recipe recipe, CraftingStation station, bool special)
		{
			if (!BasicRecipeAllowed(recipe))
			{
				return false;
			}
			if (special)
			{
				return true;
			}
			if ((Object)(object)recipe.m_craftingStation != (Object)null && (Object)(object)station != (Object)null)
			{
				return string.Equals(recipe.m_craftingStation.m_name, station.m_name, StringComparison.Ordinal);
			}
			return false;
		}

		private static bool BasicRecipeAllowed(Recipe recipe)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Invalid comparison between Unknown and I4
			if ((Object)(object)recipe == (Object)null || !recipe.m_enabled || (Object)(object)recipe.m_item == (Object)null || recipe.m_item.m_itemData == null || recipe.m_noCraftOnlyUpgrade || recipe.m_requireOnlyOneIngredient)
			{
				return false;
			}
			SharedData shared = recipe.m_item.m_itemData.m_shared;
			if (shared != null && !shared.m_questItem)
			{
				return (int)shared.m_itemType != 2;
			}
			return false;
		}

		private static bool IsFoodStation(CraftingStation station)
		{
			if ((Object)(object)station == (Object)null)
			{
				return false;
			}
			string name = station.m_name;
			if (!string.Equals(name, "$piece_cauldron", StringComparison.Ordinal) && !string.Equals(name, "$piece_preptable", StringComparison.Ordinal))
			{
				return string.Equals(name, "$piece_meadcauldron", StringComparison.Ordinal);
			}
			return true;
		}

		private static bool IsGaldrTable(CraftingStation station)
		{
			if ((Object)(object)station != (Object)null)
			{
				return string.Equals(station.m_name, "$piece_magetable", StringComparison.Ordinal);
			}
			return false;
		}

		private static bool IsSpecialReverse(CraftingStation station, Recipe recipe)
		{
			if (IsGaldrTable(station) && (Object)(object)recipe != (Object)null && (Object)(object)recipe.m_item != (Object)null)
			{
				return GaldrReversePrefabs.Contains(((Object)((Component)recipe.m_item).gameObject).name);
			}
			return false;
		}

		private static void AddSpecialReverseRecipes(Player player, CraftingStation station, List<Recipe> source)
		{
			if (!IsGaldrTable(station) || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return;
			}
			List<Recipe> recipes = ObjectDB.instance.m_recipes;
			for (int i = 0; i < recipes.Count; i++)
			{
				Recipe val = recipes[i];
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val.m_item == (Object)null) && val.m_item.m_itemData != null && GaldrReversePrefabs.Contains(((Object)((Component)val.m_item).gameObject).name))
				{
					string name = val.m_item.m_itemData.m_shared.m_name;
					if (player.IsRecipeKnown(name) && AllMaterialsKnown(player, val) && !source.Contains(val))
					{
						source.Add(val);
					}
				}
			}
		}

		private static bool AllMaterialsKnown(Player player, Recipe recipe)
		{
			Requirement[] resources = recipe.m_resources;
			foreach (Requirement val in resources)
			{
				if (val != null && !((Object)(object)val.m_resItem == (Object)null) && !player.IsMaterialKnown(val.m_resItem.m_itemData.m_shared.m_name))
				{
					return false;
				}
			}
			return true;
		}

		private static bool IsStationUsableForPlan(Player player, CraftingStation station, RecyclePlan plan)
		{
			if ((Object)(object)player == (Object)null || (Object)(object)station == (Object)null || plan == null || !station.CheckUsable(player, false))
			{
				return false;
			}
			if (plan.SpecialReverse)
			{
				if (IsGaldrTable(station))
				{
					return station.GetLevel(true) >= plan.RequiredLevel;
				}
				return false;
			}
			if ((Object)(object)plan.Recipe != (Object)null && (Object)(object)plan.Recipe.m_craftingStation != (Object)null && string.Equals(plan.Recipe.m_craftingStation.m_name, station.m_name, StringComparison.Ordinal))
			{
				return station.GetLevel(true) >= plan.RequiredLevel;
			}
			return false;
		}

		private static int GetConsumeAmount(ItemData item, Recipe recipe)
		{
			if (item == null || (Object)(object)recipe == (Object)null || recipe.m_amount <= 0)
			{
				return 0;
			}
			if (recipe.m_amount == 1)
			{
				return item.m_stack;
			}
			if (item.m_stack < recipe.m_amount)
			{
				return 0;
			}
			int num = Mathf.CeilToInt((float)recipe.m_amount * 1.5f);
			return Mathf.Min(item.m_stack, num);
		}

		private static int GetBatches(RecyclePlan plan)
		{
			if (plan == null || (Object)(object)plan.Recipe == (Object)null || plan.Recipe.m_amount <= 0)
			{
				return 0;
			}
			return Mathf.Max(1, plan.ConsumeAmount / plan.Recipe.m_amount);
		}

		private static float GetRecoveryRate(ItemData item)
		{
			int nonPotentialQuality = GetNonPotentialQuality(item);
			if (nonPotentialQuality <= 1)
			{
				return 0.8f;
			}
			return nonPotentialQuality switch
			{
				2 => 0.85f, 
				3 => 0.9f, 
				_ => 1f, 
			};
		}

		private static int GetNonPotentialQuality(ItemData item)
		{
			return Mathf.Clamp(item.m_quality, 1, Mathf.Max(1, item.m_shared.m_maxQuality));
		}

		private static float GetCraftBonus(InventoryGui gui)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)gui == (Object)null)
			{
				return 0f;
			}
			return Mathf.Clamp01(((Character)localPlayer).GetSkillFactor((SkillType)107) * gui.m_craftBonusChance);
		}

		private static void BuildOutputs(InventoryGui gui, RecyclePlan plan)
		{
			int batches = GetBatches(plan);
			float recoveryRate = GetRecoveryRate(plan.Item);
			float craftBonus = GetCraftBonus(gui);
			int nonPotentialQuality = GetNonPotentialQuality(plan.Item);
			Requirement[] resources = plan.Recipe.m_resources;
			foreach (Requirement val in resources)
			{
				if (val == null || (Object)(object)val.m_resItem == (Object)null || val.m_upgraderResource)
				{
					continue;
				}
				int num = val.GetAmount(1) * batches;
				if (num > 0)
				{
					RecycleOutput recycleOutput = new RecycleOutput
					{
						Item = val.m_resItem
					};
					if (val.m_resItem.m_itemData.IsEquipable())
					{
						recycleOutput.BaseMin = num;
						recycleOutput.BaseMax = num;
					}
					else
					{
						ConfigureBaseRecovery(recycleOutput, (float)num * recoveryRate, craftBonus);
					}
					int num2 = 0;
					for (int j = 2; j <= nonPotentialQuality; j++)
					{
						num2 += val.GetAmount(j) * batches;
					}
					ConfigureUpgradeRecovery(recycleOutput, (float)num2 * craftBonus);
					MergeOutput(plan.Outputs, recycleOutput);
				}
			}
		}

		private static void ConfigureBaseRecovery(RecycleOutput output, float exact, float craftBonus)
		{
			if (exact <= 0f)
			{
				return;
			}
			int num = Mathf.FloorToInt(exact);
			int num2 = Mathf.CeilToInt(exact);
			if (num == 0 && num2 == 1)
			{
				output.BaseMin = 1;
				output.BaseMax = 1;
				return;
			}
			output.BaseMin = num;
			output.BaseMax = num2;
			if (num2 > num)
			{
				float num3 = exact - (float)num;
				output.BaseHighChance = Mathf.Clamp01(num3 + (1f - num3) * craftBonus);
			}
		}

		private static void ConfigureUpgradeRecovery(RecycleOutput output, float exact)
		{
			if (!(exact <= 0f))
			{
				int num = Mathf.FloorToInt(exact);
				int num2 = Mathf.CeilToInt(exact);
				output.UpgradeMin = num;
				output.UpgradeMax = num2;
				if (num2 > num)
				{
					output.UpgradeHighChance = Mathf.Clamp01(exact - (float)num);
				}
			}
		}

		private static void MergeOutput(List<RecycleOutput> outputs, RecycleOutput incoming)
		{
			if (incoming == null || (Object)(object)incoming.Item == (Object)null)
			{
				return;
			}
			string name = incoming.Item.m_itemData.m_shared.m_name;
			for (int i = 0; i < outputs.Count; i++)
			{
				RecycleOutput recycleOutput = outputs[i];
				if (!(recycleOutput.Item.m_itemData.m_shared.m_name != name))
				{
					recycleOutput.BaseMin += incoming.BaseMin;
					recycleOutput.BaseMax += incoming.BaseMax;
					recycleOutput.BaseHighChance = Mathf.Max(recycleOutput.BaseHighChance, incoming.BaseHighChance);
					recycleOutput.UpgradeMin += incoming.UpgradeMin;
					recycleOutput.UpgradeMax += incoming.UpgradeMax;
					recycleOutput.UpgradeHighChance = Mathf.Max(recycleOutput.UpgradeHighChance, incoming.UpgradeHighChance);
					return;
				}
			}
			outputs.Add(incoming);
		}

		private static void ShowStationLevel(InventoryGui gui, Player player, RecyclePlan plan)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			bool flag = plan != null && plan.RequiredLevel > 0;
			((Component)gui.m_minStationLevelIcon).gameObject.SetActive(flag);
			if (!flag)
			{
				return;
			}
			((Component)gui.m_minStationLevelText).gameObject.SetActive(true);
			gui.m_minStationLevelText.text = plan.RequiredLevel.ToString();
			Color val = Color.white;
			if (GuiAccess.MinStationBaseColor != null)
			{
				object value = GuiAccess.MinStationBaseColor.GetValue(gui);
				if (value is Color)
				{
					val = (Color)value;
				}
			}
			CraftingStation currentCraftingStation = player.GetCurrentCraftingStation();
			bool flag2 = IsStationUsableForPlan(player, currentCraftingStation, plan);
			((Graphic)gui.m_minStationLevelText).color = (flag2 ? val : ((Mathf.Sin(Time.time * 10f) > 0f) ? Color.red : val));
		}

		private static void ShowOutputs(InventoryGui gui, RecyclePlan plan)
		{
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			int num = gui.m_recipeRequirementList.Length;
			int num2 = Mathf.Min(num, plan.Outputs.Count);
			for (int i = 0; i < num2; i++)
			{
				RecycleOutput recycleOutput = plan.Outputs[i];
				Transform transform = gui.m_recipeRequirementList[i].transform;
				Image component = ((Component)transform.Find("res_icon")).GetComponent<Image>();
				TMP_Text component2 = ((Component)transform.Find("res_name")).GetComponent<TMP_Text>();
				TMP_Text component3 = ((Component)transform.Find("res_amount")).GetComponent<TMP_Text>();
				((Component)component).gameObject.SetActive(true);
				((Component)component2).gameObject.SetActive(true);
				((Component)component3).gameObject.SetActive(true);
				component.sprite = recycleOutput.Item.m_itemData.GetIcon();
				((Graphic)component).color = Color.white;
				string text = (component2.text = Localization.instance.Localize(recycleOutput.Item.m_itemData.m_shared.m_name));
				int minAmount = recycleOutput.MinAmount;
				int maxAmount = recycleOutput.MaxAmount;
				component3.text = ((minAmount == maxAmount) ? minAmount.ToString() : (minAmount + "-" + maxAmount));
				((Graphic)component3).color = Color.white;
				UITooltip component4 = ((Component)transform).GetComponent<UITooltip>();
				if ((Object)(object)component4 != (Object)null)
				{
					component4.m_text = text + "\n" + FormatOutputOdds(recycleOutput);
				}
			}
			for (int j = num2; j < num; j++)
			{
				InventoryGui.HideRequirement(gui.m_recipeRequirementList[j].transform);
			}
		}

		private static string BuildRecycleSummary(InventoryGui gui, RecyclePlan plan)
		{
			StringBuilder stringBuilder = new StringBuilder();
			int num = Mathf.Max(1, plan.Item.m_shared.m_maxQuality);
			int nonPotentialQuality = GetNonPotentialQuality(plan.Item);
			int num2 = Mathf.Max(0, plan.Item.m_quality - num);
			float recoveryRate = GetRecoveryRate(plan.Item);
			float craftBonus = GetCraftBonus(gui);
			stringBuilder.Append("<color=orange><b>RECYCLING</b></color>");
			stringBuilder.Append("\nAmount: <color=yellow>" + plan.ConsumeAmount + "</color>");
			if (plan.Recipe.m_amount > 1)
			{
				stringBuilder.Append("\nRecipe batch: " + plan.Recipe.m_amount + "  |  Max per recycle: " + Mathf.CeilToInt((float)plan.Recipe.m_amount * 1.5f));
			}
			stringBuilder.Append("\nBase recovery: <color=yellow>" + Mathf.RoundToInt(recoveryRate * 100f) + "%</color>");
			stringBuilder.Append("\nCrafting rounding bonus: <color=yellow>" + (craftBonus * 100f).ToString("0.#") + "%</color>");
			if (nonPotentialQuality > 1)
			{
				stringBuilder.Append("\nVanilla quality counted: Q" + nonPotentialQuality);
			}
			if (num2 > 0)
			{
				stringBuilder.Append("\nPotential +" + num2 + ": <color=#AAAAAA>no extra recycle value</color>");
			}
			stringBuilder.Append("\n\n<color=orange><b>POSSIBLE RETURNS</b></color>");
			for (int i = 0; i < plan.Outputs.Count; i++)
			{
				RecycleOutput recycleOutput = plan.Outputs[i];
				string text = Localization.instance.Localize(recycleOutput.Item.m_itemData.m_shared.m_name);
				stringBuilder.Append("\n- " + text + ": " + FormatOutputOdds(recycleOutput));
			}
			return stringBuilder.ToString();
		}

		private static string FormatOutputOdds(RecycleOutput output)
		{
			SortedDictionary<int, float> sortedDictionary = new SortedDictionary<int, float>();
			AddCombinedOdds(sortedDictionary, output.BaseMin, output.BaseMax, output.BaseHighChance, output.UpgradeMin, output.UpgradeMax, output.UpgradeHighChance);
			if (sortedDictionary.Count == 1)
			{
				using SortedDictionary<int, float>.Enumerator enumerator = sortedDictionary.GetEnumerator();
				if (enumerator.MoveNext())
				{
					return enumerator.Current.Key.ToString();
				}
			}
			StringBuilder stringBuilder = new StringBuilder();
			bool flag = true;
			foreach (KeyValuePair<int, float> item in sortedDictionary)
			{
				if (!(item.Value < 0.0005f))
				{
					if (!flag)
					{
						stringBuilder.Append(" | ");
					}
					flag = false;
					stringBuilder.Append(item.Key + " (" + (item.Value * 100f).ToString("0.#") + "%)");
				}
			}
			return stringBuilder.ToString();
		}

		private static void AddCombinedOdds(SortedDictionary<int, float> odds, int baseMin, int baseMax, float baseHighChance, int upgradeMin, int upgradeMax, float upgradeHighChance)
		{
			float num = ((baseMax > baseMin) ? (1f - baseHighChance) : 1f);
			float num2 = ((baseMax > baseMin) ? baseHighChance : 0f);
			float num3 = ((upgradeMax > upgradeMin) ? (1f - upgradeHighChance) : 1f);
			float num4 = ((upgradeMax > upgradeMin) ? upgradeHighChance : 0f);
			AddOdds(odds, baseMin + upgradeMin, num * num3);
			if (upgradeMax > upgradeMin)
			{
				AddOdds(odds, baseMin + upgradeMax, num * num4);
			}
			if (baseMax > baseMin)
			{
				AddOdds(odds, baseMax + upgradeMin, num2 * num3);
				if (upgradeMax > upgradeMin)
				{
					AddOdds(odds, baseMax + upgradeMax, num2 * num4);
				}
			}
		}

		private static void AddOdds(SortedDictionary<int, float> odds, int amount, float chance)
		{
			if (!(chance <= 0f))
			{
				odds.TryGetValue(amount, out var value);
				odds[amount] = value + chance;
			}
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "Awake")]
	internal static class InventoryGuiAwakePatch
	{
		[HarmonyPostfix]
		private static void Postfix(InventoryGui __instance)
		{
			RecyclerUi.Initialize(__instance);
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "OnDestroy")]
	internal static class InventoryGuiDestroyPatch
	{
		[HarmonyPrefix]
		private static void Prefix()
		{
			RecyclerUi.Shutdown();
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "Hide")]
	internal static class InventoryGuiHidePatch
	{
		[HarmonyPrefix]
		private static void Prefix()
		{
			RecyclerUi.LeaveRecycleTab();
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "UpdateCraftingPanel")]
	internal static class InventoryGuiCraftingPanelPatch
	{
		[HarmonyPostfix]
		private static void Postfix(InventoryGui __instance)
		{
			if (RecyclerUi.Active && (!((Selectable)__instance.m_tabCraft).interactable || !((Selectable)__instance.m_tabUpgrade).interactable))
			{
				RecyclerUi.LeaveRecycleTab();
			}
			RecyclerUi.SyncTabVisibility(__instance);
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "UpdateRecipeList")]
	internal static class InventoryGuiRecipeListPatch
	{
		[HarmonyPostfix]
		private static void Postfix(InventoryGui __instance, List<Recipe> recipes)
		{
			RecyclerUi.RebuildRecipeList(__instance, recipes);
		}
	}
	internal static class CraftXpDebt
	{
		private static Player _player;

		private static readonly Dictionary<SkillType, int> Debt = new Dictionary<SkillType, int>();

		internal static void Reset()
		{
			_player = null;
			Debt.Clear();
		}

		private static void EnsurePlayer(Player player)
		{
			if (!((Object)(object)_player == (Object)(object)player))
			{
				_player = player;
				Debt.Clear();
			}
		}

		internal static void Add(Player player, SkillType skill, int amount)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)player == (Object)null) && (int)skill != 0 && amount > 0)
			{
				EnsurePlayer(player);
				Debt.TryGetValue(skill, out var value);
				long num = (long)value + (long)amount;
				Debt[skill] = (int)((num > int.MaxValue) ? int.MaxValue : num);
			}
		}

		internal static bool Apply(Player player, SkillType skill, ref float value)
		{
			//IL_0016: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null || (Object)(object)_player != (Object)(object)player || (int)skill == 0 || value <= 0f)
			{
				return false;
			}
			if (!Debt.TryGetValue(skill, out var value2) || value2 <= 0)
			{
				return false;
			}
			int num = Mathf.Max(0, Mathf.FloorToInt(value + 0.0001f));
			if (num <= 0)
			{
				return false;
			}
			int num2 = Mathf.Min(value2, num);
			value2 -= num2;
			value -= num2;
			if (value2 > 0)
			{
				Debt[skill] = value2;
			}
			else
			{
				Debt.Remove(skill);
			}
			return value <= 0f;
		}
	}
	internal struct UpdateRecipeState
	{
		internal bool Changed;

		internal bool Previous;
	}
	[HarmonyPatch(typeof(InventoryGui), "UpdateRecipe")]
	internal static class InventoryGuiUpdateRecipePatch
	{
		[HarmonyPrefix]
		private static void Prefix(InventoryGui __instance, out UpdateRecipeState __state)
		{
			__state = new UpdateRecipeState
			{
				Changed = RecyclerUi.ForceFiveCraftDuration(__instance, out var previous),
				Previous = previous
			};
		}

		[HarmonyPostfix]
		private static void Postfix(InventoryGui __instance, Player player, UpdateRecipeState __state)
		{
			RecyclerUi.RestoreMultiCrafting(__instance, __state.Changed, __state.Previous);
			RecyclerUi.OverrideRecipeDetails(__instance, player);
		}

		[HarmonyFinalizer]
		private static Exception Finalizer(InventoryGui __instance, Exception __exception, UpdateRecipeState __state)
		{
			if (__exception != null)
			{
				RecyclerUi.RestoreMultiCrafting(__instance, __state.Changed, __state.Previous);
			}
			return __exception;
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "OnCraftPressed")]
	internal static class InventoryGuiCraftPressedPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(InventoryGui __instance)
		{
			return RecyclerUi.HandleCraftPressed(__instance);
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "OnCraftCancelPressed")]
	internal static class InventoryGuiCraftCancelPatch
	{
		[HarmonyPostfix]
		private static void Postfix()
		{
			RecyclerUi.HandleCraftCancelled();
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "DoCrafting", new Type[] { typeof(Player) })]
	internal static class InventoryGuiDoCraftingPatch
	{
		internal static bool NormalCraftActive { get; private set; }

		[HarmonyPrefix]
		private static bool Prefix(InventoryGui __instance, Player player)
		{
			if (!RecyclerUi.Active)
			{
				NormalCraftActive = true;
				return true;
			}
			NormalCraftActive = false;
			RecyclerUi.CompleteRecycle(__instance, player);
			return false;
		}

		[HarmonyPostfix]
		private static void Postfix()
		{
			NormalCraftActive = false;
		}

		[HarmonyFinalizer]
		private static Exception Finalizer(Exception __exception)
		{
			NormalCraftActive = false;
			return __exception;
		}
	}
	[HarmonyPatch(typeof(Player), "RaiseSkill", new Type[]
	{
		typeof(SkillType),
		typeof(float)
	})]
	internal static class PlayerRaiseCraftSkillPatch
	{
		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static bool Prefix(Player __instance, SkillType skill, ref float value)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (!InventoryGuiDoCraftingPatch.NormalCraftActive)
			{
				return true;
			}
			return !CraftXpDebt.Apply(__instance, skill, ref value);
		}
	}
}