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 AzuExtendedPlayerInventory v2.4.2
AzuExtendedPlayerInventory.dll
Decompiled 2 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Timers; using APIManager; using AzuEPI; using AzuEPI.Core.Input; using AzuEPI.Core.InventoryHandlers; using AzuEPI.Core.Slots; using AzuEPI.Core.Text; using AzuEPI.Core.Utilities.Extensions; using AzuEPI.EPI; using AzuEPI.Game.Compatibility; using AzuEPI.Game.Compatibility.AdvBackpacks; using AzuEPI.Game.Loadout; using AzuEPI.Game.Panels; using AzuEPI.Game.Panels.Stats; using AzuEPI.Game.Panels.Vanity; using AzuEPI.Game.Patches; using AzuEPI.Game.PlayerPreview; using AzuEPI.Game.Slots; using AzuEPI.Game.Slots.QAB; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using BepInEx.Preloader; using BepInEx.Preloader.Patching; using HarmonyLib; using JetBrains.Annotations; using LocalizationManager; using Microsoft.CodeAnalysis; using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Collections.Generic; 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("AzuExtendedPlayerInventory")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Azumatt")] [assembly: AssemblyProduct("AzuExtendedPlayerInventory")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("4358610B-F3F4-4843-B7AF-98B7BC60DCDE")] [assembly: AssemblyFileVersion("2.4.2")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.4.2.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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] [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; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class ExtensionMarkerAttribute : Attribute { public ExtensionMarkerAttribute(string name) { } } } public static class ToggleExtensions { [SpecialName] public sealed class <G>$4F220943ABCF1C1726BA9F32F1C84BFA { [SpecialName] public static class <M>$B886148B8B9A8A91C986883EF65534E9 { } [ExtensionMarker("<M>$B886148B8B9A8A91C986883EF65534E9")] public bool isOn() { throw null; } [ExtensionMarker("<M>$B886148B8B9A8A91C986883EF65534E9")] public bool isOff() { throw null; } } public static bool isOn(this AzuExtendedPlayerInventoryPlugin.Toggle toggle) { return toggle == AzuExtendedPlayerInventoryPlugin.Toggle.On; } public static bool isOff(this AzuExtendedPlayerInventoryPlugin.Toggle toggle) { return toggle == AzuExtendedPlayerInventoryPlugin.Toggle.Off; } } namespace AzuExtendedPlayerInventory { [PublicAPI] public class API { public delegate void SlotAddedHandler(string slotName); public delegate void SlotRemovedHandler(string slotName); private static readonly Dictionary<SlotAddedHandler, AzuEPI.API.SlotAddedHandler> _slotAddedMap = new Dictionary<SlotAddedHandler, AzuEPI.API.SlotAddedHandler>(); private static readonly Dictionary<SlotRemovedHandler, AzuEPI.API.SlotRemovedHandler> _slotRemovedMap = new Dictionary<SlotRemovedHandler, AzuEPI.API.SlotRemovedHandler>(); private static readonly Dictionary<Action<Hud>, Action<Hud>> _hudAwakeMap = new Dictionary<Action<Hud>, Action<Hud>>(); private static readonly Dictionary<Action<Hud>, Action<Hud>> _hudAwakeCompleteMap = new Dictionary<Action<Hud>, Action<Hud>>(); private static readonly Dictionary<Action<Hud>, Action<Hud>> _hudUpdateMap = new Dictionary<Action<Hud>, Action<Hud>>(); private static readonly Dictionary<Action<Hud>, Action<Hud>> _hudUpdateCompleteMap = new Dictionary<Action<Hud>, Action<Hud>>(); public static event SlotAddedHandler? SlotAdded { add { if (value == null || _slotAddedMap.ContainsKey(value)) { return; } AzuEPI.API.SlotAddedHandler value2 = delegate(string s) { try { value(s); } catch { } }; _slotAddedMap[value] = value2; AzuEPI.API.SlotAdded += value2; } remove { if (value != null && _slotAddedMap.TryGetValue(value, out AzuEPI.API.SlotAddedHandler value2)) { AzuEPI.API.SlotAdded -= value2; _slotAddedMap.Remove(value); } } } public static event SlotRemovedHandler? SlotRemoved { add { if (value == null || _slotRemovedMap.ContainsKey(value)) { return; } AzuEPI.API.SlotRemovedHandler value2 = delegate(string s) { try { value(s); } catch { } }; _slotRemovedMap[value] = value2; AzuEPI.API.SlotRemoved += value2; } remove { if (value != null && _slotRemovedMap.TryGetValue(value, out AzuEPI.API.SlotRemovedHandler value2)) { AzuEPI.API.SlotRemoved -= value2; _slotRemovedMap.Remove(value); } } } public static event Action<Hud>? OnHudAwake { add { AddHudEvent(value, _hudAwakeMap, delegate(Action<Hud> h) { AzuEPI.API.OnHudAwake += h; }); } remove { RemoveHudEvent(value, _hudAwakeMap, delegate(Action<Hud> h) { AzuEPI.API.OnHudAwake -= h; }); } } public static event Action<Hud>? OnHudAwakeComplete { add { AddHudEvent(value, _hudAwakeCompleteMap, delegate(Action<Hud> h) { AzuEPI.API.OnHudAwakeComplete += h; }); } remove { RemoveHudEvent(value, _hudAwakeCompleteMap, delegate(Action<Hud> h) { AzuEPI.API.OnHudAwakeComplete -= h; }); } } public static event Action<Hud>? OnHudUpdate { add { AddHudEvent(value, _hudUpdateMap, delegate(Action<Hud> h) { AzuEPI.API.OnHudUpdate += h; }); } remove { RemoveHudEvent(value, _hudUpdateMap, delegate(Action<Hud> h) { AzuEPI.API.OnHudUpdate -= h; }); } } public static event Action<Hud>? OnHudUpdateComplete { add { AddHudEvent(value, _hudUpdateCompleteMap, delegate(Action<Hud> h) { AzuEPI.API.OnHudUpdateComplete += h; }); } remove { RemoveHudEvent(value, _hudUpdateCompleteMap, delegate(Action<Hud> h) { AzuEPI.API.OnHudUpdateComplete -= h; }); } } private static void AddHudEvent(Action<Hud>? handler, Dictionary<Action<Hud>, Action<Hud>> map, Action<Action<Hud>> subscribe) { if (handler == null || map.ContainsKey(handler)) { return; } Action<Hud> action = delegate(Hud h) { try { handler(h); } catch { } }; map[handler] = action; subscribe(action); } private static void RemoveHudEvent(Action<Hud>? handler, Dictionary<Action<Hud>, Action<Hud>> map, Action<Action<Hud>> unsubscribe) { if (handler != null && map.TryGetValue(handler, out Action<Hud> value)) { unsubscribe(value); map.Remove(handler); } } public static bool IsLoaded() { return AzuEPI.API.IsLoaded(); } public static bool AddSlot(string slotName, Func<Player, ItemData?> getItem, Func<ItemData, bool> isValid, int index = -1) { if (Localization.m_instance == null || Localization.m_instance.Localize(slotName).Contains("[")) { Localizer.OnLocalizationComplete += delegate { AzuEPI.API.AddSlot(slotName, getItem, isValid, index); }; } else { AzuEPI.API.AddSlot(slotName, getItem, isValid, index); } return true; } public static bool RemoveSlot(string slotName) { return AzuEPI.API.RemoveSlot(slotName); } public static SlotInfo GetSlots() { AzuEPI.SlotInfo slots = AzuEPI.API.GetSlots(); return new SlotInfo { SlotNames = (slots.SlotNames ?? Array.Empty<string>()), SlotPositions = (slots.SlotPositions ?? Array.Empty<Vector2>()), GetItemFuncs = (slots.GetItemFuncs ?? Array.Empty<Func<Player, ItemData>>()), IsValidFuncs = (slots.IsValidFuncs ?? Array.Empty<Func<ItemData, bool>>()) }; } public static SlotInfo GetQuickSlots() { AzuEPI.SlotInfo quickSlots = AzuEPI.API.GetQuickSlots(); return new SlotInfo { SlotNames = (quickSlots.SlotNames ?? Array.Empty<string>()), SlotPositions = (quickSlots.SlotPositions ?? Array.Empty<Vector2>()), GetItemFuncs = (quickSlots.GetItemFuncs ?? Array.Empty<Func<Player, ItemData>>()), IsValidFuncs = (quickSlots.IsValidFuncs ?? Array.Empty<Func<ItemData, bool>>()) }; } public static List<ItemData> GetQuickSlotsItems() { return AzuEPI.API.GetQuickSlotsItems(); } public static int GetAddedRows(int width) { return AzuEPI.API.GetAddedRows(width); } public static void HudAwake(Hud h) { SafeInvoke(delegate { AzuEPI.API.HudAwake(h); }); } public static void HudAwakeComplete(Hud h) { SafeInvoke(delegate { AzuEPI.API.HudAwakeComplete(h); }); } public static void HudUpdate(Hud h) { SafeInvoke(delegate { AzuEPI.API.HudUpdate(h); }); } public static void HudUpdateComplete(Hud h) { SafeInvoke(delegate { AzuEPI.API.HudUpdateComplete(h); }); } private static void SafeInvoke(Action a) { try { a(); } catch { } } } [PublicAPI] public class SlotInfo { public string[] SlotNames { get; set; } = Array.Empty<string>(); public Vector2[] SlotPositions { get; set; } = Array.Empty<Vector2>(); public Func<Player, ItemData?>?[] GetItemFuncs { get; set; } = Array.Empty<Func<Player, ItemData>>(); public Func<ItemData, bool>?[] IsValidFuncs { get; set; } = Array.Empty<Func<ItemData, bool>>(); } } namespace APIManager { public static class Patcher { private class MonoAssemblyResolver : IAssemblyResolver, IDisposable { public AssemblyDefinition Resolve(AssemblyNameReference name) { return AssemblyDefinition.ReadAssembly(AppDomain.CurrentDomain.Load(name.FullName).Location); } public AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters) { return Resolve(name); } public void Dispose() { } } private class AssemblyLoadInterceptor { private static string? assemblyPath; private static MethodInfo TargetMethod() { return AccessTools.DeclaredMethod(typeof(Assembly), "Load", new Type[1] { typeof(byte[]) }, (Type[])null); } private static bool Prefix(ref byte[] __0, ref Assembly? __result) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Expected O, but got Unknown //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Expected O, but got Unknown //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Expected O, but got Unknown //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Expected O, but got Unknown //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Expected O, but got Unknown //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Unknown result type (might be due to invalid IL or missing references) assemblyPath = null; if (modifyNextLoad) { modifyNextLoad = false; try { AssemblyDefinition val = AssemblyDefinition.ReadAssembly((Stream)new MemoryStream(__0), new ReaderParameters { AssemblyResolver = (IAssemblyResolver)(object)new MonoAssemblyResolver() }); try { ((Dictionary<string, string>)typeof(EnvVars).Assembly.GetType("BepInEx.Preloader.RuntimeFixes.UnityPatches").GetProperty("AssemblyLocations").GetValue(null))[val.FullName] = currentAssemblyPath; FixupModuleReferences(val.MainModule); TypeDefinition val2 = val.MainModule.GetType("APIManager", "PatchedAttribute"); if (val2 == null) { val2 = new TypeDefinition("APIManager", "PatchedAttribute", (TypeAttributes)3) { BaseType = val.MainModule.ImportReference(typeof(Attribute)) }; MethodDefinition val3 = new MethodDefinition(".ctor", (MethodAttributes)6278, val.MainModule.TypeSystem.Void); ((MethodReference)val3).Parameters.Add(new ParameterDefinition(val.MainModule.TypeSystem.String)); ((MethodReference)val3).Parameters.Add(new ParameterDefinition(val.MainModule.TypeSystem.String)); val3.Body.Instructions.Add(Instruction.Create(OpCodes.Ret)); val2.Methods.Add(val3); val.MainModule.Types.Add(val2); CustomAttribute val4 = new CustomAttribute((MethodReference)(object)val3); val4.ConstructorArguments.Add(new CustomAttributeArgument(val.MainModule.TypeSystem.String, (object)"")); val4.ConstructorArguments.Add(new CustomAttributeArgument(val.MainModule.TypeSystem.String, (object)val.MainModule.Mvid.ToString())); val.CustomAttributes.Add(val4); } CustomAttribute val5 = new CustomAttribute((MethodReference)(object)((IEnumerable<MethodDefinition>)val2.Methods).First((MethodDefinition m) => ((MemberReference)m).Name == ".ctor")); val5.ConstructorArguments.Add(new CustomAttributeArgument(val.MainModule.TypeSystem.String, (object)modGUID)); val5.ConstructorArguments.Add(new CustomAttributeArgument(val.MainModule.TypeSystem.String, (object)patchingAssembly.ManifestModule.ModuleVersionId.ToString())); val.CustomAttributes.Add(val5); using MemoryStream memoryStream = new MemoryStream(); val.Write((Stream)memoryStream); __0 = memoryStream.ToArray(); string dumpedAssembliesPath = Patcher.dumpedAssembliesPath; char directorySeparatorChar = Path.DirectorySeparatorChar; string path = dumpedAssembliesPath + directorySeparatorChar + ((AssemblyNameReference)val.Name).Name + ".dll"; Directory.CreateDirectory(Patcher.dumpedAssembliesPath); File.WriteAllBytes(path, __0); assemblyPath = path; __result = null; return false; } finally { ((IDisposable)val)?.Dispose(); } } catch (BadImageFormatException) { } catch (Exception ex2) { Debug.LogError((object)("Failed patching ... " + ex2)); } } return true; } private static void Postfix(ref Assembly? __result) { if (assemblyPath != null && __result == null) { __result = Assembly.LoadFrom(assemblyPath); assemblyPath = null; } } } private static PluginInfo? lastPluginInfo; private static bool modifyNextLoad = false; private static string modGUID = null; private static HashSet<string> redirectedNamespaces = null; private static readonly Assembly patchingAssembly = Assembly.GetExecutingAssembly(); private static string currentAssemblyPath = null; private static readonly string dumpedAssembliesPath = (string)AccessTools.DeclaredField(typeof(AssemblyPatcher), "DumpedAssembliesPath").GetValue(null); private static void GrabPluginInfo(PluginInfo __instance) { lastPluginInfo = __instance; } [HarmonyPriority(700)] private static void CheckAssemblyLoadFile(string __0) { PluginInfo? obj = lastPluginInfo; if (__0 == ((obj != null) ? obj.Location : null) && lastPluginInfo.Dependencies.Any((BepInDependency d) => d.DependencyGUID == modGUID)) { modifyNextLoad = true; currentAssemblyPath = __0; } lastPluginInfo = null; } [HarmonyPriority(500)] private static bool InterceptAssemblyLoadFile(string __0, ref Assembly? __result) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) if (modifyNextLoad && (object)__result == null) { string text = dumpedAssembliesPath; char directorySeparatorChar = Path.DirectorySeparatorChar; string text2 = text + directorySeparatorChar + Path.GetFileName(__0); if (File.Exists(text2)) { AssemblyDefinition val = AssemblyDefinition.ReadAssembly(text2, new ReaderParameters { AssemblyResolver = (IAssemblyResolver)(object)new MonoAssemblyResolver() }); try { bool flag = false; Enumerator<CustomAttribute> enumerator = val.CustomAttributes.GetEnumerator(); try { while (enumerator.MoveNext()) { CustomAttribute current = enumerator.Current; TypeReference declaringType = ((MemberReference)current.Constructor).DeclaringType; if (declaringType.Namespace == "APIManager" && ((MemberReference)declaringType).Name == "PatchedAttribute") { CustomAttributeArgument val2 = current.ConstructorArguments[0]; if ((string)((CustomAttributeArgument)(ref val2)).Value == modGUID) { val2 = current.ConstructorArguments[1]; flag = (string)((CustomAttributeArgument)(ref val2)).Value == patchingAssembly.ManifestModule.ModuleVersionId.ToString(); break; } } } } finally { ((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose(); } if (flag) { return true; } } finally { ((IDisposable)val)?.Dispose(); } } __result = Assembly.Load(File.ReadAllBytes(__0)); return false; } return true; } [HarmonyPriority(499)] private static bool ReplaceAssemblyLoadWithCache(ref string __0, ref Assembly? __result) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) if (modifyNextLoad && (object)__result == null && !__0.StartsWith(dumpedAssembliesPath)) { string text = dumpedAssembliesPath; char directorySeparatorChar = Path.DirectorySeparatorChar; string text2 = text + directorySeparatorChar + Path.GetFileName(__0); AssemblyDefinition val = AssemblyDefinition.ReadAssembly(text2, new ReaderParameters { AssemblyResolver = (IAssemblyResolver)(object)new MonoAssemblyResolver() }); AssemblyDefinition val2 = AssemblyDefinition.ReadAssembly(__0, new ReaderParameters { AssemblyResolver = (IAssemblyResolver)(object)new MonoAssemblyResolver() }); Enumerator<CustomAttribute> enumerator = val.CustomAttributes.GetEnumerator(); try { while (enumerator.MoveNext()) { CustomAttribute current = enumerator.Current; TypeReference declaringType = ((MemberReference)current.Constructor).DeclaringType; if (declaringType.Namespace == "APIManager" && ((MemberReference)declaringType).Name == "PatchedAttribute") { CustomAttributeArgument val3 = current.ConstructorArguments[0]; string text3 = (string)((CustomAttributeArgument)(ref val3)).Value; bool num; if (!(text3 == "")) { num = !Chainloader.PluginInfos.ContainsKey(text3); } else { val3 = current.ConstructorArguments[1]; num = (string)((CustomAttributeArgument)(ref val3)).Value != val2.MainModule.Mvid.ToString(); } if (num) { val2.Dispose(); val.Dispose(); __result = Assembly.Load(File.ReadAllBytes(__0)); return false; } } } } finally { ((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose(); } ((Dictionary<string, string>)typeof(EnvVars).Assembly.GetType("BepInEx.Preloader.RuntimeFixes.UnityPatches").GetProperty("AssemblyLocations").GetValue(null))[val.FullName] = __0; val2.Dispose(); val.Dispose(); __0 = text2; } modifyNextLoad = false; return true; } private static void FixupModuleReferences(ModuleDefinition module) { foreach (TypeDefinition type3 in module.GetTypes()) { if ((object)patchingAssembly.GetType(((MemberReference)type3).FullName) == null) { Dispatch(type3); } } static bool AreSame(TypeReference a, TypeReference b) { return (bool)typeof(MetadataResolver).Assembly.GetType("Mono.Cecil.MetadataResolver").GetMethod("AreSame", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[2] { typeof(TypeReference), typeof(TypeReference) }, null).Invoke(null, new object[2] { a, b }); } void Dispatch(TypeDefinition type) { if (type.BaseType != null && (object)type.BaseType.Scope == module && redirectedNamespaces.Contains(baseDeclaringType(type.BaseType).Namespace)) { Type type2 = patchingAssembly.GetType(((MemberReference)type.BaseType).FullName); if ((object)type2 != null) { type.BaseType = module.ImportReference(type2); } } DispatchGenericParameters((IGenericParameterProvider)(object)type, ((MemberReference)type).FullName); DispatchInterfaces(type, ((MemberReference)type).FullName); DispatchAttributes((ICustomAttributeProvider)(object)type, ((MemberReference)type).FullName); DispatchFields(type, ((MemberReference)type).FullName); DispatchProperties(type, ((MemberReference)type).FullName); DispatchEvents(type, ((MemberReference)type).FullName); DispatchMethods(type); } void DispatchAttributes(ICustomAttributeProvider provider, string referencingEntityName) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) if (!provider.HasCustomAttributes) { return; } Enumerator<CustomAttribute> enumerator2 = provider.CustomAttributes.GetEnumerator(); try { while (enumerator2.MoveNext()) { CustomAttribute current2 = enumerator2.Current; MethodReference val = importMethodReference(current2.Constructor); if (val != null) { current2.Constructor = val; } else { VisitMethod(current2.Constructor, referencingEntityName); } for (int i = 0; i < current2.ConstructorArguments.Count; i++) { CustomAttributeArgument val2 = current2.ConstructorArguments[i]; current2.ConstructorArguments[i] = new CustomAttributeArgument(VisitType(((CustomAttributeArgument)(ref val2)).Type, referencingEntityName), ((CustomAttributeArgument)(ref val2)).Value); } CustomAttributeArgument argument; for (int j = 0; j < current2.Properties.Count; j++) { CustomAttributeNamedArgument val3 = current2.Properties[j]; Collection<CustomAttributeNamedArgument> properties = current2.Properties; int num = j; string name = ((CustomAttributeNamedArgument)(ref val3)).Name; argument = ((CustomAttributeNamedArgument)(ref val3)).Argument; TypeReference? obj = VisitType(((CustomAttributeArgument)(ref argument)).Type, referencingEntityName); argument = ((CustomAttributeNamedArgument)(ref val3)).Argument; properties[num] = new CustomAttributeNamedArgument(name, new CustomAttributeArgument(obj, ((CustomAttributeArgument)(ref argument)).Value)); } for (int k = 0; k < current2.Fields.Count; k++) { CustomAttributeNamedArgument val4 = current2.Fields[k]; Collection<CustomAttributeNamedArgument> fields = current2.Fields; int num2 = k; string name2 = ((CustomAttributeNamedArgument)(ref val4)).Name; argument = ((CustomAttributeNamedArgument)(ref val4)).Argument; TypeReference? obj2 = VisitType(((CustomAttributeArgument)(ref argument)).Type, referencingEntityName); argument = ((CustomAttributeNamedArgument)(ref val4)).Argument; fields[num2] = new CustomAttributeNamedArgument(name2, new CustomAttributeArgument(obj2, ((CustomAttributeArgument)(ref argument)).Value)); } } } finally { ((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose(); } } void DispatchEvents(TypeDefinition type, string referencingEntityName) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) Enumerator<EventDefinition> enumerator2 = type.Events.GetEnumerator(); try { while (enumerator2.MoveNext()) { EventDefinition current2 = enumerator2.Current; ((EventReference)current2).EventType = VisitType(((EventReference)current2).EventType, referencingEntityName); DispatchAttributes((ICustomAttributeProvider)(object)current2, referencingEntityName); } } finally { ((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose(); } } void DispatchFields(TypeDefinition type, string referencingEntityName) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) Enumerator<FieldDefinition> enumerator2 = type.Fields.GetEnumerator(); try { while (enumerator2.MoveNext()) { FieldDefinition current2 = enumerator2.Current; ((FieldReference)current2).FieldType = VisitType(((FieldReference)current2).FieldType, referencingEntityName); DispatchAttributes((ICustomAttributeProvider)(object)current2, referencingEntityName); } } finally { ((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose(); } } void DispatchGenericArguments(IGenericInstance genericInstance, string referencingEntityName) { for (int i = 0; i < genericInstance.GenericArguments.Count; i++) { genericInstance.GenericArguments[i] = VisitType(genericInstance.GenericArguments[i], referencingEntityName); } } void DispatchGenericParameters(IGenericParameterProvider provider, string referencingEntityName) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) Enumerator<GenericParameter> enumerator2 = provider.GenericParameters.GetEnumerator(); try { while (enumerator2.MoveNext()) { GenericParameter current2 = enumerator2.Current; DispatchAttributes((ICustomAttributeProvider)(object)current2, referencingEntityName); for (int i = 0; i < current2.Constraints.Count; i++) { current2.Constraints[i] = VisitType(current2.Constraints[i], referencingEntityName); } } } finally { ((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose(); } } void DispatchInterfaces(TypeDefinition type, string referencingEntityName) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) Enumerator<InterfaceImplementation> enumerator2 = type.Interfaces.GetEnumerator(); try { while (enumerator2.MoveNext()) { InterfaceImplementation current2 = enumerator2.Current; current2.InterfaceType = VisitType(current2.InterfaceType, referencingEntityName); } } finally { ((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose(); } } void DispatchMethod(MethodDefinition method) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) ((MethodReference)method).ReturnType = VisitType(((MethodReference)method).ReturnType, ((MemberReference)method).FullName); DispatchAttributes((ICustomAttributeProvider)(object)((MethodReference)method).MethodReturnType, ((MemberReference)method).FullName); DispatchGenericParameters((IGenericParameterProvider)(object)method, ((MemberReference)method).FullName); Enumerator<ParameterDefinition> enumerator2 = ((MethodReference)method).Parameters.GetEnumerator(); try { while (enumerator2.MoveNext()) { ParameterDefinition current2 = enumerator2.Current; ((ParameterReference)current2).ParameterType = VisitType(((ParameterReference)current2).ParameterType, ((MemberReference)method).FullName); DispatchAttributes((ICustomAttributeProvider)(object)current2, ((MemberReference)method).FullName); } } finally { ((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose(); } for (int i = 0; i < method.Overrides.Count; i++) { MethodReference val = importMethodReference(method.Overrides[i]); if (val != null) { method.Overrides[i] = val; } else { VisitMethod(method.Overrides[i], ((MemberReference)method).FullName); } } if (method.HasBody) { DispatchMethodBody(method.Body); } } void DispatchMethodBody(MethodBody body) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) Enumerator<VariableDefinition> enumerator2 = body.Variables.GetEnumerator(); try { while (enumerator2.MoveNext()) { VariableDefinition current2 = enumerator2.Current; ((VariableReference)current2).VariableType = VisitType(((VariableReference)current2).VariableType, ((MemberReference)body.Method).FullName); } } finally { ((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose(); } Enumerator<Instruction> enumerator3 = body.Instructions.GetEnumerator(); try { while (enumerator3.MoveNext()) { Instruction current3 = enumerator3.Current; object operand = current3.Operand; FieldReference val = (FieldReference)((operand is FieldReference) ? operand : null); if (val == null) { MethodReference val2 = (MethodReference)((operand is MethodReference) ? operand : null); if (val2 == null) { TypeReference val3 = (TypeReference)((operand is TypeReference) ? operand : null); if (val3 != null) { current3.Operand = VisitType(val3, ((MemberReference)body.Method).FullName); } } else { MethodReference val4 = importMethodReference(val2); if (val4 != null) { current3.Operand = val4; } else { VisitMethod(val2, ((MemberReference)body.Method).FullName); } } } else { FieldReference val5 = importFieldReference(val); if (val5 != null) { current3.Operand = val5; } else { VisitField(val, ((MemberReference)body.Method).FullName); } } } } finally { ((IDisposable)enumerator3/*cast due to .constrained prefix*/).Dispose(); } } void DispatchMethods(TypeDefinition type) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) Enumerator<MethodDefinition> enumerator2 = type.Methods.GetEnumerator(); try { while (enumerator2.MoveNext()) { MethodDefinition current2 = enumerator2.Current; DispatchMethod(current2); } } finally { ((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose(); } } void DispatchProperties(TypeDefinition type, string referencingEntityName) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) Enumerator<PropertyDefinition> enumerator2 = type.Properties.GetEnumerator(); try { while (enumerator2.MoveNext()) { PropertyDefinition current2 = enumerator2.Current; ((PropertyReference)current2).PropertyType = VisitType(((PropertyReference)current2).PropertyType, referencingEntityName); DispatchAttributes((ICustomAttributeProvider)(object)current2, referencingEntityName); } } finally { ((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose(); } } TypeReference FixupType(TypeReference type) { if ((object)type.Scope == module && redirectedNamespaces.Contains(baseDeclaringType(type).Namespace)) { if (type.IsNested) { return FixupType(((MemberReference)type).DeclaringType); } Type type2 = patchingAssembly.GetType(((MemberReference)type).FullName); if ((object)type2 != null) { return module.ImportReference(type2); } } return type; } void VisitField(FieldReference? field, string referencingEntityName) { if (field != null) { field.FieldType = VisitType(field.FieldType, referencingEntityName); if (!(field is FieldDefinition)) { ((MemberReference)field).DeclaringType = VisitType(((MemberReference)field).DeclaringType, referencingEntityName); } } } void VisitMethod(MethodReference? method, string referencingEntityName) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) if (method != null) { GenericInstanceMethod val = (GenericInstanceMethod)(object)((method is GenericInstanceMethod) ? method : null); if (val != null) { DispatchGenericArguments((IGenericInstance)(object)val, referencingEntityName); } method.ReturnType = VisitType(method.ReturnType, referencingEntityName); Enumerator<ParameterDefinition> enumerator2 = method.Parameters.GetEnumerator(); try { while (enumerator2.MoveNext()) { ParameterDefinition current2 = enumerator2.Current; ((ParameterReference)current2).ParameterType = VisitType(((ParameterReference)current2).ParameterType, referencingEntityName); } } finally { ((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose(); } if (!(method is MethodSpecification)) { ((MemberReference)method).DeclaringType = VisitType(((MemberReference)method).DeclaringType, referencingEntityName); } } } TypeReference? VisitType(TypeReference? type, string referencingEntityName) { if (type == null) { return type; } if (type.GetElementType().IsGenericParameter) { return type; } GenericInstanceType val = (GenericInstanceType)(object)((type is GenericInstanceType) ? type : null); if (val != null) { DispatchGenericArguments((IGenericInstance)(object)val, referencingEntityName); } return FixupType(type); } static TypeReference baseDeclaringType(TypeReference type) { while (((MemberReference)type).DeclaringType != null) { type = ((MemberReference)type).DeclaringType; } return type; } FieldReference? importFieldReference(FieldReference field) { if ((object)((MemberReference)field).DeclaringType.Scope == module && redirectedNamespaces.Contains(baseDeclaringType(((MemberReference)field).DeclaringType).Namespace)) { FieldInfo fieldInfo = patchingAssembly.GetType(((MemberReference)((MemberReference)field).DeclaringType).FullName)?.GetField(((MemberReference)field).Name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if ((object)fieldInfo != null) { return module.ImportReference(fieldInfo); } } return null; } MethodReference? importMethodReference(MethodReference method) { //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Expected O, but got Unknown if ((object)((MemberReference)method).DeclaringType.Scope == module && redirectedNamespaces.Contains(baseDeclaringType(((MemberReference)method).DeclaringType).Namespace)) { if (((MemberReference)method).Name == ".cctor") { ConstructorInfo[] array = patchingAssembly.GetType(((MemberReference)((MemberReference)method).DeclaringType).FullName)?.GetConstructors(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (array != null && array.Length == 1) { return module.ImportReference((MethodBase)array[0]); } } else if (((MemberReference)method).Name == ".ctor") { ConstructorInfo constructorInfo = patchingAssembly.GetType(((MemberReference)((MemberReference)method).DeclaringType).FullName)?.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault(CompareMethods); if ((object)constructorInfo != null) { return module.ImportReference((MethodBase)constructorInfo); } } else { MethodInfo methodInfo = patchingAssembly.GetType(((MemberReference)((MemberReference)method).DeclaringType).FullName)?.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault(delegate(MethodInfo m) { if (m.Name != ((MemberReference)method).Name) { return false; } return (((MemberReference)method.ReturnType).ContainsGenericParameter == m.ReturnType.IsGenericParameter || AreSame(method.ReturnType, module.ImportReference(m.ReturnType))) && CompareMethods(m); }); if ((object)methodInfo != null) { MethodReference val = module.ImportReference((MethodBase)methodInfo); MethodReference obj = method; GenericInstanceMethod val2 = (GenericInstanceMethod)(object)((obj is GenericInstanceMethod) ? obj : null); if (val2 != null) { GenericInstanceMethod val3 = new GenericInstanceMethod(val); for (int num = 0; num < val2.GenericArguments.Count; num++) { val2.GenericArguments[num] = VisitType(val2.GenericArguments[num], ((MemberReference)method).FullName); val3.GenericArguments.Add(val2.GenericArguments[num]); } val = (MethodReference)(object)val3; } return val; } } } return null; bool CompareMethods(MethodBase m) { ParameterInfo[] parameters = m.GetParameters(); if (method.IsGenericInstance != m.IsGenericMethodDefinition || parameters.Length != 0 != method.HasParameters) { return false; } if (method.HasParameters) { if (method.Parameters.Count != parameters.Length) { return false; } for (int i = 0; i < method.Parameters.Count; i++) { if (parameters[i].ParameterType.IsGenericParameter ? (!((ParameterReference)method.Parameters[i]).ParameterType.IsGenericParameter) : (!AreSame(((ParameterReference)method.Parameters[i]).ParameterType, module.ImportReference(parameters[i].ParameterType)))) { return false; } } } return true; } } } public static bool PreventHarmonyInteropFixLoad(Assembly? __0) { return __0 == null; } public static void Patch(IEnumerable<string>? extraNamespaces = null) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Expected O, but got Unknown //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Expected O, but got Unknown //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Expected O, but got Unknown Harmony val = new Harmony("org.bepinex.plugins.APIManager"); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(PluginInfo), "ToString", (Type[])null, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Patcher), "GrabPluginInfo", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Assembly), "LoadFile", new Type[1] { typeof(string) }, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Patcher), "InterceptAssemblyLoadFile", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Assembly), "LoadFile", new Type[1] { typeof(string) }, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Patcher), "CheckAssemblyLoadFile", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Assembly), "LoadFile", new Type[1] { typeof(string) }, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Patcher), "ReplaceAssemblyLoadWithCache", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); new PatchClassProcessor(val, typeof(AssemblyLoadInterceptor), true).Patch(); Type type = typeof(AssemblyPatcher).Assembly.GetType("BepInEx.Preloader.RuntimeFixes.HarmonyInteropFix"); if ((object)type != null) { val.Patch((MethodBase)AccessTools.DeclaredMethod(type, "OnAssemblyLoad", (Type[])null, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Patcher), "PreventHarmonyInteropFixLoad", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } IEnumerable<TypeInfo> source; try { source = patchingAssembly.DefinedTypes.ToList(); } catch (ReflectionTypeLoadException ex) { source = from t in ex.Types where t != null select t.GetTypeInfo(); } BaseUnityPlugin val2 = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First((TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t))); HashSet<string> hashSet = new HashSet<string>(); foreach (string item in extraNamespaces ?? Array.Empty<string>()) { hashSet.Add(item); } hashSet.Add(((object)val2).GetType().Namespace); redirectedNamespaces = hashSet; modGUID = val2.Info.Metadata.GUID; } } } namespace LocalizationManager { [PublicAPI] public class Localizer { private static readonly Dictionary<string, Dictionary<string, Func<string>>> PlaceholderProcessors; private static readonly Dictionary<string, Dictionary<string, string>> loadedTexts; private static readonly ConditionalWeakTable<Localization, string> localizationLanguage; private static readonly List<WeakReference<Localization>> localizationObjects; private static BaseUnityPlugin? _plugin; private static readonly List<string> fileExtensions; private static BaseUnityPlugin plugin { get { //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Expected O, but got Unknown if (_plugin == null) { IEnumerable<TypeInfo> source; try { source = Assembly.GetExecutingAssembly().DefinedTypes.ToList(); } catch (ReflectionTypeLoadException ex) { source = from t in ex.Types where t != null select t.GetTypeInfo(); } _plugin = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First((TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t))); } return _plugin; } } public static event Action? OnLocalizationComplete; private static void UpdatePlaceholderText(Localization localization, string key) { localizationLanguage.TryGetValue(localization, out string value); string text = loadedTexts[value][key]; if (PlaceholderProcessors.TryGetValue(key, out Dictionary<string, Func<string>> value2)) { text = value2.Aggregate(text, (string current, KeyValuePair<string, Func<string>> kv) => current.Replace("{" + kv.Key + "}", kv.Value())); } localization.AddWord(key, text); } public static void AddPlaceholder<T>(string key, string placeholder, ConfigEntry<T> config, Func<T, string>? convertConfigValue = null) where T : notnull { if (convertConfigValue == null) { convertConfigValue = (T val) => val.ToString(); } if (!PlaceholderProcessors.ContainsKey(key)) { PlaceholderProcessors[key] = new Dictionary<string, Func<string>>(); } config.SettingChanged += delegate { UpdatePlaceholder(); }; if (loadedTexts.ContainsKey(Localization.instance.GetSelectedLanguage())) { UpdatePlaceholder(); } void UpdatePlaceholder() { PlaceholderProcessors[key][placeholder] = () => convertConfigValue(config.Value); UpdatePlaceholderText(Localization.instance, key); } } public static void AddText(string key, string text) { List<WeakReference<Localization>> list = new List<WeakReference<Localization>>(); foreach (WeakReference<Localization> localizationObject in localizationObjects) { if (localizationObject.TryGetTarget(out var target)) { Dictionary<string, string> dictionary = loadedTexts[localizationLanguage.GetOrCreateValue(target)]; if (!target.m_translations.ContainsKey(key)) { dictionary[key] = text; target.AddWord(key, text); } } else { list.Add(localizationObject); } } foreach (WeakReference<Localization> item in list) { localizationObjects.Remove(item); } } public static void Load() { _ = plugin; } public static void LoadLocalizationLater(Localization __instance) { LoadLocalization(Localization.instance, __instance.GetSelectedLanguage()); } public static void SafeCallLocalizeComplete() { Localizer.OnLocalizationComplete?.Invoke(); } private static void LoadLocalization(Localization __instance, string language) { if (!localizationLanguage.Remove(__instance)) { localizationObjects.Add(new WeakReference<Localization>(__instance)); } localizationLanguage.Add(__instance, language); Dictionary<string, string> dictionary = new Dictionary<string, string>(); foreach (string item in from f in Directory.GetFiles(Path.GetDirectoryName(Paths.PluginPath), plugin.Info.Metadata.Name + ".*", SearchOption.AllDirectories) where fileExtensions.IndexOf(Path.GetExtension(f)) >= 0 select f) { string text = Path.GetFileNameWithoutExtension(item).Split(new char[1] { '.' })[1]; if (dictionary.ContainsKey(text)) { Debug.LogWarning((object)("Duplicate key " + text + " found for " + plugin.Info.Metadata.Name + ". The duplicate file found at " + item + " will be skipped.")); } else { dictionary[text] = item; } } byte[] array = LoadTranslationFromAssembly("English"); if (array == null) { throw new Exception("Found no English localizations in mod " + plugin.Info.Metadata.Name + ". Expected an embedded resource translations/English.json or translations/English.yml."); } Dictionary<string, string> dictionary2 = new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(Encoding.UTF8.GetString(array)); if (dictionary2 == null) { throw new Exception("Localization for mod " + plugin.Info.Metadata.Name + " failed: Localization file was empty."); } string text2 = null; if (language != "English") { if (dictionary.TryGetValue(language, out var value)) { text2 = File.ReadAllText(value); } else { byte[] array2 = LoadTranslationFromAssembly(language); if (array2 != null) { text2 = Encoding.UTF8.GetString(array2); } } } if (text2 == null && dictionary.TryGetValue("English", out var value2)) { text2 = File.ReadAllText(value2); } if (text2 != null) { foreach (KeyValuePair<string, string> item2 in new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(text2) ?? new Dictionary<string, string>()) { dictionary2[item2.Key] = item2.Value; } } loadedTexts[language] = dictionary2; foreach (KeyValuePair<string, string> item3 in dictionary2) { UpdatePlaceholderText(__instance, item3.Key); } } static Localizer() { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Expected O, but got Unknown //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected O, but got Unknown PlaceholderProcessors = new Dictionary<string, Dictionary<string, Func<string>>>(); loadedTexts = new Dictionary<string, Dictionary<string, string>>(); localizationLanguage = new ConditionalWeakTable<Localization, string>(); localizationObjects = new List<WeakReference<Localization>>(); fileExtensions = new List<string>(2) { ".json", ".yml" }; Harmony val = new Harmony("org.bepinex.helpers.LocalizationManager"); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Localization), "SetupLanguage", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalization", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "SetupGui", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalizationLater", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "Start", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "SafeCallLocalizeComplete", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } private static byte[]? LoadTranslationFromAssembly(string language) { foreach (string fileExtension in fileExtensions) { byte[] array = ReadEmbeddedFileBytes("translations." + language + fileExtension); if (array != null) { return array; } } return null; } public static byte[]? ReadEmbeddedFileBytes(string resourceFileName, Assembly? containingAssembly = null) { using MemoryStream memoryStream = new MemoryStream(); if ((object)containingAssembly == null) { containingAssembly = Assembly.GetCallingAssembly(); } string text = containingAssembly.GetManifestResourceNames().FirstOrDefault((string str) => str.EndsWith(resourceFileName, StringComparison.Ordinal)); if (text != null) { containingAssembly.GetManifestResourceStream(text)?.CopyTo(memoryStream); } return (memoryStream.Length == 0L) ? null : memoryStream.ToArray(); } } } namespace ItemDataManager { [PublicAPI] public abstract class ItemData { internal static WeakReference<ItemInfo> constructingInfo = null; internal WeakReference<ItemInfo>? info; private static readonly FieldInfo parameterInfoClassImpl = AccessTools.DeclaredField(typeof(ParameterInfo), "ClassImpl"); private static Dictionary<Type, Dictionary<string, FieldInfo>> serializedFields = new Dictionary<Type, Dictionary<string, FieldInfo>>(); public string CustomDataKey { get; internal set; } protected virtual bool AllowStackingIdenticalValues { get; set; } public string Value { get { if (!Item.m_customData.TryGetValue(CustomDataKey, out var value)) { return ""; } return value; } set { Item.m_customData[CustomDataKey] = value; } } public string Key { get; internal set; } public bool IsCloned => Info.isCloned.Contains(CustomDataKey); public bool IsAlive { get { ItemInfo target; return (info ?? constructingInfo).TryGetTarget(out target); } } public ItemData Item => Info.ItemData; public ItemInfo Info { get { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown if (!(info ?? constructingInfo).TryGetTarget(out ItemInfo target)) { return new ItemInfo(new ItemData()); } return target; } } public virtual void FirstLoad() { } public virtual void Load() { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown Dictionary<string, FieldInfo> dictionary = fetchSerializedFields(); if (dictionary == null || dictionary.Count <= 0 || Value == "") { return; } List<object> list = new List<object>(); string[] array = Value.Split(new char[1] { '|' }); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(new char[1] { ':' }); if (array2.Length == 2 && dictionary.TryGetValue(array2[0], out var value)) { ZPackage val = new ZPackage(array2[1]); ParameterInfo parameterInfo = (ParameterInfo)FormatterServices.GetUninitializedObject(typeof(ParameterInfo)); parameterInfoClassImpl.SetValue(parameterInfo, value.FieldType); list.Clear(); ZRpc.Deserialize(new ParameterInfo[2] { null, parameterInfo }, val, ref list); if (list.Count > 0) { value.SetValue(this, list[0]); } } } } public virtual void Save() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown Dictionary<string, FieldInfo> dictionary = fetchSerializedFields(); if (dictionary == null || dictionary.Count <= 0) { return; } StringBuilder stringBuilder = new StringBuilder(); foreach (FieldInfo value in dictionary.Values) { ZPackage val = new ZPackage(); ZRpc.Serialize(new object[1] { value.GetValue(this) }, ref val); stringBuilder.Append(value.Name); stringBuilder.Append(':'); stringBuilder.Append(val.GetBase64()); stringBuilder.Append('|'); } int length = stringBuilder.Length - 1; stringBuilder.Length = length; Value = stringBuilder.ToString(); } public virtual void Unload() { } public virtual void Upgraded() { } public virtual string? TryStack(ItemData? data) { if (!AllowStackingIdenticalValues || !(data?.Value == Value)) { return null; } return Value; } private Dictionary<string, FieldInfo> fetchSerializedFields() { Type type = GetType(); if (serializedFields.TryGetValue(type, out Dictionary<string, FieldInfo> value)) { return value; } return serializedFields[type] = (from f in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) where f.GetCustomAttributes(typeof(SerializeField), inherit: true).Length != 0 select f).ToDictionary((FieldInfo f) => f.Name, (FieldInfo f) => f); } } public sealed class StringItemData : ItemData { } [PublicAPI] public class ItemInfo : IEnumerable<ItemData>, IEnumerable { public static HashSet<Type> ForceLoadTypes; internal static string? _modGuid; private static Dictionary<Type, HashSet<Type>> typeInheritorsCache; private static HashSet<string> knownTypes; private Dictionary<string, ItemData> data = new Dictionary<string, ItemData>(); private WeakReference<ItemInfo>? selfReference; internal HashSet<string> isCloned = new HashSet<string>(); private static ItemData? awakeningItem; private static Assembly primaryAssembly; private static Dictionary<Assembly, string> assemblyNameCache; private static Dictionary<Type, string> classKeyCache; private HashSet<string> fetchedClassKeys = new HashSet<string>(); private static MethodInfo removeMethod; private static ItemData? checkingForStackableItemData; private static Dictionary<string, string>? newValuesOnStackable; private static ItemData? currentlyUpgradingItem; internal static string modGuid => _modGuid ?? (_modGuid = ((Func<string>)delegate { //IL_0091: Unknown result type (might be due to invalid IL or missing references) IEnumerable<TypeInfo> source; try { source = Assembly.GetExecutingAssembly().DefinedTypes.ToList(); } catch (ReflectionTypeLoadException ex) { source = from t in ex.Types where t != null select t.GetTypeInfo(); } return ((BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First((TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t)))).Info.Metadata.GUID; })()); public string Mod => modGuid; public ItemData ItemData { get; private set; } public string? this[string key] { get { return Get<StringItemData>(key)?.Value; } set { GetOrCreate<StringItemData>(key).Value = value ?? ""; } } internal static void addTypeToInheritorsCache(Type type, string typeKey) { if (!knownTypes.Contains(typeKey)) { knownTypes.Add(typeKey); Type type2 = type; while ((object)type2 != null) { AddInterfaces(type2); type2 = type2.BaseType; } } void AddInterfaces(Type baseType) { if (!typeInheritorsCache.TryGetValue(baseType, out HashSet<Type> value)) { HashSet<Type> hashSet = (typeInheritorsCache[baseType] = new HashSet<Type>()); value = hashSet; } value.Add(type); Type[] interfaces = baseType.GetInterfaces(); for (int i = 0; i < interfaces.Length; i++) { AddInterfaces(interfaces[i]); } } } private static string cachedAssemblyName(Assembly assembly) { if (assemblyNameCache.TryGetValue(assembly, out string value)) { return value; } return assemblyNameCache[assembly] = assembly.GetName().Name; } internal static string classKey(Type type, string key) { if (!classKeyCache.TryGetValue(type, out string value)) { value = type.FullName + ((type.Assembly != primaryAssembly) ? ("," + cachedAssemblyName(type.Assembly)) : ""); addTypeToInheritorsCache(type, value); } if (key == "") { return value; } return value + "#" + key; } internal static string dataKey(string key) { return modGuid + "#" + key; } internal ItemInfo(ItemData itemData) { ItemData = itemData; string text = dataKey(""); foreach (string item in ItemData.m_customData.Keys.ToList()) { if (!item.StartsWith(text)) { continue; } string[] array = item.Substring(text.Length).Split(new char[1] { '#' }, 2); if (!knownTypes.Contains(array[0])) { Type type = Type.GetType(array[0]); if ((object)type != null && typeof(ItemData).IsAssignableFrom(type)) { addTypeToInheritorsCache(type, array[0]); } } } } public T GetOrCreate<T>(string key = "") where T : ItemData, new() { return Add<T>(key) ?? Get<T>(key); } public T? Add<T>(string key = "") where T : ItemData, new() { string text = classKey(typeof(T), key); if (fetchedClassKeys.Contains(text) && data.ContainsKey(text)) { return null; } string text2 = dataKey(text); if (ItemData.m_customData.ContainsKey(text2) || (awakeningItem != ItemData && data.ContainsKey(text))) { return null; } ItemData.m_customData[text2] = ""; ItemDataManager.ItemData.constructingInfo = selfReference ?? (selfReference = new WeakReference<ItemInfo>(this)); T val = new T { info = selfReference, Key = key, CustomDataKey = text2 }; data[text] = val; val.Value = ""; val.FirstLoad(); return val; } public T? Get<T>(string key = "") where T : class { if (!typeInheritorsCache.TryGetValue(typeof(T), out HashSet<Type> value)) { if (!typeof(ItemData).IsAssignableFrom(typeof(T)) || typeof(T) == typeof(ItemData)) { throw new Exception("Trying to get value from ItemDataManager for class not inheriting from ItemData"); } return null; } foreach (Type item in value) { string text = classKey(item, key); if (data.TryGetValue(text, out ItemData value2)) { return (T)(object)value2; } if (!fetchedClassKeys.Contains(text) && awakeningItem != ItemData) { string text2 = dataKey(text); fetchedClassKeys.Add(text); if (ItemData.m_customData.ContainsKey(text2)) { return (T)(object)constructDataObj(text2, text); } } } return null; } public Dictionary<string, T> GetAll<T>() where T : ItemData { LoadAll(); return data.Values.Where((ItemData o) => o is T).ToDictionary((ItemData o) => o.Key, (ItemData o) => (T)o); } public bool Remove(string key = "") { return Remove<StringItemData>(key); } public bool Remove<T>(string key = "") where T : ItemData { string key2 = classKey(typeof(T), key); string key3 = dataKey(key2); if (ItemData.m_customData.Remove(key3)) { if (data.TryGetValue(key2, out ItemData value)) { value.Unload(); data.Remove(key2); } return true; } return false; } public bool Remove<T>(T itemData) where T : ItemData { if (typeof(T) == itemData.GetType()) { return Remove<T>(itemData.Key); } return (bool)removeMethod.MakeGenericMethod(itemData.GetType()).Invoke(this, new object[1] { itemData.Key }); } private ItemData? constructDataObj(string fullkey, string key) { string[] array = key.Split(new char[1] { '#' }, 2); Type type = Type.GetType(array[0]); if ((object)type == null || !typeof(ItemData).IsAssignableFrom(type)) { return null; } ItemDataManager.ItemData.constructingInfo = selfReference ?? (selfReference = new WeakReference<ItemInfo>(this)); ItemData itemData = (ItemData)Activator.CreateInstance(type); data[key] = itemData; itemData.info = selfReference; itemData.Key = ((array.Length > 1) ? array[1] : ""); itemData.CustomDataKey = fullkey; itemData.Load(); return itemData; } public void Save() { foreach (ItemData value in data.Values) { value.Save(); } } public void LoadAll() { if (awakeningItem == ItemData) { return; } string text = dataKey(""); foreach (string item in ItemData.m_customData.Keys.ToList()) { if (item.StartsWith(text)) { string key = item.Substring(text.Length); if (!data.ContainsKey(key)) { constructDataObj(item, key); } } } } public IEnumerator<ItemData> GetEnumerator() { LoadAll(); return data.Values.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } private static void SavePrefix(ItemData __instance) { SaveItem(__instance); } private static void SaveInventoryPrefix(Inventory __instance) { foreach (ItemData item in __instance.m_inventory) { SaveItem(item); } } private static void SaveItem(ItemData item) { if (ItemExtensions.itemInfo.TryGetValue(item, out ItemInfo value)) { value.Save(); } } public Dictionary<string, string>? IsStackableWithOtherInfo(ItemInfo? info) { LoadAll(); Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (info != null) { info.LoadAll(); foreach (string item in new HashSet<string>(info.data.Keys.Intersect(data.Keys))) { string text = data[item].TryStack(info.data[item]); if (text == null) { return null; } dictionary[item] = text; } foreach (KeyValuePair<string, ItemData> datum in info.data) { if (!dictionary.ContainsKey(datum.Key)) { string text2 = info.data[datum.Key].TryStack(null); if (text2 == null) { return null; } dictionary[datum.Key] = text2; } } } foreach (KeyValuePair<string, ItemData> datum2 in data) { if (!dictionary.ContainsKey(datum2.Key)) { string text3 = data[datum2.Key].TryStack(null); if (text3 == null) { return null; } dictionary[datum2.Key] = text3; } } return dictionary.ToDictionary((KeyValuePair<string, string> kv) => dataKey(kv.Key), (KeyValuePair<string, string> kv) => kv.Value); } private static void RegisterForceLoadedTypesAddItem(ItemData? __result) { awakeningItem = null; if (__result != null) { RegisterForceLoadedTypes(__result); } } private static void RegisterForceLoadedTypes(ItemData itemData) { foreach (Type forceLoadType in ForceLoadTypes) { string key = classKey(forceLoadType, ""); string text = dataKey(key); if (itemData.m_customData.ContainsKey(text)) { ItemInfo itemInfo = itemData.Data(); if (!itemInfo.data.ContainsKey(key)) { itemInfo.constructDataObj(text, key); } } } } private static void ItemDropAwake(ItemDrop __instance) { GameObject dropPrefab = __instance.m_itemData.m_dropPrefab; if (dropPrefab == null || !ItemExtensions.itemInfo.TryGetValue(dropPrefab.GetComponent<ItemDrop>().m_itemData, out ItemInfo value)) { return; } ItemInfo itemInfo = __instance.m_itemData.Data(); HashSet<string> hashSet = new HashSet<string>(); foreach (string item in value.data.Values.Select((ItemData i) => i.CustomDataKey)) { hashSet.Add(item); } itemInfo.isCloned = hashSet; } private static void ItemDropAwakeDelayed(ItemDrop __instance) { if (!ZNetView.m_forceDisableInit) { RegisterForceLoadedTypes(__instance.m_itemData); } } private static void ItemDataClonePrefix(ItemData __instance, ItemData __result) { SaveItem(__instance); } private static void ItemDataClonePostfix(ItemData __instance, ItemData __result) { if (!ItemExtensions.itemInfo.TryGetValue(__instance, out ItemInfo value)) { return; } ItemInfo itemInfo = __result.Data(); HashSet<string> hashSet = new HashSet<string>(); foreach (string item in value.data.Values.Select((ItemData i) => i.CustomDataKey)) { hashSet.Add(item); } itemInfo.isCloned = hashSet; } private static void ItemDataClonePostfixDelayed(ItemData __result) { RegisterForceLoadedTypes(__result); } private static void RegisterForceLoadedTypesOnPlayerLoaded(Player __instance) { foreach (Food food in __instance.m_foods) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(food.m_name); if (itemPrefab.GetComponent<ItemDrop>().m_itemData == food.m_item) { food.m_item = food.m_item.Clone(); food.m_item.m_dropPrefab = itemPrefab; } RegisterForceLoadedTypes(food.m_item); } } private static void SaveCheckingForStackableItemData(ItemData item) { if (item == awakeningItem) { awakeningItem = null; } checkingForStackableItemData = item; } private static void ResetCheckingForStackableItemData() { checkingForStackableItemData = null; } private static IEnumerable<CodeInstruction> CheckStackableInFindFreeStackMethods(IEnumerable<CodeInstruction> instructionsEnumerable) { CodeInstruction[] instructions = instructionsEnumerable.ToArray(); Label target = (Label)instructions.First((CodeInstruction val) => val.opcode == OpCodes.Br || val.opcode == OpCodes.Br_S).operand; CodeInstruction targetedInstr = instructions.First((CodeInstruction val) => val.labels.Contains(target)); Label? label = default(Label?); CodeInstruction lastBranch = instructions.Reverse().First((CodeInstruction val) => CodeInstructionExtensions.Branches(val, ref label) && targetedInstr.labels.Contains(label.Value)); CodeInstruction loadingInstruction = null; int i = 0; while (i < instructions.Length) { yield return instructions[i]; if (loadingInstruction == null && instructions[i].opcode == OpCodes.Call && ((MethodInfo)instructions[i].operand).Name == "get_Current") { loadingInstruction = instructions[i + 1].Clone(); loadingInstruction.opcode = new Dictionary<OpCode, OpCode> { { OpCodes.Stloc_0, OpCodes.Ldloc_0 }, { OpCodes.Stloc_1, OpCodes.Ldloc_1 }, { OpCodes.Stloc_2, OpCodes.Ldloc_2 }, { OpCodes.Stloc_3, OpCodes.Ldloc_3 }, { OpCodes.Stloc_S, OpCodes.Ldloc_S } }[loadingInstruction.opcode]; } if (instructions[i] == lastBranch) { yield return loadingInstruction; yield return new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.DeclaredField(typeof(ItemInfo), "checkingForStackableItemData")); yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(ItemInfo), "CheckItemDataIsStackableFindFree", (Type[])null, (Type[])null)); yield return new CodeInstruction(OpCodes.Brfalse, (object)target); } int num = i + 1; i = num; } } private static bool CheckItemDataIsStackableFindFree(ItemData item, ItemData? target) { if (target == null) { return true; } Dictionary<string, string> dictionary = IsStackable(item, target); if (dictionary != null) { newValuesOnStackable = dictionary; return true; } return false; } private static void ResetNewValuesOnStackable() { newValuesOnStackable = null; } private static void ApplyNewValuesOnStackable(ItemData? __result) { if (__result == null || newValuesOnStackable == null) { return; } foreach (KeyValuePair<string, string> item in newValuesOnStackable) { __result.m_customData[item.Key] = item.Value; } } private static Dictionary<string, string>? IsStackable(ItemData a, ItemData b) { ItemInfo itemInfo = a.Data(); if (itemInfo != null) { return itemInfo.IsStackableWithOtherInfo(b.Data()); } ItemInfo itemInfo2 = b.Data(); if (itemInfo2 != null) { return itemInfo2.IsStackableWithOtherInfo(null); } return new Dictionary<string, string>(); } private static bool CheckItemDataStackableAddItem(Inventory __instance, ItemData item, int x, int y, ref Dictionary<string, string>? __state, ref bool __result) { ItemData itemAt = __instance.GetItemAt(x, y); if (itemAt != null) { Dictionary<string, string> dictionary = IsStackable(item, itemAt); if (dictionary == null) { __result = false; return false; } __state = dictionary; } return true; } private static void ApplyCustomItemDataStackableAddItem(Inventory __instance, int x, int y, Dictionary<string, string>? __state, bool __result) { if (!__result || __state == null) { return; } foreach (KeyValuePair<string, string> item in __state) { __instance.GetItemAt(x, y).m_customData[item.Key] = item.Value; } } private static void ApplyCustomItemDataStackableAutoStack(ItemDrop item, Dictionary<string, string> customData) { item.m_itemData.m_customData = customData; } private static Dictionary<string, string>? IsStackableItemDrop(ItemDrop drop, ItemData item) { return IsStackable(drop.m_itemData, item); } private static IEnumerable<CodeInstruction> HandleAutostackableItems(IEnumerable<CodeInstruction> instructionList, ILGenerator ilg) { //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Expected O, but got Unknown //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Expected O, but got Unknown //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Expected O, but got Unknown //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Expected O, but got Unknown //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Expected O, but got Unknown //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Expected O, but got Unknown //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Expected O, but got Unknown //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Expected O, but got Unknown //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Expected O, but got Unknown //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Expected O, but got Unknown //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Expected O, but got Unknown List<CodeInstruction> list = instructionList.ToList(); FieldInfo fieldInfo = AccessTools.DeclaredField(typeof(ItemData), "m_stack"); FieldInfo fieldInfo2 = AccessTools.DeclaredField(typeof(ItemDrop), "m_itemData"); Label? label = default(Label?); for (int i = 0; i < list.Count; i++) { if (!CodeInstructionExtensions.StoresField(list[i], fieldInfo)) { continue; } for (int num = i; num > 0; num--) { if (CodeInstructionExtensions.Branches(list[num], ref label)) { for (int num2 = num; num2 > 0; num2--) { if (CodeInstructionExtensions.LoadsField(list[num2], fieldInfo2, false)) { LocalBuilder localBuilder = ilg.DeclareLocal(typeof(Dictionary<string, string>)); LocalBuilder localBuilder2 = ilg.DeclareLocal(typeof(ItemData)); list.Insert(i + 1, new CodeInstruction(OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(ItemInfo), "ApplyCustomItemDataStackableAutoStack", (Type[])null, (Type[])null))); list.Insert(i + 1, new CodeInstruction(OpCodes.Ldloc, (object)localBuilder.LocalIndex)); list.Insert(i + 1, new CodeInstruction(OpCodes.Ldarg_0, (object)null)); list.Insert(num + 1, new CodeInstruction(OpCodes.Brfalse, (object)label)); list.Insert(num + 1, new CodeInstruction(OpCodes.Stloc, (object)localBuilder.LocalIndex)); list.Insert(num + 1, new CodeInstruction(OpCodes.Dup, (object)localBuilder.LocalIndex)); list.Insert(num + 1, new CodeInstruction(OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(ItemInfo), "IsStackableItemDrop", (Type[])null, (Type[])null))); list.Insert(num + 1, new CodeInstruction(OpCodes.Ldloc, (object)localBuilder2.LocalIndex)); list.Insert(num + 1, new CodeInstruction(OpCodes.Ldarg_0, (object)null)); list.Insert(num2 + 1, new CodeInstruction(OpCodes.Stloc, (object)localBuilder2.LocalIndex)); list.Insert(num2 + 1, new CodeInstruction(OpCodes.Dup, (object)null)); return list; } } } } } throw new Exception("Found no stack store in a branch"); } private static IEnumerable<CodeInstruction> TransferCustomItemDataOnUpgrade(IEnumerable<CodeInstruction> instructions, ILGenerator ilg) { MethodInfo itemDeleter = AccessTools.DeclaredMethod(typeof(Inventory), "RemoveItem", new Type[1] { typeof(ItemData) }, (Type[])null); foreach (CodeInstruction instruction in instructions) { if (instruction.opcode == OpCodes.Callvirt && CodeInstructionExtensions.OperandIs(instruction, (MemberInfo)itemDeleter)) { yield return new CodeInstruction(OpCodes.Dup, (object)null); yield return new CodeInstruction(OpCodes.Stsfld, (object)AccessTools.DeclaredField(typeof(ItemInfo), "currentlyUpgradingItem")); } yield return instruction; } } private static void ResetCurrentlyUpgradingItem() { currentlyUpgradingItem = null; } private static void CopyCustomDataFromUpgradedItem(ItemDrop item) { if (currentlyUpgradingItem != null) { item.m_itemData.m_customData = currentlyUpgradingItem.m_customData; ItemInfo itemInfo = currentlyUpgradingItem.Data(); ItemExtensions.itemInfo.Remove(currentlyUpgradingItem); ItemExtensions.itemInfo.Add(item.m_itemData, itemInfo); item.m_itemData.m_quality = currentlyUpgradingItem.m_quality + 1; item.m_itemData.m_variant = currentlyUpgradingItem.m_variant; itemInfo.ItemData = item.m_itemData; itemInfo.LoadAll(); foreach (ItemData value in itemInfo.data.Values) { value.Upgraded(); } currentlyUpgradingItem = null; awakeningItem = null; return; } GameObject dropPrefab = item.m_itemData.m_dropPrefab; if (dropPrefab == null || item.m_itemData.m_customData.Count != 0) { return; } ZNetView component = ((Component)item).GetComponent<ZNetView>(); ZDO val = ((Object.op_Implicit((Object)(object)component) && component.IsValid()) ? component.GetZDO() : null); if (val != null && val.GetInt(ZDOVars.s_dataCount, -1) != -1) { return; } item.m_itemData.m_customData = new Dictionary<string, string>(dropPrefab.GetComponent<ItemDrop>().m_itemData.m_customData); if (val == null) { return; } int num = 0; val.Set(ZDOVars.s_dataCount, item.m_itemData.m_customData.Count, false); foreach (KeyValuePair<string, string> customDatum in item.m_itemData.m_customData) { val.Set($"data_{num}", customDatum.Key); val.Set($"data__{++num}", customDatum.Value); } } private static IEnumerable<CodeInstruction> ImportCustomDataOnUpgrade(IEnumerable<CodeInstruction> instructionList) { List<CodeInstruction> list = instructionList.ToList(); foreach (CodeInstruction instruction in list) { yield return instruction; if (instruction.opcode == OpCodes.Stfld && CodeInstructionExtensions.OperandIs(instruction, (MemberInfo)AccessTools.DeclaredField(typeof(ItemData), "m_dropPrefab"))) { yield return new CodeInstruction(OpCodes.Ldarg_0, (object)null); yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(ItemInfo), "CopyCustomDataFromUpgradedItem", (Type[])null, (Type[])null)); } } } private static void TrackAwakeningItem(ItemDrop __instance) { if (ZNetView.m_forceDisableInit) { awakeningItem = __instance.m_itemData; } } static ItemInfo() { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Expected O, but got Unknown //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Expected O, but got Unknown //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Expected O, but got Unknown //IL_01d0: Expected O, but got Unknown //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Expected O, but got Unknown //IL_023f: Expected O, but got Unknown //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_0296: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Expected O, but got Unknown //IL_02a1: Expected O, but got Unknown //IL_02ee: Unknown result type (might be due to invalid IL or missing references) //IL_0305: Unknown result type (might be due to invalid IL or missing references) //IL_0310: Expected O, but got Unknown //IL_0310: Expected O, but got Unknown //IL_0340: Unknown result type (might be due to invalid IL or missing references) //IL_034c: Expected O, but got Unknown //IL_037a: Unknown result type (might be due to invalid IL or missing references) //IL_0381: Expected O, but got Unknown //IL_0397: Unknown result type (might be due to invalid IL or missing references) //IL_03b2: Unknown result type (might be due to invalid IL or missing references) //IL_03c0: Expected O, but got Unknown //IL_03c0: Expected O, but got Unknown //IL_03f0: Unknown result type (might be due to invalid IL or missing references) //IL_03fc: Expected O, but got Unknown //IL_042c: Unknown result type (might be due to invalid IL or missing references) //IL_0447: Unknown result type (might be due to invalid IL or missing references) //IL_0452: Expected O, but got Unknown //IL_0452: Expected O, but got Unknown //IL_04a3: Unknown result type (might be due to invalid IL or missing references) //IL_04b0: Expected O, but got Unknown //IL_0503: Unknown result type (might be due to invalid IL or missing references) //IL_0510: Expected O, but got Unknown //IL_05bc: Unknown result type (might be due to invalid IL or missing references) //IL_05c9: Expected O, but got Unknown //IL_05f7: Unknown result type (might be due to invalid IL or missing references) //IL_0622: Unknown result type (might be due to invalid IL or missing references) //IL_0629: Expected O, but got Unknown //IL_064f: Unknown result type (might be due to invalid IL or missing references) //IL_065d: Expected O, but got Unknown //IL_065d: Expected O, but got Unknown //IL_069c: Unknown result type (might be due to invalid IL or missing references) //IL_06a9: Expected O, but got Unknown //IL_06d7: Unknown result type (might be due to invalid IL or missing references) //IL_0702: Unknown result type (might be due to invalid IL or missing references) //IL_070f: Expected O, but got Unknown //IL_070f: Expected O, but got Unknown //IL_074e: Unknown result type (might be due to invalid IL or missing references) //IL_075b: Expected O, but got Unknown ForceLoadTypes = new HashSet<Type>(); typeInheritorsCache = new Dictionary<Type, HashSet<Type>>(); knownTypes = new HashSet<string>(); awakeningItem = null; primaryAssembly = Assembly.GetExecutingAssembly(); assemblyNameCache = new Dictionary<Assembly, string>(); classKeyCache = new Dictionary<Type, string>(); removeMethod = typeof(ItemInfo).GetMethods().Single((MethodInfo m) => m.Name == "Remove" && m.IsGenericMethod && m.GetParameters()[0].ParameterType == typeof(string)); Harmony val = new Harmony("org.bepinex.helpers.ItemDataManager"); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Inventory), "Save", (Type[])null, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "SaveInventoryPrefix", (Type[])null, (Type[])null), 800, (string[])null, (string[])null, (bool?)null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); foreach (MethodInfo item in from m in typeof(ItemData).GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) where m.Name == "SaveToZDO" select m) { val.Patch((MethodBase)item, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "SavePrefix", (Type[])null, (Type[])null), 800, (string[])null, (string[])null, (bool?)null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Inventory), "AddItem", new Type[4] { typeof(ItemData), typeof(int), typeof(int), typeof(int) }, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "CheckItemDataStackableAddItem", (Type[])null, (Type[])null)), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "ApplyCustomItemDataStackableAddItem", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Inventory), "CanAddItem", new Type[2] { typeof(ItemData), typeof(int) }, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "SaveCheckingForStackableItemData", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(ItemInfo), "ResetCheckingForStackableItemData", (Type[])null), (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Inventory), "AddItem", new Type[1] { typeof(ItemData) }, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "SaveCheckingForStackableItemData", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(ItemInfo), "ResetCheckingForStackableItemData", (Type[])null), (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Inventory), "AddItem", new Type[2] { typeof(ItemData), typeof(Vector2i) }, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "SaveCheckingForStackableItemData", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(ItemInfo), "ResetCheckingForStackableItemData", (Type[])null), (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Inventory), "FindFreeStackSpace", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "CheckStackableInFindFreeStackMethods", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null); MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(Inventory), "FindFreeStackItem", (Type[])null, (Type[])null); HarmonyMethod val2 = new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "CheckStackableInFindFreeStackMethods", (Type[])null, (Type[])null)); val.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "ResetNewValuesOnStackable", (Type[])null, (Type[])null)), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "ApplyNewValuesOnStackable", (Type[])null, (Type[])null)), val2, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(ItemDrop), "AutoStackItems", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "HandleAutostackableItems", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(InventoryGui), "DoCrafting", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "TransferCustomItemDataOnUpgrade", (Type[])null, (Type[])null)), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "ResetCurrentlyUpgradingItem", (Type[])null, (Type[])null)), (HarmonyMethod)null); foreach (MethodInfo item2 in from m in typeof(ItemData).GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) where m.Name == "LoadFromZDO" select m) { val.Patch((MethodBase)item2, (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "RegisterForceLoadedTypes", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Player), "Load", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "RegisterForceLoadedTypesOnPlayerLoaded", (Type[])null, (Type[])null), 700, (string[])null, (string[])null, (bool?)null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Inventory), "AddItem", new Type[8] { typeof(string), typeof(int), typeof(int), typeof(int), typeof(long), typeof(string), typeof(Vector2i), typeof(bool) }, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "RegisterForceLoadedTypesAddItem", (Type[])null, (Type[])null), 800, (string[])null, (string[])null, (bool?)null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); MethodInfo methodInfo2 = AccessTools.DeclaredMethod(typeof(ItemDrop), "Awake", (Type[])null, (Type[])null); HarmonyMethod val3 = new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "TrackAwakeningItem", (Type[])null, (Type[])null)); val2 = new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "ImportCustomDataOnUpgrade", (Type[])null, (Type[])null), 800, (string[])null, (string[])null, (bool?)null); val.Patch((MethodBase)methodInfo2, val3, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "ItemDropAwake", (Type[])null, (Type[])null), 800, (string[])null, (string[])null, (bool?)null), val2, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(ItemDrop), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "ItemDropAwakeDelayed", (Type[])null, (Type[])null), 799, (string[])null, (string[])null, (bool?)null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(ItemData), "Clone", (Type[])null, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "ItemDataClonePrefix", (Type[])null, (Type[])null)), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "ItemDataClonePostfix", (Type[])null, (Type[])null), 500, (string[])null, (string[])null, (bool?)null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(ItemData), "Clone", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "ItemDataClonePostfixDelayed", (Type[])null, (Type[])null), 499, (string[])null, (string[])null, (bool?)null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } [PublicAPI] public class ForeignItemInfo : IEnumerable<object>, IEnumerable { private readonly object foreignItemInfo; public string Mod => ((string)foreignItemInfo.GetType().GetProperty("Mod")?.GetValue(foreignItemInfo)) ?? ""; public ItemData ItemData { get; private set; } public string? this[string key] { get { object obj = foreignItemInfo.GetType().InvokeMember("Item", BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty, null, foreignItemInfo, new object[1] { key }); if (obj != null) { return (string)obj.GetType().GetProperty("Value")?.GetValue(obj); } return null; } set { foreignItemInfo.GetType().GetMethod("set_Item", BindingFlags.Instance | BindingFlags.Public)?.Invoke(foreignItemInfo, new object[2] { key, value }); } } internal ForeignItemInfo(ItemData itemData, object foreignItemInfo) { ItemData = itemData; this.foreignItemInfo = foreignItemInfo; } public T GetOrCreate<T>(string key = "") where T : class, new() { return Add<T>(key) ?? Get<T>(key); } private object? call(string name, object?[] values, Type?[] args, Type? generic = null) { MethodInfo[] methods = foreignItemInfo.GetType().GetMethods(); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name == name && (from p in methodInfo.GetParameters() select (!p.ParameterType.IsGenericParameter) ? p.ParameterType : null).SequenceEqual<Type>(args) && (object)generic != null == methodInfo.IsGenericMethod) { MethodInfo methodInfo2 = methodInfo; if ((object)generic != null) { methodInfo2 = methodInfo2.MakeGenericMethod(generic); } return methodInfo2.Invoke(foreignItemInfo, values); } } return null; } public T? Add<T>(string key = "") where T : class, new() { return call("Add", new object[1] { key }, new Type[1] { typeof(string) }, typeof(T)) as T; } public T? Get<T>(string key = "") where T : class { return call("Get", new object[1] { key }, new Type[1] { typeof(string) }, typeof(T)) as T; } public Dictionary<string, T> GetAll<T>() where T : class { return ((call("GetAll", Array.Empty<object>(), Array.Empty<Type>(), typeof(T)) as T) as Dictionary<string, T>) ?? new Dictionary<string, T>(); } public bool Remove(string key = "") { return call("Add", new object[1] { key }, new Type[1] { typeof(string) }) as bool? == true; } public bool Remove<T>(string key = "") where T : class { return call("Remove", new object[1] { key }, new Type[1] { typeof(string) }, typeof(T)) as bool? == true; } public bool Remove<T>(T itemData) where T : class { return call("Remove", new object[1] { itemData }, new Type[1], typeof(T)) as bool? == true; } public void Save() { call("Save", Array.Empty<object>(), Array.Empty<Type>()); } public void LoadAll() { call("LoadAll", Array.Empty<object>(), Array.Empty<Type>()); } public IEnumerator<object> GetEnumerator() { return (IEnumerator<object>)((call("GetEnumerator", Array.Empty<object>(), Array.Empty<Type>()) as IEnumerator<object>) ?? ((object)new List<object>().GetEnumerator())); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } [PublicAPI] public static class ItemExtensions { [SpecialName] public sealed class <G>$89A7D4A522B437A8B95320B2CAC6531E { [SpecialName] public static class <M>$091BBA0B72542A51B2CEA87B8CA8E7DC { } [ExtensionMarker("<M>$091BBA0B72542A51B2CEA87B8CA8E7DC")] public ItemInfo Data() { throw null; } [ExtensionMarker("<M>$091BBA0B72542A51B2CEA87B8CA8E7DC")] public ForeignItemInfo? Data(string mod) { throw null; } } private const string className = "ItemDataManager.ItemExtensions"; internal static readonly ConditionalWeakTable<ItemData, ItemInfo> itemInfo = new ConditionalWeakTable<ItemData, ItemInfo>(); private static readonly ConditionalWeakTable<ItemData, Dictionary<string, ForeignItemInfo?>> foreignItemInfo = new ConditionalWeakTable<ItemData, Dictionary<string, ForeignItemInfo>>(); public static ItemInfo Data(this ItemData item) { if (itemInfo.TryGetValue(item, out ItemInfo value)) { return value; } itemInfo.Add(item, value = new ItemInfo(item)); return value; } public static ForeignItemInfo? Data(this ItemData item, string mod) { Dictionary<string, ForeignItemInfo> orCreateValue = ItemExtensions.foreignItemInfo.GetOrCreateValue(item); if (orCreateValue.TryGetValue(mod, out var value)) { return value; } if (!Chainloader.PluginInfos.TryGetValue(mod,