Please disclose if your mod was created primarily using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Recycle N Reclaim v1.4.0
Recycle_N_Reclaim.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.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using Auga; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using JetBrains.Annotations; using Jewelcrafting; using LocalizationManager; using Microsoft.CodeAnalysis; using Recycle_N_Reclaim.GamePatches.MarkAsTrash; using Recycle_N_Reclaim.GamePatches.Recycling; using Recycle_N_Reclaim.GamePatches.UI; using Recycle_N_Reclaim.Managers; using Recycle_N_Reclaim.YAMLStuff; using ServerSync; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Core.Tokens; using YamlDotNet.Helpers; using YamlDotNet.Serialization; using YamlDotNet.Serialization.BufferedDeserialization; using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators; using YamlDotNet.Serialization.Converters; using YamlDotNet.Serialization.EventEmitters; using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization.NodeDeserializers; using YamlDotNet.Serialization.NodeTypeResolvers; using YamlDotNet.Serialization.ObjectFactories; using YamlDotNet.Serialization.ObjectGraphTraversalStrategies; using YamlDotNet.Serialization.ObjectGraphVisitors; using YamlDotNet.Serialization.Schemas; using YamlDotNet.Serialization.TypeInspectors; using YamlDotNet.Serialization.TypeResolvers; using YamlDotNet.Serialization.Utilities; using YamlDotNet.Serialization.ValueDeserializers; [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: ComVisible(false)] [assembly: AssemblyTrademark("")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyProduct("Recycle_N_Reclaim")] [assembly: AssemblyCompany("Azumatt")] [assembly: Guid("4358610B-F3F4-4843-B7AF-98B7BC60DCDE")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyTitle("Recycle_N_Reclaim")] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: CompilationRelaxations(8)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyDescription("")] [assembly: AssemblyFileVersion("1.4.0")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.4.0.0")] [module: UnverifiableCode] [module: <fac50906-3bde-460d-98de-2a6e5ea09b08>RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [<1905cf53-6ed0-488b-898d-837b48827112>Embedded] [CompilerGenerated] internal sealed class <1905cf53-6ed0-488b-898d-837b48827112>EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] [<1905cf53-6ed0-488b-898d-837b48827112>Embedded] internal sealed class <6829e025-ae21-47c8-ac92-c1c427b43056>NullableAttribute : Attribute { public readonly byte[] NullableFlags; public <6829e025-ae21-47c8-ac92-c1c427b43056>NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public <6829e025-ae21-47c8-ac92-c1c427b43056>NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] [<1905cf53-6ed0-488b-898d-837b48827112>Embedded] internal sealed class <298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContextAttribute : Attribute { public readonly byte Flag; public <298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContextAttribute(byte P_0) { Flag = P_0; } } [<1905cf53-6ed0-488b-898d-837b48827112>Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] [CompilerGenerated] internal sealed class <fac50906-3bde-460d-98de-2a6e5ea09b08>RefSafetyRulesAttribute : Attribute { public readonly int Version; public <fac50906-3bde-460d-98de-2a6e5ea09b08>RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace LocalizationManager { [PublicAPI] [<6829e025-ae21-47c8-ac92-c1c427b43056>Nullable(0)] [<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(1)] public class Localizer { private static readonly Dictionary<string, Dictionary<string, Func<string>>> PlaceholderProcessors; private static readonly Dictionary<string, Dictionary<string, string>> loadedTexts; private static readonly ConditionalWeakTable<Localization, string> localizationLanguage; private static readonly List<WeakReference<Localization>> localizationObjects; [<6829e025-ae21-47c8-ac92-c1c427b43056>Nullable(2)] private static BaseUnityPlugin _plugin; private static readonly List<string> fileExtensions; 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([<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(0)] (TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t))); } return _plugin; } } [<6829e025-ae21-47c8-ac92-c1c427b43056>Nullable(2)] [method: <298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(2)] [field: <6829e025-ae21-47c8-ac92-c1c427b43056>Nullable(2)] public static event Action OnLocalizationComplete; private static void UpdatePlaceholderText(Localization localization, string key) { localizationLanguage.TryGetValue(localization, out var value); string text = loadedTexts[value][key]; if (PlaceholderProcessors.TryGetValue(key, out var value2)) { text = value2.Aggregate(text, [<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(0)] (string current, KeyValuePair<string, Func<string>> kv) => current.Replace("{" + kv.Key + "}", kv.Value())); } localization.AddWord(key, text); } public static void AddPlaceholder<T>(string key, string placeholder, ConfigEntry<T> config, [<6829e025-ae21-47c8-ac92-c1c427b43056>Nullable(new byte[] { 2, 1, 1 })] Func<T, string> convertConfigValue = null) { if (convertConfigValue == null) { convertConfigValue = (T val) => val.ToString(); } if (!PlaceholderProcessors.ContainsKey(key)) { PlaceholderProcessors[key] = new Dictionary<string, Func<string>>(); } config.SettingChanged += [<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(0)] (object _, EventArgs _) => { UpdatePlaceholder(); }; if (loadedTexts.ContainsKey(Localization.instance.GetSelectedLanguage())) { UpdatePlaceholder(); } void UpdatePlaceholder() { PlaceholderProcessors[key][placeholder] = () => convertConfigValue(config.Value); UpdatePlaceholderText(Localization.instance, key); } } public static void AddText(string key, string text) { List<WeakReference<Localization>> list = new List<WeakReference<Localization>>(); foreach (WeakReference<Localization> localizationObject in localizationObjects) { if (localizationObject.TryGetTarget(out var target)) { Dictionary<string, string> dictionary = loadedTexts[localizationLanguage.GetOrCreateValue(target)]; if (!target.m_translations.ContainsKey(key)) { dictionary[key] = text; target.AddWord(key, text); } } else { list.Add(localizationObject); } } foreach (WeakReference<Localization> item in list) { localizationObjects.Remove(item); } } public static void Load() { _ = plugin; } public static void LoadLocalizationLater(Localization __instance) { LoadLocalization(Localization.instance, __instance.GetSelectedLanguage()); } public static void SafeCallLocalizeComplete() { Localizer.OnLocalizationComplete?.Invoke(); } private static void LoadLocalization(Localization __instance, string language) { if (!localizationLanguage.Remove(__instance)) { localizationObjects.Add(new WeakReference<Localization>(__instance)); } localizationLanguage.Add(__instance, language); Dictionary<string, string> dictionary = new Dictionary<string, string>(); foreach (string item in from f in Directory.GetFiles(Path.GetDirectoryName(Paths.PluginPath), plugin.Info.Metadata.Name + ".*", SearchOption.AllDirectories) where fileExtensions.IndexOf(Path.GetExtension(f)) >= 0 select f) { string[] array = Path.GetFileNameWithoutExtension(item).Split(new char[1] { '.' }); if (array.Length >= 2) { string text = array[1]; if (dictionary.ContainsKey(text)) { Debug.LogWarning((object)("Duplicate key " + text + " found for " + plugin.Info.Metadata.Name + ". The duplicate file found at " + item + " will be skipped.")); } else { dictionary[text] = item; } } } byte[] array2 = LoadTranslationFromAssembly("English"); if (array2 == null) { throw new Exception("Found no English localizations in mod " + plugin.Info.Metadata.Name + ". Expected an embedded resource translations/English.json or translations/English.yml."); } Dictionary<string, string> dictionary2 = new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(Encoding.UTF8.GetString(array2)); if (dictionary2 == null) { throw new Exception("Localization for mod " + plugin.Info.Metadata.Name + " failed: Localization file was empty."); } string text2 = null; if (language != "English") { if (dictionary.TryGetValue(language, out var value)) { text2 = File.ReadAllText(value); } else { byte[] array3 = LoadTranslationFromAssembly(language); if (array3 != null) { text2 = Encoding.UTF8.GetString(array3); } } } if (text2 == null && dictionary.TryGetValue("English", out var value2)) { text2 = File.ReadAllText(value2); } if (text2 != null) { foreach (KeyValuePair<string, string> item2 in new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(text2) ?? new Dictionary<string, string>()) { dictionary2[item2.Key] = item2.Value; } } loadedTexts[language] = dictionary2; foreach (KeyValuePair<string, string> item3 in dictionary2) { UpdatePlaceholderText(__instance, item3.Key); } } static Localizer() { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Expected O, but got Unknown //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected O, but got Unknown PlaceholderProcessors = new Dictionary<string, Dictionary<string, Func<string>>>(); loadedTexts = new Dictionary<string, Dictionary<string, string>>(); localizationLanguage = new ConditionalWeakTable<Localization, string>(); localizationObjects = new List<WeakReference<Localization>>(); fileExtensions = new List<string>(2) { ".json", ".yml" }; Harmony val = new Harmony("org.bepinex.helpers.LocalizationManager"); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Localization), "SetupLanguage", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalization", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "SetupGui", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalizationLater", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "Start", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "SafeCallLocalizeComplete", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } [return: <6829e025-ae21-47c8-ac92-c1c427b43056>Nullable(2)] private static byte[] LoadTranslationFromAssembly(string language) { foreach (string fileExtension in fileExtensions) { byte[] array = ReadEmbeddedFileBytes("translations." + language + fileExtension); if (array != null) { return array; } } return null; } [<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(2)] public static byte[] ReadEmbeddedFileBytes([<6829e025-ae21-47c8-ac92-c1c427b43056>Nullable(1)] string resourceFileName, Assembly containingAssembly = null) { using MemoryStream memoryStream = new MemoryStream(); if ((object)containingAssembly == null) { containingAssembly = Assembly.GetCallingAssembly(); } string text = containingAssembly.GetManifestResourceNames().FirstOrDefault([<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(0)] (string str) => str.EndsWith(resourceFileName, StringComparison.Ordinal)); if (text != null) { containingAssembly.GetManifestResourceStream(text)?.CopyTo(memoryStream); } return (memoryStream.Length == 0L) ? null : memoryStream.ToArray(); } } public static class LocalizationManagerVersion { [<6829e025-ae21-47c8-ac92-c1c427b43056>Nullable(1)] public const string Version = "1.4.1"; } } namespace Recycle_N_Reclaim { [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("Azumatt.Recycle_N_Reclaim", "Recycle_N_Reclaim", "1.4.0")] [<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(1)] [<6829e025-ae21-47c8-ac92-c1c427b43056>Nullable(0)] public class Recycle_N_ReclaimPlugin : BaseUnityPlugin { [<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(0)] public enum Toggle { On = 1, Off = 0 } [<6829e025-ae21-47c8-ac92-c1c427b43056>Nullable(0)] private class ConfigurationManagerAttributes { [UsedImplicitly] public int? Order; [UsedImplicitly] public bool? Browsable; [UsedImplicitly] public string Category; [UsedImplicitly] public Action<ConfigEntryBase> CustomDrawer; } [<6829e025-ae21-47c8-ac92-c1c427b43056>Nullable(0)] private class AcceptableShortcuts : AcceptableValueBase { public AcceptableShortcuts() : base(typeof(KeyboardShortcut)) { } public override object Clamp(object value) { return value; } public override bool IsValid(object value) { return true; } public override string ToDescriptionString() { return "# Acceptable values: " + string.Join(", ", UnityInput.Current.SupportedKeyCodes); } } internal const string ModName = "Recycle_N_Reclaim"; internal const string ModVersion = "1.4.0"; internal const string Author = "Azumatt"; private const string ModGUID = "Azumatt.Recycle_N_Reclaim"; private static string ConfigFileName = "Azumatt.Recycle_N_Reclaim.cfg"; private static string ConfigFileFullPath; [<6829e025-ae21-47c8-ac92-c1c427b43056>Nullable(2)] internal static Assembly epicLootAssembly; internal static string ConnectionError; public static bool HasAuga; private ContainerRecyclingButtonHolder _containerRecyclingButton; private readonly Harmony _harmony = new Harmony("Azumatt.Recycle_N_Reclaim"); public static readonly ManualLogSource Recycle_N_ReclaimLogger; internal static readonly ConfigSync ConfigSyncVar; internal static readonly string yamlFileName; internal static readonly string yamlPath; internal static readonly CustomSyncedValue<string> RNRExcludeListData; internal static Root yamlData; internal static Dictionary<string, HashSet<string>> predefinedGroups; private static ConfigEntry<Toggle> _serverConfigLocked; public static ConfigEntry<Toggle> ApplyCraftedBy; public static ConfigEntry<KeyboardShortcut> hotKey; public static ConfigEntry<Toggle> discardInvEnabled; public static ConfigEntry<Toggle> lockToAdmin; public static ConfigEntry<Toggle> returnUnknownResources; public static ConfigEntry<Toggle> returnEnchantedResources; public static ConfigEntry<float> returnResources; private ConfigEntry<string> _stationFilterListString; public static List<string> StationFilterList; public static ConfigEntry<Toggle> StationFilterEnabled; public static ConfigEntry<Toggle> EnableExperimentalCraftingTabUI; public static ConfigEntry<Toggle> NotifyOnSalvagingImpediments; public static ConfigEntry<Toggle> PreventZeroResourceYields; public static ConfigEntry<Toggle> UnstackableItemsAlwaysReturnAtLeastOneResource; public static ConfigEntry<float> RecyclingRate; public static ConfigEntry<Toggle> ContainerRecyclingEnabled; public static ConfigEntry<Toggle> IgnoreItemsOnHotbar; public static ConfigEntry<Vector3> ContainerRecyclingButtonPositionJsonString; public static ConfigEntry<Toggle> AllowRecyclingUnknownRecipes; public static ConfigEntry<Toggle> DebugAlwaysDumpAnalysisContext; public static ConfigEntry<Toggle> DebugAllowSpammyLogs; public static ConfigEntry<Toggle> HideEquippedItemsInRecyclingTab; public static ConfigEntry<Toggle> RequireExactCraftingStationForRecycling; public static ConfigEntry<Toggle> returnEnchantedResourcesReclaiming; public static ConfigEntry<Color> BorderColorTrashedItem; public static ConfigEntry<Color> BorderColorTrashedSlot; public static ConfigEntry<bool> DisplayTooltipHint; public static ConfigEntry<bool> ShowRecycleYieldInTooltip; public static ConfigEntry<KeyboardShortcut> UndoRecycleKeybind; public static ConfigEntry<float> UndoRecycleGracePeriodSeconds; public static ConfigEntry<KeyboardShortcut> TrashingModifierKeybind1; public static ConfigEntry<KeyboardShortcut> TrashingKeybind; public static ConfigEntry<string> TrashedSlotTooltip; public static StationRecyclingTabHolder RecyclingTabButtonHolder { get; private set; } private ConfigEntry<string> StationFilterListString { get { return _stationFilterListString; } set { _stationFilterListString = value; value.SettingChanged += [<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(0)] (object sender, EventArgs args) => { SplitNewValueAndSetProperty(); }; SplitNewValueAndSetProperty(); void SplitNewValueAndSetProperty() { StationFilterList = (from entry in value.Value.Split(new char[1] { ',' }) select entry.Trim()).ToList(); } } } public void Awake() { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Expected O, but got Unknown //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Expected O, but got Unknown //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Expected O, but got Unknown //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Unknown result type (might be due to invalid IL or missing references) //IL_039e: Unknown result type (might be due to invalid IL or missing references) Localizer.Load(); _serverConfigLocked = config("1 - General", "Lock Configuration", Toggle.On, "If on, the configuration is locked and can be changed by server admins only."); ConfigSyncVar.AddLockingConfigEntry<Toggle>(_serverConfigLocked); ApplyCraftedBy = config("1 - General", "Apply Crafted By", Toggle.On, "If on, the player will be the 'crafter' of each recycled item. If off, these values are empty"); string group = "2 - Inventory Recycle"; discardInvEnabled = config(group, "Enabled", Toggle.On, new ConfigDescription("If on, you'll be able to discard things inside of the player inventory.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 2 } })); lockToAdmin = config(group, "Lock to Admin", Toggle.On, new ConfigDescription("If on, only admin's can use this feature.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 1 } })); hotKey = config<KeyboardShortcut>(group, "DiscardHotkey(s)", new KeyboardShortcut((KeyCode)127, Array.Empty<KeyCode>()), new ConfigDescription("The hotkey to discard an item or regain resources. Must be enabled", (AcceptableValueBase)(object)new AcceptableShortcuts(), Array.Empty<object>()), synchronizedSetting: false); returnUnknownResources = config(group, "ReturnUnknownResources", Toggle.Off, "If on, discarding an item in the inventory will return resources if recipe is unknown"); returnEnchantedResources = config(group, "ReturnEnchantedResources", Toggle.On, "If on and Epic Loot or Jewelcrafting is installed, discarding an item in the inventory will return resources for Epic Loot enchantments or Jewelcrafting gems"); returnResources = config(group, "ReturnResources", 1f, "Fraction of resources to return (0.0 - 1.0). This setting is forced to be between 0 and 1. Any higher or lower values will be set to 0 or 1 respectively."); returnResources.SettingChanged += [<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(0)] (object sender, EventArgs args) => { if (returnResources.Value > 1f) { returnResources.Value = 1f; } if (returnResources.Value < 0f) { returnResources.Value = 0f; } }; string text = "While this & right click are held, hovering over items marks them for trashing. Releasing this will cancel trashing for all items."; BorderColorTrashedSlot = config<Color>(group, "BorderColorTrashedItem", new Color(1f, 0f, 0f), "Color of the border for slots containing Trashed items.", synchronizedSetting: false); DisplayTooltipHint = config(group, "DisplayTooltipHint", value: true, "Whether to add additional info the item tooltip of a Trashed or trash flagged item.", synchronizedSetting: false); ShowRecycleYieldInTooltip = config(group, "ShowRecycleYieldInTooltip", value: false, "If on, hovering an item will show what it would yield if recycled.", synchronizedSetting: false); TrashingKeybind = config<KeyboardShortcut>(group, "TrashingKeybind", new KeyboardShortcut((KeyCode)325, Array.Empty<KeyCode>()), "Key(s) that when pressed while holding your modifier key will trash all items marked as trash. Default setting is middle mouse click", synchronizedSetting: false); TrashingModifierKeybind1 = config<KeyboardShortcut>(group, "TrashingModifierKeybind1", new KeyboardShortcut((KeyCode)120, Array.Empty<KeyCode>()), text + ".", synchronizedSetting: false); TrashedSlotTooltip = config(group, "TrashedSlotTooltip", "Slot is Trashed and will be a part of the bulk delete", string.Empty, synchronizedSetting: false); RecyclingRate = config("3 - Reclaiming", "RecyclingRate", 0.5f, "Rate at which the resources are recycled. Value must be between 0 and 1.\nThe mod always rolls *down*, so if you were supposed to get 2.5 items, you would only receive 2. If the recycling rate is 0.5 (50%), the player will receive half of the resources they would usually need to craft the item, assuming a single item in a stack and the item is of quality level 1. If the item is of higher quality, the resulting yield would be higher as well."); RecyclingRate.SettingChanged += [<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(0)] (object sender, EventArgs args) => { if (RecyclingRate.Value > 1f) { RecyclingRate.Value = 1f; } if (RecyclingRate.Value < 0f) { RecyclingRate.Value = 0f; } }; UnstackableItemsAlwaysReturnAtLeastOneResource = config("3 - Reclaiming", "UnstackableItemsAlwaysReturnAtLeastOneResource", Toggle.On, "If enabled and recycling a specific _unstackable_ item would yield 0 of a material,\ninstead you will receive 1. If disabled, you get nothing."); RequireExactCraftingStationForRecycling = config("3 - Reclaiming", "RequireExactCraftingStationForRecycling", Toggle.On, "If enabled, recycling will also check for the required crafting station type and level.\nIf disabled, will ignore all crafting station requirements altogether.\nEnabled by default, to keep things close to how Valheim operates."); returnEnchantedResourcesReclaiming = config("3 - Reclaiming", "ReturnEnchantedResources", Toggle.On, "If on and Epic Loot or Jewelcrafting is installed, discarding an item in the inventory will return resources for Epic Loot enchantments or Jewelcrafting gems"); PreventZeroResourceYields = config("3 - Reclaiming", "PreventZeroResourceYields", Toggle.On, "If enabled and recycling an item that would yield 0 of any material,\ninstead you will receive 1. If disabled, you get nothing."); AllowRecyclingUnknownRecipes = config("3 - Reclaiming", "AllowRecyclingUnknownRecipes", Toggle.Off, "If enabled, it will allow you to recycle items that you do not know the recipe for yet.\nDisabled by default as this can be cheaty, but sometimes required due to people losing progress."); UndoRecycleKeybind = config<KeyboardShortcut>("3 - Reclaiming", "UndoRecycleKeybind", new KeyboardShortcut((KeyCode)122, (KeyCode[])(object)new KeyCode[1] { (KeyCode)306 }), "Keybind to undo the last reclaim from the Reclaim tab. Only works within the grace period.", synchronizedSetting: false); UndoRecycleGracePeriodSeconds = config("3 - Reclaiming", "UndoRecycleGracePeriodSeconds", 20f, "Number of seconds after a reclaim during which it can be undone. Set to 0 to disable undo entirely."); UndoRecycleGracePeriodSeconds.SettingChanged += [<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(0)] (object sender, EventArgs args) => { if (UndoRecycleGracePeriodSeconds.Value < 0f) { UndoRecycleGracePeriodSeconds.Value = 0f; } }; ContainerRecyclingButtonPositionJsonString = config<Vector3>("4 - UI", "ContainerButtonPosition", new Vector3(496f, -374f, -1f), "The last saved recycling button position stored in JSON"); ContainerRecyclingEnabled = config("4 - UI", "ContainerRecyclingEnabled", Toggle.On, "If enabled, the mod will display the container recycling button"); NotifyOnSalvagingImpediments = config("4 - UI", "NotifyOnSalvagingImpediments", Toggle.On, "If enabled and recycling a specific item runs into any issues, the mod will print a message\nin the center of the screen (native Valheim notification). At the time of implementation,\nthis happens in the following cases:\n - not enough free slots in the inventory to place the resulting resources\n - player does not know the recipe for the item\n - if enabled, cases when `PreventZeroResourceYields` kicks in and prevent the crafting"); EnableExperimentalCraftingTabUI = config("4 - UI", "EnableExperimentalCraftingTabUI", Toggle.On, "If enabled, will display the experimental work in progress crafting tab UI\nEnabled by default."); HideEquippedItemsInRecyclingTab = config("4 - UI", "HideRecipesForEquippedItems", Toggle.On, "If enabled, it will hide equipped items in the crafting tab.\nThis does not make the item recyclable and only influences whether or not it's shown.\nEnabled by default."); IgnoreItemsOnHotbar = config("4 - UI", "IgnoreItemsOnHotbar", Toggle.On, "If enabled, it will hide hotbar items in the crafting tab.\nEnabled by default."); StationFilterEnabled = config("4 - UI", "StationFilterEnabled", Toggle.On, "If enabled, will filter all recycling recipes based on the crafting station\nused to produce said item. Main purpose of this is to prevent showing food\nas a recyclable item, but can be extended further if needed.\nEnabled by default"); StationFilterListString = config("4 - UI", "StationFilterList", "piece_cauldron", "Comma separated list of crafting stations (by their \"prefab name\")\nrecipes from which should be ignored in regards to recycling.\nMain purpose of this is to prevent showing food as a recyclable item,\nbut can be extended further if needed.\n\nFull list of stations used in recipes as of 0.216.9:\n- identifier: `forge` in game name: Forge\n- identifier: `blackforge` in game name: Black Forge\n- identifier: `piece_workbench` in game name: Workbench\n- identifier: `piece_cauldron` in game name: Cauldron\n- identifier: `piece_stonecutter` in game name: Stonecutter\n- identifier: `piece_artisanstation` in game name: Artisan table\n- identifier: `piece_magetable` in game name: Galdr table\n"); DebugAlwaysDumpAnalysisContext = config("zDebug", "DebugAlwaysDumpAnalysisContext", Toggle.Off, "If enabled will dump a complete detailed recycling report every time. This is taxing in terms\nof performance and should only be used when debugging issues. "); DebugAllowSpammyLogs = config("zDebug", "DebugAllowSpammyLogs", Toggle.Off, "If enabled, will spam recycling checks to the console.\nVERY. VERY. SPAMMY. Influences performance. "); if (!File.Exists(yamlPath)) { YAMLUtils.WriteConfigFileFromResource(yamlPath); } RNRExcludeListData.ValueChanged += OnValChangedUpdate; RNRExcludeListData.AssignLocalValue(File.ReadAllText(yamlPath)); Assembly executingAssembly = Assembly.GetExecutingAssembly(); _harmony.PatchAll(executingAssembly); SetupWatcher(); } private void Start() { InventoryGridUpdateGuiPatch.border = loadSprite("trashingborder.png"); AutoDoc(); HasAuga = Auga.API.IsLoaded(); _containerRecyclingButton = ((Component)this).gameObject.AddComponent<ContainerRecyclingButtonHolder>(); _containerRecyclingButton.OnRecycleAllTriggered += ContainerRecyclingTriggered; RecyclingTabButtonHolder = ((Component)this).gameObject.AddComponent<StationRecyclingTabHolder>(); if (Chainloader.PluginInfos.ContainsKey("randyknapp.mods.epicloot")) { epicLootAssembly = ((object)Chainloader.PluginInfos["randyknapp.mods.epicloot"].Instance).GetType().Assembly; Recycle_N_ReclaimLogger.LogDebug((object)"Epic Loot found, providing compatibility"); } } internal static Sprite loadSprite(string name) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) Texture2D val = loadTexture(name); if ((Object)(object)val != (Object)null) { return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), Vector2.zero); } return null; } private static Texture2D loadTexture(string name) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_001f: Expected O, but got Unknown Texture2D val = new Texture2D(0, 0); ImageConversion.LoadImage(val, ReadEmbeddedFileBytes("Assets." + name)); return val; } private static byte[] ReadEmbeddedFileBytes(string name) { using MemoryStream memoryStream = new MemoryStream(); Assembly.GetExecutingAssembly().GetManifestResourceStream(Assembly.GetExecutingAssembly().GetName().Name + "." + name).CopyTo(memoryStream); return memoryStream.ToArray(); } private void AutoDoc() { } private void OnDestroy() { ((BaseUnityPlugin)this).Config.Save(); } private void SetupWatcher() { FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, ConfigFileName); fileSystemWatcher.Changed += ReadConfigValues; fileSystemWatcher.Created += ReadConfigValues; fileSystemWatcher.Renamed += ReadConfigValues; fileSystemWatcher.IncludeSubdirectories = true; fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher.EnableRaisingEvents = true; FileSystemWatcher fileSystemWatcher2 = new FileSystemWatcher(Paths.ConfigPath, yamlFileName); fileSystemWatcher2.Changed += ReadYamlFiles; fileSystemWatcher2.Created += ReadYamlFiles; fileSystemWatcher2.Renamed += ReadYamlFiles; fileSystemWatcher2.IncludeSubdirectories = true; fileSystemWatcher2.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher2.EnableRaisingEvents = true; } private void ReadConfigValues(object sender, FileSystemEventArgs e) { if (!File.Exists(ConfigFileFullPath)) { return; } try { Recycle_N_ReclaimLogger.LogDebug((object)"ReadConfigValues called"); ((BaseUnityPlugin)this).Config.Reload(); } catch { Recycle_N_ReclaimLogger.LogError((object)("There was an issue loading your " + ConfigFileName)); Recycle_N_ReclaimLogger.LogError((object)"Please check your config entries for spelling and format!"); } } private void ReadYamlFiles(object sender, FileSystemEventArgs e) { if (!File.Exists(yamlPath)) { return; } try { Recycle_N_ReclaimLogger.LogDebug((object)"ReadConfigValues called"); RNRExcludeListData.AssignLocalValue(File.ReadAllText(yamlPath)); } catch { Recycle_N_ReclaimLogger.LogError((object)("There was an issue loading your " + yamlFileName)); Recycle_N_ReclaimLogger.LogError((object)"Please check your entries for spelling and format!"); } } private static void OnValChangedUpdate() { Recycle_N_ReclaimLogger.LogDebug((object)"OnValChanged called"); try { YAMLUtils.ReadYaml(RNRExcludeListData.Value); } catch (Exception arg) { Recycle_N_ReclaimLogger.LogError((object)$"Failed to deserialize {yamlFileName}: {arg}"); } } public static string Localize(string text) { return Localization.instance.Localize(text); } public static string Localize(string text, params string[] words) { return Localization.instance.Localize(text, words); } private void ContainerRecyclingTriggered() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown Player localPlayer = Player.m_localPlayer; Container val = (Container)AccessTools.Field(typeof(InventoryGui), "m_currentContainer").GetValue(InventoryGui.instance); if (!((Object)(object)val == (Object)null)) { Recycle_N_ReclaimLogger.LogDebug((object)("Player " + localPlayer.GetPlayerName() + " triggered recycling")); Reclaimer.RecycleInventoryForAllRecipes(val.GetInventory(), GroupUtils.GetPrefabName(((Object)((Component)val).transform).name), localPlayer); } } private ConfigEntry<T> config<[<6829e025-ae21-47c8-ac92-c1c427b43056>Nullable(2)] T>(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown ConfigDescription val = new ConfigDescription(description.Description + (synchronizedSetting ? " [Synced with Server]" : " [Not Synced with Server]"), description.AcceptableValues, description.Tags); ConfigEntry<T> val2 = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, val); ConfigSyncVar.AddConfigEntry<T>(val2).SynchronizedConfig = synchronizedSetting; return val2; } private ConfigEntry<T> config<[<6829e025-ae21-47c8-ac92-c1c427b43056>Nullable(2)] T>(string group, string name, T value, string description, bool synchronizedSetting = true) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown return config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting); } static Recycle_N_ReclaimPlugin() { string configPath = Paths.ConfigPath; char directorySeparatorChar = Path.DirectorySeparatorChar; ConfigFileFullPath = configPath + directorySeparatorChar + ConfigFileName; ConnectionError = ""; Recycle_N_ReclaimLogger = Logger.CreateLogSource("Recycle_N_Reclaim"); ConfigSyncVar = new ConfigSync("Azumatt.Recycle_N_Reclaim") { DisplayName = "Recycle_N_Reclaim", CurrentVersion = "1.4.0", MinimumRequiredVersion = "1.4.0" }; yamlFileName = "Azumatt.Recycle_N_Reclaim_ExcludeLists.yml"; string configPath2 = Paths.ConfigPath; directorySeparatorChar = Path.DirectorySeparatorChar; yamlPath = configPath2 + directorySeparatorChar + yamlFileName; RNRExcludeListData = new CustomSyncedValue<string>(ConfigSyncVar, "RNR_YamlData", ""); yamlData = new Root(); predefinedGroups = new Dictionary<string, HashSet<string>>(); _serverConfigLocked = null; ApplyCraftedBy = null; hotKey = null; discardInvEnabled = null; lockToAdmin = null; returnUnknownResources = null; returnEnchantedResources = null; returnResources = null; StationFilterList = new List<string>(); StationFilterEnabled = null; EnableExperimentalCraftingTabUI = null; NotifyOnSalvagingImpediments = null; PreventZeroResourceYields = null; UnstackableItemsAlwaysReturnAtLeastOneResource = null; RecyclingRate = null; ContainerRecyclingEnabled = null; IgnoreItemsOnHotbar = null; ContainerRecyclingButtonPositionJsonString = null; AllowRecyclingUnknownRecipes = null; DebugAlwaysDumpAnalysisContext = null; DebugAllowSpammyLogs = null; HideEquippedItemsInRecyclingTab = null; RequireExactCraftingStationForRecycling = null; returnEnchantedResourcesReclaiming = null; BorderColorTrashedItem = null; BorderColorTrashedSlot = null; DisplayTooltipHint = null; ShowRecycleYieldInTooltip = null; UndoRecycleKeybind = null; UndoRecycleGracePeriodSeconds = null; TrashingModifierKeybind1 = null; TrashingKeybind = null; TrashedSlotTooltip = null; } } public static class KeyboardExtensions { public static bool IsKeyDown(this KeyboardShortcut shortcut) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) if ((int)((KeyboardShortcut)(ref shortcut)).MainKey != 0 && Input.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey)) { return ((KeyboardShortcut)(ref shortcut)).Modifiers.All((Func<KeyCode, bool>)Input.GetKey); } return false; } public static bool IsKeyHeld(this KeyboardShortcut shortcut) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) if ((int)((KeyboardShortcut)(ref shortcut)).MainKey != 0 && Input.GetKey(((KeyboardShortcut)(ref shortcut)).MainKey)) { return ((KeyboardShortcut)(ref shortcut)).Modifiers.All((Func<KeyCode, bool>)Input.GetKey); } return false; } } public static class ToggleExtensions { public static bool IsOn(this Recycle_N_ReclaimPlugin.Toggle toggle) { return toggle == Recycle_N_ReclaimPlugin.Toggle.On; } public static bool IsOff(this Recycle_N_ReclaimPlugin.Toggle toggle) { return toggle == Recycle_N_ReclaimPlugin.Toggle.Off; } } } namespace Recycle_N_Reclaim.YAMLStuff { [HarmonyPatch(typeof(ObjectDB), "Awake")] internal static class PredefinedGroupGrab { [HarmonyPriority(0)] [<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(1)] private static void Postfix(ObjectDB __instance) { if (Object.op_Implicit((Object)(object)ZNetScene.instance)) { GroupUtils.CreatePredefinedGroups(__instance); Reclaimer.BuildRecipeCache(__instance); } } } [<6829e025-ae21-47c8-ac92-c1c427b43056>Nullable(0)] [<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(1)] public class GroupUtils { public static List<string> GetExcludedGroups(string container) { if (Recycle_N_ReclaimPlugin.yamlData.Containers.TryGetValue(container, out var value)) { return value.Exclude.Where([<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(0)] (string excludeItem) => Recycle_N_ReclaimPlugin.yamlData.Groups.ContainsKey(excludeItem)).ToList(); } return new List<string>(); } public static bool IsGroupDefined(string groupName) { return Recycle_N_ReclaimPlugin.yamlData.Groups.ContainsKey(groupName); } public static bool GroupExists(string groupName) { return Recycle_N_ReclaimPlugin.yamlData.Groups.ContainsKey(groupName); } public static List<string> GetAllGroups() { return Recycle_N_ReclaimPlugin.yamlData.Groups.Keys.ToList(); } public static List<string> GetItemsInGroup(string groupName) { if (Recycle_N_ReclaimPlugin.yamlData.Groups.TryGetValue(groupName, out var value)) { return value.ToList(); } return new List<string>(); } public static string GetPrefabName(string name) { char[] anyOf = new char[2] { '(', ' ' }; int num = name.IndexOfAny(anyOf); if (num >= 0) { return name.Substring(0, num); } return name; } [return: <6829e025-ae21-47c8-ac92-c1c427b43056>Nullable(2)] internal static GameObject GetItemPrefabFromGameObject(ItemDrop itemDropComponent, GameObject inputGameObject) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(GetPrefabName(((Object)inputGameObject).name)); itemDropComponent.m_itemData.m_dropPrefab = itemPrefab; if (!((Object)(object)itemPrefab != (Object)null)) { return null; } return itemPrefab; } internal static bool CheckItemDropIntegrity(ItemDrop itemDropComp) { if (itemDropComp.m_itemData == null) { return false; } return itemDropComp.m_itemData.m_shared != null; } internal static void CreatePredefinedGroups(ObjectDB __instance) { //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Invalid comparison between Unknown and I4 //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Expected I4, but got Unknown //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Expected I4, but got Unknown foreach (GameObject item in __instance.m_items.Where([<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(0)] (GameObject x) => (Object)(object)x.GetComponentInChildren<ItemDrop>() != (Object)null)) { ItemDrop componentInChildren = item.GetComponentInChildren<ItemDrop>(); if (!CheckItemDropIntegrity(componentInChildren)) { continue; } GameObject itemPrefabFromGameObject = GetItemPrefabFromGameObject(componentInChildren, item); componentInChildren.m_itemData.m_dropPrefab = ((Component)componentInChildren).gameObject; if (!((Object)(object)itemPrefabFromGameObject != (Object)null)) { continue; } SharedData sharedData = componentInChildren.m_itemData.m_shared; string text = ""; if ((double)sharedData.m_food > 0.0 && (double)sharedData.m_foodStamina > 0.0) { text = "Food"; } if ((double)sharedData.m_food > 0.0 && (double)sharedData.m_foodStamina == 0.0) { text = "Potion"; } else if ((int)sharedData.m_itemType == 21) { text = "Fish"; } ItemType itemType = sharedData.m_itemType; switch (itemType - 1) { case 2: case 3: case 13: case 21: { SkillType skillType = sharedData.m_skillType; switch (skillType - 1) { case 0: text = "Swords"; break; case 7: text = "Bows"; break; case 13: text = "Crossbows"; break; case 6: text = "Axes"; break; case 2: text = "Clubs"; break; case 1: text = "Knives"; break; case 11: text = "Pickaxes"; break; case 3: text = "Polearms"; break; case 4: text = "Spears"; break; } break; } case 14: text = "Equipment"; break; case 12: text = (new string[6] { "eikthyr", "elder", "bonemass", "dragonqueen", "goblinking", "SeekerQueen" }.Any(sharedData.m_name.EndsWith) ? "Boss Trophy" : "Trophy"); break; case 0: { GameObject val = ((IEnumerable<GameObject>)ObjectDB.instance.GetItemPrefab("Cultivator").GetComponent<ItemDrop>().m_itemData.m_shared.m_buildPieces.m_pieces).FirstOrDefault((Func<GameObject, bool>)([<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(0)] (GameObject p) => { Requirement[] resources = p.GetComponent<Piece>().m_resources; return resources.Length == 1 && resources[0].m_resItem.m_itemData.m_shared.m_name == sharedData.m_name; })); if (val != null) { Plant component = val.GetComponent<Plant>(); text = ((component != null && component.m_grownPrefabs[0].GetComponent<Pickable>()?.m_amount > 1) ? "Crops" : "Seeds"); } if (ZNetScene.instance.GetPrefab("smelter").GetComponent<Smelter>().m_conversion.Any([<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(0)] (ItemConversion c) => c.m_from.m_itemData.m_shared.m_name == sharedData.m_name)) { text = "Ores"; } if (ZNetScene.instance.GetPrefab("smelter").GetComponent<Smelter>().m_conversion.Any([<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(0)] (ItemConversion c) => c.m_to.m_itemData.m_shared.m_name == sharedData.m_name)) { text = "Metals"; } if (ZNetScene.instance.GetPrefab("blastfurnace").GetComponent<Smelter>().m_conversion.Any([<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(0)] (ItemConversion c) => c.m_from.m_itemData.m_shared.m_name == sharedData.m_name)) { text = "Ores"; } if (ZNetScene.instance.GetPrefab("blastfurnace").GetComponent<Smelter>().m_conversion.Any([<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(0)] (ItemConversion c) => c.m_to.m_itemData.m_shared.m_name == sharedData.m_name)) { text = "Metals"; } if (ZNetScene.instance.GetPrefab("charcoal_kiln").GetComponent<Smelter>().m_conversion.Any([<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(0)] (ItemConversion c) => c.m_from.m_itemData.m_shared.m_name == sharedData.m_name)) { text = "Woods"; } if (sharedData.m_name == "$item_elderbark") { text = "Woods"; } break; } case 5: text = "Helmets"; break; case 6: case 10: case 11: case 16: text = "Armor"; break; case 8: case 22: text = "Ammunition"; break; case 17: text = "Utilities"; break; case 18: text = "Tools"; break; case 15: text = "Miscellaneous"; break; case 9: text = "Customizations"; break; } if (!string.IsNullOrEmpty(text)) { AddItemToGroup(text, componentInChildren); } if (sharedData != null) { text = "All"; AddItemToGroup(text, componentInChildren); } } } private static void AddItemToGroup(string groupName, ItemDrop itemDrop) { if (!GroupExists(groupName)) { Recycle_N_ReclaimPlugin.yamlData.Groups[groupName] = new List<string>(); Recycle_N_ReclaimPlugin.predefinedGroups[groupName] = new HashSet<string>(); } string prefabName = Utils.GetPrefabName(itemDrop.m_itemData.m_dropPrefab); if (!Recycle_N_ReclaimPlugin.yamlData.Groups[groupName].Contains(prefabName)) { Recycle_N_ReclaimPlugin.yamlData.Groups[groupName].Add(prefabName); Recycle_N_ReclaimPlugin.predefinedGroups[groupName].Add(prefabName); } } public static float? GetRecycleRateOverride(string prefabName) { Dictionary<string, float> dictionary = Recycle_N_ReclaimPlugin.yamlData?.Reclaiming?.RecycleRates; if (dictionary == null || dictionary.Count == 0) { return null; } if (dictionary.TryGetValue(prefabName, out var value)) { return Mathf.Clamp01(value); } foreach (KeyValuePair<string, float> item in dictionary) { if (Recycle_N_ReclaimPlugin.yamlData.Groups.TryGetValue(item.Key, out var value2) && value2.Contains(prefabName)) { return Mathf.Clamp01(item.Value); } } return null; } public static bool IsPrefabExcludedInReclaiming(string prefabName) { return IsPrefabExcludedInEntity(Recycle_N_ReclaimPlugin.yamlData.Reclaiming, prefabName); } public static bool IsPrefabExcludedInInventory(string prefabName) { return IsPrefabExcludedInEntity(Recycle_N_ReclaimPlugin.yamlData.Inventory, prefabName); } public static bool IsPrefabExcludedInContainer(string containerName, string prefabName) { if (Recycle_N_ReclaimPlugin.yamlData.Containers.TryGetValue(containerName, out var value)) { return IsPrefabExcludedInEntity(value, prefabName); } return false; } private static bool IsPrefabExcludedInEntity(object entity, string prefabName) { bool flag = ((entity is excludeContainer || entity is Reclaiming || entity is Inventory) ? true : false); if (!flag) { throw new ArgumentException("The entity type is not supported."); } List<string> list = null; List<string> list2 = null; if (!(entity is excludeContainer excludeContainer2)) { if (!(entity is Reclaiming reclaiming)) { if (entity is Inventory inventory) { list2 = inventory.Exclude; list = inventory.IncludeOverride; } } else { list = reclaiming.IncludeOverride; list2 = reclaiming.Exclude; } } else { list = excludeContainer2.IncludeOverride; list2 = excludeContainer2.Exclude; } if (list != null) { foreach (string item in list) { if (item == prefabName) { flag = false; } else { if (!Recycle_N_ReclaimPlugin.yamlData.Groups.TryGetValue(item, out var value) || !value.Contains(prefabName)) { continue; } flag = false; } goto IL_014b; } } if (list2 != null) { foreach (string item2 in list2) { if (item2 == prefabName) { flag = true; } else { if (!Recycle_N_ReclaimPlugin.yamlData.Groups.TryGetValue(item2, out var value2) || !value2.Contains(prefabName)) { continue; } flag = true; } goto IL_014b; } } return false; IL_014b: return flag; } } [<6829e025-ae21-47c8-ac92-c1c427b43056>Nullable(0)] [<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(1)] public class Root { [YamlMember(Alias = "groups")] public Dictionary<string, List<string>> Groups { get; set; } [YamlMember(Alias = "containers")] public Dictionary<string, excludeContainer> Containers { get; set; } [YamlMember(Alias = "reclaiming")] public Reclaiming Reclaiming { get; set; } [YamlMember(Alias = "inventory")] public Inventory Inventory { get; set; } } [<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(1)] [<6829e025-ae21-47c8-ac92-c1c427b43056>Nullable(0)] public class excludeContainer { [YamlMember(Alias = "exclude")] public List<string> Exclude { get; set; } [YamlMember(Alias = "includeOverride")] public List<string> IncludeOverride { get; set; } } [<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(1)] [<6829e025-ae21-47c8-ac92-c1c427b43056>Nullable(0)] public class Reclaiming { [YamlMember(Alias = "exclude")] public List<string> Exclude { get; set; } [YamlMember(Alias = "includeOverride")] public List<string> IncludeOverride { get; set; } [YamlMember(Alias = "recycleRates")] public Dictionary<string, float> RecycleRates { get; set; } } [<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(1)] [<6829e025-ae21-47c8-ac92-c1c427b43056>Nullable(0)] public class Inventory { [YamlMember(Alias = "exclude")] public List<string> Exclude { get; set; } [YamlMember(Alias = "includeOverride")] public List<string> IncludeOverride { get; set; } } [<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(1)] [<6829e025-ae21-47c8-ac92-c1c427b43056>Nullable(0)] public class YAMLUtils { internal static void WriteConfigFileFromResource(string configFilePath) { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string text = "Recycle_N_Reclaim.YAMLStuff.Example.yml"; using Stream stream = executingAssembly.GetManifestResourceStream(text); if (stream == null) { throw new FileNotFoundException("Resource '" + text + "' not found in the assembly."); } using StreamReader streamReader = new StreamReader(stream); string contents = streamReader.ReadToEnd(); File.WriteAllText(configFilePath, contents); } internal static void ReadYaml(string yamlInput) { Recycle_N_ReclaimPlugin.yamlData = new DeserializerBuilder().Build().Deserialize<Root>(yamlInput); Recycle_N_ReclaimPlugin.Recycle_N_ReclaimLogger.LogDebug((object)("yamlData:\n" + yamlInput)); foreach (KeyValuePair<string, HashSet<string>> predefinedGroup in Recycle_N_ReclaimPlugin.predefinedGroups) { Recycle_N_ReclaimPlugin.yamlData.Groups[predefinedGroup.Key] = predefinedGroup.Value.ToList(); } } internal static void ParseGroups() { if (Recycle_N_ReclaimPlugin.yamlData == null) { Recycle_N_ReclaimPlugin.yamlData.Groups = new Dictionary<string, List<string>>(); } if (!Recycle_N_ReclaimPlugin.yamlData.Groups.Any()) { return; } foreach (KeyValuePair<string, List<string>> group in Recycle_N_ReclaimPlugin.yamlData.Groups) { string key = group.Key; List<string> value = group.Value; if (value == null) { continue; } List<string> list = new List<string>(); foreach (string item in value) { list.Add(item); } Recycle_N_ReclaimPlugin.yamlData.Groups[key] = list; } } public static void WriteYaml(string filePath) { ISerializer serializer = new SerializerBuilder().Build(); using StreamWriter writer = new StreamWriter(filePath); serializer.Serialize(writer, Recycle_N_ReclaimPlugin.yamlData); string contents = serializer.Serialize(Recycle_N_ReclaimPlugin.yamlData); File.AppendAllText(filePath, contents); } } } namespace Recycle_N_Reclaim.Managers { [<6829e025-ae21-47c8-ac92-c1c427b43056>Nullable(0)] [<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(1)] internal static class RecycleUndoManager { [<6829e025-ae21-47c8-ac92-c1c427b43056>Nullable(2)] private static ItemData _lastItem; private static List<RecyclingAnalysisContext.ReclaimingYieldEntry> _lastEntries = new List<RecyclingAnalysisContext.ReclaimingYieldEntry>(); private static float _recordedAt = float.MinValue; internal static bool CanUndo { get { if (_lastItem != null && Recycle_N_ReclaimPlugin.UndoRecycleGracePeriodSeconds.Value > 0f) { return Time.time - _recordedAt <= Recycle_N_ReclaimPlugin.UndoRecycleGracePeriodSeconds.Value; } return false; } } internal static void Record(ItemData item, List<RecyclingAnalysisContext.ReclaimingYieldEntry> entries) { _lastItem = item.Clone(); _lastEntries = entries.Where((RecyclingAnalysisContext.ReclaimingYieldEntry e) => e.Amount > 0 && !e.InitialRecipeHadZero).ToList(); _recordedAt = Time.time; } internal static void TryUndo() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } if (!CanUndo) { ((Character)localPlayer).Message((MessageType)2, Recycle_N_ReclaimPlugin.Localize("$azumatt_recycle_n_reclaim_undo_expired"), 0, (Sprite)null); Clear(); return; } Inventory inventory = ((Humanoid)localPlayer).GetInventory(); foreach (RecyclingAnalysisContext.ReclaimingYieldEntry lastEntry in _lastEntries) { if (inventory.CountItems(lastEntry.RecipeItemData.m_shared.m_name, -1, true) < lastEntry.Amount) { ((Character)localPlayer).Message((MessageType)2, Recycle_N_ReclaimPlugin.Localize("$azumatt_recycle_n_reclaim_undo_failed"), 0, (Sprite)null); Clear(); return; } } List<RecyclingAnalysisContext.ReclaimingYieldEntry> list = new List<RecyclingAnalysisContext.ReclaimingYieldEntry>(); foreach (RecyclingAnalysisContext.ReclaimingYieldEntry lastEntry2 in _lastEntries) { inventory.RemoveItem(lastEntry2.RecipeItemData.m_shared.m_name, lastEntry2.Amount, -1, true); list.Add(lastEntry2); } ItemData lastItem = _lastItem; if ((((Object)(object)lastItem.m_dropPrefab != (Object)null) ? inventory.AddItem(((Object)lastItem.m_dropPrefab).name, lastItem.m_stack, lastItem.m_quality, lastItem.m_variant, lastItem.m_crafterID, lastItem.m_crafterName, false) : null) == null) { bool flag = false; foreach (RecyclingAnalysisContext.ReclaimingYieldEntry item in list) { if (inventory.AddItem(((Object)item.Prefab).name, item.Amount, item.mQuality, item.mVariant, 0L, "", false) == null) { flag = true; Recycle_N_ReclaimPlugin.Recycle_N_ReclaimLogger.LogError((object)$"Undo rollback: failed to restore {item.Amount}x {((Object)item.Prefab).name} to inventory."); } } if (flag) { Recycle_N_ReclaimPlugin.Recycle_N_ReclaimLogger.LogError((object)"Undo rollback was incomplete. One or more resources could not be returned to inventory."); } ((Character)localPlayer).Message((MessageType)2, Recycle_N_ReclaimPlugin.Localize("$azumatt_recycle_n_reclaim_undo_failed"), 0, (Sprite)null); Clear(); } else { ((Character)localPlayer).Message((MessageType)2, Recycle_N_ReclaimPlugin.Localize("$azumatt_recycle_n_reclaim_undo_success"), 0, (Sprite)null); Clear(); } } internal static void Clear() { _lastItem = null; _lastEntries.Clear(); } } } namespace Recycle_N_Reclaim.GamePatches { [HarmonyPatch(typeof(InventoryGui), "UpdateItemDrag")] [<6829e025-ae21-47c8-ac92-c1c427b43056>Nullable(0)] [<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(2)] public static class UpdateItemDragPatch { internal static readonly Type epicLootType = Recycle_N_ReclaimPlugin.epicLootAssembly?.GetType("EpicLoot.ItemDataExtensions"); internal static readonly MethodInfo isMagicMethod = epicLootType?.GetMethod("IsMagic", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(ItemData) }, null); internal static readonly MethodInfo getRarityMethod = epicLootType?.GetMethod("GetRarity", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(ItemData) }, null); internal static readonly Type enchantTabControllerType = Recycle_N_ReclaimPlugin.epicLootAssembly?.GetType("EpicLoot.Crafting.EnchantHelper"); internal static readonly MethodInfo getEnchantCostsMethod = enchantTabControllerType?.GetMethod("GetEnchantCosts", BindingFlags.Static | BindingFlags.Public); [<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(1)] private static void Postfix(InventoryGui __instance, ItemData ___m_dragItem, Inventory ___m_dragInventory, int ___m_dragAmount, ref GameObject ___m_dragGo) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) if ((!Recycle_N_ReclaimPlugin.lockToAdmin.Value.IsOn() || Recycle_N_ReclaimPlugin.ConfigSyncVar.IsAdmin) && !Recycle_N_ReclaimPlugin.discardInvEnabled.Value.IsOff()) { KeyboardShortcut value = Recycle_N_ReclaimPlugin.hotKey.Value; if (((KeyboardShortcut)(ref value)).IsDown() && ___m_dragItem != null && ___m_dragInventory.ContainsItem(___m_dragItem)) { Recycle_N_ReclaimPlugin.Recycle_N_ReclaimLogger.LogDebug((object)$"Discarding {___m_dragAmount}/{___m_dragItem.m_stack} {((Object)___m_dragItem.m_dropPrefab).name}"); Utils.InventoryRecycleItem(___m_dragItem, ___m_dragAmount, ___m_dragInventory, __instance, ___m_dragGo); Object.Destroy((Object)(object)___m_dragGo); ___m_dragGo = null; __instance.UpdateCraftingPanel(false); } } } } [<6829e025-ae21-47c8-ac92-c1c427b43056>Nullable(0)] [<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(1)] public class ObjectDumper { private readonly List<int> _hashListOfFoundElements; private readonly int _indentSize; private readonly StringBuilder _stringBuilder; private int _level; private ObjectDumper(int indentSize) { _indentSize = indentSize; _stringBuilder = new StringBuilder(); _hashListOfFoundElements = new List<int>(); } public static string Dump(object element, int indentSize = 2) { return new ObjectDumper(indentSize).DumpElement(element); } private string GetTypeName(Type type) { if (!IsAnonymousType(type)) { return type.Name; } return "AnonymousType"; } private string DumpElement(object element) { if ((element == null || element is ValueType || element is string) ? true : false) { Write(FormatValue(element)); } else { Type type = element.GetType(); if (!typeof(IEnumerable).IsAssignableFrom(type)) { Write("{{{0}}}", GetTypeName(type)); _hashListOfFoundElements.Add(element.GetHashCode()); _level++; } if (element is IEnumerable enumerable) { foreach (object item in enumerable) { if (item is IEnumerable enumerable2 && !(enumerable2 is string)) { _level++; DumpElement(item); _level--; } else if (!AlreadyTouched(item)) { DumpElement(item); } else { Write("{{{0}}} <-- bidirectional reference found", GetTypeName(item.GetType())); } } } else { MemberInfo[] members = element.GetType().GetMembers(BindingFlags.Instance | BindingFlags.Public); foreach (MemberInfo memberInfo in members) { FieldInfo fieldInfo = memberInfo as FieldInfo; PropertyInfo propertyInfo = memberInfo as PropertyInfo; if (fieldInfo == null && propertyInfo == null) { continue; } Type type2 = ((fieldInfo != null) ? fieldInfo.FieldType : propertyInfo.PropertyType); object obj = ((fieldInfo != null) ? fieldInfo.GetValue(element) : propertyInfo.GetValue(element, null)); if (type2.IsValueType || type2 == typeof(string)) { Write("{0}: {1}", memberInfo.Name, FormatValue(obj)); continue; } bool flag = typeof(IEnumerable).IsAssignableFrom(type2); Write("{0}: {1}", memberInfo.Name, flag ? "..." : "{ }"); bool num = !flag && AlreadyTouched(obj); _level++; if (!num) { DumpElement(obj); } else { Write("{{{0}}} <-- bidirectional reference found", GetTypeName(obj.GetType())); } _level--; } } if (!typeof(IEnumerable).IsAssignableFrom(type)) { _level--; } } return _stringBuilder.ToString(); } private bool AlreadyTouched(object value) { if (value == null) { return false; } int hashCode = value.GetHashCode(); for (int i = 0; i < _hashListOfFoundElements.Count; i++) { if (_hashListOfFoundElements[i] == hashCode) { return true; } } return false; } private void Write(string value, params object[] args) { string text = new string(' ', _level * _indentSize); if (args != null) { value = string.Format(value, args); } _stringBuilder.AppendLine(text + value); } private string FormatValue(object o) { if (o != null) { if (!(o is DateTime dateTime)) { if (!(o is string)) { if (o is char) { if ((char)o == '\0') { return string.Empty; } } else if (!(o is ValueType)) { if (o is IEnumerable) { return "..."; } return "{ }"; } return o.ToString(); } return $"\"{o}\""; } return dateTime.ToShortDateString(); } return "null"; } private static bool IsAnonymousType(Type type) { if (type == null) { throw new ArgumentNullException("type"); } if (Attribute.IsDefined(type, typeof(CompilerGeneratedAttribute), inherit: false) && type.IsGenericType && type.Name.Contains("AnonymousType") && (type.Name.StartsWith("<>") || type.Name.StartsWith("VB$"))) { return type.Attributes.HasFlag(TypeAttributes.NotPublic); } return false; } } [<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(1)] [<6829e025-ae21-47c8-ac92-c1c427b43056>Nullable(0)] public static class Utils { public static Texture2D LoadTextureFromResources(string pathName, string folderName = "Assets") { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown Stream manifestResourceStream = typeof(Recycle_N_ReclaimPlugin).Assembly.GetManifestResourceStream(typeof(Recycle_N_ReclaimPlugin).Namespace + "." + folderName + "." + pathName); Texture2D val = new Texture2D(2, 2); Texture2D result = new Texture2D(2, 2); if (manifestResourceStream == null) { return result; } byte[] array; using (BinaryReader binaryReader = new BinaryReader(manifestResourceStream)) { array = binaryReader.ReadBytes((int)manifestResourceStream.Length); } if (!ImageConversion.LoadImage(val, array)) { return result; } return val; } public static void InventoryRecycleItem(ItemData ___m_dragItem, int ___m_dragAmount, Inventory ___m_dragInventory, InventoryGui __instance, GameObject ___m_dragGo) { //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Expected O, but got Unknown //IL_03fd: Unknown result type (might be due to invalid IL or missing references) //IL_0402: Unknown result type (might be due to invalid IL or missing references) //IL_0427: Unknown result type (might be due to invalid IL or missing references) //IL_0439: Expected O, but got Unknown //IL_0642: Unknown result type (might be due to invalid IL or missing references) //IL_0649: Unknown result type (might be due to invalid IL or missing references) //IL_064e: Unknown result type (might be due to invalid IL or missing references) //IL_0655: Unknown result type (might be due to invalid IL or missing references) //IL_065a: Unknown result type (might be due to invalid IL or missing references) //IL_0661: Unknown result type (might be due to invalid IL or missing references) if (GroupUtils.IsPrefabExcludedInInventory(((Object)___m_dragItem.m_dropPrefab).name)) { ((Character)Player.m_localPlayer).Message((MessageType)2, ((Object)___m_dragItem.m_dropPrefab).name + " is blocked via ExcludeLists.yml file [inventory excludes]", 0, (Sprite)null); return; } if (Recycle_N_ReclaimPlugin.returnResources.Value > 0f) { Recipe recipe = ObjectDB.instance.GetRecipe(___m_dragItem); if ((Object)(object)recipe != (Object)null && (Recycle_N_ReclaimPlugin.returnUnknownResources.Value.IsOn() || Player.m_localPlayer.IsRecipeKnown(___m_dragItem.m_shared.m_name))) { Recycle_N_ReclaimPlugin.Recycle_N_ReclaimLogger.LogDebug((object)$"Recipe stack: {recipe.m_amount} num of stacks: {___m_dragAmount / recipe.m_amount}"); List<Requirement> list = recipe.m_resources.ToList(); bool flag = false; bool flag2 = false; if (Recycle_N_ReclaimPlugin.epicLootAssembly != null && Recycle_N_ReclaimPlugin.returnEnchantedResources.Value.IsOn()) { MethodInfo isMagicMethod = UpdateItemDragPatch.isMagicMethod; object obj; if ((object)isMagicMethod == null) { obj = null; } else { object[] parameters = (object[])(object)new ItemData[1] { ___m_dragItem }; obj = isMagicMethod.Invoke(null, parameters); } flag = (bool)obj; } if (flag) { MethodInfo getRarityMethod = UpdateItemDragPatch.getRarityMethod; object obj2; if ((object)getRarityMethod == null) { obj2 = null; } else { object[] parameters = (object[])(object)new ItemData[1] { ___m_dragItem }; obj2 = getRarityMethod.Invoke(null, parameters); } int num = (int)obj2; foreach (KeyValuePair<ItemDrop, int> item in (List<KeyValuePair<ItemDrop, int>>)(UpdateItemDragPatch.getEnchantCostsMethod?.Invoke(null, new object[2] { ___m_dragItem, num }))) { Recipe recipe2 = ObjectDB.instance.GetRecipe(item.Key.m_itemData); bool flag3 = (Object)(object)recipe2 != (Object)null && Player.m_localPlayer.IsRecipeKnown(item.Key.m_itemData.m_shared.m_name); bool flag4 = Player.m_localPlayer.m_knownMaterial.Contains(item.Key.m_itemData.m_shared.m_name); if (Recycle_N_ReclaimPlugin.returnUnknownResources.Value.IsOff() && (!flag3 || !flag4)) { ((Character)Player.m_localPlayer).Message((MessageType)2, Recycle_N_ReclaimPlugin.Localize("$azumatt_recycle_n_reclaim_no_material_recipes"), 0, (Sprite)null); return; } list.Add(new Requirement { m_amount = (((Object)(object)recipe2 != (Object)null) ? recipe2.m_amount : item.Value), m_resItem = item.Key }); } } if (Jewelcrafting.API.IsLoaded() && Recycle_N_ReclaimPlugin.returnEnchantedResources.Value.IsOn() && Jewelcrafting.API.GetGems(___m_dragItem).Any()) { foreach (KeyValuePair<ItemDrop, ItemData> item2 in (from gem in Jewelcrafting.API.GetGems(___m_dragItem) where gem != null select ObjectDB.instance.GetItemPrefab(gem.gemPrefab).GetComponent<ItemDrop>() into itemDrop where (Object)(object)itemDrop != (Object)null select itemDrop).ToDictionary([<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(0)] (ItemDrop itemDrop) => itemDrop, [<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(0)] (ItemDrop itemDrop) => itemDrop.m_itemData)) { Recipe recipe3 = ObjectDB.instance.GetRecipe(item2.Value); bool flag5 = (Object)(object)recipe3 != (Object)null && Player.m_localPlayer.IsRecipeKnown(item2.Value.m_shared.m_name); bool flag6 = Player.m_localPlayer.m_knownMaterial.Contains(item2.Value.m_shared.m_name); if (Recycle_N_ReclaimPlugin.returnUnknownResources.Value.IsOff() && (!flag5 || !flag6)) { ((Character)Player.m_localPlayer).Message((MessageType)2, Recycle_N_ReclaimPlugin.Localize("$azumatt_recycle_n_reclaim_no_material_recipes"), 0, (Sprite)null); return; } list.Add(new Requirement { m_amount = (((Object)(object)recipe3 != (Object)null) ? recipe3.m_amount : item2.Value.m_stack), m_resItem = item2.Key }); } } if (!flag2 && ___m_dragAmount / recipe.m_amount > 0) { for (int i = 0; i < ___m_dragAmount / recipe.m_amount; i++) { foreach (Requirement req in list) { for (int num2 = ___m_dragItem.m_quality; num2 > 0; num2--) { GameObject val = ((IEnumerable<GameObject>)ObjectDB.instance.m_items).FirstOrDefault((Func<GameObject, bool>)([<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(0)] (GameObject item) => item.GetComponent<ItemDrop>().m_itemData.m_shared.m_name == req.m_resItem.m_itemData.m_shared.m_name)); ItemData itemData = val.GetComponent<ItemDrop>().m_itemData.Clone(); int num3 = Mathf.RoundToInt((float)req.GetAmount(num2) * Recycle_N_ReclaimPlugin.returnResources.Value); Recycle_N_ReclaimPlugin.Recycle_N_ReclaimLogger.LogDebug((object)$"Returning {num3}/{req.GetAmount(num2)} {((Object)val).name}"); while (num3 > 0) { int num4 = Mathf.Min(req.m_resItem.m_itemData.m_shared.m_maxStackSize, num3); num3 -= num4; if (!GroupUtils.IsPrefabExcludedInInventory(Utils.GetPrefabName(val))) { Player localPlayer = Player.m_localPlayer; Inventory inventory = ((Humanoid)localPlayer).GetInventory(); if ((Recycle_N_ReclaimPlugin.ApplyCraftedBy.Value.IsOn() ? inventory.AddItem(((Object)val).name, num4, req.m_resItem.m_itemData.m_quality, req.m_resItem.m_itemData.m_variant, localPlayer.GetPlayerID(), localPlayer.GetPlayerName(), false) : inventory.AddItem(((Object)val).name, num4, req.m_resItem.m_itemData.m_quality, req.m_resItem.m_itemData.m_variant, 0L, "", false)) == null) { Transform transform; ItemDrop component = Object.Instantiate<GameObject>(val, (transform = ((Component)Player.m_localPlayer).transform).position + transform.forward + transform.up, transform.rotation).GetComponent<ItemDrop>(); component.m_itemData = itemData; component.m_itemData.m_dropPrefab = val; component.m_itemData.m_stack = num4; component.Save(); } } } } } } } } } if (___m_dragAmount == ___m_dragItem.m_stack) { ((Humanoid)Player.m_localPlayer).RemoveEquipAction(___m_dragItem); ((Humanoid)Player.m_localPlayer).UnequipItem(___m_dragItem, false); ___m_dragInventory.RemoveItem(___m_dragItem); } else { ___m_dragInventory.RemoveItem(___m_dragItem, ___m_dragAmount); } } } [HarmonyPatch(typeof(ZNet), "OnNewConnection")] public static class RegisterAndCheckVersion { [<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(1)] private static void Prefix(ZNetPeer peer, ref ZNet __instance) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown Recycle_N_ReclaimPlugin.Recycle_N_ReclaimLogger.LogDebug((object)"Registering version RPC handler"); peer.m_rpc.Register<ZPackage>("Recycle_N_Reclaim_VersionCheck", (Action<ZRpc, ZPackage>)RpcHandlers.RPC_Recycle_N_Reclaim_Version); Recycle_N_ReclaimPlugin.Recycle_N_ReclaimLogger.LogInfo((object)"Invoking version check"); ZPackage val = new ZPackage(); val.Write("1.4.0"); val.Write(RpcHandlers.ComputeHashForMod().Replace("-", "")); peer.m_rpc.Invoke("Recycle_N_Reclaim_VersionCheck", new object[1] { val }); } } [<6829e025-ae21-47c8-ac92-c1c427b43056>Nullable(0)] [<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(1)] [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] public static class VerifyClient { private static bool Prefix(ZRpc rpc, ZPackage pkg, ref ZNet __instance) { if (!__instance.IsServer() || RpcHandlers.ValidatedPeers.Contains(rpc)) { return true; } Recycle_N_ReclaimPlugin.Recycle_N_ReclaimLogger.LogWarning((object)("Peer (" + rpc.m_socket.GetHostName() + ") never sent version or couldn't due to previous disconnect, disconnecting")); rpc.Invoke("Error", new object[1] { 3 }); return false; } private static void Postfix(ZNet __instance) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), "Recycle_N_ReclaimRequestAdminSync", new object[1] { (object)new ZPackage() }); } } [HarmonyPatch(typeof(FejdStartup), "ShowConnectError")] public class ShowConnectionError { [<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(1)] private static void Postfix(FejdStartup __instance) { if (__instance.m_connectionFailedPanel.activeSelf) { __instance.m_connectionFailedError.fontSizeMax = 25f; __instance.m_connectionFailedError.fontSizeMin = 15f; TMP_Text connectionFailedError = __instance.m_connectionFailedError; connectionFailedError.text = connectionFailedError.text + "\n" + Recycle_N_ReclaimPlugin.ConnectionError; } } } [HarmonyPatch(typeof(ZNet), "Disconnect")] public static class RemoveDisconnectedPeerFromVerified { [<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(1)] private static void Prefix(ZNetPeer peer, ref ZNet __instance) { if (__instance.IsServer()) { Recycle_N_ReclaimPlugin.Recycle_N_ReclaimLogger.LogInfo((object)("Peer (" + peer.m_rpc.m_socket.GetHostName() + ") disconnected, removing from validated list")); RpcHandlers.ValidatedPeers.Remove(peer.m_rpc); } } } [<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(1)] [<6829e025-ae21-47c8-ac92-c1c427b43056>Nullable(0)] public static class RpcHandlers { public static readonly List<ZRpc> ValidatedPeers = new List<ZRpc>(); public static void RPC_Recycle_N_Reclaim_Version(ZRpc rpc, ZPackage pkg) { string text = pkg.ReadString(); string text2 = pkg.ReadString(); string text3 = ComputeHashForMod().Replace("-", ""); Recycle_N_ReclaimPlugin.Recycle_N_ReclaimLogger.LogInfo((object)("Hash/Version check, local: 1.4.0 " + text3 + " remote: " + text + " " + text2)); if (text2 != text3 || text != "1.4.0") { Recycle_N_ReclaimPlugin.ConnectionError = "Recycle_N_Reclaim Installed: 1.4.0 " + text3 + "\n Needed: " + text + " " + text2; if (ZNet.instance.IsServer()) { Recycle_N_ReclaimPlugin.Recycle_N_ReclaimLogger.LogWarning((object)("Peer (" + rpc.m_socket.GetHostName() + ") has incompatible version, disconnecting...")); rpc.Invoke("Error", new object[1] { 3 }); } } else if (!ZNet.instance.IsServer()) { Recycle_N_ReclaimPlugin.Recycle_N_ReclaimLogger.LogInfo((object)"Received same version from server!"); } else { Recycle_N_ReclaimPlugin.Recycle_N_ReclaimLogger.LogInfo((object)("Adding peer (" + rpc.m_socket.GetHostName() + ") to validated list")); ValidatedPeers.Add(rpc); } } public static string ComputeHashForMod() { using SHA256 sHA = SHA256.Create(); byte[] array = sHA.ComputeHash(File.ReadAllBytes(Assembly.GetExecutingAssembly().Location)); StringBuilder stringBuilder = new StringBuilder(); byte[] array2 = array; foreach (byte b in array2) { stringBuilder.Append(b.ToString("X2")); } return stringBuilder.ToString(); } } } namespace Recycle_N_Reclaim.GamePatches.UI { [<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(1)] [<6829e025-ae21-47c8-ac92-c1c427b43056>Nullable(0)] public class ContainerRecyclingButtonHolder : MonoBehaviour { [<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(0)] public delegate void RecycleAllHandler(); private Button _recycleAllButton; private bool _prefired; private TMP_Text _textComponent; private Image _imageComponent; public event RecycleAllHandler OnRecycleAllTriggered; private void Start() { ((MonoBehaviour)this).InvokeRepeating("EnsureRecyclingButtonExistsIfPossible", 0f, 5f); } private void EnsureRecyclingButtonExistsIfPossible() { if (!((Object)(object)InventoryGui.instance == (Object)null)) { if ((Object)(object)_recycleAllButton == (Object)null) { SetupButton(); } ((Component)_recycleAllButton).gameObject.SetActive(Recycle_N_ReclaimPlugin.ContainerRecyclingEnabled.Value.IsOn()); } } private void OnDestroy() { try { Object.Destroy((Object)(object)((Component)_recycleAllButton).gameObject); } catch { } } private void FixedUpdate() { if (!Recycle_N_ReclaimPlugin.ContainerRecyclingEnabled.Value.IsOff() && !((Object)(object)_recycleAllButton == (Object)null) && !InventoryGui.instance.IsContainerOpen() && _prefired) { SetButtonState(showPrefire: false); } } private void SetupButton() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Expected O, but got Unknown if (!((Object)(object)_recycleAllButton != (Object)null)) { if (Recycle_N_ReclaimPlugin.HasAuga) { _recycleAllButton = ((Component)((Transform)InventoryGui.instance.m_container).Find("RecycleAll")).GetComponent<Button>(); } else { Vector3 savedButtonPosition = GetSavedButtonPosition(); _recycleAllButton = Object.Instantiate<Button>(InventoryGui.instance.m_takeAllButton, ((Component)InventoryGui.instance.m_takeAllButton).transform); ((Component)_recycleAllButton).transform.SetParent(((Component)InventoryGui.instance.m_takeAllButton).transform.parent); ((Component)_recycleAllButton).transform.localPosition = savedButtonPosition; } _recycleAllButton.onClick = new ButtonClickedEvent(); ((UnityEvent)_recycleAllButton.onClick).AddListener(new UnityAction(OnRecycleAllPressed)); _textComponent = ((Component)_recycleAllButton).GetComponentInChildren<TMP_Text>(); _imageComponent = ((Component)_recycleAllButton).GetComponentInChildren<Image>(); ((Component)_recycleAllButton).gameObject.AddComponent<UIDragger>().OnUIDropped += delegate(object source, Vector3 position) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) Recycle_N_ReclaimPlugin.ContainerRecyclingButtonPositionJsonString.Value = position; }; SetButtonState(showPrefire: false); } } private Vector3 GetSavedButtonPosition() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) return Recycle_N_ReclaimPlugin.ContainerRecyclingButtonPositionJsonString.Value; } private void SetButtonState(bool showPrefire) { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) if (showPrefire) { _prefired = true; _textComponent.text = Recycle_N_ReclaimPlugin.Localize("$azumatt_recycle_n_reclaim_confirm"); ((Graphic)_imageComponent).color = new Color(1f, 0.5f, 0.5f); } else { _prefired = false; _textComponent.text = Recycle_N_ReclaimPlugin.Localize("$azumatt_recycle_n_reclaim_reclaim_all"); ((Graphic)_imageComponent).color = new Color(0.5f, 1f, 0.5f); } } private void OnRecycleAllPressed() { if (Object.op_Implicit((Object)(object)Player.m_localPlayer)) { if (!_prefired) { SetButtonState(showPrefire: true); return; } SetButtonState(showPrefire: false); this.OnRecycleAllTriggered?.Invoke(); } } } [<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(1)] [<6829e025-ae21-47c8-ac92-c1c427b43056>Nullable(0)] public static class InventoryGuiExtensions { public static float get_m_recipeListBaseSize(this InventoryGui instance) { return instance.m_recipeListBaseSize; } public static List<RecipeDataPair> get_m_recipeList(this InventoryGui instance) { return instance.m_availableRecipes; } public static List<RecipeDataPair> get_m_availableRecipes(this InventoryGui instance) { return instance.m_availableRecipes; } public static RecipeDataPair get_m_selectedRecipe(this InventoryGui instance) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return instance.m_selectedRecipe; } public static void set_m_selectedRecipe(this InventoryGui instance, RecipeDataPair value) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) instance.m_selectedRecipe = value; } public static int get_m_selectedVariant(this InventoryGui instance) { return instance.m_selectedVariant; } public static void set_m_selectedVariant(this InventoryGui instance, int value) { instance.m_selectedVariant = value; } public static float get_m_craftTimer(this InventoryGui instance) { return instance.m_craftTimer; } public static void set_m_craftTimer(this InventoryGui instance, float value) { instance.m_craftTimer = value; } public static Color get_m_minStationLevelBasecolor(this InventoryGui instance) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return instance.m_minStationLevelBasecolor; } } [<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(1)] [HarmonyPatch] [<6829e025-ae21-47c8-ac92-c1c427b43056>Nullable(0)] public static class InventoryGuiPatches { [HarmonyPriority(600)] [HarmonyPatch(typeof(InventoryGui), "OnTabUpgradePressed")] [HarmonyPatch(typeof(InventoryGui), "OnTabCraftPressed")] [HarmonyPrefix] private static void OnTabCraftPressedAlsoEnableRecycling1(InventoryGui __instance) { Recycle_N_ReclaimPlugin.RecyclingTabButtonHolder.SetInteractable(interactable: true); __instance.UpdateCraftingPanel(false); } [HarmonyPrefix] [HarmonyPatch(typeof(InventoryGui), "UpdateCraftingPanel")] private static bool UpdateCraftingPanelDetourOnRecyclingTab(InventoryGui __instance) { if (Recycle_N_ReclaimPlugin.RecyclingTabButtonHolder.InRecycleTab()) { return false; } return true; } [HarmonyPatch(typeof(InventoryGui), "Hide")] [HarmonyPrefix] private static void OnHideSetToCraftingTab(InventoryGui __instance) { if (!((Object)(object)Recycle_N_ReclaimPlugin.RecyclingTabButtonHolder == (Object)null) && Recycle_N_ReclaimPlugin.RecyclingTabButtonHolder.InRecycleTab()) { InventoryGui.instance.OnTabCraftPressed(); Recycle_N_ReclaimPlugin.RecyclingTabButtonHolder.SetActive(active: false); } } [HarmonyPostfix] [HarmonyPatch(typeof(InventoryGui), "UpdateCraftingPanel")] private static void UpdateCraftingPanelDetourOnOtherTabsEnableRecyclingButton(InventoryGui __instance) { if (!Recycle_N_ReclaimPlugin.RecyclingTabButtonHolder.InRecycleTab()) { Player localPlayer = Player.m_localPlayer; Recycle_N_ReclaimPlugin.RecyclingTabButtonHolder.SetInteractable(interactable: true); if (!Object.op_Implicit((Object)(object)localPlayer.GetCurrentCraftingStation()) && !localPlayer.NoCostCheat()) { Recycle_N_ReclaimPlugin.RecyclingTabButtonHolder.SetActive(active: false); } else { Recycle_N_ReclaimPlugin.RecyclingTabButtonHolder.SetActive(active: true); } } } [HarmonyPrefix] [HarmonyPatch(typeof(InventoryGui), "UpdateRecipe", new Type[] { typeof(Player), typeof(float) })] private static bool UpdateRecipeOnRecyclingTab(InventoryGui __instance, Player player, float dt) { if (!Recycle_N_ReclaimPlugin.RecyclingTabButtonHolder.InRecycleTab()) { return true; } Recycle_N_ReclaimPlugin.RecyclingTabButtonHolder.UpdateRecipe(player, dt); return false; } [HarmonyPostfix] [HarmonyPatch(typeof(Inventory), "Changed")] private static void InventorySave(Inventory __instance) { if (!((Object)(object)Recycle_N_ReclaimPlugin.RecyclingTabButtonHolder == (Object)null) && Recycle_N_ReclaimPlugin.RecyclingTabButtonHolder.InRecycleTab() && __instance == ((Humanoid)Player.m_localPlayer).GetInventory() && Recycle_N_ReclaimPlugin.RecyclingTabButtonHolder.HasInventoryChanged(__instance)) { Recycle_N_ReclaimPlugin.RecyclingTabButtonHolder.UpdateRecyclingList(); InventoryGui.instance.SetRecipe(-1, false); } } [HarmonyPatch(typeof(InventoryGui), "Update")] [HarmonyPostfix] private static void OnInventoryGuiUpdate() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (InventoryGui.IsVisible() && !((Object)(object)Player.m_localPlayer == (Object)null) && Recycle_N_ReclaimPlugin.UndoRecycleKeybind.Value.IsKeyDown() && RecycleUndoManager.CanUndo) { RecycleUndoManager.TryUndo(); } } [HarmonyPostfix] [HarmonyPatch(typeof(Humanoid), "UnequipItem", new Type[] { typeof(ItemData), typeof(bool) })] [HarmonyPatch(typeof(Humanoid), "EquipItem", new Type[] { typeof(ItemData), typeof(bool) })] private static void HumanoidEquip(Humanoid __instance) { if (!((Object)(object)Recycle_N_ReclaimPlugin.RecyclingTabButtonHolder == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && Recycle_N_ReclaimPlugin.RecyclingTabButtonHolder.InRecycleTab() && __instance.GetInventory() == ((Humanoid)Player.m_localPlayer).GetInventory()) { Recycle_N_ReclaimPlugin.RecyclingTabButtonHolder.UpdateRecyclingList(); InventoryGui.instance.SetRecipe(-1, false); } } } [<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(1)] [<6829e025-ae21-47c8-ac92-c1c427b43056>Nullable(0)] public class StationRecyclingTabHolder : MonoBehaviour { private GameObject _recyclingTabButtonGameObject; private Button _recyclingTabButtonComponent; private List<RecyclingAnalysisContext> _recyclingAnalysisContexts = new List<RecyclingAnalysisContext>(); private int _lastInventoryHash; private WorkbenchTabData _augaTabData; private GameObject _itemInfoGo; private GameObject _descriptionBoxGo; private void Start() { ((MonoBehaviour)this).InvokeRepeating("EnsureRecyclingTabExists", 5f, 5f); } private void EnsureRecyclingTabExists() { if (!((Object)(object)InventoryGui.instance == (Object)null) && (Object)(object)_recyclingTabButtonComponent == (Object)null) { SetupTabButton(); } } private void OnDestroy() { try { Object.Destroy((Object)(object)_recyclingTabButtonGameObject.gameObject); } catch { } } private void SetupTabButton() { //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Expected O, but got Unknown //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Expected O, but got Unknown //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.m_localPlayer == (Object)null) { return; } Recycle_N_ReclaimPlugin.Recycle_N_ReclaimLogger.LogDebug((object)"Creating Workbench Tab"); if (Recycle_N_ReclaimPlugin.HasAuga) { if (!Auga.API.Workbench_HasWorkbenchTab("Reclaim")) { Texture2D val = Utils.LoadTextureFromResources("RecyclingPanel.png"); Sprite tabIcon = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0f, 0f), 100f); if (Recycle_N_ReclaimPlugin.epicLootAssembly != null) { _augaTabData = Auga.API.Workbench_AddWorkbenchTab("Reclaim", tabIcon, "Recycle_N_Reclaim".Replace("_", "-"), delegate { OnRecycleClick(); }); } else { _augaTabData = Auga.API.Workbench_AddVanillaWorkbenchTab("Reclaim", tabIcon, "Recycle_N_Reclaim".Replace("_", "-"), delegate { OnRecycleClick(); }); } _recyclingTabButtonComponent = (_recyclingTabButtonGameObject = _augaTabData.TabButtonGO).GetComponent<Button>(); _itemInfoGo = _augaTabData.ItemInfoGO; Auga.API.ComplexTooltip_AddDivider(_itemInfoGo); _descriptionBoxGo = Auga.API.ComplexTooltip_AddTwoColumnTextBox(_itemInfoGo); Auga.API.ComplexTooltip_EnableDescription(_itemInfoGo, enabled: false); } } else { Transform transform = ((Component)InventoryGui.instance.m_tabUpgrade).transform; _recyclingTabButtonGameObject = Object.Instantiate<GameObject>(((Component)InventoryGui.instance.m_tabUpgrade).gameObject, transform.position, transform.rotation, transform.parent); ((Object)_recyclingTabButtonGameObject).name = "RECLAIM"; _recyclingTabButtonGameObject.transform.parent.Find("TabBorder").SetAsLastSibling(); _recyclingTabButtonGameObject.transform.localPosition = new Vector3(-45f, -94f, 0f); _recyclingTabButtonComponent = _recyclingTabButtonGameObject.GetComponent<Button>(); ((Selectable)_recyclingTabButtonComponent).interactable = true; _recyclingTabButtonComponent.onClick = new ButtonClickedEvent(); ((UnityEvent)_recyclingTabButtonComponent.onClick).AddListener(new UnityAction(OnRecycleClick)); TMP_Text componentInChildren = _recyclingTabButtonGameObject.GetComponentInChildren<TMP_Text>(); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.text = Recycle_N_ReclaimPlugin.Localize("$azumatt_recycle_n_reclaim_reclaim_tab"); } } bool active = (Object)(object)Player.m_localPlayer.GetCurrentCraftingStation() != (Object)null; _recyclingTabButtonGameObject.SetActive(active); } private void OnRecycleClick() { ((Selectable)_recyclingTabButtonComponent).interactable = false; ((Selectable)InventoryGui.instance.m_tabCraft).interactable = true; ((Selectable)InventoryGui.instance.m_tabUpgrade).interactable = true; Recycle_N_ReclaimPlugin.Recycle_N_ReclaimLogger.LogDebug((object)"OnRecycleClick"); UpdateCraftingPanel(); } public void UpdateCraftingPanel() { //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) InventoryGui instance = InventoryGui.instance; Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer.GetCurrentCraftingStation() == (Object)null && !localPlayer.NoCostCheat()) { ((Selectable)instance.m_tabCraft).interactable = false; ((Selectable)instance.m_tabUpgrade).interactable = true; ((Component)instance.m_tabUpgrade).gameObject.SetActive(false); ((Selectable)_recyclingTabButtonComponent).interactable = true; ((Component)_recyclingTabButtonComponent).gameObject.SetActive(false); } else { ((Component)instance.m_tabUpgrade).gameObject.SetActive(true); } UpdateRecyclingList(); RecipeDataPair val; if (instance.m_availableRecipes.Count > 0) { val = instance.get_m_selectedRecipe(); if ((Object)(object)((RecipeDataPair)(ref val)).Recipe != (Object)null) { instance.SetRecipe(instance.GetSelectedRecipeIndex(false), true); } else { instance.SetRecipe(0, true); } } else { InventoryGui.instance.SetRecipe(-1, true); } if (Recycle_N_ReclaimPlugin.HasAuga) { GameObject itemInfoGo = _itemInfoGo; val = instance.get_m_selectedRecipe(); Auga.API.ComplexTooltip_SetItem(itemInfoGo, ((RecipeDataPair)(ref val)).ItemData); } } public void UpdateRecyclingList() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; InventoryGui instance = InventoryGui.instance; List<RecipeDataPair> list = instance.get_m_recipeList(); Recycle_N_ReclaimPlugin.Recycle_N_ReclaimLogger.LogDebug((object)$"Old recipe list had {list.Count} entries. Cleaning up"); foreach (RecipeDataPair item in list) { RecipeDataPair current = item; Object.Destroy((Object)(object)((RecipeDataPair)(ref current)).InterfaceElement); } list.Clear(); _recyclingAnalysisContexts.Clear(); IEnumerable<RecyclingAnalysisContext> source = from context in Reclaimer.GetRecyclingAnalysisForInventory(((Humanoid)localPlayer).GetInventory(), localPlayer) where (Object)(object)context.Recipe != (Object)null && context.DisplayImpediments.Count == 0 select context; _recyclingAnalysisContexts.AddRange(source.Where([<298e2216-e15e-46fc-9981-b5eb9d2dff2b>NullableContext(0)] (RecyclingAnalysisContext x) => !GroupUtils.IsPrefabExcludedInReclaiming(((Object)x.Item.m_dropPrefab).name))); foreach (RecyclingAnalysisContext recyclingAnalysisContext in _recyclingAnalysisContexts) { if (!((Object)(object)recyclingAnalysisContext.Recipe == (Object)null)) { AddRecipeToList(recyclingAnalysisContext, list); } } Recycle_N_ReclaimPlugin.Recycle_N_ReclaimLogger.LogDebug((object)$"Added {list.Count} entries"); instance.m_recipeListRoot.SetSizeWithCurrentAnchors((Axis)1, Mathf.Max(instance.get_m_recipeListBaseSize(), (float)list.Count * instance.m_recipeListSpace)); _lastInventoryHash = ComputeInventoryHash(((Humanoid)localPlayer).GetInventory()); } private void AddRecipeToList(RecyclingAnalysisContext context, List<RecipeDataPair> m_recipeList) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Expected O, but got Unknown //IL_02d6: Unknown result type (might be due to invalid IL or missing references) int count = m_recipeList.Count; InventoryGui igui = InventoryGui.instance; RectTransform recipeListRoot = igui.m_recipeListRoot; GameObject element = Object.Instantiate<GameObject>(igui.m_recipeElementPrefab, (Transform)(object)recipeListRoot); element.SetActive(true); ((RectTransform)element.transform).anchoredPosition = new Vector2(0f, (float)count * (0f - igui.m_recipeListSpace)); Image component = ((Component)element.transform.Find("icon")).GetComponent<Image>(); component.sprite = context.Item.GetIcon(); ((Graphic)component).color = (Color)((context.RecyclingImpediments.Count == 0) ? Color.white : new Color(1f, 0f, 1f, 0f)); TMP_Text component2 = ((Component)element.transform.Find("name")).GetComponent<TMP_Text>(); string text = Recycle_N_ReclaimPlugin.Localize(context.Item.m_shared.m_name); if (context.Item.m_stack > 1 && context.Item.m_shared.m_maxStackSize > 1) { text = $"{text} x{context.Item.m_stack}"; } component2.text = text; ((Graphic)component2).color = (Color)((context.RecyclingImpediments.Count == 0) ? Color.white : new Color(0.66f, 0.66f, 0.66f, 1f)); GuiBar component3 = ((Component)element.transform.Find("Durability")).GetComponent<GuiBar>(); if (context.Item.m_shared.m_useDurability && (double)context.Item.m_durability < (double)context.Item.GetMaxDurability()) { ((Component)component3).gameObject.SetActive(true); component3.SetValue(context.Item.GetDurabilityPercentage()); } else { ((Component)component3).gameObject.SetActive(false); } TMP_Text component4 = ((Component)element.transform.Find("QualityLevel")).GetComponent<TMP_Text>(); ((Component)component4).gameObject.SetActive(true); component4.text = context.Item.m_quality.ToString(); ((UnityEvent)element.GetComponent<Button>().onClick).AddListener((UnityAction)delegate { igui.OnSelectedRecipe(element); }); bool globalKey = ZoneSystem.instance.GetGlobalKey((GlobalKeys)20); bool flag = (igui.InCraftTab() ? (Player.m_localPlayer.HaveRequirements(context.Recipe, false, 1, 1) || globalKey) : (context.Item.m_quality < context.Item.m_shared.m_maxQuality && (Player.m_localPlayer.HaveRequirements(context.Recipe, false, context.Item.m_quality + 1, 1) || globalKey))); m_recipeList.Add(new RecipeDataPair(context.Recipe, context.Item, element, flag)); } private static int ComputeInventoryHash(Inventory inventory) { int num = 17; foreach (ItemData item in from i in inventory.GetAllItems() orderby i.m_shared.m_name, i.m_quality select i) { num = num * 31 + item.m_shared.m_name.GetHashCode(); num = num * 31 + item.m_quality; num = num * 31