using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using Backpacks; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using DadsStorage.APIs; using DadsStorage.APIs.Compatibility.WardIsLove; using DadsStorage.APIs.MUC; using DadsStorage.APIs.MUC.MUCSrc.Data; using DadsStorage.APIs.MUC.MUCSrc.Helper; using DadsStorage.APIs.MUC.MUCSrc.Patches; using DadsStorage.APIs.MUC.MUCSrc.Patches.Compatibility; using DadsStorage.Interfaces; using DadsStorage.Patches; using DadsStorage.Patches.Favoriting; using DadsStorage.Util; using HarmonyLib; using ItemDataManager; using JetBrains.Annotations; using Microsoft.CodeAnalysis; using ServerSync; using TMPro; using UnityEngine; using UnityEngine.UI; using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Core.Tokens; using YamlDotNet.Helpers; using YamlDotNet.Serialization; using YamlDotNet.Serialization.BufferedDeserialization; using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators; using YamlDotNet.Serialization.Converters; using YamlDotNet.Serialization.EventEmitters; using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization.NodeDeserializers; using YamlDotNet.Serialization.NodeTypeResolvers; using YamlDotNet.Serialization.ObjectFactories; using YamlDotNet.Serialization.ObjectGraphTraversalStrategies; using YamlDotNet.Serialization.ObjectGraphVisitors; using YamlDotNet.Serialization.Schemas; using YamlDotNet.Serialization.TypeInspectors; using YamlDotNet.Serialization.TypeResolvers; using YamlDotNet.Serialization.Utilities; using YamlDotNet.Serialization.ValueDeserializers; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("DadsStorage")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Dad_Is_Bored")] [assembly: AssemblyProduct("DadsStorage")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("4358610B-F3F4-4843-B7AF-98B7BC60DCDE")] [assembly: AssemblyFileVersion("1.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [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; } } } namespace LocalizationManager { [PublicAPI] public class Localizer { private static readonly Dictionary>> PlaceholderProcessors; private static readonly Dictionary> loadedTexts; private static readonly ConditionalWeakTable localizationLanguage; private static readonly List> localizationObjects; private static BaseUnityPlugin? _plugin; private static readonly List 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 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> value2)) { text = value2.Aggregate(text, (string current, KeyValuePair> kv) => current.Replace("{" + kv.Key + "}", kv.Value())); } localization.AddWord(key, text); } public static void AddPlaceholder(string key, string placeholder, ConfigEntry config, Func? convertConfigValue = null) where T : notnull { if (convertConfigValue == null) { convertConfigValue = (T val) => val.ToString(); } if (!PlaceholderProcessors.ContainsKey(key)) { PlaceholderProcessors[key] = new Dictionary>(); } 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> list = new List>(); foreach (WeakReference localizationObject in localizationObjects) { if (localizationObject.TryGetTarget(out var target)) { Dictionary dictionary = loadedTexts[localizationLanguage.GetOrCreateValue(target)]; if (!target.m_translations.ContainsKey(key)) { dictionary[key] = text; target.AddWord(key, text); } } else { list.Add(localizationObject); } } foreach (WeakReference 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(__instance)); } localizationLanguage.Add(__instance, language); Dictionary dictionary = new Dictionary(); foreach (string item in from f in Directory.GetFiles(Path.GetDirectoryName(Paths.PluginPath), plugin.Info.Metadata.Name + ".*", SearchOption.AllDirectories) where fileExtensions.IndexOf(Path.GetExtension(f)) >= 0 select f) { string[] array = Path.GetFileNameWithoutExtension(item).Split(new char[1] { '.' }); if (array.Length >= 2) { string text = array[1]; if (dictionary.ContainsKey(text)) { Debug.LogWarning((object)("Duplicate key " + text + " found for " + plugin.Info.Metadata.Name + ". The duplicate file found at " + item + " will be skipped.")); } else { dictionary[text] = item; } } } byte[] array2 = LoadTranslationFromAssembly("English"); if (array2 == null) { throw new Exception("Found no English localizations in mod " + plugin.Info.Metadata.Name + ". Expected an embedded resource translations/English.json or translations/English.yml."); } Dictionary dictionary2 = new DeserializerBuilder().IgnoreFields().Build().Deserialize>(Encoding.UTF8.GetString(array2)); if (dictionary2 == null) { throw new Exception("Localization for mod " + plugin.Info.Metadata.Name + " failed: Localization file was empty."); } string text2 = null; if (language != "English") { if (dictionary.TryGetValue(language, out var value)) { text2 = File.ReadAllText(value); } else { byte[] array3 = LoadTranslationFromAssembly(language); if (array3 != null) { text2 = Encoding.UTF8.GetString(array3); } } } if (text2 == null && dictionary.TryGetValue("English", out var value2)) { text2 = File.ReadAllText(value2); } if (text2 != null) { foreach (KeyValuePair item2 in new DeserializerBuilder().IgnoreFields().Build().Deserialize>(text2) ?? new Dictionary()) { dictionary2[item2.Key] = item2.Value; } } loadedTexts[language] = dictionary2; foreach (KeyValuePair 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>>(); loadedTexts = new Dictionary>(); localizationLanguage = new ConditionalWeakTable(); localizationObjects = new List>(); fileExtensions = new List(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(); } } public static class LocalizationManagerVersion { public const string Version = "1.4.1"; } } namespace ItemDataManager { [PublicAPI] public abstract class ItemData { internal static WeakReference<<269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo> constructingInfo = null; internal WeakReference<<269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo>? info; private static readonly FieldInfo parameterInfoClassImpl = AccessTools.DeclaredField(typeof(ParameterInfo), "ClassImpl"); private static Dictionary> serializedFields = new Dictionary>(); 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 { <269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo target; return (info ?? constructingInfo).TryGetTarget(out target); } } public ItemData Item => Info.ItemData; public <269f569e-d242-4b09-8e71-130b4eda4578>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 <269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo target)) { return new <269f569e-d242-4b09-8e71-130b4eda4578>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 dictionary = fetchSerializedFields(); if (dictionary == null || dictionary.Count <= 0 || Value == "") { return; } List list = new List(); 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 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 fetchSerializedFields() { Type type = GetType(); if (serializedFields.TryGetValue(type, out Dictionary 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 <269f569e-d242-4b09-8e71-130b4eda4578>StringItemData : ItemData { } [PublicAPI] public class <269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo : IEnumerable, IEnumerable { public static HashSet ForceLoadTypes; internal static string? _modGuid; private static Dictionary> typeInheritorsCache; private static HashSet knownTypes; private Dictionary data = new Dictionary(); private WeakReference<<269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo>? selfReference; internal HashSet isCloned = new HashSet(); private static ItemData? awakeningItem; private static Assembly primaryAssembly; private static Dictionary assemblyNameCache; private static Dictionary classKeyCache; private HashSet fetchedClassKeys = new HashSet(); private static MethodInfo removeMethod; private static ItemData? checkingForStackableItemData; private static Dictionary? newValuesOnStackable; private static ItemData? currentlyUpgradingItem; internal static string modGuid => _modGuid ?? (_modGuid = ((Func)delegate { //IL_0091: Unknown result type (might be due to invalid IL or missing references) IEnumerable 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<<269f569e-d242-4b09-8e71-130b4eda4578>StringItemData>(key)?.Value; } set { GetOrCreate<<269f569e-d242-4b09-8e71-130b4eda4578>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 value)) { HashSet hashSet = (typeInheritorsCache[baseType] = new HashSet()); 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 <269f569e-d242-4b09-8e71-130b4eda4578>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(string key = "") where T : ItemData, new() { return Add(key) ?? Get(key); } public T? Add(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<<269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo>(this)); T val = new T { info = selfReference, Key = key, CustomDataKey = text2 }; data[text] = val; val.Value = ""; val.FirstLoad(); return val; } public T? Get(string key = "") where T : class { if (!typeInheritorsCache.TryGetValue(typeof(T), out HashSet 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 GetAll() 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<<269f569e-d242-4b09-8e71-130b4eda4578>StringItemData>(key); } public bool Remove(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 itemData) where T : ItemData { if (typeof(T) == itemData.GetType()) { return Remove(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<<269f569e-d242-4b09-8e71-130b4eda4578>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 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 (<269f569e-d242-4b09-8e71-130b4eda4578>ItemExtensions.itemInfo.TryGetValue(item, out <269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo value)) { value.Save(); } } public Dictionary? IsStackableWithOtherInfo(<269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo? info) { LoadAll(); Dictionary dictionary = new Dictionary(); if (info != null) { info.LoadAll(); foreach (string item in new HashSet(info.data.Keys.Intersect(data.Keys))) { string text = data[item].TryStack(info.data[item]); if (text == null) { return null; } dictionary[item] = text; } foreach (KeyValuePair 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 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 kv) => dataKey(kv.Key), (KeyValuePair 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)) { <269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo <269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo2 = <269f569e-d242-4b09-8e71-130b4eda4578>ItemExtensions.Data(itemData); if (!<269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo2.data.ContainsKey(key)) { <269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo2.constructDataObj(text, key); } } } } private static void ItemDropAwake(ItemDrop __instance) { GameObject dropPrefab = __instance.m_itemData.m_dropPrefab; if (dropPrefab != null && <269f569e-d242-4b09-8e71-130b4eda4578>ItemExtensions.itemInfo.TryGetValue(dropPrefab.GetComponent().m_itemData, out <269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo value)) { <269f569e-d242-4b09-8e71-130b4eda4578>ItemExtensions.Data(__instance.m_itemData).isCloned = new HashSet(value.data.Values.Select((ItemData i) => i.CustomDataKey)); } } 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 (<269f569e-d242-4b09-8e71-130b4eda4578>ItemExtensions.itemInfo.TryGetValue(__instance, out <269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo value)) { <269f569e-d242-4b09-8e71-130b4eda4578>ItemExtensions.Data(__result).isCloned = new HashSet(value.data.Values.Select((ItemData i) => i.CustomDataKey)); } } 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().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 CheckStackableInFindFreeStackMethods(IEnumerable 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 { { 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(<269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo), "checkingForStackableItemData")); yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(<269f569e-d242-4b09-8e71-130b4eda4578>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 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 item in newValuesOnStackable) { __result.m_customData[item.Key] = item.Value; } } private static Dictionary? IsStackable(ItemData a, ItemData b) { <269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo <269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo2 = <269f569e-d242-4b09-8e71-130b4eda4578>ItemExtensions.Data(a); if (<269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo2 != null) { return <269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo2.IsStackableWithOtherInfo(<269f569e-d242-4b09-8e71-130b4eda4578>ItemExtensions.Data(b)); } <269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo <269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo3 = <269f569e-d242-4b09-8e71-130b4eda4578>ItemExtensions.Data(b); if (<269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo3 != null) { return <269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo3.IsStackableWithOtherInfo(null); } return new Dictionary(); } private static bool CheckItemDataStackableAddItem(Inventory __instance, ItemData item, int x, int y, ref Dictionary? __state, ref bool __result) { ItemData itemAt = __instance.GetItemAt(x, y); if (itemAt != null) { Dictionary 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? __state, bool __result) { if (!__result || __state == null) { return; } foreach (KeyValuePair item in __state) { __instance.GetItemAt(x, y).m_customData[item.Key] = item.Value; } } private static void ApplyCustomItemDataStackableAutoStack(ItemDrop item, Dictionary customData) { item.m_itemData.m_customData = customData; } private static Dictionary? IsStackableItemDrop(ItemDrop drop, ItemData item) { return IsStackable(drop.m_itemData, item); } private static IEnumerable HandleAutostackableItems(IEnumerable 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 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)); LocalBuilder localBuilder2 = ilg.DeclareLocal(typeof(ItemData)); list.Insert(i + 1, new CodeInstruction(OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(<269f569e-d242-4b09-8e71-130b4eda4578>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(<269f569e-d242-4b09-8e71-130b4eda4578>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 TransferCustomItemDataOnUpgrade(IEnumerable 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(<269f569e-d242-4b09-8e71-130b4eda4578>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; <269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo <269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo2 = <269f569e-d242-4b09-8e71-130b4eda4578>ItemExtensions.Data(currentlyUpgradingItem); <269f569e-d242-4b09-8e71-130b4eda4578>ItemExtensions.itemInfo.Remove(currentlyUpgradingItem); <269f569e-d242-4b09-8e71-130b4eda4578>ItemExtensions.itemInfo.Add(item.m_itemData, <269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo2); item.m_itemData.m_quality = currentlyUpgradingItem.m_quality + 1; item.m_itemData.m_variant = currentlyUpgradingItem.m_variant; <269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo2.ItemData = item.m_itemData; <269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo2.LoadAll(); foreach (ItemData value in <269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo2.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(); 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(dropPrefab.GetComponent().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 customDatum in item.m_itemData.m_customData) { val.Set($"data_{num}", customDatum.Key); val.Set($"data__{num++}", customDatum.Value); } } private static IEnumerable ImportCustomDataOnUpgrade(IEnumerable instructionList) { List 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(<269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo), "CopyCustomDataFromUpgradedItem", (Type[])null, (Type[])null)); } } } private static void TrackAwakeningItem(ItemDrop __instance) { if (ZNetView.m_forceDisableInit) { awakeningItem = __instance.m_itemData; } } static <269f569e-d242-4b09-8e71-130b4eda4578>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_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Expected O, but got Unknown //IL_01dd: Expected O, but got Unknown //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Expected O, but got Unknown //IL_024c: Expected O, but got Unknown //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: Unknown result type (might be due to invalid IL or missing references) //IL_02ae: Expected O, but got Unknown //IL_02ae: Expected O, but got Unknown //IL_02fb: Unknown result type (might be due to invalid IL or missing references) //IL_0312: Unknown result type (might be due to invalid IL or missing references) //IL_031d: Expected O, but got Unknown //IL_031d: Expected O, but got Unknown //IL_034d: Unknown result type (might be due to invalid IL or missing references) //IL_0359: Expected O, but got Unknown //IL_0387: Unknown result type (might be due to invalid IL or missing references) //IL_038e: Expected O, but got Unknown //IL_03a4: Unknown result type (might be due to invalid IL or missing references) //IL_03bf: Unknown result type (might be due to invalid IL or missing references) //IL_03cd: Expected O, but got Unknown //IL_03cd: Expected O, but got Unknown //IL_03fd: Unknown result type (might be due to invalid IL or missing references) //IL_0409: Expected O, but got Unknown //IL_0439: Unknown result type (might be due to invalid IL or missing references) //IL_0454: Unknown result type (might be due to invalid IL or missing references) //IL_045f: Expected O, but got Unknown //IL_045f: Expected O, but got Unknown //IL_04b0: Unknown result type (might be due to invalid IL or missing references) //IL_04bd: Expected O, but got Unknown //IL_0510: Unknown result type (might be due to invalid IL or missing references) //IL_051d: Expected O, but got Unknown //IL_05c9: Unknown result type (might be due to invalid IL or missing references) //IL_05d6: Expected O, but got Unknown //IL_0604: Unknown result type (might be due to invalid IL or missing references) //IL_062f: Unknown result type (might be due to invalid IL or missing references) //IL_0636: Expected O, but got Unknown //IL_065c: Unknown result type (might be due to invalid IL or missing references) //IL_066a: Expected O, but got Unknown //IL_066a: Expected O, but got Unknown //IL_06a9: Unknown result type (might be due to invalid IL or missing references) //IL_06b6: Expected O, but got Unknown //IL_06e4: Unknown result type (might be due to invalid IL or missing references) //IL_070f: Unknown result type (might be due to invalid IL or missing references) //IL_071c: Expected O, but got Unknown //IL_071c: Expected O, but got Unknown //IL_075b: Unknown result type (might be due to invalid IL or missing references) //IL_0768: Expected O, but got Unknown ForceLoadTypes = new HashSet(); typeInheritorsCache = new Dictionary>(); knownTypes = new HashSet(); awakeningItem = null; primaryAssembly = Assembly.GetExecutingAssembly(); assemblyNameCache = new Dictionary(); classKeyCache = new Dictionary(); removeMethod = typeof(<269f569e-d242-4b09-8e71-130b4eda4578>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(<269f569e-d242-4b09-8e71-130b4eda4578>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(<269f569e-d242-4b09-8e71-130b4eda4578>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[5] { typeof(ItemData), typeof(int), typeof(int), typeof(int), typeof(bool) }, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(<269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo), "CheckItemDataStackableAddItem", (Type[])null, (Type[])null)), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(<269f569e-d242-4b09-8e71-130b4eda4578>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(<269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo), "SaveCheckingForStackableItemData", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(<269f569e-d242-4b09-8e71-130b4eda4578>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(<269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo), "SaveCheckingForStackableItemData", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(<269f569e-d242-4b09-8e71-130b4eda4578>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(<269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo), "SaveCheckingForStackableItemData", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(<269f569e-d242-4b09-8e71-130b4eda4578>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(<269f569e-d242-4b09-8e71-130b4eda4578>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(<269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo), "CheckStackableInFindFreeStackMethods", (Type[])null, (Type[])null)); val.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(<269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo), "ResetNewValuesOnStackable", (Type[])null, (Type[])null)), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(<269f569e-d242-4b09-8e71-130b4eda4578>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(<269f569e-d242-4b09-8e71-130b4eda4578>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(<269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo), "TransferCustomItemDataOnUpgrade", (Type[])null, (Type[])null)), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(<269f569e-d242-4b09-8e71-130b4eda4578>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(<269f569e-d242-4b09-8e71-130b4eda4578>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(<269f569e-d242-4b09-8e71-130b4eda4578>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(<269f569e-d242-4b09-8e71-130b4eda4578>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(<269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo), "TrackAwakeningItem", (Type[])null, (Type[])null)); val2 = new HarmonyMethod(AccessTools.DeclaredMethod(typeof(<269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo), "ImportCustomDataOnUpgrade", (Type[])null, (Type[])null), 800, (string[])null, (string[])null, (bool?)null); val.Patch((MethodBase)methodInfo2, val3, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(<269f569e-d242-4b09-8e71-130b4eda4578>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(<269f569e-d242-4b09-8e71-130b4eda4578>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(<269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo), "ItemDataClonePrefix", (Type[])null, (Type[])null)), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(<269f569e-d242-4b09-8e71-130b4eda4578>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(<269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo), "ItemDataClonePostfixDelayed", (Type[])null, (Type[])null), 499, (string[])null, (string[])null, (bool?)null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } [PublicAPI] public class <269f569e-d242-4b09-8e71-130b4eda4578>ForeignItemInfo : IEnumerable, 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 <269f569e-d242-4b09-8e71-130b4eda4578>ForeignItemInfo(ItemData itemData, object foreignItemInfo) { ItemData = itemData; this.foreignItemInfo = foreignItemInfo; } public T GetOrCreate(string key = "") where T : class, new() { return Add(key) ?? Get(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(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(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(string key = "") where T : class { return call("Get", new object[1] { key }, new Type[1] { typeof(string) }, typeof(T)) as T; } public Dictionary GetAll() where T : class { return ((call("GetAll", Array.Empty(), Array.Empty(), typeof(T)) as T) as Dictionary) ?? new Dictionary(); } public bool Remove(string key = "") { return call("Add", new object[1] { key }, new Type[1] { typeof(string) }) as bool? == true; } public bool Remove(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 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(), Array.Empty()); } public void LoadAll() { call("LoadAll", Array.Empty(), Array.Empty()); } public IEnumerator GetEnumerator() { return (IEnumerator)((call("GetEnumerator", Array.Empty(), Array.Empty()) as IEnumerator) ?? ((object)new List().GetEnumerator())); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } [PublicAPI] public static class <269f569e-d242-4b09-8e71-130b4eda4578>ItemExtensions { private const string className = "ItemDataManager.ItemExtensions"; internal static readonly ConditionalWeakTableItemInfo> itemInfo = new ConditionalWeakTableItemInfo>(); private static readonly ConditionalWeakTableForeignItemInfo?>> foreignItemInfo = new ConditionalWeakTableForeignItemInfo>>(); public static <269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo Data(this ItemData item) { if (itemInfo.TryGetValue(item, out <269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo value)) { return value; } itemInfo.Add(item, value = new <269f569e-d242-4b09-8e71-130b4eda4578>ItemInfo(item)); return value; } public static <269f569e-d242-4b09-8e71-130b4eda4578>ForeignItemInfo? Data(this ItemData item, string mod) { DictionaryForeignItemInfo> orCreateValue = foreignItemInfo.GetOrCreateValue(item); if (orCreateValue.TryGetValue(mod, out var value)) { return value; } if (!Chainloader.PluginInfos.TryGetValue(mod, out var value2)) { return null; } object obj = ((object)value2.Instance).GetType().Assembly.GetType("ItemDataManager.ItemExtensions")?.GetMethod("Data", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(ItemData) }, Array.Empty())?.Invoke(null, new object[1] { item }); if (obj != null) { return orCreateValue[mod] = new <269f569e-d242-4b09-8e71-130b4eda4578>ForeignItemInfo(item, obj); } Debug.LogWarning((object)("Mod " + mod + " has an ItemDataManager.ItemExtensions class, but no Data(ItemDrop.ItemData) method could be called on it.")); return orCreateValue[mod] = null; } } } namespace DadsStorage { [BepInPlugin("com.dadisbored.dadsstorage", "DadsStorage", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class DadsStoragePlugin : BaseUnityPlugin { public enum Toggle { Off, On } private class ConfigurationManagerAttributes { [UsedImplicitly] public int? Order; [UsedImplicitly] public bool? Browsable; [UsedImplicitly] public string Category; [UsedImplicitly] public Action? CustomDrawer; } private class AcceptableShortcuts : AcceptableValueBase { public AcceptableShortcuts() : base(typeof(KeyboardShortcut)) { } public override object Clamp(object value) { return value; } public override bool IsValid(object value) { return true; } public override string ToDescriptionString() { return "# Acceptable values: " + string.Join(", ", UnityInput.Current.SupportedKeyCodes); } } internal const string ModName = "DadsStorage"; internal const string ModVersion = "1.0.0"; internal const string Author = "Dad_Is_Bored"; internal const string ModGUID = "com.dadisbored.dadsstorage"; internal const string KgGuid = "kg.ItemDrawers"; internal const string BackpacksGuid = "org.bepinex.plugins.backpacks"; private const string ConfigFileName = "com.dadisbored.dadsstorage.cfg"; private static readonly string ConfigFileFullPath; internal static string ConnectionError; private readonly Harmony _harmony = new Harmony("com.dadisbored.dadsstorage"); public static readonly ManualLogSource DadsStorageLogger; private static readonly ConfigSync ConfigSync; internal static bool BackpacksIsLoaded; internal static readonly string yamlFileName; internal static readonly string yamlPath; internal static readonly CustomSyncedValue DadsStorageContainerData; internal static readonly CustomSyncedValue CraftyContainerGroupsData; internal static Dictionary? yamlData; internal static Dictionary> groups; internal static DadsStoragePlugin self; private static ConfigEntry _serverConfigLocked; internal static ConfigEntry DontStoreToBackpacks; internal static ConfigEntry ChestsPickupFromGround; internal static ConfigEntry MustHaveExistingItemToPull; internal static ConfigEntry SingleItemShortcut; private static ConfigEntry _storeShortcut; private static ConfigEntry _pauseShortcut; internal static ConfigEntry SecondsToWaitBeforeStoring; internal static ConfigEntry IntervalSeconds; internal static ConfigEntry FishSuction; internal static ConfigEntry PlayerRange; internal static ConfigEntry FallbackRange; internal static ConfigEntry PlayerIgnoreHotbar; internal static ConfigEntry PlayerIgnoreQuickSlots; internal static ConfigEntry PingVfxString; internal static ConfigEntry HighlightContainers; internal static ConfigEntry PingContainers; public static ConfigEntry BorderColorFavoritedItem; public static ConfigEntry BorderColorFavoritedItemOnFavoritedSlot; public static ConfigEntry BorderColorFavoritedSlot; public static ConfigEntry DisplayTooltipHint; public static ConfigEntry FavoritingModifierKeybind1; public static ConfigEntry FavoritingModifierKeybind2; public static ConfigEntry SearchModifierKeybind; public static ConfigEntry FavoritedItemTooltip; public static ConfigEntry FavoritedSlotTooltip; public static ConfigEntry ItemOnFavoritedSlotTooltip; public void Awake() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Expected O, but got Unknown //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Expected O, but got Unknown //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Expected O, but got Unknown //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Expected O, but got Unknown //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Expected O, but got Unknown //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Expected O, but got Unknown //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Expected O, but got Unknown //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_0285: Expected O, but got Unknown //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: Expected O, but got Unknown //IL_02e5: Unknown result type (might be due to invalid IL or missing references) //IL_02f0: Expected O, but got Unknown //IL_0310: Unknown result type (might be due to invalid IL or missing references) //IL_031b: Expected O, but got Unknown //IL_0337: Unknown result type (might be due to invalid IL or missing references) //IL_0342: Expected O, but got Unknown //IL_035c: Unknown result type (might be due to invalid IL or missing references) //IL_0385: Unknown result type (might be due to invalid IL or missing references) //IL_0390: Expected O, but got Unknown //IL_03a7: Unknown result type (might be due to invalid IL or missing references) //IL_03d0: Unknown result type (might be due to invalid IL or missing references) //IL_03db: Expected O, but got Unknown //IL_03fb: Unknown result type (might be due to invalid IL or missing references) //IL_040f: Unknown result type (might be due to invalid IL or missing references) //IL_041a: Expected O, but got Unknown //IL_0431: Unknown result type (might be due to invalid IL or missing references) //IL_0445: Unknown result type (might be due to invalid IL or missing references) //IL_0450: Expected O, but got Unknown //IL_0477: Unknown result type (might be due to invalid IL or missing references) //IL_04cb: Unknown result type (might be due to invalid IL or missing references) //IL_04f6: Unknown result type (might be due to invalid IL or missing references) //IL_0531: Unknown result type (might be due to invalid IL or missing references) //IL_055a: Unknown result type (might be due to invalid IL or missing references) self = this; _serverConfigLocked = config("1 - General", "Lock Configuration", Toggle.On, new ConfigDescription("If on, the configuration is locked and can be changed by server admins only.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 10 } })); ConfigSync.AddLockingConfigEntry(_serverConfigLocked); DontStoreToBackpacks = config("1 - General", "Dont Store to Backpacks", Toggle.Off, new ConfigDescription("If on, items will not be stored in backpacks.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 9 } })); ChestsPickupFromGround = config("1 - General", "Chests Pickup From Ground", Toggle.On, new ConfigDescription("If on, chests will pick up items from the ground if they are in range. If off, chests will not begin their periodic checks for items nearby. Reloading zone or logging out might be required.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 8 } })); MustHaveExistingItemToPull = config("1 - General", "Must Have Existing Item To Pull", Toggle.On, new ConfigDescription("If on, the chest must already have the item in its inventory to pull it from the world or player into the chest.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 7 } })); PlayerRange = config("1 - General", "Player Range", 5f, new ConfigDescription("The maximum distance from the player to store items in chests when the Store Shortcut is pressed. Follows storage rules for allowed items.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 100f), new object[1] { new ConfigurationManagerAttributes { Order = 6 } })); FallbackRange = config("1 - General", "Fallback Range", 10f, new ConfigDescription("The range to use if the container has no range set in the yml file. This will be the fallback range for all containers.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 5 } })); PlayerIgnoreHotbar = config("1 - General", "Player Ignore Hotbar", Toggle.On, new ConfigDescription("If on, the player's hotbar will not be stored when the Store Shortcut is pressed.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 4 } }), synchronizedSetting: false); PlayerIgnoreQuickSlots = config("1 - General", "Player Ignore Quick Slots", Toggle.Off, new ConfigDescription("If on, the player's quick slots will not be stored when the Store Shortcut is pressed. (Requires Quick Slots mod, turn on only if you need it!)", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 3 } }), synchronizedSetting: false); PingVfxString = TextEntryConfig("1 - General", "Ping VFX", "vfx_Potion_health_medium", new ConfigDescription("The VFX to play when a chest is pinged. Leave blank to disable and only highlight the chest. (Full prefab list: https://valheim-modding.github.io/Jotunn/data/prefabs/prefab-list.html)", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 2 } })); HighlightContainers = config("1 - General", "Highlight Containers", Toggle.On, new ConfigDescription("If on, the containers will be highlighted when something is stored in them. If off, the containers will not be highlighted if something is stored in them.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 1 } }), synchronizedSetting: false); PingContainers = config("1 - General", "Ping Containers", Toggle.On, new ConfigDescription("If on, the containers will be pinged with the Ping VFX when something is stored in them. If off, the containers will not be pinged if something is stored in them.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 0 } }), synchronizedSetting: false); SecondsToWaitBeforeStoring = config("1 - General", "Seconds To Wait Before Storing", 10, new ConfigDescription("The number of seconds to wait before storing items into chests nearby automatically after you have pressed your hotkey to pause.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 60), Array.Empty())); IntervalSeconds = config("1 - General", "IntervalSeconds", 10f, new ConfigDescription("The number of seconds that must pass before the chest will do an automatic check for items nearby, WARNING: Reducing this will decrease performance!", (AcceptableValueBase)null, Array.Empty())); FishSuction = config("1.5 - Fish", "Fish Suction", Toggle.Off, new ConfigDescription("Allow auto-storing fish that are still in water (boat 'netting'). Off = require fish to be out of the water; On = ignore IsOutOfWater() check.", (AcceptableValueBase)null, Array.Empty())); SingleItemShortcut = config("2 - Shortcuts", "Store Single Item Shortcut", new KeyboardShortcut((KeyCode)325, Array.Empty()), new ConfigDescription("Keyboard shortcut/Hotkey to store a single item that you click from your inventory into nearby containers.", (AcceptableValueBase)(object)new AcceptableShortcuts(), new object[1] { new ConfigurationManagerAttributes { Order = 2 } }), synchronizedSetting: false); _storeShortcut = config("2 - Shortcuts", "Store Shortcut", new KeyboardShortcut((KeyCode)46, Array.Empty()), new ConfigDescription("Keyboard shortcut/Hotkey to store your inventory into nearby containers.", (AcceptableValueBase)(object)new AcceptableShortcuts(), new object[1] { new ConfigurationManagerAttributes { Order = 1 } }), synchronizedSetting: false); _pauseShortcut = config("2 - Shortcuts", "Pause Shortcut", new KeyboardShortcut((KeyCode)46, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), new ConfigDescription("Keyboard shortcut/Hotkey to temporarily stop storing items into chests nearby automatically. Does not override the player hotkey store.", (AcceptableValueBase)(object)new AcceptableShortcuts(), Array.Empty()), synchronizedSetting: false); SearchModifierKeybind = config("2 - Shortcuts", "SearchModifierKeybind", new KeyboardShortcut((KeyCode)121, Array.Empty()), new ConfigDescription("While holding this, you can search nearby chests for the prefab you clicked in your inventory.", (AcceptableValueBase)(object)new AcceptableShortcuts(), Array.Empty()), synchronizedSetting: false); string text = "3 - Favoriting"; string text2 = "While holding this, left clicking on items or right clicking on slots favorites them, disallowing storing"; BorderColorFavoritedItem = config(text, "BorderColorFavoritedItem", new Color(1f, 0.8482759f, 0f), "Color of the border for slots containing favorited items.", synchronizedSetting: false); BorderColorFavoritedItem.SettingChanged += delegate { FavoritingMode.RefreshDisplay(); }; BorderColorFavoritedItemOnFavoritedSlot = config(text, "BorderColorFavoritedItemOnFavoritedSlot", new Color(0.5f, 0.67413795f, 0.5f), "Color of the border of a favorited slot that also contains a favorited item.", synchronizedSetting: false); BorderColorFavoritedSlot = config(text, "BorderColorFavoritedSlot", new Color(0f, 0.5f, 1f), "Color of the border for favorited slots.", synchronizedSetting: false); DisplayTooltipHint = config(text, "DisplayTooltipHint", value: true, "Whether to add additional info the item tooltip of a favorited or trash flagged item.", synchronizedSetting: false); FavoritingModifierKeybind1 = config(text, "FavoritingModifierKeybind1", new KeyboardShortcut((KeyCode)122, Array.Empty()), text2 + " Identical to FavoritingModifierKeybind2.", synchronizedSetting: false); FavoritingModifierKeybind2 = config(text, "FavoritingModifierKeybind2", new KeyboardShortcut((KeyCode)122, Array.Empty()), text2 + " Identical to FavoritingModifierKeybind1.", synchronizedSetting: false); FavoritedItemTooltip = config(text, "FavoritedItemTooltip", "Item is favorited and won't be stored", string.Empty, synchronizedSetting: false); FavoritedSlotTooltip = config(text, "FavoritedSlotTooltip", "Slot is favorited and won't be stored", string.Empty, synchronizedSetting: false); ItemOnFavoritedSlotTooltip = config(text, "ItemOnFavoritedSlotTooltip", "Item & Slot are favorited and won't be stored", string.Empty, synchronizedSetting: false); if (!File.Exists(yamlPath)) { WriteConfigFileFromResource(yamlPath); } DadsStorageContainerData.ValueChanged += OnValChangedUpdate; DadsStorageContainerData.AssignLocalValue(File.ReadAllText(yamlPath)); AutoDoc(); Assembly executingAssembly = Assembly.GetExecutingAssembly(); _harmony.PatchAll(executingAssembly); SetupWatcher(); } public void Start() { BorderRenderer.Border = loadSprite("border.png"); if (Chainloader.PluginInfos.ContainsKey("org.bepinex.plugins.backpacks")) { BackpacksIsLoaded = true; } Log.Init(DadsStorageLogger); if (!MUCCompat.DoNotPatch && Chainloader.PluginInfos.ContainsKey("mkz.itemdrawers")) { try { _harmony.PatchAll(typeof(ItemDrawerCompat)); } catch (Exception ex) { DadsStorageLogger.LogWarning((object)("Couldn't apply the ItemDrawers compatibility patches: " + ex.Message)); } } } private void AutoDoc() { } private static void WriteConfigFileFromResource(string configFilePath) { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string text = "DadsStorage.Example.yml"; using Stream stream = executingAssembly.GetManifestResourceStream(text); if (stream == null) { throw new FileNotFoundException("Resource '" + text + "' not found in the assembly."); } using StreamReader streamReader = new StreamReader(stream); string contents = streamReader.ReadToEnd(); File.WriteAllText(configFilePath, contents); } private void Update() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return; } KeyboardShortcut value = _storeShortcut.Value; if (((KeyboardShortcut)(ref value)).IsDown() && ((Character)Player.m_localPlayer).TakeInput()) { Functions.TryStore(); } value = _pauseShortcut.Value; if (!((KeyboardShortcut)(ref value)).IsDown() || !((Character)Player.m_localPlayer).TakeInput()) { return; } Boxes.StoringPaused = !Boxes.StoringPaused; foreach (Container container in Boxes.Containers) { if (container.m_nview.IsValid()) { container.m_nview.InvokeRPC("RequestPause", new object[1] { Boxes.StoringPaused }); } } } private void OnDestroy() { ((BaseUnityPlugin)this).Config.Save(); } private void SetupWatcher() { FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, "com.dadisbored.dadsstorage.cfg"); fileSystemWatcher.Changed += ReadConfigValues; fileSystemWatcher.Created += ReadConfigValues; fileSystemWatcher.Renamed += ReadConfigValues; fileSystemWatcher.IncludeSubdirectories = true; fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher.EnableRaisingEvents = true; FileSystemWatcher fileSystemWatcher2 = new FileSystemWatcher(Paths.ConfigPath, yamlFileName); fileSystemWatcher2.Changed += ReadYamlFiles; fileSystemWatcher2.Created += ReadYamlFiles; fileSystemWatcher2.Renamed += ReadYamlFiles; fileSystemWatcher2.IncludeSubdirectories = true; fileSystemWatcher2.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher2.EnableRaisingEvents = true; } private void ReadConfigValues(object sender, FileSystemEventArgs e) { if (!File.Exists(ConfigFileFullPath)) { return; } try { Functions.LogDebug("ReadConfigValues called"); ((BaseUnityPlugin)this).Config.Reload(); } catch { Functions.LogError("There was an issue loading your com.dadisbored.dadsstorage.cfg"); Functions.LogError("Please check your config entries for spelling and format!"); } } private void ReadYamlFiles(object sender, FileSystemEventArgs e) { if (!File.Exists(yamlPath)) { return; } try { DadsStorageLogger.LogDebug((object)"ReadConfigValues called"); DadsStorageContainerData.AssignLocalValue(File.ReadAllText(yamlPath)); } catch { DadsStorageLogger.LogError((object)("There was an issue loading your " + yamlFileName)); DadsStorageLogger.LogError((object)"Please check your entries for spelling and format!"); } } private static void OnValChangedUpdate() { DadsStorageLogger.LogDebug((object)"OnValChanged called"); try { YamlUtils.ReadYaml(DadsStorageContainerData.Value); YamlUtils.ParseGroups(); Functions.ClearRangeCache(); } catch (Exception arg) { DadsStorageLogger.LogError((object)$"Failed to deserialize {yamlFileName}: {arg}"); } } private static byte[] ReadEmbeddedFileBytes(string name) { using MemoryStream memoryStream = new MemoryStream(); Assembly.GetExecutingAssembly().GetManifestResourceStream(Assembly.GetExecutingAssembly().GetName().Name + "." + name).CopyTo(memoryStream); return memoryStream.ToArray(); } private static Texture2D loadTexture(string name) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_001e: Expected O, but got Unknown Texture2D val = new Texture2D(0, 0); LoadImageBytes(val, ReadEmbeddedFileBytes("assets." + name)); return val; } private static void LoadImageBytes(Texture2D texture, byte[] bytes) { typeof(ImageConversion).GetMethod("LoadImage", new Type[3] { typeof(Texture2D), typeof(byte[]), typeof(bool) })?.Invoke(null, new object[3] { texture, bytes, false }); } internal static Sprite loadSprite(string name) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) Texture2D val = loadTexture(name); if ((Object)(object)val != (Object)null) { return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), Vector2.zero); } return null; } private ConfigEntry config(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown ConfigDescription val = new ConfigDescription(description.Description + (synchronizedSetting ? " [Synced with Server]" : " [Not Synced with Server]"), description.AcceptableValues, description.Tags); ConfigEntry val2 = ((BaseUnityPlugin)this).Config.Bind(group, name, value, val); ConfigSync.AddConfigEntry(val2).SynchronizedConfig = synchronizedSetting; return val2; } private ConfigEntry config(string group, string name, T value, string description, bool synchronizedSetting = true) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown return config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty()), synchronizedSetting); } private ConfigEntry TextEntryConfig(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown ConfigDescription val = new ConfigDescription(description.Description + (synchronizedSetting ? " [Synced with Server]" : " [Not Synced with Server]"), description.AcceptableValues, description.Tags); ConfigEntry val2 = ((BaseUnityPlugin)this).Config.Bind(group, name, value, val); ConfigSync.AddConfigEntry(val2).SynchronizedConfig = synchronizedSetting; return val2; } private ConfigEntry TextEntryConfig(string group, string name, T value, string desc, bool synchronizedSetting = true) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes { CustomDrawer = ConfigExtensions.TextAreaDrawer }; return TextEntryConfig(group, name, value, new ConfigDescription(desc, (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }), synchronizedSetting); } static DadsStoragePlugin() { string configPath = Paths.ConfigPath; char directorySeparatorChar = Path.DirectorySeparatorChar; ConfigFileFullPath = configPath + directorySeparatorChar + "com.dadisbored.dadsstorage.cfg"; ConnectionError = ""; DadsStorageLogger = Logger.CreateLogSource("DadsStorage"); ConfigSync = new ConfigSync("com.dadisbored.dadsstorage") { DisplayName = "DadsStorage", CurrentVersion = "1.0.0", MinimumRequiredVersion = "1.0.0" }; BackpacksIsLoaded = false; yamlFileName = "com.dadisbored.dadsstorage.yml"; string configPath2 = Paths.ConfigPath; directorySeparatorChar = Path.DirectorySeparatorChar; yamlPath = configPath2 + directorySeparatorChar + yamlFileName; DadsStorageContainerData = new CustomSyncedValue(ConfigSync, "dadsstorageData", ""); CraftyContainerGroupsData = new CustomSyncedValue(ConfigSync, "dadsstorageGroupsData", ""); groups = null; self = null; _serverConfigLocked = null; DontStoreToBackpacks = null; ChestsPickupFromGround = null; MustHaveExistingItemToPull = null; SingleItemShortcut = null; _storeShortcut = null; _pauseShortcut = null; SecondsToWaitBeforeStoring = null; IntervalSeconds = null; FishSuction = null; PlayerRange = null; FallbackRange = null; PlayerIgnoreHotbar = null; PlayerIgnoreQuickSlots = null; PingVfxString = null; HighlightContainers = null; PingContainers = null; BorderColorFavoritedItem = null; BorderColorFavoritedItemOnFavoritedSlot = null; BorderColorFavoritedSlot = null; DisplayTooltipHint = null; FavoritingModifierKeybind1 = null; FavoritingModifierKeybind2 = null; SearchModifierKeybind = null; FavoritedItemTooltip = null; FavoritedSlotTooltip = null; ItemOnFavoritedSlotTooltip = null; } } public static class ToggleExtensions { public static bool IsOn(this DadsStoragePlugin.Toggle toggle) { return toggle == DadsStoragePlugin.Toggle.On; } public static bool IsOff(this DadsStoragePlugin.Toggle toggle) { return toggle == DadsStoragePlugin.Toggle.Off; } } public static class KeyboardExtensions { public static bool IsKeyDown(this KeyboardShortcut shortcut) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) if ((int)((KeyboardShortcut)(ref shortcut)).MainKey != 0 && Input.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey)) { return ((KeyboardShortcut)(ref shortcut)).Modifiers.All((Func)Input.GetKey); } return false; } public static bool IsKeyHeld(this KeyboardShortcut shortcut) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) if ((int)((KeyboardShortcut)(ref shortcut)).MainKey != 0 && Input.GetKey(((KeyboardShortcut)(ref shortcut)).MainKey)) { return ((KeyboardShortcut)(ref shortcut)).Modifiers.All((Func)Input.GetKey); } return false; } } public static class ConfigExtensions { internal static void TextAreaDrawer(ConfigEntryBase entry) { GUILayout.ExpandHeight(true); GUILayout.ExpandWidth(true); entry.BoxedValue = GUILayout.TextArea((string)entry.BoxedValue, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true) }); } } [HarmonyPatch(typeof(Terminal), "InitTerminal")] internal static class TerminalInitTerminalPatch { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static Func <>9__2_8; public static Func <>9__2_10; public static Func <>9__2_12; public static ConsoleEvent <>9__2_0; public static ConsoleOptionsFetcher <>9__2_1; internal void b__2_0(ConsoleEventArgs args) { <>c__DisplayClass2_0 <>c__DisplayClass2_ = new <>c__DisplayClass2_0(); if (args.Length > 1 && Object.op_Implicit((Object)(object)ZNetScene.instance)) { <>c__DisplayClass2_.itemCount = 0; bool flag = <>c__DisplayClass2_.g__SearchNearbyContainersFor|2(args[1]); ((Character)Player.m_localPlayer).Message((MessageType)2, flag ? $"Found {<>c__DisplayClass2_.itemCount} items matching '{args[1]}' in nearby containers." : ("No items matching '" + args[1] + "' found in nearby containers."), 0, (Sprite)null, false); } } internal bool b__2_8(Piece p) { return Object.op_Implicit((Object)(object)((Component)p).GetComponent()); } internal VanillaContainers b__2_10(Piece p) { return VanillaContainers.Create(((Component)p).GetComponent()); } internal int b__2_12(ItemData item) { return item.m_stack; } internal List b__2_1() { if (Object.op_Implicit((Object)(object)ZNetScene.instance)) { return ZNetScene.instance.GetPrefabNames(); } return new List(); } } [CompilerGenerated] private sealed class <>c__DisplayClass2_0 { public int itemCount; } private const float SearchRadius = 50f; public static void GetAllPiecesInRadius(Vector3 p, float radius, List pieces) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) if (Piece.s_ghostLayer == 0) { Piece.s_ghostLayer = LayerMask.NameToLayer("ghost"); } foreach (Piece s_allPiece in Piece.s_allPieces) { if (((Component)s_allPiece).gameObject.layer != Piece.s_ghostLayer && (double)Vector3.Distance(p, ((Component)s_allPiece).transform.position) < (double)radius) { pieces.Add(s_allPiece); } } } private static void Postfix(Terminal __instance) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown object obj = <>c.<>9__2_0; if (obj == null) { ConsoleEvent val = delegate(ConsoleEventArgs args) { int itemCount; if (args.Length > 1 && Object.op_Implicit((Object)(object)ZNetScene.instance)) { itemCount = 0; bool flag = SearchNearbyContainersFor(args[1]); ((Character)Player.m_localPlayer).Message((MessageType)2, flag ? $"Found {itemCount} items matching '{args[1]}' in nearby containers." : ("No items matching '" + args[1] + "' found in nearby containers."), 0, (Sprite)null, false); } IEnumerable GetNearbyMatchingPieces(string query) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) List list = new List(); GetAllPiecesInRadius(((Component)Player.m_localPlayer).transform.position, 50f, list); IEnumerable second = ItemDrawers_API.AllDrawers.Where((ItemDrawers_API.Drawer x) => string.Equals(x.Prefab, query, StringComparison.CurrentCultureIgnoreCase)).Select(kgDrawer.Create); IEnumerable second2 = MkzItemDrawers_API.AllDrawers.Where((MkzItemDrawers_API.Drawer x) => string.Equals(x.Prefab, query, StringComparison.CurrentCultureIgnoreCase)).Select(mkzDrawer.Create); return (from p in list where Object.op_Implicit((Object)(object)((Component)p).GetComponent()) where ContainerContainsMatchingItem((Component)(object)p, query.ToLower(), ref itemCount) select VanillaContainers.Create(((Component)p).GetComponent())).Concat(second).Concat(second2); } bool SearchNearbyContainersFor(string query) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) bool result = false; DadsStorage.Interfaces.IContainer container = null; float num = float.MaxValue; foreach (DadsStorage.Interfaces.IContainer item in GetNearbyMatchingPieces(query)) { Functions.PingContainer(item.gameObject); result = true; float num2 = Vector3.Distance(item.gameObject.transform.position, ((Component)Player.m_localPlayer).transform.position); if (num2 < num) { num = num2; container = item; } } if (container != null) { Vector3 position = container.gameObject.transform.position; ((Character)Player.m_localPlayer).SetLookDir(position - ((Component)Player.m_localPlayer).transform.position, 3.5f); } return result; } }; <>c.<>9__2_0 = val; obj = (object)val; } object obj2 = <>c.<>9__2_1; if (obj2 == null) { ConsoleOptionsFetcher val2 = () => Object.op_Implicit((Object)(object)ZNetScene.instance) ? ZNetScene.instance.GetPrefabNames() : new List(); <>c.<>9__2_1 = val2; obj2 = (object)val2; } new ConsoleCommand("dadsstoragesearch", "[prefab name/query text] - search for items in chests near the player. It uses the prefab name", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)obj2, false, false, false); static bool ContainerContainsMatchingItem(Component container, string query, ref int count) { IEnumerable source = (from i in container.GetComponent().GetInventory().GetAllItems() where NormalizedItemName(i).Contains(query) || i.m_shared.m_name.ToLower().Contains(query) select i).ToList(); count += source.Sum((ItemData item) => item.m_stack); return source.Any(); } static string NormalizedItemName(ItemData itemData) { return Utils.GetPrefabName(itemData.m_dropPrefab).ToLower(); } } } [HarmonyPatch(typeof(ZNet), "OnNewConnection")] public static class RegisterAndCheckVersion { private static void Prefix(ZNetPeer peer, ref ZNet __instance) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown DadsStoragePlugin.DadsStorageLogger.LogDebug((object)"Registering version RPC handler"); peer.m_rpc.Register("DadsStorage_VersionCheck", (Action)RpcHandlers.RPC_DadsStorage_Version); DadsStoragePlugin.DadsStorageLogger.LogInfo((object)"Invoking version check"); ZPackage val = new ZPackage(); val.Write("1.0.0"); peer.m_rpc.Invoke("DadsStorage_VersionCheck", new object[1] { val }); } } [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] public static class VerifyClient { private static bool Prefix(ZRpc rpc, ZPackage pkg, ref ZNet __instance) { if (!__instance.IsServer() || RpcHandlers.ValidatedPeers.Contains(rpc)) { return true; } DadsStoragePlugin.DadsStorageLogger.LogWarning((object)("Peer (" + rpc.m_socket.GetHostName() + ") never sent version or couldn't due to previous disconnect, disconnecting")); rpc.Invoke("Error", new object[1] { 3 }); return false; } private static void Postfix(ZNet __instance) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), "DadsStorageRequestAdminSync", new object[1] { (object)new ZPackage() }); } } [HarmonyPatch(typeof(FejdStartup), "ShowConnectError")] public class ShowConnectionError { private static void Postfix(FejdStartup __instance) { if (__instance.m_connectionFailedPanel.activeSelf) { __instance.m_connectionFailedError.fontSizeMax = 25f; __instance.m_connectionFailedError.fontSizeMin = 15f; TMP_Text connectionFailedError = __instance.m_connectionFailedError; connectionFailedError.text = connectionFailedError.text + "\n" + DadsStoragePlugin.ConnectionError; } } } [HarmonyPatch(typeof(ZNet), "Disconnect")] public static class RemoveDisconnectedPeerFromVerified { private static void Prefix(ZNetPeer peer, ref ZNet __instance) { if (__instance.IsServer()) { DadsStoragePlugin.DadsStorageLogger.LogInfo((object)("Peer (" + peer.m_rpc.m_socket.GetHostName() + ") disconnected, removing from validated list")); RpcHandlers.ValidatedPeers.Remove(peer.m_rpc); } } } public static class RpcHandlers { public static readonly List ValidatedPeers = new List(); public static void RPC_DadsStorage_Version(ZRpc rpc, ZPackage pkg) { string text = pkg.ReadString(); DadsStoragePlugin.DadsStorageLogger.LogInfo((object)("Version check, local: 1.0.0, remote: " + text)); if (text != "1.0.0") { DadsStoragePlugin.ConnectionError = "DadsStorage Installed: 1.0.0\n Needed: " + text; if (ZNet.instance.IsServer()) { DadsStoragePlugin.DadsStorageLogger.LogWarning((object)("Peer (" + rpc.m_socket.GetHostName() + ") has incompatible version, disconnecting...")); rpc.Invoke("Error", new object[1] { 3 }); } } else if (!ZNet.instance.IsServer()) { DadsStoragePlugin.DadsStorageLogger.LogInfo((object)"Received same version from server!"); } else { DadsStoragePlugin.DadsStorageLogger.LogInfo((object)("Adding peer (" + rpc.m_socket.GetHostName() + ") to validated list")); ValidatedPeers.Add(rpc); } } } } namespace DadsStorage.Util { public class Boxes { internal static readonly List Containers = new List(); private static readonly List ContainersToAdd = new List(); private static readonly List ContainersToRemove = new List(); internal static readonly List ContainersToPing = new List(); internal static bool StoringPaused; internal static void AddContainer(Container container) { if (!Containers.Contains(container)) { ContainersToAdd.Add(container); DadsStoragePlugin.DadsStorageLogger.LogDebug((object)("Added container " + ((Object)container).name + " to list")); } UpdateContainers(); } internal static void RemoveContainer(Container container) { if (Containers.Contains(container)) { ContainersToRemove.Add(container); if (Object.op_Implicit((Object)(object)container)) { DadsStoragePlugin.DadsStorageLogger.LogDebug((object)("Removed container " + ((Object)container).name + " from list")); } } UpdateContainers(); } internal static void PruneDestroyed() { for (int num = Containers.Count - 1; num >= 0; num--) { Container val = Containers[num]; if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)((Component)val).transform) || val.GetInventory() == null) { Containers.RemoveAt(num); } } } internal static void UpdateContainers() { Containers.AddRange(ContainersToAdd); ContainersToAdd.Clear(); foreach (Container item in ContainersToRemove) { Containers.Remove(item); } ContainersToRemove.Clear(); } internal static List GetNearbyContainers(T gameObject, float rangeToUse) where T : Component { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) List list = new List(); foreach (Container container in Containers) { if (!((Object)(object)gameObject == (Object)null) && !((Object)(object)container == (Object)null)) { float num = Vector3.Distance(((Component)container).transform.position, ((Component)gameObject).transform.position); if (num <= rangeToUse) { DadsStoragePlugin.DadsStorageLogger.LogDebug((object)$"Distance to container {((Object)container).name} is {num}m, within the range of {rangeToUse}m set to store items for this chest"); list.Add(VanillaContainers.Create(container)); } } } IEnumerable second = new List(); List list2 = new List(); if (DadsStoragePlugin.BackpacksIsLoaded && DadsStoragePlugin.DontStoreToBackpacks.Value.IsOff()) { foreach (ItemData item2 in from x in ((Humanoid)Player.m_localPlayer).GetInventory().GetAllItems() where ((x == null) ? null : <269f569e-d242-4b09-8e71-130b4eda4578>ItemExtensions.Data(x, "org.bepinex.plugins.backpacks")?.Get()) != null select x) { BackpackContainer item = BackpackContainer.Create((item2 == null) ? null : <269f569e-d242-4b09-8e71-130b4eda4578>ItemExtensions.Data(item2, "org.bepinex.plugins.backpacks")?.Get()); if (!list2.Contains(item)) { list2.Add(item); } } second = list2; } IEnumerable second2 = ItemDrawers_API.AllDrawersInRange(((Component)gameObject).transform.position, rangeToUse).Select(kgDrawer.Create); IEnumerable second3 = MkzItemDrawers_API.AllDrawersInRange(((Component)gameObject).transform.position, rangeToUse).Select(mkzDrawer.Create); return list.Concat(second2).Concat(second3).Concat(second) .ToList(); } public static void AddContainerIfNotExists(string containerName) { if (DadsStoragePlugin.yamlData != null && !DadsStoragePlugin.yamlData.ContainsKey(containerName)) { DadsStoragePlugin.yamlData[containerName] = new Dictionary { { "exclude", new List() }, { "includeOverride", new List() } }; YamlUtils.WriteYaml(DadsStoragePlugin.yamlPath); } } public static Dictionary> GetExcludedPrefabsForAllContainers() { Dictionary> dictionary = new Dictionary>(); foreach (string allContainer in GetAllContainers()) { dictionary[allContainer] = GetExcludedPrefabs(allContainer); } return dictionary; } public static List? GetAllContainers() { return DadsStoragePlugin.yamlData?.Keys.Where((string key) => key != "groups").ToList(); } public static bool CanItemBeStored(string container, string prefab) { if (DadsStoragePlugin.yamlData == null) { DadsStoragePlugin.DadsStorageLogger.LogError((object)"yamlData is null."); return false; } if (!DadsStoragePlugin.yamlData.ContainsKey(container)) { return true; } if (!(DadsStoragePlugin.yamlData[container] is Dictionary dict)) { DadsStoragePlugin.DadsStorageLogger.LogError((object)("Unable to cast containerData for container '" + container + "' to Dictionary.")); return false; } List list = (GetValueCaseInsensitive(dict, "exclude") as List) ?? new List(); if (((GetValueCaseInsensitive(dict, "includeOverride") as List) ?? new List()).Contains(prefab)) { return true; } foreach (object item in list) { if (prefab.Equals(item)) { return false; } if (GroupUtils.IsGroupDefined((string)item) && GroupUtils.GetItemsInGroup((string)item).Contains(prefab)) { return false; } } return true; } internal static bool IsPrefabExcluded(string prefab, List exclusionList) { if (exclusionList != null) { foreach (object exclusion in exclusionList) { string text = exclusion.ToString(); if (DadsStoragePlugin.groups.TryGetValue(text, out HashSet value)) { if (value.Contains(prefab)) { return true; } } else if (text == prefab) { return true; } } } return false; } public static List GetExcludedPrefabs(string container) { if (DadsStoragePlugin.yamlData != null && DadsStoragePlugin.yamlData.TryGetValue(container, out object value) && value is Dictionary dict) { object valueCaseInsensitive = GetValueCaseInsensitive(dict, "exclude"); if (valueCaseInsensitive != null && valueCaseInsensitive is List list) { List list2 = new List(); { foreach (object item in list) { string text = item.ToString(); if (DadsStoragePlugin.groups.TryGetValue(text, out HashSet value2)) { list2.AddRange(value2); } else { list2.Add(text); } } return list2; } } } return new List(); } internal static void RPC_RequestPause(long sender, bool pause, Container container) { if (container.m_nview.IsValid() && container.m_nview.IsOwner()) { container.m_nview.GetZDO().Set(ContainerAwakePatch.storingPausedHash, pause); } } internal static object? GetValueCaseInsensitive(Dictionary dict, string key) { foreach (KeyValuePair item in dict) { if (string.Equals(item.Key?.ToString(), key, StringComparison.OrdinalIgnoreCase)) { return item.Value; } } return null; } } public class ChestPingEffect : MonoBehaviour { private GameObject pingObject; private void Awake() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrWhiteSpace(DadsStoragePlugin.PingVfxString.Value)) { pingObject = Object.Instantiate(ZNetScene.instance.GetPrefab(DadsStoragePlugin.PingVfxString.Value), ((Component)this).transform.position, Quaternion.identity); Trigger(); } } public void Trigger() { ((MonoBehaviour)this).InvokeRepeating("DestroyNow", 10f, 1f); } public void DestroyNow() { if ((Object)(object)pingObject != (Object)null) { ZNetScene.instance.Destroy(pingObject); } Object.DestroyImmediate((Object)(object)this); } } public static class YamlUtils { internal static void ReadYaml(string yamlInput) { DadsStoragePlugin.yamlData = new DeserializerBuilder().Build().Deserialize>(yamlInput); DadsStoragePlugin.DadsStorageLogger.LogDebug((object)("yamlData:\n" + yamlInput)); } internal static void ParseGroups() { if (DadsStoragePlugin.groups == null) { DadsStoragePlugin.groups = new Dictionary>(); } object value; if (DadsStoragePlugin.yamlData == null) { DadsStoragePlugin.DadsStorageLogger.LogError((object)"yamlData is null."); } else if (DadsStoragePlugin.yamlData.TryGetValue("groups", out value)) { if (value is Dictionary dictionary) { { foreach (KeyValuePair item in dictionary) { string text = item.Key?.ToString(); if (text == null || !(item.Value is List list)) { continue; } HashSet hashSet = new HashSet(); foreach (object item2 in list) { string text2 = item2?.ToString(); if (text2 != null) { hashSet.Add(text2); } } DadsStoragePlugin.groups[text] = hashSet; } return; } } DadsStoragePlugin.DadsStorageLogger.LogError((object)"groupData is not of type Dictionary."); } else { DadsStoragePlugin.DadsStorageLogger.LogError((object)"No 'groups' key found in yamlData."); } } public static void WriteYaml(string filePath) { ISerializer serializer = new SerializerBuilder().Build(); using StreamWriter writer = new StreamWriter(filePath); serializer.Serialize(writer, DadsStoragePlugin.yamlData); string contents = serializer.Serialize(DadsStoragePlugin.yamlData); File.AppendAllText(filePath, contents); } } public class Functions { private readonly struct NearbyContainer { internal readonly Container Container; internal readonly Vector3 Position; internal readonly float RangeSq; internal NearbyContainer(Container container, Vector3 position, float rangeSq) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) Container = container; Position = position; RangeSq = rangeSq; } } private static readonly Dictionary RangeByPrefab = new Dictionary(); private static readonly List Nearby = new List(); private static readonly Dictionary PendingSends = new Dictionary(); public static void LogContainerStatus(Container container) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) try { object[] obj = new object[4] { ((Object)container).name, ((Component)container).transform.position, container.m_nview.IsOwner() ? "owned" : "not owned", null }; Inventory inventory = container.GetInventory(); obj[3] = ((inventory != null) ? inventory.NrOfItems() : 0); LogIfBuildDebug(string.Format("Container {0} at {1} is {2} and has {3} items.", obj)); } catch { } } internal static void ClearRangeCache() { RangeByPrefab.Clear(); } internal static float GetContainerRange(Container container) { if (DadsStoragePlugin.yamlData == null) { DadsStoragePlugin.DadsStorageLogger.LogError((object)"yamlData is null when trying to get the container range for a container. Make sure that your YAML file is not empty or to call DeserializeYamlFile() before using GetContainerRange."); return -1f; } if (container.GetInventory() == null) { return -1f; } string prefabName = MiscFunctions.GetPrefabName(((Object)((Component)container).transform.root).name); if (RangeByPrefab.TryGetValue(prefabName, out var value)) { if (!float.IsNaN(value)) { return value; } return DadsStoragePlugin.FallbackRange.Value; } if (DadsStoragePlugin.yamlData.TryGetValue(prefabName, out object value2)) { if (!(value2 is Dictionary dictionary)) { DadsStoragePlugin.DadsStorageLogger.LogError((object)("Unable to cast containerData for container '" + prefabName + "' to Dictionary.")); return -1f; } object obj = null; foreach (KeyValuePair item in dictionary) { if (string.Equals(item.Key?.ToString(), "range", StringComparison.OrdinalIgnoreCase)) { obj = item.Value; break; } } if (obj != null && float.TryParse(obj.ToString(), out var result)) { RangeByPrefab[prefabName] = result; return result; } } RangeByPrefab[prefabName] = float.NaN; return DadsStoragePlugin.FallbackRange.Value; } internal static void BuildNearbyContainers() { //IL_0057: Unknown result type (might be due to invalid IL or missing references) Nearby.Clear(); Boxes.PruneDestroyed(); List containers = Boxes.Containers; for (int i = 0; i < containers.Count; i++) { Container val = containers[i]; if (!((Object)(object)val.m_nview == (Object)null) && val.m_nview.IsValid()) { float containerRange = GetContainerRange(val); if (!(containerRange < 0f)) { Nearby.Add(new NearbyContainer(val, ((Component)val).transform.position, containerRange * containerRange)); } } } } internal static void ClearNearbyContainers() { Nearby.Clear(); } private static bool SatLongEnoughToAskFor(ItemDrop itemDrop) { if ((Object)(object)ZNet.instance == (Object)null) { return false; } long num = itemDrop.m_nview.GetZDO().GetLong(ZDOVars.s_spawnTime, 0L); if (num > 0) { DateTime maxValue = DateTime.MaxValue; if (num <= maxValue.Ticks) { return (ZNet.instance.GetTime() - new DateTime(num)).TotalSeconds >= (double)Math.Max(15f, DadsStoragePlugin.IntervalSeconds.Value * 2f); } } return false; } private static bool AnyContainerWants(ItemDrop itemDrop) { //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_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) ItemData itemData = itemDrop.m_itemData; long playerID = Game.instance.GetPlayerProfile().GetPlayerID(); Vector3 position = ((Component)itemDrop).transform.position; for (int i = 0; i < Nearby.Count; i++) { NearbyContainer nearbyContainer = Nearby[i]; Container container = nearbyContainer.Container; if (!Object.op_Implicit((Object)(object)container) || !Object.op_Implicit((Object)(object)((Component)container).transform) || (Object)(object)container.m_nview == (Object)null || !container.m_nview.IsValid()) { continue; } Vector3 val = nearbyContainer.Position - position; if (!(((Vector3)(ref val)).sqrMagnitude > nearbyContainer.RangeSq)) { Inventory inventory = container.GetInventory(); if (inventory != null && !container.m_nview.GetZDO().GetBool(ContainerAwakePatch.storingPausedHash, false) && (!DadsStoragePlugin.MustHaveExistingItemToPull.Value.IsOn() || inventory.HaveItem(itemData.m_shared.m_name, true)) && Boxes.CanItemBeStored(MiscFunctions.GetPrefabName(((Object)((Component)container).transform.root).name), ((Object)itemData.m_dropPrefab).name) && container.CheckAccess(playerID) && !container.IsInUse() && container.m_nview.GetZDO().GetInt(ZDOVars.s_inUse, 0) == 0 && InventoryMove.HowMuchFits(inventory, itemData) > 0) { return true; } } } return false; } internal static void CheckItemDropInstanceAndStore(ItemDrop itemDrop) { //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) if (Boxes.Containers == null || (Object)(object)itemDrop == (Object)null || (Object)(object)((Component)itemDrop).transform == (Object)null || DadsStoragePlugin.ChestsPickupFromGround.Value.IsOff()) { return; } ZNetView nview = itemDrop.m_nview; Fish val = default(Fish); if (!Object.op_Implicit((Object)(object)nview) || !nview.IsValid() || !Object.op_Implicit((Object)(object)itemDrop.m_itemData.m_dropPrefab) || (itemDrop.m_itemData.m_dropPrefab.TryGetComponent(ref val) && !val.IsOutOfWater() && !DadsStoragePlugin.FishSuction.Value.IsOn()) || nview.GetZDO() == null) { return; } if (!nview.IsOwner()) { if ((nview.HasOwner() && !SatLongEnoughToAskFor(itemDrop)) || !AnyContainerWants(itemDrop)) { return; } if (nview.HasOwner()) { try { itemDrop.RequestOwn(); return; } catch { return; } } try { nview.ClaimOwnership(); } catch { } if (!nview.IsOwner()) { return; } } bool flag = false; Vector3 position = ((Component)itemDrop).transform.position; for (int i = 0; i < Nearby.Count; i++) { NearbyContainer nearbyContainer = Nearby[i]; Container container = nearbyContainer.Container; if (!Object.op_Implicit((Object)(object)container) || !Object.op_Implicit((Object)(object)((Component)container).transform) || container.GetInventory() == null || (Object)(object)container.m_nview == (Object)null || !container.m_nview.IsValid()) { continue; } Vector3 val2 = nearbyContainer.Position - position; if (((Vector3)(ref val2)).sqrMagnitude > nearbyContainer.RangeSq || container.m_nview.GetZDO().GetBool(ContainerAwakePatch.storingPausedHash, false)) { continue; } if (!container.m_nview.IsOwner()) { if (container.m_nview.HasOwner() || IsContainerBeingUsed(container) || SharesRootZDO(container)) { continue; } container.m_nview.ClaimOwnership(); if (!container.m_nview.IsOwner()) { continue; } } if (container.IsInUse() || container.m_nview.GetZDO().GetInt(ZDOVars.s_inUse, 0) != 0) { continue; } LogDebug("Nearby item name: " + ((Object)itemDrop.m_itemData.m_dropPrefab).name); if (TryStore(container, ref itemDrop.m_itemData)) { flag = true; if (itemDrop.m_itemData.m_stack <= 0) { break; } } } if (!flag) { return; } itemDrop.Save(); if (itemDrop.m_itemData.m_stack <= 0) { if (!Object.op_Implicit((Object)(object)itemDrop.m_nview)) { Object.DestroyImmediate((Object)(object)((Component)itemDrop).gameObject); } else { ZNetScene.instance.Destroy(((Component)itemDrop).gameObject); } } } internal static bool TryStore(Container nearbyContainer, ref ItemData item, bool fromPlayer = false, bool singleItemData = false) { bool flag = false; LogIfBuildDebug("Checking container " + ((nearbyContainer != null) ? ((Object)nearbyContainer).name : null)); if (!Object.op_Implicit((Object)(object)nearbyContainer) || !MiscFunctions.CheckItemSharedIntegrity(item)) { return false; } Inventory inventory = nearbyContainer.GetInventory(); if (inventory == null) { return false; } if (DadsStoragePlugin.MustHaveExistingItemToPull.Value.IsOn() && !inventory.HaveItem(item.m_shared.m_name, true)) { if (singleItemData) { GameObject dropPrefab = item.m_dropPrefab; LogDebug("Skipping " + ((dropPrefab != null) ? ((Object)dropPrefab).name : null) + " because it is not in the container"); Player localPlayer = Player.m_localPlayer; string[] obj = new string[5] { "", item.m_shared.m_name, " [", null, null }; GameObject dropPrefab2 = item.m_dropPrefab; obj[3] = ((dropPrefab2 != null) ? ((Object)dropPrefab2).name : null); obj[4] = "] is not in nearby containers"; ((Character)localPlayer).Message((MessageType)2, string.Concat(obj), 0, (Sprite)null, false); } return false; } string prefabName = MiscFunctions.GetPrefabName(((Object)((Component)nearbyContainer).transform.root).name); GameObject dropPrefab3 = item.m_dropPrefab; if (!Boxes.CanItemBeStored(prefabName, ((dropPrefab3 != null) ? ((Object)dropPrefab3).name : null) ?? "")) { if (singleItemData) { Player localPlayer2 = Player.m_localPlayer; string[] obj2 = new string[5] { "", item.m_shared.m_name, " [", null, null }; GameObject dropPrefab4 = item.m_dropPrefab; obj2[3] = ((dropPrefab4 != null) ? ((Object)dropPrefab4).name : null); obj2[4] = "] cannot be stored based on configuration settings"; ((Character)localPlayer2).Message((MessageType)2, string.Concat(obj2), 0, (Sprite)null, false); } LogDebug(item.m_shared.m_name + " cannot be stored based on configuration setting"); return false; } if (!nearbyContainer.CheckAccess(Game.instance.GetPlayerProfile().GetPlayerID())) { LogDebug("Cannot store items in " + ((Object)nearbyContainer).name + " because the player does not have access."); return false; } int num; if (nearbyContainer.m_nview.IsOwner()) { num = InventoryMove.MoveStack(inventory, item); } else { num = TryStoreToOtherOwner(nearbyContainer, item); if (num <= 0) { LogDebug("Cannot store items in " + ((Object)nearbyContainer).name + ": not the owner and nothing to route the write through."); return false; } } flag = num > 0; if (!flag) { return flag; } if (!fromPlayer) { PingContainer(((Component)nearbyContainer).gameObject); } return flag; } private static Inventory PendingView(Inventory target) { if (PendingSends.TryGetValue(target, out Inventory value)) { return value; } value = InventoryHelper.CopyInventory(target); PendingSends[target] = value; return value; } internal static void ClearPendingSends() { PendingSends.Clear(); } internal static int TryStoreToOtherOwner(Container container, ItemData item) { if (!MUCCompat.CanRouteToOtherOwner) { return 0; } if (!container.m_nview.HasOwner()) { return 0; } if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return 0; } Inventory inventory = ((Humanoid)Player.m_localPlayer).GetInventory(); if (inventory == null || !inventory.ContainsItem(item)) { return 0; } Inventory inventory2 = container.GetInventory(); if (inventory2 == null) { return 0; } Inventory target = PendingView(inventory2); int num = InventoryMove.HowMuchFits(target, item); if (num <= 0) { return 0; } int stack = item.m_stack; inventory2.AddItem(item, num, -1, -1, false); int num2; if (!inventory.ContainsItem(item)) { item.m_stack = 0; num2 = stack; } else { num2 = stack - item.m_stack; } if (num2 > 0) { ItemData val = item.Clone(); val.m_stack = num2; InventoryMove.MoveStack(target, val); } return num2; } internal static bool SharesRootZDO(Container container) { return Object.op_Implicit((Object)(object)container.m_rootObjectOverride); } internal static bool IsContainerBeingUsed(Container container) { if (!container.m_nview.IsValid()) { return false; } if (container.m_nview.IsOwner()) { return container.IsInUse(); } return container.m_nview.GetZDO().GetInt(ZDOVars.s_inUse, 0) != 0; } internal static void TryStore() { if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return; } LogDebug("Trying to store items from player inventory"); Boxes.ContainersToPing.Clear(); ClearPendingSends(); int num = 0; foreach (DadsStorage.Interfaces.IContainer nearbyContainer in Boxes.GetNearbyContainers(Player.m_localPlayer, DadsStoragePlugin.PlayerRange.Value)) { num += StoreToContainer(nearbyContainer, null, null); } StoreSuccess(num); } internal static void TryStoreThisItem(ItemData itemData, Inventory m_inventory) { if (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || m_inventory != ((Humanoid)Player.m_localPlayer).GetInventory()) { return; } LogDebug("Trying to store " + itemData.m_shared.m_name); Boxes.ContainersToPing.Clear(); ClearPendingSends(); int num = 0; foreach (DadsStorage.Interfaces.IContainer nearbyContainer in Boxes.GetNearbyContainers(Player.m_localPlayer, DadsStoragePlugin.PlayerRange.Value)) { num += StoreToContainer(nearbyContainer, itemData, m_inventory); } StoreSuccess(num); } private static int StoreToContainer(DadsStorage.Interfaces.IContainer container, ItemData? singleItem, Inventory? inv) { //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) if (!(container is VanillaContainers vanillaContainers)) { if (singleItem != null) { return container.TryStoreThisItem(singleItem, inv); } return container.TryStore(); } if (!vanillaContainers.m_nview.IsValid()) { return 0; } ZDO val = null; if (!MUCCompat.CanRouteToOtherOwner) { Container component = vanillaContainers.gameObject.GetComponent(); if ((Object)(object)component != (Object)null && IsContainerBeingUsed(component)) { LogDebug("Skipping " + ((Object)vanillaContainers.gameObject).name + ": container is in use."); return 0; } Container component2 = vanillaContainers.gameObject.GetComponent(); if (!vanillaContainers.IsOwner()) { if ((Object)(object)component2 != (Object)null && SharesRootZDO(component2)) { return 0; } vanillaContainers.m_nview.ClaimOwnership(); } val = vanillaContainers.m_nview.GetZDO(); if (val != null) { val.Set(ZDOVars.s_inUse, 1, false); } if (val != null) { ZDOMan.instance.ForceSendZDO(ZNet.GetUID(), val.m_uid); } } int result = 0; try { result = ((singleItem == null) ? vanillaContainers.TryStore() : vanillaContainers.TryStoreThisItem(singleItem, inv)); } catch (Exception arg) { LogError($"Error while storing to {((Object)vanillaContainers.gameObject).name}: {arg}"); } finally { if (val != null) { val.Set(ZDOVars.s_inUse, 0, false); ZDOMan.instance.ForceSendZDO(ZNet.GetUID(), val.m_uid); } } return result; } internal static void StoreSuccess(int total) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) try { if (total <= 0) { return; } ((Character)Player.m_localPlayer).Message((MessageType)2, $"Stored {total} items from your inventory into nearby containers", 0, (Sprite)null, false); foreach (DadsStorage.Interfaces.IContainer item in Boxes.ContainersToPing) { PingContainer(item.gameObject); try { if (Object.op_Implicit((Object)(object)InventoryGui.instance) && (Object)(object)item.gameObject.GetComponent() != (Object)(object)InventoryGui.instance.m_currentContainer) { InventoryGui.instance.m_moveItemEffects.Create(item.gameObject.transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID)); } } catch (Exception arg) { DadsStoragePlugin.DadsStorageLogger.LogError((object)$"Error while playing move effect for container {((Object)item.gameObject).name}: {arg}"); } } } finally { Boxes.ContainersToPing.Clear(); ClearPendingSends(); } } internal static void PingContainer(GameObject container) { if (!((Object)(object)container == (Object)null)) { if (DadsStoragePlugin.PingContainers.Value.IsOn() && (Object)(object)container.GetComponent() == (Object)null) { container.AddComponent(); } if (DadsStoragePlugin.HighlightContainers.Value.IsOn() && (Object)(object)container.GetComponent() == (Object)null) { container.AddComponent(); } } } internal static void LogDebug(string data) { DadsStoragePlugin.DadsStorageLogger.LogDebug((object)data); } internal static void LogIfBuildDebug(string data) { } internal static void LogError(string data) { DadsStoragePlugin.DadsStorageLogger.LogError((object)data); } internal static void LogInfo(string data) { DadsStoragePlugin.DadsStorageLogger.LogInfo((object)data); } internal static void LogWarning(string data) { DadsStoragePlugin.DadsStorageLogger.LogWarning((object)data); } } public class GroupUtils { public static List GetExcludedGroups(string container) { if (DadsStoragePlugin.yamlData != null && DadsStoragePlugin.yamlData.TryGetValue(container, out object value) && value is Dictionary dictionary && dictionary.TryGetValue("exclude", out var value2) && value2 is List source) { return (from excludeItem in source where DadsStoragePlugin.groups.ContainsKey(excludeItem.ToString()) select excludeItem.ToString()).ToList(); } return new List(); } public static bool IsGroupDefined(string? groupName) { if (DadsStoragePlugin.yamlData == null) { DadsStoragePlugin.DadsStorageLogger.LogError((object)"yamlData is null. Make sure that your YAML file is not empty or to call DeserializeYamlFile() before using IsGroupDefined."); return false; } bool flag = false; if (DadsStoragePlugin.yamlData.ContainsKey("groups")) { if (DadsStoragePlugin.yamlData["groups"] is Dictionary dictionary) { if (groupName != null) { flag = dictionary.ContainsKey(groupName); } } else { DadsStoragePlugin.DadsStorageLogger.LogError((object)"Unable to cast groupsData to Dictionary."); } } if (!flag) { return DadsStoragePlugin.groups.ContainsKey(groupName); } return true; } public static bool GroupExists(string? groupName) { return DadsStoragePlugin.groups.ContainsKey(groupName); } public static List GetAllGroups() { return DadsStoragePlugin.groups.Keys.ToList(); } public static List GetItemsInGroup(string? groupName) { if (DadsStoragePlugin.groups.TryGetValue(groupName, out HashSet value)) { return value.ToList(); } return new List(); } } public class HighLightChest : MonoBehaviour { private WearNTear? wnt; private void Awake() { WearNTear val = default(WearNTear); wnt = (((Component)this).TryGetComponent(ref val) ? val : null); if ((Object)(object)wnt == (Object)null) { DestroyNow(); } else { Trigger(); } } public void Trigger() { ((MonoBehaviour)this).InvokeRepeating("DestroyNow", 10f, 1f); } public void DestroyNow() { Object.DestroyImmediate((Object)(object)this); } private void Update() { WearNTear? obj = wnt; if (obj != null) { obj.Highlight(); } } } internal static class InventoryMove { private static int FreeStackSpace(Inventory target, ItemData item, int max) { int num = 0; foreach (ItemData allItem in target.GetAllItems()) { if (!(allItem.m_shared.m_name != item.m_shared.m_name) && allItem.m_quality == item.m_quality && allItem.m_worldLevel == item.m_worldLevel && allItem.m_stack < max) { num += max - allItem.m_stack; } } return num; } internal static int HowMuchFits(Inventory target, ItemData item) { if (target == null || item == null || item.m_stack <= 0) { return 0; } int num = Mathf.Max(1, item.m_shared.m_maxStackSize); int num2 = FreeStackSpace(target, item, num); int num3 = target.m_width * target.m_height - target.m_inventory.Count; if (num3 > 0) { num2 += num3 * num; } return Math.Min(item.m_stack, num2); } internal static int MoveStack(Inventory target, ItemData sourceItem) { if (target == null || sourceItem == null || sourceItem.m_stack <= 0) { return 0; } int stack = sourceItem.m_stack; ItemData val = sourceItem.Clone(); int num = (target.AddItem(val) ? stack : (stack - val.m_stack)); sourceItem.m_stack -= num; return num; } } public class MiscFunctions { private static bool dataChanged; private static void LogResourceInfo(int totalAmount, int totalRequirement, string reqName) { DadsStoragePlugin.DadsStorageLogger.LogDebug((object)$"(ConsumeResourcesPatch) Have {totalAmount}/{totalRequirement} {reqName} in player inventory"); } public static string GetPrefabName(string name) { char[] anyOf = new char[2] { '(', ' ' }; int num = name.IndexOfAny(anyOf); if (num >= 0) { return name.Substring(0, num); } return name; } internal static GameObject? GetItemPrefabFromGameObject(ItemDrop itemDropComponent, GameObject inputGameObject) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(GetPrefabName(((Object)inputGameObject).name)); itemDropComponent.m_itemData.m_dropPrefab = itemPrefab; if (!((Object)(object)itemPrefab != (Object)null)) { return null; } return itemPrefab; } internal static bool CheckItemDropIntegrity(ItemDrop itemDropComp) { if (itemDropComp.m_itemData == null) { return false; } return itemDropComp.m_itemData.m_shared != null; } internal static bool CheckItemSharedIntegrity(ItemData itemData) { return itemData.m_shared != null; } internal static void CreatePredefinedGroups(ObjectDB __instance) { //IL_01bb: 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_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Expected I4, but got Unknown //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0281: Expected I4, but got Unknown //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Invalid comparison between Unknown and I4 foreach (GameObject item in __instance.m_items.Where((GameObject x) => (Object)(object)x.GetComponentInChildren() != (Object)null)) { ItemDrop componentInChildren = item.GetComponentInChildren(); if (!CheckItemDropIntegrity(componentInChildren)) { continue; } GameObject? itemPrefabFromGameObject = GetItemPrefabFromGameObject(componentInChildren, item); componentInChildren.m_itemData.m_dropPrefab = ((Component)componentInChildren).gameObject; if (!((Object)(object)itemPrefabFromGameObject != (Object)null)) { continue; } SharedData sharedData = componentInChildren.m_itemData.m_shared; List list = new List(); if ((double)sharedData.m_food > 0.0 && (double)sharedData.m_foodStamina > 0.0) { list.Add("Food"); } if ((Object)(object)sharedData.m_consumeStatusEffect != (Object)null) { if (((double)sharedData.m_food > 0.0 && (double)sharedData.m_foodStamina == 0.0) || ((Object)sharedData.m_consumeStatusEffect).name.ToLower().Contains("potion") || sharedData.m_consumeStatusEffect.m_name.ToLower().Contains("potion") || sharedData.m_consumeStatusEffect.m_category.ToLower().Contains("potion") || sharedData.m_ammoType.ToLower().Contains("mead")) { list.Add("Potion"); } else if ((int)sharedData.m_itemType == 21) { list.Add("Fish"); } } ItemType itemType = sharedData.m_itemType; switch (itemType - 1) { case 2: case 3: case 13: case 21: { bool flag = true; SkillType skillType = sharedData.m_skillType; switch (skillType - 1) { case 0: list.Add("Swords"); break; case 7: list.Add("Bows"); break; case 13: list.Add("Crossbows"); break; case 6: list.Add("Axes"); break; case 2: list.Add("Clubs"); break; case 1: list.Add("Knives"); break; case 11: list.Add("Pickaxes"); break; case 3: list.Add("Polearms"); break; case 4: list.Add("Spears"); break; case 8: list.Add("ElementalMagic"); break; case 9: list.Add("BloodMagic"); break; default: flag = false; break; } if (flag) { list.Add("Weapons"); } break; } case 4: list.Add("Shield"); list.Add(((double)sharedData.m_timedBlockBonus > 0.0) ? "Round Shield" : "Tower Shield"); break; case 5: list.AddRange(new <>z__ReadOnlyArray(new string[2] { "Armor", "Helmet" })); break; case 6: list.AddRange(new <>z__ReadOnlyArray(new string[2] { "Armor", "Chest" })); break; case 10: list.AddRange(new <>z__ReadOnlyArray(new string[2] { "Armor", "Legs" })); break; case 16: list.AddRange(new <>z__ReadOnlyArray(new string[2] { "Armor", "Shoulder" })); break; case 17: list.AddRange(new <>z__ReadOnlySingleElementList("Utility")); break; case 23: list.AddRange(new <>z__ReadOnlySingleElementList("Trinket")); break; case 8: { string ammoType = sharedData.m_ammoType; if (ammoType != "$ammo_bolts") { if (ammoType == "$ammo_arrows") { list.Add("Arrows"); } } else { list.Add("Bolts"); } list.Add("Ammo"); break; } case 14: case 18: list.Add("Equipment"); break; case 12: { string[] source = new string[6] { "eikthyr", "elder", "bonemass", "dragonqueen", "goblinking", "SeekerQueen" }; list.Add(source.Any(sharedData.m_name.EndsWith) ? "Boss Trophy" : "Trophy"); break; } case 0: { GameObject val = ((IEnumerable)ObjectDB.instance.GetItemPrefab("Cultivator").GetComponent().m_itemData.m_shared.m_buildPieces.m_pieces).FirstOrDefault((Func)delegate(GameObject p) { Requirement[] resources = p.GetComponent().m_resources; return resources.Length == 1 && resources[0].m_resItem.m_itemData.m_shared.m_name == sharedData.m_name; }); if (val != null) { Plant component = val.GetComponent(); list.Add((component != null && component.m_grownPrefabs[0].GetComponent()?.m_amount > 1) ? "Crops" : "Seeds"); } if (ZNetScene.instance.GetPrefab("smelter").GetComponent().m_conversion.Any((ItemConversion c) => c.m_from.m_itemData.m_shared.m_name == sharedData.m_name)) { list.Add("Ores"); } if (ZNetScene.instance.GetPrefab("smelter").GetComponent().m_conversion.Any((ItemConversion c) => c.m_to.m_itemData.m_shared.m_name == sharedData.m_name)) { list.Add("Metals"); } if (ZNetScene.instance.GetPrefab("blastfurnace").GetComponent().m_conversion.Any((ItemConversion c) => c.m_from.m_itemData.m_shared.m_name == sharedData.m_name)) { list.Add("Ores"); } if (ZNetScene.instance.GetPrefab("blastfurnace").GetComponent().m_conversion.Any((ItemConversion c) => c.m_to.m_itemData.m_shared.m_name == sharedData.m_name)) { list.Add("Metals"); } if (ZNetScene.instance.GetPrefab("charcoal_kiln").GetComponent().m_conversion.Any((ItemConversion c) => c.m_from.m_itemData.m_shared.m_name == sharedData.m_name)) { list.Add("Woods"); } if (sharedData.m_name == "$item_elderbark") { list.Add("Woods"); } break; } } foreach (string item2 in list) { if (!string.IsNullOrEmpty(item2)) { AddItemToGroup(item2, componentInChildren); } } if (sharedData != null) { AddItemToGroup("All", componentInChildren); } } SaveGroupsToFile(); } private static void AddItemToGroup(string? groupName, ItemDrop itemDrop) { if (!GroupUtils.GroupExists(groupName)) { DadsStoragePlugin.groups[groupName] = new HashSet(); } string prefabName = Utils.GetPrefabName(itemDrop.m_itemData.m_dropPrefab); if (!DadsStoragePlugin.groups[groupName].Contains(prefabName)) { DadsStoragePlugin.groups[groupName].Add(prefabName); DadsStoragePlugin.DadsStorageLogger.LogDebug((object)("(CreatePredefinedGroups) Added " + prefabName + " to " + groupName)); } } private static void SaveGroupsToFile() { if (!dataChanged) { return; } using StreamWriter streamWriter = new StreamWriter(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? string.Empty, "DadsStorage_PredefinedGroups.txt"), append: false); foreach (string item in DadsStoragePlugin.groups.Keys.OrderBy((string x) => x)) { streamWriter.WriteLine(item); if (item == null) { continue; } foreach (string item2 in DadsStoragePlugin.groups[item].OrderBy((string x) => x)) { streamWriter.WriteLine("\t" + item2); } } dataChanged = false; } } } namespace DadsStorage.Patches { [HarmonyPatch(typeof(Container), "Awake")] internal static class ContainerAwakePatch { internal static int pausedSeconds = 0; internal static readonly int storingPausedHash = StringExtensionMethods.GetStableHashCode("storingPaused"); internal static bool TryAddContainer(Container container) { //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)container) || (Object)(object)container.m_nview == (Object)null || container.m_nview.GetZDO() == null) { return false; } Character componentInParent = ((Component)container).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null && (Object)(object)componentInParent != (Object)(object)Player.m_localPlayer) { return false; } if (!container.m_nview.IsValid() || container.GetInventory() == null) { return false; } if (container.m_nview.GetZDO().GetLong(ZDOVars.s_creator, 0L) == 0L) { return false; } try { if (WardIsLovePlugin.IsLoaded() && WardIsLovePlugin.WardEnabled().Value) { if (!WardMonoscript.CheckAccess(((Component)container).transform.position, 0f, flash: false, wardCheck: true)) { return false; } Boxes.AddContainer(container); return true; } if (PrivateArea.CheckAccess(((Component)container).transform.position, 0f, false, true)) { Boxes.AddContainer(container); return true; } } catch { } return false; } private static void Postfix(Container __instance) { Functions.LogContainerStatus(__instance); if (!((Object)(object)__instance.m_nview == (Object)null) && __instance.m_nview.GetZDO() != null) { __instance.m_nview.Unregister("RequestPause"); __instance.m_nview.Register("RequestPause", (Action)delegate(long sender, bool pause) { Boxes.RPC_RequestPause(sender, pause, __instance); }); TryAddContainer(__instance); } } } [HarmonyPatch(typeof(Container), "OnDestroyed")] internal static class ContainerOnDestroyedPatch { private static void Postfix(Container __instance) { if (__instance.m_nview.GetZDO().GetLong(ZDOVars.s_creator, 0L) != 0L && __instance.GetInventory() != null && __instance.m_nview.IsValid()) { Boxes.RemoveContainer(__instance); } } } [HarmonyPatch(typeof(WearNTear), "OnDestroy")] internal static class WearNTearOnDestroyPatch { private static readonly List Found = new List(); private static void Prefix(WearNTear __instance) { if (Boxes.Containers.Count != 0) { Found.Clear(); ((Component)__instance).GetComponentsInChildren(Found); for (int i = 0; i < Found.Count; i++) { Boxes.RemoveContainer(Found[i]); } Found.Clear(); ((Component)__instance).GetComponentsInParent(false, Found); for (int j = 0; j < Found.Count; j++) { Boxes.RemoveContainer(Found[j]); } Found.Clear(); } } } [HarmonyPatch(typeof(Container), "SetInUse")] internal static class ContainerSetInUseClearWithoutOwnershipPatch { private static void Prefix(Container __instance, bool inUse) { if (!inUse && !__instance.m_nview.IsOwner()) { __instance.m_inUse = false; } } } [HarmonyPatch(typeof(Container), "Interact")] internal static class ContainerInteractPatch { private static void Postfix(Container __instance, Humanoid character, bool hold, bool alt) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) long playerID = Game.instance.GetPlayerProfile().GetPlayerID(); if ((!__instance.m_checkGuardStone || PrivateArea.CheckAccess(((Component)__instance).transform.position, 0f, true, false)) && __instance.CheckAccess(playerID)) { ContainerAwakePatch.TryAddContainer(__instance); } } } [HarmonyPatch(typeof(Player), "OnSpawned")] internal static class PlayerOnSpawnedContainerScanPatch { private static void Postfix(Player __instance) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { Container[] array = Resources.FindObjectsOfTypeAll(); for (int i = 0; i < array.Length; i++) { ContainerAwakePatch.TryAddContainer(array[i]); } } } } [HarmonyPatch(typeof(ZNetScene), "Awake")] internal static class ZNetSceneAwakePatch { private static void Postfix(ZNetScene __instance) { Container[] array = Resources.FindObjectsOfTypeAll(); foreach (Container val in array) { Functions.LogIfBuildDebug("Found container by the name of " + ((Object)val).name + " in your game."); } } } [HarmonyPatch(typeof(Player), "UpdateTeleport")] public static class PlayerUpdateTeleportPatchCleanupContainers { public static void Prefix(float dt) { if (!((Object)(object)Player.m_localPlayer == (Object)null) && Player.m_localPlayer.m_teleporting) { Boxes.PruneDestroyed(); } } } [HarmonyPatch(typeof(Inventory), "StackAll", new Type[] { typeof(Inventory), typeof(bool) })] public static class Inventory_StackAll_Patch { public static IEnumerable Transpiler(IEnumerable instructions) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Expected O, but got Unknown //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(Inventory), "GetAllItems", Type.EmptyTypes, (Type[])null); ConstructorInfo constructorInfo = AccessTools.Constructor(typeof(List), new Type[1] { typeof(IEnumerable) }, false); MethodInfo methodInfo2 = AccessTools.DeclaredMethod(typeof(Inventory_StackAll_Patch), "FilterItems", (Type[])null, (Type[])null); return new CodeMatcher(instructions, (ILGenerator)null).MatchForward(false, (CodeMatch[])(object)new CodeMatch[2] { new CodeMatch((OpCode?)OpCodes.Callvirt, (object)methodInfo, (string)null), new CodeMatch((OpCode?)OpCodes.Newobj, (object)constructorInfo, (string)null) }).Advance(2).Insert((CodeInstruction[])(object)new CodeInstruction[2] { new CodeInstruction(OpCodes.Ldarg_1, (object)null), new CodeInstruction(OpCodes.Call, (object)methodInfo2) }) .InstructionEnumeration(); } public static List FilterItems(List items, Inventory fromInventory) { if (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || fromInventory != ((Humanoid)Player.m_localPlayer).GetInventory()) { return items; } return items.Where(ShouldIncludeItem).ToList(); } public static bool ShouldIncludeItem(ItemData item) { return !VanillaContainers.CantStoreFavorite(item, UserConfig.GetPlayerConfig(Player.m_localPlayer.GetPlayerID())); } } [HarmonyPatch(typeof(InventoryGrid), "UpdateGui")] internal static class InventoryGridGetHoveredElementPatch { private static void Prefix(InventoryGrid __instance) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) InventoryElement val = ((__instance.m_uiGroup.IsActive && ZInput.IsGamepadActive()) ? __instance.GetElement(__instance.m_selected.x, __instance.m_selected.y, __instance.m_inventory.GetWidth()) : __instance.GetHoveredElement()); if (!((Object)(object)val == (Object)null) && DadsStoragePlugin.SingleItemShortcut.Value.IsKeyDown()) { ItemData itemAt = __instance.m_inventory.GetItemAt(val.Position.x, val.Position.y); if (itemAt != null && __instance.m_inventory != null) { Functions.TryStoreThisItem(itemAt, __instance.m_inventory); } } } } [HarmonyPatch(typeof(ObjectDB), "Awake")] internal static class PredefinedGroupGrab { private static void Postfix(ObjectDB __instance) { if (Object.op_Implicit((Object)(object)ZNetScene.instance)) { MiscFunctions.CreatePredefinedGroups(__instance); } } } } namespace DadsStorage.Patches.Favoriting { [HarmonyPatch(typeof(InventoryGrid), "UpdateGui")] internal static class BorderRenderer { public static Sprite Border; public const string BorderName = "DadsStorageFavoritingBorder"; [HarmonyPostfix] [HarmonyAfter(new string[] { "goldenrevolver.quick_stack_store" })] [HarmonyPriority(300)] private static void UpdateGui(InventoryGrid __instance, Player player, Inventory ___m_inventory, List ___m_elements) { //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || ((Humanoid)player).m_inventory != ___m_inventory) { return; } int width = ___m_inventory.GetWidth(); UserConfig playerConfig = UserConfig.GetPlayerConfig(player.GetPlayerID()); for (int i = 0; i < ___m_inventory.GetHeight(); i++) { for (int j = 0; j < ___m_inventory.GetWidth(); j++) { int index = i * width + j; object obj = ((((Component)___m_elements[index].m_queued).transform.childCount > 0 && (Object)(object)Utils.FindChild(((Component)___m_elements[index].m_queued).transform, "DadsStorageFavoritingBorder", (IterativeSearchType)0) != (Object)null) ? ((object)((Component)Utils.FindChild(((Component)___m_elements[index].m_queued).transform, "DadsStorageFavoritingBorder", (IterativeSearchType)0)).GetComponent()) : ((object)CreateBorderImage(___m_elements[index].m_queued))); ((Graphic)obj).color = DadsStoragePlugin.BorderColorFavoritedSlot.Value; ((Behaviour)obj).enabled = playerConfig.IsSlotFavorited(new Vector2i(j, i)); } } foreach (ItemData item in ___m_inventory.m_inventory) { int index2 = item.GridVectorToGridIndex(width); Image val = (Image)((((Component)___m_elements[index2].m_queued).transform.childCount > 0 && (Object)(object)Utils.FindChild(((Component)___m_elements[index2].m_queued).transform, "DadsStorageFavoritingBorder", (IterativeSearchType)0) != (Object)null) ? ((object)((Component)Utils.FindChild(((Component)___m_elements[index2].m_queued).transform, "DadsStorageFavoritingBorder", (IterativeSearchType)0)).GetComponent()) : ((object)CreateBorderImage(___m_elements[index2].m_queued))); bool flag = playerConfig.IsItemNameFavorited(item.m_shared); if (flag) { ((Graphic)val).color = (((Behaviour)val).enabled ? DadsStoragePlugin.BorderColorFavoritedItemOnFavoritedSlot.Value : DadsStoragePlugin.BorderColorFavoritedItem.Value); ((Behaviour)val).enabled = ((Behaviour)val).enabled || flag; } } } private static Image CreateBorderImage(Image baseImg) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) Image val = Object.Instantiate(baseImg, ((Component)baseImg).transform); foreach (Transform item in ((Component)val).transform) { Object.Destroy((Object)(object)((Component)item).gameObject); } ((Object)val).name = "DadsStorageFavoritingBorder"; ((Component)val).transform.SetParent(((Component)baseImg).transform); val.sprite = Border; return val; } } public static class ItemDataExtension { public static int GridVectorToGridIndex(this ItemData item, int width) { return item.m_gridPos.y * width + item.m_gridPos.x; } } internal class ButtonRenderer { internal class MainButtonUpdate { internal static void UpdateInventoryGuiButtons(InventoryGui __instance) { if (hasOpenedInventoryOnce && !((Object)(object)__instance != (Object)(object)InventoryGui.instance) && Object.op_Implicit((Object)(object)Player.m_localPlayer)) { FavoritingMode.HasCurrentlyToggledFavoriting = false; } } } internal static bool hasOpenedInventoryOnce; internal static Button favoritingTogglingButton; internal static IEnumerator WaitAFrameToUpdateUIElements(InventoryGui instance, bool includeTrashButton) { yield return null; if (!((Object)(object)instance == (Object)null)) { MainButtonUpdate.UpdateInventoryGuiButtons(instance); } } } internal class FavoritingMode { private static bool hasCurrentlyToggledFavoriting; internal static bool HasCurrentlyToggledFavoriting { get { return hasCurrentlyToggledFavoriting; } set { hasCurrentlyToggledFavoriting = value; } } internal static void RefreshDisplay() { HasCurrentlyToggledFavoriting = HasCurrentlyToggledFavoriting; } internal static bool IsInFavoritingMode() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (!HasCurrentlyToggledFavoriting && !DadsStoragePlugin.FavoritingModifierKeybind1.Value.IsKeyHeld() && !DadsStoragePlugin.FavoritingModifierKeybind2.Value.IsKeyHeld()) { return DadsStoragePlugin.SearchModifierKeybind.Value.IsKeyHeld(); } return true; } } [HarmonyPatch(typeof(InventoryGrid))] internal class InventoryGridButtonHandlingPatches { [HarmonyPatch("OnRightDown")] [HarmonyPrefix] internal static bool OnRightClick(InventoryGrid __instance, UIInputHandler element) { return HandleClick(__instance, element, isLeftClick: false); } [HarmonyPatch("OnLeftDown")] [HarmonyPrefix] internal static bool OnLeftDown(InventoryGrid __instance, UIInputHandler clickHandler) { return HandleClick(__instance, clickHandler, isLeftClick: true); } internal static bool HandleClick(InventoryGrid __instance, UIInputHandler clickHandler, bool isLeftClick) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) Vector2i buttonPos = __instance.GetButtonPos(((Component)clickHandler).gameObject); return HandleClick(__instance, buttonPos, isLeftClick, DadsStoragePlugin.SearchModifierKeybind.Value.IsKeyHeld()); } [HarmonyPatch("UpdateGamepad")] private static void Postfix(InventoryGrid __instance) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)__instance != (Object)(object)InventoryGui.instance.m_playerGrid) && __instance.m_uiGroup.IsActive) { if (ZInput.GetButtonDown("JoyButtonA")) { HandleClick(__instance, __instance.m_selected, isLeftClick: true); } else if (ZInput.GetButtonDown("JoyButtonX")) { HandleClick(__instance, __instance.m_selected, isLeftClick: false); } } } internal static bool HandleClick(InventoryGrid __instance, Vector2i buttonPos, bool isLeftClick, bool searchBypass = false) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_0070: 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) if ((Object)(object)InventoryGui.instance.m_playerGrid != (Object)(object)__instance) { return true; } Player localPlayer = Player.m_localPlayer; if (((Character)localPlayer).IsTeleporting()) { return true; } if (Object.op_Implicit((Object)(object)InventoryGui.instance.m_dragGo)) { return true; } if (!FavoritingMode.IsInFavoritingMode()) { return true; } if (buttonPos == new Vector2i(-1, -1)) { return true; } if (!isLeftClick) { UserConfig.GetPlayerConfig(localPlayer.GetPlayerID()).ToggleSlotFavoriting(buttonPos); } else if (searchBypass) { ItemData itemAt = __instance.m_inventory.GetItemAt(buttonPos.x, buttonPos.y); if (itemAt == null) { return true; } ((Terminal)Chat.instance).TryRunCommand("dadsstoragesearch " + ((Object)itemAt.m_dropPrefab).name.ToLower(), false, true); } else { ItemData itemAt2 = __instance.m_inventory.GetItemAt(buttonPos.x, buttonPos.y); if (itemAt2 == null) { return true; } UserConfig.GetPlayerConfig(localPlayer.GetPlayerID()).ToggleItemNameFavoriting(itemAt2.m_shared); } return false; } } [HarmonyPatch(typeof(InventoryGui), "Show")] internal static class InventoryGuiShowPatch { [HarmonyPriority(300)] private static void Postfix(InventoryGui __instance) { ButtonRenderer.hasOpenedInventoryOnce = true; ButtonRenderer.MainButtonUpdate.UpdateInventoryGuiButtons(__instance); } } [HarmonyPatch(typeof(InventoryGui), "Hide")] internal static class InventoryGuiHidePatch { [HarmonyPriority(300)] private static void Postfix(InventoryGui __instance) { FavoritingMode.HasCurrentlyToggledFavoriting = false; } } [HarmonyPatch(typeof(ItemData))] internal static class TooltipRenderer { [HarmonyPatch("GetTooltip", new Type[] { typeof(ItemData), typeof(int), typeof(bool), typeof(float), typeof(int), typeof(bool) })] [HarmonyPostfix] public static void GetTooltip(ItemData item, bool crafting, ref string __result) { //IL_009c: 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_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) if (!crafting && DadsStoragePlugin.DisplayTooltipHint.Value) { StringBuilder stringBuilder = new StringBuilder(256); stringBuilder.Append(__result); UserConfig playerConfig = UserConfig.GetPlayerConfig(Player.m_localPlayer.GetPlayerID()); if (playerConfig.IsItemNameFavorited(item.m_shared)) { string text = ColorUtility.ToHtmlStringRGB(DadsStoragePlugin.BorderColorFavoritedItem.Value); stringBuilder.Append(Environment.NewLine + "" + DadsStoragePlugin.FavoritedItemTooltip.Value + ""); } else if (playerConfig.IsSlotFavorited(item.m_gridPos)) { string text2 = ColorUtility.ToHtmlStringRGB(DadsStoragePlugin.BorderColorFavoritedSlot.Value); stringBuilder.Append(Environment.NewLine + "" + DadsStoragePlugin.FavoritedSlotTooltip.Value + ""); } else if (playerConfig.IsSlotFavorited(item.m_gridPos) && playerConfig.IsItemNameFavorited(item.m_shared)) { string text3 = ColorUtility.ToHtmlStringRGB(DadsStoragePlugin.BorderColorFavoritedItemOnFavoritedSlot.Value); stringBuilder.Append(Environment.NewLine + "" + DadsStoragePlugin.ItemOnFavoritedSlotTooltip.Value + ""); } __result = stringBuilder.ToString(); } } } public class UserConfig { private static readonly Dictionary PlayerConfigs = new Dictionary(); private readonly string _configPath; private readonly string[] _mirrorPaths; private HashSet _favoritedSlots; private HashSet _favoritedItems; private static readonly BinaryFormatter Bf = new BinaryFormatter(); public static UserConfig GetPlayerConfig(long playerID) { if (PlayerConfigs.TryGetValue(playerID, out UserConfig value)) { return value; } value = new UserConfig(playerID); PlayerConfigs[playerID] = value; return value; } public UserConfig(long uid) { string text = Path.Combine(Paths.ConfigPath, string.Format("{0}_player_{1}.dat", "DadsStorage", uid)); string text2 = Path.Combine(Paths.ConfigPath, $"DadsEPI_player_{uid}.dat"); if (Chainloader.PluginInfos.ContainsKey("goldenrevolver.quick_stack_store")) { _configPath = Path.Combine(Paths.ConfigPath, $"QuickStackStore_player_{uid}.dat"); _mirrorPaths = new string[2] { text, text2 }; } else { _configPath = text; _mirrorPaths = new string[1] { text2 }; } Load(); } internal void ResetAllFavoriting() { DadsStoragePlugin.DadsStorageLogger.LogWarning((object)"Resetting all favoriting data!"); _favoritedSlots = new HashSet(); _favoritedItems = new HashSet(); Save(); } private void Save() { WriteFile(_configPath); foreach (string item in _mirrorPaths.Where(File.Exists)) { try { WriteFile(item); } catch (Exception ex) when (((ex is IOException || ex is UnauthorizedAccessException) ? 1 : 0) != 0) { DadsStoragePlugin.DadsStorageLogger.LogWarning((object)("Couldn't sync favorites to " + item + ": " + ex.Message)); } } } private void WriteFile(string path) { using Stream serializationStream = File.Open(path, FileMode.Create); List> graph = _favoritedSlots.Select((Vector2i item) => new Tuple(item.x, item.y)).ToList(); Bf.Serialize(serializationStream, graph); Bf.Serialize(serializationStream, _favoritedItems.ToList()); } private static object TryDeserialize(Stream stream) { try { return Bf.Deserialize(stream); } catch (SerializationException) { return null; } } private static void LoadProperty(Stream file, out T property) where T : new() { if (TryDeserialize(file) is T val) { property = val; } else { property = new T(); } } private void Load() { _favoritedSlots = new HashSet(); _favoritedItems = new HashSet(); foreach (string item in _mirrorPaths.Prepend(_configPath).Where(File.Exists)) { try { ReadFileInto(item); } catch (Exception ex) when (((ex is IOException || ex is UnauthorizedAccessException) ? 1 : 0) != 0) { DadsStoragePlugin.DadsStorageLogger.LogWarning((object)("Couldn't read favorites from " + item + ": " + ex.Message)); } } } private void ReadFileInto(string path) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) using Stream file = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read); List> property = new List>(); LoadProperty>>(file, out property); if (property != null) { foreach (Tuple item in property) { _favoritedSlots.Add(new Vector2i(item.Item1, item.Item2)); } } List property2 = new List(); LoadProperty>(file, out property2); if (property2 == null) { return; } foreach (string item2 in property2) { _favoritedItems.Add(item2); } } public void ToggleSlotFavoriting(Vector2i position) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) _favoritedSlots.XAdd(position); Save(); } public bool ToggleItemNameFavoriting(SharedData item) { _favoritedItems.XAdd(item.m_name); Save(); return true; } public bool IsSlotFavorited(Vector2i position) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return _favoritedSlots.Contains(position); } public bool IsItemNameFavorited(SharedData item) { return _favoritedItems.Contains(item.m_name); } public bool IsItemNameOrSlotFavorited(ItemData item) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) if (!IsItemNameFavorited(item.m_shared)) { return IsSlotFavorited(item.m_gridPos); } return true; } } public static class CollectionExtension { public static bool XAdd(this HashSet instance, T item) { if (instance.Contains(item)) { instance.Remove(item); return false; } instance.Add(item); return true; } } } namespace DadsStorage.Managers { [HarmonyPatch(typeof(Game), "Start")] public static class GameStartPatch { private static void Postfix() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)DadsStorageItemDropManager.Instance)) { Object.DontDestroyOnLoad((Object)(object)new GameObject("DadsStorage_ItemDropManager").AddComponent()); } } } public class DadsStorageItemDropManager : MonoBehaviour { internal static DadsStorageItemDropManager? Instance; private static readonly List DropBuffer = new List(); private void Awake() { Instance = this; ((MonoBehaviour)this).InvokeRepeating("ProcessItemDrops", DadsStoragePlugin.IntervalSeconds.Value, DadsStoragePlugin.IntervalSeconds.Value); DadsStoragePlugin.IntervalSeconds.SettingChanged += OnIntervalSecondsChanged; } private void OnDestroy() { DadsStoragePlugin.IntervalSeconds.SettingChanged -= OnIntervalSecondsChanged; DropBuffer.Clear(); Functions.ClearNearbyContainers(); if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } private void ProcessItemDrops() { if (ShouldPause() || Boxes.Containers == null || Boxes.Containers.Count == 0) { return; } DropBuffer.Clear(); List s_instances = ItemDrop.s_instances; for (int i = 0; i < s_instances.Count; i++) { ItemDrop val = s_instances[i]; if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).transform == (Object)null) && !((Object)(object)val.m_nview == (Object)null) && val.m_nview.IsValid() && !val.IsPiece()) { DropBuffer.Add(val); } } if (DropBuffer.Count == 0) { return; } try { Functions.BuildNearbyContainers(); for (int j = 0; j < DropBuffer.Count; j++) { Functions.CheckItemDropInstanceAndStore(DropBuffer[j]); } } finally { Functions.ClearNearbyContainers(); DropBuffer.Clear(); } } private void OnIntervalSecondsChanged(object sender, EventArgs e) { ((MonoBehaviour)this).CancelInvoke("ProcessItemDrops"); ((MonoBehaviour)this).InvokeRepeating("ProcessItemDrops", DadsStoragePlugin.IntervalSeconds.Value, DadsStoragePlugin.IntervalSeconds.Value); } private static bool ShouldPause() { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && !((Character)localPlayer).IsTeleporting()) { return ((Character)localPlayer).IsDead(); } return true; } } } namespace DadsStorage.Interfaces { public class BackpackContainer(ItemContainer _container) : IContainer { public GameObject gameObject => ((Component)Player.m_localPlayer).gameObject; public ZNetView m_nview => ((Character)Player.m_localPlayer).m_nview; public static bool CantStoreFavorite(ItemData item, UserConfig playerConfig) { return playerConfig.IsItemNameOrSlotFavorited(item); } internal static void LogDebug(string data) { DadsStoragePlugin.DadsStorageLogger.LogDebug((object)data); } public int TryStore() { if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return 0; } int num = 0; Inventory inventory = ((Humanoid)Player.m_localPlayer).GetInventory(); List allItems = inventory.GetAllItems(); for (int num2 = allItems.Count - 1; num2 >= 0; num2--) { ItemData item = allItems[num2]; if (item.m_equipped) { LogDebug("Skipping equipped item " + ((Object)item.m_dropPrefab).name); } else { int x = item.m_gridPos.x; if (x >= 0 && x <= 8 && item.m_gridPos.y == 0 && DadsStoragePlugin.PlayerIgnoreHotbar.Value.IsOn()) { LogDebug("Skipping item " + ((Object)item.m_dropPrefab).name + " because it is in the hotbar"); } else if (DadsEPICompat.IsLoaded() && DadsEPICompat.GetQuickSlotsItems().Any((ItemData quickSlotItem) => quickSlotItem.m_gridPos == item.m_gridPos)) { LogDebug("Skipping item " + ((Object)item.m_dropPrefab).name + " because it is in your quick slots"); } else if (CantStoreFavorite(item, UserConfig.GetPlayerConfig(Player.m_localPlayer.GetPlayerID()))) { LogDebug("Skipping favorited item/slot " + ((Object)item.m_dropPrefab).name); } else { LogDebug("Checking item " + ((Object)item.m_dropPrefab).name); int stack = item.m_stack; if (TryStore(_container, ref item, fromPlayer: true)) { int num3 = stack - item.m_stack; if (num3 > 0) { num += num3; if (item.m_stack == 0) { inventory.RemoveItem(item); } else { inventory.Changed(false, false); } LogDebug($"Stored {num3} {((Object)item.m_dropPrefab).name} into {((Object)_container.Item.m_dropPrefab).name}"); if (!Boxes.ContainersToPing.Contains(this)) { Boxes.ContainersToPing.Add(this); } } } } } } return num; } public int TryStoreThisItem(ItemData? singleItemData = null, Inventory? playerInventory = null) { if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return 0; } Inventory val = playerInventory ?? ((Humanoid)Player.m_localPlayer).GetInventory(); if (singleItemData == null) { return 0; } ItemData item = singleItemData; if (item.m_equipped) { LogDebug("Skipping equipped item " + ((Object)item.m_dropPrefab).name); return 0; } int x = item.m_gridPos.x; if (x >= 0 && x <= 8 && item.m_gridPos.y == 0 && DadsStoragePlugin.PlayerIgnoreHotbar.Value.IsOn()) { LogDebug("Skipping item " + ((Object)item.m_dropPrefab).name + " because it is in the hotbar"); return 0; } if (DadsEPICompat.IsLoaded() && DadsEPICompat.GetQuickSlotsItems().Any((ItemData quickSlotItem) => quickSlotItem.m_gridPos == item.m_gridPos)) { LogDebug("Skipping item " + ((Object)item.m_dropPrefab).name + " because it is in your quick slots"); return 0; } if (CantStoreFavorite(item, UserConfig.GetPlayerConfig(Player.m_localPlayer.GetPlayerID()))) { LogDebug("Skipping favorited item/slot " + ((Object)item.m_dropPrefab).name); return 0; } LogDebug("Checking item " + ((Object)item.m_dropPrefab).name); int stack = item.m_stack; if (!TryStore(_container, ref item, fromPlayer: true, singleItemData: true)) { return 0; } int num = stack - item.m_stack; if (num <= 0) { return 0; } if (item.m_stack == 0) { val.RemoveItem(item); } else { val.Changed(false, false); } LogDebug($"Stored {num} {((Object)item.m_dropPrefab).name} into {((Object)_container.Item.m_dropPrefab).name}"); if (!Boxes.ContainersToPing.Contains(this)) { Boxes.ContainersToPing.Add(this); } return num; } internal bool TryStore(ItemContainer nearbyContainer, ref ItemData item, bool fromPlayer = false) { bool flag = false; LogDebug("Checking container " + ((Object)nearbyContainer.Item.m_dropPrefab).name); if (!MiscFunctions.CheckItemSharedIntegrity(item)) { return flag; } if (DadsStoragePlugin.MustHaveExistingItemToPull.Value.IsOn() && !nearbyContainer.Inventory.HaveItem(item.m_shared.m_name, true)) { return false; } if (!Boxes.CanItemBeStored(MiscFunctions.GetPrefabName(((Object)nearbyContainer.Item.m_dropPrefab).name), ((Object)item.m_dropPrefab).name)) { return false; } while (item.m_stack > 0 && nearbyContainer.CanAddItem(item)) { ItemData val = item.Clone(); val.m_stack = 1; API.AddItemToBackpack(_container.Item, val); ItemData obj = item; obj.m_stack--; flag = true; LogDebug("Auto storing " + ((Object)item.m_dropPrefab).name + " in " + ((Object)nearbyContainer.Item.m_dropPrefab).name); } if (!flag) { return flag; } if (!fromPlayer) { Functions.PingContainer(((Component)Player.m_localPlayer).gameObject); } nearbyContainer.Save(); return flag; } internal static bool TryStore(ItemContainer nearbyContainer, ref ItemData item, bool fromPlayer = false, bool singleItemData = false) { bool flag = false; LogDebug("Checking container " + ((Object)nearbyContainer.Item.m_dropPrefab).name); if (!MiscFunctions.CheckItemSharedIntegrity(item)) { return flag; } if (DadsStoragePlugin.MustHaveExistingItemToPull.Value.IsOn() && !nearbyContainer.Inventory.HaveItem(item.m_shared.m_name, true)) { if (singleItemData) { LogDebug("Skipping " + ((Object)item.m_dropPrefab).name + " because it is not in the container"); ((Character)Player.m_localPlayer).Message((MessageType)2, "" + item.m_shared.m_name + " is not in nearby containers", 0, (Sprite)null, false); } return false; } if (!Boxes.CanItemBeStored(MiscFunctions.GetPrefabName(((Object)nearbyContainer.Item.m_dropPrefab).name), ((Object)item.m_dropPrefab).name)) { return false; } while (item.m_stack > 1 && nearbyContainer.Inventory.CanAddItem(item, 1)) { ItemData val = item.Clone(); val.m_stack = 1; API.AddItemToBackpack(nearbyContainer.Item, val); ItemData obj = item; obj.m_stack--; flag = true; LogDebug("Auto storing " + ((Object)item.m_dropPrefab).name + " in " + ((Object)nearbyContainer.Item.m_dropPrefab).name); } if (item.m_stack == 1 && nearbyContainer.Inventory.CanAddItem(item, 1)) { ItemData item2 = item.Clone(); item.m_stack = 0; API.AddItemToBackpack(nearbyContainer.Item, item2); flag = true; } if (!flag) { return flag; } if (!fromPlayer) { Functions.PingContainer(((Component)Player.m_localPlayer).gameObject); } try { nearbyContainer.Save(); } catch { } return flag; } public bool IsOwner() { return true; } public static BackpackContainer Create(ItemContainer container) { return new BackpackContainer(container); } } internal static class DadsEPICompat { private const string PluginGuid = "com.dadisbored.dadsepi"; private const BindingFlags StaticMembers = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; internal static bool IsLoaded() { return Chainloader.PluginInfos.ContainsKey("com.dadisbored.dadsepi"); } internal static List GetQuickSlotsItems() { //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) List list = new List(); Player localPlayer = Player.m_localPlayer; Inventory val = ((localPlayer != null) ? ((Humanoid)localPlayer).GetInventory() : null); if (val == null || !IsLoaded()) { return list; } Type? type = Type.GetType("DadsEPI.InventoryLayout, DadsEPI"); PropertyInfo propertyInfo = type?.GetProperty("EquipmentSlotCount", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); PropertyInfo propertyInfo2 = type?.GetProperty("EnabledQuickSlots", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); MethodInfo methodInfo = type?.GetMethod("SlotPosition", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[2] { typeof(int), typeof(int) }, null); if (propertyInfo == null || propertyInfo2 == null || methodInfo == null) { return list; } try { int num = (int)propertyInfo.GetValue(null); int num2 = (int)propertyInfo2.GetValue(null); int width = val.GetWidth(); for (int i = 0; i < num2; i++) { Vector2i val2 = (Vector2i)methodInfo.Invoke(null, new object[2] { num + i, width }); ItemData itemAt = val.GetItemAt(val2.x, val2.y); if (itemAt != null) { list.Add(itemAt); } } } catch (Exception ex) { DadsStoragePlugin.DadsStorageLogger.LogWarning((object)("DadsEPI quick-slot lookup failed: " + ex.Message)); } return list; } } public interface IContainer { GameObject gameObject { get; } ZNetView m_nview { get; } int TryStore(); int TryStoreThisItem(ItemData item, Inventory playerInventory); bool IsOwner(); } public class kgDrawer(ItemDrawers_API.Drawer _drawer) : IContainer { public GameObject gameObject => _drawer.gameObject; public ZNetView m_nview => _drawer.m_nview; private static bool CantStoreFavorite(ItemData item, UserConfig playerConfig) { return playerConfig.IsItemNameOrSlotFavorited(item); } internal static void LogDebug(string data) { DadsStoragePlugin.DadsStorageLogger.LogDebug((object)data); } public bool ContainsItem(string prefab, int amount, out int result) { result = 0; if (_drawer.Prefab != prefab) { return false; } result = _drawer.Amount; return result >= amount; } public void RemoveItem(string prefab, int amount) { amount = Mathf.Min(amount, _drawer.Amount); _drawer.Remove(amount); } public int TryStore() { if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return 0; } int num = 0; Inventory inventory = ((Humanoid)Player.m_localPlayer).GetInventory(); List allItems = inventory.GetAllItems(); for (int num2 = allItems.Count - 1; num2 >= 0; num2--) { ItemData item = allItems[num2]; if (!(((Object)item.m_dropPrefab).name != _drawer.Prefab)) { if (item.m_equipped) { LogDebug("Skipping equipped item " + ((Object)item.m_dropPrefab).name); } else { int x = item.m_gridPos.x; if (x >= 0 && x <= 8 && item.m_gridPos.y == 0 && DadsStoragePlugin.PlayerIgnoreHotbar.Value.IsOn()) { LogDebug("Skipping item " + ((Object)item.m_dropPrefab).name + " because it is in the hotbar"); } else if (DadsEPICompat.IsLoaded() && DadsEPICompat.GetQuickSlotsItems().Any((ItemData quickSlotItem) => quickSlotItem.m_gridPos == item.m_gridPos)) { LogDebug("Skipping item " + ((Object)item.m_dropPrefab).name + " because it is in your quick slots"); } else if (CantStoreFavorite(item, UserConfig.GetPlayerConfig(Player.m_localPlayer.GetPlayerID()))) { LogDebug("Skipping favorited item/slot " + ((Object)item.m_dropPrefab).name); } else { int stack = item.m_stack; if (TryStoreToKG(_drawer, ref item, fromPlayer: true)) { int num3 = stack - item.m_stack; if (num3 > 0) { num += num3; if (item.m_stack == 0) { inventory.RemoveItem(item); } else { inventory.Changed(false, false); } LogDebug($"Stored {num3} {((Object)item.m_dropPrefab).name} into {((Object)_drawer.gameObject).name}"); if (!Boxes.ContainersToPing.Contains(this)) { Boxes.ContainersToPing.Add(this); } } } } } } } return num; } public int TryStoreThisItem(ItemData? singleItemData = null, Inventory? playerInventory = null) { if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return 0; } Inventory val = playerInventory ?? ((Humanoid)Player.m_localPlayer).GetInventory(); if (singleItemData == null) { return 0; } ItemData item = singleItemData; if (((Object)item.m_dropPrefab).name != _drawer.Prefab) { return 0; } if (item.m_equipped) { LogDebug("Skipping equipped item " + ((Object)item.m_dropPrefab).name); return 0; } int x = item.m_gridPos.x; if (x >= 0 && x <= 8 && item.m_gridPos.y == 0 && DadsStoragePlugin.PlayerIgnoreHotbar.Value.IsOn()) { LogDebug("Skipping item " + ((Object)item.m_dropPrefab).name + " because it is in the hotbar"); return 0; } if (DadsEPICompat.IsLoaded() && DadsEPICompat.GetQuickSlotsItems().Any((ItemData quickSlotItem) => quickSlotItem.m_gridPos == item.m_gridPos)) { LogDebug("Skipping item " + ((Object)item.m_dropPrefab).name + " because it is in your quick slots"); return 0; } if (CantStoreFavorite(item, UserConfig.GetPlayerConfig(Player.m_localPlayer.GetPlayerID()))) { LogDebug("Skipping favorited item/slot " + ((Object)item.m_dropPrefab).name); return 0; } LogDebug("Checking item " + ((Object)item.m_dropPrefab).name); int stack = item.m_stack; if (!TryStoreToKG(_drawer, ref item, fromPlayer: true, singleItemData: true)) { return 0; } int num = stack - item.m_stack; if (num <= 0) { return 0; } if (item.m_stack == 0) { val.RemoveItem(item); } else { val.Changed(false, false); } LogDebug($"Stored {num} {((Object)item.m_dropPrefab).name} into {((Object)_drawer.gameObject).name}"); if (!Boxes.ContainersToPing.Contains(this)) { Boxes.ContainersToPing.Add(this); } return num; } internal bool TryStoreToKG(ItemDrawers_API.Drawer nearbyContainer, ref ItemData item, bool fromPlayer = false, bool singleItemData = false) { bool flag = false; LogDebug("Checking container " + ((Object)_drawer.gameObject).name); if (!MiscFunctions.CheckItemSharedIntegrity(item)) { return flag; } if (DadsStoragePlugin.MustHaveExistingItemToPull.Value.IsOn() && nearbyContainer.Prefab != ((Object)item.m_dropPrefab).name) { if (singleItemData) { LogDebug("Skipping " + ((Object)item.m_dropPrefab).name + " because it is not in the container"); ((Character)Player.m_localPlayer).Message((MessageType)2, "" + item.m_shared.m_name + " is not in nearby containers", 0, (Sprite)null, false); } return false; } if (!Boxes.CanItemBeStored(MiscFunctions.GetPrefabName(((Object)_drawer.gameObject).name), ((Object)item.m_dropPrefab).name)) { return false; } if (nearbyContainer.Quality != item.m_quality) { LogDebug($"Container {((Object)_drawer.gameObject).name} has {nearbyContainer.Prefab} that is different quality than what you're trying to store. Container Quality: {nearbyContainer.Quality} | Item Quality: {item.m_quality}"); return false; } while (item.m_stack > 1 && nearbyContainer.Prefab == ((Object)item.m_dropPrefab).name) { ItemData val = item.Clone(); val.m_stack = 1; _drawer.Add(1, val.m_quality); ItemData obj = item; obj.m_stack--; flag = true; LogDebug("Auto storing " + ((Object)item.m_dropPrefab).name + " in " + ((Object)_drawer.gameObject).name); } if (item.m_stack == 1 && nearbyContainer.Prefab == ((Object)item.m_dropPrefab).name) { ItemData val2 = item.Clone(); item.m_stack = 0; _drawer.Add(val2.m_stack, val2.m_quality); flag = true; } if (!flag || fromPlayer) { return flag; } if (!Boxes.ContainersToPing.Contains(this)) { Boxes.ContainersToPing.Add(this); } return flag; } public bool IsOwner() { return true; } public static kgDrawer Create(ItemDrawers_API.Drawer drawer) { return new kgDrawer(drawer); } } public sealed class mkzDrawer(MkzItemDrawers_API.Drawer _drawer) : IContainer { public GameObject gameObject => _drawer.gameObject; public ZNetView m_nview => _drawer.m_nview; private static bool CantStoreFavorite(ItemData item, UserConfig playerConfig) { return playerConfig.IsItemNameOrSlotFavorited(item); } internal static void LogDebug(string s) { DadsStoragePlugin.DadsStorageLogger.LogDebug((object)s); } public bool IsOwner() { return true; } public static mkzDrawer Create(MkzItemDrawers_API.Drawer d) { return new mkzDrawer(d); } public int TryStore() { if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return 0; } List allItems = ((Humanoid)Player.m_localPlayer).GetInventory().GetAllItems(); int num = 0; for (int num2 = allItems.Count - 1; num2 >= 0; num2--) { ItemData item = allItems[num2]; if (item != null && !item.m_equipped) { int x = item.m_gridPos.x; if ((x < 0 || x > 8 || item.m_gridPos.y != 0 || !DadsStoragePlugin.PlayerIgnoreHotbar.Value.IsOn()) && (!DadsEPICompat.IsLoaded() || !DadsEPICompat.GetQuickSlotsItems().Any((ItemData q) => q.m_gridPos == item.m_gridPos)) && !CantStoreFavorite(item, UserConfig.GetPlayerConfig(Player.m_localPlayer.GetPlayerID()))) { string text = (Object.op_Implicit((Object)(object)item.m_dropPrefab) ? ((Object)item.m_dropPrefab).name : null); if (!string.IsNullOrEmpty(text) && Boxes.CanItemBeStored(MiscFunctions.GetPrefabName(((Object)_drawer.gameObject).name), text) && (!DadsStoragePlugin.MustHaveExistingItemToPull.Value.IsOn() || string.Equals(_drawer.Prefab, text)) && _drawer.Accepts(text)) { int stack = item.m_stack; if (stack > 0) { _drawer.Add(text, stack); num += stack; } } } } } if (num > 0 && !Boxes.ContainersToPing.Contains(this)) { Boxes.ContainersToPing.Add(this); } return 0; } public int TryStoreThisItem(ItemData singleItemData = null, Inventory playerInventory = null) { if (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || singleItemData == null) { return 0; } ItemData item = singleItemData; if (item.m_equipped) { return 0; } int x = item.m_gridPos.x; if (x >= 0 && x <= 8 && item.m_gridPos.y == 0 && DadsStoragePlugin.PlayerIgnoreHotbar.Value.IsOn()) { return 0; } if (DadsEPICompat.IsLoaded() && DadsEPICompat.GetQuickSlotsItems().Any((ItemData q) => q.m_gridPos == item.m_gridPos)) { return 0; } if (CantStoreFavorite(item, UserConfig.GetPlayerConfig(Player.m_localPlayer.GetPlayerID()))) { return 0; } string text = (Object.op_Implicit((Object)(object)item.m_dropPrefab) ? ((Object)item.m_dropPrefab).name : null); if (string.IsNullOrEmpty(text)) { return 0; } if (!Boxes.CanItemBeStored(MiscFunctions.GetPrefabName(((Object)_drawer.gameObject).name), text)) { return 0; } if (DadsStoragePlugin.MustHaveExistingItemToPull.Value.IsOn() && !string.Equals(_drawer.Prefab, text)) { ((Character)Player.m_localPlayer).Message((MessageType)2, "" + item.m_shared.m_name + " [" + text + "] is not in nearby drawers", 0, (Sprite)null, false); return 0; } if (!_drawer.Accepts(text)) { return 0; } int stack = item.m_stack; if (stack <= 0) { return 0; } _drawer.Add(text, stack); if (!Boxes.ContainersToPing.Contains(this)) { Boxes.ContainersToPing.Add(this); } return 0; } } public class VanillaContainers(Container _container) : IContainer { public GameObject gameObject => ((Component)_container).gameObject; public ZNetView m_nview => _container.m_nview; public static bool CantStoreFavorite(ItemData item, UserConfig playerConfig) { return playerConfig.IsItemNameOrSlotFavorited(item); } internal static void LogDebug(string data) { DadsStoragePlugin.DadsStorageLogger.LogDebug((object)data); } private static List? QuickSlots() { if (!DadsEPICompat.IsLoaded()) { return null; } return DadsEPICompat.GetQuickSlotsItems(); } private static bool ShouldSkip(ItemData item, List? quickSlots) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) if (item.m_equipped) { LogDebug("Skipping equipped item " + ((Object)item.m_dropPrefab).name); return true; } int x = item.m_gridPos.x; if (x >= 0 && x <= 8 && item.m_gridPos.y == 0 && DadsStoragePlugin.PlayerIgnoreHotbar.Value.IsOn()) { LogDebug("Skipping item " + ((Object)item.m_dropPrefab).name + " because it is in the hotbar"); return true; } if (quickSlots != null) { for (int i = 0; i < quickSlots.Count; i++) { if (!(quickSlots[i].m_gridPos != item.m_gridPos)) { LogDebug("Skipping item " + ((Object)item.m_dropPrefab).name + " because it is in your quick slots"); return true; } } } if (CantStoreFavorite(item, UserConfig.GetPlayerConfig(Player.m_localPlayer.GetPlayerID()))) { LogDebug("Skipping favorited item/slot " + ((Object)item.m_dropPrefab).name); return true; } return false; } private int Commit(ItemData item, Inventory inv, int originalAmount) { int num = originalAmount - item.m_stack; if (num <= 0) { return 0; } if (item.m_stack > 0) { inv.Changed(false, false); } else if (inv.ContainsItem(item)) { inv.RemoveItem(item); } LogDebug($"Stored {num} {((Object)item.m_dropPrefab).name} into {((Object)_container).name}"); if (!Boxes.ContainersToPing.Contains(this)) { Boxes.ContainersToPing.Add(this); } return num; } public int TryStore() { if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return 0; } int num = 0; Inventory inventory = ((Humanoid)Player.m_localPlayer).GetInventory(); List allItems = inventory.GetAllItems(); List quickSlots = QuickSlots(); for (int num2 = allItems.Count - 1; num2 >= 0; num2--) { ItemData item = allItems[num2]; if (!ShouldSkip(item, quickSlots)) { LogDebug("Checking item " + ((Object)item.m_dropPrefab).name); int stack = item.m_stack; if (Functions.TryStore(_container, ref item, fromPlayer: true)) { num += Commit(item, inventory, stack); } } } return num; } public int TryStoreThisItem(ItemData? singleItemData = null, Inventory? playerInventory = null) { if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return 0; } if (singleItemData == null) { return 0; } Inventory inv = playerInventory ?? ((Humanoid)Player.m_localPlayer).GetInventory(); ItemData item = singleItemData; if (ShouldSkip(item, QuickSlots())) { return 0; } LogDebug("Checking item " + ((Object)item.m_dropPrefab).name); int stack = item.m_stack; if (!Functions.TryStore(_container, ref item, fromPlayer: true, singleItemData: true)) { return 0; } return Commit(item, inv, stack); } public bool IsOwner() { return _container.m_nview.IsOwner(); } public Inventory GetInventory() { return _container.GetInventory(); } public static VanillaContainers Create(Container container) { return new VanillaContainers(container); } } } namespace DadsStorage.APIs { public static class ItemDrawers_API { public class Drawer(ZNetView znv) { public string Prefab = znv.m_zdo.GetString("Prefab", ""); public int Amount = znv.m_zdo.GetInt("Amount", 0); public int Quality = znv.m_zdo.GetInt("Quality", 1); public Vector3 Position => ((Component)znv).transform.position; public GameObject gameObject => ((Component)znv).gameObject; public string ZNVName => ((Object)((Component)znv).gameObject).name; public ZNetView m_nview => znv; public void Remove(int amount) { znv.ClaimOwnership(); znv.InvokeRPC("ForceRemove", new object[1] { amount }); } public void Withdraw(int amount) { znv.InvokeRPC("WithdrawItem_Request", new object[1] { amount }); } public void Add(int amount, int quality) { znv.InvokeRPC("AddItem_Request", new object[3] { Prefab, amount, quality }); } } private static readonly bool _IsInstalled; private static readonly MethodInfo MI_GetAllDrawers; public static List AllDrawers { get { if (!_IsInstalled) { return new List(); } return ((List)MI_GetAllDrawers.Invoke(null, null)).Select((ZNetView znv) => new Drawer(znv)).ToList(); } } public static List AllDrawersInRange(Vector3 pos, float range) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) if (!_IsInstalled) { return new List(); } return (from znv in (List)MI_GetAllDrawers.Invoke(null, null) where Vector3.Distance(((Component)znv).transform.position, pos) <= range select new Drawer(znv)).ToList(); } static ItemDrawers_API() { Type type = Type.GetType("API.ClientSideV2, kg_ItemDrawers"); if ((object)type == null) { _IsInstalled = false; return; } _IsInstalled = true; MI_GetAllDrawers = type.GetMethod("AllDrawers", BindingFlags.Static | BindingFlags.Public); } } public static class MkzItemDrawers_API { public class Drawer { private readonly Component _drawer; private readonly ZNetView _nview; public GameObject gameObject => _drawer.gameObject; public ZNetView m_nview => _nview; public Vector3 Position => _drawer.transform.position; public string Prefab { get { if (_fiItem == null) { return null; } object? value = _fiItem.GetValue(_drawer); GameObject val = ((ItemData)(((value is ItemData) ? value : null)?)).m_dropPrefab; if (!Object.op_Implicit((Object)(object)val)) { return null; } return ((Object)val).name; } } public int? Amount { get { if (_fiQuantity == null) { return null; } return (int)_fiQuantity.GetValue(_drawer); } } internal Drawer(Component drawer) { _drawer = drawer; _nview = drawer.GetComponent(); } public bool Accepts(string prefab) { string prefab2 = Prefab; if (!string.IsNullOrEmpty(prefab2)) { return string.Equals(prefab2, prefab, StringComparison.Ordinal); } return true; } public void Add(string prefab, int amount) { if (amount > 0 && !string.IsNullOrEmpty(prefab) && Object.op_Implicit((Object)(object)_nview)) { _nview.ClaimOwnership(); _nview.InvokeRPC("AddItem", new object[2] { prefab, amount }); } } } private static readonly bool _isInstalled; private static readonly Type? _drawerType; private static readonly FieldInfo? _fiItem; private static readonly FieldInfo? _fiQuantity; public static List AllDrawers { get { if (_isInstalled) { return FindAllRuntimeDrawers(); } return new List(); } } public static List AllDrawersInRange(Vector3 pos, float range) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) if (_isInstalled) { return (from d in FindAllRuntimeDrawers() where Vector3.Distance(d.Position, pos) <= range select d).ToList(); } return new List(); } static MkzItemDrawers_API() { _drawerType = Type.GetType("DrawerContainer, itemdrawers"); if (_drawerType == null) { _isInstalled = false; return; } _fiItem = _drawerType.GetField("_item", BindingFlags.Instance | BindingFlags.NonPublic); _fiQuantity = _drawerType.GetField("_quantity", BindingFlags.Instance | BindingFlags.NonPublic); _isInstalled = true; } private static List FindAllRuntimeDrawers() { List list = new List(); Object[] array = Object.FindObjectsByType(_drawerType, (FindObjectsSortMode)0); foreach (Object obj in array) { Component val = (Component)(object)((obj is Component) ? obj : null); if (val != null) { ZNetView component = val.GetComponent(); if (Object.op_Implicit((Object)(object)component) && component.IsValid()) { list.Add(new Drawer(val)); } } } return list; } } } namespace DadsStorage.APIs.MUC { internal static class MUCCompat { internal static bool DoNotPatch { get { if (!Chainloader.PluginInfos.ContainsKey("com.maxsch.valheim.MultiUserChest") && !Chainloader.PluginInfos.ContainsKey("org.bepinex.plugins.valheim.quick_stack") && !Chainloader.PluginInfos.ContainsKey("aedenthorn.SimpleSort")) { return Chainloader.PluginInfos.ContainsKey("aedenthorn.QuickStore"); } return true; } } internal static bool MUCLoaded => Chainloader.PluginInfos.ContainsKey("com.maxsch.valheim.MultiUserChest"); internal static bool CanRouteToOtherOwner { get { if (!MUCLoaded) { return !DoNotPatch; } return true; } } } } namespace DadsStorage.APIs.MUC.MUCSrc { public static class CodeMatcherExtensions { public static CodeMatcher GetPosition(this CodeMatcher codeMatcher, out int position) { position = codeMatcher.Pos; return codeMatcher; } public static CodeMatcher AddLabel(this CodeMatcher codeMatcher, out Label label) { label = default(Label); codeMatcher.AddLabels((IEnumerable