Decompiled source of LootBox v1.0.7
plugins/LootBox.dll
Decompiled 5 days 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.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; using System.Reflection.Emit; 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 System.Text.RegularExpressions; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using ItemManager; using JetBrains.Annotations; using Microsoft.CodeAnalysis; using ServerSync; using TMPro; using UnityEngine; [assembly: AssemblyFileVersion("1.0.7")] [assembly: Guid("B0E3D5AB-8B5F-4C7E-90C6-7F2E1CF7C2B9")] [assembly: ComVisible(false)] [assembly: AssemblyTrademark("")] [assembly: AssemblyCopyright("")] [assembly: AssemblyProduct("LootBox")] [assembly: AssemblyCompany("Radamanto")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyDescription("")] [assembly: AssemblyTitle("LootBox")] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: CompilationRelaxations(8)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.7.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [<8da6f078-7bee-43ee-b47c-40f2acbab342>Embedded] internal sealed class <8da6f078-7bee-43ee-b47c-40f2acbab342>EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [<8da6f078-7bee-43ee-b47c-40f2acbab342>Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class <a6313b97-aa7e-4d6b-882d-a90990831bc6>NullableAttribute : Attribute { public readonly byte[] NullableFlags; public <a6313b97-aa7e-4d6b-882d-a90990831bc6>NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public <a6313b97-aa7e-4d6b-882d-a90990831bc6>NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] [<8da6f078-7bee-43ee-b47c-40f2acbab342>Embedded] internal sealed class <97f3fb7d-43ae-48ec-8a26-23897b225d38>NullableContextAttribute : Attribute { public readonly byte Flag; public <97f3fb7d-43ae-48ec-8a26-23897b225d38>NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace LootBox { [BepInPlugin("radamanto.LootBox", "LootBox", "1.0.7")] public class LootboxPlugin : BaseUnityPlugin { [HarmonyPatch(typeof(ObjectDB), "Awake")] private static class ObjectDbAwake_Post { private static void Postfix() { GameObject managerObject = Chainloader.ManagerObject; ((managerObject != null) ? managerObject.GetComponent<LootboxPlugin>() : null)?.EnsureAllItemsRegistered(); } } [HarmonyPatch(typeof(InventoryGui), "UpdateRecipe")] private static class InventoryGui_UpdateRecipe_Patch { private static void Postfix() { if (InventoryGui.IsVisible()) { GameObject managerObject = Chainloader.ManagerObject; LootboxPlugin lootboxPlugin = ((managerObject != null) ? managerObject.GetComponent<LootboxPlugin>() : null); if ((Object)(object)lootboxPlugin != (Object)null && lootboxPlugin._defsById.Count > 0) { lootboxPlugin.ForceUpdateAllTooltips(); } } } } private static AudioClip _sfxOpen; private const string SfxOpenName = "loot_box_oppenig"; private const string SfxBundleName = "rd_box"; private float _lastOpenRealtime; public const string ModGUID = "radamanto.LootBox"; public const string ModName = "LootBox"; public const string ModVersion = "1.0.7"; private Harmony _harmony; private readonly HashSet<ConfigEntryBase> _syncedConfigEntries = new HashSet<ConfigEntryBase>(); private static readonly LootboxCatalog Catalog = LootboxCatalog.FromBundle("rd_box", "assets", "rd_lootbox_01", "rd_lootbox_02", "rd_lootbox_03", "rd_lootbox_04", "rd_lootbox_05", "rd_lootbox_06", "rd_lootbox_07", "rd_lootbox_08", "rd_lootbox_09", "rd_lootbox_10", "rd_lootbox_11", "rd_lootbox_12", "rd_lootbox_13", "rd_lootbox_14", "rd_lootbox_15", "rd_lootbox_16", "rd_lootbox_17", "rd_lootbox_18", "rd_lootbox_19", "rd_gift_box_01", "rd_gift_box_02", "rd_gift_box_03", "rd_darkbox_01", "rd_darkbox_02", "rd_darkbox_03", "rd_darkbox_04", "rd_pinkbox_01", "rd_pinkbox_02", "rd_pinkbox_03", "rd_pinkbox_04"); private readonly Dictionary<string, LootBoxDefinition> _defsById = new Dictionary<string, LootBoxDefinition>(StringComparer.OrdinalIgnoreCase); private readonly Dictionary<string, LootBoxDefinition> _defsByPrefab = new Dictionary<string, LootBoxDefinition>(StringComparer.OrdinalIgnoreCase); private readonly HashSet<string> _lootboxPrefabNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private bool _bundlesRegistered; private ConfigSync _configSync; private FileSystemWatcher _cfgWatcher; private readonly object _cfgLock = new object(); private DateTime _lastCfgEventUtc; public static ConfigEntry<bool> ServerConfigLocked; private DateTime _lastSettingChangeUtc; private void EnsureAllItemsRegistered() { try { if (!_bundlesRegistered) { RegisterFixedBundleOnce(Catalog.Bundle, Catalog.Folder); _bundlesRegistered = true; } foreach (LootBoxDefinition value in _defsById.Values) { if (value.Enabled) { EnsureOneItemRegistered(value); } } ForceUpdateAllTooltips(); } catch { } } private void RegisterFixedBundleOnce(string bundleName, string folder) { Type typeFromHandle = typeof(PrefabManager); MethodInfo method = typeFromHandle.GetMethod("RegisterAssetBundle", BindingFlags.Static | BindingFlags.Public, null, new Type[2] { typeof(Assembly), typeof(string) }, null); MethodInfo method2 = typeFromHandle.GetMethod("RegisterAssetBundle", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(AssetBundle) }, null); try { if (method != null) { method.Invoke(null, new object[2] { Assembly.GetExecutingAssembly(), bundleName }); TryResolveOpenClip(); return; } using Stream stream = FindEmbeddedBundleStream(Assembly.GetExecutingAssembly(), bundleName, folder); if (stream == null) { TryResolveOpenClip(); return; } AssetBundle val = AssetBundle.LoadFromStream(stream); if ((Object)(object)val == (Object)null) { TryResolveOpenClip(); return; } method2?.Invoke(null, new object[1] { val }); TryResolveOpenClip(); } catch { } } private void TryResolveOpenClip() { if (Object.op_Implicit((Object)(object)_sfxOpen)) { return; } try { foreach (AssetBundle allLoadedAssetBundle in AssetBundle.GetAllLoadedAssetBundles()) { if (!Object.op_Implicit((Object)(object)allLoadedAssetBundle) || ((Object)allLoadedAssetBundle).name == null || !((Object)allLoadedAssetBundle).name.Equals("rd_box", StringComparison.OrdinalIgnoreCase)) { continue; } AudioClip val = SafeLoadAudioClip(allLoadedAssetBundle, "loot_box_oppenig"); if (Object.op_Implicit((Object)(object)val)) { _sfxOpen = val; } else { Debug.LogWarning((object)"[LootBox] Áudio 'loot_box_oppenig' não foi encontrado dentro do bundle 'rd_box'."); } return; } Debug.LogWarning((object)"[LootBox] AssetBundle 'rd_box' não está carregado; som de abertura desabilitado."); } catch { } } private static AudioClip SafeLoadAudioClip(AssetBundle ab, string name) { try { return ab.LoadAsset<AudioClip>(name); } catch { return null; } } private static Stream FindEmbeddedBundleStream(Assembly asm, string bundleBaseName, string folder) { string[] manifestResourceNames = asm.GetManifestResourceNames(); string text = manifestResourceNames.FirstOrDefault((string n) => n.EndsWith("." + folder + "." + bundleBaseName, StringComparison.OrdinalIgnoreCase) || n.EndsWith("." + bundleBaseName, StringComparison.OrdinalIgnoreCase)); return (text != null) ? asm.GetManifestResourceStream(text) : null; } private void EnsureOneItemRegistered(LootBoxDefinition def) { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown try { if (def == null || string.IsNullOrWhiteSpace(def.Prefab)) { return; } GameObject val = null; try { Type typeFromHandle = typeof(PrefabManager); MethodInfo method = typeFromHandle.GetMethod("GetPrefab", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(string) }, null); if (method != null) { val = (GameObject)method.Invoke(null, new object[1] { def.Prefab }); } } catch { } if (!Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)ZNetScene.instance)) { val = ZNetScene.instance.GetPrefab(def.Prefab); } if (!Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)ObjectDB.instance)) { val = ObjectDB.instance.GetItemPrefab(def.Prefab); } if (!Object.op_Implicit((Object)(object)val)) { string value = (string.IsNullOrWhiteSpace(def.Bundle) ? Catalog.Bundle : def.Bundle); foreach (AssetBundle allLoadedAssetBundle in AssetBundle.GetAllLoadedAssetBundles()) { try { if (Object.op_Implicit((Object)(object)allLoadedAssetBundle) && ((Object)allLoadedAssetBundle).name != null && ((Object)allLoadedAssetBundle).name.Equals(value, StringComparison.OrdinalIgnoreCase)) { val = allLoadedAssetBundle.LoadAsset<GameObject>(def.Prefab); if (Object.op_Implicit((Object)(object)val)) { break; } } } catch { } } } if (Object.op_Implicit((Object)(object)val)) { try { Item item = new Item(val); item.Name.English(def.DisplayName ?? def.Id); item.Description.English(def.BuildTooltipText()); } catch { } PostCreateAdjust(def); } } catch { } } private void PostCreateAdjust(LootBoxDefinition def) { //IL_00c2: Unknown result type (might be due to invalid IL or missing references) try { ObjectDB instance = ObjectDB.instance; ZNetScene instance2 = ZNetScene.instance; if (!Object.op_Implicit((Object)(object)instance) && !Object.op_Implicit((Object)(object)instance2)) { return; } GameObject val = null; if (Object.op_Implicit((Object)(object)instance)) { val = instance.GetItemPrefab(def.Prefab); } if (!Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)instance2)) { val = instance2.GetPrefab(def.Prefab); } if (!Object.op_Implicit((Object)(object)val)) { return; } ItemDrop component = val.GetComponent<ItemDrop>(); if (!Object.op_Implicit((Object)(object)component)) { return; } SharedData val2 = component.m_itemData?.m_shared; if (val2 != null) { val2.m_itemType = (ItemType)1; if (val2.m_maxStackSize <= 1) { val2.m_maxStackSize = 10; } val2.m_consumeStatusEffect = null; val2.m_food = 0f; val2.m_foodStamina = 0f; val2.m_foodRegen = 0f; val2.m_foodBurnTime = 0f; if ((Object)(object)component.m_itemData.m_dropPrefab == (Object)null) { component.m_itemData.m_dropPrefab = val; } UpdateItemSharedData(def, val2); } } catch { } } private void UpdateItemSharedData(LootBoxDefinition def, SharedData shared) { if (shared == null || def == null) { return; } try { shared.m_name = def.DisplayName ?? def.Id; shared.m_description = def.BuildTooltipText(); } catch { } } private void ForceUpdateAllTooltips() { try { ObjectDB instance = ObjectDB.instance; if ((Object)(object)instance == (Object)null) { return; } foreach (LootBoxDefinition value in _defsById.Values) { if (!value.Enabled) { continue; } GameObject itemPrefab = instance.GetItemPrefab(value.Prefab); if (Object.op_Implicit((Object)(object)itemPrefab)) { ItemDrop component = itemPrefab.GetComponent<ItemDrop>(); if (Object.op_Implicit((Object)(object)component) && component.m_itemData?.m_shared != null) { UpdateItemSharedData(value, component.m_itemData.m_shared); } } } } catch { } } internal void RefreshAllTooltipsAfterConfigChange() { ForceUpdateAllTooltips(); RefreshExistingItemStacksInInventories(); try { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { Inventory inventory = ((Humanoid)localPlayer).GetInventory(); if (inventory != null) { inventory.Changed(); } InventoryGui instance = InventoryGui.instance; if ((Object)(object)instance != (Object)null && (Object)(object)Player.m_localPlayer != (Object)null) { instance.UpdateRecipe(Player.m_localPlayer, 0f); } } } catch { } } private void RefreshExistingItemStacksInInventories() { try { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { Inventory inventory = ((Humanoid)localPlayer).GetInventory(); if (inventory != null) { List<ItemData> allItems = inventory.GetAllItems(); if (allItems != null) { foreach (ItemData item in allItems) { TryRefreshOneItemShared(item); } inventory.Changed(); } } } InventoryGui instance = InventoryGui.instance; if (!((Object)(object)instance != (Object)null) || !((Object)(object)instance.m_currentContainer != (Object)null)) { return; } Inventory inventory2 = instance.m_currentContainer.GetInventory(); if (inventory2 == null) { return; } List<ItemData> allItems2 = inventory2.GetAllItems(); if (allItems2 == null) { return; } foreach (ItemData item2 in allItems2) { TryRefreshOneItemShared(item2); } inventory2.Changed(); } catch { } } private void TryRefreshOneItemShared(ItemData item) { try { if (item == null || item.m_shared == null) { return; } string text = null; try { if (Object.op_Implicit((Object)(object)item.m_dropPrefab)) { text = ((Object)item.m_dropPrefab).name; } } catch { } if (string.IsNullOrWhiteSpace(text)) { return; } int num = text.IndexOf("(Clone", StringComparison.Ordinal); if (num > 0) { text = text.Substring(0, num); } foreach (LootBoxDefinition value in _defsById.Values) { if (!value.Enabled || !string.Equals(value.Prefab, text, StringComparison.Ordinal)) { continue; } UpdateItemSharedData(value, item.m_shared); break; } } catch { } } internal void RefreshLocalizedTexts() { try { ObjectDB instance = ObjectDB.instance; if ((Object)(object)instance == (Object)null) { return; } foreach (LootBoxDefinition value in _defsById.Values) { if (!value.Enabled) { continue; } GameObject itemPrefab = instance.GetItemPrefab(value.Prefab); if (Object.op_Implicit((Object)(object)itemPrefab)) { string text = value.BuildTooltipText(); string text2 = value.DisplayName ?? value.Id; ItemDrop component = itemPrefab.GetComponent<ItemDrop>(); if ((Object)(object)component != (Object)null && component.m_itemData != null && component.m_itemData.m_shared != null) { component.m_itemData.m_shared.m_name = text2; component.m_itemData.m_shared.m_description = text; } try { Item item = new Item(itemPrefab, skipRegistering: true); item.Name.English(text2); item.Description.English(text); } catch { } } } try { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { Inventory inventory = ((Humanoid)localPlayer).GetInventory(); if (inventory != null) { inventory.Changed(); } } } catch { } } catch { } } private static void InstallLanguageHooksDynamically(Harmony harmony) { TryPatch("SetLanguage"); TryPatch("SetupLanguage"); TryPatch("ReloadData"); TryPatch("LoadCSV"); void TryPatch(string methodName) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown try { MethodInfo method = typeof(Localization).GetMethod(methodName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (!(method == null)) { HarmonyMethod val = new HarmonyMethod(typeof(LanguageHooksDynamic).GetMethod("Postfix", BindingFlags.Static | BindingFlags.Public)); harmony.Patch((MethodBase)method, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } catch { } } } private void InstallLanguageIntegration(Harmony harmony) { LootLoc.RefreshActive(); InstallLanguageHooksDynamically(harmony); } private List<LootResult> Roll(LootBoxDefinition def, int seed) { List<LootResult> list = new List<LootResult>(); if (def == null || def.Items.Count == 0) { return list; } try { Random random = new Random(seed); foreach (LootEntry item in def.Items) { if (item != null && !string.IsNullOrWhiteSpace(item.Prefab)) { int num = Math.Max(0, item.Chance); if (!(random.NextDouble() * 100.0 > (double)num)) { int num2 = Math.Min(item.Min, item.Max); int num3 = Math.Max(item.Min, item.Max); int amount = ((num2 == num3) ? Math.Max(1, num2) : random.Next(num2, num3 + 1)); int quality = ((item.Quality <= 0) ? 1 : item.Quality); int variant = ((item.Variant > 0) ? item.Variant : 0); list.Add(new LootResult(item.Prefab, amount, quality, variant)); } } } } catch { } return list; } private void GiveAll(Player player, List<LootResult> drops) { if ((Object)(object)player == (Object)null || drops == null || drops.Count == 0) { return; } try { foreach (LootResult drop in drops) { if (!string.IsNullOrWhiteSpace(drop.Prefab)) { SafeItemDelivery.GiveOrDrop(player, drop.Prefab, drop.Amount, drop.Quality, drop.Variant); } } } catch { } } private bool ConsumeOneByGridOrName(Inventory inv, ItemData hovered) { try { if (hovered != null && hovered.m_stack > 0) { hovered.m_stack--; if (hovered.m_stack <= 0) { inv.RemoveItem(hovered); } inv.Changed(); return true; } string name = hovered?.m_shared?.m_name; if (!string.IsNullOrEmpty(name)) { ItemData val = ((IEnumerable<ItemData>)inv.m_inventory).FirstOrDefault((Func<ItemData, bool>)((ItemData i) => i != null && i.m_shared != null && i.m_shared.m_name == name)); if (val != null && val.m_stack > 0) { val.m_stack--; if (val.m_stack <= 0) { inv.RemoveItem(val); } inv.Changed(); return true; } } } catch { } return false; } internal bool OpenFromInventory(Player player, Inventory inv, ItemData hovered, Vector2i? gridPos = null) { if ((Object)(object)player == (Object)null || inv == null || hovered == null) { return false; } if (Time.realtimeSinceStartup - _lastOpenRealtime < 0.3f) { return false; } _lastOpenRealtime = Time.realtimeSinceStartup; string text = (Object.op_Implicit((Object)(object)hovered.m_dropPrefab) ? ((Object)hovered.m_dropPrefab).name : null); if (string.IsNullOrEmpty(text)) { return false; } if (!TryGetDefByPrefab(text, out var def)) { return false; } bool flag = false; if (!flag) { flag = ConsumeOneByGridOrName(inv, hovered); } if (!flag) { return false; } PlayOpenClipIfPossible(player); List<LootResult> drops = Roll(def, Random.Range(int.MinValue, int.MaxValue)); GiveAll(player, drops); ((Character)player).Message((MessageType)2, LootLoc.Tf("msg_opened", def?.DisplayName ?? "Lootbox"), 0, (Sprite)null); return true; } private void PlayOpenClipIfPossible(Player player) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown //IL_00ba: Unknown result type (might be due to invalid IL or missing references) try { if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsDedicated()) { return; } if ((Object)(object)_sfxOpen == (Object)null) { TryResolveOpenClip(); } if (!((Object)(object)_sfxOpen == (Object)null)) { GameObject val = new GameObject("Lootbox_OpenSFX_Temp"); AudioSource val2 = val.AddComponent<AudioSource>(); val2.clip = _sfxOpen; val2.playOnAwake = false; val2.loop = false; val2.spatialBlend = 0f; val2.volume = 1f; val2.pitch = 1f; if (Object.op_Implicit((Object)(object)player)) { val.transform.position = ((Component)player).transform.position; } val2.Play(); Object.Destroy((Object)(object)val, _sfxOpen.length + 0.2f); } } catch { } } private void Awake() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown LootLoc.RefreshActive(); _harmony = new Harmony("radamanto.LootBox"); InstallLanguageIntegration(_harmony); SetupConfigSync(); _harmony.PatchAll(typeof(ObjectDbAwake_Post)); _harmony.PatchAll(typeof(InvGui_RightClickOpen)); RegisterPerLootboxDefaults(); ParseAllDefinitions(); TryEnsureAllRegisteredImmediately(); } private static string DefaultDisplayNameFor(string prefab) { if (1 == 0) { } string result = prefab switch { "rd_lootbox_01" => "Golden Box", "rd_lootbox_02" => "Silver Box", "rd_lootbox_03" => "Bronze Box", "rd_lootbox_04" => "Pink Box 01", "rd_lootbox_05" => "Pink Box 02", "rd_lootbox_06" => "Pink Box 03", "rd_lootbox_07" => "Pink Box 04", "rd_lootbox_08" => "Blue Box 01", "rd_lootbox_09" => "Blue Box 02", "rd_lootbox_10" => "Blue Box 03", "rd_lootbox_11" => "Blue Box 04", "rd_lootbox_12" => "Red Box 01", "rd_lootbox_13" => "Red Box 02", "rd_lootbox_14" => "Red Box 03", "rd_lootbox_15" => "Red Box 04", "rd_lootbox_16" => "Green Box 01", "rd_lootbox_17" => "Green Box 02", "rd_lootbox_18" => "Green Box 03", "rd_lootbox_19" => "Green Box 04", "rd_gift_box_01" => "Gift Box Red", "rd_gift_box_02" => "Gift Box Green", "rd_gift_box_03" => "Gift Box Blue", "rd_darkbox_01" => "Dark Box 01", "rd_darkbox_02" => "Dark Box 02", "rd_darkbox_03" => "Dark Box 03", "rd_darkbox_04" => "Dark Box 04", "rd_pinkbox_01" => "Bloom Box 01", "rd_pinkbox_02" => "Bloom Box 02", "rd_pinkbox_03" => "Bloom Box 03", "rd_pinkbox_04" => "Bloom Box 04", _ => "Lootbox", }; if (1 == 0) { } return result; } private static string DefaultItemsFor(string prefab) { if (1 == 0) { } string result = prefab switch { "rd_lootbox_01" => "Coins, 70, 50-120, 1, Wood, 20, 30-60, 1, Resin, 10, 10-20, 1", "rd_lootbox_02" => "Coins, 70, 50-120, 1, Wood, 20, 30-60, 1, Resin, 10, 10-20, 1", "rd_lootbox_03" => "Coins, 70, 50-120, 1, Wood, 20, 30-60, 1, Resin, 10, 10-20, 1", "rd_lootbox_04" => "Coins, 70, 50-120, 1, Wood, 20, 30-60, 1, Resin, 10, 10-20, 1", "rd_lootbox_05" => "Coins, 70, 50-120, 1, Wood, 20, 30-60, 1, Resin, 10, 10-20, 1", "rd_lootbox_06" => "Coins, 70, 50-120, 1, Wood, 20, 30-60, 1, Resin, 10, 10-20, 1", "rd_lootbox_07" => "Coins, 70, 50-120, 1, Wood, 20, 30-60, 1, Resin, 10, 10-20, 1", "rd_lootbox_08" => "Coins, 70, 50-120, 1, Wood, 20, 30-60, 1, Resin, 10, 10-20, 1", "rd_lootbox_09" => "Coins, 70, 50-120, 1, Wood, 20, 30-60, 1, Resin, 10, 10-20, 1", "rd_lootbox_10" => "Coins, 70, 50-120, 1, Wood, 20, 30-60, 1, Resin, 10, 10-20, 1", "rd_lootbox_11" => "Coins, 70, 50-120, 1, Wood, 20, 30-60, 1, Resin, 10, 10-20, 1", "rd_lootbox_12" => "Coins, 70, 50-120, 1, Wood, 20, 30-60, 1, Resin, 10, 10-20, 1", "rd_lootbox_13" => "Coins, 70, 50-120, 1, Wood, 20, 30-60, 1, Resin, 10, 10-20, 1", "rd_lootbox_14" => "Coins, 70, 50-120, 1, Wood, 20, 30-60, 1, Resin, 10, 10-20, 1", "rd_lootbox_15" => "Coins, 70, 50-120, 1, Wood, 20, 30-60, 1, Resin, 10, 10-20, 1", "rd_lootbox_16" => "Coins, 70, 50-120, 1, Wood, 20, 30-60, 1, Resin, 10, 10-20, 1", "rd_lootbox_17" => "Coins, 70, 50-120, 1, Wood, 20, 30-60, 1, Resin, 10, 10-20, 1", "rd_lootbox_18" => "Coins, 70, 50-120, 1, Wood, 20, 30-60, 1, Resin, 10, 10-20, 1", "rd_lootbox_19" => "Coins, 70, 50-120, 1, Wood, 20, 30-60, 1, Resin, 10, 10-20, 1", "rd_gift_box_01" => "Coins, 70, 50-120, 1, Wood, 20, 30-60, 1, Resin, 10, 10-20, 1", "rd_gift_box_02" => "Coins, 70, 50-120, 1, Wood, 20, 30-60, 1, Resin, 10, 10-20, 1", "rd_gift_box_03" => "Coins, 70, 50-120, 1, Wood, 20, 30-60, 1, Resin, 10, 10-20, 1", "rd_darkbox_01" => "Coins, 70, 50-120, 1, Wood, 20, 30-60, 1, Resin, 10, 10-20, 1", "rd_darkbox_02" => "Coins, 70, 50-120, 1, Wood, 20, 30-60, 1, Resin, 10, 10-20, 1", "rd_darkbox_03" => "Coins, 70, 50-120, 1, Wood, 20, 30-60, 1, Resin, 10, 10-20, 1", "rd_darkbox_04" => "Coins, 70, 50-120, 1, Wood, 20, 30-60, 1, Resin, 10, 10-20, 1", "rd_pinkbox_01" => "Coins, 70, 50-120, 1, Wood, 20, 30-60, 1, Resin, 10, 10-20, 1", "rd_pinkbox_02" => "Coins, 70, 50-120, 1, Wood, 20, 30-60, 1, Resin, 10, 10-20, 1", "rd_pinkbox_03" => "Coins, 70, 50-120, 1, Wood, 20, 30-60, 1, Resin, 10, 10-20, 1", "rd_pinkbox_04" => "Coins, 70, 50-120, 1, Wood, 20, 30-60, 1, Resin, 10, 10-20, 1", _ => "Coins, 70, 50-120, 1, Iron, 20, 3-5, 1, Ruby, 10, 1, 1", }; if (1 == 0) { } return result; } private void RegisterPerLootboxDefaults() { foreach (string prefab in Catalog.Prefabs) { string group = "Lootbox:" + prefab; Cfg(group, "Enable", value: true, "Enable/disable this lootbox without removing it."); Cfg(group, "DisplayName", DefaultDisplayNameFor(prefab), "Display name (token or plain)."); Cfg(group, "Items", DefaultItemsFor(prefab), "Inline format (repeat groups of 4): Item, Chance%, Amount, Quality"); } } private void ParseAllDefinitions() { _defsById.Clear(); _defsByPrefab.Clear(); _lootboxPrefabNames.Clear(); foreach (string prefab in Catalog.Prefabs) { if (TryParseLootbox(prefab, out var def) && def != null && def.Enabled) { _defsById[def.Id] = def; _defsByPrefab[def.Prefab] = def; _lootboxPrefabNames.Add(def.Prefab); } } } private bool TryParseLootbox(string id, out LootBoxDefinition def) { def = null; string group = "Lootbox:" + id; ConfigEntry<bool> val = Cfg(group, "Enable", value: true); ConfigEntry<string> val2 = Cfg(group, "DisplayName", DefaultDisplayNameFor(id)); ConfigEntry<string> val3 = Cfg(group, "Items", DefaultItemsFor(id)); LootBoxDefinition lootBoxDefinition = LootBoxDefinition.Parse(id, val2.Value, id, Catalog.Bundle, Catalog.Folder, 1, val3.Value, val.Value); if (lootBoxDefinition == null) { return false; } def = lootBoxDefinition; return true; } internal bool IsLootboxPrefab(string prefabName) { return _lootboxPrefabNames.Contains(prefabName); } internal bool TryGetDefByPrefab(string prefabName, out LootBoxDefinition def) { return _defsByPrefab.TryGetValue(prefabName, out def); } private void TryEnsureAllRegisteredImmediately() { if ((Object)(object)ObjectDB.instance != (Object)null && (Object)(object)ZNetScene.instance != (Object)null) { EnsureAllItemsRegistered(); } } private void SetupConfigSync() { if (_configSync == null) { _configSync = new ConfigSync("radamanto.LootBox") { DisplayName = "LootBox", CurrentVersion = "1.0.7", MinimumRequiredVersion = "1.0.7" }; } ServerConfigLocked = Cfg("General", "ServerConfigLocked", value: true, "When true, synced configs can only be changed by the server."); MethodInfo method = _configSync.GetType().GetMethod("AddLockingConfigEntry", BindingFlags.Instance | BindingFlags.Public); if (method != null) { try { method.Invoke(_configSync, new object[1] { ServerConfigLocked }); } catch (Exception) { SyncedConfigEntry<bool> syncedConfigEntry = _configSync.AddConfigEntry<bool>(ServerConfigLocked); syncedConfigEntry.SynchronizedConfig = true; _configSync.IsLocked = ServerConfigLocked.Value; } } else { SyncedConfigEntry<bool> syncedConfigEntry2 = _configSync.AddConfigEntry<bool>(ServerConfigLocked); syncedConfigEntry2.SynchronizedConfig = true; _configSync.IsLocked = ServerConfigLocked.Value; } try { EventInfo @event = _configSync.GetType().GetEvent("ConfigurationSynchronized", BindingFlags.Instance | BindingFlags.Public); if (@event != null) { EventHandler handler = OnConfigurationSynchronized; @event.AddEventHandler(_configSync, handler); } } catch (Exception) { } if (_cfgWatcher == null) { string fileName = Path.GetFileName(((BaseUnityPlugin)this).Config.ConfigFilePath); if (!string.IsNullOrEmpty(fileName)) { _cfgWatcher = new FileSystemWatcher(Paths.ConfigPath, fileName) { IncludeSubdirectories = false, NotifyFilter = (NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite | NotifyFilters.CreationTime), EnableRaisingEvents = true }; _cfgWatcher.Changed += OnCfgChanged; _cfgWatcher.Created += OnCfgChanged; _cfgWatcher.Renamed += OnCfgChanged; } } } private void OnDestroy() { if (_cfgWatcher != null) { try { _cfgWatcher.EnableRaisingEvents = false; _cfgWatcher.Changed -= OnCfgChanged; _cfgWatcher.Created -= OnCfgChanged; _cfgWatcher.Renamed -= OnCfgChanged; _cfgWatcher.Dispose(); } catch { } _cfgWatcher = null; } } private void OnCfgChanged(object sender, FileSystemEventArgs e) { DateTime utcNow = DateTime.UtcNow; if (!((utcNow - _lastCfgEventUtc).TotalMilliseconds < 200.0)) { _lastCfgEventUtc = utcNow; ThreadPool.QueueUserWorkItem(delegate { Thread.Sleep(150); ReloadConfigIfChanged(); }); } } private void ReloadConfigIfChanged() { lock (_cfgLock) { try { if (!File.Exists(((BaseUnityPlugin)this).Config.ConfigFilePath)) { return; } using (FileStream stream = new FileStream(((BaseUnityPlugin)this).Config.ConfigFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { using StreamReader streamReader = new StreamReader(stream); if (string.IsNullOrWhiteSpace(streamReader.ReadToEnd())) { return; } } ((BaseUnityPlugin)this).Config.Reload(); if (_configSync != null) { MethodInfo method = _configSync.GetType().GetMethod("AddLockingConfigEntry", BindingFlags.Instance | BindingFlags.Public); if (method == null && ServerConfigLocked != null) { _configSync.IsLocked = ServerConfigLocked.Value; } } SafeReparse(); } catch { } } } private void OnConfigurationSynchronized(object sender, EventArgs e) { try { if (ServerConfigLocked != null && _configSync != null) { _configSync.IsLocked = ServerConfigLocked.Value; } SafeReparse(); Debug.Log((object)"[LootBox] Config sincronizada pelo servidor e reprocessada."); } catch (Exception arg) { Debug.LogError((object)$"[LootBox] Falha ao aplicar sincronização do servidor: {arg}"); } } private ConfigEntry<T> Cfg<T>(string group, string name, T value, string description = "", bool synced = true) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown ConfigDescription val = new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()); ConfigEntry<T> val2 = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, val); if (_configSync != null && _syncedConfigEntries.Add((ConfigEntryBase)(object)val2)) { SyncedConfigEntry<T> syncedConfigEntry = _configSync.AddConfigEntry<T>(val2); syncedConfigEntry.SynchronizedConfig = synced; } val2.SettingChanged += delegate { DateTime utcNow = DateTime.UtcNow; if (!((utcNow - _lastSettingChangeUtc).TotalMilliseconds < 100.0)) { _lastSettingChangeUtc = utcNow; try { if (_configSync != null && _configSync.IsLocked && (Object)(object)ZNet.instance != (Object)null && !ZNet.instance.IsServer()) { ((BaseUnityPlugin)this).Config.Reload(); Debug.Log((object)"[LootBox] Mudança local rejeitada (ServerConfigLocked ativo). Recarregando config."); return; } } catch { } SafeReparse(); } }; return val2; } private void SafeReparse() { try { ParseAllDefinitions(); TryEnsureAllRegisteredImmediately(); RefreshAllTooltipsAfterConfigChange(); Debug.Log((object)"[LootBox] Definições reprocessadas e tooltips atualizados."); } catch (Exception arg) { Debug.LogError((object)$"[LootBox] Falha ao reprocessar definições: {arg}"); } } } [HarmonyPatch(typeof(InventoryGui), "OnRightClickItem")] internal static class InvGui_RightClickOpen { private static bool Prefix(InventoryGui __instance, InventoryGrid grid, ItemData item, Vector2i pos) { //IL_00de: Unknown result type (might be due to invalid IL or missing references) try { if (item == null || (Object)(object)item.m_dropPrefab == (Object)null) { return true; } string name = ((Object)item.m_dropPrefab).name; GameObject managerObject = Chainloader.ManagerObject; LootboxPlugin lootboxPlugin = ((managerObject != null) ? managerObject.GetComponent<LootboxPlugin>() : null); if ((Object)(object)lootboxPlugin == (Object)null) { return true; } if (!lootboxPlugin.IsLootboxPrefab(name)) { return true; } if (!ZInput.GetKey((KeyCode)304, true) && !ZInput.GetKey((KeyCode)303, true)) { return true; } Player localPlayer = Player.m_localPlayer; Inventory val = (((Object)(object)grid != (Object)null) ? grid.m_inventory : ((localPlayer != null) ? ((Humanoid)localPlayer).GetInventory() : null)); if ((Object)(object)localPlayer == (Object)null || val == null) { return true; } if (lootboxPlugin.OpenFromInventory(localPlayer, val, item, pos)) { return false; } } catch { } return true; } } internal static class LootLoc { private static Dictionary<string, Dictionary<string, string>> _byLang; private static string _currentLang; private static Dictionary<string, string> _active; private static Dictionary<string, string> _fallback; public const string Key_HintOpen = "hint_open"; public const string Key_Rewards = "possible_rewards"; public const string Key_Quality = "abbr_quality"; public const string Key_MsgOpened = "msg_opened"; static LootLoc() { _currentLang = "English"; BuildAll(); _active = _byLang["English"]; _fallback = _active; RefreshActive(); } public static bool RefreshActive() { string currentLang = _currentLang; try { string lang = TryGetGameLanguage(); string text = NormalizeLanguageName(lang); _currentLang = (string.IsNullOrWhiteSpace(text) ? "English" : text); if (_byLang != null && !_byLang.TryGetValue(_currentLang, out _active)) { string key = TryMapCloseName(_currentLang); if (!_byLang.TryGetValue(key, out _active)) { _active = _byLang["English"]; } } if (_byLang != null) { _fallback = _byLang["English"]; } } catch { _currentLang = "English"; if (_byLang != null) { _active = _byLang["English"]; _fallback = _active; } } return !string.Equals(currentLang, _currentLang, StringComparison.Ordinal); } public static string T(string key) { if (string.IsNullOrEmpty(key)) { return key; } if (_active != null && _active.TryGetValue(key, out var value)) { return value; } if (_fallback != null && _fallback.TryGetValue(key, out var value2)) { return value2; } return key; } public static string Tf(string key, params object[] args) { string text = T(key); try { return string.Format(CultureInfo.InvariantCulture, text, args); } catch { return text; } } private static string TryGetGameLanguage() { try { Localization loc = Localization.instance; Type t; if (loc != null) { t = ((object)loc).GetType(); string text = TryMethod("GetSelectedLanguage") ?? TryMethod("GetLanguage") ?? TryMethod("GetCurrentLanguage"); if (!string.IsNullOrWhiteSpace(text)) { return text; } string text2 = TryField("m_language") ?? TryField("m_selectedLanguage"); if (!string.IsNullOrWhiteSpace(text2)) { return text2; } } string TryField(string name) { FieldInfo field = t.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.GetValue(loc) is string text3 && !string.IsNullOrWhiteSpace(text3)) { return text3; } return null; } string TryMethod(string name) { MethodInfo method = t.GetMethod(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method != null && method.ReturnType == typeof(string)) { string text4 = method.Invoke(loc, null) as string; if (!string.IsNullOrWhiteSpace(text4)) { return text4; } } return null; } } catch { } try { string @string = PlayerPrefs.GetString("language", "English"); if (!string.IsNullOrWhiteSpace(@string)) { return @string; } } catch { } return "English"; } private static string NormalizeLanguageName(string lang) { if (string.IsNullOrWhiteSpace(lang)) { return "English"; } string text = lang.Trim().Replace('_', '-'); string text2 = text.ToLowerInvariant(); if (text2.StartsWith("pt") || text2.StartsWith("pt-") || text2.Contains("portugu") || text2.Contains("brazil")) { return "Português (Brasil)"; } if (text2.StartsWith("en") || text2.StartsWith("en-") || text2.Contains("english")) { return "English"; } if (string.Equals(text, "Portuguese (Brazil)", StringComparison.OrdinalIgnoreCase)) { return "Português (Brasil)"; } if (string.Equals(text, "Brazilian Portuguese", StringComparison.OrdinalIgnoreCase)) { return "Português (Brasil)"; } if (string.Equals(text, "pt-BR", StringComparison.OrdinalIgnoreCase)) { return "Português (Brasil)"; } if (string.Equals(text, "en-US", StringComparison.OrdinalIgnoreCase)) { return "English"; } return text; } private static string TryMapCloseName(string normalized) { string text = normalized.ToLowerInvariant(); if (text.StartsWith("pt") || text.Contains("portugu") || text.Contains("brazil")) { return "Português (Brasil)"; } if (text.StartsWith("en") || text.Contains("english")) { return "English"; } return "English"; } private static void BuildAll() { _byLang = LootboxLocalizationDictionary.Data; if (!_byLang.ContainsKey("English")) { _byLang["English"] = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); } } } public static class LootboxLocalizationDictionary { public static readonly Dictionary<string, Dictionary<string, string>> Data; static LootboxLocalizationDictionary() { Dictionary<string, string> value = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) { ["msg_opened"] = "<color=#E3C16F>Opened {0}!</color>", ["hint_open"] = "Hold <color=#FFF58A>Shift</color> + <color=#FFF58A>Right-Click</color> to open.", ["possible_rewards"] = "<color=#E3C16F>Possible rewards:</color>", ["abbr_quality"] = "<color=#C0C0C0>q{0}</color>", ["msg_invalid_item"] = "<color=#E3A16F>Invalid loot box.</color>", ["msg_no_rewards"] = "<color=#E3A16F>This box contained no rewards.</color>", ["msg_inv_full"] = "<color=#E3A16F>Your inventory is full!</color>", ["msg_not_allowed"] = "<color=#E3A16F>You can't open this here.</color>", ["msg_disabled"] = "<color=#E3A16F>This loot box is disabled by the server.</color>", ["tooltip_chance"] = "<color=#C0C0C0>Chance</color>", ["tooltip_amount"] = "<color=#C0C0C0>Amount</color>", ["tooltip_quality"] = "<color=#C0C0C0>Quality</color>" }; Dictionary<string, string> value2 = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) { ["msg_opened"] = "<color=#E3C16F>Abriu {0}!</color>", ["hint_open"] = "Segure <color=#FFF58A>Shift</color> + <color=#FFF58A>Clique direito</color> para abrir.", ["possible_rewards"] = "<color=#E3C16F>Recompensas possíveis:</color>", ["abbr_quality"] = "<color=#C0C0C0>q{0}</color>", ["msg_invalid_item"] = "<color=#E3A16F>Caixa de saque inválida.</color>", ["msg_no_rewards"] = "<color=#E3A16F>Esta caixa não continha recompensas.</color>", ["msg_inv_full"] = "<color=#E3A16F>Seu inventário está cheio!</color>", ["msg_not_allowed"] = "<color=#E3A16F>Você não pode abrir isso aqui.</color>", ["msg_disabled"] = "<color=#E3A16F>Esta caixa está desativada pelo servidor.</color>", ["tooltip_chance"] = "<color=#C0C0C0>Chance</color>", ["tooltip_amount"] = "<color=#C0C0C0>Quantidade</color>", ["tooltip_quality"] = "<color=#C0C0C0>Qualidade</color>" }; Data = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase) { ["English"] = value, ["Português (Brasil)"] = value2, ["Portuguese_Brazilian"] = value2, ["en-US"] = value, ["pt-BR"] = value2 }; } } internal static class LanguageHooksDynamic { public static void Postfix() { try { if (LootLoc.RefreshActive()) { GameObject managerObject = Chainloader.ManagerObject; LootboxPlugin lootboxPlugin = ((managerObject != null) ? managerObject.GetComponent<LootboxPlugin>() : null); if ((Object)(object)lootboxPlugin != (Object)null) { lootboxPlugin.RefreshLocalizedTexts(); } } } catch { } } } internal static class SafeItemDelivery { [<97f3fb7d-43ae-48ec-8a26-23897b225d38>NullableContext(1)] public static void GiveOrDrop(Player player, string prefab, int amount, int quality, int variant, float dropYOffset = 0.5f) { //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)player) || string.IsNullOrWhiteSpace(prefab) || amount <= 0) { return; } Inventory inventory = ((Humanoid)player).GetInventory(); ObjectDB instance = ObjectDB.instance; if (inventory == null || (Object)(object)instance == (Object)null) { return; } GameObject itemPrefab = instance.GetItemPrefab(prefab); if (!Object.op_Implicit((Object)(object)itemPrefab)) { Debug.LogWarning((object)("[LootBox] Prefab não encontrado: " + prefab)); return; } ItemDrop component = itemPrefab.GetComponent<ItemDrop>(); if (!Object.op_Implicit((Object)(object)component)) { Debug.LogWarning((object)("[LootBox] ItemDrop ausente: " + prefab)); return; } int num = Mathf.Max(1, component.m_itemData.m_shared.m_maxStackSize); int num2 = Mathf.Max(1, component.m_itemData.m_shared.m_maxQuality); int num3 = Mathf.Clamp((quality <= 0) ? 1 : quality, 1, num2); int num4 = Mathf.Max(0, variant); int num5 = amount; while (num5 > 0) { int num6 = Mathf.Min(num5, num); num5 -= num6; ItemData val = inventory.AddItem(((Object)itemPrefab).name, num6, num3, num4, 0L, "", false); if (val == null) { Vector3 val2 = ((Component)player).transform.position + new Vector3(0f, dropYOffset, 0f); GameObject val3 = Object.Instantiate<GameObject>(itemPrefab, val2, Quaternion.identity); ItemDrop component2 = val3.GetComponent<ItemDrop>(); if (Object.op_Implicit((Object)(object)component2)) { component2.m_itemData.m_stack = num6; component2.m_itemData.m_quality = num3; component2.m_itemData.m_variant = num4; component2.m_itemData.m_durability = component2.m_itemData.GetMaxDurability(); component2.m_autoPickup = true; } } } } } internal sealed class LootboxCatalog { public string Bundle { get; } public string Folder { get; } public IReadOnlyList<string> Prefabs { get; } private LootboxCatalog(string bundle, string folder, IEnumerable<string> prefabs) { Bundle = bundle ?? "rd_box"; Folder = folder ?? "assets"; Prefabs = prefabs?.ToArray() ?? Array.Empty<string>(); } public static LootboxCatalog FromBundle(string bundle, string folder, params string[] prefabs) { return new LootboxCatalog(bundle, folder, prefabs ?? Array.Empty<string>()); } } internal class LootBoxDefinition { public string Id = ""; public string DisplayName = ""; public string Prefab = ""; public string Bundle = "rd_box"; public string Folder = "assets"; public int Rolls = 1; public bool Enabled = true; public readonly List<LootEntry> Items = new List<LootEntry>(); [return: <a6313b97-aa7e-4d6b-882d-a90990831bc6>Nullable(2)] public static LootBoxDefinition Parse(string id, string displayName, string prefab, string bundle, string folder, int rolls, string itemsBlob, bool enabled = true) { if (string.IsNullOrWhiteSpace(prefab)) { return null; } LootBoxDefinition lootBoxDefinition = new LootBoxDefinition { Id = (id ?? "unknown"), DisplayName = (string.IsNullOrWhiteSpace(displayName) ? (id ?? "unknown") : displayName), Prefab = prefab.Trim(), Bundle = (string.IsNullOrWhiteSpace(bundle) ? "rd_box" : bundle.Trim()), Folder = (string.IsNullOrWhiteSpace(folder) ? "assets" : folder.Trim()), Rolls = 1, Enabled = enabled }; string text = (itemsBlob ?? "").Trim(); if (string.IsNullOrEmpty(text)) { return null; } List<string> list = (from t in text.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries) select t.Trim() into t where !string.IsNullOrEmpty(t) select t).ToList(); int num = 0; while (num < list.Count && num + 2 < list.Count) { LootEntry lootEntry = new LootEntry(); lootEntry.Prefab = list[num++]; lootEntry.Chance = SafeInt(list[num++], 0); ParseAmount(list[num++], out lootEntry.Min, out lootEntry.Max); if (num < list.Count) { if (int.TryParse(list[num], out var result)) { lootEntry.Quality = result; num++; } else { lootEntry.Quality = 1; } } else { lootEntry.Quality = 1; } FixEntry(lootEntry); lootBoxDefinition.Items.Add(lootEntry); } if (lootBoxDefinition.Items.Count == 0) { return null; } return lootBoxDefinition; } private static void ParseAmount(string token, out int min, out int max) { token = token.Trim(); if (token.Contains("-")) { string[] array = token.Split(new char[1] { '-' }); min = SafeInt(array[0], 1); max = SafeInt((array.Length > 1) ? array[1] : array[0], min); } else { min = (max = SafeInt(token, 1)); } if (max < min) { int num = min; min = max; max = num; } } private static void FixEntry(LootEntry e) { if (e.Min < 1) { e.Min = 1; } if (e.Max < e.Min) { e.Max = e.Min; } if (e.Chance < 0) { e.Chance = 0; } if (e.Chance > 100) { e.Chance = 100; } if (e.Quality <= 0) { e.Quality = 1; } if (e.Variant < 0) { e.Variant = 0; } } private static int SafeInt(string s, int def) { int result; return int.TryParse(s, out result) ? result : def; } public string BuildTooltipText() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine(LootLoc.T("hint_open")); stringBuilder.AppendLine(); stringBuilder.AppendLine(LootLoc.T("possible_rewards")); foreach (LootEntry item in Items) { double num = Math.Max(0, Math.Min(100, item.Chance)); string text = ((Math.Abs(num - Math.Round(num)) < 0.0001) ? $"{(int)Math.Round(num)}%" : $"{num:0.0}%"); string text2 = ((item.Min == item.Max) ? $"{item.Min}" : $"{item.Min}-{item.Max}"); string text3 = ((item.Quality > 1) ? (" " + LootLoc.Tf("abbr_quality", item.Quality)) : ""); string text4 = TryLocalizeItemName(item.Prefab); stringBuilder.AppendLine("- " + text4 + ": " + text + " (" + text2 + ")" + text3); } return stringBuilder.ToString().TrimEnd(Array.Empty<char>()); } private static string TryLocalizeItemName(string prefab) { try { ObjectDB instance = ObjectDB.instance; if ((Object)(object)instance != (Object)null) { GameObject itemPrefab = instance.GetItemPrefab(prefab); if (Object.op_Implicit((Object)(object)itemPrefab)) { SharedData val = itemPrefab.GetComponent<ItemDrop>()?.m_itemData?.m_shared; if (val != null && !string.IsNullOrEmpty(val.m_name)) { return Localization.instance.Localize(val.m_name); } } } } catch { } try { string text = "$item_" + prefab.ToLowerInvariant(); string text2 = Localization.instance.Localize(text); if (!string.Equals(text2, text, StringComparison.Ordinal)) { return text2; } } catch { } return prefab; } } internal class LootEntry { public string Prefab = ""; public int Chance = 0; public int Min = 1; public int Max = 1; public int Quality = 1; public int Variant = 0; } internal readonly struct LootResult { public readonly string Prefab; public readonly int Amount; public readonly int Quality; public readonly int Variant; public LootResult(string prefab, int amount, int quality, int variant) { Prefab = prefab ?? ""; Amount = amount; Quality = quality; Variant = variant; } } } [CompilerGenerated] internal sealed class <f740f072-6b65-491c-b3a6-9416ef5f5f62><PrivateImplementationDetails> { internal static uint ComputeStringHash(string s) { uint num = default(uint); if (s != null) { num = 2166136261u; for (int i = 0; i < s.Length; i++) { num = (s[i] ^ num) * 16777619; } } return num; } } namespace Microsoft.CodeAnalysis { [CompilerGenerated] [<496dcfdb-3b53-44b7-8989-4ddbfcc01b8d>Embedded] internal sealed class <496dcfdb-3b53-44b7-8989-4ddbfcc01b8d>EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [<496dcfdb-3b53-44b7-8989-4ddbfcc01b8d>Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class <8fb052af-b43b-495d-8db0-28a94a7fdebf>NullableAttribute : Attribute { public readonly byte[] NullableFlags; public <8fb052af-b43b-495d-8db0-28a94a7fdebf>NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public <8fb052af-b43b-495d-8db0-28a94a7fdebf>NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] [CompilerGenerated] [<496dcfdb-3b53-44b7-8989-4ddbfcc01b8d>Embedded] internal sealed class <e6316c3a-6861-424f-9257-dc50efeeb914>NullableContextAttribute : Attribute { public readonly byte Flag; public <e6316c3a-6861-424f-9257-dc50efeeb914>NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace ItemManager { [PublicAPI] internal enum CraftingTable { Disabled, Inventory, [InternalName("piece_workbench")] Workbench, [InternalName("piece_cauldron")] Cauldron, [InternalName("piece_MeadCauldron")] MeadCauldron, [InternalName("forge")] Forge, [InternalName("piece_artisanstation")] ArtisanTable, [InternalName("piece_stonecutter")] StoneCutter, [InternalName("piece_magetable")] MageTable, [InternalName("piece_preptable")] PrepTable, [InternalName("blackforge")] BlackForge, Custom } [PublicAPI] internal enum ConversionPiece { Disabled, [InternalName("smelter")] Smelter, [InternalName("charcoal_kiln")] CharcoalKiln, [InternalName("blastfurnace")] BlastFurnace, [InternalName("windmill")] Windmill, [InternalName("piece_spinningwheel")] SpinningWheel, [InternalName("eitrrefinery")] EitrRefinery, Custom } [<e6316c3a-6861-424f-9257-dc50efeeb914>NullableContext(1)] [<8fb052af-b43b-495d-8db0-28a94a7fdebf>Nullable(0)] internal class InternalName : Attribute { public readonly string internalName; public InternalName(string internalName) { this.internalName = internalName; } } [PublicAPI] [<8fb052af-b43b-495d-8db0-28a94a7fdebf>Nullable(0)] [<e6316c3a-6861-424f-9257-dc50efeeb914>NullableContext(1)] internal class RequiredResourceList { public readonly List<Requirement> Requirements = new List<Requirement>(); public bool Free; public void Add(string itemName, int amount, int quality = 0) { Requirements.Add(new Requirement { itemName = itemName, amount = amount, quality = quality }); } public void Add(string itemName, ConfigEntry<int> amountConfig, int quality = 0) { Requirements.Add(new Requirement { itemName = itemName, amountConfig = amountConfig, quality = quality }); } } [<e6316c3a-6861-424f-9257-dc50efeeb914>NullableContext(1)] [<8fb052af-b43b-495d-8db0-28a94a7fdebf>Nullable(0)] [PublicAPI] internal class CraftingStationList { public readonly List<CraftingStationConfig> Stations = new List<CraftingStationConfig>(); public void Add(CraftingTable table, int level) { Stations.Add(new CraftingStationConfig { Table = table, level = level }); } public void Add(string customTable, int level) { Stations.Add(new CraftingStationConfig { Table = CraftingTable.Custom, level = level, custom = customTable }); } } [<e6316c3a-6861-424f-9257-dc50efeeb914>NullableContext(1)] [<8fb052af-b43b-495d-8db0-28a94a7fdebf>Nullable(0)] [PublicAPI] internal class ItemRecipe { public readonly RequiredResourceList RequiredItems = new RequiredResourceList(); public readonly RequiredResourceList RequiredUpgradeItems = new RequiredResourceList(); public readonly CraftingStationList Crafting = new CraftingStationList(); public int CraftAmount = 1; public bool RequireOnlyOneIngredient; public float QualityResultAmountMultiplier = 1f; [<8fb052af-b43b-495d-8db0-28a94a7fdebf>Nullable(2)] public ConfigEntryBase RecipeIsActive; } [PublicAPI] internal class Trade { public Trader Trader; public uint Price; public uint Stack = 1u; [<8fb052af-b43b-495d-8db0-28a94a7fdebf>Nullable(2)] public string RequiredGlobalKey; } [Flags] [PublicAPI] internal enum Trader { None = 0, Haldor = 1, Hildir = 2 } internal struct Requirement { [<8fb052af-b43b-495d-8db0-28a94a7fdebf>Nullable(1)] public string itemName; public int amount; [<8fb052af-b43b-495d-8db0-28a94a7fdebf>Nullable(2)] public ConfigEntry<int> amountConfig; [Description("Set to a non-zero value to apply the requirement only for a specific quality")] public int quality; } internal struct CraftingStationConfig { public CraftingTable Table; public int level; [<8fb052af-b43b-495d-8db0-28a94a7fdebf>Nullable(2)] public string custom; } [Flags] internal enum Configurability { Disabled = 0, Recipe = 1, Stats = 2, Drop = 4, Trader = 8, Full = 0xF } [PublicAPI] [<8fb052af-b43b-495d-8db0-28a94a7fdebf>Nullable(0)] [<e6316c3a-6861-424f-9257-dc50efeeb914>NullableContext(1)] internal class DropTargets { public readonly List<DropTarget> Drops = new List<DropTarget>(); public void Add(string creatureName, float chance, int min = 1, int? max = null, bool levelMultiplier = true) { Drops.Add(new DropTarget { creature = creatureName, chance = chance, min = min, max = max.GetValueOrDefault(min), levelMultiplier = levelMultiplier }); } } internal struct DropTarget { [<8fb052af-b43b-495d-8db0-28a94a7fdebf>Nullable(1)] public string creature; public int min; public int max; public float chance; public bool levelMultiplier; } internal enum Toggle { On = 1, Off = 0 } [PublicAPI] [<8fb052af-b43b-495d-8db0-28a94a7fdebf>Nullable(0)] [<e6316c3a-6861-424f-9257-dc50efeeb914>NullableContext(1)] internal class Item { [<8fb052af-b43b-495d-8db0-28a94a7fdebf>Nullable(0)] private class ItemConfig { [<8fb052af-b43b-495d-8db0-28a94a7fdebf>Nullable(new byte[] { 2, 1 })] public ConfigEntry<string> craft; [<8fb052af-b43b-495d-8db0-28a94a7fdebf>Nullable(new byte[] { 2, 1 })] public ConfigEntry<string> upgrade; public ConfigEntry<CraftingTable> table; public ConfigEntry<int> tableLevel; public ConfigEntry<string> customTable; [<8fb052af-b43b-495d-8db0-28a94a7fdebf>Nullable(2)] public ConfigEntry<int> maximumTableLevel; public ConfigEntry<Toggle> requireOneIngredient; public ConfigEntry<float> qualityResultAmountMultiplier; } [<8fb052af-b43b-495d-8db0-28a94a7fdebf>Nullable(0)] private class TraderConfig { public ConfigEntry<Trader> trader; public ConfigEntry<uint> price; public ConfigEntry<uint> stack; public ConfigEntry<string> requiredGlobalKey; } [<e6316c3a-6861-424f-9257-dc50efeeb914>NullableContext(0)] private class RequirementQuality { public int quality; } [<e6316c3a-6861-424f-9257-dc50efeeb914>NullableContext(2)] [<8fb052af-b43b-495d-8db0-28a94a7fdebf>Nullable(0)] private class ConfigurationManagerAttributes { [UsedImplicitly] public int? Order; [UsedImplicitly] public bool? Browsable; [UsedImplicitly] public string Category; [UsedImplicitly] [<8fb052af-b43b-495d-8db0-28a94a7fdebf>Nullable(new byte[] { 2, 1 })] public Action<ConfigEntryBase> CustomDrawer; public Func<bool> browsability; } [PublicAPI] [<e6316c3a-6861-424f-9257-dc50efeeb914>NullableContext(0)] public enum DamageModifier { Normal, Resistant, Weak, Immune, Ignore, VeryResistant, VeryWeak, None } [<e6316c3a-6861-424f-9257-dc50efeeb914>NullableContext(0)] private delegate void setDmgFunc(ref DamageTypes dmg, float value); [<8fb052af-b43b-495d-8db0-28a94a7fdebf>Nullable(0)] private class SerializedRequirements { public readonly List<Requirement> Reqs; public SerializedRequirements(List<Requirement> reqs) { Reqs = reqs; } public SerializedRequirements(string reqs) : this(reqs.Split(new char[1] { ',' }).Select([<e6316c3a-6861-424f-9257-dc50efeeb914>NullableContext(0)] (string r) => { string[] array = r.Split(new char[1] { ':' }); Requirement result = default(Requirement); result.itemName = array[0]; result.amount = ((array.Length <= 1 || !int.TryParse(array[1], out var result2)) ? 1 : result2); result.quality = ((array.Length > 2 && int.TryParse(array[2], out var result3)) ? result3 : 0); return result; }).ToList()) { } public override string ToString() { return string.Join(",", Reqs.Select([<e6316c3a-6861-424f-9257-dc50efeeb914>NullableContext(0)] (Requirement r) => $"{r.itemName}:{r.amount}" + ((r.quality > 0) ? $":{r.quality}" : ""))); } [return: <8fb052af-b43b-495d-8db0-28a94a7fdebf>Nullable(2)] public static ItemDrop fetchByName(ObjectDB objectDB, string name) { GameObject itemPrefab = objectDB.GetItemPrefab(name); ItemDrop obj = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null); if ((Object)(object)obj == (Object)null) { Debug.LogWarning((object)("The required item '" + name + "' does not exist.")); } return obj; } public static Requirement[] toPieceReqs(ObjectDB objectDB, SerializedRequirements craft, SerializedRequirements upgrade) { //IL_00f0: 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_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Expected O, but got Unknown //IL_0194: Expected O, but got Unknown //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Expected O, but got Unknown Dictionary<string, Requirement> dictionary = craft.Reqs.Where((Requirement r) => r.itemName != "").ToDictionary((Func<Requirement, string>)([<e6316c3a-6861-424f-9257-dc50efeeb914>NullableContext(0)] (Requirement r) => r.itemName), (Func<Requirement, Requirement>)([<e6316c3a-6861-424f-9257-dc50efeeb914>NullableContext(0)] (Requirement r) => { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown ItemDrop val6 = ResItem(r); return (val6 != null) ? new Requirement { m_amount = (r.amountConfig?.Value ?? r.amount), m_resItem = val6, m_amountPerLevel = 0 } : ((Requirement)null); })); List<Requirement> list = dictionary.Values.Where([<e6316c3a-6861-424f-9257-dc50efeeb914>NullableContext(0)] (Requirement v) => v != null).ToList(); foreach (Requirement item in upgrade.Reqs.Where((Requirement r) => r.itemName != "")) { if (item.quality > 0) { ItemDrop val = ResItem(item); if (val != null) { Requirement val2 = new Requirement { m_resItem = val, m_amountPerLevel = (item.amountConfig?.Value ?? item.amount), m_amount = 0 }; list.Add(val2); requirementQuality.Add(val2, new RequirementQuality { quality = item.quality }); } continue; } if (!dictionary.TryGetValue(item.itemName, out var value) || value == null) { ItemDrop val3 = ResItem(item); if (val3 != null) { string itemName = item.itemName; Requirement val4 = new Requirement { m_resItem = val3, m_amount = 0 }; Requirement val5 = val4; dictionary[itemName] = val4; value = val5; list.Add(value); } } if (value != null) { value.m_amountPerLevel = item.amountConfig?.Value ?? item.amount; } } return list.ToArray(); [<e6316c3a-6861-424f-9257-dc50efeeb914>NullableContext(2)] ItemDrop ResItem(Requirement r) { return fetchByName(objectDB, r.itemName); } } } [<8fb052af-b43b-495d-8db0-28a94a7fdebf>Nullable(0)] private class SerializedDrop { public readonly List<DropTarget> Drops; public SerializedDrop(List<DropTarget> drops) { Drops = drops; } public SerializedDrop(string drops) { Drops = ((drops == "") ? ((IEnumerable<string>)Array.Empty<string>()) : ((IEnumerable<string>)drops.Split(new char[1] { ',' }))).Select([<e6316c3a-6861-424f-9257-dc50efeeb914>NullableContext(0)] (string r) => { string[] array = r.Split(new char[1] { ':' }); if (array.Length <= 2 || !int.TryParse(array[2], out var result)) { result = 1; } if (array.Length <= 3 || !int.TryParse(array[3], out var result2)) { result2 = result; } bool levelMultiplier = array.Length <= 4 || array[4] != "0"; DropTarget result3 = default(DropTarget); result3.creature = array[0]; result3.chance = ((array.Length > 1 && float.TryParse(array[1], out var result4)) ? result4 : 1f); result3.min = result; result3.max = result2; result3.levelMultiplier = levelMultiplier; return result3; }).ToList(); } public override string ToString() { return string.Join(",", Drops.Select([<e6316c3a-6861-424f-9257-dc50efeeb914>NullableContext(0)] (DropTarget r) => $"{r.creature}:{r.chance.ToString(CultureInfo.InvariantCulture)}:{r.min}:" + ((r.min == r.max) ? "" : $"{r.max}") + (r.levelMultiplier ? "" : ":0"))); } [return: <8fb052af-b43b-495d-8db0-28a94a7fdebf>Nullable(2)] private static Character fetchByName(ZNetScene netScene, string name) { GameObject prefab = netScene.GetPrefab(name); Character obj = ((prefab != null) ? prefab.GetComponent<Character>() : null); if ((Object)(object)obj == (Object)null) { Debug.LogWarning((object)("The drop target character '" + name + "' does not exist.")); } return obj; } public Dictionary<Character, Drop> toCharacterDrops(ZNetScene netScene, GameObject item) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown Dictionary<Character, Drop> dictionary = new Dictionary<Character, Drop>(); foreach (DropTarget drop in Drops) { Character val = fetchByName(netScene, drop.creature); if (val != null) { dictionary[val] = new Drop { m_prefab = item, m_amountMin = drop.min, m_amountMax = drop.max, m_chance = drop.chance, m_levelMultiplier = drop.levelMultiplier }; } } return dictionary; } } private static readonly List<Item> registeredItems = new List<Item>(); private static readonly Dictionary<ItemDrop, Item> itemDropMap = new Dictionary<ItemDrop, Item>(); private static Dictionary<Item, Dictionary<string, List<Recipe>>> activeRecipes = new Dictionary<Item, Dictionary<string, List<Recipe>>>(); [<8fb052af-b43b-495d-8db0-28a94a7fdebf>Nullable(new byte[] { 1, 1, 2 })] private static Dictionary<Recipe, ConfigEntryBase> hiddenCraftRecipes = new Dictionary<Recipe, ConfigEntryBase>(); [<8fb052af-b43b-495d-8db0-28a94a7fdebf>Nullable(new byte[] { 1, 1, 2 })] private static Dictionary<Recipe, ConfigEntryBase> hiddenUpgradeRecipes = new Dictionary<Recipe, ConfigEntryBase>(); private static Dictionary<Item, Dictionary<string, ItemConfig>> itemCraftConfigs = new Dictionary<Item, Dictionary<string, ItemConfig>>(); private static Dictionary<Item, ConfigEntry<string>> itemDropConfigs = new Dictionary<Item, ConfigEntry<string>>(); private Dictionary<CharacterDrop, Drop> characterDrops = new Dictionary<CharacterDrop, Drop>(); private readonly Dictionary<ConfigEntryBase, Action> statsConfigs = new Dictionary<ConfigEntryBase, Action>(); private static readonly ConditionalWeakTable<Requirement, RequirementQuality> requirementQuality = new ConditionalWeakTable<Requirement, RequirementQuality>(); public static Configurability DefaultConfigurability = Configurability.Full; public Configurability? Configurable; private Configurability configurationVisible = Configurability.Full; [<8fb052af-b43b-495d-8db0-28a94a7fdebf>Nullable(2)] private TraderConfig traderConfig; public readonly GameObject Prefab; [Description("Specifies the maximum required crafting station level to upgrade and repair the item.\nDefault is calculated from crafting station level and maximum quality.")] public int MaximumRequiredStationLevel = int.MaxValue; [Description("Assigns the item as a drop item to a creature.\nUses a creature name, a drop chance and a minimum and maximum amount.")] public readonly DropTargets DropsFrom = new DropTargets(); [Description("Configures whether the item can be bought at the trader.\nDon't forget to set cost to something above 0 or the item will be sold for free.")] public readonly Trade Trade = new Trade(); internal List<Conversion> Conversions = new List<Conversion>(); internal List<ItemConversion> conversions = new List<ItemConversion>(); public Dictionary<string, ItemRecipe> Recipes = new Dictionary<string, ItemRecipe>(); [<8fb052af-b43b-495d-8db0-28a94a7fdebf>Nullable(2)] private LocalizeKey _name; [<8fb052af-b43b-495d-8db0-28a94a7fdebf>Nullable(2)] private LocalizeKey _description; [<8fb052af-b43b-495d-8db0-28a94a7fdebf>Nullable(2)] private static object configManager; [<8fb052af-b43b-495d-8db0-28a94a7fdebf>Nullable(2)] private static Localization _english; [<8fb052af-b43b-495d-8db0-28a94a7fdebf>Nullable(2)] private static BaseUnityPlugin _plugin; private static bool hasConfigSync = true; [<8fb052af-b43b-495d-8db0-28a94a7fdebf>Nullable(2)] private static object _configSync; private Configurability configurability => Configurable ?? DefaultConfigurability; [Description("Specifies the resources needed to craft the item.\nUse .Add to add resources with their internal ID and an amount.\nUse one .Add for each resource type the item should need.")] public RequiredResourceList RequiredItems => this[""].RequiredItems; [Description("Specifies the resources needed to upgrade the item.\nUse .Add to add resources with their internal ID and an amount. This amount will be multipled by the item quality level.\nUse one .Add for each resource type the upgrade should need.")] public RequiredResourceList RequiredUpgradeItems => this[""].RequiredUpgradeItems; [Description("Specifies the crafting station needed to craft the item.\nUse .Add to add a crafting station, using the CraftingTable enum and a minimum level for the crafting station.\nUse one .Add for each crafting station.")] public CraftingStationList Crafting => this[""].Crafting; [Description("Specifies a config entry which toggles whether a recipe is active.")] [<8fb052af-b43b-495d-8db0-28a94a7fdebf>Nullable(2)] public ConfigEntryBase RecipeIsActive { [<e6316c3a-6861-424f-9257-dc50efeeb914>NullableContext(2)] get { return this[""].RecipeIsActive; } [<e6316c3a-6861-424f-9257-dc50efeeb914>NullableContext(2)] set { this[""].RecipeIsActive = value; } } [Description("Specifies the number of items that should be given to the player with a single craft of the item.\nDefaults to 1.")] public int CraftAmount { get { return this[""].CraftAmount; } set { this[""].CraftAmount = value; } } public bool RequireOnlyOneIngredient { get { return this[""].RequireOnlyOneIngredient; } set { this[""].RequireOnlyOneIngredient = value; } } public float QualityResultAmountMultiplier { get { return this[""].QualityResultAmountMultiplier; } set { this[""].QualityResultAmountMultiplier = value; } } public ItemRecipe this[string name] { get { if (Recipes.TryGetValue(name, out var value)) { return value; } return Recipes[name] = new ItemRecipe(); } } public LocalizeKey Name { get { LocalizeKey name = _name; if (name != null) { return name; } SharedData shared = Prefab.GetComponent<ItemDrop>().m_itemData.m_shared; if (shared.m_name.StartsWith("$")) { _name = new LocalizeKey(shared.m_name); } else { string text = "$item_" + ((Object)Prefab).name.Replace(" ", "_"); _name = new LocalizeKey(text).English(shared.m_name); shared.m_name = text; } return _name; } } public LocalizeKey Description { get { LocalizeKey description = _description; if (description != null) { return description; } SharedData shared = Prefab.GetComponent<ItemDrop>().m_itemData.m_shared; if (shared.m_description.StartsWith("$")) { _description = new LocalizeKey(shared.m_description); } else { string text = "$itemdesc_" + ((Object)Prefab).name.Replace(" ", "_"); _description = new LocalizeKey(text).English(shared.m_description); shared.m_description = text; } return _description; } } private static Localization english => _english ?? (_english = LocalizationCache.ForLanguage("English")); private static BaseUnityPlugin plugin { get { //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Expected O, but got Unknown if (_plugin == null) { IEnumerable<TypeInfo> source; try { source = Assembly.GetExecutingAssembly().DefinedTypes.ToList(); } catch (ReflectionTypeLoadException ex) { source = from t in ex.Types where t != null select t.GetTypeInfo(); } _plugin = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First([<e6316c3a-6861-424f-9257-dc50efeeb914>NullableContext(0)] (TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t))); } return _plugin; } } [<8fb052af-b43b-495d-8db0-28a94a7fdebf>Nullable(2)] private static object configSync { [<e6316c3a-6861-424f-9257-dc50efeeb914>NullableContext(2)] get { if (_configSync == null && hasConfigSync) { Type type = Assembly.GetExecutingAssembly().GetType("ServerSync.ConfigSync"); if ((object)type != null) { _configSync = Activator.CreateInstance(type, plugin.Info.Metadata.GUID + " ItemManager"); type.GetField("CurrentVersion").SetValue(_configSync, plugin.Info.Metadata.Version.ToString()); type.GetProperty("IsLocked").SetValue(_configSync, true); } else { hasConfigSync = false; } } return _configSync; } } public Item(string assetBundleFileName, string prefabName, string folderName = "assets") : this(PrefabManager.RegisterAssetBundle(assetBundleFileName, folderName), prefabName) { } public Item(AssetBundle bundle, string prefabName) : this(PrefabManager.RegisterPrefab(bundle, prefabName, addToObjectDb: true), skipRegistering: true) { } public Item(GameObject prefab, bool skipRegistering = false) { if (!skipRegistering) { PrefabManager.RegisterPrefab(prefab, addToObjectDb: true); } Prefab = prefab; registeredItems.Add(this); itemDropMap[Prefab.GetComponent<ItemDrop>()] = this; Prefab.GetComponent<ItemDrop>().m_itemData.m_dropPrefab = Prefab; } public void ToggleConfigurationVisibility(Configurability visible) { configurationVisible = visible; if (itemDropConfigs.TryGetValue(this, out var value)) { Toggle((ConfigEntryBase)(object)value, Configurability.Drop); } if (itemCraftConfigs.TryGetValue(this, out var value2)) { foreach (ItemConfig value4 in value2.Values) { ToggleObj(value4, Configurability.Recipe); } } foreach (Conversion conversion in Conversions) { if (conversion.config != null) { ToggleObj(conversion.config, Configurability.Recipe); } } foreach (KeyValuePair<ConfigEntryBase, Action> statsConfig in statsConfigs) { Toggle(statsConfig.Key, Configurability.Stats); if ((visible & Configurability.Stats) != 0) { statsConfig.Value(); } } reloadConfigDisplay(); void Toggle(ConfigEntryBase cfg, Configurability check) { object[] tags = cfg.Description.Tags; for (int j = 0; j < tags.Length; j++) { if (tags[j] is ConfigurationManagerAttributes configurationManagerAttributes) { configurationManagerAttributes.Browsable = (visible & check) != 0 && (configurationManagerAttributes.browsability == null || configurationManagerAttributes.browsability()); } } } void ToggleObj(object obj, Configurability check) { FieldInfo[] fields = obj.GetType().GetFields(); for (int i = 0; i < fields.Length; i++) { object? value3 = fields[i].GetValue(obj); ConfigEntryBase val = (ConfigEntryBase)((value3 is ConfigEntryBase) ? value3 : null); if (val != null) { Toggle(val, check); } } } } internal static void reloadConfigDisplay() { object obj = configManager?.GetType().GetProperty("DisplayingWindow").GetValue(configManager); if (obj is bool && (bool)obj) { configManager.GetType().GetMethod("BuildSettingList").Invoke(configManager, Array.Empty<object>()); } } private void UpdateItemTableConfig(string recipeKey, CraftingTable table, string customTableValue) { if (activeRecipes.ContainsKey(this) && activeRecipes[this].TryGetValue(recipeKey, out var value)) { value.First().m_enabled = table != CraftingTable.Disabled; if ((uint)table <= 1u) { value.First().m_craftingStation = null; } else if (table == CraftingTable.Custom) { Recipe obj = value.First(); GameObject prefab = ZNetScene.instance.GetPrefab(customTableValue); obj.m_craftingStation = ((prefab != null) ? prefab.GetComponent<CraftingStation>() : null); } else { value.First().m_craftingStation = ZNetScene.instance.GetPrefab(getInternalName(table)).GetComponent<CraftingStation>(); } } } private void UpdateCraftConfig(string recipeKey, SerializedRequirements craftRequirements, SerializedRequirements upgradeRequirements) { if (!Object.op_Implicit((Object)(object)ObjectDB.instance) || !activeRecipes.ContainsKey(this) || !activeRecipes[this].TryGetValue(recipeKey, out var value)) { return; } foreach (Recipe item in value) { item.m_resources = SerializedRequirements.toPieceReqs(ObjectDB.instance, craftRequirements, upgradeRequirements); } } internal static void Patch_FejdStartup() { //IL_0e8a: Unknown result type (might be due to invalid IL or missing references) //IL_0e8f: Unknown result type (might be due to invalid IL or missing references) //IL_2155: Unknown result type (might be due to invalid IL or missing references) //IL_215f: Expected O, but got Unknown //IL_0f53: Unknown result type (might be due to invalid IL or missing references) //IL_0f56: Unknown result type (might be due to invalid IL or missing references) //IL_0fac: Expected I4, but got Unknown //IL_0b79: Unknown result type (might be due to invalid IL or missing references) //IL_0b83: Expected O, but got Unknown //IL_030b: Unknown result type (might be due to invalid IL or missing references) //IL_0315: Expected O, but got Unknown //IL_10e0: Unknown result type (might be due to invalid IL or missing references) //IL_10e3: Unknown result type (might be due to invalid IL or missing references) //IL_10e5: Invalid comparison between Unknown and I4 //IL_10e7: Unknown result type (might be due to invalid IL or missing references) //IL_10eb: Invalid comparison between Unknown and I4 //IL_0c9c: Unknown result type (might be due to invalid IL or missing references) //IL_0ca6: Expected O, but got Unknown //IL_0d47: Unknown result type (might be due to invalid IL or missing references) //IL_0d51: Expected O, but got Unknown //IL_10ed: Unknown result type (might be due to invalid IL or missing references) //IL_10f1: Invalid comparison between Unknown and I4 //IL_03fe: Unknown result type (might be due to invalid IL or missing references) //IL_0408: Expected O, but got Unknown //IL_0dfb: Unknown result type (might be due to invalid IL or missing references) //IL_0e05: Expected O, but got Unknown //IL_12ec: Unknown result type (might be due to invalid IL or missing references) //IL_12ef: Unknown result type (might be due to invalid IL or missing references) //IL_12f1: Invalid comparison between Unknown and I4 //IL_12f3: Unknown result type (might be due to invalid IL or missing references) //IL_12f7: Unknown result type (might be due to invalid IL or missing references) //IL_12f9: Invalid comparison between Unknown and I4 //IL_0539: Unknown result type (might be due to invalid IL or missing references) //IL_0543: Expected O, but got Unknown //IL_12fb: Unknown result type (might be due to invalid IL or missing references) //IL_12ff: Invalid comparison between Unknown and I4 //IL_13d4: Unknown result type (might be due to invalid IL or missing references) //IL_13d9: Unknown result type (might be due to invalid IL or missing references) //IL_13db: Unknown result type (might be due to invalid IL or missing references) //IL_13de: Invalid comparison between Unknown and I4 //IL_13e0: Unknown result type (might be due to invalid IL or missing references) //IL_13e4: Invalid comparison between Unknown and I4 //IL_06f0: Unknown result type (might be due to invalid IL or missing references) //IL_06fa: Expected O, but got Unknown //IL_0651: Unknown result type (might be due to invalid IL or missing references) //IL_065b: Expected O, but got Unknown //IL_1453: Unknown result type (might be due to invalid IL or missing references) //IL_1456: Unknown result type (might be due to invalid IL or missing references) //IL_1458: Invalid comparison between Unknown and I4 //IL_07fa: Unknown result type (might be due to invalid IL or missing references) //IL_0804: Expected O, but got Unknown //IL_145a: Unknown result type (might be due to invalid IL or missing references) //IL_145e: Unknown result type (might be due to invalid IL or missing references) //IL_1460: Invalid comparison between Unknown and I4 //IL_1462: Unknown result type (might be due to invalid IL or missing references) //IL_1466: Invalid comparison between Unknown and I4 //IL_15a3: Unknown result type (might be due to invalid IL or missing references) //IL_15a6: Invalid comparison between Unknown and I4 //IL_17a3: Unknown result type (might be due to invalid IL or missing references) //IL_17aa: Invalid comparison between Unknown and I4 //IL_1873: Unknown result type (might be due to invalid IL or missing references) //IL_1878: Unknown result type (might be due to invalid IL or missing references) //IL_187a: Unknown result type (might be due to invalid IL or missing references) //IL_187e: Unknown result type (might be due to invalid IL or missing references) //IL_1880: Invalid comparison between Unknown and I4 //IL_18ef: Unknown result type (might be due to invalid IL or missing references) //IL_18f2: Unknown result type (might be due to invalid IL or missing references) //IL_18f4: Invalid comparison between Unknown and I4 //IL_1519: Unknown result type (might be due to invalid IL or missing references) //IL_151e: Unknown result type (might be due to invalid IL or missing references) //IL_18f6: Unknown result type (might be due to invalid IL or missing references) //IL_18fa: Invalid comparison between Unknown and I4 //IL_18fc: Unknown result type (might be due to invalid IL or missing references) //IL_1900: Invalid comparison between Unknown and I4 //IL_1d6d: Unknown result type (might be due to invalid IL or missing references) //IL_1d70: Invalid comparison between Unknown and I4 Type type = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault([<e6316c3a-6861-424f-9257-dc50efeeb914>NullableContext(0)] (Assembly a) => a.GetName().Name == "ConfigurationManager")?.GetType("ConfigurationManager.ConfigurationManager"); if (DefaultConfigurability != 0) { bool saveOnConfigSet = plugin.Config.SaveOnConfigSet; plugin.Config.SaveOnConfigSet = false; foreach (Item item4 in registeredItems.Where([<e6316c3a-6861-424f-9257-dc50efeeb914>NullableContext(0)] (Item i) => i.configurability != Configurability.Disabled)) { Item item3 = item4; string name2 = item3.Prefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_name; string englishName = new Regex("[=\\n\\t\\\\\"\\'\\[\\]]*").Replace(english.Localize(name2), "").Trim(); string localizedName = Localization.instance.Localize(name2).Trim(); int order = 0; if ((item3.configurability & Configurability.Recipe) != 0) { itemCraftConfigs[item3] = new Dictionary<string, ItemConfig>(); foreach (string item5 in item3.Recipes.Keys.DefaultIfEmpty("")) { string configKey = item5; string text = ((configKey == "") ? "" : (" (" + configKey + ")")); if (!item3.Recipes.ContainsKey(configKey) || item3.Recipes[configKey].Crafting.Stations.Count <= 0) { continue; } ItemConfig itemConfig2 = (itemCraftConfigs[item3][configKey] = new ItemConfig()); ItemConfig cfg = itemConfig2; List<ConfigurationManagerAttributes> hideWhenNoneAttributes = new List<ConfigurationManagerAttributes>(); cfg.table = config(englishName, "Crafting Station" + text, item3.Recipes[configKey].Crafting.Stations.First().Table, new ConfigDescription("Crafting station where " + englishName + " is available.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = (order -= 1), Browsable = ((item3.configurationVisible & Configurability.Recipe) != 0), Category = localizedName } })); ConfigurationManagerAttributes customTableAttributes = new ConfigurationManagerAttributes { Order = (order -= 1), browsability = CustomTableBrowsability, Browsable = (CustomTableBrowsability() && (item3.configurationVisible & Configurability.Recipe) != 0), Category = localizedName }; cfg.customTable = config(englishName, "Custom Crafting Station" + text, item3.Recipes[configKey].Crafting.Stations.First().custom ?? "", new ConfigDescription("", (AcceptableValueBase)null, new object[1] { customTableAttributes })); cfg.table.SettingChanged += TableConfigChanged; cfg.customTable.SettingChanged += TableConfigChanged; ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes { Order = (order -= 1), browsability = TableLevelBrowsability, Browsable = (TableLevelBrowsability() && (item3.configurationVisible & Configurability.Recipe) != 0), Category = localizedName }; hideWhenNoneAttributes.Add(configurationManagerAttributes); cfg.tableLevel = config(englishName, "Crafting Station Level" + text, item3.Recipes[configKey].Crafting.Stations.First().level, new ConfigDescription("Required crafting station level to craft " + englishName + ".", (AcceptableValueBase)null, new object[1] { configurationManagerAttributes })); cfg.tableLevel.SettingChanged += [<e6316c3a-6861-424f-9257-dc50efeeb914>NullableContext(0)] (object _, EventArgs _) => { if (activeRecipes.ContainsKey(item3) && activeRecipes[item3].TryGetValue(configKey, out var value6)) { value6.First().m_minStationLevel = cfg.tableLevel.Value; } }; if (item3.Prefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_maxQuality > 1) { cfg.maximumTableLevel = config(englishName, "Maximum Crafting Station Level" + text, (item3.MaximumRequiredStationLevel == int.MaxValue) ? (item3.Recipes[configKey].Crafting.Stations.First().level + item3.Prefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_maxQuality - 1) : item3.MaximumRequiredStationLevel, new ConfigDescription("Maximum crafting station level to upgrade and repair " + englishName + ".", (AcceptableValueBase)null, new object[1] { configurationManagerAttributes })); } cfg.requireOneIngredient = config(englishName, "Require only one resource" + text, item3.Recipes[configKey].RequireOnlyOneIngredient ? Toggle.On : Toggle.Off, new ConfigDescription("Whether only one of the ingredients is needed to craft " + englishName, (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = (order -= 1), Category = localizedName } })); ConfigurationManagerAttributes qualityResultAttributes = new ConfigurationManagerAttributes { Order = (order -= 1), browsability = QualityResultBrowsability, Browsable = (QualityResultBrowsability() && (item3.configurationVisible & Configurability.Recipe) != 0), Category = localizedName }; cfg.requireOneIngredient.SettingChanged += [<e6316c3a-6861-424f-9257-dc50efeeb914>NullableContext(0)] (object _, EventArgs _) => { if (activeRecipes.ContainsKey(item3) && activeRecipes[item3].TryGetValue(configKey, out var value5)) { foreach (Recipe item6 in value5) { item6.m_requireOnlyOneIngredient = cfg.requireOneIngredient.Value == Toggle.On; } } qualityResultAttributes.Browsable = QualityResultBrowsability(); reloadConfigDisplay(); }; cfg.qualityResultAmountMultiplier = config(englishName, "Quality Multiplier" + text, item3.Recipes[configKey].QualityResultAmountMultiplier, new ConfigDescription("Multiplies the crafted amount based on the quality of the resources when crafting " + englishName + ". Only works, if Require Only One Resource is true.", (AcceptableValueBase)null, new object[1] { qualityResultAttributes })); cfg.qualityResultAmountMultiplier.SettingChanged += [<e6316c3a-6861-424f-9257-dc50efeeb914>NullableContext(0)] (object _, EventArgs _) => { if (activeRecipes.ContainsKey(item3) && activeRecipes[item3].TryGetValue(configKey, out var value4)) { foreach (Recipe item7 in value4) { item7.m_qualityResultAmountMultiplier = cfg.qualityResultAmountMultiplier.Value; } } }; if ((!item3.Recipes[configKey].RequiredItems.Free || item3.Recipes[configKey].RequiredItems.Requirements.Count > 0) && item3.Recipes[configKey].RequiredItems.Requirements.All((Requirement r) => r.amountConfig == null)) { cfg.craft = itemConfig("Crafting Costs" + text, new SerializedRequirements(item3.Recipes[configKey].RequiredItems.Requirements).ToString(), "Item costs to craft " + englishName, isUpgrade: false); } if (item3.Prefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_maxQuality > 1 && (!item3.Recipes[configKey].RequiredUpgradeItems.Free || item3.Recipes[configKey].RequiredUpgradeItems.Requirements.Count > 0) && item3.Recipes[configKey].RequiredUpgradeItems.Requirements.All((Requirement r) => r.amountConfig == null)) { cfg.upgrade = itemConfig("Upgrading Costs" + text, new SerializedRequirements(item3.Recipes[configKey].RequiredUpgradeItems.Requirements).ToString(), "Item costs per level to upgrade " + englishName, isUpgrade: true); } if (cfg.craft != null) { cfg.craft.SettingChanged += ConfigChanged; } if (cfg.upgrade != null) { cfg.upgrade.SettingChanged += ConfigChanged; } void ConfigChanged(object o, EventArgs e) { item3.UpdateCraftConfig(configKey, new SerializedRequirements(cfg.craft?.Value ?? ""), new SerializedRequirements(cfg.upgrade?.Value ?? "")); } bool CustomTableBrowsability() { return cfg.table.Value == CraftingTable.Custom; } bool ItemBrowsability() { return cfg.table.Value != CraftingTable.Disabled; } bool QualityResultBrowsability() { return cfg.requireOneIngredient.Value == Toggle.On; } void TableConfigChanged(object o, EventArgs e) { item3.UpdateItemTableConfig(configKey, cfg.table.Value, cfg.customTable.Value); customTableAttributes.Browsable = cfg.table.Value == CraftingTable.Custom; foreach (ConfigurationManagerAttributes item8 in hideWhenNoneAttributes) { item8.Browsable = cfg.table.Value != CraftingTable.Disabled; } reloadConfigDisplay(); } bool TableLevelBrowsability() { return cfg.table.Value != CraftingTable.Disabled; } ConfigEntry<string> itemConfig(string name, string value, string desc, bool isUpgrade) { //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Expected O, but got Unknown ConfigurationManagerAttributes configurationManagerAttributes3 = new ConfigurationManagerAttributes { CustomDrawer = drawRequirementsConfigTable(item3, isUpgrade), Order = (order -= 1), browsability = ItemBrowsability, Browsable = (ItemBrowsability() && (item3.configurationVisible & Configurability.Recipe) != 0), Category = localizedName }; hideWhenNoneAttributes.Add(configurationManagerAttributes3); return config(englishName, name, value, new ConfigDescription(desc, (AcceptableValueBase)null, new object[1] { configurationManagerAttributes3 })); } } if ((item3.configurability & Configurability.Drop) != 0) { ConfigEntry<string> val3 = (itemDropConfigs[item3] = config(englishName, "Drops from", new SerializedDrop(item3.DropsFrom.Drops).ToString(), new ConfigDescription(englishName + " drops from this creature.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { CustomDrawer = drawDropsConfigTable, Category = localizedName, Browsable = ((item3.configurationVisible & Configurability.Drop) != 0) } }))); val3.SettingChanged += [<e6316c3a-6861-424f-9257-dc50efeeb914>NullableContext(0)] (object _, EventArgs _) => { item3.UpdateCharacterDrop(); }; } for (int j = 0; j < item3.Conversions.Count; j++) { string text2 = ((item3.Conversions.Count > 1) ? $"{j + 1}. " : ""); Conversion conversion = item3.Conversions[j]; conversion.config = new Conversion.ConversionConfig(); int index = j; conversion.config.input = config(englishName, text2 + "Conversion Input Item", conversion.Input, new ConfigDescription("Input item to create " + englishName, (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Category = localizedName, Browsable = ((item3.configurationVisible & Configurability.Recipe) != 0) } })); conversion.config.input.SettingChanged += [<e6316c3a-6861-424f-9257-dc50efeeb914>NullableContext(0)] (object _, EventArgs _) => { if (index < item3.conversions.Count) { ObjectDB instance = ObjectDB.instance; if (instance != null) { ItemDrop from = SerializedRequirements.fetchByName(instance, conversion.config.input.Value); item3.conversions[index].m_from = from; UpdatePiece(); } } }; conversion.config.piece = config(englishName, text2 + "Conversion Piece", conversion.Piece, new ConfigDescription("Conversion piece used to create " + englishName, (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Category = localizedName, Browsable = ((item3.configurationVisible & Configurability.Recipe) != 0) } })); conversion.config.piece.SettingChanged += [<e6316c3a-6861-424f-9257-dc50efeeb914>NullableContext(0)] (object _, EventArgs _) => { UpdatePiece(); }; conversion.config.customPiece = config(englishName, text2 + "Conversion Custom Piece", conversion.customPiece ?? "", new ConfigDescription("Custom conversion piece to create " + englishName, (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Category = localizedName, Browsable = ((item3.configurationVisible & Configurability.Recipe) != 0) } })); conversion.config.customPiece.SettingChanged += [<e6316c3a-6861-424f-9257-dc50efeeb914>NullableContext(0)] (object _, EventArgs _) => { UpdatePiece(); }; void UpdatePiece() { if (index < item3.conversions.Count && Object.op_Implicit((Object)(object)ZNetScene.instance)) { string text3 = ((conversion.config.piece.Value == ConversionPiece.Disabled) ? null : ((conversion.config.piece.Value == ConversionPiece.Custom) ? conversion.config.customPiece.Value : getInternalName(conversion.config.piece.Value))); string activePiece = conversion.config.activePiece; if (conversion.config.activePiece != null) { int num = ZNetScene.instance.GetPrefab(conversion.config.activePiece).GetComponent<Smelter>().m_conversion.IndexOf(item3.conversions[index]); if (num >= 0) { Smelter[] array3 = Resources.FindObjectsOfTypeAll<Smelter>(); foreach (Smelter val4 in array3) { if (Utils.GetPrefabName(((Component)val4).gameObject) == activePiece) { val4.m_conversion.RemoveAt(num); } } } conversion.config.activePiece = null; } if (item3.conversions[index].m_from != null && conversion.config.piece.Value != 0) { GameObject prefab = ZNetScene.instance.GetPrefab(text3); if (((prefab != null) ? prefab.GetComponent<Smelter>() : null) != null) { conversion.config.activePiece = text3; Smelter[] array3 = Resources.FindObjectsOfTypeAll<Smelter>(); foreach (Smelter val5 in array3) { if (Utils.GetPrefabName(((Component)val5).gameObject) == text3) { val5.m_conversion.Add(item3.conversions[index]); } } } } } } } } if ((item3.configurability & Configurability.Stats) != 0) { item3.statsConfigs.Clear(); SharedData shared2 = item3.Prefab.GetComponent<ItemDrop>().m_itemData.m_shared; ItemType itemType = shared2.m_itemType; statcfg<float>("Weight", "Weight of " + englishName + ".", (SharedData shared) => shared.m_weight, delegate(SharedData shared, float value) { shared.m_weight = value; }); statcfg<int>("Trader Value", "Trader value of " + englishName + ".", (SharedData shared) => shared.m_value, delegate(SharedData shared, int value) { shared.m_value = value; }); bool flag; switch (itemType - 3) { case 0: case 1: case 2: case 3: case 4: case 8: case 9: case 11: case 14: case 16: case 19: flag = true; break; default: flag = false; break; } if (flag) { statcfg<float>("Durability", "Durability of " + englishName + ".", (SharedData shared) => shared.m_maxDurability, delegate(SharedData shared, float valu