Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ChanceCraft v1.1.6
ChanceCraft.dll
Decompiled 5 months ago
The result has been truncated due to the large size, download it to view full contents!
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