Decompiled source of ChanceCraft v1.1.6
ChanceCraft.dll
Decompiled a week 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