Decompiled source of OttoStash v3.4.1

OttoStash.dll

Decompiled 2 days ago
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 AzuExtendedPlayerInventory;
using Backpacks;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using ItemDataManager;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
using OttoStash.APIs;
using OttoStash.APIs.Compatibility.WardIsLove;
using OttoStash.APIs.MUC;
using OttoStash.APIs.MUC.MUCSrc.Data;
using OttoStash.APIs.MUC.MUCSrc.Helper;
using OttoStash.APIs.MUC.MUCSrc.Patches;
using OttoStash.APIs.MUC.MUCSrc.Patches.Compatibility;
using OttoStash.Favoriting;
using OttoStash.Storing;
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("OttoStash")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("potto007")]
[assembly: AssemblyProduct("OttoStash")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("4358610B-F3F4-4843-B7AF-98B7BC60DCDE")]
[assembly: AssemblyFileVersion("3.4.1")]
[assembly: InternalsVisibleTo("OttoStash.Tests")]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("3.4.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[CompilerGenerated]
internal sealed class <>z__ReadOnlyArray<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T>
{
	int ICollection.Count => _items.Length;

	bool ICollection.IsSynchronized => false;

	object ICollection.SyncRoot => this;

	object IList.this[int index]
	{
		get
		{
			return _items[index];
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	bool IList.IsFixedSize => true;

	bool IList.IsReadOnly => true;

	int IReadOnlyCollection<T>.Count => _items.Length;

	T IReadOnlyList<T>.this[int index] => _items[index];

	int ICollection<T>.Count => _items.Length;

	bool ICollection<T>.IsReadOnly => true;

	T IList<T>.this[int index]
	{
		get
		{
			return _items[index];
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	public <>z__ReadOnlyArray(T[] items)
	{
		_items = items;
	}

	IEnumerator IEnumerable.GetEnumerator()
	{
		return ((IEnumerable)_items).GetEnumerator();
	}

	void ICollection.CopyTo(Array array, int index)
	{
		((ICollection)_items).CopyTo(array, index);
	}

	int IList.Add(object value)
	{
		throw new NotSupportedException();
	}

	void IList.Clear()
	{
		throw new NotSupportedException();
	}

	bool IList.Contains(object value)
	{
		return ((IList)_items).Contains(value);
	}

	int IList.IndexOf(object value)
	{
		return ((IList)_items).IndexOf(value);
	}

	void IList.Insert(int index, object value)
	{
		throw new NotSupportedException();
	}

	void IList.Remove(object value)
	{
		throw new NotSupportedException();
	}

	void IList.RemoveAt(int index)
	{
		throw new NotSupportedException();
	}

	IEnumerator<T> IEnumerable<T>.GetEnumerator()
	{
		return ((IEnumerable<T>)_items).GetEnumerator();
	}

	void ICollection<T>.Add(T item)
	{
		throw new NotSupportedException();
	}

	void ICollection<T>.Clear()
	{
		throw new NotSupportedException();
	}

	bool ICollection<T>.Contains(T item)
	{
		return ((ICollection<T>)_items).Contains(item);
	}

	void ICollection<T>.CopyTo(T[] array, int arrayIndex)
	{
		((ICollection<T>)_items).CopyTo(array, arrayIndex);
	}

	bool ICollection<T>.Remove(T item)
	{
		throw new NotSupportedException();
	}

	int IList<T>.IndexOf(T item)
	{
		return ((IList<T>)_items).IndexOf(item);
	}

	void IList<T>.Insert(int index, T item)
	{
		throw new NotSupportedException();
	}

	void IList<T>.RemoveAt(int index)
	{
		throw new NotSupportedException();
	}
}
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<string, Dictionary<string, Func<string>>> PlaceholderProcessors;

		private static readonly Dictionary<string, Dictionary<string, string>> loadedTexts;

		private static readonly ConditionalWeakTable<Localization, string> localizationLanguage;

		private static readonly List<WeakReference<Localization>> localizationObjects;

		private static BaseUnityPlugin? _plugin;

		private static readonly List<string> fileExtensions;

		private static BaseUnityPlugin plugin
		{
			get
			{
				//IL_009b: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a5: Expected O, but got Unknown
				if (_plugin == null)
				{
					IEnumerable<TypeInfo> source;
					try
					{
						source = Assembly.GetExecutingAssembly().DefinedTypes.ToList();
					}
					catch (ReflectionTypeLoadException ex)
					{
						source = from t in ex.Types
							where t != null
							select t.GetTypeInfo();
					}
					_plugin = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First((TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t)));
				}
				return _plugin;
			}
		}

		private static void UpdatePlaceholderText(Localization localization, string key)
		{
			localizationLanguage.TryGetValue(localization, out string value);
			string text = loadedTexts[value][key];
			if (PlaceholderProcessors.TryGetValue(key, out Dictionary<string, Func<string>> value2))
			{
				text = value2.Aggregate(text, (string current, KeyValuePair<string, Func<string>> kv) => current.Replace("{" + kv.Key + "}", kv.Value()));
			}
			localization.AddWord(key, text);
		}

		public static void AddPlaceholder<T>(string key, string placeholder, ConfigEntry<T> config, Func<T, string>? convertConfigValue = null) where T : notnull
		{
			if (convertConfigValue == null)
			{
				convertConfigValue = (T val) => val.ToString();
			}
			if (!PlaceholderProcessors.ContainsKey(key))
			{
				PlaceholderProcessors[key] = new Dictionary<string, Func<string>>();
			}
			config.SettingChanged += delegate
			{
				UpdatePlaceholder();
			};
			if (loadedTexts.ContainsKey(Localization.instance.GetSelectedLanguage()))
			{
				UpdatePlaceholder();
			}
			void UpdatePlaceholder()
			{
				PlaceholderProcessors[key][placeholder] = () => convertConfigValue(config.Value);
				UpdatePlaceholderText(Localization.instance, key);
			}
		}

		public static void AddText(string key, string text)
		{
			List<WeakReference<Localization>> list = new List<WeakReference<Localization>>();
			foreach (WeakReference<Localization> localizationObject in localizationObjects)
			{
				if (localizationObject.TryGetTarget(out var target))
				{
					Dictionary<string, string> dictionary = loadedTexts[localizationLanguage.GetOrCreateValue(target)];
					if (!target.m_translations.ContainsKey(key))
					{
						dictionary[key] = text;
						target.AddWord(key, text);
					}
				}
				else
				{
					list.Add(localizationObject);
				}
			}
			foreach (WeakReference<Localization> item in list)
			{
				localizationObjects.Remove(item);
			}
		}

		public static void Load()
		{
			LoadLocalization(Localization.instance, Localization.instance.GetSelectedLanguage());
		}

		private static void LoadLocalization(Localization __instance, string language)
		{
			if (!localizationLanguage.Remove(__instance))
			{
				localizationObjects.Add(new WeakReference<Localization>(__instance));
			}
			localizationLanguage.Add(__instance, language);
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			foreach (string item in from f in Directory.GetFiles(Path.GetDirectoryName(Paths.PluginPath), plugin.Info.Metadata.Name + ".*", SearchOption.AllDirectories)
				where fileExtensions.IndexOf(Path.GetExtension(f)) >= 0
				select f)
			{
				string text = Path.GetFileNameWithoutExtension(item).Split(new char[1] { '.' })[1];
				if (dictionary.ContainsKey(text))
				{
					Debug.LogWarning((object)("Duplicate key " + text + " found for " + plugin.Info.Metadata.Name + ". The duplicate file found at " + item + " will be skipped."));
				}
				else
				{
					dictionary[text] = item;
				}
			}
			byte[] array = LoadTranslationFromAssembly("English");
			if (array == null)
			{
				throw new Exception("Found no English localizations in mod " + plugin.Info.Metadata.Name + ". Expected an embedded resource translations/English.json or translations/English.yml.");
			}
			Dictionary<string, string> dictionary2 = new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(Encoding.UTF8.GetString(array));
			if (dictionary2 == null)
			{
				throw new Exception("Localization for mod " + plugin.Info.Metadata.Name + " failed: Localization file was empty.");
			}
			string text2 = null;
			if (language != "English")
			{
				if (dictionary.ContainsKey(language))
				{
					text2 = File.ReadAllText(dictionary[language]);
				}
				else
				{
					byte[] array2 = LoadTranslationFromAssembly(language);
					if (array2 != null)
					{
						text2 = Encoding.UTF8.GetString(array2);
					}
				}
			}
			if (text2 == null && dictionary.ContainsKey("English"))
			{
				text2 = File.ReadAllText(dictionary["English"]);
			}
			if (text2 != null)
			{
				foreach (KeyValuePair<string, string> item2 in new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(text2) ?? new Dictionary<string, string>())
				{
					dictionary2[item2.Key] = item2.Value;
				}
			}
			loadedTexts[language] = dictionary2;
			foreach (KeyValuePair<string, string> item3 in dictionary2)
			{
				UpdatePlaceholderText(__instance, item3.Key);
			}
		}

		static Localizer()
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			PlaceholderProcessors = new Dictionary<string, Dictionary<string, Func<string>>>();
			loadedTexts = new Dictionary<string, Dictionary<string, string>>();
			localizationLanguage = new ConditionalWeakTable<Localization, string>();
			localizationObjects = new List<WeakReference<Localization>>();
			fileExtensions = new List<string> { ".json", ".yml" };
			new Harmony("org.bepinex.helpers.LocalizationManager").Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Localization), "LoadCSV", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalization", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static byte[]? LoadTranslationFromAssembly(string language)
		{
			foreach (string fileExtension in fileExtensions)
			{
				byte[] array = ReadEmbeddedFileBytes("translations." + language + fileExtension);
				if (array != null)
				{
					return array;
				}
			}
			return null;
		}

		public static byte[]? ReadEmbeddedFileBytes(string resourceFileName, Assembly? containingAssembly = null)
		{
			using MemoryStream memoryStream = new MemoryStream();
			if ((object)containingAssembly == null)
			{
				containingAssembly = Assembly.GetCallingAssembly();
			}
			string text = containingAssembly.GetManifestResourceNames().FirstOrDefault((string str) => str.EndsWith(resourceFileName, StringComparison.Ordinal));
			if (text != null)
			{
				containingAssembly.GetManifestResourceStream(text)?.CopyTo(memoryStream);
			}
			return (memoryStream.Length == 0L) ? null : memoryStream.ToArray();
		}
	}
}
namespace ItemDataManager
{
	[PublicAPI]
	public abstract class ItemData
	{
		internal static WeakReference<<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo> constructingInfo = null;

		internal WeakReference<<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo>? info;

		private static readonly FieldInfo parameterInfoClassImpl = AccessTools.DeclaredField(typeof(ParameterInfo), "ClassImpl");

		private static Dictionary<Type, Dictionary<string, FieldInfo>> serializedFields = new Dictionary<Type, Dictionary<string, FieldInfo>>();

		public string CustomDataKey { get; internal set; }

		protected virtual bool AllowStackingIdenticalValues { get; set; }

		public string Value
		{
			get
			{
				if (!Item.m_customData.TryGetValue(CustomDataKey, out var value))
				{
					return "";
				}
				return value;
			}
			set
			{
				Item.m_customData[CustomDataKey] = value;
			}
		}

		public string Key { get; internal set; }

		public bool IsCloned => Info.isCloned.Contains(CustomDataKey);

		public bool IsAlive
		{
			get
			{
				<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo target;
				return (info ?? constructingInfo).TryGetTarget(out target);
			}
		}

		public ItemData Item => Info.ItemData;

		public <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>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 <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo target))
				{
					return new <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo(new ItemData());
				}
				return target;
			}
		}

		public virtual void FirstLoad()
		{
		}

		public virtual void Load()
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			Dictionary<string, FieldInfo> dictionary = fetchSerializedFields();
			if (dictionary == null || dictionary.Count <= 0 || Value == "")
			{
				return;
			}
			List<object> list = new List<object>();
			string[] array = Value.Split(new char[1] { '|' });
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split(new char[1] { ':' });
				if (array2.Length == 2 && dictionary.TryGetValue(array2[0], out var value))
				{
					ZPackage val = new ZPackage(array2[1]);
					ParameterInfo parameterInfo = (ParameterInfo)FormatterServices.GetUninitializedObject(typeof(ParameterInfo));
					parameterInfoClassImpl.SetValue(parameterInfo, value.FieldType);
					list.Clear();
					ZRpc.Deserialize(new ParameterInfo[2] { null, parameterInfo }, val, ref list);
					if (list.Count > 0)
					{
						value.SetValue(this, list[0]);
					}
				}
			}
		}

		public virtual void Save()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			Dictionary<string, FieldInfo> dictionary = fetchSerializedFields();
			if (dictionary == null || dictionary.Count <= 0)
			{
				return;
			}
			StringBuilder stringBuilder = new StringBuilder();
			foreach (FieldInfo value in dictionary.Values)
			{
				ZPackage val = new ZPackage();
				ZRpc.Serialize(new object[1] { value.GetValue(this) }, ref val);
				stringBuilder.Append(value.Name);
				stringBuilder.Append(':');
				stringBuilder.Append(val.GetBase64());
				stringBuilder.Append('|');
			}
			int length = stringBuilder.Length - 1;
			stringBuilder.Length = length;
			Value = stringBuilder.ToString();
		}

		public virtual void Unload()
		{
		}

		public virtual void Upgraded()
		{
		}

		public virtual string? TryStack(ItemData? data)
		{
			if (!AllowStackingIdenticalValues || !(data?.Value == Value))
			{
				return null;
			}
			return Value;
		}

		private Dictionary<string, FieldInfo> fetchSerializedFields()
		{
			Type type = GetType();
			if (serializedFields.TryGetValue(type, out Dictionary<string, FieldInfo> value))
			{
				return value;
			}
			return serializedFields[type] = (from f in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
				where f.GetCustomAttributes(typeof(SerializeField), inherit: true).Length != 0
				select f).ToDictionary((FieldInfo f) => f.Name, (FieldInfo f) => f);
		}
	}
	public sealed class <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>StringItemData : ItemData
	{
	}
	[PublicAPI]
	public class <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo : IEnumerable<ItemData>, IEnumerable
	{
		public static HashSet<Type> ForceLoadTypes;

		internal static string? _modGuid;

		private static Dictionary<Type, HashSet<Type>> typeInheritorsCache;

		private static HashSet<string> knownTypes;

		private Dictionary<string, ItemData> data = new Dictionary<string, ItemData>();

		private WeakReference<<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo>? selfReference;

		internal HashSet<string> isCloned = new HashSet<string>();

		private static ItemData? awakeningItem;

		private static Assembly primaryAssembly;

		private static Dictionary<Assembly, string> assemblyNameCache;

		private static Dictionary<Type, string> classKeyCache;

		private HashSet<string> fetchedClassKeys = new HashSet<string>();

		private static MethodInfo removeMethod;

		private static ItemData? checkingForStackableItemData;

		private static Dictionary<string, string>? newValuesOnStackable;

		private static ItemData? currentlyUpgradingItem;

		internal static string modGuid => _modGuid ?? (_modGuid = ((Func<string>)delegate
		{
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			IEnumerable<TypeInfo> source;
			try
			{
				source = Assembly.GetExecutingAssembly().DefinedTypes.ToList();
			}
			catch (ReflectionTypeLoadException ex)
			{
				source = from t in ex.Types
					where t != null
					select t.GetTypeInfo();
			}
			return ((BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First((TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t)))).Info.Metadata.GUID;
		})());

		public string Mod => modGuid;

		public ItemData ItemData { get; private set; }

		public string? this[string key]
		{
			get
			{
				return Get<<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>StringItemData>(key)?.Value;
			}
			set
			{
				GetOrCreate<<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>StringItemData>(key).Value = value ?? "";
			}
		}

		internal static void addTypeToInheritorsCache(Type type, string typeKey)
		{
			if (!knownTypes.Contains(typeKey))
			{
				knownTypes.Add(typeKey);
				Type type2 = type;
				while ((object)type2 != null)
				{
					AddInterfaces(type2);
					type2 = type2.BaseType;
				}
			}
			void AddInterfaces(Type baseType)
			{
				if (!typeInheritorsCache.TryGetValue(baseType, out HashSet<Type> value))
				{
					HashSet<Type> hashSet = (typeInheritorsCache[baseType] = new HashSet<Type>());
					value = hashSet;
				}
				value.Add(type);
				Type[] interfaces = baseType.GetInterfaces();
				for (int i = 0; i < interfaces.Length; i++)
				{
					AddInterfaces(interfaces[i]);
				}
			}
		}

		private static string cachedAssemblyName(Assembly assembly)
		{
			if (assemblyNameCache.TryGetValue(assembly, out string value))
			{
				return value;
			}
			return assemblyNameCache[assembly] = assembly.GetName().Name;
		}

		internal static string classKey(Type type, string key)
		{
			if (!classKeyCache.TryGetValue(type, out string value))
			{
				value = type.FullName + ((type.Assembly != primaryAssembly) ? ("," + cachedAssemblyName(type.Assembly)) : "");
				addTypeToInheritorsCache(type, value);
			}
			if (key == "")
			{
				return value;
			}
			return value + "#" + key;
		}

		internal static string dataKey(string key)
		{
			return modGuid + "#" + key;
		}

		internal <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo(ItemData itemData)
		{
			ItemData = itemData;
			string text = dataKey("");
			foreach (string item in ItemData.m_customData.Keys.ToList())
			{
				if (!item.StartsWith(text))
				{
					continue;
				}
				string[] array = item.Substring(text.Length).Split(new char[1] { '#' }, 2);
				if (!knownTypes.Contains(array[0]))
				{
					Type type = Type.GetType(array[0]);
					if ((object)type != null && typeof(ItemData).IsAssignableFrom(type))
					{
						addTypeToInheritorsCache(type, array[0]);
					}
				}
			}
		}

		public T GetOrCreate<T>(string key = "") where T : ItemData, new()
		{
			return Add<T>(key) ?? Get<T>(key);
		}

		public T? Add<T>(string key = "") where T : ItemData, new()
		{
			string text = classKey(typeof(T), key);
			if (fetchedClassKeys.Contains(text) && data.ContainsKey(text))
			{
				return null;
			}
			string text2 = dataKey(text);
			if (ItemData.m_customData.ContainsKey(text2) || (awakeningItem != ItemData && data.ContainsKey(text)))
			{
				return null;
			}
			ItemData.m_customData[text2] = "";
			ItemDataManager.ItemData.constructingInfo = selfReference ?? (selfReference = new WeakReference<<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo>(this));
			T val = new T
			{
				info = selfReference,
				Key = key,
				CustomDataKey = text2
			};
			data[text] = val;
			val.Value = "";
			val.FirstLoad();
			return val;
		}

		public T? Get<T>(string key = "") where T : class
		{
			if (!typeInheritorsCache.TryGetValue(typeof(T), out HashSet<Type> value))
			{
				if (!typeof(ItemData).IsAssignableFrom(typeof(T)) || typeof(T) == typeof(ItemData))
				{
					throw new Exception("Trying to get value from ItemDataManager for class not inheriting from ItemData");
				}
				return null;
			}
			foreach (Type item in value)
			{
				string text = classKey(item, key);
				if (data.TryGetValue(text, out ItemData value2))
				{
					return (T)(object)value2;
				}
				if (!fetchedClassKeys.Contains(text) && awakeningItem != ItemData)
				{
					string text2 = dataKey(text);
					fetchedClassKeys.Add(text);
					if (ItemData.m_customData.ContainsKey(text2))
					{
						return (T)(object)constructDataObj(text2, text);
					}
				}
			}
			return null;
		}

		public Dictionary<string, T> GetAll<T>() where T : ItemData
		{
			LoadAll();
			return data.Values.Where((ItemData o) => o is T).ToDictionary((ItemData o) => o.Key, (ItemData o) => (T)o);
		}

		public bool Remove(string key = "")
		{
			return Remove<<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>StringItemData>(key);
		}

		public bool Remove<T>(string key = "") where T : ItemData
		{
			string key2 = classKey(typeof(T), key);
			string key3 = dataKey(key2);
			if (ItemData.m_customData.Remove(key3))
			{
				if (data.TryGetValue(key2, out ItemData value))
				{
					value.Unload();
					data.Remove(key2);
				}
				return true;
			}
			return false;
		}

		public bool Remove<T>(T itemData) where T : ItemData
		{
			if (typeof(T) == itemData.GetType())
			{
				return Remove<T>(itemData.Key);
			}
			return (bool)removeMethod.MakeGenericMethod(itemData.GetType()).Invoke(this, new object[1] { itemData.Key });
		}

		private ItemData? constructDataObj(string fullkey, string key)
		{
			string[] array = key.Split(new char[1] { '#' }, 2);
			Type type = Type.GetType(array[0]);
			if ((object)type == null || !typeof(ItemData).IsAssignableFrom(type))
			{
				return null;
			}
			ItemDataManager.ItemData.constructingInfo = selfReference ?? (selfReference = new WeakReference<<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo>(this));
			ItemData itemData = (ItemData)Activator.CreateInstance(type);
			data[key] = itemData;
			itemData.info = selfReference;
			itemData.Key = ((array.Length > 1) ? array[1] : "");
			itemData.CustomDataKey = fullkey;
			itemData.Load();
			return itemData;
		}

		public void Save()
		{
			foreach (ItemData value in data.Values)
			{
				value.Save();
			}
		}

		public void LoadAll()
		{
			if (awakeningItem == ItemData)
			{
				return;
			}
			string text = dataKey("");
			foreach (string item in ItemData.m_customData.Keys.ToList())
			{
				if (item.StartsWith(text))
				{
					string key = item.Substring(text.Length);
					if (!data.ContainsKey(key))
					{
						constructDataObj(item, key);
					}
				}
			}
		}

		public IEnumerator<ItemData> GetEnumerator()
		{
			LoadAll();
			return data.Values.GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}

		private static void SavePrefix(ItemData __instance)
		{
			SaveItem(__instance);
		}

		private static void SaveInventoryPrefix(Inventory __instance)
		{
			foreach (ItemData item in __instance.m_inventory)
			{
				SaveItem(item);
			}
		}

		private static void SaveItem(ItemData item)
		{
			if (<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemExtensions.itemInfo.TryGetValue(item, out <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo value))
			{
				value.Save();
			}
		}

		public Dictionary<string, string>? IsStackableWithOtherInfo(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo? info)
		{
			LoadAll();
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			if (info != null)
			{
				info.LoadAll();
				foreach (string item in new HashSet<string>(info.data.Keys.Intersect(data.Keys)))
				{
					string text = data[item].TryStack(info.data[item]);
					if (text == null)
					{
						return null;
					}
					dictionary[item] = text;
				}
				foreach (KeyValuePair<string, ItemData> datum in info.data)
				{
					if (!dictionary.ContainsKey(datum.Key))
					{
						string text2 = info.data[datum.Key].TryStack(null);
						if (text2 == null)
						{
							return null;
						}
						dictionary[datum.Key] = text2;
					}
				}
			}
			foreach (KeyValuePair<string, ItemData> datum2 in data)
			{
				if (!dictionary.ContainsKey(datum2.Key))
				{
					string text3 = data[datum2.Key].TryStack(null);
					if (text3 == null)
					{
						return null;
					}
					dictionary[datum2.Key] = text3;
				}
			}
			return dictionary.ToDictionary((KeyValuePair<string, string> kv) => dataKey(kv.Key), (KeyValuePair<string, string> kv) => kv.Value);
		}

		private static void RegisterForceLoadedTypesAddItem(ItemData? __result)
		{
			awakeningItem = null;
			if (__result != null)
			{
				RegisterForceLoadedTypes(__result);
			}
		}

		private static void RegisterForceLoadedTypes(ItemData itemData)
		{
			foreach (Type forceLoadType in ForceLoadTypes)
			{
				string key = classKey(forceLoadType, "");
				string text = dataKey(key);
				if (itemData.m_customData.ContainsKey(text))
				{
					<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo2 = <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemExtensions.Data(itemData);
					if (!<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo2.data.ContainsKey(key))
					{
						<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo2.constructDataObj(text, key);
					}
				}
			}
		}

		private static void ItemDropAwake(ItemDrop __instance)
		{
			GameObject dropPrefab = __instance.m_itemData.m_dropPrefab;
			if (dropPrefab != null && <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemExtensions.itemInfo.TryGetValue(dropPrefab.GetComponent<ItemDrop>().m_itemData, out <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo value))
			{
				<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemExtensions.Data(__instance.m_itemData).isCloned = new HashSet<string>(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 (<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemExtensions.itemInfo.TryGetValue(__instance, out <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo value))
			{
				<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemExtensions.Data(__result).isCloned = new HashSet<string>(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<ItemDrop>().m_itemData == food.m_item)
				{
					food.m_item = food.m_item.Clone();
					food.m_item.m_dropPrefab = itemPrefab;
				}
				RegisterForceLoadedTypes(food.m_item);
			}
		}

		private static void SaveCheckingForStackableItemData(ItemData item)
		{
			if (item == awakeningItem)
			{
				awakeningItem = null;
			}
			checkingForStackableItemData = item;
		}

		private static void ResetCheckingForStackableItemData()
		{
			checkingForStackableItemData = null;
		}

		private static IEnumerable<CodeInstruction> CheckStackableInFindFreeStackMethods(IEnumerable<CodeInstruction> instructionsEnumerable)
		{
			CodeInstruction[] instructions = instructionsEnumerable.ToArray();
			Label target = (Label)instructions.First((CodeInstruction val) => val.opcode == OpCodes.Br || val.opcode == OpCodes.Br_S).operand;
			CodeInstruction targetedInstr = instructions.First((CodeInstruction val) => val.labels.Contains(target));
			Label? label = default(Label?);
			CodeInstruction lastBranch = instructions.Reverse().First((CodeInstruction val) => CodeInstructionExtensions.Branches(val, ref label) && targetedInstr.labels.Contains(label.Value));
			CodeInstruction loadingInstruction = null;
			int i = 0;
			while (i < instructions.Length)
			{
				yield return instructions[i];
				if (loadingInstruction == null && instructions[i].opcode == OpCodes.Call && ((MethodInfo)instructions[i].operand).Name == "get_Current")
				{
					loadingInstruction = instructions[i + 1].Clone();
					loadingInstruction.opcode = new Dictionary<OpCode, OpCode>
					{
						{
							OpCodes.Stloc_0,
							OpCodes.Ldloc_0
						},
						{
							OpCodes.Stloc_1,
							OpCodes.Ldloc_1
						},
						{
							OpCodes.Stloc_2,
							OpCodes.Ldloc_2
						},
						{
							OpCodes.Stloc_3,
							OpCodes.Ldloc_3
						},
						{
							OpCodes.Stloc_S,
							OpCodes.Ldloc_S
						}
					}[loadingInstruction.opcode];
				}
				if (instructions[i] == lastBranch)
				{
					yield return loadingInstruction;
					yield return new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.DeclaredField(typeof(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo), "checkingForStackableItemData"));
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo), "CheckItemDataIsStackableFindFree", (Type[])null, (Type[])null));
					yield return new CodeInstruction(OpCodes.Brfalse, (object)target);
				}
				int num = i + 1;
				i = num;
			}
		}

		private static bool CheckItemDataIsStackableFindFree(ItemData item, ItemData? target)
		{
			if (target == null)
			{
				return true;
			}
			Dictionary<string, string> dictionary = IsStackable(item, target);
			if (dictionary != null)
			{
				newValuesOnStackable = dictionary;
				return true;
			}
			return false;
		}

		private static void ResetNewValuesOnStackable()
		{
			newValuesOnStackable = null;
		}

		private static void ApplyNewValuesOnStackable(ItemData? __result)
		{
			if (__result == null || newValuesOnStackable == null)
			{
				return;
			}
			foreach (KeyValuePair<string, string> item in newValuesOnStackable)
			{
				__result.m_customData[item.Key] = item.Value;
			}
		}

		private static Dictionary<string, string>? IsStackable(ItemData a, ItemData b)
		{
			<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo2 = <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemExtensions.Data(a);
			if (<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo2 != null)
			{
				return <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo2.IsStackableWithOtherInfo(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemExtensions.Data(b));
			}
			<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo3 = <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemExtensions.Data(b);
			if (<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo3 != null)
			{
				return <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo3.IsStackableWithOtherInfo(null);
			}
			return new Dictionary<string, string>();
		}

		private static bool CheckItemDataStackableAddItem(Inventory __instance, ItemData item, int x, int y, ref Dictionary<string, string>? __state, ref bool __result)
		{
			ItemData itemAt = __instance.GetItemAt(x, y);
			if (itemAt != null)
			{
				Dictionary<string, string> dictionary = IsStackable(item, itemAt);
				if (dictionary == null)
				{
					__result = false;
					return false;
				}
				__state = dictionary;
			}
			return true;
		}

		private static void ApplyCustomItemDataStackableAddItem(Inventory __instance, int x, int y, Dictionary<string, string>? __state, bool __result)
		{
			if (!__result || __state == null)
			{
				return;
			}
			foreach (KeyValuePair<string, string> item in __state)
			{
				__instance.GetItemAt(x, y).m_customData[item.Key] = item.Value;
			}
		}

		private static void ApplyCustomItemDataStackableAutoStack(ItemDrop item, Dictionary<string, string> customData)
		{
			item.m_itemData.m_customData = customData;
		}

		private static Dictionary<string, string>? IsStackableItemDrop(ItemDrop drop, ItemData item)
		{
			return IsStackable(drop.m_itemData, item);
		}

		private static IEnumerable<CodeInstruction> HandleAutostackableItems(IEnumerable<CodeInstruction> instructionList, ILGenerator ilg)
		{
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Expected O, but got Unknown
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Expected O, but got Unknown
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Expected O, but got Unknown
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Expected O, but got Unknown
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Expected O, but got Unknown
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Expected O, but got Unknown
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Expected O, but got Unknown
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Expected O, but got Unknown
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Expected O, but got Unknown
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Expected O, but got Unknown
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Expected O, but got Unknown
			List<CodeInstruction> list = instructionList.ToList();
			FieldInfo fieldInfo = AccessTools.DeclaredField(typeof(ItemData), "m_stack");
			FieldInfo fieldInfo2 = AccessTools.DeclaredField(typeof(ItemDrop), "m_itemData");
			Label? label = default(Label?);
			for (int i = 0; i < list.Count; i++)
			{
				if (!CodeInstructionExtensions.StoresField(list[i], fieldInfo))
				{
					continue;
				}
				for (int num = i; num > 0; num--)
				{
					if (CodeInstructionExtensions.Branches(list[num], ref label))
					{
						for (int num2 = num; num2 > 0; num2--)
						{
							if (CodeInstructionExtensions.LoadsField(list[num2], fieldInfo2, false))
							{
								LocalBuilder localBuilder = ilg.DeclareLocal(typeof(Dictionary<string, string>));
								LocalBuilder localBuilder2 = ilg.DeclareLocal(typeof(ItemData));
								list.Insert(i + 1, new CodeInstruction(OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>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(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo), "IsStackableItemDrop", (Type[])null, (Type[])null)));
								list.Insert(num + 1, new CodeInstruction(OpCodes.Ldloc, (object)localBuilder2.LocalIndex));
								list.Insert(num + 1, new CodeInstruction(OpCodes.Ldarg_0, (object)null));
								list.Insert(num2 + 1, new CodeInstruction(OpCodes.Stloc, (object)localBuilder2.LocalIndex));
								list.Insert(num2 + 1, new CodeInstruction(OpCodes.Dup, (object)null));
								return list;
							}
						}
					}
				}
			}
			throw new Exception("Found no stack store in a branch");
		}

		private static IEnumerable<CodeInstruction> TransferCustomItemDataOnUpgrade(IEnumerable<CodeInstruction> instructions, ILGenerator ilg)
		{
			MethodInfo itemDeleter = AccessTools.DeclaredMethod(typeof(Inventory), "RemoveItem", new Type[1] { typeof(ItemData) }, (Type[])null);
			foreach (CodeInstruction instruction in instructions)
			{
				if (instruction.opcode == OpCodes.Callvirt && CodeInstructionExtensions.OperandIs(instruction, (MemberInfo)itemDeleter))
				{
					yield return new CodeInstruction(OpCodes.Dup, (object)null);
					yield return new CodeInstruction(OpCodes.Stsfld, (object)AccessTools.DeclaredField(typeof(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>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;
				<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo2 = <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemExtensions.Data(currentlyUpgradingItem);
				<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemExtensions.itemInfo.Remove(currentlyUpgradingItem);
				<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemExtensions.itemInfo.Add(item.m_itemData, <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo2);
				item.m_itemData.m_quality = currentlyUpgradingItem.m_quality + 1;
				item.m_itemData.m_variant = currentlyUpgradingItem.m_variant;
				<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo2.ItemData = item.m_itemData;
				<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo2.LoadAll();
				foreach (ItemData value in <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>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<ZNetView>();
			ZDO val = ((Object.op_Implicit((Object)(object)component) && component.IsValid()) ? component.GetZDO() : null);
			if (val != null && val.GetInt(ZDOVars.s_dataCount, -1) != -1)
			{
				return;
			}
			item.m_itemData.m_customData = new Dictionary<string, string>(dropPrefab.GetComponent<ItemDrop>().m_itemData.m_customData);
			if (val == null)
			{
				return;
			}
			int num = 0;
			val.Set(ZDOVars.s_dataCount, item.m_itemData.m_customData.Count, false);
			foreach (KeyValuePair<string, string> customDatum in item.m_itemData.m_customData)
			{
				val.Set($"data_{num}", customDatum.Key);
				val.Set($"data__{num++}", customDatum.Value);
			}
		}

		private static IEnumerable<CodeInstruction> ImportCustomDataOnUpgrade(IEnumerable<CodeInstruction> instructionList)
		{
			List<CodeInstruction> list = instructionList.ToList();
			foreach (CodeInstruction instruction in list)
			{
				yield return instruction;
				if (instruction.opcode == OpCodes.Stfld && CodeInstructionExtensions.OperandIs(instruction, (MemberInfo)AccessTools.DeclaredField(typeof(ItemData), "m_dropPrefab")))
				{
					yield return new CodeInstruction(OpCodes.Ldarg_0, (object)null);
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo), "CopyCustomDataFromUpgradedItem", (Type[])null, (Type[])null));
				}
			}
		}

		private static void TrackAwakeningItem(ItemDrop __instance)
		{
			if (ZNetView.m_forceDisableInit)
			{
				awakeningItem = __instance.m_itemData;
			}
		}

		static <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo()
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected O, but got Unknown
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Expected O, but got Unknown
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Expected O, but got Unknown
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Expected O, but got Unknown
			//IL_01d0: Expected O, but got Unknown
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Expected O, but got Unknown
			//IL_023f: Expected O, but got Unknown
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Expected O, but got Unknown
			//IL_02a1: Expected O, but got Unknown
			//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0305: Unknown result type (might be due to invalid IL or missing references)
			//IL_0310: Expected O, but got Unknown
			//IL_0310: Expected O, but got Unknown
			//IL_0340: Unknown result type (might be due to invalid IL or missing references)
			//IL_034c: Expected O, but got Unknown
			//IL_037a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0381: Expected O, but got Unknown
			//IL_0397: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c0: Expected O, but got Unknown
			//IL_03c0: Expected O, but got Unknown
			//IL_03f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fc: Expected O, but got Unknown
			//IL_042c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0447: Unknown result type (might be due to invalid IL or missing references)
			//IL_0452: Expected O, but got Unknown
			//IL_0452: Expected O, but got Unknown
			//IL_04a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b0: Expected O, but got Unknown
			//IL_0503: Unknown result type (might be due to invalid IL or missing references)
			//IL_0510: Expected O, but got Unknown
			//IL_05bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c9: Expected O, but got Unknown
			//IL_05f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0622: Unknown result type (might be due to invalid IL or missing references)
			//IL_0629: Expected O, but got Unknown
			//IL_064f: Unknown result type (might be due to invalid IL or missing references)
			//IL_065d: Expected O, but got Unknown
			//IL_065d: Expected O, but got Unknown
			//IL_069c: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a9: Expected O, but got Unknown
			//IL_06d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0702: Unknown result type (might be due to invalid IL or missing references)
			//IL_070f: Expected O, but got Unknown
			//IL_070f: Expected O, but got Unknown
			//IL_074e: Unknown result type (might be due to invalid IL or missing references)
			//IL_075b: Expected O, but got Unknown
			ForceLoadTypes = new HashSet<Type>();
			typeInheritorsCache = new Dictionary<Type, HashSet<Type>>();
			knownTypes = new HashSet<string>();
			awakeningItem = null;
			primaryAssembly = Assembly.GetExecutingAssembly();
			assemblyNameCache = new Dictionary<Assembly, string>();
			classKeyCache = new Dictionary<Type, string>();
			removeMethod = typeof(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>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(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>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(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo), "SavePrefix", (Type[])null, (Type[])null), 800, (string[])null, (string[])null, (bool?)null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Inventory), "AddItem", new Type[4]
			{
				typeof(ItemData),
				typeof(int),
				typeof(int),
				typeof(int)
			}, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo), "CheckItemDataStackableAddItem", (Type[])null, (Type[])null)), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>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(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo), "SaveCheckingForStackableItemData", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>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(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo), "SaveCheckingForStackableItemData", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>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(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo), "SaveCheckingForStackableItemData", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>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(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>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(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo), "CheckStackableInFindFreeStackMethods", (Type[])null, (Type[])null));
			val.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo), "ResetNewValuesOnStackable", (Type[])null, (Type[])null)), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>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(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>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(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo), "TransferCustomItemDataOnUpgrade", (Type[])null, (Type[])null)), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>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(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>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(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>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(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>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(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo), "TrackAwakeningItem", (Type[])null, (Type[])null));
			val2 = new HarmonyMethod(AccessTools.DeclaredMethod(typeof(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo), "ImportCustomDataOnUpgrade", (Type[])null, (Type[])null), 800, (string[])null, (string[])null, (bool?)null);
			val.Patch((MethodBase)methodInfo2, val3, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>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(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>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(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo), "ItemDataClonePrefix", (Type[])null, (Type[])null)), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>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(<a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo), "ItemDataClonePostfixDelayed", (Type[])null, (Type[])null), 499, (string[])null, (string[])null, (bool?)null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}
	}
	[PublicAPI]
	public class <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ForeignItemInfo : IEnumerable<object>, IEnumerable
	{
		private readonly object foreignItemInfo;

		public string Mod => ((string)foreignItemInfo.GetType().GetProperty("Mod")?.GetValue(foreignItemInfo)) ?? "";

		public ItemData ItemData { get; private set; }

		public string? this[string key]
		{
			get
			{
				object obj = foreignItemInfo.GetType().InvokeMember("Item", BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty, null, foreignItemInfo, new object[1] { key });
				if (obj != null)
				{
					return (string)obj.GetType().GetProperty("Value")?.GetValue(obj);
				}
				return null;
			}
			set
			{
				foreignItemInfo.GetType().GetMethod("set_Item", BindingFlags.Instance | BindingFlags.Public)?.Invoke(foreignItemInfo, new object[2] { key, value });
			}
		}

		internal <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ForeignItemInfo(ItemData itemData, object foreignItemInfo)
		{
			ItemData = itemData;
			this.foreignItemInfo = foreignItemInfo;
		}

		public T GetOrCreate<T>(string key = "") where T : class, new()
		{
			return Add<T>(key) ?? Get<T>(key);
		}

		private object? call(string name, object?[] values, Type?[] args, Type? generic = null)
		{
			MethodInfo[] methods = foreignItemInfo.GetType().GetMethods();
			foreach (MethodInfo methodInfo in methods)
			{
				if (methodInfo.Name == name && (from p in methodInfo.GetParameters()
					select (!p.ParameterType.IsGenericParameter) ? p.ParameterType : null).SequenceEqual<Type>(args) && (object)generic != null == methodInfo.IsGenericMethod)
				{
					MethodInfo methodInfo2 = methodInfo;
					if ((object)generic != null)
					{
						methodInfo2 = methodInfo2.MakeGenericMethod(generic);
					}
					return methodInfo2.Invoke(foreignItemInfo, values);
				}
			}
			return null;
		}

		public T? Add<T>(string key = "") where T : class, new()
		{
			return call("Add", new object[1] { key }, new Type[1] { typeof(string) }, typeof(T)) as T;
		}

		public T? Get<T>(string key = "") where T : class
		{
			return call("Get", new object[1] { key }, new Type[1] { typeof(string) }, typeof(T)) as T;
		}

		public Dictionary<string, T> GetAll<T>() where T : class
		{
			return ((call("GetAll", Array.Empty<object>(), Array.Empty<Type>(), typeof(T)) as T) as Dictionary<string, T>) ?? new Dictionary<string, T>();
		}

		public bool Remove(string key = "")
		{
			return call("Add", new object[1] { key }, new Type[1] { typeof(string) }) as bool? == true;
		}

		public bool Remove<T>(string key = "") where T : class
		{
			return call("Remove", new object[1] { key }, new Type[1] { typeof(string) }, typeof(T)) as bool? == true;
		}

		public bool Remove<T>(T itemData) where T : class
		{
			return call("Remove", new object[1] { itemData }, new Type[1], typeof(T)) as bool? == true;
		}

		public void Save()
		{
			call("Save", Array.Empty<object>(), Array.Empty<Type>());
		}

		public void LoadAll()
		{
			call("LoadAll", Array.Empty<object>(), Array.Empty<Type>());
		}

		public IEnumerator<object> GetEnumerator()
		{
			return (IEnumerator<object>)((call("GetEnumerator", Array.Empty<object>(), Array.Empty<Type>()) as IEnumerator<object>) ?? ((object)new List<object>().GetEnumerator()));
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}
	}
	[PublicAPI]
	public static class <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemExtensions
	{
		private const string className = "ItemDataManager.ItemExtensions";

		internal static readonly ConditionalWeakTable<ItemData, <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo> itemInfo = new ConditionalWeakTable<ItemData, <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo>();

		private static readonly ConditionalWeakTable<ItemData, Dictionary<string, <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ForeignItemInfo?>> foreignItemInfo = new ConditionalWeakTable<ItemData, Dictionary<string, <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ForeignItemInfo>>();

		public static <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo Data(this ItemData item)
		{
			if (itemInfo.TryGetValue(item, out <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo value))
			{
				return value;
			}
			itemInfo.Add(item, value = new <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ItemInfo(item));
			return value;
		}

		public static <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ForeignItemInfo? Data(this ItemData item, string mod)
		{
			Dictionary<string, <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>ForeignItemInfo> 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<ParameterModifier>())?.Invoke(null, new object[1] { item });
			if (obj != null)
			{
				return orCreateValue[mod] = new <a5a7ce1e-8fa3-402d-86ac-cc292e8cc2e9>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 OttoStash
{
	[BepInPlugin("potto007.OttoStash", "OttoStash", "3.4.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class OttoStashPlugin : BaseUnityPlugin
	{
		public enum Toggle
		{
			Off,
			On
		}

		private class ConfigurationManagerAttributes
		{
			[UsedImplicitly]
			public int? Order;

			[UsedImplicitly]
			public bool? Browsable;

			[UsedImplicitly]
			public string Category;

			[UsedImplicitly]
			public Action<ConfigEntryBase>? 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 = "OttoStash";

		internal const string ModVersion = "3.4.1";

		internal const string Author = "potto007";

		internal const string ModGUID = "potto007.OttoStash";

		internal const string KgGuid = "kg.ItemDrawers";

		internal const string BackpacksGuid = "org.bepinex.plugins.backpacks";

		private const string ConfigFileName = "potto007.OttoStash.cfg";

		private static readonly string ConfigFileFullPath;

		private readonly Harmony _harmony = new Harmony("potto007.OttoStash");

		internal static readonly ManualLogSource LogSource;

		private static readonly ConfigSync ConfigSync;

		internal static bool BackpacksIsLoaded;

		internal static readonly string yamlFileName;

		internal static readonly string yamlPath;

		internal static readonly CustomSyncedValue<string> OttoStashContainerData;

		internal static readonly CustomSyncedValue<string> CraftyContainerGroupsData;

		internal static OttoStashPlugin self;

		private static readonly MethodInfo? LoadImageMethod;

		private static ConfigEntry<Toggle> _serverConfigLocked;

		internal static ConfigEntry<Toggle> DontStoreToBackpacks;

		internal static ConfigEntry<Toggle> ChestsPickupFromGround;

		internal static ConfigEntry<Toggle> MustHaveExistingItemToPull;

		internal static ConfigEntry<KeyboardShortcut> SingleItemShortcut;

		private static ConfigEntry<KeyboardShortcut> _storeShortcut;

		private static ConfigEntry<KeyboardShortcut> _pauseShortcut;

		internal static ConfigEntry<int> SecondsToWaitBeforeStoring;

		internal static ConfigEntry<float> IntervalSeconds;

		internal static ConfigEntry<Toggle> FishSuction;

		internal static ConfigEntry<float> PlayerRange;

		internal static ConfigEntry<float> FallbackRange;

		internal static ConfigEntry<Toggle> PlayerIgnoreHotbar;

		internal static ConfigEntry<Toggle> PlayerIgnoreQuickSlots;

		internal static ConfigEntry<string> PingVfxString;

		internal static ConfigEntry<Toggle> HighlightContainers;

		internal static ConfigEntry<Toggle> PingContainers;

		public static ConfigEntry<Color> BorderColorFavoritedItem;

		public static ConfigEntry<Color> BorderColorFavoritedItemOnFavoritedSlot;

		public static ConfigEntry<Color> BorderColorFavoritedSlot;

		public static ConfigEntry<bool> DisplayTooltipHint;

		public static ConfigEntry<KeyboardShortcut> FavoritingModifierKeybind1;

		public static ConfigEntry<KeyboardShortcut> FavoritingModifierKeybind2;

		public static ConfigEntry<KeyboardShortcut> SearchModifierKeybind;

		public static ConfigEntry<string> FavoritedItemTooltip;

		public static ConfigEntry<string> FavoritedSlotTooltip;

		public static ConfigEntry<string> ItemOnFavoritedSlotTooltip;

		private static void CarryOverAzuAutoStoreConfig()
		{
			try
			{
				string configPath = Paths.ConfigPath;
				char directorySeparatorChar = Path.DirectorySeparatorChar;
				string text = configPath + directorySeparatorChar + "Azumatt.AzuAutoStore.cfg";
				if (File.Exists(text) && !File.Exists(ConfigFileFullPath))
				{
					File.Copy(text, ConfigFileFullPath);
					LogSource.LogInfo((object)"Carried your AzuAutoStore settings over to potto007.OttoStash.cfg.");
				}
				string configPath2 = Paths.ConfigPath;
				directorySeparatorChar = Path.DirectorySeparatorChar;
				string text2 = configPath2 + directorySeparatorChar + "Azumatt.AzuAutoStore.yml";
				if (File.Exists(text2) && !File.Exists(yamlPath))
				{
					File.Copy(text2, yamlPath);
					LogSource.LogInfo((object)("Carried your AzuAutoStore container rules over to " + yamlFileName + "."));
				}
			}
			catch (Exception ex)
			{
				LogSource.LogWarning((object)("Could not carry the AzuAutoStore configuration over: " + ex.Message));
			}
		}

		public void Awake()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Expected O, but got Unknown
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Expected O, but got Unknown
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Expected O, but got Unknown
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Expected O, but got Unknown
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Expected O, but got Unknown
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Expected O, but got Unknown
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Expected O, but got Unknown
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Expected O, but got Unknown
			//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: Expected O, but got Unknown
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f5: Expected O, but got Unknown
			//IL_0315: Unknown result type (might be due to invalid IL or missing references)
			//IL_0320: Expected O, but got Unknown
			//IL_033c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0347: Expected O, but got Unknown
			//IL_0361: Unknown result type (might be due to invalid IL or missing references)
			//IL_038a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0395: Expected O, but got Unknown
			//IL_03ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e0: Expected O, but got Unknown
			//IL_0400: Unknown result type (might be due to invalid IL or missing references)
			//IL_0414: Unknown result type (might be due to invalid IL or missing references)
			//IL_041f: Expected O, but got Unknown
			//IL_0436: Unknown result type (might be due to invalid IL or missing references)
			//IL_044a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0455: Expected O, but got Unknown
			//IL_047c: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_050d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0536: Unknown result type (might be due to invalid IL or missing references)
			self = this;
			CarryOverAzuAutoStoreConfig();
			_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<Toggle>(_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<float>(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<int>(0, 60), Array.Empty<object>()));
			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<object>()));
			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<object>()));
			SingleItemShortcut = config<KeyboardShortcut>("2 - Shortcuts", "Store Single Item Shortcut", new KeyboardShortcut((KeyCode)325, Array.Empty<KeyCode>()), 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<KeyboardShortcut>("2 - Shortcuts", "Store Shortcut", new KeyboardShortcut((KeyCode)46, Array.Empty<KeyCode>()), 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<KeyboardShortcut>("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<object>()), synchronizedSetting: false);
			SearchModifierKeybind = config<KeyboardShortcut>("2 - Shortcuts", "SearchModifierKeybind", new KeyboardShortcut((KeyCode)121, Array.Empty<KeyCode>()), new ConfigDescription("While holding this, you can search nearby chests for the prefab you clicked in your inventory.", (AcceptableValueBase)(object)new AcceptableShortcuts(), Array.Empty<object>()), 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<Color>(text, "BorderColorFavoritedItem", new Color(1f, 0.8482759f, 0f), "Color of the border for slots containing favorited items.", synchronizedSetting: false);
			BorderColorFavoritedItemOnFavoritedSlot = config<Color>(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<Color>(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<KeyboardShortcut>(text, "FavoritingModifierKeybind1", new KeyboardShortcut((KeyCode)122, Array.Empty<KeyCode>()), text2 + " Identical to FavoritingModifierKeybind2.", synchronizedSetting: false);
			FavoritingModifierKeybind2 = config<KeyboardShortcut>(text, "FavoritingModifierKeybind2", new KeyboardShortcut((KeyCode)122, Array.Empty<KeyCode>()), text2 + " Identical to FavoritingModifierKeybind1.", synchronizedSetting: false);
			FavoritedItemTooltip = config(text, "FavoritedItemTooltip", "Item is favorited and will not be stored", string.Empty, synchronizedSetting: false);
			FavoritedSlotTooltip = config(text, "FavoritedSlotTooltip", "Slot is favorited and will not be stored", string.Empty, synchronizedSetting: false);
			ItemOnFavoritedSlotTooltip = config(text, "ItemOnFavoritedSlotTooltip", "Item & Slot are favorited and will not be stored", string.Empty, synchronizedSetting: false);
			ReplaceOldDefault(FavoritedItemTooltip, "Item is favorited and won't be stored");
			ReplaceOldDefault(FavoritedSlotTooltip, "Slot is favorited and won't be stored");
			ReplaceOldDefault(ItemOnFavoritedSlotTooltip, "Item & Slot are favorited and won't be stored");
			if (!File.Exists(yamlPath))
			{
				WriteConfigFileFromResource(yamlPath);
			}
			OttoStashContainerData.ValueChanged += OnValChangedUpdate;
			OttoStashContainerData.AssignLocalValue(File.ReadAllText(yamlPath));
			AutoDoc();
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			_harmony.PatchAll(executingAssembly);
			SetupWatcher();
		}

		public void Start()
		{
			FavoritingPatches.BorderSprite = LoadSprite("border.png");
			if (Chainloader.PluginInfos.ContainsKey("org.bepinex.plugins.backpacks"))
			{
				BackpacksIsLoaded = true;
			}
			if (!MUCCompat.MUCLoaded)
			{
				MUCCompat.ForceEnableMUC(enabled: true);
			}
		}

		private static void ReplaceOldDefault(ConfigEntry<string> entry, string oldDefault)
		{
			if (entry.Value == oldDefault)
			{
				entry.Value = (string)((ConfigEntryBase)entry).DefaultValue;
			}
		}

		private void AutoDoc()
		{
		}

		private static void WriteConfigFileFromResource(string configFilePath)
		{
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			string text = "OttoStash.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))
			{
				KeyboardShortcut value = _storeShortcut.Value;
				if (((KeyboardShortcut)(ref value)).IsDown() && ((Character)Player.m_localPlayer).TakeInput())
				{
					PlayerStore.StoreAll();
				}
				value = _pauseShortcut.Value;
				if (((KeyboardShortcut)(ref value)).IsDown() && ((Character)Player.m_localPlayer).TakeInput())
				{
					StorePause.Toggle();
				}
			}
		}

		private void OnDestroy()
		{
			((BaseUnityPlugin)this).Config.Save();
		}

		private void SetupWatcher()
		{
			FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, "potto007.OttoStash.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
			{
				StashLog.Debug("ReadConfigValues called");
				((BaseUnityPlugin)this).Config.Reload();
			}
			catch
			{
				StashLog.Error("There was an issue loading your potto007.OttoStash.cfg");
				StashLog.Error("Please check your config entries for spelling and format!");
			}
		}

		private void ReadYamlFiles(object sender, FileSystemEventArgs e)
		{
			if (!File.Exists(yamlPath))
			{
				return;
			}
			try
			{
				LogSource.LogDebug((object)"ReadConfigValues called");
				OttoStashContainerData.AssignLocalValue(File.ReadAllText(yamlPath));
			}
			catch
			{
				LogSource.LogError((object)("There was an issue loading your " + yamlFileName));
				LogSource.LogError((object)"Please check your entries for spelling and format!");
			}
		}

		private static void OnValChangedUpdate()
		{
			LogSource.LogDebug((object)"OnValChanged called");
			try
			{
				ContainerRules.Read(OttoStashContainerData.Value);
				ContainerRules.ParseGroups();
			}
			catch (Exception arg)
			{
				LogSource.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_0008: Expected O, but got Unknown
			Texture2D val = new Texture2D(0, 0);
			if (LoadImageMethod == null)
			{
				LogSource.LogError((object)"UnityEngine.ImageConversion.LoadImage was not found. Textures will not load.");
				return val;
			}
			LoadImageMethod.Invoke(null, new object[2]
			{
				val,
				ReadEmbeddedFileBytes("assets." + name)
			});
			return val;
		}

		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<T> config<T>(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			ConfigDescription val = new ConfigDescription(description.Description + (synchronizedSetting ? " [Synced with Server]" : " [Not Synced with Server]"), description.AcceptableValues, description.Tags);
			ConfigEntry<T> val2 = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, val);
			ConfigSync.AddConfigEntry<T>(val2).SynchronizedConfig = synchronizedSetting;
			return val2;
		}

		private ConfigEntry<T> config<T>(string group, string name, T value, string description, bool synchronizedSetting = true)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			return config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting);
		}

		private ConfigEntry<T> TextEntryConfig<T>(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			ConfigDescription val = new ConfigDescription(description.Description + (synchronizedSetting ? " [Synced with Server]" : " [Not Synced with Server]"), description.AcceptableValues, description.Tags);
			ConfigEntry<T> val2 = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, val);
			ConfigSync.AddConfigEntry<T>(val2).SynchronizedConfig = synchronizedSetting;
			return val2;
		}

		private ConfigEntry<T> TextEntryConfig<T>(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 OttoStashPlugin()
		{
			string configPath = Paths.ConfigPath;
			char directorySeparatorChar = Path.DirectorySeparatorChar;
			ConfigFileFullPath = configPath + directorySeparatorChar + "potto007.OttoStash.cfg";
			LogSource = Logger.CreateLogSource("OttoStash");
			ConfigSync = new ConfigSync("potto007.OttoStash")
			{
				DisplayName = "OttoStash",
				CurrentVersion = "3.4.1",
				MinimumRequiredVersion = "3.4.1",
				ModRequired = false
			};
			BackpacksIsLoaded = false;
			yamlFileName = "potto007.OttoStash.yml";
			string configPath2 = Paths.ConfigPath;
			directorySeparatorChar = Path.DirectorySeparatorChar;
			yamlPath = configPath2 + directorySeparatorChar + yamlFileName;
			OttoStashContainerData = new CustomSyncedValue<string>(ConfigSync, "ottostashData", "");
			CraftyContainerGroupsData = new CustomSyncedValue<string>(ConfigSync, "ottostashGroupsData", "");
			self = null;
			LoadImageMethod = AccessTools.Method("UnityEngine.ImageConversion:LoadImage", new Type[2]
			{
				typeof(Texture2D),
				typeof(byte[])
			}, (Type[])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 OttoStashPlugin.Toggle toggle)
		{
			return toggle == OttoStashPlugin.Toggle.On;
		}

		public static bool IsOff(this OttoStashPlugin.Toggle toggle)
		{
			return toggle == OttoStashPlugin.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<KeyCode, bool>)Input.GetKey);
			}
			return false;
		}

		public static bool IsKeyHeld(this KeyboardShortcut shortcut)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			if ((int)((KeyboardShortcut)(ref shortcut)).MainKey != 0 && Input.GetKey(((KeyboardShortcut)(ref shortcut)).MainKey))
			{
				return ((KeyboardShortcut)(ref shortcut)).Modifiers.All((Func<KeyCode, bool>)Input.GetKey);
			}
			return false;
		}
	}
	public static class 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)
			});
		}
	}
}
namespace OttoStash.Storing
{
	internal sealed class BackpackTarget : IStoreTarget
	{
		private readonly ItemContainer _backpack;

		public GameObject GameObject => ((Component)Player.m_localPlayer).gameObject;

		public ZNetView NetView => ((Character)Player.m_localPlayer).m_nview;

		internal BackpackTarget(ItemContainer backpack)
		{
			_backpack = backpack;
		}

		public bool IsOwner()
		{
			return true;
		}

		public int StoreAll()
		{
			if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				return 0;
			}
			int num = 0;
			Inventory inventory = ((Humanoid)Player.m_localPlayer).GetInventory();
			List<ItemData> allItems = inventory.GetAllItems();
			for (int num2 = allItems.Count - 1; num2 >= 0; num2--)
			{
				ItemData item = allItems[num2];
				if (!PlayerItemFilter.StaysWithPlayer(item))
				{
					num += StoreOne(item, inventory, announce: false);
				}
			}
			return num;
		}

		public int StoreItem(ItemData item, Inventory playerInventory)
		{
			if ((Object)(object)Player.m_localPlayer == (Object)null || item == null)
			{
				return 0;
			}
			if (PlayerItemFilter.StaysWithPlayer(item))
			{
				return 0;
			}
			return StoreOne(item, playerInventory ?? ((Humanoid)Player.m_localPlayer).GetInventory(), announce: true);
		}

		private int StoreOne(ItemData item, Inventory inventory, bool announce)
		{
			StashLog.Debug("Checking item " + PrefabNames.Of(item));
			int stack = item.m_stack;
			if (!TryStore(ref item, announce))
			{
				return 0;
			}
			int num = stack - item.m_stack;
			if (num <= 0)
			{
				return 0;
			}
			if (item.m_stack == 0)
			{
				inventory.RemoveItem(item);
			}
			else
			{
				inventory.Changed(false, false);
			}
			StashLog.Debug($"Stored {num} {PrefabNames.Of(item)} into {((Object)_backpack.Item.m_dropPrefab).name}");
			if (!ContainerRegistry.Filled.Contains(this))
			{
				ContainerRegistry.Filled.Add(this);
			}
			return num;
		}

		private bool TryStore(ref ItemData item, bool announce)
		{
			string name = ((Object)_backpack.Item.m_dropPrefab).name;
			StashLog.Debug("Checking container " + name);
			if (item.m_shared == null)
			{
				return false;
			}
			if (OttoStashPlugin.MustHaveExistingItemToPull.Value.IsOn() && !_backpack.Inventory.HaveItem(item.m_shared.m_name, true))
			{
				if (announce)
				{
					StashLog.Debug("Skipping " + ((Object)item.m_dropPrefab).name + " because it is not in the container");
					((Character)Player.m_localPlayer).Message((MessageType)2, "<color=red>" + item.m_shared.m_name + " is not in nearby containers</color>", 0, (Sprite)null, false);
				}
				return false;
			}
			if (!ContainerRules.CanStore(PrefabNames.FromSceneName(name), ((Object)item.m_dropPrefab).name))
			{
				return false;
			}
			bool flag = false;
			while (item.m_stack > 1 && _backpack.Inventory.CanAddItem(item, 1))
			{
				ItemData val = item.Clone();
				val.m_stack = 1;
				Backpacks.API.AddItemToBackpack(_backpack.Item, val);
				ItemData obj = item;
				obj.m_stack--;
				flag = true;
				StashLog.Debug("Auto storing " + ((Object)item.m_dropPrefab).name + " in " + name);
			}
			if (item.m_stack == 1 && _backpack.Inventory.CanAddItem(item, 1))
			{
				ItemData item2 = item.Clone();
				item.m_stack = 0;
				Backpacks.API.AddItemToBackpack(_backpack.Item, item2);
				flag = true;
			}
			if (!flag)
			{
				return false;
			}
			try
			{
				_backpack.Save();
			}
			catch
			{
			}
			return true;
		}
	}
	internal static class ChestEffects
	{
		internal static void Ping(GameObject chest)
		{
			if (!((Object)(object)chest == (Object)null))
			{
				if (OttoStashPlugin.PingContainers.Value.IsOn() && (Object)(object)chest.GetComponent<ChestPingEffect>() == (Object)null)
				{
					chest.AddComponent<ChestPingEffect>();
				}
				if (OttoStashPlugin.HighlightContainers.Value.IsOn() && (Object)(object)chest.GetComponent<ChestHighlight>() == (Object)null)
				{
					chest.AddComponent<ChestHighlight>();
				}
			}
		}
	}
	internal sealed class ChestPingEffect : MonoBehaviour
	{
		private const float LifetimeSeconds = 10f;

		private GameObject? _effect;

		private void Awake()
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			if (!string.IsNullOrWhiteSpace(OttoStashPlugin.PingVfxString.Value))
			{
				_effect = Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab(OttoStashPlugin.PingVfxString.Value), ((Component)this).transform.position, Quaternion.identity);
				((MonoBehaviour)this).InvokeRepeating("Finish", 10f, 1f);
			}
		}

		private void Finish()
		{
			if ((Object)(object)_effect != (Object)null)
			{
				ZNetScene.instance.Destroy(_effect);
			}
			Object.DestroyImmediate((Object)(object)this);
		}
	}
	internal sealed class ChestHighlight : MonoBehaviour
	{
		private const float LifetimeSeconds = 10f;

		private WearNTear? _wearNTear;

		private void Awake()
		{
			WearNTear val = default(WearNTear);
			_wearNTear = (((Component)this).TryGetComponent<WearNTear>(ref val) ? val : null);
			if ((Object)(object)_wearNTear == (Object)null)
			{
				Finish();
			}
			else
			{
				((MonoBehaviour)this).InvokeRepeating("Finish", 10f, 1f);
			}
		}

		private void Update()
		{
			WearNTear? wearNTear = _wearNTear;
			if (wearNTear != null)
			{
				wearNTear.Highlight();
			}
		}

		private void Finish()
		{
			Object.DestroyImmediate((Object)(object)this);
		}
	}
	internal static class ChestGate
	{
		internal static bool IsOpenElsewhere(bool isLocalPlayersOpenChest, bool ownerInUseFlag, int syncedInUse, bool multiUserChestActive)
		{
			if (multiUserChestActive)
			{
				return false;
			}
			if (isLocalPlayersOpenChest)
			{
				return false;
			}
			if (!ownerInUseFlag)
			{
				return syncedInUse == 1;
			}
			return true;
		}

		internal static bool IsOpenElsewhere(Container? chest)
		{
			if ((Object)(object)chest == (Object)null)
			{
				return false;
			}
			bool isLocalPlayersOpenChest = (Object)(object)InventoryGui.instance != (Object)null && (Object)(object)InventoryGui.instance.m_currentContainer == (Object)(object)chest;
			ZDO val = (((Object)(object)chest.m_nview != (Object)null) ? chest.m_nview.GetZDO() : null);
			return IsOpenElsewhere(syncedInUse: (val != null) ? val.GetInt(ZDOVars.s_inUse, 0) : 0, isLocalPlayersOpenChest: isLocalPlayersOpenChest, ownerInUseFlag: chest.IsInUse(), multiUserChestActive: MUCCompat.MultiUserChestActive);
		}
	}
	internal static class ChestStore
	{
		internal static bool TryStore(Container chest, ref ItemData item, bool fromPlayer, bool announce)
		{
			StashLog.BuildDebug("Checking container " + (((Object)(object)chest != (Object)null) ? ((Object)chest).name : "none"));
			if ((Object)(object)chest == (Object)null || item.m_shared == null || (Object)(object)item.m_dropPrefab == (Object)null)
			{
				return false;
			}
			Inventory inventory = chest.GetInventory();
			if (inventory == null)
			{
				return false;
			}
			string name = ((Object)item.m_dropPrefab).name;
			if (OttoStashPlugin.MustHaveExistingItemToPull.Value.IsOn() && !inventory.HaveItem(item.m_shared.m_name, true))
			{
				if (announce)
				{
					StashLog.Debug("Skipping " + name + " because it is not in the container");
					((Character)Player.m_localPlayer).Message((MessageType)2, "<color=red>" + item.m_shared.m_name + " [" + name + "] is not in nearby containers</color>", 0, (Sprite)null, false);
				}
				return false;
			}
			if (!ContainerRules.CanStore(PrefabNames.FromSceneName(((Object)((Component)chest).transform.root).name), name))
			{
				if (announce)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "<color=red>" + item.m_shared.m_name + " [" + name + "] cannot be stored based on configuration settings</color>", 0, (Sprite)null, false);
				}
				StashLog.Debug(item.m_shared.m_name + " cannot be stored based on configuration setting");
				return false;
			}
			if (!chest.CheckAccess(Game.instance.GetPlayerProfile().GetPlayerID()))
			{
				StashLog.Debug("Cannot store items in " + ((Object)chest).name + " because the player does not have access.");
				return false;
			}
			if (!MUCCompat.MultiUserChestActive && !chest.m_nview.IsOwner())
			{
				StashLog.Debug("Cannot store items in " + ((Object)chest).name + " because the player is not the owner.");
				return false;
			}
			if (InventoryMove.MoveStackChunked(inventory, item) <= 0)
			{
				return false;
			}
			if (!fromPlayer)
			{
				ChestEffects.Ping(((Component)chest).gameObject);
			}
			chest.Save();
			return true;
		}

		internal static float RangeOf(Container chest)
		{
			if (chest.GetInventory() == null)
			{
				return -1f;
			}
			return ContainerRules.RangeFor(PrefabNames.FromSceneName(((Object)((Component)chest).transform.root).name), OttoStashPlugin.FallbackRange.Value);
		}
	}
	internal sealed class ChestTarget : IStoreTarget
	{
		private readonly Container _chest;

		internal Container Chest => _chest;

		public GameObject GameObject => ((Component)_chest).gameObject;

		public ZNetView NetView => _chest.m_nview;

		internal ChestTarget(Container chest)
		{
			_chest = chest;
		}

		public bool IsOwner()
		{
			return _chest.m_nview.IsOwner();
		}

		public int StoreAll()
		{
			if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				return 0;
			}
			int num = 0;
			Inventory inventory = ((Humanoid)Player.m_localPlayer).GetInventory();
			List<ItemData> allItems = inventory.GetAllItems();
			for (int num2 = allItems.Count - 1; num2 >= 0; num2--)
			{
				ItemData item = allItems[num2];
				if (!PlayerItemFilter.StaysWithPlayer(item))
				{
					num += StoreOne(item, inventory, announce: false);
				}
			}
			return num;
		}

		public int StoreItem(ItemData item, Inventory playerInventory)
		{
			if ((Object)(object)Player.m_localPlayer == (Object)null || item == null)
			{
				return 0;
			}
			if (PlayerItemFilter.StaysWithPlayer(item))
			{
				return 0;
			}
			return StoreOne(item, playerInventory ?? ((Humanoid)Player.m_localPlayer).GetInventory(), announce: true);
		}

		private int StoreOne(ItemData item, Inventory inventory, bool announce)
		{
			StashLog.Debug("Checking item " + PrefabNames.Of(item));
			int stack = item.m_stack;
			if (!ChestStore.TryStore(_chest, ref item, fromPlayer: true, announce))
			{
				return 0;
			}
			int num = stack - item.m_stack;
			if (num <= 0)
			{
				return 0;
			}
			if (item.m_stack == 0)
			{
				inventory.RemoveItem(item);
			}
			else
			{
				inventory.Changed(false, false);
			}
			StashLog.Debug($"Stored {num} {PrefabNames.Of(item)} into {((Object)_chest).name}");
			if (!ContainerRegistry.Filled.Contains(this))
			{
				ContainerRegistry.Filled.Add(this);
			}
			return num;
		}
	}
	internal static class ContainerRegistry
	{
		internal static readonly List<Container> Containers = new List<Container>();

		internal static readonly List<IStoreTarget> Filled = new List<IStoreTarget>();

		internal static void Add(Container container)
		{
			if (!Containers.Contains(container))
			{
				Containers.Add(container);
				StashLog.Debug("Added container " + ((Object)container).name + " to list");
			}
		}

		internal static void Remove(Container container)
		{
			if (Containers.Remove(container) && (Object)(object)container != (Object)null)
			{
				StashLog.Debug("Removed container " + ((Object)container).name + " from list");
			}
		}

		internal static void Prune()
		{
			foreach (Container item in Containers.ToList())
			{
				if ((Object)(object)item == (Object)null || (Object)(object)((Component)item).transform == (Object)null || item.GetInventory() == null)
				{
					Containers.Remove(item);
				}
			}
		}

		internal static List<IStoreTarget> Nearby(Component origin, float range)
		{
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1