Decompiled source of ChanceCraft v1.1.6

ChanceCraft.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("ChanceCraft")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ChanceCraft")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("4BA1E0D1-50C4-4C46-92A7-AD47D0717105")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
public static class ChanceCraftUIRefreshUsage
{
	public static void RefreshCraftingUiAfterChange()
	{
		try
		{
			GameObject craftingPanelRoot = GetCraftingPanelRoot();
			if ((Object)(object)craftingPanelRoot != (Object)null)
			{
				UIRemoteRefresher.Instance.RefreshNextFrame(craftingPanelRoot);
				Debug.Log((object)("[ChanceCraft] RefreshCraftingUiAfterChange: scheduled refresher for panel: " + ((Object)craftingPanelRoot).name));
			}
			else
			{
				Debug.LogWarning((object)"[ChanceCraft] RefreshCraftingUiAfterChange: couldn't find crafting panel root");
			}
		}
		catch (Exception ex)
		{
			Debug.LogWarning((object)("[ChanceCraft] RefreshCraftingUiAfterChange exception: " + ex));
		}
	}

	private static GameObject GetCraftingPanelRoot()
	{
		try
		{
			Type type = Type.GetType("CraftingPanel, Assembly-CSharp") ?? Type.GetType("CraftingPanel");
			if (type != null)
			{
				Object obj = Object.FindObjectOfType(type);
				Component val = (Component)(object)((obj is Component) ? obj : null);
				if ((Object)(object)val != (Object)null && (Object)(object)val.gameObject != (Object)null)
				{
					Debug.Log((object)("[ChanceCraft] Found crafting panel via CraftingPanel type: " + ((Object)val.gameObject).name));
					return val.gameObject;
				}
			}
		}
		catch (Exception ex)
		{
			Debug.LogWarning((object)("[ChanceCraft] GetCraftingPanelRoot: Type.GetType('CraftingPanel') failed: " + ex));
		}
		string[] array = new string[7] { "Crafting", "crafting", "CraftingPanel", "craftingpanel", "CraftingMenu", "RecipePanel", "piece_workbench(Clone)" };
		string[] array2 = array;
		foreach (string text in array2)
		{
			GameObject val2 = GameObject.Find(text);
			if ((Object)(object)val2 != (Object)null)
			{
				Debug.Log((object)("[ChanceCraft] Found crafting panel via GameObject.Find: " + text));
				return val2;
			}
		}
		Canvas[] array3 = Object.FindObjectsOfType<Canvas>(true);
		Canvas[] array4 = array3;
		foreach (Canvas val3 in array4)
		{
			if (!((Object)(object)val3 == (Object)null) && !string.IsNullOrEmpty(((Object)val3).name))
			{
				string text2 = ((Object)val3).name.ToLowerInvariant();
				if (text2.Contains("craft") || text2.Contains("recipe") || text2.Contains("workbench") || text2.Contains("bench"))
				{
					Debug.Log((object)("[ChanceCraft] Found crafting panel via Canvas name: " + ((Object)val3).name));
					return ((Component)val3).gameObject;
				}
			}
		}
		RectTransform[] array5 = Object.FindObjectsOfType<RectTransform>(true);
		RectTransform[] array6 = array5;
		foreach (RectTransform val4 in array6)
		{
			if (!((Object)(object)val4 == (Object)null))
			{
				string text3 = ((Object)val4).name.ToLowerInvariant();
				if (text3.Contains("recipe") || text3.Contains("recipelist") || text3.Contains("craft"))
				{
					Debug.Log((object)("[ChanceCraft] Found crafting panel candidate via RectTransform name: " + ((Object)val4).name));
					return ((Component)val4).gameObject;
				}
			}
		}
		return null;
	}
}
public class UIRemoteRefresher : MonoBehaviour
{
	[CompilerGenerated]
	private sealed class <RefreshRoutine>d__5 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public GameObject panel;

		public int additionalFrames;

		public UIRemoteRefresher <>4__this;

		private int <i>5__1;

		private bool <active>5__2;

		private Exception <ex>5__3;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <RefreshRoutine>d__5(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<ex>5__3 = null;
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<>2__current = null;
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				<i>5__1 = 0;
				break;
			case 2:
				<>1__state = -1;
				<i>5__1++;
				break;
			}
			if (<i>5__1 < additionalFrames)
			{
				<>2__current = null;
				<>1__state = 2;
				return true;
			}
			try
			{
				if ((Object)(object)panel != (Object)null)
				{
					try
					{
						<active>5__2 = panel.activeSelf;
						if (<active>5__2)
						{
							panel.SetActive(false);
						}
						if (<active>5__2)
						{
							panel.SetActive(true);
						}
					}
					catch
					{
					}
				}
				try
				{
					Canvas.ForceUpdateCanvases();
				}
				catch
				{
				}
				try
				{
					ChanceCraftUIRefreshUsage.RefreshCraftingUiAfterChange();
				}
				catch
				{
				}
			}
			catch (Exception ex)
			{
				<ex>5__3 = ex;
				Debug.LogWarning((object)$"[ChanceCraft] UIRemoteRefresher.RefreshRoutine exception: {<ex>5__3}");
			}
			return false;
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	private static UIRemoteRefresher _instance;

	public static UIRemoteRefresher Instance
	{
		get
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			if ((Object)(object)_instance == (Object)null)
			{
				_instance = Object.FindObjectOfType<UIRemoteRefresher>();
				if ((Object)(object)_instance == (Object)null)
				{
					GameObject val = new GameObject("UIRemoteRefresher");
					Object.DontDestroyOnLoad((Object)(object)val);
					_instance = val.AddComponent<UIRemoteRefresher>();
				}
			}
			return _instance;
		}
	}

	private void Awake()
	{
		if ((Object)(object)_instance == (Object)null)
		{
			_instance = this;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
		}
		else if ((Object)(object)_instance != (Object)(object)this)
		{
			Object.Destroy((Object)(object)((Component)this).gameObject);
		}
	}

	public void RefreshNextFrame(GameObject panel, int additionalFramesToWait = 0)
	{
		((MonoBehaviour)this).StartCoroutine(RefreshRoutine(panel, Mathf.Max(0, additionalFramesToWait)));
	}

	[IteratorStateMachine(typeof(<RefreshRoutine>d__5))]
	private IEnumerator RefreshRoutine(GameObject panel, int additionalFrames)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <RefreshRoutine>d__5(0)
		{
			<>4__this = this,
			panel = panel,
			additionalFrames = additionalFrames
		};
	}
}
namespace ChanceCraft
{
	[BepInPlugin("deep.ChanceCraft", "Chance Craft", "1.1.5")]
	public class ChanceCraft : BaseUnityPlugin
	{
		public class ChanceCraftLine
		{
			public float IncreaseCraftPercentage;

			public string ItemPrefab;

			public bool IsActive => !string.IsNullOrWhiteSpace(ItemPrefab);
		}

		[HarmonyPatch(typeof(InventoryGui), "DoCrafting")]
		private static class InventoryGuiDoCraftingPatch
		{
			private static readonly Dictionary<string, object> _savedResources = new Dictionary<string, object>();

			private static readonly object _savedResourcesLockLocal = new object();

			private static bool _suppressedThisCall = false;

			private static Recipe _savedRecipeForCall = null;

			private static string GetRecipeKey(Recipe r)
			{
				if ((Object)(object)r == (Object)null)
				{
					return null;
				}
				try
				{
					string arg = r.m_item?.m_itemData?.m_shared?.m_name ?? ((Object)r).name ?? "unknown";
					int valueOrDefault = (r.m_item?.m_itemData?.m_quality).GetValueOrDefault();
					int valueOrDefault2 = (r.m_item?.m_itemData?.m_variant).GetValueOrDefault();
					return $"{arg}|q{valueOrDefault}|v{valueOrDefault2}";
				}
				catch
				{
					return ((object)r).GetHashCode().ToString();
				}
			}

			private static void Prefix(InventoryGui __instance)
			{
				//IL_168e: Unknown result type (might be due to invalid IL or missing references)
				//IL_1694: Invalid comparison between Unknown and I4
				//IL_1680: Unknown result type (might be due to invalid IL or missing references)
				//IL_1698: Unknown result type (might be due to invalid IL or missing references)
				//IL_169f: Invalid comparison between Unknown and I4
				//IL_16a3: Unknown result type (might be due to invalid IL or missing references)
				//IL_16a9: Invalid comparison between Unknown and I4
				//IL_16ad: Unknown result type (might be due to invalid IL or missing references)
				//IL_16b4: Invalid comparison between Unknown and I4
				//IL_16b8: Unknown result type (might be due to invalid IL or missing references)
				//IL_16be: Invalid comparison between Unknown and I4
				//IL_16c2: Unknown result type (might be due to invalid IL or missing references)
				//IL_16c8: Invalid comparison between Unknown and I4
				//IL_16cc: Unknown result type (might be due to invalid IL or missing references)
				//IL_16d2: Invalid comparison between Unknown and I4
				//IL_16d6: Unknown result type (might be due to invalid IL or missing references)
				//IL_16dd: Invalid comparison between Unknown and I4
				//IL_16e1: Unknown result type (might be due to invalid IL or missing references)
				//IL_16e8: Invalid comparison between Unknown and I4
				_suppressedThisCall = false;
				_savedRecipeForCall = null;
				_isUpgradeDetected = false;
				_upgradeTargetItem = null;
				_upgradeRecipe = null;
				_upgradeGuiRecipe = null;
				_preCraftSnapshot = null;
				_preCraftSnapshotData = null;
				_snapshotRecipe = null;
				_upgradeGuiRequirements = null;
				_upgradeTargetItemIndex = -1;
				_preCraftSnapshotHashQuality = null;
				try
				{
					FieldInfo field = typeof(InventoryGui).GetField("m_selectedRecipe", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (field == null)
					{
						return;
					}
					object value = field.GetValue(__instance);
					Recipe val = null;
					if (value != null && value.GetType().Name == "RecipeDataPair")
					{
						PropertyInfo property = value.GetType().GetProperty("Recipe", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
						if (property != null)
						{
							object? value2 = property.GetValue(value);
							val = (Recipe)((value2 is Recipe) ? value2 : null);
						}
					}
					else
					{
						val = (Recipe)((value is Recipe) ? value : null);
					}
					if ((Object)(object)val == (Object)null)
					{
						return;
					}
					try
					{
						if (value != null)
						{
							if (ChanceCraftRecipeHelpers.TryExtractRecipeFromWrapper(value, val, out var foundRecipe, out var _))
							{
								_upgradeGuiRecipe = foundRecipe;
								try
								{
									string item = ChanceCraftRecipeHelpers.RecipeFingerprint(foundRecipe);
									lock (_suppressedRecipeKeysLock)
									{
										if (!_suppressedRecipeKeys.Contains(item))
										{
											_suppressedRecipeKeys.Add(item);
										}
									}
								}
								catch
								{
								}
							}
							else
							{
								Recipe upgradeRecipeFromGui = ChanceCraftRecipeHelpers.GetUpgradeRecipeFromGui(__instance);
								if ((Object)(object)upgradeRecipeFromGui != (Object)null)
								{
									_upgradeGuiRecipe = upgradeRecipeFromGui;
									try
									{
										string item2 = ChanceCraftRecipeHelpers.RecipeFingerprint(upgradeRecipeFromGui);
										lock (_suppressedRecipeKeysLock)
										{
											if (!_suppressedRecipeKeys.Contains(item2))
											{
												_suppressedRecipeKeys.Add(item2);
											}
										}
									}
									catch
									{
									}
								}
							}
						}
						if ((Object)(object)_upgradeGuiRecipe == (Object)null || _upgradeGuiRecipe == val)
						{
							Recipe val2 = ChanceCraftRecipeHelpers.FindBestUpgradeRecipeCandidate(val);
							if ((Object)(object)val2 != (Object)null)
							{
								_upgradeRecipe = val2;
								if (ChanceCraftRecipeHelpers.RecipeConsumesResult(val2))
								{
									_isUpgradeDetected = true;
								}
							}
						}
					}
					catch (Exception arg)
					{
						LogWarning($"Prefix early discovery exception: {arg}");
					}
					_savedRecipeForCall = val;
					try
					{
						if (_upgradeTargetItem == null)
						{
							Type typeFromHandle = typeof(InventoryGui);
							FieldInfo field2 = typeFromHandle.GetField("m_craftUpgradeItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
							if (field2 != null)
							{
								object? value3 = field2.GetValue(__instance);
								_upgradeTargetItem = (ItemData)((value3 is ItemData) ? value3 : null);
							}
							if (_upgradeTargetItem == null)
							{
								FieldInfo field3 = typeFromHandle.GetField("m_upgradeItems", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
								FieldInfo field4 = typeFromHandle.GetField("m_upgradeItemIndex", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
								if (field3 != null && field3.GetValue(__instance) is IList list && list.Count > 0)
								{
									int num = -1;
									if (field4 != null && field4.GetValue(__instance) is int num2)
									{
										num = num2;
									}
									_upgradeTargetItem = (ItemData)((num >= 0 && num < list.Count) ? /*isinst with value type is only supported in some contexts*/: /*isinst with value type is only supported in some contexts*/);
								}
							}
							if (_upgradeTargetItem == null)
							{
								string[] array = new string[4] { "m_selectedItem", "m_selected", "m_selectedItemData", "m_selectedInventoryItem" };
								string[] array2 = array;
								foreach (string name2 in array2)
								{
									try
									{
										FieldInfo field5 = typeFromHandle.GetField(name2, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
										if (field5 != null)
										{
											object? value4 = field5.GetValue(__instance);
											ItemData val3 = (ItemData)((value4 is ItemData) ? value4 : null);
											if (val3 != null)
											{
												_upgradeTargetItem = val3;
												break;
											}
										}
									}
									catch
									{
									}
								}
							}
						}
					}
					catch
					{
					}
					try
					{
						if (ChanceCraftUIHelpers.TryGetRequirementsFromGui(__instance, out List<(string, int)> requirements) && requirements != null && requirements.Count > 0)
						{
							bool flag = false;
							try
							{
								FieldInfo field6 = typeof(InventoryGui).GetField("m_craftUpgrade", BindingFlags.Instance | BindingFlags.NonPublic);
								if (field6 != null)
								{
									object value5 = field6.GetValue(__instance);
									if (value5 is int)
									{
										int num3 = (int)value5;
										if (num3 > 1)
										{
											flag = true;
										}
									}
								}
							}
							catch
							{
							}
							try
							{
								int valueOrDefault = (val.m_item?.m_itemData?.m_quality).GetValueOrDefault();
								if (_upgradeTargetItem != null && valueOrDefault > _upgradeTargetItem.m_quality)
								{
									flag = true;
								}
							}
							catch
							{
							}
							try
							{
								if (ChanceCraftRecipeHelpers.RecipeConsumesResult(val))
								{
									flag = true;
								}
							}
							catch
							{
							}
							try
							{
								Dictionary<string, int> dictionary = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
								if (((object)val).GetType().GetField("m_resources", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(val) is IEnumerable enumerable)
								{
									foreach (object item6 in enumerable)
									{
										try
										{
											Type type = item6.GetType();
											object obj9 = type.GetField("m_resItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(item6);
											string text = null;
											if (obj9 != null)
											{
												object obj10 = obj9.GetType().GetField("m_itemData", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj9);
												object obj11 = obj10?.GetType().GetField("m_shared", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj10);
												text = obj11?.GetType().GetField("m_name", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj11) as string;
											}
											object obj12 = type.GetField("m_amount", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(item6);
											int num4 = ((obj12 != null) ? Convert.ToInt32(obj12) : 0);
											if (!string.IsNullOrEmpty(text))
											{
												if (dictionary.ContainsKey(text))
												{
													dictionary[text] += num4;
												}
												else
												{
													dictionary[text] = num4;
												}
											}
										}
										catch
										{
										}
									}
								}
								Dictionary<string, int> dictionary2 = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
								foreach (var item7 in requirements)
								{
									dictionary2[item7.Item1] = (dictionary2.ContainsKey(item7.Item1) ? (dictionary2[item7.Item1] + item7.Item2) : item7.Item2);
								}
								Dictionary<string, int> dictionary3 = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
								if (((object)val).GetType().GetField("m_resources", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(val) is IEnumerable enumerable2)
								{
									foreach (object item8 in enumerable2)
									{
										try
										{
											Type type2 = item8.GetType();
											object obj14 = type2.GetField("m_resItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(item8);
											string text2 = null;
											if (obj14 != null)
											{
												object obj15 = obj14.GetType().GetField("m_itemData", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj14);
												object obj16 = obj15?.GetType().GetField("m_shared", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj15);
												text2 = obj16?.GetType().GetField("m_name", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj16) as string;
											}
											object obj17 = type2.GetField("m_amount", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(item8);
											int num5 = ((obj17 != null) ? Convert.ToInt32(obj17) : 0);
											if (!string.IsNullOrEmpty(text2))
											{
												if (dictionary3.ContainsKey(text2))
												{
													dictionary3[text2] += num5;
												}
												else
												{
													dictionary3[text2] = num5;
												}
											}
										}
										catch
										{
										}
									}
								}
								Dictionary<string, int> dictionary4 = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
								foreach (var item9 in requirements)
								{
									dictionary4[item9.Item1] = (dictionary4.ContainsKey(item9.Item1) ? (dictionary4[item9.Item1] + item9.Item2) : item9.Item2);
								}
								bool flag2 = false;
								if (dictionary4.Count != dictionary3.Count)
								{
									flag2 = true;
								}
								else
								{
									foreach (KeyValuePair<string, int> item10 in dictionary4)
									{
										if (!dictionary3.TryGetValue(item10.Key, out var value6) || value6 != item10.Value)
										{
											flag2 = true;
											break;
										}
									}
								}
								bool flag3 = false;
								try
								{
									FieldInfo field7 = typeof(InventoryGui).GetField("m_craftUpgrade", BindingFlags.Instance | BindingFlags.NonPublic);
									if (field7 != null)
									{
										object value7 = field7.GetValue(__instance);
										if (value7 is int)
										{
											int num6 = (int)value7;
											if (num6 > 1)
											{
												flag3 = true;
											}
										}
									}
								}
								catch
								{
									flag3 = false;
								}
								bool flag4 = false;
								try
								{
									ItemData selectedInventoryItem = ChanceCraftRecipeHelpers.GetSelectedInventoryItem(__instance);
									int valueOrDefault2 = (val.m_item?.m_itemData?.m_quality).GetValueOrDefault();
									if (selectedInventoryItem != null && selectedInventoryItem.m_shared != null && !string.IsNullOrEmpty(val.m_item?.m_itemData?.m_shared?.m_name) && selectedInventoryItem.m_shared.m_name == val.m_item.m_itemData.m_shared.m_name && selectedInventoryItem.m_quality < valueOrDefault2)
									{
										flag4 = true;
									}
								}
								catch
								{
									flag4 = false;
								}
								bool flag5 = false;
								try
								{
									if (ChanceCraftRecipeHelpers.RecipeConsumesResult(val))
									{
										flag5 = true;
									}
								}
								catch
								{
									flag5 = false;
								}
								if (flag2 && (flag3 || flag4 || flag5))
								{
									flag = true;
								}
							}
							catch
							{
							}
							if (flag)
							{
								int num7 = 1;
								try
								{
									Recipe val4 = _upgradeGuiRecipe ?? ChanceCraftRecipeHelpers.FindBestUpgradeRecipeCandidate(val) ?? val;
									if (_upgradeTargetItem != null)
									{
										int valueOrDefault3 = (val4?.m_item?.m_itemData?.m_quality).GetValueOrDefault();
										num7 = Math.Max(1, valueOrDefault3 - _upgradeTargetItem.m_quality);
									}
									else
									{
										FieldInfo field8 = typeof(InventoryGui).GetField("m_craftUpgrade", BindingFlags.Instance | BindingFlags.NonPublic);
										if (field8 != null)
										{
											object value8 = field8.GetValue(__instance);
											if (value8 is int)
											{
												int num8 = (int)value8;
												if (num8 > 0)
												{
													num7 = num8;
												}
											}
										}
									}
								}
								catch
								{
									num7 = 1;
								}
								List<(string, int)> list2 = new List<(string, int)>();
								Recipe val5 = ChanceCraftRecipeHelpers.FindBestUpgradeRecipeCandidate(val);
								foreach (var item11 in requirements)
								{
									int item3 = item11.Item2;
									int item4 = item3;
									if (num7 > 1 && item3 > 0 && item3 % num7 == 0)
									{
										item4 = item3 / num7;
									}
									else if ((Object)(object)val5 != (Object)null)
									{
										try
										{
											if (((object)val5).GetType().GetField("m_resources", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(val5) is IEnumerable enumerable3)
											{
												foreach (object item12 in enumerable3)
												{
													try
													{
														Type type3 = item12.GetType();
														object obj24 = type3.GetField("m_resItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(item12);
														string text3 = null;
														if (obj24 != null)
														{
															object obj25 = obj24.GetType().GetField("m_itemData", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj24);
															object obj26 = obj25?.GetType().GetField("m_shared", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj25);
															text3 = obj26?.GetType().GetField("m_name", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj26) as string;
														}
														if (string.IsNullOrEmpty(text3) || !string.Equals(text3, item11.Item1, StringComparison.OrdinalIgnoreCase))
														{
															continue;
														}
														object obj27 = type3.GetField("m_amountPerLevel", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(item12);
														if (obj27 != null)
														{
															int num9 = Convert.ToInt32(obj27);
															if (num9 > 0)
															{
																item4 = num9;
															}
															break;
														}
														object obj28 = type3.GetField("m_amount", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(item12);
														int num10 = ((obj28 != null) ? Convert.ToInt32(obj28) : 0);
														if (num10 > 0)
														{
															if (num7 > 1 && num10 % num7 == 0)
															{
																item4 = num10 / num7;
															}
															else if (num10 < item3)
															{
																item4 = num10;
															}
														}
														break;
													}
													catch
													{
													}
												}
											}
										}
										catch
										{
										}
									}
									list2.Add((item11.Item1, item4));
								}
								_isUpgradeDetected = true;
								_upgradeGuiRequirements = list2;
								string text4 = string.Join(", ", _upgradeGuiRequirements.Select(((string name, int amount) x) => x.name + ":" + x.amount));
								LogInfo("Prefix-DBG: GUI requirement list indicates UPGRADE -> " + text4);
							}
						}
					}
					catch (Exception arg2)
					{
						LogWarning($"Prefix try-get-reqs exception: {arg2}");
					}
					try
					{
						FieldInfo field9 = typeof(InventoryGui).GetField("m_craftUpgrade", BindingFlags.Instance | BindingFlags.NonPublic);
						if (field9 != null)
						{
							object value9 = field9.GetValue(__instance);
							if (value9 is int)
							{
								int num11 = (int)value9;
								if (num11 > 1)
								{
									_savedRecipeForCall = null;
									_isUpgradeDetected = true;
									_upgradeGuiRecipe = ChanceCraftRecipeHelpers.GetUpgradeRecipeFromGui(__instance);
									_upgradeRecipe = _upgradeRecipe ?? val;
									_upgradeTargetItem = ChanceCraftRecipeHelpers.GetSelectedInventoryItem(__instance);
									return;
								}
							}
						}
					}
					catch
					{
					}
					try
					{
						FieldInfo field10 = ((object)val).GetType().GetField("m_resources", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
						if (field10 == null || !(field10.GetValue(val) is IEnumerable enumerable4))
						{
							return;
						}
						List<object> list3 = enumerable4.Cast<object>().ToList();
						try
						{
							string text5 = val.m_item?.m_itemData?.m_shared?.m_name;
							Player localPlayer = Player.m_localPlayer;
							if (!string.IsNullOrEmpty(text5) && (Object)(object)localPlayer != (Object)null)
							{
								Inventory inventory = ((Humanoid)localPlayer).GetInventory();
								if (inventory != null)
								{
									List<ItemData> list4 = new List<ItemData>();
									Dictionary<ItemData, (int, int)> dictionary5 = new Dictionary<ItemData, (int, int)>();
									foreach (ItemData allItem in inventory.GetAllItems())
									{
										if (allItem != null && allItem.m_shared != null && allItem.m_shared.m_name == text5)
										{
											if (!list4.Contains(allItem))
											{
												list4.Add(allItem);
											}
											dictionary5[allItem] = (allItem.m_quality, allItem.m_variant);
											LogInfo("Prefix snapshot: found existing " + ChanceCraftRecipeHelpers.ItemInfo(allItem));
										}
									}
									lock (typeof(ChanceCraft))
									{
										_preCraftSnapshot = list4;
										_preCraftSnapshotData = dictionary5;
										_snapshotRecipe = val;
										try
										{
											_preCraftSnapshotHashQuality = new Dictionary<int, int>();
											foreach (ItemData item13 in list4)
											{
												if (item13 != null)
												{
													_preCraftSnapshotHashQuality[RuntimeHelpers.GetHashCode(item13)] = item13.m_quality;
												}
											}
										}
										catch
										{
											_preCraftSnapshotHashQuality = null;
										}
									}
								}
							}
						}
						catch
						{
						}
						try
						{
							string text6 = val.m_item?.m_itemData?.m_shared?.m_name;
							int valueOrDefault4 = (val.m_item?.m_itemData?.m_quality).GetValueOrDefault();
							ItemData selectedInventoryItem2 = ChanceCraftRecipeHelpers.GetSelectedInventoryItem(__instance);
							if (selectedInventoryItem2 != null && selectedInventoryItem2.m_shared != null && !string.IsNullOrEmpty(text6) && selectedInventoryItem2.m_shared.m_name == text6 && selectedInventoryItem2.m_quality < valueOrDefault4)
							{
								_isUpgradeDetected = true;
								_upgradeTargetItem = selectedInventoryItem2;
								_upgradeRecipe = _upgradeRecipe ?? val;
								_upgradeGuiRecipe = ChanceCraftRecipeHelpers.GetUpgradeRecipeFromGui(__instance) ?? val;
								_savedRecipeForCall = null;
								return;
							}
							if (!string.IsNullOrEmpty(text6) && valueOrDefault4 > 0 && (Object)(object)Player.m_localPlayer != (Object)null)
							{
								Inventory inventory2 = ((Humanoid)Player.m_localPlayer).GetInventory();
								if (inventory2 != null)
								{
									ItemData val6 = null;
									foreach (ItemData allItem2 in inventory2.GetAllItems())
									{
										if (allItem2 == null || allItem2.m_shared == null || !(allItem2.m_shared.m_name == text6) || allItem2.m_quality >= valueOrDefault4)
										{
											continue;
										}
										val6 = allItem2;
										break;
									}
									if (val6 != null)
									{
										_isUpgradeDetected = true;
										_upgradeTargetItem = val6;
										_upgradeRecipe = _upgradeRecipe ?? val;
										_upgradeGuiRecipe = ChanceCraftRecipeHelpers.GetUpgradeRecipeFromGui(__instance) ?? val;
										_savedRecipeForCall = null;
										return;
									}
								}
							}
						}
						catch
						{
						}
						try
						{
							if (ChanceCraftRecipeHelpers.RecipeConsumesResult(val))
							{
								_isUpgradeDetected = true;
								_upgradeRecipe = _upgradeRecipe ?? val;
								_upgradeGuiRecipe = ChanceCraftRecipeHelpers.GetUpgradeRecipeFromGui(__instance) ?? val;
								_savedRecipeForCall = null;
								return;
							}
						}
						catch
						{
						}
						List<object> list5 = new List<object>();
						foreach (object item14 in list3)
						{
							object obj36 = GetMember(item14, "m_resItem");
							if (obj36 != null)
							{
								string value10 = null;
								try
								{
									object obj37 = obj36.GetType().GetField("m_itemData", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj36);
									object obj38 = obj37?.GetType().GetField("m_shared", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj37);
									value10 = obj38?.GetType().GetField("m_name", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj38) as string;
								}
								catch
								{
								}
								int num12 = ToInt(GetMember(item14, "m_amount"));
								if (!string.IsNullOrEmpty(value10) && num12 > 0)
								{
									list5.Add(item14);
								}
							}
						}
						if (list5.Count <= 1)
						{
							return;
						}
						ItemType? val7 = val.m_item?.m_itemData?.m_shared?.m_itemType;
						if ((int)val7.GetValueOrDefault() != 3 && (int)val7.GetValueOrDefault() != 14 && (int)val7.GetValueOrDefault() != 4 && (int)val7.GetValueOrDefault() != 22 && (int)val7.GetValueOrDefault() != 5 && (int)val7.GetValueOrDefault() != 6 && (int)val7.GetValueOrDefault() != 7 && (int)val7.GetValueOrDefault() != 11 && (int)val7.GetValueOrDefault() != 9)
						{
							return;
						}
						lock (_savedResourcesLock)
						{
							string recipeKey = GetRecipeKey(val);
							if (!string.IsNullOrEmpty(recipeKey))
							{
								lock (_savedResourcesLock)
								{
									if (!_savedResources.ContainsKey(recipeKey))
									{
										_savedResources[recipeKey] = enumerable4;
									}
								}
							}
						}
						try
						{
							string item5 = ChanceCraftRecipeHelpers.RecipeFingerprint(val);
							lock (_suppressedRecipeKeysLock)
							{
								if (!_suppressedRecipeKeys.Contains(item5))
								{
									_suppressedRecipeKeys.Add(item5);
								}
							}
						}
						catch
						{
						}
						try
						{
							Type fieldType = field10.FieldType;
							object obj41 = null;
							if (fieldType.IsArray)
							{
								obj41 = Array.CreateInstance(fieldType.GetElementType(), 0);
							}
							else if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(List<>))
							{
								obj41 = Activator.CreateInstance(fieldType);
							}
							if (obj41 != null)
							{
								field10.SetValue(val, obj41);
								_suppressedThisCall = true;
								IsDoCraft = true;
							}
						}
						catch
						{
						}
					}
					catch (Exception arg3)
					{
						LogWarning($"Prefix snapshot/build exception: {arg3}");
					}
				}
				catch (Exception arg4)
				{
					LogWarning($"Prefix outer exception: {arg4}");
					_suppressedThisCall = false;
					_savedRecipeForCall = null;
					IsDoCraft = false;
				}
				static object GetMember(object obj, string name)
				{
					if (obj == null)
					{
						return null;
					}
					Type type4 = obj.GetType();
					FieldInfo field11 = type4.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (field11 != null)
					{
						return field11.GetValue(obj);
					}
					PropertyInfo property2 = type4.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (property2 != null)
					{
						return property2.GetValue(obj);
					}
					return null;
				}
				static int ToInt(object v)
				{
					if (v != null)
					{
						try
						{
							return Convert.ToInt32(v);
						}
						catch
						{
							return 0;
						}
					}
					return 0;
				}
			}

			private static void Postfix(InventoryGui __instance, Player player)
			{
				try
				{
					if ((Object)(object)_savedRecipeForCall != (Object)null && _suppressedThisCall)
					{
						lock (_savedResourcesLock)
						{
							string recipeKey = GetRecipeKey(_savedRecipeForCall);
							if (!string.IsNullOrEmpty(recipeKey) && _savedResources.TryGetValue(recipeKey, out var value))
							{
								try
								{
									FieldInfo field = ((object)_savedRecipeForCall).GetType().GetField("m_resources", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
									if (field != null)
									{
										field.SetValue(_savedRecipeForCall, value);
									}
								}
								catch
								{
								}
								_savedResources.Remove(recipeKey);
							}
						}
					}
					if (!_suppressedThisCall)
					{
						_suppressedThisCall = false;
						_savedRecipeForCall = null;
						IsDoCraft = false;
						return;
					}
					Recipe savedRecipeForCall = _savedRecipeForCall;
					_suppressedThisCall = false;
					_savedRecipeForCall = null;
					IsDoCraft = false;
					try
					{
						if (_isUpgradeDetected || ChanceCraftRecipeHelpers.IsUpgradeOperation(__instance, savedRecipeForCall))
						{
							if ((Object)(object)_upgradeGuiRecipe == (Object)null)
							{
								_upgradeGuiRecipe = ChanceCraftRecipeHelpers.GetUpgradeRecipeFromGui(__instance);
							}
							if (_upgradeTargetItem == null)
							{
								_upgradeTargetItem = ChanceCraftRecipeHelpers.GetSelectedInventoryItem(__instance);
							}
							Recipe val = TrySpawnCraftEffect(__instance, savedRecipeForCall, isUpgradeCall: true);
							if ((Object)(object)val == (Object)null)
							{
								try
								{
									if ((Object)(object)savedRecipeForCall != (Object)null)
									{
										string item = ChanceCraftRecipeHelpers.RecipeFingerprint(savedRecipeForCall);
										lock (_suppressedRecipeKeysLock)
										{
											_suppressedRecipeKeys.Remove(item);
										}
									}
									if ((Object)(object)_upgradeGuiRecipe != (Object)null)
									{
										string item2 = ChanceCraftRecipeHelpers.RecipeFingerprint(_upgradeGuiRecipe);
										lock (_suppressedRecipeKeysLock)
										{
											_suppressedRecipeKeys.Remove(item2);
										}
									}
								}
								catch
								{
								}
								lock (typeof(ChanceCraft))
								{
									_preCraftSnapshot = null;
									_preCraftSnapshotData = null;
									_snapshotRecipe = null;
								}
								_upgradeTargetItem = null;
								_upgradeRecipe = null;
								_upgradeGuiRecipe = null;
								_isUpgradeDetected = false;
								return;
							}
						}
						Recipe val2 = TrySpawnCraftEffect(__instance, savedRecipeForCall);
						if (!((Object)(object)player != (Object)null) || !((Object)(object)val2 != (Object)null))
						{
							return;
						}
						try
						{
							List<ItemData> list = null;
							lock (typeof(ChanceCraft))
							{
								if ((Object)(object)_snapshotRecipe != (Object)null && (Object)(object)_snapshotRecipe == (Object)(object)val2)
								{
									list = _preCraftSnapshot;
								}
								_preCraftSnapshot = null;
								_preCraftSnapshotData = null;
								_snapshotRecipe = null;
							}
							int num = ((val2.m_amount <= 0) ? 1 : val2.m_amount);
							Inventory inventory = ((Humanoid)player).GetInventory();
							List<ItemData> list2 = ((inventory != null) ? inventory.GetAllItems() : null);
							if (list2 == null)
							{
								return;
							}
							int num2 = 0;
							int num3 = list2.Count - 1;
							while (num3 >= 0 && num > 0)
							{
								ItemData val3 = list2[num3];
								if (val3 != null && val3.m_shared != null)
								{
									string text = val2.m_item?.m_itemData?.m_shared?.m_name;
									int valueOrDefault = (val2.m_item?.m_itemData?.m_quality).GetValueOrDefault();
									int valueOrDefault2 = (val2.m_item?.m_itemData?.m_variant).GetValueOrDefault();
									if (val3.m_shared.m_name == text && val3.m_quality == valueOrDefault && val3.m_variant == valueOrDefault2 && val3 != _upgradeTargetItem && (list == null || !list.Contains(val3)))
									{
										int num4 = Math.Min(val3.m_stack, num);
										val3.m_stack -= num4;
										num -= num4;
										num2 += num4;
										if (val3.m_stack <= 0)
										{
											((Humanoid)player).GetInventory().RemoveItem(val3);
										}
									}
								}
								num3--;
							}
							if (num <= 0 || (list != null && num2 == 0))
							{
								return;
							}
							int num5 = list2.Count - 1;
							while (num5 >= 0 && num > 0)
							{
								ItemData val4 = list2[num5];
								if (val4 != null && val4.m_shared != null)
								{
									string text2 = val2.m_item?.m_itemData?.m_shared?.m_name;
									int valueOrDefault3 = (val2.m_item?.m_itemData?.m_quality).GetValueOrDefault();
									int valueOrDefault4 = (val2.m_item?.m_itemData?.m_variant).GetValueOrDefault();
									if (val4.m_shared.m_name == text2 && val4.m_quality == valueOrDefault3 && val4.m_variant == valueOrDefault4 && val4 != _upgradeTargetItem)
									{
										int num6 = Math.Min(val4.m_stack, num);
										val4.m_stack -= num6;
										num -= num6;
										if (val4.m_stack <= 0)
										{
											((Humanoid)player).GetInventory().RemoveItem(val4);
										}
									}
								}
								num5--;
							}
						}
						catch (Exception arg)
						{
							LogWarning($"Postfix removal exception: {arg}");
						}
					}
					catch (Exception arg2)
					{
						LogWarning($"Postfix logic exception: {arg2}");
					}
				}
				catch (Exception arg3)
				{
					LogWarning($"Postfix outer exception: {arg3}");
					_suppressedThisCall = false;
					_savedRecipeForCall = null;
					IsDoCraft = false;
				}
			}
		}

		public const string pluginID = "deep.ChanceCraft";

		public const string pluginName = "Chance Craft";

		public const string pluginVersion = "1.1.5";

		private Harmony _harmony;

		internal static ConfigEntry<float> weaponSuccessChance;

		internal static ConfigEntry<float> armorSuccessChance;

		internal static ConfigEntry<float> arrowSuccessChance;

		internal static ConfigEntry<float> weaponSuccessUpgrade;

		internal static ConfigEntry<float> armorSuccessUpgrade;

		internal static ConfigEntry<float> arrowSuccessUpgrade;

		internal static ConfigEntry<bool> loggingEnabled;

		private ConfigEntry<float> line1_increase;

		private ConfigEntry<string> line1_item;

		private ConfigEntry<float> line2_increase;

		private ConfigEntry<string> line2_item;

		private ConfigEntry<float> line3_increase;

		private ConfigEntry<string> line3_item;

		private ConfigEntry<float> line4_increase;

		private ConfigEntry<string> line4_item;

		private ConfigEntry<float> line5_increase;

		private ConfigEntry<string> line5_item;

		internal static bool IsDoCraft;

		internal static List<ItemData> _preCraftSnapshot;

		internal static Recipe _snapshotRecipe;

		internal static Dictionary<ItemData, (int quality, int variant)> _preCraftSnapshotData;

		internal static Dictionary<int, int> _preCraftSnapshotHashQuality;

		internal static List<string> _suppressedRecipeKeys = new List<string>();

		internal static readonly object _suppressedRecipeKeysLock = new object();

		internal static readonly HashSet<string> _recentRemovalKeys = new HashSet<string>();

		internal static readonly object _recentRemovalKeysLock = new object();

		internal static ItemData _upgradeTargetItem;

		internal static Recipe _upgradeRecipe;

		internal static Recipe _upgradeGuiRecipe;

		internal static bool _isUpgradeDetected;

		internal static int _upgradeTargetItemIndex = -1;

		internal static List<(string name, int amount)> _upgradeGuiRequirements;

		internal static bool VERBOSE_DEBUG = false;

		internal static readonly object _savedResourcesLock = new object();

		private void Awake()
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Expected O, but got Unknown
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected O, but got Unknown
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Expected O, but got Unknown
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Expected O, but got Unknown
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Expected O, but got Unknown
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Expected O, but got Unknown
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Expected O, but got Unknown
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Expected O, but got Unknown
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Expected O, but got Unknown
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Expected O, but got Unknown
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Expected O, but got Unknown
			//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e2: Expected O, but got Unknown
			//IL_0308: Unknown result type (might be due to invalid IL or missing references)
			//IL_0312: Expected O, but got Unknown
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			//IL_0350: Expected O, but got Unknown
			//IL_0376: Unknown result type (might be due to invalid IL or missing references)
			//IL_0380: Expected O, but got Unknown
			_harmony = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "ChanceCraft");
			loggingEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Logging", "Logging Enabled", true, "Enable logging");
			weaponSuccessChance = ((BaseUnityPlugin)this).Config.Bind<float>("General", "WeaponSuccessChance", 0.6f, new ConfigDescription("Chance to successfully craft weapons (0.0 - 1.0)", (AcceptableValueBase)null, Array.Empty<object>()));
			armorSuccessChance = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ArmorSuccessChance", 0.6f, new ConfigDescription("Chance to successfully craft armors (0.0 - 1.0)", (AcceptableValueBase)null, Array.Empty<object>()));
			arrowSuccessChance = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ArrowSuccessChance", 0.6f, new ConfigDescription("Chance to successfully craft arrows (0.0 - 1.0)", (AcceptableValueBase)null, Array.Empty<object>()));
			weaponSuccessUpgrade = ((BaseUnityPlugin)this).Config.Bind<float>("General", "WeaponSuccessUpgrade", weaponSuccessChance.Value, new ConfigDescription("Chance to successfully upgrade weapons (0.0 - 1.0)", (AcceptableValueBase)null, Array.Empty<object>()));
			armorSuccessUpgrade = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ArmorSuccessUpgrade", armorSuccessChance.Value, new ConfigDescription("Chance to successfully upgrade armors (0.0 - 1.0)", (AcceptableValueBase)null, Array.Empty<object>()));
			arrowSuccessUpgrade = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ArrowSuccessUpgrade", arrowSuccessChance.Value, new ConfigDescription("Chance to successfully upgrade arrows (0.0 - 1.0)", (AcceptableValueBase)null, Array.Empty<object>()));
			line1_increase = ((BaseUnityPlugin)this).Config.Bind<float>("ChanceCraft.Line1", "increase craft percentage", 0.05f, new ConfigDescription("Line1: Increase craft percentage (0.05 = 5%). Range 0.0 - 1.0", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			line1_item = ((BaseUnityPlugin)this).Config.Bind<string>("ChanceCraft.Line1", "item prefab", "KnifeFlint", new ConfigDescription("Line1: Valheim prefab name for the item (e.g. KnifeFlint). Leave empty to disable this line.", (AcceptableValueBase)null, Array.Empty<object>()));
			line2_increase = ((BaseUnityPlugin)this).Config.Bind<float>("ChanceCraft.Line2", "increase craft percentage", 0.1f, new ConfigDescription("Line2: Increase craft percentage (0.1 = 10%).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			line2_item = ((BaseUnityPlugin)this).Config.Bind<string>("ChanceCraft.Line2", "item prefab", string.Empty, new ConfigDescription("Line2: Valheim prefab name for the item. Leave empty to disable this line.", (AcceptableValueBase)null, Array.Empty<object>()));
			line3_increase = ((BaseUnityPlugin)this).Config.Bind<float>("ChanceCraft.Line3", "increase craft percentage", 0.15f, new ConfigDescription("Line3: Increase craft percentage (0.15 = 15%).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			line3_item = ((BaseUnityPlugin)this).Config.Bind<string>("ChanceCraft.Line3", "item prefab", string.Empty, new ConfigDescription("Line3: Valheim prefab name for the item. Leave empty to disable this line.", (AcceptableValueBase)null, Array.Empty<object>()));
			line4_increase = ((BaseUnityPlugin)this).Config.Bind<float>("ChanceCraft.Line4", "increase craft percentage", 0.2f, new ConfigDescription("Line4: Increase craft percentage (0.2 = 20%).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			line4_item = ((BaseUnityPlugin)this).Config.Bind<string>("ChanceCraft.Line4", "item prefab", string.Empty, new ConfigDescription("Line4: Valheim prefab name for the item. Leave empty to disable this line.", (AcceptableValueBase)null, Array.Empty<object>()));
			line5_increase = ((BaseUnityPlugin)this).Config.Bind<float>("ChanceCraft.Line5", "increase craft percentage", 0.3f, new ConfigDescription("Line5: Increase craft percentage (0.3 = 30%).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			line5_item = ((BaseUnityPlugin)this).Config.Bind<string>("ChanceCraft.Line5", "item prefab", string.Empty, new ConfigDescription("Line5: Valheim prefab name for the item. Leave empty to disable this line.", (AcceptableValueBase)null, Array.Empty<object>()));
			((BaseUnityPlugin)this).Logger.LogInfo((object)"ChanceCraft configured lines:");
			foreach (ChanceCraftLine configuredLine in GetConfiguredLines())
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("- prefab='{0}' increase={1} active={2}", configuredLine.ItemPrefab ?? "<empty>", configuredLine.IncreaseCraftPercentage, configuredLine.IsActive));
			}
			LogInfo($"ChanceCraft loaded: craft weapon={weaponSuccessChance.Value}, armor={armorSuccessChance.Value}, arrow={arrowSuccessChance.Value}; upgrade weapon={weaponSuccessUpgrade.Value}, armor={armorSuccessUpgrade.Value}, arrow={arrowSuccessUpgrade.Value}");
			Game.isModded = true;
		}

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

		public static void LogWarning(string msg)
		{
			ConfigEntry<bool> obj = loggingEnabled;
			if (obj != null && obj.Value)
			{
				Debug.LogWarning((object)("[ChanceCraft] " + msg));
			}
		}

		public static void LogInfo(string msg)
		{
			ConfigEntry<bool> obj = loggingEnabled;
			if (obj != null && obj.Value)
			{
				Debug.Log((object)("[ChanceCraft] " + msg));
			}
		}

		public static void LogDebugIf(bool cond, string msg)
		{
			if (cond)
			{
				LogInfo(msg);
			}
		}

		private void TryValidatePrefabs()
		{
			try
			{
				if ((Object)(object)ZNetScene.instance == (Object)null)
				{
					return;
				}
				foreach (ChanceCraftLine item in from l in GetConfiguredLines()
					where l.IsActive
					select l)
				{
					GameObject prefab = ZNetScene.instance.GetPrefab(item.ItemPrefab);
					if ((Object)(object)prefab == (Object)null)
					{
						((BaseUnityPlugin)this).Logger.LogWarning((object)("ChanceCraft: configured prefab '" + item.ItemPrefab + "' not found in ZNetScene. This line will not match at runtime."));
					}
				}
			}
			catch
			{
			}
		}

		public List<ChanceCraftLine> GetConfiguredLines()
		{
			return new List<ChanceCraftLine>
			{
				new ChanceCraftLine
				{
					IncreaseCraftPercentage = line1_increase.Value,
					ItemPrefab = line1_item.Value
				},
				new ChanceCraftLine
				{
					IncreaseCraftPercentage = line2_increase.Value,
					ItemPrefab = line2_item.Value
				},
				new ChanceCraftLine
				{
					IncreaseCraftPercentage = line3_increase.Value,
					ItemPrefab = line3_item.Value
				},
				new ChanceCraftLine
				{
					IncreaseCraftPercentage = line4_increase.Value,
					ItemPrefab = line4_item.Value
				},
				new ChanceCraftLine
				{
					IncreaseCraftPercentage = line5_increase.Value,
					ItemPrefab = line5_item.Value
				}
			};
		}

		public float GetAdditionalChanceForPrefab(string craftedPrefab)
		{
			if (string.IsNullOrWhiteSpace(craftedPrefab))
			{
				return 0f;
			}
			float num = 0f;
			foreach (ChanceCraftLine configuredLine in GetConfiguredLines())
			{
				if (configuredLine.IsActive && configuredLine.ItemPrefab == craftedPrefab)
				{
					num += configuredLine.IncreaseCraftPercentage;
				}
			}
			return Mathf.Clamp01(num);
		}

		public float ApplyExtraChanceToBase(string craftedPrefab, float baseChance)
		{
			float additionalChanceForPrefab = GetAdditionalChanceForPrefab(craftedPrefab);
			float num = baseChance + additionalChanceForPrefab;
			return Mathf.Clamp01(num);
		}

		private static string TryGetPrefabNameFromInventoryGui(InventoryGui gui)
		{
			if ((Object)(object)gui == (Object)null)
			{
				return null;
			}
			string[] array = new string[6] { "m_selectedItem", "m_selected", "m_selectedPiece", "m_craftPrefab", "m_currentItem", "m_item" };
			string[] array2 = array;
			foreach (string name in array2)
			{
				FieldInfo field = GetField(((object)gui).GetType(), name);
				if (field != null)
				{
					object value = field.GetValue(gui);
					string text = ExtractPrefabNameFromObject(value);
					if (!string.IsNullOrWhiteSpace(text))
					{
						return text;
					}
				}
				PropertyInfo property = GetProperty(((object)gui).GetType(), name);
				if (property != null)
				{
					object value2 = property.GetValue(gui);
					string text2 = ExtractPrefabNameFromObject(value2);
					if (!string.IsNullOrWhiteSpace(text2))
					{
						return text2;
					}
				}
			}
			FieldInfo[] fields = ((object)gui).GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			FieldInfo[] array3 = fields;
			foreach (FieldInfo fieldInfo in array3)
			{
				try
				{
					object value3 = fieldInfo.GetValue(gui);
					string text3 = ExtractPrefabNameFromObject(value3);
					if (!string.IsNullOrWhiteSpace(text3))
					{
						return text3;
					}
				}
				catch
				{
				}
			}
			PropertyInfo[] properties = ((object)gui).GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			PropertyInfo[] array4 = properties;
			foreach (PropertyInfo propertyInfo in array4)
			{
				try
				{
					if (propertyInfo.GetIndexParameters().Length == 0)
					{
						object value4 = propertyInfo.GetValue(gui);
						string text4 = ExtractPrefabNameFromObject(value4);
						if (!string.IsNullOrWhiteSpace(text4))
						{
							return text4;
						}
					}
				}
				catch
				{
				}
			}
			return null;
		}

		private static ItemType? TryGetItemTypeFromInventoryGui(InventoryGui gui)
		{
			if ((Object)(object)gui == (Object)null)
			{
				return null;
			}
			FieldInfo[] fields = ((object)gui).GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			FieldInfo[] array = fields;
			foreach (FieldInfo fieldInfo in array)
			{
				try
				{
					object value = fieldInfo.GetValue(gui);
					ItemType? result = ExtractItemTypeFromObject(value);
					if (result.HasValue)
					{
						return result;
					}
				}
				catch
				{
				}
			}
			PropertyInfo[] properties = ((object)gui).GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			PropertyInfo[] array2 = properties;
			foreach (PropertyInfo propertyInfo in array2)
			{
				try
				{
					if (propertyInfo.GetIndexParameters().Length == 0)
					{
						object value2 = propertyInfo.GetValue(gui);
						ItemType? result2 = ExtractItemTypeFromObject(value2);
						if (result2.HasValue)
						{
							return result2;
						}
					}
				}
				catch
				{
				}
			}
			return null;
		}

		private static string ExtractPrefabNameFromObject(object obj)
		{
			if (obj == null)
			{
				return null;
			}
			GameObject val = (GameObject)((obj is GameObject) ? obj : null);
			if (val != null)
			{
				return ((Object)val).name.Replace("(Clone)", "");
			}
			PropertyInfo property = obj.GetType().GetProperty("gameObject", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (property != null)
			{
				try
				{
					object? value = property.GetValue(obj);
					GameObject val2 = (GameObject)((value is GameObject) ? value : null);
					if ((Object)(object)val2 != (Object)null)
					{
						return ((Object)val2).name.Replace("(Clone)", "");
					}
				}
				catch
				{
				}
			}
			FieldInfo field = obj.GetType().GetField("m_dropPrefab", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null)
			{
				try
				{
					object? value2 = field.GetValue(obj);
					GameObject val3 = (GameObject)((value2 is GameObject) ? value2 : null);
					if ((Object)(object)val3 != (Object)null)
					{
						return ((Object)val3).name.Replace("(Clone)", "");
					}
				}
				catch
				{
				}
			}
			PropertyInfo property2 = obj.GetType().GetProperty("m_dropPrefab", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (property2 != null)
			{
				try
				{
					object? value3 = property2.GetValue(obj);
					GameObject val4 = (GameObject)((value3 is GameObject) ? value3 : null);
					if ((Object)(object)val4 != (Object)null)
					{
						return ((Object)val4).name.Replace("(Clone)", "");
					}
				}
				catch
				{
				}
			}
			FieldInfo field2 = obj.GetType().GetField("m_itemData", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field2 != null)
			{
				try
				{
					object value4 = field2.GetValue(obj);
					if (value4 != null)
					{
						FieldInfo field3 = value4.GetType().GetField("m_dropPrefab", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
						if (field3 != null)
						{
							object? value5 = field3.GetValue(value4);
							GameObject val5 = (GameObject)((value5 is GameObject) ? value5 : null);
							if ((Object)(object)val5 != (Object)null)
							{
								return ((Object)val5).name.Replace("(Clone)", "");
							}
						}
						PropertyInfo property3 = value4.GetType().GetProperty("m_dropPrefab", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
						if (property3 != null)
						{
							object? value6 = property3.GetValue(value4);
							GameObject val6 = (GameObject)((value6 is GameObject) ? value6 : null);
							if ((Object)(object)val6 != (Object)null)
							{
								return ((Object)val6).name.Replace("(Clone)", "");
							}
						}
					}
				}
				catch
				{
				}
			}
			FieldInfo field4 = obj.GetType().GetField("name", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field4 != null)
			{
				try
				{
					string text = field4.GetValue(obj) as string;
					if (!string.IsNullOrWhiteSpace(text))
					{
						return text.Replace("(Clone)", "");
					}
				}
				catch
				{
				}
			}
			PropertyInfo property4 = obj.GetType().GetProperty("name", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (property4 != null)
			{
				try
				{
					string text2 = property4.GetValue(obj) as string;
					if (!string.IsNullOrWhiteSpace(text2))
					{
						return text2.Replace("(Clone)", "");
					}
				}
				catch
				{
				}
			}
			return null;
		}

		private static ItemType? ExtractItemTypeFromObject(object obj)
		{
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			if (obj == null)
			{
				return null;
			}
			if (obj.GetType().Name == "ItemDrop" || obj.GetType().Name == "ItemDrop+ItemData" || obj.GetType().Name == "ItemDrop.ItemData")
			{
				FieldInfo field = obj.GetType().GetField("m_shared", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					try
					{
						object value = field.GetValue(obj);
						if (value != null)
						{
							FieldInfo field2 = value.GetType().GetField("m_itemType", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
							if (field2 != null && field2.GetValue(value) is ItemType value2)
							{
								return value2;
							}
							PropertyInfo property = value.GetType().GetProperty("m_itemType", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
							if (property != null)
							{
								object value3 = property.GetValue(value);
								if (value3 is ItemType)
								{
									ItemType value4 = (ItemType)value3;
									if (true)
									{
										return value4;
									}
								}
							}
						}
					}
					catch
					{
					}
				}
				FieldInfo field3 = obj.GetType().GetField("m_itemType", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field3 != null)
				{
					try
					{
						object value5 = field3.GetValue(obj);
						if (value5 is ItemType)
						{
							ItemType value6 = (ItemType)value5;
							if (true)
							{
								return value6;
							}
						}
					}
					catch
					{
					}
				}
				PropertyInfo property2 = obj.GetType().GetProperty("m_itemType", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (property2 != null)
				{
					try
					{
						object value7 = property2.GetValue(obj);
						if (value7 is ItemType)
						{
							ItemType value8 = (ItemType)value7;
							if (true)
							{
								return value8;
							}
						}
					}
					catch
					{
					}
				}
			}
			GameObject val = (GameObject)((obj is GameObject) ? obj : null);
			if (val != null)
			{
				try
				{
					ItemDrop component = val.GetComponent<ItemDrop>();
					if ((Object)(object)component != (Object)null)
					{
						PropertyInfo property3 = ((object)component).GetType().GetProperty("m_itemData", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
						if (property3 != null)
						{
							object value9 = property3.GetValue(component);
							ItemType? result = ExtractItemTypeFromObject(value9);
							if (result.HasValue)
							{
								return result;
							}
						}
					}
				}
				catch
				{
				}
			}
			FieldInfo field4 = obj.GetType().GetField("m_itemData", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field4 != null)
			{
				try
				{
					object value10 = field4.GetValue(obj);
					ItemType? result2 = ExtractItemTypeFromObject(value10);
					if (result2.HasValue)
					{
						return result2;
					}
				}
				catch
				{
				}
			}
			PropertyInfo property4 = obj.GetType().GetProperty("m_itemData", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (property4 != null)
			{
				try
				{
					object value11 = property4.GetValue(obj);
					ItemType? result3 = ExtractItemTypeFromObject(value11);
					if (result3.HasValue)
					{
						return result3;
					}
				}
				catch
				{
				}
			}
			return null;
		}

		private static FieldInfo GetField(Type t, string name)
		{
			while (t != null)
			{
				FieldInfo field = t.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					return field;
				}
				t = t.BaseType;
			}
			return null;
		}

		private static PropertyInfo GetProperty(Type t, string name)
		{
			while (t != null)
			{
				PropertyInfo property = t.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (property != null)
				{
					return property;
				}
				t = t.BaseType;
			}
			return null;
		}

		private static void ClearCapturedUpgradeGui()
		{
			try
			{
				_upgradeGuiRecipe = null;
				_upgradeGuiRequirements = null;
				_upgradeRecipe = null;
				_upgradeTargetItem = null;
			}
			catch
			{
			}
		}

		public static Recipe TrySpawnCraftEffect(InventoryGui gui, Recipe forcedRecipe = null, bool isUpgradeCall = false)
		{
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Invalid comparison between Unknown and I4
			//IL_0928: Unknown result type (might be due to invalid IL or missing references)
			//IL_092e: Invalid comparison between Unknown and I4
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Invalid comparison between Unknown and I4
			//IL_0932: Unknown result type (might be due to invalid IL or missing references)
			//IL_0939: Invalid comparison between Unknown and I4
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Invalid comparison between Unknown and I4
			//IL_093d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0943: Invalid comparison between Unknown and I4
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Invalid comparison between Unknown and I4
			//IL_0977: Unknown result type (might be due to invalid IL or missing references)
			//IL_097d: Invalid comparison between Unknown and I4
			//IL_0947: Unknown result type (might be due to invalid IL or missing references)
			//IL_094e: Invalid comparison between Unknown and I4
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Invalid comparison between Unknown and I4
			//IL_0981: Unknown result type (might be due to invalid IL or missing references)
			//IL_0987: Invalid comparison between Unknown and I4
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Invalid comparison between Unknown and I4
			//IL_098b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0991: Invalid comparison between Unknown and I4
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Invalid comparison between Unknown and I4
			//IL_09c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_09cc: Invalid comparison between Unknown and I4
			//IL_0995: Unknown result type (might be due to invalid IL or missing references)
			//IL_099c: Invalid comparison between Unknown and I4
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Invalid comparison between Unknown and I4
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Invalid comparison between Unknown and I4
			//IL_0cba: Unknown result type (might be due to invalid IL or missing references)
			//IL_0cc7: Unknown result type (might be due to invalid IL or missing references)
			Recipe val = forcedRecipe;
			if ((Object)(object)val == (Object)null)
			{
				FieldInfo field = typeof(InventoryGui).GetField("m_selectedRecipe", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					object value = field.GetValue(gui);
					if (value != null && value.GetType().Name == "RecipeDataPair")
					{
						PropertyInfo property = value.GetType().GetProperty("Recipe", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
						if (property != null)
						{
							object? value2 = property.GetValue(value);
							val = (Recipe)((value2 is Recipe) ? value2 : null);
						}
					}
					else
					{
						val = (Recipe)((value is Recipe) ? value : null);
					}
				}
			}
			if ((Object)(object)val == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				return null;
			}
			ItemType? val2 = null;
			try
			{
				val2 = val.m_item?.m_itemData?.m_shared?.m_itemType;
				bool vERBOSE_DEBUG = VERBOSE_DEBUG;
				object obj2;
				if (!val2.HasValue)
				{
					obj2 = "<null>";
				}
				else
				{
					ItemType value3 = val2.Value;
					obj2 = ((object)(ItemType)(ref value3)).ToString();
				}
				LogDebugIf(vERBOSE_DEBUG, "Extracted itemType = " + (string?)obj2);
			}
			catch (Exception ex)
			{
				LogWarning("Failed to extract itemType via direct access: " + ex);
				val2 = null;
			}
			bool flag = (int)val2.GetValueOrDefault() == 3 || (int)val2.GetValueOrDefault() == 14 || (int)val2.GetValueOrDefault() == 4 || (int)val2.GetValueOrDefault() == 22 || (int)val2.GetValueOrDefault() == 5 || (int)val2.GetValueOrDefault() == 6 || (int)val2.GetValueOrDefault() == 7 || (int)val2.GetValueOrDefault() == 11 || (int)val2.GetValueOrDefault() == 9;
			LogDebugIf(VERBOSE_DEBUG, $"isEligibleType = {flag}");
			if (!flag)
			{
				LogDebugIf(VERBOSE_DEBUG, "Item type is not eligible for ChanceCraft -> skipping plugin logic.");
				return null;
			}
			float num = 0f;
			bool flag2 = false;
			ChanceCraft component = Chainloader.ManagerObject.GetComponent<ChanceCraft>();
			if ((Object)(object)component == (Object)null)
			{
				LogWarning("ChanceCraft plugin instance not found (plugin == null). Can't access configured lines. Skipping inventory boost checks.");
			}
			else
			{
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer == (Object)null)
				{
					LogWarning("Player.m_localPlayer is null; cannot check inventory.");
				}
				else
				{
					Inventory inv = ((Humanoid)localPlayer).GetInventory();
					if (inv == null)
					{
						LogWarning("Player inventory (GetInventory()) returned null.");
					}
					else
					{
						IEnumerable enumerable = null;
						MethodInfo method = ((object)inv).GetType().GetMethod("GetAllItems", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
						if (method != null)
						{
							try
							{
								enumerable = (IEnumerable)method.Invoke(inv, null);
								LogDebugIf(VERBOSE_DEBUG, "Obtained inventory items via GetAllItems().");
							}
							catch (Exception ex2)
							{
								LogWarning("GetAllItems() invocation failed: " + ex2);
								enumerable = null;
							}
						}
						if (enumerable == null)
						{
							FieldInfo fieldInfo = ((object)inv).GetType().GetField("m_inventory", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? ((object)inv).GetType().GetField("m_items", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
							if (fieldInfo != null)
							{
								try
								{
									enumerable = fieldInfo.GetValue(inv) as IEnumerable;
									LogDebugIf(VERBOSE_DEBUG, "Obtained inventory items via field '" + fieldInfo.Name + "'.");
								}
								catch (Exception ex3)
								{
									LogWarning("Accessing inventory field failed: " + ex3);
									enumerable = null;
								}
							}
							else
							{
								LogDebugIf(VERBOSE_DEBUG, "No inventory field found (m_inventory / m_items).");
							}
						}
						if (enumerable == null)
						{
							LogWarning("Failed to enumerate inventory items (invItems == null).");
						}
						else
						{
							string text = null;
							string text2 = null;
							try
							{
								text = val.m_item?.m_itemData?.m_shared?.m_name;
								if (!string.IsNullOrWhiteSpace(text))
								{
									text2 = text;
								}
							}
							catch
							{
								text = null;
								text2 = null;
							}
							try
							{
								GameObject val3 = val.m_item?.m_itemData?.m_dropPrefab;
								if ((Object)(object)val3 != (Object)null)
								{
									string text3 = ((Object)val3).name?.Replace("(Clone)", "");
									if (!string.IsNullOrWhiteSpace(text3))
									{
										text2 = text2 ?? text3;
									}
								}
							}
							catch
							{
							}
							Func<string, string> func = delegate(string s)
							{
								if (string.IsNullOrEmpty(s))
								{
									return s;
								}
								string text21 = s.Trim();
								if (text21.StartsWith("$"))
								{
									text21 = text21.Substring(1);
								}
								if (text21.StartsWith("item_", StringComparison.OrdinalIgnoreCase))
								{
									text21 = text21.Substring(5);
								}
								text21 = text21.Replace("(Clone)", "");
								return text21.Replace("_", "").Replace("-", "").Replace(" ", "")
									.ToLowerInvariant();
							};
							string text4 = func(text2);
							List<ItemData> list = null;
							try
							{
								lock (typeof(ChanceCraft))
								{
									if (_preCraftSnapshot != null)
									{
										list = new List<ItemData>(_preCraftSnapshot);
									}
								}
							}
							catch
							{
								list = null;
							}
							Func<object, string> func2 = delegate(object obj)
							{
								if (obj == null)
								{
									return null;
								}
								try
								{
									Type type2 = obj.GetType();
									FieldInfo field5 = type2.GetField("m_shared", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
									object obj35 = ((field5 != null) ? field5.GetValue(obj) : null);
									if (obj35 != null)
									{
										Type type3 = obj35.GetType();
										FieldInfo field6 = type3.GetField("m_dropPrefab", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
										if (field6 != null)
										{
											object? value9 = field6.GetValue(obj35);
											GameObject val15 = (GameObject)((value9 is GameObject) ? value9 : null);
											if ((Object)(object)val15 != (Object)null)
											{
												return ((Object)val15).name.Replace("(Clone)", "");
											}
										}
										PropertyInfo property3 = type3.GetProperty("m_dropPrefab", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
										if (property3 != null)
										{
											object? value10 = property3.GetValue(obj35);
											GameObject val16 = (GameObject)((value10 is GameObject) ? value10 : null);
											if ((Object)(object)val16 != (Object)null)
											{
												return ((Object)val16).name.Replace("(Clone)", "");
											}
										}
									}
									FieldInfo field7 = type2.GetField("m_dropPrefab", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
									if (field7 != null)
									{
										object? value11 = field7.GetValue(obj);
										GameObject val17 = (GameObject)((value11 is GameObject) ? value11 : null);
										if ((Object)(object)val17 != (Object)null)
										{
											return ((Object)val17).name.Replace("(Clone)", "");
										}
									}
									PropertyInfo property4 = type2.GetProperty("m_dropPrefab", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
									if (property4 != null)
									{
										object? value12 = property4.GetValue(obj);
										GameObject val18 = (GameObject)((value12 is GameObject) ? value12 : null);
										if ((Object)(object)val18 != (Object)null)
										{
											return ((Object)val18).name.Replace("(Clone)", "");
										}
									}
									PropertyInfo property5 = type2.GetProperty("gameObject", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
									if (property5 != null)
									{
										object? value13 = property5.GetValue(obj);
										GameObject val19 = (GameObject)((value13 is GameObject) ? value13 : null);
										if ((Object)(object)val19 != (Object)null)
										{
											return ((Object)val19).name.Replace("(Clone)", "");
										}
									}
									FieldInfo field8 = type2.GetField("name", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
									if (field8 != null)
									{
										string text19 = field8.GetValue(obj) as string;
										if (!string.IsNullOrWhiteSpace(text19))
										{
											return text19.Replace("(Clone)", "");
										}
									}
									PropertyInfo property6 = type2.GetProperty("name", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
									if (property6 != null)
									{
										string text20 = property6.GetValue(obj) as string;
										if (!string.IsNullOrWhiteSpace(text20))
										{
											return text20.Replace("(Clone)", "");
										}
									}
								}
								catch (Exception ex11)
								{
									LogDebugIf(VERBOSE_DEBUG, "extractPrefabName exception: " + ex11);
								}
								return null;
							};
							Action<object> action = delegate(object invItemObj)
							{
								try
								{
									Type type = invItemObj.GetType();
									MethodInfo method3 = ((object)inv).GetType().GetMethod("RemoveItem", new Type[2]
									{
										type,
										typeof(int)
									});
									if (method3 != null)
									{
										try
										{
											method3.Invoke(inv, new object[2] { invItemObj, 1 });
											LogDebugIf(VERBOSE_DEBUG, "Removed 1 item (RemoveItem(itemData, int) used).");
											return;
										}
										catch (Exception ex5)
										{
											LogDebugIf(VERBOSE_DEBUG, "RemoveItem(itemData, int) failed: " + ex5);
										}
									}
									FieldInfo field2 = type.GetField("m_shared", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
									string text18 = null;
									if (field2 != null)
									{
										try
										{
											object value8 = field2.GetValue(invItemObj);
											if (value8 != null)
											{
												FieldInfo field3 = value8.GetType().GetField("m_name", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
												if (field3 != null)
												{
													text18 = field3.GetValue(value8) as string;
												}
												if (string.IsNullOrWhiteSpace(text18))
												{
													PropertyInfo property2 = value8.GetType().GetProperty("m_name", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
													if (property2 != null)
													{
														text18 = property2.GetValue(value8) as string;
													}
												}
											}
										}
										catch (Exception ex6)
										{
											LogDebugIf(VERBOSE_DEBUG, "Failed to read shared.m_name: " + ex6);
											text18 = null;
										}
									}
									if (!string.IsNullOrWhiteSpace(text18))
									{
										MethodInfo method4 = ((object)inv).GetType().GetMethod("RemoveItem", new Type[2]
										{
											typeof(string),
											typeof(int)
										});
										if (method4 != null)
										{
											try
											{
												method4.Invoke(inv, new object[2] { text18, 1 });
												LogDebugIf(VERBOSE_DEBUG, "Removed 1 item by name ('" + text18 + "') via RemoveItem(string, int).");
												return;
											}
											catch (Exception ex7)
											{
												LogDebugIf(VERBOSE_DEBUG, "RemoveItem(string,int) failed: " + ex7);
											}
										}
									}
									MethodInfo method5 = ((object)inv).GetType().GetMethod("RemoveItem", new Type[1] { type });
									if (method5 != null)
									{
										try
										{
											method5.Invoke(inv, new object[1] { invItemObj });
											LogDebugIf(VERBOSE_DEBUG, "Removed 1 item (RemoveItem(itemData) used).");
											return;
										}
										catch (Exception ex8)
										{
											LogDebugIf(VERBOSE_DEBUG, "RemoveItem(itemData) failed: " + ex8);
										}
									}
									FieldInfo field4 = type.GetField("m_stack", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
									if (field4 != null)
									{
										try
										{
											if (field4.GetValue(invItemObj) is int num22 && num22 > 1)
											{
												field4.SetValue(invItemObj, num22 - 1);
												LogDebugIf(VERBOSE_DEBUG, "Decremented m_stack by 1 as a fallback removal.");
												return;
											}
											LogDebugIf(VERBOSE_DEBUG, "m_stack present but not >1; cannot decrement to remove one reliably.");
										}
										catch (Exception ex9)
										{
											LogWarning("m_stack decrement failed: " + ex9);
										}
									}
									LogWarning("Could not remove item via any known method; item may remain in inventory.");
								}
								catch (Exception ex10)
								{
									LogDebugIf(VERBOSE_DEBUG, "removeOne outer exception: " + ex10);
								}
							};
							List<ChanceCraftLine> configuredLines = component.GetConfiguredLines();
							LogDebugIf(VERBOSE_DEBUG, "Configured lines count: " + ((configuredLines == null) ? "<null>" : configuredLines.Count.ToString()));
							if (configuredLines != null)
							{
								foreach (ChanceCraftLine item3 in configuredLines)
								{
									if (item3 == null || !item3.IsActive)
									{
										LogDebugIf(VERBOSE_DEBUG, "Skipping inactive or null config line.");
										continue;
									}
									LogDebugIf(VERBOSE_DEBUG, $"Checking config line: ItemPrefab='{item3.ItemPrefab}', IncreaseCraftPercentage={item3.IncreaseCraftPercentage}");
									object obj6 = null;
									int num2 = 0;
									string text5 = func(item3.ItemPrefab);
									foreach (object item4 in enumerable)
									{
										num2++;
										if (item4 == null)
										{
											continue;
										}
										string text6 = func2(item4);
										if (string.IsNullOrWhiteSpace(text6))
										{
											continue;
										}
										string text7 = func(text6);
										if (!string.IsNullOrEmpty(text4) && !string.IsNullOrEmpty(text7) && text7 == text4)
										{
											bool flag3 = false;
											if (list != null)
											{
												foreach (ItemData item5 in list)
												{
													if (item5 == item4)
													{
														flag3 = true;
														break;
													}
												}
											}
											if (!flag3)
											{
												LogDebugIf(VERBOSE_DEBUG, "Skipping inventory prefab '" + text6 + "' because it appears to be the crafted result (no pre-craft snapshot entry).");
												continue;
											}
										}
										if (!string.IsNullOrEmpty(text5) && text7 == text5)
										{
											obj6 = item4;
											break;
										}
										if (!(text6 == item3.ItemPrefab))
										{
											continue;
										}
										obj6 = item4;
										break;
									}
									LogDebugIf(VERBOSE_DEBUG, $"Checked {num2} inventory entries for prefab '{item3.ItemPrefab}'.");
									if (obj6 != null)
									{
										num += item3.IncreaseCraftPercentage;
										flag2 = true;
										LogDebugIf(VERBOSE_DEBUG, $"Matched inventory prefab '{item3.ItemPrefab}'. Increase +{item3.IncreaseCraftPercentage}. Attempting to remove one instance.");
										action(obj6);
										LogDebugIf(VERBOSE_DEBUG, "Attempted removal for '" + item3.ItemPrefab + "'.");
									}
									else
									{
										LogDebugIf(VERBOSE_DEBUG, "No inventory match found for prefab '" + item3.ItemPrefab + "'.");
									}
								}
							}
						}
					}
				}
			}
			try
			{
				if ((Object)(object)component != (Object)null && num > 0f)
				{
					LogInfo($"ChanceCraft: total modified percentage from inventory consumed items = {num * 100f}%");
				}
			}
			catch (Exception ex4)
			{
				LogDebugIf(VERBOSE_DEBUG, "Final logging failed: " + ex4);
			}
			Player localPlayer2 = Player.m_localPlayer;
			float num3 = 0.6f;
			float num4 = 0.6f;
			if ((int)val2.GetValueOrDefault() == 3 || (int)val2.GetValueOrDefault() == 14 || (int)val2.GetValueOrDefault() == 4 || (int)val2.GetValueOrDefault() == 22)
			{
				num3 = weaponSuccessChance.Value;
				num4 = weaponSuccessUpgrade.Value;
			}
			else if ((int)val2.GetValueOrDefault() == 5 || (int)val2.GetValueOrDefault() == 6 || (int)val2.GetValueOrDefault() == 7 || (int)val2.GetValueOrDefault() == 11)
			{
				num3 = armorSuccessChance.Value;
				num4 = armorSuccessUpgrade.Value;
			}
			else if ((int)val2.GetValueOrDefault() == 9)
			{
				num3 = arrowSuccessChance.Value;
				num4 = arrowSuccessUpgrade.Value;
			}
			num3 = Mathf.Clamp01(num3 + num);
			int valueOrDefault = (val.m_item?.m_itemData?.m_quality).GetValueOrDefault(1);
			float num5 = 0.05f;
			float num6 = 1f + num5 * (float)Math.Max(0, valueOrDefault - 1);
			float num7 = Mathf.Clamp01(num3 * num6);
			float num8 = Mathf.Clamp01(num4 * num6);
			bool flag4 = ShouldTreatAsUpgrade(gui, val, isUpgradeCall);
			float value4 = Random.value;
			bool flag5 = IsDoCraft;
			try
			{
				string item = ChanceCraftRecipeHelpers.RecipeFingerprint(val);
				lock (_suppressedRecipeKeysLock)
				{
					if (_suppressedRecipeKeys.Contains(item))
					{
						flag5 = true;
					}
				}
			}
			catch
			{
			}
			try
			{
				lock (typeof(ChanceCraft))
				{
					if ((Object)(object)_snapshotRecipe != (Object)null && (Object)(object)_snapshotRecipe == (Object)(object)val && _preCraftSnapshotData != null && _preCraftSnapshotData.Count > 0)
					{
						flag5 = true;
					}
				}
			}
			catch
			{
			}
			try
			{
				string text8 = (((Object)(object)val != (Object)null) ? ChanceCraftRecipeHelpers.RecipeFingerprint(val) : "null");
				float num9 = (flag4 ? num8 : num7);
				LogInfo($"TrySpawnCraftEffect-DBG: recipe={text8} itemType={val2} quality={valueOrDefault} craftChance={num7:F3} upgradeChance={num8:F3} chosenChance={num9:F3} rand={value4:F3} suppressed={flag5} isUpgradeCall={isUpgradeCall}");
			}
			catch
			{
			}
			float num10 = (flag4 ? num8 : num7);
			if (value4 <= num10)
			{
				object obj10 = typeof(InventoryGui).GetField("currentCraftingStation", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(gui);
				if (obj10 != null)
				{
					object obj11 = obj10.GetType().GetField("m_craftItemEffects", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj10);
					if (obj11 != null)
					{
						MethodInfo method2 = obj11.GetType().GetMethod("Create", new Type[2]
						{
							typeof(Vector3),
							typeof(Quaternion)
						});
						if (method2 != null)
						{
							try
							{
								method2.Invoke(obj11, new object[2]
								{
									((Component)localPlayer2).transform.position,
									Quaternion.identity
								});
							}
							catch
							{
							}
						}
					}
				}
				bool flag6 = flag5;
				try
				{
					string item2 = ChanceCraftRecipeHelpers.RecipeFingerprint(val);
					lock (_suppressedRecipeKeysLock)
					{
						if (_suppressedRecipeKeys.Contains(item2))
						{
							flag6 = true;
						}
					}
				}
				catch
				{
				}
				try
				{
					lock (typeof(ChanceCraft))
					{
						if ((Object)(object)_snapshotRecipe != (Object)null && (Object)(object)_snapshotRecipe == (Object)(object)val && _preCraftSnapshotData != null && _preCraftSnapshotData.Count > 0)
						{
							flag6 = true;
						}
					}
				}
				catch
				{
				}
				if (flag4)
				{
					try
					{
						Recipe val4 = _upgradeGuiRecipe ?? _upgradeRecipe ?? ChanceCraftRecipeHelpers.GetUpgradeRecipeFromGui(gui) ?? val;
						if (val4 == val)
						{
							Recipe val5 = ChanceCraftRecipeHelpers.FindBestUpgradeRecipeCandidate(val);
							if ((Object)(object)val5 != (Object)null)
							{
								val4 = val5;
							}
						}
						if (_upgradeTargetItem == null)
						{
							_upgradeTargetItem = ChanceCraftRecipeHelpers.GetSelectedInventoryItem(gui);
						}
						try
						{
							string text9 = (((Object)(object)val4 != (Object)null) ? ChanceCraftRecipeHelpers.RecipeFingerprint(val4) : "null");
							string text10 = ((_upgradeTargetItem != null) ? RuntimeHelpers.GetHashCode(_upgradeTargetItem).ToString("X") : "null");
							int num11 = ((_preCraftSnapshot != null) ? _preCraftSnapshot.Count : 0);
							int num12 = ((_preCraftSnapshotData != null) ? _preCraftSnapshotData.Count : 0);
							LogInfo($"TrySpawnCraftEffect-DBG SUCCESS UPGRADE: recipeToUse={text9} targetHash={text10} preSnapshotCount={num11} preSnapshotData={num12}");
						}
						catch
						{
						}
						ChanceCraftResourceHelpers.RemoveRequiredResourcesUpgrade(gui, localPlayer2, val4, _upgradeTargetItem, crafted: true);
						lock (typeof(ChanceCraft))
						{
							_preCraftSnapshot = null;
							_preCraftSnapshotData = null;
							_snapshotRecipe = null;
							_upgradeTargetItemIndex = -1;
							_preCraftSnapshotHashQuality = null;
						}
						ClearCapturedUpgradeGui();
					}
					catch (Exception arg)
					{
						LogWarning($"TrySpawnCraftEffect success/upgrade removal exception: {arg}");
					}
					return null;
				}
				if (flag6)
				{
					try
					{
						if (ShouldTreatAsUpgrade(gui, val, isUpgradeCall: false))
						{
							Recipe val6 = _upgradeGuiRecipe ?? _upgradeRecipe ?? ChanceCraftRecipeHelpers.GetUpgradeRecipeFromGui(gui) ?? val;
							if (val6 == val)
							{
								Recipe val7 = ChanceCraftRecipeHelpers.FindBestUpgradeRecipeCandidate(val);
								if ((Object)(object)val7 != (Object)null)
								{
									val6 = val7;
								}
							}
							ItemData val8 = _upgradeTargetItem ?? ChanceCraftRecipeHelpers.GetSelectedInventoryItem(gui);
							string text11 = ((val8 != null) ? RuntimeHelpers.GetHashCode(val8).ToString("X") : "null");
							LogInfo("TrySpawnCraftEffect-DBG suppressed-success treating as UPGRADE: recipe=" + ChanceCraftRecipeHelpers.RecipeFingerprint(val6) + " target=" + text11);
							ChanceCraftResourceHelpers.RemoveRequiredResourcesUpgrade(gui, localPlayer2, val6, val8, crafted: true);
						}
						else
						{
							ChanceCraftResourceHelpers.RemoveRequiredResources(gui, localPlayer2, val, crafted: true);
						}
					}
					catch (Exception arg2)
					{
						LogWarning($"TrySpawnCraftEffect success removal exception: {arg2}");
					}
					ClearCapturedUpgradeGui();
				}
				if (flag2)
				{
					float num13 = num * 100f;
					string text12 = $"<color=yellow>Percentage increased by {num13:0.##}%</color>";
					LogInfo("Displaying HUD message to player: " + text12);
					if ((Object)(object)MessageHud.instance != (Object)null)
					{
						MessageHud.instance.ShowMessage((MessageType)2, text12, 0, (Sprite)null, false);
					}
					else if ((Object)(object)Player.m_localPlayer != (Object)null)
					{
						((Character)Player.m_localPlayer).Message((MessageType)2, text12, 0, (Sprite)null);
					}
				}
				return null;
			}
			if (isUpgradeCall || ChanceCraftRecipeHelpers.IsUpgradeOperation(gui, val) || _isUpgradeDetected || flag4)
			{
				try
				{
					try
					{
						string arg3 = (((Object)(object)val != (Object)null) ? ChanceCraftRecipeHelpers.RecipeFingerprint(val) : "null");
						int num14 = ((_preCraftSnapshotData != null) ? _preCraftSnapshotData.Count : 0);
						LogInfo($"TrySpawnCraftEffect-DBG FAILURE UPGRADE: recipe={arg3} preSnapshotData={num14} upgradeTargetIndex={_upgradeTargetItemIndex}");
					}
					catch
					{
					}
					bool flag7 = false;
					lock (typeof(ChanceCraft))
					{
						if (_preCraftSnapshotData != null)
						{
							Player localPlayer3 = Player.m_localPlayer;
							object obj17;
							if (localPlayer3 == null)
							{
								obj17 = null;
							}
							else
							{
								Inventory inventory = ((Humanoid)localPlayer3).GetInventory();
								obj17 = ((inventory != null) ? inventory.GetAllItems() : null);
							}
							List<ItemData> list2 = (List<ItemData>)obj17;
							List<ItemData> preCraftSnapshot = _preCraftSnapshot;
							foreach (KeyValuePair<ItemData, (int, int)> preCraftSnapshotDatum in _preCraftSnapshotData)
							{
								ItemData key = preCraftSnapshotDatum.Key;
								(int, int) value5 = preCraftSnapshotDatum.Value;
								try
								{
									if (key != null && list2 != null && list2.Contains(key))
									{
										if (ChanceCraftRecipeHelpers.TryUnpackQualityVariant(value5, out var quality, out var variant) && (key.m_quality != quality || key.m_variant != variant))
										{
											key.m_quality = quality;
											key.m_variant = variant;
											flag7 = true;
										}
										continue;
									}
									string text13 = key?.m_shared?.m_name ?? val.m_item?.m_itemData?.m_shared?.m_name;
									if (string.IsNullOrEmpty(text13) || list2 == null)
									{
										continue;
									}
									foreach (ItemData item6 in list2)
									{
										if (item6 == null || item6.m_shared == null || !string.Equals(item6.m_shared.m_name, text13, StringComparison.OrdinalIgnoreCase) || !ChanceCraftRecipeHelpers.TryUnpackQualityVariant(value5, out var quality2, out var variant2) || item6.m_quality <= quality2 || (preCraftSnapshot != null && preCraftSnapshot.Contains(item6)))
										{
											continue;
										}
										item6.m_quality = quality2;
										item6.m_variant = variant2;
										flag7 = true;
										break;
									}
								}
								catch
								{
								}
							}
						}
						if (!flag7)
						{
							try
							{
								string text14 = val.m_item?.m_itemData?.m_shared?.m_name;
								int num15 = Math.Max(0, (val.m_item?.m_itemData?.m_quality).GetValueOrDefault() - 1);
								if (_preCraftSnapshotData != null && _preCraftSnapshotData.Count > 0)
								{
									int quality7;
									int variant7;
									List<int> list3 = _preCraftSnapshotData.Values.Select(((int quality, int variant) v) => ChanceCraftRecipeHelpers.TryUnpackQualityVariant(v, out quality7, out variant7) ? quality7 : 0).ToList();
									if (list3.Count > 0)
									{
										num15 = Math.Max(0, list3.Max());
									}
								}
								if (!string.IsNullOrEmpty(text14) && (Object)(object)Player.m_localPlayer != (Object)null)
								{
									Inventory inventory2 = ((Humanoid)Player.m_localPlayer).GetInventory();
									List<ItemData> list4 = ((inventory2 != null) ? inventory2.GetAllItems() : null);
									if (list4 != null)
									{
										foreach (ItemData item7 in list4)
										{
											if (item7 != null && item7.m_shared != null && string.Equals(item7.m_shared.m_name, text14, StringComparison.OrdinalIgnoreCase) && item7.m_quality > num15 && (_preCraftSnapshot == null || !_preCraftSnapshot.Contains(item7)))
											{
												item7.m_quality = num15;
											}
										}
									}
								}
							}
							catch
							{
							}
						}
						if (!flag7 && _upgradeTargetItemIndex >= 0)
						{
							try
							{
								Player localPlayer4 = Player.m_localPlayer;
								Inventory val9 = ((localPlayer4 != null) ? ((Humanoid)localPlayer4).GetInventory() : null);
								List<ItemData> list5 = ((val9 != null) ? val9.GetAllItems() : null);
								if (list5 != null && _upgradeTargetItemIndex >= 0 && _upgradeTargetItemIndex < list5.Count)
								{
									ItemData val10 = list5[_upgradeTargetItemIndex];
									if (val10 != null && val10.m_shared != null)
									{
										string resultName = val.m_item?.m_itemData?.m_shared?.m_name;
										int valueOrDefault2 = (val.m_item?.m_itemData?.m_quality).GetValueOrDefault();
										int num16 = Math.Max(0, valueOrDefault2 - 1);
										if (_preCraftSnapshotData != null)
										{
											KeyValuePair<ItemData, (int, int)> keyValuePair = _preCraftSnapshotData.FirstOrDefault((KeyValuePair<ItemData, (int quality, int variant)> p) => p.Key != null && p.Key.m_shared != null && string.Equals(p.Key.m_shared.m_name, resultName, StringComparison.OrdinalIgnoreCase));
											if (!keyValuePair.Equals(default(KeyValuePair<ItemData, (int, int)>)) && ChanceCraftRecipeHelpers.TryUnpackQualityVariant(keyValuePair.Value, out var quality3, out var _))
											{
												num16 = quality3;
											}
										}
										if (string.Equals(val10.m_shared.m_name, resultName, StringComparison.OrdinalIgnoreCase) && val10.m_quality > num16)
										{
											val10.m_quality = num16;
											flag7 = true;
										}
									}
								}
							}
							catch
							{
							}
						}
						if (!flag7 && _preCraftSnapshotHashQuality != null && _preCraftSnapshotHashQuality.Count > 0)
						{
							try
							{
								string text15 = val.m_item?.m_itemData?.m_shared?.m_name;
								int valueOrDefault3 = (val.m_item?.m_itemData?.m_quality).GetValueOrDefault();
								int num17 = Math.Max(0, valueOrDefault3 - 1);
								Player localPlayer5 = Player.m_localPlayer;
								object obj21;
								if (localPlayer5 == null)
								{
									obj21 = null;
								}
								else
								{
									Inventory inventory3 = ((Humanoid)localPlayer5).GetInventory();
									obj21 = ((inventory3 != null) ? inventory3.GetAllItems() : null);
								}
								List<ItemData> list6 = (List<ItemData>)obj21;
								if (list6 != null)
								{
									foreach (ItemData item8 in list6)
									{
										if (item8 == null || item8.m_shared == null)
										{
											continue;
										}
										int h = RuntimeHelpers.GetHashCode(item8);
										if (_preCraftSnapshotHashQuality.TryGetValue(h, out var value6))
										{
											if (item8.m_quality > value6)
											{
												item8.m_quality = value6;
												KeyValuePair<ItemData, (int, int)> keyValuePair2 = _preCraftSnapshotData.FirstOrDefault((KeyValuePair<ItemData, (int quality, int variant)> p) => RuntimeHelpers.GetHashCode(p.Key) == h);
												if (!keyValuePair2.Equals(default(KeyValuePair<ItemData, (int, int)>)) && ChanceCraftRecipeHelpers.TryUnpackQualityVariant(keyValuePair2.Value, out var _, out var variant4))
												{
													item8.m_variant = variant4;
												}
												flag7 = true;
											}
										}
										else if (!string.IsNullOrEmpty(text15) && string.Equals(item8.m_shared.m_name, text15, StringComparison.OrdinalIgnoreCase) && item8.m_quality > num17)
										{
											item8.m_quality = num17;
											flag7 = true;
										}
									}
								}
							}
							catch
							{
							}
						}
						try
						{
							ChanceCraftUIHelpers.ForceSimulateTabSwitchRefresh(gui);
							try
							{
								ChanceCraftUIHelpers.RefreshInventoryGui(gui);
							}
							catch
							{
							}
							try
							{
								ChanceCraftUIHelpers.RefreshCraftingPanel(gui);
							}
							catch
							{
							}
							try
							{
								if (gui != null)
								{
									((MonoBehaviour)gui).StartCoroutine(ChanceCraftUIHelpers.DelayedRefreshCraftingPanel(gui));
								}
							}
							catch
							{
							}
							Debug.LogWarning((object)"[ChanceCraft] TrySpawnCraftEffect: performed UI refresh after revert attempts.");
						}
						catch (Exception arg4)
						{
							Debug.LogWarning((object)$"[ChanceCraft] TrySpawnCraftEffect: UI refresh after revert failed: {arg4}");
						}
						try
						{
							Player localPlayer6 = Player.m_localPlayer;
							if (localPlayer6 != null)
							{
								((Character)localPlayer6).Message((MessageType)2, "<color=red>Upgrade failed!</color>", 0, (Sprite)null);
							}
						}
						catch
						{
						}
					}
					try
					{
						ItemData val11 = _upgradeTargetItem ?? ChanceCraftRecipeHelpers.GetSelectedInventoryItem(gui);
						string text16 = ((val11 != null) ? RuntimeHelpers.GetHashCode(val11).ToString("X") : "null");
						Player localPlayer7 = Player.m_localPlayer;
						Inventory val12 = ((localPlayer7 != null) ? ((Humanoid)localPlayer7).GetInventory() : null);
						int num18 = 0;
						int num19 = 0;
						int num20 = 0;
						if (val12 != null)
						{
							List<ItemData> allItems = val12.GetAllItems();
							try
							{
								num18 = allItems.Where((ItemData it) => it != null && it.m_shared != null && string.Equals(it.m_shared.m_name, "$item_wood", StringComparison.OrdinalIgnoreCase)).Sum((ItemData i) => i.m_stack);
							}
							catch
							{
							}
							try
							{
								num19 = allItems.Where((ItemData it) => it != null && it.m_shared != null && string.Equals(it.m_shared.m_name, "$item_leatherscraps", StringComparison.OrdinalIgnoreCase)).Sum((ItemData i) => i.m_stack);
							}
							catch
							{
							}
							try
							{
								num20 = allItems.Where((ItemData it) => it != null && it.m_shared != null && string.Equals(it.m_shared.m_name, "$item_deerhide", StringComparison.OrdinalIgnoreCase)).Sum((ItemData i) => i.m_stack);
							}
							catch
							{
							}
						}
						LogInfo($"TrySpawnCraftEffect-DBG BEFORE removal: targetHash={text16} wood={num18} scraps={num19} hides={num20} didRevertAny={false}");
					}
					catch
					{
					}
					Recipe val13 = _upgradeGuiRecipe ?? _upgradeRecipe ?? ChanceCraftRecipeHelpers.GetUpgradeRecipeFromGui(gui) ?? val;
					if (val13 == val)
					{
						Recipe val14 = ChanceCraftRecipeHelpers.FindBestUpgradeRecipeCandidate(val);
						if ((Object)(object)val14 != (Object)null)
						{
							val13 = val14;
						}
					}
					ItemData upgradeTarget = _upgradeTargetItem ?? ChanceCraftRecipeHelpers.GetSelectedInventoryItem(gui);
					ChanceCraftResourceHelpers.RemoveRequiredResourcesUpgrade(gui, Player.m_localPlayer, val13, upgradeTarget, crafted: false);
					try
					{
						ChanceCraftUIHelpers.ForceRevertAfterRemoval(gui, val13, upgradeTarget);
					}
					catch
					{
					}
					lock (typeof(ChanceCraft))
					{
						_preCraftSnapshot = null;
						_preCraftSnapshotData = null;
						_snapsho