Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of InventorySlots v1.0.4
InventorySlots.dll
Decompiled 8 hours 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.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using JetBrains.Annotations; using LocalizationManager; using Microsoft.CodeAnalysis; 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.ObjectPool; using YamlDotNet.Core.Tokens; using YamlDotNet.Helpers; using YamlDotNet.Serialization; using YamlDotNet.Serialization.BufferedDeserialization; using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators; using YamlDotNet.Serialization.Callbacks; 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: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("InventorySlots")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("sighsorry")] [assembly: AssemblyProduct("InventorySlots")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("A57F2112-F59E-48EF-9D76-F2E4580F7401")] [assembly: AssemblyFileVersion("1.0.4")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.4.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace LocalizationManager { internal static class Localizer { [CompilerGenerated] private sealed class <FindExternalTranslationFiles>d__15 : IEnumerable<string>, IEnumerable, IEnumerator<string>, IDisposable, IEnumerator { private int <>1__state; private string <>2__current; private int <>l__initialThreadId; private string language; public string <>3__language; private string <modName>5__2; private IEnumerator<string> <>7__wrap2; private string <root>5__4; private string[] <>7__wrap4; private int <>7__wrap5; private string[] <>7__wrap6; private int <>7__wrap7; string IEnumerator<string>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <FindExternalTranslationFiles>d__15(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <modName>5__2 = null; <>7__wrap2 = null; <root>5__4 = null; <>7__wrap4 = null; <>7__wrap6 = null; <>1__state = -2; } private bool MoveNext() { try { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -3; <>7__wrap7++; goto IL_011f; } <>1__state = -1; if ((Object)(object)_plugin == (Object)null) { return false; } <modName>5__2 = _plugin.Info.Metadata.Name; <>7__wrap2 = GetExternalTranslationRoots().GetEnumerator(); <>1__state = -3; goto IL_0165; IL_011f: if (<>7__wrap7 < <>7__wrap6.Length) { string text = <>7__wrap6[<>7__wrap7]; <>2__current = text; <>1__state = 1; return true; } <>7__wrap6 = null; <>7__wrap5++; goto IL_0144; IL_0144: if (<>7__wrap5 < <>7__wrap4.Length) { string text2 = <>7__wrap4[<>7__wrap5]; string searchPattern = <modName>5__2 + "." + language + text2; <>7__wrap6 = Directory.GetFiles(<root>5__4, searchPattern, SearchOption.AllDirectories); <>7__wrap7 = 0; goto IL_011f; } <>7__wrap4 = null; <root>5__4 = null; goto IL_0165; IL_0165: do { if (<>7__wrap2.MoveNext()) { <root>5__4 = <>7__wrap2.Current; continue; } <>m__Finally1(); <>7__wrap2 = null; return false; } while (!Directory.Exists(<root>5__4)); <>7__wrap4 = FileExtensions; <>7__wrap5 = 0; goto IL_0144; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>7__wrap2 != null) { <>7__wrap2.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<string> IEnumerable<string>.GetEnumerator() { <FindExternalTranslationFiles>d__15 <FindExternalTranslationFiles>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <FindExternalTranslationFiles>d__ = this; } else { <FindExternalTranslationFiles>d__ = new <FindExternalTranslationFiles>d__15(0); } <FindExternalTranslationFiles>d__.language = <>3__language; return <FindExternalTranslationFiles>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<string>)this).GetEnumerator(); } } [CompilerGenerated] private sealed class <GetExternalTranslationRoots>d__16 : IEnumerable<string>, IEnumerable, IEnumerator<string>, IDisposable, IEnumerator { private int <>1__state; private string <>2__current; private int <>l__initialThreadId; string IEnumerator<string>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <GetExternalTranslationRoots>d__16(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (!string.IsNullOrWhiteSpace(Paths.PluginPath)) { <>2__current = Paths.PluginPath; <>1__state = 1; return true; } goto IL_0049; case 1: <>1__state = -1; goto IL_0049; case 2: { <>1__state = -1; break; } IL_0049: if ((Object)(object)_plugin != (Object)null) { <>2__current = Path.Combine(Paths.ConfigPath, _plugin.Info.Metadata.GUID + "Translations"); <>1__state = 2; return true; } break; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<string> IEnumerable<string>.GetEnumerator() { if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; return this; } return new <GetExternalTranslationRoots>d__16(0); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<string>)this).GetEnumerator(); } } private static readonly string[] FileExtensions = new string[2] { ".yml", ".json" }; private static readonly ManualLogSource Log = Logger.CreateLogSource("InventorySlots.Localization"); private static BaseUnityPlugin? _plugin; private static bool _loaded; public static event Action? OnLocalizationComplete; public static void Load(BaseUnityPlugin plugin) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown _plugin = plugin; if (_loaded) { TryLoadCurrentLanguage(); return; } _loaded = true; PatchLocalization(new Harmony(plugin.Info.Metadata.GUID + ".LocalizationManager")); TryLoadCurrentLanguage(); } private static void PatchLocalization(Harmony harmony) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(Localization), "SetupLanguage", (Type[])null, (Type[])null); if (methodInfo != null) { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(Localizer), "LocalizationSetupLanguagePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } MethodInfo methodInfo2 = AccessTools.DeclaredMethod(typeof(FejdStartup), "SetupGui", (Type[])null, (Type[])null); if (methodInfo2 != null) { harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(Localizer), "FejdStartupSetupGuiPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } private static void LocalizationSetupLanguagePostfix(Localization __instance, string language) { LoadLocalization(__instance, language); } private static void FejdStartupSetupGuiPostfix() { TryLoadCurrentLanguage(); } private static void TryLoadCurrentLanguage() { if (Localization.instance != null) { LoadLocalization(Localization.instance, Localization.instance.GetSelectedLanguage()); } } private static void LoadLocalization(Localization localization, string language) { if ((Object)(object)_plugin == (Object)null || localization == null) { return; } Dictionary<string, string> dictionary = LoadLanguageDictionary("English"); if (!string.Equals(language, "English", StringComparison.OrdinalIgnoreCase)) { Merge(dictionary, LoadLanguageDictionary(language)); } foreach (KeyValuePair<string, string> item in dictionary) { localization.AddWord(item.Key, item.Value); } Localizer.OnLocalizationComplete?.Invoke(); } private static Dictionary<string, string> LoadLanguageDictionary(string language) { Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); Merge(dictionary, LoadEmbeddedLanguage(language)); foreach (string item in FindExternalTranslationFiles(language)) { try { Merge(dictionary, ParseTranslations(File.ReadAllText(item), item)); } catch (Exception ex) { Log.LogWarning((object)("Failed to load localization file " + item + ": " + ex.Message)); } } return dictionary; } private static Dictionary<string, string> LoadEmbeddedLanguage(string language) { string[] fileExtensions = FileExtensions; foreach (string text in fileExtensions) { byte[] array = ReadEmbeddedFileBytes("translations." + language + text); if (array != null) { return ParseTranslations(Encoding.UTF8.GetString(array), language + text); } } if (string.Equals(language, "English", StringComparison.OrdinalIgnoreCase)) { Log.LogWarning((object)"Found no embedded English localization for InventorySlots."); } return new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); } [IteratorStateMachine(typeof(<FindExternalTranslationFiles>d__15))] private static IEnumerable<string> FindExternalTranslationFiles(string language) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <FindExternalTranslationFiles>d__15(-2) { <>3__language = language }; } [IteratorStateMachine(typeof(<GetExternalTranslationRoots>d__16))] private static IEnumerable<string> GetExternalTranslationRoots() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <GetExternalTranslationRoots>d__16(-2); } private static Dictionary<string, string> ParseTranslations(string text, string source) { try { return new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(text) ?? new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); } catch (Exception ex) { Log.LogWarning((object)("Failed to parse localization source " + source + ": " + ex.Message)); return new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); } } private static void Merge(Dictionary<string, string> target, Dictionary<string, string> source) { foreach (KeyValuePair<string, string> item in source) { target[item.Key] = item.Value; } } private static byte[]? ReadEmbeddedFileBytes(string resourceFileName) { string resourceFileName2 = resourceFileName; if ((Object)(object)_plugin == (Object)null) { return null; } Assembly assembly = ((object)_plugin).GetType().Assembly; string text = assembly.GetManifestResourceNames().FirstOrDefault((string name) => name.EndsWith(resourceFileName2, StringComparison.OrdinalIgnoreCase)); if (text == null) { return null; } using Stream stream = assembly.GetManifestResourceStream(text); if (stream == null) { return null; } using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); return (memoryStream.Length == 0L) ? null : memoryStream.ToArray(); } } } namespace InventorySlots { [BepInPlugin("sighsorry.InventorySlots", "InventorySlots", "1.0.4")] [BepInIncompatibility("Azumatt.AzuExtendedPlayerInventory")] [BepInIncompatibility("shudnal.ExtraSlots")] [BepInIncompatibility("shudnal.ExtraSlotsCustomSlots")] [BepInIncompatibility("randyknapp.mods.equipmentandquickslots")] [BepInIncompatibility("com.bruce.valheim.comfyquickslots")] [BepInIncompatibility("goldenrevolver.quick_stack_store")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class InventorySlotsPlugin : BaseUnityPlugin { private sealed class AzuCraftyBoxesApi { private readonly MethodInfo _getNearbyContainersMethod; private readonly MethodInfo _canItemBePulledMethod; private readonly MethodInfo? _shouldPreventMethod; private readonly FieldInfo? _rangeField; private readonly FieldInfo? _leaveOneField; private readonly FieldInfo? _resourceStringField; private readonly FieldInfo? _flashColorField; private readonly FieldInfo? _unFlashColorField; private readonly Dictionary<Type, MethodInfo?> _getPrefabNameMethods = new Dictionary<Type, MethodInfo>(); private readonly Dictionary<Type, MethodInfo?> _itemCountMethods = new Dictionary<Type, MethodInfo>(); private ConfigEntryBase? _rangeConfig; private ConfigEntryBase? _leaveOneConfig; private ConfigEntryBase? _resourceStringConfig; private ConfigEntryBase? _flashColorConfig; private ConfigEntryBase? _unFlashColorConfig; private AzuCraftyBoxesApi(MethodInfo getNearbyContainersMethod, MethodInfo canItemBePulledMethod, MethodInfo? shouldPreventMethod, FieldInfo? rangeField, FieldInfo? leaveOneField, FieldInfo? resourceStringField, FieldInfo? flashColorField, FieldInfo? unFlashColorField) { _getNearbyContainersMethod = getNearbyContainersMethod; _canItemBePulledMethod = canItemBePulledMethod; _shouldPreventMethod = shouldPreventMethod; _rangeField = rangeField; _leaveOneField = leaveOneField; _resourceStringField = resourceStringField; _flashColorField = flashColorField; _unFlashColorField = unFlashColorField; } public static bool TryCreate(Assembly assembly, out AzuCraftyBoxesApi? api, out string detail) { api = null; Type type = assembly.GetType("AzuCraftyBoxes.API"); Type type2 = assembly.GetType("AzuCraftyBoxes.AzuCraftyBoxesPlugin"); Type type3 = assembly.GetType("AzuCraftyBoxes.Util.Functions.MiscFunctions"); MethodInfo methodInfo = (type?.GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault((MethodInfo method) => method.Name == "GetNearbyContainers" && method.IsGenericMethodDefinition && method.GetParameters().Length == 2))?.MakeGenericMethod(typeof(Player)); MethodInfo methodInfo2 = type?.GetMethod("CanItemBePulled", BindingFlags.Static | BindingFlags.Public, null, new Type[2] { typeof(string), typeof(string) }, null); if (methodInfo == null || methodInfo2 == null) { detail = "required API methods were not found"; return false; } api = new AzuCraftyBoxesApi(methodInfo, methodInfo2, type3?.GetMethod("ShouldPrevent", BindingFlags.Static | BindingFlags.NonPublic), type2?.GetField("mRange", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic), type2?.GetField("leaveOne", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic), type2?.GetField("resourceString", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic), type2?.GetField("flashColor", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic), type2?.GetField("unFlashColor", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)); detail = ""; return true; } public IEnumerable? GetNearbyContainers(Player player, float range) { return _getNearbyContainersMethod.Invoke(null, new object[2] { player, range }) as IEnumerable; } public bool CanItemBePulled(string containerPrefab, string itemPrefab) { try { object obj = _canItemBePulledMethod.Invoke(null, new object[2] { containerPrefab, itemPrefab }); return obj is bool && (bool)obj; } catch { return false; } } public bool ShouldPrevent() { if (_shouldPreventMethod == null) { return false; } try { object obj = _shouldPreventMethod.Invoke(null, null); return obj is bool && (bool)obj; } catch { return false; } } public float GetRange() { object cachedConfigEntryValue = GetCachedConfigEntryValue(_rangeField, ref _rangeConfig); if (cachedConfigEntryValue == null) { return 20f; } try { return Convert.ToSingle(cachedConfigEntryValue); } catch { return 20f; } } public bool GetLeaveOne() { string a = GetCachedConfigEntryValue(_leaveOneField, ref _leaveOneConfig)?.ToString() ?? ""; if (!string.Equals(a, "On", StringComparison.OrdinalIgnoreCase)) { return string.Equals(a, "True", StringComparison.OrdinalIgnoreCase); } return true; } public string InvokeString(object instance, string methodName) { Type type = instance.GetType(); if (!_getPrefabNameMethods.TryGetValue(type, out MethodInfo value)) { value = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public); _getPrefabNameMethods[type] = value; } try { return (value?.Invoke(instance, null) as string) ?? ""; } catch { return ""; } } public int InvokeInt(object instance, string methodName, string argument) { Type type = instance.GetType(); if (!_itemCountMethods.TryGetValue(type, out MethodInfo value)) { value = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public, null, new Type[1] { typeof(string) }, null); _itemCountMethods[type] = value; } try { return (value?.Invoke(instance, new object[1] { argument }) is int num) ? num : 0; } catch { return 0; } } public bool TryFormatRequirementAmount(int available, int required, out string text) { text = ""; string text2 = (GetCachedConfigEntryValue(_resourceStringField, ref _resourceStringConfig) as string) ?? ""; if (string.IsNullOrWhiteSpace(text2)) { text = required.ToString(); return true; } try { text = string.Format(text2, FormatThousands(available), required); return true; } catch { text = $"{FormatThousands(available)}/{required}"; return true; } } public bool TryGetRequirementFlashColor(out Color color) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) color = default(Color); FieldInfo fieldInfo = ((Mathf.Sin(Time.time * 10f) > 0f) ? _flashColorField : _unFlashColorField); if (((fieldInfo == _flashColorField) ? GetCachedConfigEntryValue(fieldInfo, ref _flashColorConfig) : GetCachedConfigEntryValue(fieldInfo, ref _unFlashColorConfig)) is Color val) { color = val; return true; } return false; } private object? GetCachedConfigEntryValue(FieldInfo? field, ref ConfigEntryBase? config) { if (field == null) { return null; } try { if (config == null) { object? value = field.GetValue(null); config = (ConfigEntryBase?)((value is ConfigEntryBase) ? value : null); } ConfigEntryBase? obj = config; return (obj != null) ? obj.BoxedValue : null; } catch { config = null; return null; } } private static string FormatThousands(int number) { if (number >= 1000000) { return ((double)number / 1000000.0).ToString("0.#") + "M"; } if (number < 1000) { return number.ToString(); } return ((double)number / 1000.0).ToString("0.#") + "K"; } } private sealed class AdventureBackpacksApi { private readonly MethodInfo _isBackpackMethod; private readonly MethodInfo? _equipItemPostfixMethod; private readonly MethodInfo? _unequipItemPrefixMethod; private readonly MethodInfo? _isBackpackEquippedMethod; private readonly MethodInfo? _isThisBackpackEquippedMethod; private readonly MethodInfo? _getEquippedBackpackMethod; private readonly FieldInfo? _backpackEquippedField; private AdventureBackpacksApi(MethodInfo isBackpackMethod, MethodInfo? equipItemPostfixMethod, MethodInfo? unequipItemPrefixMethod, MethodInfo? isBackpackEquippedMethod, MethodInfo? isThisBackpackEquippedMethod, MethodInfo? getEquippedBackpackMethod, FieldInfo? backpackEquippedField) { _isBackpackMethod = isBackpackMethod; _equipItemPostfixMethod = equipItemPostfixMethod; _unequipItemPrefixMethod = unequipItemPrefixMethod; _isBackpackEquippedMethod = isBackpackEquippedMethod; _isThisBackpackEquippedMethod = isThisBackpackEquippedMethod; _getEquippedBackpackMethod = getEquippedBackpackMethod; _backpackEquippedField = backpackEquippedField; } public static bool TryCreate(Assembly assembly, out AdventureBackpacksApi? api, out string detail) { api = null; MethodInfo methodInfo = assembly.GetType("AdventureBackpacks.API.ABAPI")?.GetMethod("IsBackpack", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(ItemData) }, null); if (methodInfo == null) { detail = "AdventureBackpacks.API.ABAPI.IsBackpack was not found"; return false; } Type? type = assembly.GetType("AdventureBackpacks.Patches.HumanoidPatches"); Type type2 = type?.GetNestedType("HumanoidEquipItemPatch", BindingFlags.NonPublic); Type type3 = type?.GetNestedType("HumanoidUnequipItemPatch", BindingFlags.NonPublic); Type type4 = assembly.GetType("AdventureBackpacks.Extensions.PlayerExtensions"); Type type5 = assembly.GetType("AdventureBackpacks.Patches.InventoryGuiPatches"); api = new AdventureBackpacksApi(methodInfo, type2?.GetMethod("Postfix", BindingFlags.Static | BindingFlags.NonPublic), type3?.GetMethod("Prefix", BindingFlags.Static | BindingFlags.NonPublic), type4?.GetMethod("IsBackpackEquipped", BindingFlags.Static | BindingFlags.Public), type4?.GetMethod("IsThisBackpackEquipped", BindingFlags.Static | BindingFlags.Public), type4?.GetMethod("GetEquippedBackpack", BindingFlags.Static | BindingFlags.Public), type5?.GetField("BackpackEquipped", BindingFlags.Static | BindingFlags.Public)); detail = ""; return true; } public bool IsBackpack(ItemData? item) { if (item == null) { return false; } try { object obj = _isBackpackMethod.Invoke(null, new object[1] { item }); return obj is bool && (bool)obj; } catch { return false; } } public bool IsBackpackEquippedFlagSet() { try { object obj = _backpackEquippedField?.GetValue(null); return obj is bool && (bool)obj; } catch { return false; } } public void OnCustomBackpackEquipped(Player player, ItemData item) { if ((Object)(object)player == (Object)null || item == null || !IsBackpack(item)) { return; } try { _equipItemPostfixMethod?.Invoke(null, new object[2] { item, true }); _backpackEquippedField?.SetValue(null, true); } catch (Exception ex) { Log.LogDebug((object)("AdventureBackpacks equip sync failed: " + ex.Message)); } } public void OnCustomBackpackUnequipping(Player player, ItemData item) { if ((Object)(object)player == (Object)null || item == null || !IsBackpack(item)) { return; } ItemData shoulderItem = ((Humanoid)player).m_shoulderItem; try { ((Humanoid)player).m_shoulderItem = item; _unequipItemPrefixMethod?.Invoke(null, new object[1] { item }); } catch (Exception ex) { Log.LogDebug((object)("AdventureBackpacks unequip sync failed: " + ex.Message)); } finally { ((Humanoid)player).m_shoulderItem = shoulderItem; } } public void ApplyPatches(Harmony harmony) { PatchOptional(harmony, _isBackpackEquippedMethod, null, "AdventureBackpackIsBackpackEquippedPostfix", "AdventureBackpacks IsBackpackEquipped"); PatchOptional(harmony, _isThisBackpackEquippedMethod, null, "AdventureBackpackIsThisBackpackEquippedPostfix", "AdventureBackpacks IsThisBackpackEquipped"); PatchOptional(harmony, _getEquippedBackpackMethod, "AdventureBackpackGetEquippedBackpackPrefix", "AdventureBackpackGetEquippedBackpackPostfix", "AdventureBackpacks GetEquippedBackpack"); } private static void PatchOptional(Harmony harmony, MethodInfo? target, string? prefix = null, string? postfix = null, string? label = null) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) if (harmony != null && !(target == null)) { MethodInfo methodInfo = ((prefix == null) ? null : AccessTools.Method(typeof(InventorySlotsPlugin), prefix, (Type[])null, (Type[])null)); MethodInfo methodInfo2 = ((postfix == null) ? null : AccessTools.Method(typeof(InventorySlotsPlugin), postfix, (Type[])null, (Type[])null)); harmony.Patch((MethodBase)target, (methodInfo == null) ? ((HarmonyMethod)null) : new HarmonyMethod(methodInfo), (methodInfo2 == null) ? ((HarmonyMethod)null) : new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogDebug((object)((label ?? target.Name) + " compatibility patch applied.")); } } } private sealed class SmoothbrainBackpacksApi { private readonly MethodInfo _validateBackpackMethod; private readonly FieldInfo _visualsField; private readonly FieldInfo _equippedBackpackItemField; private readonly FieldInfo? _currentBackpackItemHashField; private readonly MethodInfo? _setBackpackItemMethod; private readonly MethodInfo? _forceSetBackpackEquippedMethod; private SmoothbrainBackpacksApi(MethodInfo validateBackpackMethod, FieldInfo visualsField, FieldInfo equippedBackpackItemField, FieldInfo? currentBackpackItemHashField, MethodInfo? setBackpackItemMethod, MethodInfo? forceSetBackpackEquippedMethod) { _validateBackpackMethod = validateBackpackMethod; _visualsField = visualsField; _equippedBackpackItemField = equippedBackpackItemField; _currentBackpackItemHashField = currentBackpackItemHashField; _setBackpackItemMethod = setBackpackItemMethod; _forceSetBackpackEquippedMethod = forceSetBackpackEquippedMethod; } public static bool TryCreate(Assembly assembly, out SmoothbrainBackpacksApi? api, out string detail) { api = null; Type? type = assembly.GetType("Backpacks.Backpacks"); Type type2 = assembly.GetType("Backpacks.Visual"); MethodInfo methodInfo = type?.GetMethod("validateBackpack", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[1] { typeof(ItemData) }, null); FieldInfo fieldInfo = type2?.GetField("visuals", BindingFlags.Static | BindingFlags.Public); FieldInfo fieldInfo2 = type2?.GetField("equippedBackpackItem", BindingFlags.Instance | BindingFlags.Public); if (methodInfo == null || fieldInfo == null || fieldInfo2 == null) { detail = "validateBackpack or Visual fields were not found"; return false; } api = new SmoothbrainBackpacksApi(methodInfo, fieldInfo, fieldInfo2, type2?.GetField("currentBackpackItemHash", BindingFlags.Instance | BindingFlags.Public), type2?.GetMethod("setBackpackItem", BindingFlags.Instance | BindingFlags.NonPublic), type2?.GetMethod("forceSetBackpackEquipped", BindingFlags.Instance | BindingFlags.Public)); detail = ""; return true; } public bool IsBackpack(ItemData? item) { if (item == null) { return false; } try { object obj = _validateBackpackMethod.Invoke(null, new object[1] { item }); return obj is bool && (bool)obj; } catch { return false; } } public void SyncEquippedBackpack(Player player, ItemData? item) { if ((Object)(object)player == (Object)null || IsUnityNull((Object?)(object)((Humanoid)player).m_visEquipment) || !TryGetVisual(((Humanoid)player).m_visEquipment, out object visual) || visual == null) { return; } try { string text = (((Object)(object)item?.m_dropPrefab != (Object)null) ? ((Object)item.m_dropPrefab).name : ""); int num = ((!string.IsNullOrWhiteSpace(text)) ? StringExtensionMethods.GetStableHashCode(text) : 0); if (_equippedBackpackItemField.GetValue(visual) != item) { _equippedBackpackItemField.SetValue(visual, item); } _setBackpackItemMethod?.Invoke(visual, new object[1] { text }); if (_forceSetBackpackEquippedMethod != null && GetCurrentHash(visual) != num) { _forceSetBackpackEquippedMethod.Invoke(visual, new object[1] { num }); } } catch (Exception ex) { Log.LogDebug((object)("Smoothbrain Backpacks visual sync failed: " + ex.Message)); } } private bool TryGetVisual(VisEquipment visEquipment, out object? visual) { visual = null; if (!(_visualsField.GetValue(null) is IDictionary dictionary) || !dictionary.Contains(visEquipment)) { return false; } visual = dictionary[visEquipment]; return visual != null; } private int GetCurrentHash(object visual) { try { return (_currentBackpackItemHashField?.GetValue(visual) is int num) ? num : 0; } catch { return 0; } } } private sealed class RustyBagsApi { private readonly MethodInfo _isBagMethod; private readonly MethodInfo _isQuiverMethod; private readonly Type _bagEquipmentType; private readonly Type _bagType; private readonly Type _quiverType; private readonly MethodInfo _getBagMethod; private readonly MethodInfo _getQuiverMethod; private readonly MethodInfo _setBagMethod; private readonly MethodInfo _setQuiverMethod; private RustyBagsApi(MethodInfo isBagMethod, MethodInfo isQuiverMethod, Type bagEquipmentType, Type bagType, Type quiverType, MethodInfo getBagMethod, MethodInfo getQuiverMethod, MethodInfo setBagMethod, MethodInfo setQuiverMethod) { _isBagMethod = isBagMethod; _isQuiverMethod = isQuiverMethod; _bagEquipmentType = bagEquipmentType; _bagType = bagType; _quiverType = quiverType; _getBagMethod = getBagMethod; _getQuiverMethod = getQuiverMethod; _setBagMethod = setBagMethod; _setQuiverMethod = setQuiverMethod; } public static bool TryCreate(Assembly assembly, out RustyBagsApi? api, out string detail) { api = null; Type type = assembly.GetType("RustyBags.API"); Type type2 = assembly.GetType("RustyBags.BagEquipment"); Type type3 = assembly.GetType("RustyBags.Bag"); Type type4 = assembly.GetType("RustyBags.Quiver"); MethodInfo methodInfo = type?.GetMethod("IsBag", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(string) }, null); MethodInfo methodInfo2 = type?.GetMethod("IsQuiver", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(string) }, null); MethodInfo methodInfo3 = type2?.GetMethod("GetBag", BindingFlags.Instance | BindingFlags.Public); MethodInfo methodInfo4 = type2?.GetMethod("GetQuiver", BindingFlags.Instance | BindingFlags.Public); MethodInfo methodInfo5 = type2?.GetMethod("SetBag", BindingFlags.Instance | BindingFlags.NonPublic); MethodInfo methodInfo6 = type2?.GetMethod("SetQuiver", BindingFlags.Instance | BindingFlags.Public); if (methodInfo == null || methodInfo2 == null || type2 == null || type3 == null || type4 == null || methodInfo3 == null || methodInfo4 == null || methodInfo5 == null || methodInfo6 == null) { detail = "RustyBags API or BagEquipment methods were not found"; return false; } api = new RustyBagsApi(methodInfo, methodInfo2, type2, type3, type4, methodInfo3, methodInfo4, methodInfo5, methodInfo6); detail = ""; return true; } public bool IsBag(ItemData? item) { if (item?.m_shared == null) { return false; } try { object obj = _isBagMethod.Invoke(null, new object[1] { item.m_shared.m_name }); return obj is bool && (bool)obj; } catch { return false; } } public bool IsQuiver(ItemData? item) { if (item?.m_shared == null) { return false; } try { object obj = _isQuiverMethod.Invoke(null, new object[1] { item.m_shared.m_name }); return obj is bool && (bool)obj; } catch { return false; } } public void SyncBag(Player player, ItemData? item) { if (item == null || _bagType.IsInstanceOfType(item)) { InvokeEquipmentSetter(player, _setBagMethod, item); } } public void SyncQuiver(Player player, ItemData? item) { if (item == null || _quiverType.IsInstanceOfType(item)) { InvokeEquipmentSetter(player, _setQuiverMethod, item); } } public void ClearBagIfCurrent(Player player, ItemData item) { object bagEquipment = GetBagEquipment(player); if (bagEquipment != null && _getBagMethod.Invoke(bagEquipment, Array.Empty<object>()) == item) { _setBagMethod.Invoke(bagEquipment, new object[1]); } } public void ClearQuiverIfCurrent(Player player, ItemData item) { object bagEquipment = GetBagEquipment(player); if (bagEquipment != null && _getQuiverMethod.Invoke(bagEquipment, Array.Empty<object>()) == item) { _setQuiverMethod.Invoke(bagEquipment, new object[1]); } } private void InvokeEquipmentSetter(Player player, MethodInfo setter, ItemData? item) { object bagEquipment = GetBagEquipment(player); if (bagEquipment == null) { return; } try { setter.Invoke(bagEquipment, new object[1] { item }); } catch (Exception ex) { Log.LogDebug((object)("RustyBags equipment sync failed: " + ex.Message)); } } private object? GetBagEquipment(Player player) { if ((Object)(object)player == (Object)null) { return null; } try { return ((Component)player).GetComponent(_bagEquipmentType); } catch { return null; } } } private sealed class BetterArcheryQuiverApi { private readonly FieldInfo _quiverEnabledField; private readonly FieldInfo _quiverRowIndexField; private ConfigEntry<bool>? _quiverEnabledConfig; private bool _quiverRowIndexResolved; private int _quiverRowIndex; private BetterArcheryQuiverApi(FieldInfo quiverEnabledField, FieldInfo quiverRowIndexField) { _quiverEnabledField = quiverEnabledField; _quiverRowIndexField = quiverRowIndexField; } public static bool TryCreate(Assembly assembly, out BetterArcheryQuiverApi? api, out string detail) { api = null; Type type = assembly.GetTypes().FirstOrDefault((Type candidate) => candidate.IsClass && candidate.Name == "BetterArchery"); if (type == null) { detail = "BetterArchery type was not found"; return false; } FieldInfo[] fields = type.GetFields(BindingFlags.Static | BindingFlags.Public); FieldInfo fieldInfo = fields.FirstOrDefault((FieldInfo field) => string.Equals(field.Name, "ConfigQuiverEnabled", StringComparison.OrdinalIgnoreCase)); FieldInfo fieldInfo2 = fields.FirstOrDefault((FieldInfo field) => string.Equals(field.Name, "QuiverRowIndex", StringComparison.OrdinalIgnoreCase)); if (fieldInfo == null || fieldInfo2 == null) { detail = "quiver config fields were not found"; return false; } api = new BetterArcheryQuiverApi(fieldInfo, fieldInfo2); detail = ""; return true; } public bool IsQuiverCell(Vector2i pos, bool includeRestockableSlots) { //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) try { if (_quiverEnabledConfig == null) { _quiverEnabledConfig = _quiverEnabledField.GetValue(null) as ConfigEntry<bool>; } } catch { _quiverEnabledConfig = null; } if (_quiverEnabledConfig == null || !_quiverEnabledConfig.Value) { return false; } if (!_quiverRowIndexResolved || _quiverRowIndex == 0) { try { _quiverRowIndex = ((_quiverRowIndexField.GetValue(null) is int num) ? num : 0); } catch { _quiverRowIndex = 0; } _quiverRowIndexResolved = _quiverRowIndex != 0; } if (_quiverRowIndex == 0) { return false; } if (pos.y == _quiverRowIndex - 1) { return true; } if (pos.y == _quiverRowIndex) { if (!includeRestockableSlots) { return pos.x > 2; } return true; } return false; } } private delegate bool CompatApiFactory<TApi>(Assembly assembly, out TApi? api, out string detail) where TApi : class; private enum CompatCapabilityState { Unknown, Unavailable, Available, MissingApi, Failed } private sealed class CompatApiRuntimeState<TApi> where TApi : class { public TApi? Api; public bool ReflectionFailed; public CompatCapabilityState CapabilityState; } private sealed class CompatRuntimeState { public bool MyLittleUICraftingCompatibilityApplied; public bool JewelcraftingSlotStateInitialized; public bool AdventureBackpacksPatchesApplied; public bool LastJewelcraftingRingSlotEnabled; public bool LastJewelcraftingNecklaceSlotEnabled; public ItemData? LastAdventureBackpackCompatItem; public ItemData? LastSmoothbrainBackpackCompatItem; public ItemData? LastRustyBagCompatItem; public ItemData? LastRustyQuiverCompatItem; public ItemData? LastMagicSupremacyBeltCompatItem; public readonly CompatApiRuntimeState<AzuCraftyBoxesApi> AzuCraftyBoxes = new CompatApiRuntimeState<AzuCraftyBoxesApi>(); public readonly CompatApiRuntimeState<JewelcraftingTooltipApi> JewelcraftingTooltip = new CompatApiRuntimeState<JewelcraftingTooltipApi>(); public readonly CompatApiRuntimeState<JewelcraftingGemApi> JewelcraftingGem = new CompatApiRuntimeState<JewelcraftingGemApi>(); public readonly CompatApiRuntimeState<JewelcraftingSlotApi> JewelcraftingSlot = new CompatApiRuntimeState<JewelcraftingSlotApi>(); public readonly CompatApiRuntimeState<JewelcraftingCraftingSocketUiApi> JewelcraftingCraftingSocketUi = new CompatApiRuntimeState<JewelcraftingCraftingSocketUiApi>(); public readonly CompatApiRuntimeState<JewelcraftingGemCuttingApi> JewelcraftingGemCutting = new CompatApiRuntimeState<JewelcraftingGemCuttingApi>(); public readonly CompatApiRuntimeState<JewelcraftingVisualApi> JewelcraftingVisual = new CompatApiRuntimeState<JewelcraftingVisualApi>(); public readonly CompatApiRuntimeState<ItemRequiresSkillLevelApi> ItemRequiresSkillLevel = new CompatApiRuntimeState<ItemRequiresSkillLevelApi>(); public readonly CompatApiRuntimeState<RecycleNReclaimApi> RecycleNReclaim = new CompatApiRuntimeState<RecycleNReclaimApi>(); public readonly CompatApiRuntimeState<AdventureBackpacksApi> AdventureBackpacks = new CompatApiRuntimeState<AdventureBackpacksApi>(); public readonly CompatApiRuntimeState<SmoothbrainBackpacksApi> SmoothbrainBackpacks = new CompatApiRuntimeState<SmoothbrainBackpacksApi>(); public readonly CompatApiRuntimeState<RustyBagsApi> RustyBags = new CompatApiRuntimeState<RustyBagsApi>(); public readonly CompatApiRuntimeState<MagicSupremacyApi> MagicSupremacy = new CompatApiRuntimeState<MagicSupremacyApi>(); public readonly CompatApiRuntimeState<BetterArcheryQuiverApi> BetterArcheryQuiver = new CompatApiRuntimeState<BetterArcheryQuiverApi>(); } private readonly struct SfxVolumeMemberCache { public FieldInfo[] Fields { get; } public PropertyInfo[] Properties { get; } public SfxVolumeMemberCache(FieldInfo[] fields, PropertyInfo[] properties) { Fields = fields; Properties = properties; } } private enum ContainerTakeStacksMode { CurrentContainerMatchingStacks, AreaFavoriteRestock } private sealed class ControllerActionOption { public ControllerHotkeyAction Action { get; } public string Label { get; } public ControllerActionOption(ControllerHotkeyAction action, string label) { Action = action; Label = label; } } private sealed class CustomEquipmentVisualState { public string SlotId { get; } public int ItemHash { get; } public int Variant { get; } public string PrefabName { get; } public ItemType ItemType { get; } public CustomEquipmentVisualState(string slotId, int itemHash, int variant, string prefabName, ItemType itemType) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) SlotId = slotId; ItemHash = itemHash; Variant = variant; PrefabName = prefabName; ItemType = itemType; } } private sealed class CustomEquipmentVisual { private readonly List<GameObject> _instances = new List<GameObject>(); public string Key { get; } public VisEquipment Owner { get; } public string PrefabName { get; } public int Variant { get; } public CustomEquipmentVisual(string key, VisEquipment owner, string prefabName, int variant) { Key = key; Owner = owner; PrefabName = prefabName; Variant = variant; } public bool Matches(VisEquipment owner, string prefabName, int variant) { if (!IsUnityNull((Object?)(object)Owner) && (Object)(object)Owner == (Object)(object)owner && string.Equals(PrefabName, prefabName, StringComparison.Ordinal)) { return Variant == variant; } return false; } public bool IsOwnedBy(VisEquipment owner) { if (!IsUnityNull((Object?)(object)Owner)) { return (Object)(object)Owner == (Object)(object)owner; } return false; } public void Add(GameObject? instance) { if (!IsUnityNull((Object?)(object)instance)) { _instances.Add(instance); } } public void AddRange(IEnumerable<GameObject>? instances) { if (instances == null) { return; } foreach (GameObject instance in instances) { Add(instance); } } public void AddActiveInstancesTo(List<GameObject> roots) { foreach (GameObject instance in _instances) { if (!IsUnityNull((Object?)(object)instance)) { roots.Add(instance); } } } public void Destroy() { foreach (GameObject instance in _instances) { if (!IsUnityNull((Object?)(object)instance)) { if (!IsUnityNull((Object?)(object)Owner) && !IsUnityNull((Object?)(object)Owner.m_lodGroup)) { Utils.RemoveFromLodgroup(Owner.m_lodGroup, instance); } Object.Destroy((Object)(object)instance); } } _instances.Clear(); } } private readonly struct CraftingRequirementAvailabilityCacheEntry { public int Amount { get; } public float ExpiresAt { get; } public CraftingRequirementAvailabilityCacheEntry(int amount, float expiresAt) { Amount = amount; ExpiresAt = expiresAt; } } private sealed class CraftingRequirementRuntimeState { public readonly Dictionary<string, CraftingRequirementAvailabilityCacheEntry> AvailabilityCache = new Dictionary<string, CraftingRequirementAvailabilityCacheEntry>(StringComparer.OrdinalIgnoreCase); public readonly List<Requirement> VisibleRequirements = new List<Requirement>(); public readonly List<Requirement> VisibleRequirementCandidates = new List<Requirement>(); public readonly List<RectTransform?> OwnedSlots = new List<RectTransform>(); public int AvailabilityVersion; } private sealed class CraftingRecipeRuntimeState { public readonly List<CraftingRecipeGridCell> GridCells = new List<CraftingRecipeGridCell>(); public readonly List<CraftingRecipeViewEntry> View = new List<CraftingRecipeViewEntry>(); public readonly Dictionary<int, int> ViewIndexByOriginal = new Dictionary<int, int>(); public readonly List<CraftingRecipeGroupPanel> GroupPanels = new List<CraftingRecipeGroupPanel>(); public readonly List<CraftingRecipeGroupButton> GroupButtons = new List<CraftingRecipeGroupButton>(); public readonly Dictionary<Recipe, int> Variants = new Dictionary<Recipe, int>(); public readonly Dictionary<CraftingRecipePairCacheKey, string> SearchTextCache = new Dictionary<CraftingRecipePairCacheKey, string>(); public readonly Dictionary<string, CraftingHoverTooltipContent> HoverTooltipContentCache = new Dictionary<string, CraftingHoverTooltipContent>(StringComparer.Ordinal); public readonly List<JewelcraftingGemIconData> HoverGemIconCache = new List<JewelcraftingGemIconData>(); public readonly Dictionary<string, string> EnglishLocalizationCache = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); public readonly Dictionary<string, string> EnglishLocalizationIndex = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); public readonly Dictionary<CraftingRecipePairCacheKey, SortKey> SortKeyCache = new Dictionary<CraftingRecipePairCacheKey, SortKey>(); public readonly Dictionary<CraftingRecipePairCacheKey, Dictionary<string, bool>> GroupMatchCache = new Dictionary<CraftingRecipePairCacheKey, Dictionary<string, bool>>(); public readonly List<CraftingRecipeGroupFilter> SelectableGroupFilterCache = new List<CraftingRecipeGroupFilter>(); public readonly Dictionary<string, bool> GroupHasRecipesCache = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase); } private sealed class CraftingGridRuntimeState { public RectTransform? RecipeGrid; public bool RecipeGridDirty = true; public int RecipePage; public string RecipeGridSignature = ""; public string RecipeGridLayoutSignature = ""; public int RecipeGridCellCapacity = -1; } private sealed class CraftingScrollbarRuntimeState { public RectTransform? RecipeScrollbar; public Scrollbar? RecipeScrollbarComponent; public bool UpdatingRecipeScrollbar; public bool RecipeScrollbarDirty = true; public string RecipeScrollbarSignature = ""; } private sealed class CraftingQueueRuntimeState { public bool ContinuingQueue; public int QueueTotal; public int QueueRemaining; public int QueueVariant; public int ProgressLabelCount; public int ProgressLabelVariant; public Recipe? QueueRecipe; public Recipe? ProgressLabelRecipe; } private sealed class CraftingUiRuntimeState { public GameObject? HoverTooltip; public RectTransform? HoverTooltipPanel; public TMP_Text? HoverTooltipTopic; public TMP_Text? HoverTooltipText; public readonly ScrollableTooltipBodyState HoverTooltipTextScroll = new ScrollableTooltipBodyState(); public RectTransform? TooltipRecipeOverlay; public RectTransform? TooltipExpandedPanel; public RectTransform? TooltipGemIconRow; public TMP_InputField? SearchInput; public RectTransform? SearchInputRect; public RectTransform? RecipeGridZoomHint; public TMP_Text? RecipeGridZoomHintText; public bool SearchInputDirty = true; public int HoveredRecipeIndex = -1; public string SearchInputSignature = ""; public string RecipeGridZoomHintSignature = ""; public string HoverTooltipSignature = ""; public string HoverTooltipContentKey = ""; public string HoverTooltipLayoutSignature = ""; public string HoverTooltipVisualSignature = ""; public string HoverGemIconSignature = ""; public float HoverTooltipScrollOffset; public float HoverTooltipMaxScroll; } private static class CraftingController { public static int HoveredRecipeIndex => CraftingUi.HoveredRecipeIndex; public static bool NeedsModelRefresh(CraftingPanelUpdateReason reason, bool firstApply) { if (!firstApply && reason == CraftingPanelUpdateReason.FrameTick && !_craftingRecipeViewDirty && !_craftingRecipeGridDirty && !_craftingRecipeScrollbarDirty) { return _craftingGroupRailDirty; } return true; } public static void MarkRecipeViewDirty() { _craftingRecipeViewDirty = true; _craftingRecipeViewSignature = ""; } public static void MarkRecipeGridDirty() { _craftingRecipeGridDirty = true; _craftingRecipeGridSignature = ""; } public static void MarkRecipeScrollbarDirty() { _craftingRecipeScrollbarDirty = true; _craftingRecipeScrollbarSignature = ""; } public static void MarkGroupRailDirty() { _craftingGroupRailDirty = true; _craftingGroupRailSignature = ""; } public static void MarkBottomControlsDirty() { _craftingBottomControlsDirty = true; _craftingBottomControlsSignature = ""; } public static void MarkSearchInputDirty() { CraftingUi.SearchInputDirty = true; CraftingUi.SearchInputSignature = ""; } public static void MarkRecipeViewDirtyCascade() { MarkRecipeViewDirty(); MarkRecipeGridDirty(); MarkRecipeScrollbarDirty(); MarkGroupRailDirty(); MarkBottomControlsDirty(); } public static void MarkRecipeGridLayoutDirty() { MarkRecipeGridDirty(); MarkRecipeScrollbarDirty(); MarkBottomControlsDirty(); } public static void SetHoveredRecipe(int index) { CraftingUi.HoveredRecipeIndex = index; } public static void ClearHoveredRecipe() { CraftingUi.HoveredRecipeIndex = -1; } public static bool IsHoveredRecipe(int index) { return CraftingUi.HoveredRecipeIndex == index; } public static void InvalidateRecipeGridZoomHint() { CraftingUi.RecipeGridZoomHintSignature = ""; } public static void ClearHoverTooltipContentKey() { CraftingUi.HoverTooltipContentKey = ""; } } private sealed class CraftingTooltipNativePanelLayoutState : MonoBehaviour { public float AppliedOffsetMinYDelta; } internal sealed class KeepOnDeathItemState { public ItemData Item { get; } public Vector2i OriginalGridPos { get; } public string OriginalSlotId { get; } public SlotKind? OriginalSlotKind { get; } public bool WasQuickSlot => OriginalSlotKind.GetValueOrDefault() == SlotKind.Quick; public bool WasSpecialSlot => OriginalSlotKind.HasValue; public KeepOnDeathItemState(ItemData item, Vector2i originalGridPos, string originalSlotId, SlotKind? originalSlotKind) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) Item = item; OriginalGridPos = originalGridPos; OriginalSlotId = originalSlotId; OriginalSlotKind = originalSlotKind; } } private sealed class ItemClassification { public readonly Dictionary<string, bool> BuiltInGroupMatches = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase); public bool BigGroupResolved; public string BigGroupId = ""; } private sealed class ItemClassifierRuntimeState { public readonly Dictionary<string, ItemClassification> Cache = new Dictionary<string, ItemClassification>(StringComparer.OrdinalIgnoreCase); public string Signature = ""; } private enum FoodStat { None, Health, Stamina, Eitr } private static class ItemClassifierController { public static string GetInventoryItemBigGroupId(ItemClassifierRuntimeState state, ItemData item, IReadOnlyList<CraftingRecipeGroupFilter> groupFilters) { if (item?.m_shared == null) { return ""; } ItemClassification itemClassification = GetItemClassification(state, item); if (itemClassification.BigGroupResolved) { return itemClassification.BigGroupId; } for (int i = 0; i < groupFilters.Count; i++) { CraftingRecipeGroupFilter craftingRecipeGroupFilter = groupFilters[i]; if (craftingRecipeGroupFilter.Id != "favorite" && craftingRecipeGroupFilter.Matches(item)) { itemClassification.BigGroupId = craftingRecipeGroupFilter.Id; itemClassification.BigGroupResolved = true; return itemClassification.BigGroupId; } } itemClassification.BigGroupId = ""; itemClassification.BigGroupResolved = true; return itemClassification.BigGroupId; } public static bool ItemMatchesBuiltInPredefinedGroup(ItemClassifierRuntimeState state, ItemData item, string groupId) { string text = NormalizeGroupId(groupId); if (item?.m_shared == null || string.IsNullOrWhiteSpace(text)) { return false; } ItemClassification itemClassification = GetItemClassification(state, item); if (itemClassification.BuiltInGroupMatches.TryGetValue(text, out var value)) { return value; } bool flag = ItemMatchesBuiltInPredefinedGroupUncached(item, text); itemClassification.BuiltInGroupMatches[text] = flag; return flag; } public static void ClearCaches(ItemClassifierRuntimeState state) { state.Cache.Clear(); state.Signature = ""; } private static ItemClassification GetItemClassification(ItemClassifierRuntimeState state, ItemData item) { EnsureCacheFresh(state); string itemClassifierCacheKey = GetItemClassifierCacheKey(item); if (state.Cache.TryGetValue(itemClassifierCacheKey, out ItemClassification value)) { return value; } if (state.Cache.Count >= 2048) { state.Cache.Clear(); } ItemClassification itemClassification = new ItemClassification(); state.Cache[itemClassifierCacheKey] = itemClassification; return itemClassification; } private static void EnsureCacheFresh(ItemClassifierRuntimeState state) { string itemClassifierCacheSignature = GetItemClassifierCacheSignature(); if (!string.Equals(state.Signature, itemClassifierCacheSignature, StringComparison.Ordinal)) { state.Cache.Clear(); state.Signature = itemClassifierCacheSignature; } } } private static class ItemSortController { public static void EnsureRecipeOutputLookupCache(InventorySortRuntimeState state) { string recipeOutputLookupSignature = GetRecipeOutputLookupSignature(); if (string.Equals(state.RecipeOutputLookupSignature, recipeOutputLookupSignature, StringComparison.Ordinal)) { return; } state.RecipeOutputLookupCache.Clear(); state.RecipeOutputLookupSignature = recipeOutputLookupSignature; if (ObjectDB.instance?.m_recipes == null) { return; } foreach (Recipe recipe in ObjectDB.instance.m_recipes) { AddRecipeOutputLookup(recipe); } } public static void ClearCaches(InventorySortRuntimeState state) { state.RecipeOutputLookupCache.Clear(); state.RecipeOutputLookupSignature = ""; } } private sealed class JewelcraftingCraftingSocketUiApi { private readonly FieldInfo _socketIconsField; private readonly FieldInfo? _socketingButtonField; private readonly FieldInfo? _socketTabField; private readonly FieldInfo? _socketCostField; private readonly MethodInfo? _socketTabOpenMethod; private JewelcraftingCraftingSocketUiApi(FieldInfo socketIconsField, FieldInfo? socketingButtonField, FieldInfo? socketTabField, FieldInfo? socketCostField, MethodInfo? socketTabOpenMethod) { _socketIconsField = socketIconsField; _socketingButtonField = socketingButtonField; _socketTabField = socketTabField; _socketCostField = socketCostField; _socketTabOpenMethod = socketTabOpenMethod; } public static bool TryCreate(Assembly assembly, out JewelcraftingCraftingSocketUiApi? api, out string detail) { api = null; Type type = assembly.GetType("Jewelcrafting.GemStones+AddSocketIcons"); Type type2 = assembly.GetType("Jewelcrafting.GemStones+AddSocketAddingTab"); Type type3 = assembly.GetType("Jewelcrafting.Jewelcrafting"); FieldInfo fieldInfo = type?.GetField("socketIcons", BindingFlags.Static | BindingFlags.Public); if (fieldInfo == null) { detail = "AddSocketIcons.socketIcons was not found"; return false; } api = new JewelcraftingCraftingSocketUiApi(fieldInfo, type?.GetField("socketingButton", BindingFlags.Static | BindingFlags.Public), type2?.GetField("tab", BindingFlags.Static | BindingFlags.Public), type3?.GetField("socketCost", BindingFlags.Static | BindingFlags.Public), type2?.GetMethod("TabOpen", BindingFlags.Static | BindingFlags.Public)); detail = ""; return true; } public Array? GetSocketIcons() { return _socketIconsField.GetValue(null) as Array; } public Button? GetSocketingButton() { object? obj = _socketingButtonField?.GetValue(null); return (Button?)((obj is Button) ? obj : null); } public Transform? GetSocketTab() { object? obj = _socketTabField?.GetValue(null); return (Transform?)((obj is Transform) ? obj : null); } public string GetSocketCostMode() { try { object? obj = _socketCostField?.GetValue(null); ConfigEntryBase val = (ConfigEntryBase)((obj is ConfigEntryBase) ? obj : null); return (val == null) ? "" : (val.BoxedValue?.ToString() ?? ""); } catch { return ""; } } public bool IsSocketTabOpen() { try { object obj = _socketTabOpenMethod?.Invoke(null, null); return obj is bool && (bool)obj; } catch { return false; } } } private enum JewelcraftingSocketTabState { Unavailable, PrimaryCraftingTab, Closed, Selected } private sealed class JewelcraftingGemCuttingApi { private readonly FieldInfo _gemUpgradeChancesField; private JewelcraftingGemCuttingApi(FieldInfo gemUpgradeChancesField) { _gemUpgradeChancesField = gemUpgradeChancesField; } public static bool TryCreate(Assembly assembly, out JewelcraftingGemCuttingApi? api, out string detail) { api = null; FieldInfo fieldInfo = assembly.GetType("Jewelcrafting.Jewelcrafting")?.GetField("gemUpgradeChances", BindingFlags.Static | BindingFlags.Public); if (fieldInfo == null) { detail = "Jewelcrafting.gemUpgradeChances was not found"; return false; } api = new JewelcraftingGemCuttingApi(fieldInfo); detail = ""; return true; } public bool IsGemCuttingRecipe(Recipe recipe) { string text = (((Object)(object)recipe.m_item != (Object)null) ? (recipe.m_item.m_itemData.m_shared.m_name ?? "") : ""); if (string.IsNullOrWhiteSpace(text)) { return false; } try { return _gemUpgradeChancesField.GetValue(null) is IDictionary dictionary && dictionary.Contains(text); } catch { return false; } } } private sealed class JewelcraftingGemApi { private readonly MethodInfo _getGemsMethod; private readonly MethodInfo? _itemDataMethod; private readonly MethodInfo? _itemInfoGetSocketableMethod; private readonly FieldInfo? _socketedGemsField; private readonly FieldInfo? _socketNameField; private readonly FieldInfo? _socketSeedField; private readonly FieldInfo? _effectPowersField; private readonly FieldInfo? _effectNamesField; private readonly MethodInfo? _getGemLocationMethod; private readonly MethodInfo? _getItemGemLocationMethod; private readonly MethodInfo? _displayGemEffectPowerMethod; private readonly FieldInfo? _openEquipmentField; private readonly FieldInfo? _openInventoryField; private readonly PropertyInfo? _itemInfoItemDataProperty; private readonly MethodInfo? _itemInfoGetAllSocketSeedsMethod; private readonly PropertyInfo? _socketSeedSeedProperty; private readonly Dictionary<Type, MemberInfo?> _gemSpriteMembers = new Dictionary<Type, MemberInfo>(); private readonly Dictionary<Type, MemberInfo?> _gemPrefabMembers = new Dictionary<Type, MemberInfo>(); private readonly Dictionary<Type, MemberInfo?> _gemEffectsMembers = new Dictionary<Type, MemberInfo>(); private JewelcraftingGemApi(MethodInfo getGemsMethod, MethodInfo? itemDataMethod, MethodInfo? itemInfoGetSocketableMethod, FieldInfo? socketedGemsField, FieldInfo? socketNameField, FieldInfo? socketSeedField, FieldInfo? effectPowersField, FieldInfo? effectNamesField, MethodInfo? getGemLocationMethod, MethodInfo? getItemGemLocationMethod, MethodInfo? displayGemEffectPowerMethod, FieldInfo? openEquipmentField, FieldInfo? openInventoryField, PropertyInfo? itemInfoItemDataProperty, MethodInfo? itemInfoGetAllSocketSeedsMethod, PropertyInfo? socketSeedSeedProperty) { _getGemsMethod = getGemsMethod; _itemDataMethod = itemDataMethod; _itemInfoGetSocketableMethod = itemInfoGetSocketableMethod; _socketedGemsField = socketedGemsField; _socketNameField = socketNameField; _socketSeedField = socketSeedField; _effectPowersField = effectPowersField; _effectNamesField = effectNamesField; _getGemLocationMethod = getGemLocationMethod; _getItemGemLocationMethod = getItemGemLocationMethod; _displayGemEffectPowerMethod = displayGemEffectPowerMethod; _openEquipmentField = openEquipmentField; _openInventoryField = openInventoryField; _itemInfoItemDataProperty = itemInfoItemDataProperty; _itemInfoGetAllSocketSeedsMethod = itemInfoGetAllSocketSeedsMethod; _socketSeedSeedProperty = socketSeedSeedProperty; } public static bool TryCreate(Assembly assembly, out JewelcraftingGemApi? api, out string detail) { api = null; MethodInfo methodInfo = assembly.GetType("Jewelcrafting.API")?.GetMethod("GetGems", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(ItemData) }, null); if (methodInfo == null) { detail = "API.GetGems was not found"; return false; } Type? type = assembly.GetType("ItemDataManager.ItemExtensions"); Type type2 = assembly.GetType("ItemDataManager.ItemInfo"); Type type3 = assembly.GetType("Jewelcrafting.Socketable"); Type type4 = assembly.GetType("Jewelcrafting.SocketItem"); Type type5 = assembly.GetType("Jewelcrafting.Jewelcrafting"); Type type6 = assembly.GetType("Jewelcrafting.GemEffects.EffectDef"); Type type7 = assembly.GetType("Jewelcrafting.Utils"); Type type8 = assembly.GetType("Jewelcrafting.GemEffects.EffectPower"); Type type9 = assembly.GetType("Jewelcrafting.GemStones+AddFakeSocketsContainer"); Type type10 = assembly.GetType("Jewelcrafting.SocketSeed"); MethodInfo itemDataMethod = type?.GetMethod("Data", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(ItemData) }, null); MethodInfo itemInfoGetAllSocketSeedsMethod = null; MethodInfo itemInfoGetSocketableMethod = null; if (type2 != null) { MethodInfo[] methods = type2.GetMethods(BindingFlags.Instance | BindingFlags.Public); foreach (MethodInfo methodInfo2 in methods) { if (type3 != null && methodInfo2.Name == "Get" && methodInfo2.IsGenericMethodDefinition && methodInfo2.GetParameters().Length == 1) { itemInfoGetSocketableMethod = methodInfo2.MakeGenericMethod(type3); } else if (type10 != null && methodInfo2.Name == "GetAll" && methodInfo2.IsGenericMethodDefinition && methodInfo2.GetParameters().Length == 0) { itemInfoGetAllSocketSeedsMethod = methodInfo2.MakeGenericMethod(type10); } } } MethodInfo displayGemEffectPowerMethod = null; if (type7 != null && type8 != null) { MethodInfo[] methods = type7.GetMethods(BindingFlags.Static | BindingFlags.Public); foreach (MethodInfo methodInfo3 in methods) { if (methodInfo3.Name == "DisplayGemEffectPower" && methodInfo3.GetParameters().Length == 5) { displayGemEffectPowerMethod = methodInfo3; break; } } } api = new JewelcraftingGemApi(methodInfo, itemDataMethod, itemInfoGetSocketableMethod, type3?.GetField("socketedGems", BindingFlags.Instance | BindingFlags.Public), type4?.GetField("Name", BindingFlags.Instance | BindingFlags.Public), type4?.GetField("Seed", BindingFlags.Instance | BindingFlags.Public), type5?.GetField("EffectPowers", BindingFlags.Static | BindingFlags.Public), type6?.GetField("EffectNames", BindingFlags.Static | BindingFlags.Public), type7?.GetMethod("GetGemLocation", BindingFlags.Static | BindingFlags.Public, null, new Type[2] { typeof(SharedData), typeof(Player) }, null), type7?.GetMethod("GetItemGemLocation", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(ItemData) }, null), displayGemEffectPowerMethod, type9?.GetField("openEquipment", BindingFlags.Static | BindingFlags.Public), type9?.GetField("openInventory", BindingFlags.Static | BindingFlags.Public), type2?.GetProperty("ItemData", BindingFlags.Instance | BindingFlags.Public), itemInfoGetAllSocketSeedsMethod, type10?.GetProperty("Seed", BindingFlags.Instance | BindingFlags.Public)); detail = ""; return true; } public object? GetGems(ItemData item) { return _getGemsMethod.Invoke(null, new object[1] { item }); } public ItemData? GetOpenSocketContainerItem() { if (_openEquipmentField == null || _itemInfoItemDataProperty == null) { return null; } try { object value = _openEquipmentField.GetValue(null); return (ItemData?)((value != null) ? /*isinst with value type is only supported in some contexts*/: null); } catch { return null; } } public Inventory? GetOpenSocketContainerInventory() { if (_openInventoryField == null) { return null; } try { object? value = _openInventoryField.GetValue(null); return (Inventory?)((value is Inventory) ? value : null); } catch { return null; } } public bool TryGetGemIconData(object gem, out Sprite? sprite, out string prefabName) { sprite = null; prefabName = ""; if (gem == null) { return false; } Type type = gem.GetType(); if (!_gemSpriteMembers.TryGetValue(type, out MemberInfo value)) { value = FindGemMember(type, typeof(Sprite), "gemSprite", "GemSprite", "sprite", "Sprite", "icon", "Icon", "gemIcon", "GemIcon"); _gemSpriteMembers[type] = value; } if (!_gemPrefabMembers.TryGetValue(type, out MemberInfo value2)) { value2 = FindGemMember(type, null, "gemPrefab", "GemPrefab", "prefab", "Prefab", "prefabName", "PrefabName", "name", "Name"); _gemPrefabMembers[type] = value2; } object? gemMemberValue = GetGemMemberValue(value, gem); sprite = (Sprite?)((gemMemberValue is Sprite) ? gemMemberValue : null); object gemMemberValue2 = GetGemMemberValue(value2, gem); object obj = gemMemberValue2; string text2; if (!(obj is string text)) { GameObject val = (GameObject)((obj is GameObject) ? obj : null); if (val == null) { ItemDrop val2 = (ItemDrop)((obj is ItemDrop) ? obj : null); if (val2 == null || !((Object)(object)val2 != (Object)null) || IsUnityNull((Object?)(object)val2)) { goto IL_017e; } text2 = ((Object)((Component)val2).gameObject).name; } else { if (!((Object)(object)val != (Object)null) || IsUnityNull((Object?)(object)val)) { goto IL_017e; } text2 = ((Object)val).name; } } else { text2 = text; } goto IL_0195; IL_0195: prefabName = text2; if (!((Object)(object)sprite != (Object)null)) { return !string.IsNullOrWhiteSpace(prefabName); } return true; IL_017e: text2 = gemMemberValue2?.ToString() ?? ""; goto IL_0195; } public bool TryGetGemTooltipData(object gem, out Sprite? sprite, out string prefabName, out List<KeyValuePair<string, float>> effects) { effects = new List<KeyValuePair<string, float>>(); if (!TryGetGemIconData(gem, out sprite, out prefabName) && string.IsNullOrWhiteSpace(prefabName)) { return false; } Type type = gem.GetType(); if (!_gemEffectsMembers.TryGetValue(type, out MemberInfo value)) { value = FindGemMember(type, typeof(IDictionary), "gemEffects", "GemEffects", "effects", "Effects"); _gemEffectsMembers[type] = value; } if (!(GetGemMemberValue(value, gem) is IDictionary dictionary)) { return true; } foreach (DictionaryEntry item in dictionary) { string text = item.Key?.ToString() ?? ""; if (string.IsNullOrWhiteSpace(text)) { continue; } float result; if (item.Value is float value2) { effects.Add(new KeyValuePair<string, float>(text, value2)); } else if (item.Value is IConvertible convertible) { try { effects.Add(new KeyValuePair<string, float>(text, convertible.ToSingle(CultureInfo.InvariantCulture))); } catch { } } else if (item.Value != null && float.TryParse(item.Value.ToString(), NumberStyles.Float, CultureInfo.InvariantCulture, out result)) { effects.Add(new KeyValuePair<string, float>(text, result)); } } return true; } public List<JewelcraftingSocketGemData> GetSocketGemData(ItemData item) { List<JewelcraftingSocketGemData> list = new List<JewelcraftingSocketGemData>(); if (_itemDataMethod == null || _itemInfoGetSocketableMethod == null || _socketedGemsField == null || _socketNameField == null) { return list; } try { object obj = _itemDataMethod.Invoke(null, new object[1] { item }); object obj2 = ((obj != null) ? _itemInfoGetSocketableMethod.Invoke(obj, new object[1] { "" }) : null); if (obj2 == null || !(_socketedGemsField.GetValue(obj2) is IEnumerable enumerable)) { return list; } foreach (object item2 in enumerable) { if (item2 == null) { list.Add(new JewelcraftingSocketGemData("", null)); continue; } string prefabName = (_socketNameField.GetValue(item2) as string) ?? ""; Dictionary<string, uint> seeds = CopySocketSeeds(_socketSeedField?.GetValue(item2)); list.Add(new JewelcraftingSocketGemData(prefabName, seeds)); } } catch (Exception ex) { Log.LogDebug((object)("Jewelcrafting direct socket read failed for " + GetItemPrefabName(item) + ": " + ex.Message)); } return list; } public List<JewelcraftingSocketGemData> GetOpenSocketGemData(ItemData item) { List<JewelcraftingSocketGemData> list = new List<JewelcraftingSocketGemData>(); ItemData openSocketContainerItem = GetOpenSocketContainerItem(); Inventory openSocketContainerInventory = GetOpenSocketContainerInventory(); if (openSocketContainerItem?.m_shared == null || openSocketContainerInventory == null || !IsSameOpenSocketContainerItem(item, openSocketContainerItem)) { return list; } int num = Math.Max(1, openSocketContainerInventory.m_width); int num2 = Math.Max(0, num * Math.Max(0, openSocketContainerInventory.m_height)); for (int i = 0; i < num2; i++) { list.Add(new JewelcraftingSocketGemData("", null)); } foreach (ItemData item2 in openSocketContainerInventory.m_inventory) { if (item2?.m_shared != null) { int num3 = item2.m_gridPos.x + item2.m_gridPos.y * num; if (num3 >= 0 && num3 < list.Count) { string prefabName = (((Object)(object)item2.m_dropPrefab != (Object)null && !IsUnityNull((Object?)(object)item2.m_dropPrefab)) ? ((Object)item2.m_dropPrefab).name : GetItemPrefabName(item2)); list[num3] = new JewelcraftingSocketGemData(prefabName, GetSocketSeedData(item2)); } } } return list; } public string GetSocketDebugSummary(ItemData item) { List<JewelcraftingSocketGemData> socketGemData = GetSocketGemData(item); List<string> list = new List<string>(); foreach (JewelcraftingSocketGemData item2 in socketGemData) { list.Add(string.IsNullOrWhiteSpace(item2.PrefabName) ? "<empty>" : item2.PrefabName); } return "directSockets=" + socketGemData.Count + ", directNames=" + string.Join("/", list); } public string GetOpenSocketDebugSummary(ItemData item) { List<JewelcraftingSocketGemData> openSocketGemData = GetOpenSocketGemData(item); List<string> list = new List<string>(); foreach (JewelcraftingSocketGemData item2 in openSocketGemData) { list.Add(string.IsNullOrWhiteSpace(item2.PrefabName) ? "<empty>" : item2.PrefabName); } return "openSockets=" + openSocketGemData.Count + ", openNames=" + string.Join("/", list); } public string BuildSocketEffectText(ItemData item, JewelcraftingSocketGemData socket) { if (!socket.HasGem || _effectPowersField == null || _effectNamesField == null || _getGemLocationMethod == null || _getItemGemLocationMethod == null || _displayGemEffectPowerMethod == null || !(_effectPowersField.GetValue(null) is IDictionary dictionary) || !(_effectNamesField.GetValue(null) is IDictionary dictionary2)) { return ""; } object location = _getGemLocationMethod.Invoke(null, new object[2] { item.m_shared, Player.m_localPlayer }); object location2 = _getItemGemLocationMethod.Invoke(null, new object[1] { item }); List<object> list = new List<object>(); int stableHashCode = StringExtensionMethods.GetStableHashCode(socket.PrefabName); if (dictionary.Contains(stableHashCode) && dictionary[stableHashCode] is IDictionary locationPowers) { AddLocationPowers(locationPowers, location, list); AddLocationPowers(locationPowers, location2, list); } if (list.Count == 0) { return "$jc_effect_no_effect"; } List<string> list2 = new List<string>(); foreach (object item2 in list) { object obj = item2.GetType().GetField("Effect", BindingFlags.Instance | BindingFlags.Public)?.GetValue(item2); string text = ((obj == null || !dictionary2.Contains(obj)) ? (obj?.ToString() ?? "") : (dictionary2[obj]?.ToString() ?? obj.ToString() ?? "")); string text2 = ""; try { text2 = (_displayGemEffectPowerMethod.Invoke(null, new object[5] { item2, null, 0, socket.Seeds, false }) as string) ?? ""; } catch { } if (!string.IsNullOrWhiteSpace(text)) { list2.Add("$jc_effect_" + text.ToLowerInvariant() + (string.IsNullOrWhiteSpace(text2) ? "" : (" " + text2))); } } return string.Join("\n", list2); } private static void AddLocationPowers(IDictionary locationPowers, object? location, List<object> powers) { if (location == null || !locationPowers.Contains(location) || !(locationPowers[location] is IEnumerable enumerable)) { return; } foreach (object item in enumerable) { if (item != null) { powers.Add(item); } } } private static Dictionary<string, uint>? CopySocketSeeds(object? seedObject) { if (!(seedObject is IDictionary dictionary) || dictionary.Count == 0) { return null; } Dictionary<string, uint> dictionary2 = new Dictionary<string, uint>(); foreach (DictionaryEntry item in dictionary) { string text = item.Key?.ToString() ?? ""; if (!string.IsNullOrWhiteSpace(text)) { uint result; if (item.Value is uint value) { dictionary2[text] = value; } else if (item.Value != null && uint.TryParse(item.Value.ToString(), NumberStyles.Integer, CultureInfo.InvariantCulture, out result)) { dictionary2[text] = result; } } } if (dictionary2.Count <= 0) { return null; } return dictionary2; } private Dictionary<string, uint>? GetSocketSeedData(ItemData gem) { if (_itemDataMethod == null || _itemInfoGetAllSocketSeedsMethod == null || _socketSeedSeedProperty == null) { return null; } try { object obj = _itemDataMethod.Invoke(null, new object[1] { gem }); if (!(((obj != null) ? _itemInfoGetAllSocketSeedsMethod.Invoke(obj, null) : null) is IDictionary dictionary) || dictionary.Count == 0) { return null; } Dictionary<string, uint> dictionary2 = new Dictionary<string, uint>(); foreach (DictionaryEntry item in dictionary) { string text = item.Key?.ToString() ?? ""; if (!string.IsNullOrWhiteSpace(text) && item.Value != null) { object value = _socketSeedSeedProperty.GetValue(item.Value); uint result; if (value is uint value2) { dictionary2[text] = value2; } else if (value != null && uint.TryParse(value.ToString(), NumberStyles.Integer, CultureInfo.InvariantCulture, out result)) { dictionary2[text] = result; } } } return (dictionary2.Count > 0) ? dictionary2 : null; } catch { return null; } } private static bool IsSameOpenSocketContainerItem(ItemData item, ItemData openItem) { if (item == openItem) { return true; } if (item.m_shared != null && openItem.m_shared != null && string.Equals(GetItemPrefabName(item), GetItemPrefabName(openItem), StringComparison.Ordinal) && string.Equals(item.m_shared.m_name, openItem.m_shared.m_name, StringComparison.Ordinal) && item.m_variant == openItem.m_variant && item.m_quality == openItem.m_quality && item.m_gridPos.x == openItem.m_gridPos.x) { return item.m_gridPos.y == openItem.m_gridPos.y; } return false; } public string GetGemDebugSummary(object gem) { if (gem == null) { return "null"; } Type type = gem.GetType(); List<string> list = new List<string> { type.FullName ?? type.Name }; MemberInfo[] members = type.GetMembers(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MemberInfo memberInfo in members) { if (!(memberInfo is FieldInfo) && !(memberInfo is PropertyInfo)) { continue; } object gemMemberValue = GetGemMemberValue(memberInfo, gem); string text; if (gemMemberValue != null) { Sprite val = (Sprite)((gemMemberValue is Sprite) ? gemMemberValue : null); if (val == null) { GameObject val2 = (GameObject)((gemMemberValue is GameObject) ? gemMemberValue : null); text = ((val2 != null) ? ("GameObject:" + ((Object)val2).name) : ((!(gemMemberValue is IDictionary dictionary)) ? (gemMemberValue.ToString() ?? "") : ("Dictionary:" + dictionary.Count))); } else { text = "Sprite:" + ((Object)val).name; } } else { text = "null"; } string text2 = text; if (text2.Length > 80) { text2 = text2.Substring(0, 80) + "..."; } list.Add(memberInfo.Name + "=" + text2); if (list.Count >= 8) { break; } } return string.Join(";", list); } private static MemberInfo? FindGemMember(Type type, Type? targetType, params string[] names) { foreach (string name in names) { FieldInfo field = type.GetField(name, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && (targetType == null || targetType.IsAssignableFrom(field.FieldType) || (targetType == typeof(IDictionary) && typeof(IDictionary).IsAssignableFrom(field.FieldType)))) { return field; } PropertyInfo property = type.GetProperty(name, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if ((object)property != null && property.GetIndexParameters().Length == 0 && (targetType == null || targetType.IsAssignableFrom(property.PropertyType) || (targetType == typeof(IDictionary) && typeof(IDictionary).IsAssignableFrom(property.PropertyType)))) { return property; } } FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { if (targetType != null && (targetType.IsAssignableFrom(fieldInfo.FieldType) || (targetType == typeof(IDictionary) && typeof(IDictionary).IsAssignableFrom(fieldInfo.FieldType)))) { return fieldInfo; } } return null; } private static object? GetGemMemberValue(MemberInfo? member, object instance) { try { return (member is FieldInfo fieldInfo) ? fieldInfo.GetValue(instance) : ((!(member is PropertyInfo propertyInfo) || !propertyInfo.CanRead || propertyInfo.GetIndexParameters().Length != 0) ? null : propertyInfo.GetValue(instance)); } catch { return null; } } } private readonly struct JewelcraftingGemIconData { public readonly Sprite Sprite; public readonly string DisplayName; public JewelcraftingGemIconData(Sprite sprite, string displayName) { Sprite = sprite; DisplayName = displayName; } } private readonly struct JewelcraftingSocketGemData { public readonly string PrefabName; public readonly Dictionary<string, uint>? Seeds; public bool HasGem => !string.IsNullOrWhiteSpace(PrefabName); public JewelcraftingSocketGemData(string prefabName, Dictionary<string, uint>? seeds) { PrefabName = prefabName ?? ""; Seeds = seeds; } } private sealed class JewelcraftingSlotApi { private readonly FieldInfo _ringSlotField; private readonly FieldInfo _necklaceSlotField; private readonly MethodInfo? _isJewelryEquippedMethod; private ConfigEntryBase? _ringSlotConfig; private ConfigEntryBase? _necklaceSlotConfig; private JewelcraftingSlotApi(FieldInfo ringSlotField, FieldInfo necklaceSlotField, MethodInfo? isJewelryEquippedMethod) { _ringSlotField = ringSlotField; _necklaceSlotField = necklaceSlotField; _isJewelryEquippedMethod = isJewelryEquippedMethod; } public static bool TryCreate(Assembly assembly, out JewelcraftingSlotApi? api, out string detail) { api = null; Type? type = assembly.GetType("Jewelcrafting.Jewelcrafting"); Type type2 = assembly.GetType("Jewelcrafting.API"); FieldInfo fieldInfo = type?.GetField("ringSlot", BindingFlags.Static | BindingFlags.Public); FieldInfo fieldInfo2 = type?.GetField("necklaceSlot", BindingFlags.Static | BindingFlags.Public); if (fieldInfo == null || fieldInfo2 == null) { detail = "ringSlot or necklaceSlot config field was not found"; return false; } MethodInfo isJewelryEquippedMethod = type2?.GetMethod("IsJewelryEquipped", BindingFlags.Static | BindingFlags.Public, null, new Type[2] { typeof(Player), typeof(string) }, null); api = new JewelcraftingSlotApi(fieldInfo, fieldInfo2, isJewelryEquippedMethod); detail = ""; return true; } public bool IsRingEnabled() { return GetCompatConfigEntryToggleOn(_ringSlotField, ref _ringSlotConfig); } public bool IsNecklaceEnabled() { return GetCompatConfigEntryToggleOn(_necklaceSlotField, ref _necklaceSlotConfig); } public bool TryGetIsJewelryEquippedMethod(out MethodBase? method) { method = _isJewelryEquippedMethod; return method != null; } } private sealed class JewelcraftingTooltipApi { private readonly MethodInfo _fillItemContainerTooltipMethod; private readonly FieldInfo _socketTooltipField; private readonly FieldInfo? _advancedTooltipKeyField; private JewelcraftingTooltipApi(MethodInfo fillItemContainerTooltipMethod, FieldInfo socketTooltipField, FieldInfo? advancedTooltipKeyField) { _fillItemContainerTooltipMethod = fillItemContainerTooltipMethod; _socketTooltipField = socketTooltipField; _advancedTooltipKeyField = advancedTooltipKeyField; } public static bool TryCreate(Assembly assembly, out JewelcraftingTooltipApi? api, out string detail) { api = null; Type? type = assembly.GetType("Jewelcrafting.API"); Type type2 = assembly.GetType("Jewelcrafting.GemStoneSetup"); Type type3 = assembly.GetType("Jewelcrafting.Jewelcrafting"); MethodInfo methodInfo = type?.GetMethod("FillItemContainerTooltip", BindingFlags.Static | BindingFlags.Public, null, new Type[3] { typeof(ItemData), typeof(Transform), typeof(bool) }, null); FieldInfo fieldInfo = type2?.GetField("SocketTooltip", BindingFlags.Static | BindingFlags.Public); if (methodInfo == null || fieldInfo == null) { detail = "required API members were not found"; return false; } api = new JewelcraftingTooltipApi(methodInfo, fieldInfo, type3?.GetField("advancedTooltipKey", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)); detail = ""; return true; } public void FillItemContainerTooltip(ItemData item, RectTransform root, bool showInteract) { _fillItemContainerTooltipMethod.Invoke(null, new object[3] { item, root, showInteract }); } public GameObject? GetSocketTooltip() { object? value = _socketTooltipField.GetValue(null); return (GameObject?)((value is GameObject) ? value : null); } public bool TryIsAdvancedTooltipPressed(out bool pressed) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) pressed = false; if (!(_advancedTooltipKeyField?.GetValue(null) is ConfigEntry<KeyboardShortcut> val)) { return false; } KeyboardShortcut value = val.Value; pressed = ((KeyboardShortcut)(ref value)).IsPressed(); return true; } } private sealed class JewelcraftingVisualApi { private readonly FieldInfo _visualsField; private readonly FieldInfo _equippedFingerItemField; private readonly FieldInfo _equippedNeckItemField; private readonly FieldInfo? _currentFingerItemHashField; private readonly FieldInfo? _currentNeckItemHashField; private readonly MethodInfo? _setFingerItemMethod; private readonly MethodInfo? _setNeckItemMethod; private readonly MethodInfo? _setFingerEquippedMethod; private readonly MethodInfo? _setNeckEquippedMethod; private JewelcraftingVisualApi(FieldInfo visualsField, FieldInfo equippedFingerItemField, FieldInfo equippedNeckItemField, FieldInfo? currentFingerItemHashField, FieldInfo? currentNeckItemHashField, MethodInfo? setFingerItemMethod, MethodInfo? setNeckItemMethod, MethodInfo? setFingerEquippedMethod, MethodInfo? setNeckEquippedMethod) { _visualsField = visualsField; _equippedFingerItemField = equippedFingerItemField; _equippedNeckItemField = equippedNeckItemField; _currentFingerItemHashField = currentFingerItemHashField; _currentNeckItemHashField = currentNeckItemHashField; _setFingerItemMethod = setFingerItemMethod; _setNeckItemMethod = setNeckItemMethod; _setFingerEquippedMethod = setFingerEquippedMethod; _setNeckEquippedMethod = setNeckEquippedMethod; } public static bool TryCreate(Assembly assembly, out JewelcraftingVisualApi? api, out string detail) { api = null; Type type = assembly.GetType("Jewelcrafting.Visual"); FieldInfo fieldInfo = type?.GetField("visuals", BindingFlags.Static | BindingFlags.Public); FieldInfo fieldInfo2 = type?.GetField("equippedFingerItem", BindingFlags.Instance | BindingFlags.Public); FieldInfo fieldInfo3 = type?.GetField("equippedNeckItem", BindingFlags.Instance | BindingFlags.Public); if (fieldInfo == null || fieldInfo2 == null || fieldInfo3 == null) { detail = "Visual fields were not found"; return false; } api = new JewelcraftingVisualApi(fieldInfo, fieldInfo2, fieldInfo3, type?.GetField("currentFingerItemHash", BindingFlags.Instance | BindingFlags.Public), type?.GetField("currentNeckItemHash", BindingFlags.Instance | BindingFlags.Public), type?.GetMethod("setFingerItem", BindingFlags.Instance | BindingFlags.NonPublic), type?.GetMethod("setNeckItem", BindingFlags.Instance | BindingFlags.NonPublic), type?.GetMethod("setFingerEquipped", BindingFlags.Instance | BindingFlags.NonPublic), type?.GetMethod("setNeckEquipped", BindingFlags.Instance | BindingFlags.NonPublic)); detail = ""; return true; } public bool TryGetVisual(VisEquipment visEquipment, out object? visual) { visual = null; if (!(_visualsField.GetValue(null) is IDictionary dictionary) || !dictionary.Contains(visEquipment)) { return false; } visual = dictionary[visEquipment]; return visual != null; } public void ClearSlot(object visual, bool isRing) { FieldInfo fieldInfo = (isRing ? _equippedFingerItemField : _equippedNeckItemField); FieldInfo fieldInfo2 = (isRing ? _currentFingerItemHashField : _currentNeckItemHashField); MethodInfo? obj = (isRing ? _setFingerItemMethod : _setNeckItemMethod); MethodInfo methodInfo = (isRing ? _setFingerEquippedMethod : _setNeckEquippedMethod); fieldInfo.SetValue(visual, null); obj?.Invoke(visual, new object[1] { "" }); if (methodInfo != null) { methodInfo.Invoke(visual, new object[1] { 0 }); } else { fieldInfo2?.SetValue(visual, 0); } } } internal enum InventoryStateEnsureReason { Unknown, PeriodicAudit, PlayerAwake, PlayerSpawned, PlayerLoad, PlayerSave, InventoryChanged, EquipmentChanged, InventoryLoad, InventoryMove, Tombstone, GuiShow, SlotAction, BackupRestore, YamlReload, JewelcraftingSlotRefresh, ConfigChanged, ReentrantFollowUp } internal enum InventoryStateAuditLevel { None, HeightOnly, SlotLight, FullIntegrity } private sealed class InventoryPanelRuntimeState { public readonly Dictionary<int, RectTransform> CustomSlotPanels = new Dictionary<int, RectTransform>(); public readonly Dictionary<int, RectTransform> QuickSlotPanels = new Dictionary<int, RectTransform>(); public readonly List<MovedPlayerStatPanel> MovedPlayerStatPanels = new List<MovedPlayerStatPanel>(); public readonly Dictionary<int, Vector3> QuickSlotPanelOutroStartPositions = new Dictionary<int, Vector3>(); public readonly Dictionary<int, GameObject> FavoriteKeyHintObjects = new Dictionary<int, GameObject>(); public readonly Dictionary<int, GameObject> PinnedTooltipKeyHintObjects = new Dictionary<int, GameObject>(); public RectTransform? QuickSlotsHotkeyBarRect; public HotkeyBar? QuickSlotsHotkeyBar; public RectTransform? PlayerStatPanelHost; public RectTransform? InventorySortPanel; public RectTransform? CurrencyPocketPanel; public Button? ContainerRestockButton; public Button? ContainerStoreAllButton; public Button? ContainerSortButton; public RectTransformSnapshot? TakeAllButtonOriginal; public RectTransformSnapshot? StackAllButtonOriginal; public RectTransform? PlayerInventoryScrollbar; public Scrollbar? PlayerInventoryScrollbarComponent; public RectTransform? PlayerInventoryResizeHandle; public TMP_Text? PlayerInventoryResizeHandleLabel; public RectTransform? TrackedContainerPanel; public RectTransform? TrackedContainerWeightPanel; public Vector3 ContainerPanelBasePosition; public Vector3 ContainerPanelAppliedOffset; public Vector3 ContainerWeightPanelBasePosition; public float ContainerWeightPanelAppliedYOffset; public RectTransform? DraggedInventoryPanel; public Vector3 InventoryPanelDragStartMouse; public Vector2 InventoryPanelDragStartOffset; public bool UpdatingPlayerInventoryScrollbar; public bool PlayerInventoryRowsDragging; public bool ContainerPanelBasePositionSet; public bool ContainerWeightPanelBasePositionSet; public bool DraggingQuickSlotsPanelOffset; public bool DraggingEquipmentSlotsPanelOffset; public Vector2 EquipmentSlotsPanelRuntimeOffset = EquipmentSlotsPanelFixedOffset; public Vector2 QuickSlotsPanelRuntimeOffset = QuickSlotsPanelFixedOffset; public Vector3 PlayerInventoryRowsDragStartMouse; public int PlayerInventoryRowsDragStartRows; public int LastExpandableInventoryRows = 4; public int PlayerInventoryScrollOffset; public int PlayerInventoryMaxScroll; public float QuickSlotPanelIntroStartTime = -1f; public float QuickSlotPanelIntroDuration = 0.25f; public float QuickSlotPanelOutroStartTime = -1f; public float QuickSlotPanelOutroDuration = 0.25f; public float QuickSlotHudElementSpace = 70f; public Container? ContainerRestockHoldContainer; public float ContainerRestockHoldStartTime = -1f; public bool ContainerRestockHoldTriggered; public bool QuickSlotPanelIntroActive; public bool QuickSlotPanelOutroActive; public bool QuickSlotHudAnchorValid; public bool LastExpandableInventoryRowsLoaded; public Vector3 QuickSlotHudAnchoredPosition; } private sealed class InventorySafetyRuntimeState { public readonly Dictionary<ItemData, PendingSlotEquip> PendingSlotEquips = new Dictionary<ItemData, PendingSlotEquip>(); public readonly Dictionary<ItemData, PendingSlotUnequip> PendingSlotUnequips = new Dictionary<ItemData, PendingSlotUnequip>(); public readonly HashSet<string> SlotRecoveryWarnings = new HashSet<string>(StringComparer.OrdinalIgnoreCase); public readonly HashSet<string> ForeignSlotPreservationWarnings = new HashSet<string>(StringComparer.OrdinalIgnoreCase); public readonly Dictionary<InventoryStateEnsureReason, int> EnsureCounts = new Dictionary<InventoryStateEnsureReason, int>(); public readonly Dictionary<ItemData, float> SlotUnequipToInventoryRequests = new Dictionary<ItemData, float>(); public bool RoutingEquipToDedicatedSlot; public bool RestoringSlotBackup; public bool EnsuringInventoryState; public InventoryStateEnsureReason PendingEnsureReason; public InventoryStateAuditLevel PendingAuditLevel; public InventoryStateEnsureReason DeferredEnsureReason; public InventoryStateAuditLevel DeferredAuditLevel; public int LastFullIntegrityAuditSignature = int.MinValue; public bool SlotUnequipInProgress; public bool SuppressSlotAutoEquip; public bool HandlingSlotDropOutside; } private sealed class InventoryContainerRuntimeState { public readonly List<Container> KnownContainers = new List<Container>(); } private sealed class InventoryDefinitionRuntimeState { public readonly List<SlotDefinition> SlotDefinitions = new List<SlotDefinition>(); public readonly List<SlotDefinition> CustomPanelSlotCache = new List<SlotDefinition>(); public readonly List<SlotDefinition> QuickPanelSlotCache = new List<SlotDefinition>(); public readonly Dictionary<int, SlotDefinition> QuickSlotDefinitionCache = new Dictionary<int, SlotDefinition>(); public readonly Dictionary<string, YamlPredefinedGroup> PredefinedGroupDefinitions = new Dictionary<string, YamlPredefinedGroup>(StringComparer.OrdinalIgnoreCase); public readonly List<string> PredefinedGroupOrder = new List<string>(); public readonly Dictionary<string, List<string>> PredefinedGroupOrders = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase); public readonly Dictionary<string, int> ResourceTierByToken = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase); public readonly HashSet<string> CookingStationInputTokens = new HashSet<string>(StringComparer.OrdinalIgnoreCase); public readonly HashSet<string> CraftingRecipeFoodInputTokens = new HashSet<string>(StringComparer.OrdinalIgnoreCase); public readonly HashSet<string> CraftingRecipeHealthFoodInputTokens = new HashSet<string>(StringComparer.OrdinalIgnoreCase); public readonly HashSet<string> CraftingRecipeStaminaFoodInputTokens = new HashSet<string>(StringComparer.OrdinalIgnoreCase); public readonly HashSet<string> CraftingRecipeEitrFoodInputTokens = new HashSet<string>(StringComparer.OrdinalIgnoreCase); public readonly HashSet<string> CookingStationFoodInputTokens = new HashSet<string>(StringComparer.OrdinalIgnoreCase); public readonly HashSet<string> CookingStationHealthFoodInputTokens = new HashSet<string>(StringComparer.OrdinalIgnoreCase); public readonly HashSet<string> CookingStationStaminaFoodInputTokens = new HashSet<string>(StringComparer.OrdinalIgnoreCase); public readonly HashSet<string> CookingStationEitrFoodInputTokens = new HashSet<string>(StringComparer.OrdinalIgnoreCase); public readonly HashSet<string> FermenterInputTokens = new HashSet<string>(StringComparer.O