Decompiled source of Quick Stack Store Sort Trash Restock v1.4.7

QuickStackStore.dll

Decompiled 2 months 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 BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
using ServerSync;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Core.Tokens;
using YamlDotNet.Helpers;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.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: AssemblyCopyright("Copyright © Goldenrevolver 2022")]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("QuickStackStore")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyDescription("")]
[assembly: Guid("beeb50d8-ebd2-4791-9866-4bbf2d810422")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("QuickStackStore")]
[assembly: ComVisible(false)]
[assembly: AssemblyFileVersion("1.4.7.0")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.4.7.0")]
[module: UnverifiableCode]
namespace QuickStackStore
{
	[BepInPlugin("goldenrevolver.quick_stack_store", "Quick Stack - Store - Sort - Trash - Restock", "1.4.7")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInIncompatibility("virtuacode.valheim.trashitems")]
	public class QuickStackStorePlugin : BaseUnityPlugin
	{
		public const string GUID = "goldenrevolver.quick_stack_store";

		public const string NAME = "Quick Stack - Store - Sort - Trash - Restock";

		public const string VERSION = "1.4.7";

		protected void Start()
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			if (CompatibilitySupport.HasOutdatedMUCPlugin())
			{
				Helper.LogO("This mod is not compatible with versions of Multi User Chest earlier than 0.4.0, aborting start");
				return;
			}
			if (API.IsLoaded())
			{
				CompatibilitySupport.isUsingAzuEPIWithAPI = true;
				if (CompatibilitySupport.HasAzuEPIWithQuickslotCompatibleAPI())
				{
					CompatibilitySupport.isUsingAzuEPIWithQuickslotCompatibleAPI = true;
				}
			}
			string text = "QuickStackStore.Resources";
			BorderRenderer.border = Helper.LoadSprite(text + ".border.png", new Rect(0f, 0f, 1024f, 1024f));
			TrashModule.trashSprite = Helper.LoadSprite(text + ".trash.png", new Rect(0f, 0f, 64f, 64f));
			TrashModule.bgSprite = Helper.LoadSprite(text + ".trashmask.png", new Rect(0f, 0f, 96f, 112f));
			QSSConfig.LoadConfig((BaseUnityPlugin)(object)this);
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "goldenrevolver.quick_stack_store");
		}
	}
	[HarmonyPatch(typeof(FejdStartup))]
	internal class FejdStartupPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("Awake")]
		private static void FejdStartupAwakePatch()
		{
			LocalizationLoader.SetupTranslations();
			QSSConfig.ConfigTemplate_SettingChanged(null, null);
		}
	}
	internal sealed class ConfigurationManagerAttributes
	{
		public bool? ShowRangeAsPercent;

		public Action<ConfigEntryBase> CustomDrawer;

		public bool? Browsable;

		public string Category;

		public object DefaultValue;

		public bool? HideDefaultButton;

		public bool? HideSettingName;

		public string Description;

		public string DispName;

		public int? Order;

		public bool? ReadOnly;

		public bool? IsAdvanced;

		public Func<object, string> ObjToStr;

		public Func<string, object> StrToObj;

		internal static ConfigDescription CustomDisplay(string category, string displayName, string description, AcceptableValueBase acceptableValues = null)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			return new ConfigDescription(description, acceptableValues, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Category = category,
					DispName = displayName
				}
			});
		}

		internal static ConfigDescription CustomCategory(string category, AcceptableValueBase acceptableValues = null)
		{
			return CustomCategoryWithDescription(category, string.Empty, acceptableValues);
		}

		internal static ConfigDescription CustomCategoryWithDescription(string category, string description, AcceptableValueBase acceptableValues = null)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			return new ConfigDescription(description, acceptableValues, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Category = category
				}
			});
		}

		internal static ConfigDescription MUCSettingDisplay(string overwriteName, string category, string description, AcceptableValueBase acceptableValues = null)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			if (CompatibilitySupport.HasPlugin("com.maxsch.valheim.MultiUserChest"))
			{
				return new ConfigDescription("Area quick stacking and area restocking is always allowed while using 'Multi User Chest'.", acceptableValues, new object[1]
				{
					new ConfigurationManagerAttributes
					{
						DispName = overwriteName,
						Category = category,
						ReadOnly = true,
						CustomDrawer = delegate
						{
							CustomLabelDrawer("Enabled ('Multi User Chest' is installed)");
						}
					}
				});
			}
			return CustomCategoryWithDescription(category, description, acceptableValues);
		}

		internal static ConfigDescription HiddenDisplay(Func<bool> condition, string description, AcceptableValueBase acceptableValues = null)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			if (condition())
			{
				return new ConfigDescription(description, acceptableValues, new object[1]
				{
					new ConfigurationManagerAttributes
					{
						Browsable = false,
						ReadOnly = true
					}
				});
			}
			return new ConfigDescription(description, acceptableValues, Array.Empty<object>());
		}

		internal static ConfigDescription HiddenTrashingDisplay(string description, AcceptableValueBase acceptableValues = null)
		{
			return HiddenDisplay(CompatibilitySupport.DisallowAllTrashCanFeatures, description, acceptableValues);
		}

		internal static ConfigDescription TrashingCategoryHideNotificationDisplay(string description, AcceptableValueBase acceptableValues = null)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			if (CompatibilitySupport.DisallowAllTrashCanFeatures())
			{
				return new ConfigDescription("Force disabled due to using other mod that adds trashing/ recycling", acceptableValues, new object[1]
				{
					new ConfigurationManagerAttributes
					{
						DispName = "Trashing",
						ReadOnly = true,
						CustomDrawer = delegate
						{
							CustomLabelDrawer("Force disabled for compatibility reasons");
						}
					}
				});
			}
			return new ConfigDescription(description, acceptableValues, Array.Empty<object>());
		}

		internal static ConfigDescription ForceEnabledDisplay(Func<bool> condition, string description, AcceptableValueBase acceptableValues = null)
		{
			return SeeOnlyDisplay(condition, description, "Force enabled for better compatibility with one of your installed mods. " + description, "Force enabled for compatibility reasons", acceptableValues);
		}

		internal static ConfigDescription ForceDisabledDisplay(Func<bool> condition, string description, AcceptableValueBase acceptableValues = null)
		{
			return SeeOnlyDisplay(condition, description, "Force disabled for better compatibility with one of your installed mods. " + description, "Force disabled for compatibility reasons", acceptableValues);
		}

		internal static ConfigDescription SeeOnlyDisplay(Func<bool> condition, string description, string overwriteDescription, string overwriteLabel, AcceptableValueBase acceptableValues = null)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			if (condition())
			{
				return new ConfigDescription(overwriteDescription, acceptableValues, new object[1]
				{
					new ConfigurationManagerAttributes
					{
						ReadOnly = true,
						CustomDrawer = delegate
						{
							CustomLabelDrawer(overwriteLabel);
						}
					}
				});
			}
			return new ConfigDescription(description, acceptableValues, Array.Empty<object>());
		}

		private static void CustomLabelDrawer(string labelText)
		{
			GUILayout.Label(labelText, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
		}
	}
	internal class LocalizationLoader
	{
		private const string keyPrefix = "quickstackstore_";

		public static string[] supportedEmbeddedLanguages = new string[9] { "English", "Chinese", "Russian", "French", "Portuguese_Brazilian", "Polish", "Swedish", "Korean", "Italian" };

		private const string embeddedLanguagePathFormat = "QuickStackStore.Translations.QuickStackStore.{0}.json";

		private const string loadingLog = "Loading {0} translation file for language: {1}";

		private const string failedLoadLog = "Failed loading {0} translation file for language: {1}";

		private const string external = "external";

		private const string embedded = "embedded";

		internal static void SetupTranslations()
		{
			string selectedLanguage = Localization.instance.GetSelectedLanguage();
			LocalizationConfig.FixTakeAllDefaultText(Localization.instance, selectedLanguage);
			string[] files = Directory.GetFiles(Path.GetDirectoryName(Paths.PluginPath), "QuickStackStore.*.json", SearchOption.AllDirectories);
			bool flag = false;
			string[] array = files;
			foreach (string path in array)
			{
				string text = Path.GetFileNameWithoutExtension(path).Split(new char[1] { '.' })[1];
				if (text == selectedLanguage)
				{
					Helper.Log(string.Format("Loading {0} translation file for language: {1}", "external", selectedLanguage), QSSConfig.DebugSeverity.Everything);
					if (!LoadExternalLanguageFile(selectedLanguage, path))
					{
						Helper.LogO(string.Format("Failed loading {0} translation file for language: {1}", "external", selectedLanguage));
					}
					else
					{
						flag = true;
					}
					break;
				}
			}
			if (!flag && selectedLanguage != "English" && supportedEmbeddedLanguages.Contains(selectedLanguage))
			{
				Helper.Log(string.Format("Loading {0} translation file for language: {1}", "embedded", selectedLanguage), QSSConfig.DebugSeverity.Everything);
				if (!LoadEmbeddedLanguageFile(selectedLanguage))
				{
					Helper.LogO(string.Format("Failed loading {0} translation file for language: {1}", "embedded", selectedLanguage));
				}
			}
			Helper.Log(string.Format("Loading {0} translation file for language: {1}", "embedded", "English"), QSSConfig.DebugSeverity.Everything);
			if (!LoadEmbeddedLanguageFile("English"))
			{
				Helper.LogO(string.Format("Failed loading {0} translation file for language: {1}", "embedded", "English"));
			}
		}

		internal static bool LoadExternalLanguageFile(string language, string path)
		{
			string text = File.ReadAllText(path);
			if (text == null)
			{
				return false;
			}
			return ParseStringToLanguage(language, text);
		}

		internal static bool LoadEmbeddedLanguageFile(string language)
		{
			string text = ReadEmbeddedTextFile($"QuickStackStore.Translations.QuickStackStore.{language}.json");
			if (text == null)
			{
				return false;
			}
			return ParseStringToLanguage(language, text);
		}

		internal static bool ParseStringToLanguage(string language, string translationAsString)
		{
			Dictionary<string, string> dictionary = new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(translationAsString);
			if (dictionary == null || dictionary.Count == 0)
			{
				return false;
			}
			foreach (KeyValuePair<string, string> item in dictionary)
			{
				AddForLanguage(language, item.Key, item.Value);
			}
			return true;
		}

		internal static void AddForLanguage(string language, string key, string value)
		{
			string text = "quickstackstore_" + key.ToLower();
			bool flag = Localization.instance.GetSelectedLanguage() == language;
			bool flag2 = language == "English" && !Localization.instance.m_translations.ContainsKey(text);
			if (flag || flag2)
			{
				Localization.instance.AddWord(text, value);
			}
		}

		public static string ReadEmbeddedTextFile(string path)
		{
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			Stream manifestResourceStream = executingAssembly.GetManifestResourceStream(path);
			if (manifestResourceStream == null)
			{
				return null;
			}
			using MemoryStream memoryStream = new MemoryStream();
			manifestResourceStream.CopyTo(memoryStream);
			byte[] array = ((memoryStream.Length > 0) ? memoryStream.ToArray() : null);
			return (array != null) ? Encoding.UTF8.GetString(array) : null;
		}
	}
	internal static class ServerSyncWrapper
	{
		internal static ConfigEntry<T> BindSyncLocker<T>(this ConfigFile configFile, ConfigSync serverSyncInstance, string group, string name, T value, ConfigDescription description) where T : IConvertible
		{
			ConfigEntry<T> val = configFile.Bind<T>(group, name, value, description);
			serverSyncInstance.AddLockingConfigEntry<T>(val);
			return val;
		}

		internal static ConfigEntry<T> BindSyncLocker<T>(this ConfigFile configFile, ConfigSync serverSyncInstance, string group, string name, T value, string description) where T : IConvertible
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			return configFile.BindSyncLocker(serverSyncInstance, group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()));
		}

		internal static ConfigEntry<T> BindSynced<T>(this ConfigFile configFile, ConfigSync serverSyncInstance, string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true)
		{
			ConfigEntry<T> val = configFile.Bind<T>(group, name, value, description);
			SyncedConfigEntry<T> syncedConfigEntry = serverSyncInstance.AddConfigEntry<T>(val);
			syncedConfigEntry.SynchronizedConfig = synchronizedSetting;
			return val;
		}

		internal static ConfigEntry<T> BindSynced<T>(this ConfigFile configFile, ConfigSync serverSyncInstance, string group, string name, T value, string description, bool synchronizedSetting = true)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			return configFile.BindSynced(serverSyncInstance, group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting);
		}
	}
	internal class FavoritingMode
	{
		private static bool hasCurrentlyToggledFavoriting;

		private const string blackStar = "★";

		private const string whiteStar = "☆";

		internal static bool HasCurrentlyToggledFavoriting
		{
			get
			{
				return hasCurrentlyToggledFavoriting;
			}
			set
			{
				//IL_0035: Unknown result type (might be due to invalid IL or missing references)
				hasCurrentlyToggledFavoriting = value;
				if (Object.op_Implicit((Object)(object)ButtonRenderer.favoritingTogglingButtonText))
				{
					if (QSSConfig.FavoriteConfig.FavoriteToggleButtonStyle.Value == QSSConfig.FavoriteToggleButtonStyle.TextStarInItemFavoriteColor)
					{
						string text = ColorUtility.ToHtmlStringRGB(QSSConfig.FavoriteConfig.BorderColorFavoritedItem.Value);
						((TMP_Text)ButtonRenderer.favoritingTogglingButtonText).text = "<color=#" + text + ">" + (value ? "★" : "☆") + "</color>";
					}
					else
					{
						((TMP_Text)ButtonRenderer.favoritingTogglingButtonText).text = (value ? "★" : "☆");
					}
				}
			}
		}

		internal static void RefreshDisplay()
		{
			HasCurrentlyToggledFavoriting = HasCurrentlyToggledFavoriting;
		}

		internal static void ToggleFavoriteToggling()
		{
			HasCurrentlyToggledFavoriting = !HasCurrentlyToggledFavoriting;
		}

		internal static bool IsInFavoritingMode()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			return HasCurrentlyToggledFavoriting || QSSConfig.FavoriteConfig.FavoritingModifierKeybind1.Value.IsKeyHeld() || QSSConfig.FavoriteConfig.FavoritingModifierKeybind2.Value.IsKeyHeld();
		}
	}
	[HarmonyPatch]
	public static class KeybindChecker
	{
		[HarmonyPatch(typeof(Player))]
		public static class Player_Update_Patch
		{
			[HarmonyPatch("Update")]
			[HarmonyPostfix]
			public static void Postfix_Patch(Player __instance)
			{
				if (!((Object)(object)Player.m_localPlayer != (Object)(object)__instance) && !IgnoreKeyPresses())
				{
					if (ZInput.IsGamepadActive() && QSSConfig.ControllerConfig.UseHardcodedControllerSupport.Value)
					{
						HandleControllerKeys(__instance);
					}
					else
					{
						HandleGenericKeys(__instance);
					}
				}
			}

			private static void HandleGenericKeys(Player player)
			{
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_003f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0072: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
				//IL_0100: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
				if (QSSConfig.GeneralConfig.OverrideKeybindBehavior.Value == QSSConfig.OverrideKeybindBehavior.DisableAllNewHotkeys)
				{
					return;
				}
				if (QSSConfig.QuickStackConfig.QuickStackKeybind.Value.IsKeyDown())
				{
					QuickStackModule.DoQuickStack(player);
				}
				else if (QSSConfig.RestockConfig.RestockKeybind.Value.IsKeyDown())
				{
					RestockModule.DoRestock(player);
				}
				else
				{
					if (!InventoryGui.IsVisible())
					{
						return;
					}
					if (QSSConfig.SortConfig.SortKeybind.Value.IsKeyDown())
					{
						SortModule.DoSort(player);
						return;
					}
					if (!CompatibilitySupport.DisallowAllTrashCanFeatures())
					{
						if (QSSConfig.TrashConfig.QuickTrashKeybind.Value.IsKeyDown())
						{
							TrashModule.AttemptQuickTrash();
							return;
						}
						if (QSSConfig.TrashConfig.TrashKeybind.Value.IsKeyDown())
						{
							TrashModule.TrashOrTrashFlagItem(usedFromHotkey: true);
							return;
						}
					}
					if (QSSConfig.StoreTakeAllConfig.TakeAllKeybind.Value.IsKeyDown())
					{
						StoreTakeAllModule.DoTakeAllWithKeybind(player);
					}
					else if (QSSConfig.StoreTakeAllConfig.StoreAllKeybind.Value.IsKeyDown())
					{
						StoreTakeAllModule.DoStoreAllWithKeybind(player);
					}
				}
			}

			private static void HandleControllerKeys(Player player)
			{
				//IL_0072: Unknown result type (might be due to invalid IL or missing references)
				if (!InventoryGui.IsVisible())
				{
					return;
				}
				if (ZInput.GetButtonDown("JoyBack"))
				{
					SortModule.DoSort(player);
				}
				else if (ZInput.GetButtonDown("JoyRStick"))
				{
					StoreTakeAllModule.DoStoreAllWithKeybind(player);
				}
				else if (QSSConfig.ControllerConfig.ControllerDPadUsageInInventoryGrid.Value != 0 && (QSSConfig.ControllerConfig.ControllerDPadUsageInInventoryGrid.Value != QSSConfig.DPadUsage.KeybindsWhileHoldingModifierKey || QSSConfig.ControllerConfig.ControllerDPadUsageModifierKeybind.Value.IsKeyHeld()))
				{
					if (ZInput.GetButtonDown("JoyDPadDown"))
					{
						QuickStackModule.DoQuickStack(player);
					}
					else if (ZInput.GetButtonDown("JoyDPadUp"))
					{
						RestockModule.DoRestock(player);
					}
					else if (ZInput.GetButtonDown("JoyDPadLeft"))
					{
						FavoritingMode.ToggleFavoriteToggling();
					}
					else if (!CompatibilitySupport.DisallowAllTrashCanFeatures() && ZInput.GetButtonDown("JoyDPadRight"))
					{
						TrashModule.TrashOrTrashFlagItem();
					}
				}
			}
		}

		internal const string joyTranslationPrefix = "KEY_";

		internal const string joyGetButtonDownPrefix = "Joy";

		internal const string joySort = "Back";

		internal const string joyStoreAll = "RStick";

		internal const string joyQuickStack = "DPadDown";

		internal const string joyRestock = "DPadUp";

		internal const string joyFavoriteToggling = "DPadLeft";

		internal const string joyTrash = "DPadRight";

		public static bool IgnoreKeyPresses()
		{
			return IgnoreKeyPressesDueToPlayer(Player.m_localPlayer) || !Object.op_Implicit((Object)(object)ZNetScene.instance) || Minimap.IsOpen() || Menu.IsVisible() || Console.IsVisible() || StoreGui.IsVisible() || TextInput.IsVisible() || (Object.op_Implicit((Object)(object)Chat.instance) && Chat.instance.HasFocus()) || (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.InPasswordDialog()) || (Object.op_Implicit((Object)(object)TextViewer.instance) && TextViewer.instance.IsVisible());
		}

		private static bool IgnoreKeyPressesDueToPlayer(Player player)
		{
			return !Object.op_Implicit((Object)(object)player) || ((Character)player).InCutscene() || ((Character)player).IsTeleporting() || ((Character)player).IsDead() || ((Character)player).InPlaceMode();
		}

		public static bool IsKeyDown(this KeyboardShortcut shortcut)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			return (int)((KeyboardShortcut)(ref shortcut)).MainKey != 0 && Input.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey) && ((KeyboardShortcut)(ref shortcut)).Modifiers.All((Func<KeyCode, bool>)Input.GetKey);
		}

		public static bool IsKeyHeld(this KeyboardShortcut shortcut)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			return (int)((KeyboardShortcut)(ref shortcut)).MainKey != 0 && Input.GetKey(((KeyboardShortcut)(ref shortcut)).MainKey) && ((KeyboardShortcut)(ref shortcut)).Modifiers.All((Func<KeyCode, bool>)Input.GetKey);
		}
	}
	[HarmonyPatch(typeof(Localization))]
	internal class LocalizationPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("SetupLanguage")]
		private static void SetupLanguagePatch(Localization __instance, string language)
		{
			LocalizationConfig.FixTakeAllDefaultText(__instance, language);
		}
	}
	internal class LocalizationConfig
	{
		public static ConfigEntry<string> RestockLabelCharacter;

		public static ConfigEntry<string> QuickStackLabelCharacter;

		public static ConfigEntry<string> SortLabelCharacter;

		public static ConfigEntry<string> QuickStackResultMessageNothing;

		public static ConfigEntry<string> QuickStackResultMessageNone;

		public static ConfigEntry<string> QuickStackResultMessageOne;

		public static ConfigEntry<string> QuickStackResultMessageMore;

		public static ConfigEntry<string> RestockResultMessageNothing;

		public static ConfigEntry<string> RestockResultMessageNone;

		public static ConfigEntry<string> RestockResultMessagePartial;

		public static ConfigEntry<string> RestockResultMessageFull;

		public static ConfigEntry<string> QuickStackLabel;

		public static ConfigEntry<string> StoreAllLabel;

		public static ConfigEntry<string> SortLabel;

		public static ConfigEntry<string> RestockLabel;

		public static ConfigEntry<string> TrashLabel;

		public static ConfigEntry<string> TakeAllLabel;

		public static ConfigEntry<string> SortByInternalNameLabel;

		public static ConfigEntry<string> SortByTranslatedNameLabel;

		public static ConfigEntry<string> SortByValueLabel;

		public static ConfigEntry<string> SortByWeightLabel;

		public static ConfigEntry<string> SortByTypeLabel;

		public static ConfigEntry<string> TrashConfirmationOkayButton;

		public static ConfigEntry<string> QuickTrashConfirmation;

		public static ConfigEntry<string> CantTrashFavoritedItemWarning;

		public static ConfigEntry<string> CantTrashFlagFavoritedItemWarning;

		public static ConfigEntry<string> CantTrashHotkeyBarItemWarning;

		public static ConfigEntry<string> CantFavoriteTrashFlaggedItemWarning;

		public static ConfigEntry<string> FavoritedItemTooltip;

		public static ConfigEntry<string> TrashFlaggedItemTooltip;

		public const string takeAllKey = "inventory_takeall";

		internal static string GetRelevantTranslation(ConfigEntry<string> config, string configName)
		{
			return (!Utility.IsNullOrWhiteSpace(config?.Value)) ? config.Value : Localization.instance.Translate("quickstackstore_" + configName.ToLower());
		}

		internal static void FixTakeAllDefaultText(Localization localization, string language)
		{
			if (localization.m_translations.ContainsKey("inventory_takeall"))
			{
				switch (language)
				{
				case "English":
					localization.m_translations["inventory_takeall"] = "Take All";
					break;
				case "Russian":
					localization.m_translations["inventory_takeall"] = "взять всё";
					break;
				case "French":
					localization.m_translations["inventory_takeall"] = "Tout Prendre";
					break;
				case "Portuguese_Brazilian":
					localization.m_translations["inventory_takeall"] = "Pegar Tudo";
					break;
				}
			}
		}
	}
	internal class AreaStackRestockHelper
	{
		internal static bool IsTrueSingleplayer()
		{
			return !ZNet.m_openServer && !ZNet.m_publicServer && Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer() && !ZNet.instance.IsDedicated() && ZNet.instance.GetConnectedPeers().Count == 0;
		}

		private static bool CheckWard(Container container)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			return !container.m_checkGuardStone || PrivateArea.CheckAccess(((Component)container).transform.position, 0f, true, false);
		}

		private static bool CheckContainerPrivacy(Container container, long playerID)
		{
			return container.CheckAccess(playerID);
		}

		private static bool CheckPieceConfigs(Container container)
		{
			if (Object.op_Implicit((Object)(object)container.m_piece))
			{
				return container.m_piece.IsPlacedByPlayer() || QSSConfig.QuickStackRestockConfig.AllowAreaStackingToPhysicalNonPlayerBuiltContainers.Value;
			}
			return container.m_name == "piece_chest_drawer" || QSSConfig.QuickStackRestockConfig.AllowAreaStackingToNonPhysicalContainers.Value;
		}

		private static bool IsInUseClientSide(Container container)
		{
			return container.IsInUse() || (Object.op_Implicit((Object)(object)container.m_wagon) && container.m_wagon.InUse());
		}

		private static bool IsInUseServerSide(Container container)
		{
			return container.m_nview.GetZDO().GetInt("InUse", 0) == 1;
		}

		private static bool IsInUse(Container container)
		{
			return IsInUseServerSide(container) || IsInUseClientSide(container);
		}

		private static bool IsExcludedContainer(Container container)
		{
			Player component = ((Component)container.m_nview).GetComponent<Player>();
			return Object.op_Implicit((Object)(object)component) && (Object)(object)component != (Object)(object)Player.m_localPlayer;
		}

		private static bool IsNonMUCExcludedContainer(Container container)
		{
			bool flag = false;
			return flag | Object.op_Implicit((Object)(object)((Component)((Component)container).transform.root).GetComponentInChildren<Ship>());
		}

		internal static bool ShouldAffectNonOwnerContainer(Container container, long playerID, bool isSinglePlayer)
		{
			bool flag = !IsExcludedContainer(container) && CheckContainerPrivacy(container, playerID) && CheckWard(container) && CheckPieceConfigs(container);
			if (CompatibilitySupport.HasPlugin("com.maxsch.valheim.MultiUserChest"))
			{
				return flag;
			}
			if (!isSinglePlayer && IsNonMUCExcludedContainer(container))
			{
				return false;
			}
			return flag && !IsInUse(container);
		}

		internal static void SetNonMUCContainerInUse(Container container, bool isInUse)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			container.m_inUse = isInUse;
			if (QSSConfig.QuickStackRestockConfig.SuppressContainerSoundAndVisuals.Value)
			{
				container.m_nview.GetZDO().Set("InUse", isInUse ? 1 : 0);
			}
			else
			{
				container.SetInUse(isInUse);
			}
			ZDOMan.instance.ForceSendZDO(ZNet.GetUID(), container.m_nview.GetZDO().m_uid);
		}
	}
	public static class CompatibilitySupport
	{
		public enum RandyStatus
		{
			Disabled,
			EnabledWithoutQuickSlots,
			EnabledWithQuickSlots
		}

		private static MethodInfo IsComfyArmorSlot;

		private static FieldInfo IsQuiverEnabled;

		private static FieldInfo QuiverRowIndex;

		private static FieldInfo AedenAddEquipmentRow;

		private static FieldInfo OdinExAddEquipmentRow;

		private static FieldInfo OdinQOLAddEquipmentRow;

		private static FieldInfo AzuEPIAddEquipmentRow;

		private static FieldInfo RandyQuickSlotsEnabled;

		public const string aeden = "aedenthorn.ExtendedPlayerInventory";

		public const string comfy = "com.bruce.valheim.comfyquickslots";

		public const string odinPlus = "com.odinplusqol.mod";

		public const string odinExInv = "odinplusqol.OdinsExtendedInventory";

		public const string randy = "randyknapp.mods.equipmentandquickslots";

		public const string azuEPI = "Azumatt.AzuExtendedPlayerInventory";

		public const string auga = "randyknapp.mods.auga";

		public static bool isUsingAzuEPIWithAPI = false;

		public static bool isUsingAzuEPIWithQuickslotCompatibleAPI = false;

		public const string betterArchery = "ishid4.mods.betterarchery";

		public const string smartContainers = "flueno.SmartContainers";

		public const string backpacks = "org.bepinex.plugins.backpacks";

		public const string multiUserChest = "com.maxsch.valheim.MultiUserChest";

		public const string jewelCrafting = "org.bepinex.plugins.jewelcrafting";

		public const string recyclePlus = "TastyChickenLegs.RecyclePlus";

		public static System.Version mucUpdateVersion = new System.Version(0, 4, 0);

		public static System.Version azuEPIOnOffUpdate = new System.Version(1, 2, 0);

		public static System.Version azuEPIQuickSlotAPIUpdate = new System.Version(1, 3, 2);

		public static bool HasAedenLikeEquipOrQuickSlotPlugin()
		{
			return HasPlugin("aedenthorn.ExtendedPlayerInventory") || HasPlugin("odinplusqol.OdinsExtendedInventory") || HasPlugin("com.odinplusqol.mod") || (HasPlugin("Azumatt.AzuExtendedPlayerInventory") && !isUsingAzuEPIWithAPI);
		}

		public static bool AllowAreaStackingRestocking()
		{
			return AreaStackRestockHelper.IsTrueSingleplayer() || HasPlugin("com.maxsch.valheim.MultiUserChest") || QSSConfig.QuickStackRestockConfig.AllowAreaStackingInMultiplayerWithoutMUC.Value;
		}

		public static bool DisallowAllTrashCanFeatures()
		{
			return HasPlugin("TastyChickenLegs.RecyclePlus");
		}

		public static bool ShouldBlockChangesToTakeAllButton()
		{
			return QSSConfig.StoreTakeAllConfig.NeverMoveTakeAllButton.Value || ShouldBlockChangesToTakeAllButtonDueToPlugin();
		}

		public static bool ShouldBlockChangesToTakeAllButtonDueToPlugin()
		{
			return HasPlugin("flueno.SmartContainers") || HasPlugin("org.bepinex.plugins.backpacks") || HasPlugin("org.bepinex.plugins.jewelcrafting");
		}

		public static bool HasOutdatedMUCPlugin()
		{
			if (Chainloader.PluginInfos.ContainsKey("com.maxsch.valheim.MultiUserChest"))
			{
				PluginInfo val = Chainloader.PluginInfos["com.maxsch.valheim.MultiUserChest"];
				return val.Metadata.Version < mucUpdateVersion;
			}
			return false;
		}

		public static bool HasAzuEPIWithQuickslotCompatibleAPI()
		{
			if (Chainloader.PluginInfos.ContainsKey("Azumatt.AzuExtendedPlayerInventory"))
			{
				PluginInfo val = Chainloader.PluginInfos["Azumatt.AzuExtendedPlayerInventory"];
				return val.Metadata.Version >= azuEPIQuickSlotAPIUpdate;
			}
			return false;
		}

		public static bool HasPlugin(string guid)
		{
			return Chainloader.PluginInfos.ContainsKey(guid);
		}

		public static RandyStatus HasRandyPlugin()
		{
			if (!HasPlugin("randyknapp.mods.equipmentandquickslots"))
			{
				return RandyStatus.Disabled;
			}
			RandyStatus result = RandyStatus.EnabledWithQuickSlots;
			if (RandyQuickSlotsEnabled == null)
			{
				Assembly assembly = Assembly.Load("EquipmentAndQuickSlots");
				if (assembly != null)
				{
					Type type = assembly.GetTypes().First((Type a) => a.IsClass && a.Name == "EquipmentAndQuickSlots");
					FieldInfo[] fields = type.GetFields(BindingFlags.Static | BindingFlags.Public);
					RandyQuickSlotsEnabled = fields.First((FieldInfo t) => t.Name == "QuickSlotsEnabled");
				}
			}
			if (RandyQuickSlotsEnabled?.GetValue(null) is ConfigEntry<bool> val && !val.Value)
			{
				result = RandyStatus.EnabledWithoutQuickSlots;
			}
			return result;
		}

		public static bool HasPluginThatRequiresMiniButtonVMove()
		{
			return HasAedenLikeEquipOrQuickSlotPlugin() || (HasPlugin("Azumatt.AzuExtendedPlayerInventory") && isUsingAzuEPIWithAPI);
		}

		public static bool IsEquipSlot(int inventoryHeight, int inventoryWidth, Vector2i itemPos)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			return InternalIsEquipOrQuickSlot(inventoryHeight, inventoryWidth, itemPos, includeRestockableSlots: false);
		}

		public static bool IsEquipOrQuickSlot(int inventoryHeight, int inventoryWidth, Vector2i itemPos)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			return InternalIsEquipOrQuickSlot(inventoryHeight, inventoryWidth, itemPos, includeRestockableSlots: true);
		}

		private static bool InternalIsEquipOrQuickSlot(int inventoryHeight, int inventoryWidth, Vector2i itemPos, bool includeRestockableSlots)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			if (HasPlugin("aedenthorn.ExtendedPlayerInventory") && IsAedenLikeEquipOrQuickSlot(ref AedenAddEquipmentRow, "ExtendedPlayerInventory", "BepInExPlugin", "addEquipmentRow", inventoryHeight, itemPos, includeRestockableSlots))
			{
				return true;
			}
			if (HasPlugin("odinplusqol.OdinsExtendedInventory") && IsAedenLikeEquipOrQuickSlot(ref OdinExAddEquipmentRow, "OdinsExtendedInventory", "OdinsExtendedInventoryPlugin", "addEquipmentRow", inventoryHeight, itemPos, includeRestockableSlots))
			{
				return true;
			}
			if (HasPlugin("com.odinplusqol.mod") && IsAedenLikeEquipOrQuickSlot(ref OdinQOLAddEquipmentRow, "OdinQOL", "QuickAccessBar", "AddEquipmentRow", inventoryHeight, itemPos, includeRestockableSlots))
			{
				return true;
			}
			if (HasPlugin("Azumatt.AzuExtendedPlayerInventory") && !isUsingAzuEPIWithAPI && IsAedenLikeEquipOrQuickSlot(ref AzuEPIAddEquipmentRow, "AzuExtendedPlayerInventory", "AzuExtendedPlayerInventoryPlugin", "AddEquipmentRow", inventoryHeight, itemPos, includeRestockableSlots))
			{
				return true;
			}
			if (HasPlugin("Azumatt.AzuExtendedPlayerInventory") && isUsingAzuEPIWithAPI && IsNewAzuEPIEquipOrQuickSlot(inventoryHeight, inventoryWidth, itemPos, includeRestockableSlots))
			{
				return true;
			}
			if (HasPlugin("com.bruce.valheim.comfyquickslots") && IsComfyEquipOrQuickSlot(inventoryHeight, itemPos, includeRestockableSlots))
			{
				return true;
			}
			if (HasPlugin("ishid4.mods.betterarchery") && IsBetterArcheryQuiverSlot(itemPos, includeRestockableSlots))
			{
				return true;
			}
			return false;
		}

		private static bool HasAedenLikeEquipmentRow(ref FieldInfo fieldInfo, string assemblyName, string className, string fieldName)
		{
			if (fieldInfo == null)
			{
				Assembly assembly = Assembly.Load(assemblyName);
				if (assembly != null)
				{
					Type type = assembly.GetTypes().First((Type a) => a.IsClass && a.Name == className);
					FieldInfo[] fields = type.GetFields(BindingFlags.Static | BindingFlags.Public);
					fieldInfo = fields.First((FieldInfo t) => t.Name == fieldName);
				}
			}
			if (fieldInfo == AzuEPIAddEquipmentRow && Chainloader.PluginInfos["Azumatt.AzuExtendedPlayerInventory"].Metadata.Version >= azuEPIOnOffUpdate)
			{
				object? obj = fieldInfo?.GetValue(null);
				ConfigEntryBase val = (ConfigEntryBase)((obj is ConfigEntryBase) ? obj : null);
				return val != null && (int)val.BoxedValue != 0;
			}
			return fieldInfo?.GetValue(null) is ConfigEntry<bool> val2 && val2.Value;
		}

		private static bool IsNewAzuEPIEquipOrQuickSlot(int inventoryHeight, int inventoryWidth, Vector2i itemPos, bool includeRestockableSlots)
		{
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			if (!HasAedenLikeEquipmentRow(ref AzuEPIAddEquipmentRow, "AzuExtendedPlayerInventory", "AzuExtendedPlayerInventoryPlugin", "AddEquipmentRow"))
			{
				return false;
			}
			if (!includeRestockableSlots && isUsingAzuEPIWithQuickslotCompatibleAPI)
			{
				foreach (ItemData quickSlotsItem in API.GetQuickSlotsItems())
				{
					if (quickSlotsItem.m_gridPos == itemPos)
					{
						return false;
					}
				}
			}
			int addedRows = API.GetAddedRows(inventoryWidth);
			for (int i = 1; i <= addedRows; i++)
			{
				if (itemPos.y == inventoryHeight - i)
				{
					return true;
				}
			}
			return false;
		}

		private static bool IsAedenLikeEquipOrQuickSlot(ref FieldInfo fieldInfo, string assemblyName, string className, string fieldName, int inventoryHeight, Vector2i itemPos, bool checkForRestockableSlots)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			if (!HasAedenLikeEquipmentRow(ref fieldInfo, assemblyName, className, fieldName))
			{
				return false;
			}
			return itemPos.y == inventoryHeight - 1 && (checkForRestockableSlots || itemPos.x < 5 || itemPos.x > 7);
		}

		private static bool IsComfyEquipOrQuickSlot(int inventoryHeight, Vector2i itemPos, bool includeRestockableSlots)
		{
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			if (IsComfyArmorSlot == null)
			{
				Assembly assembly = Assembly.Load("ComfyQuickSlots");
				if (assembly != null)
				{
					Type type = assembly.GetTypes().First((Type a) => a.IsClass && a.Name == "ComfyQuickSlots");
					MethodInfo[] methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public);
					IsComfyArmorSlot = methods.First((MethodInfo t) => t.Name == "IsArmorSlot" && t.GetParameters().Length == 1);
				}
			}
			object obj = IsComfyArmorSlot?.Invoke(null, new object[1] { itemPos });
			bool flag = default(bool);
			int num;
			if (obj is bool)
			{
				flag = (bool)obj;
				num = 1;
			}
			else
			{
				num = 0;
			}
			if (((uint)num & (flag ? 1u : 0u)) != 0)
			{
				return true;
			}
			if (includeRestockableSlots)
			{
				obj = IsComfyArmorSlot?.Invoke(null, new object[1] { (object)new Vector2i(itemPos.x - 3, itemPos.y) });
				bool flag2 = default(bool);
				int num2;
				if (obj is bool)
				{
					flag2 = (bool)obj;
					num2 = 1;
				}
				else
				{
					num2 = 0;
				}
				if (((uint)num2 & (flag2 ? 1u : 0u)) != 0)
				{
					return true;
				}
			}
			return false;
		}

		private static bool IsBetterArcheryQuiverSlot(Vector2i itemPos, bool includeRestockableSlots)
		{
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			if (IsQuiverEnabled == null || QuiverRowIndex == null)
			{
				Assembly assembly = Assembly.Load("BetterArchery");
				if (assembly != null)
				{
					Type type = assembly.GetTypes().First((Type a) => a.IsClass && a.Name == "BetterArchery");
					FieldInfo[] fields = type.GetFields(BindingFlags.Static | BindingFlags.Public);
					IsQuiverEnabled = fields.First((FieldInfo t) => t.Name == "configQuiverEnabled");
					QuiverRowIndex = fields.First((FieldInfo t) => t.Name == "QuiverRowIndex");
				}
			}
			if (!(IsQuiverEnabled?.GetValue(null) is ConfigEntry<bool> val) || !val.Value)
			{
				return false;
			}
			if (QuiverRowIndex?.GetValue(null) is int num)
			{
				if (num == 0)
				{
					return false;
				}
				if (itemPos.y == num && (includeRestockableSlots || itemPos.x < 0 || itemPos.x > 2))
				{
					return true;
				}
				if (itemPos.y == num - 1)
				{
					return true;
				}
			}
			return false;
		}
	}
	internal class ContainerFinder
	{
		public static List<Container> AllContainers = new List<Container>();

		public static List<Container> FindContainersInRange(Vector3 point, float range)
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			List<Container> list = new List<Container>();
			Stopwatch stopwatch = new Stopwatch();
			stopwatch.Start();
			foreach (Container allContainer in AllContainers)
			{
				if (Object.op_Implicit((Object)(object)allContainer) && Object.op_Implicit((Object)(object)((Component)allContainer).transform) && Object.op_Implicit((Object)(object)allContainer.m_nview) && allContainer.m_nview.HasOwner() && Vector3.Distance(point, ((Component)allContainer).transform.position) < range)
				{
					list.Add(allContainer);
				}
			}
			stopwatch.Stop();
			Helper.Log($"Found {list.Count} container/s out of {AllContainers.Count} in range in {stopwatch.Elapsed}", QSSConfig.DebugSeverity.AlsoSpeedTests);
			return list;
		}
	}
	[HarmonyPatch(typeof(Container))]
	internal static class PatchContainer
	{
		[HarmonyPostfix]
		[HarmonyPatch("Awake")]
		internal static void Awake(Container __instance)
		{
			ContainerFinder.AllContainers.Add(__instance);
		}

		[HarmonyPatch("OnDestroyed")]
		[HarmonyPostfix]
		internal static void OnDestroyed(Container __instance)
		{
			ContainerFinder.AllContainers.Remove(__instance);
		}
	}
	public static class Helper
	{
		internal static void Log(object s, QSSConfig.DebugSeverity debugSeverity = QSSConfig.DebugSeverity.Normal)
		{
			if (debugSeverity > (QSSConfig.DebugConfig.DebugSeverity?.Value ?? QSSConfig.DebugSeverity.Normal))
			{
				return;
			}
			string text = "Quick Stack - Store - Sort - Trash - Restock 1.4.7: " + ((s != null) ? s.ToString() : "null");
			ConfigEntry<QSSConfig.DebugLevel> showDebugLogs = QSSConfig.DebugConfig.ShowDebugLogs;
			if (showDebugLogs != null && showDebugLogs.Value == QSSConfig.DebugLevel.Log)
			{
				Debug.Log((object)text);
				return;
			}
			ConfigEntry<QSSConfig.DebugLevel> showDebugLogs2 = QSSConfig.DebugConfig.ShowDebugLogs;
			if (showDebugLogs2 != null && showDebugLogs2.Value == QSSConfig.DebugLevel.Warning)
			{
				Debug.LogWarning((object)text);
			}
		}

		internal static void LogO(object s, QSSConfig.DebugLevel OverrideLevel = QSSConfig.DebugLevel.Warning)
		{
			string text = "Quick Stack - Store - Sort - Trash - Restock 1.4.7: " + ((s != null) ? s.ToString() : "null");
			switch (OverrideLevel)
			{
			case QSSConfig.DebugLevel.Log:
				Debug.Log((object)text);
				break;
			case QSSConfig.DebugLevel.Warning:
				Debug.LogWarning((object)text);
				break;
			}
		}

		internal static int CompareSlotOrder(Vector2i a, Vector2i b)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			int num = -a.y.CompareTo(b.y);
			if (QSSConfig.GeneralConfig.UseTopDownLogicForEverything.Value)
			{
				num *= -1;
			}
			return (num != 0) ? num : a.x.CompareTo(b.x);
		}

		public static Sprite LoadSprite(string path, Rect size, Vector2? pivot = null, int units = 100)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			if (!pivot.HasValue)
			{
				pivot = new Vector2(0.5f, 0.5f);
			}
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			Stream manifestResourceStream = executingAssembly.GetManifestResourceStream(path);
			Texture2D val = new Texture2D((int)((Rect)(ref size)).width, (int)((Rect)(ref size)).height, (TextureFormat)4, false, true);
			using MemoryStream memoryStream = new MemoryStream();
			manifestResourceStream.CopyTo(memoryStream);
			ImageConversion.LoadImage(val, memoryStream.ToArray());
			val.Apply();
			return Sprite.Create(val, size, pivot.Value, (float)units);
		}
	}
	internal class QuickStackModule
	{
		private static bool ShouldQuickStackItem(ItemData item, UserConfig playerConfig, int inventoryHeight, int inventoryWidth, bool includeHotbar)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			return item.m_shared.m_maxStackSize > 1 && (item.m_gridPos.y > 0 || includeHotbar) && !playerConfig.IsItemNameOrSlotFavorited(item) && !CompatibilitySupport.IsEquipOrQuickSlot(inventoryHeight, inventoryWidth, item.m_gridPos);
		}

		private static bool ShouldAreaQuickStack(Container currentContainer)
		{
			return QSSConfig.QuickStackConfig.QuickStackToNearbyRange.Value > 0f && ((Object)(object)currentContainer == (Object)null || QSSConfig.QuickStackConfig.QuickStackHotkeyBehaviorWhenContainerOpen.Value != 0) && CompatibilitySupport.AllowAreaStackingRestocking();
		}

		internal static void DoQuickStack(Player player, bool onlyQuickStackToCurrentContainer = false, Container currentContainerOverride = null)
		{
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Invalid comparison between Unknown and I4
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			if (((Character)player).IsTeleporting() || !Object.op_Implicit((Object)(object)InventoryGui.instance.m_container))
			{
				return;
			}
			InventoryGui.instance.SetupDragItem((ItemData)null, (Inventory)null, 0);
			UserConfig playerConfig = UserConfig.GetPlayerConfig(player.GetPlayerID());
			bool includeHotbar = QSSConfig.GeneralConfig.OverrideHotkeyBarBehavior.Value != 0 && QSSConfig.QuickStackConfig.QuickStackIncludesHotkeyBar.Value;
			List<ItemData> list = ((Humanoid)player).m_inventory.m_inventory.Where((ItemData itm) => ShouldQuickStackItem(itm, playerConfig, ((Humanoid)player).m_inventory.GetHeight(), ((Humanoid)player).m_inventory.GetWidth(), includeHotbar)).ToList();
			if (list.Count == 0 && QSSConfig.QuickStackConfig.ShowQuickStackResultMessage.Value)
			{
				((Character)player).Message((MessageType)2, LocalizationConfig.GetRelevantTranslation(LocalizationConfig.QuickStackResultMessageNothing, "QuickStackResultMessageNothing"), 0, (Sprite)null);
				return;
			}
			list.Sort((ItemData a, ItemData b) => -1 * Helper.CompareSlotOrder(a.m_gridPos, b.m_gridPos));
			List<ItemData> list2 = null;
			if (QSSConfig.QuickStackConfig.QuickStackTrophiesIntoSameContainer.Value)
			{
				list2 = new List<ItemData>();
				for (int num = list.Count - 1; num >= 0; num--)
				{
					ItemData val = list[num];
					if ((int)val.m_shared.m_itemType == 13)
					{
						list.RemoveAt(num);
						list2.Insert(0, val);
					}
				}
			}
			int num2 = 0;
			Container val2 = (Object.op_Implicit((Object)(object)currentContainerOverride) ? currentContainerOverride : InventoryGui.instance.m_currentContainer);
			if ((Object)(object)val2 != (Object)null)
			{
				num2 = QuickStackIntoThisContainer(list2, list, ((Humanoid)player).m_inventory, val2.m_inventory);
			}
			if (onlyQuickStackToCurrentContainer || !ShouldAreaQuickStack(val2))
			{
				ReportQuickStackResult(player, num2);
				return;
			}
			List<Container> list3 = ContainerFinder.FindContainersInRange(((Component)player).transform.position, QSSConfig.QuickStackConfig.QuickStackToNearbyRange.Value);
			Stopwatch stopwatch = new Stopwatch();
			stopwatch.Start();
			if (list3.Count > 0)
			{
				num2 += QuickStackIntoMultipleContainers(list2, list, player, list3);
			}
			stopwatch.Stop();
			Helper.Log($"Quick stacking time: {stopwatch.Elapsed}", QSSConfig.DebugSeverity.AlsoSpeedTests);
			ReportQuickStackResult(player, num2);
		}

		private static int QuickStackIntoThisContainer(List<ItemData> trophies, List<ItemData> nonTrophies, Inventory playerInventory, Inventory container, bool callPlayerInvChanged = true)
		{
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Invalid comparison between Unknown and I4
			int num = 0;
			Helper.Log($"Starting quick stack: inventory count: {playerInventory.m_inventory.Count}, container count: {container.m_inventory.Count}", QSSConfig.DebugSeverity.Everything);
			if (QSSConfig.QuickStackConfig.QuickStackTrophiesIntoSameContainer.Value && trophies != null && trophies.Count > 0)
			{
				for (int num2 = container.m_inventory.Count - 1; num2 >= 0; num2--)
				{
					ItemData val = container.m_inventory[num2];
					if ((int)val.m_shared.m_itemType == 13)
					{
						for (int num3 = trophies.Count - 1; num3 >= 0; num3--)
						{
							ItemData val2 = trophies[num3];
							if (container.AddItem(val2))
							{
								playerInventory.RemoveItem(val2);
								trophies.RemoveAt(num3);
								num++;
							}
						}
						break;
					}
				}
			}
			if (nonTrophies != null && nonTrophies.Count > 0)
			{
				for (int num4 = container.m_inventory.Count - 1; num4 >= 0; num4--)
				{
					ItemData val3 = container.m_inventory[num4];
					for (int num5 = nonTrophies.Count - 1; num5 >= 0; num5--)
					{
						ItemData val4 = nonTrophies[num5];
						if (!(val3.m_shared.m_name != val4.m_shared.m_name) && container.AddItem(val4))
						{
							playerInventory.RemoveItem(val4);
							nonTrophies.RemoveAt(num5);
							num++;
						}
					}
				}
			}
			Helper.Log($"Finished quick stack: Removed {num} stacks (remember that these merge with non full stacks in the container first). Inventory count: {playerInventory.m_inventory.Count}, container count: {container.m_inventory.Count}", QSSConfig.DebugSeverity.Everything);
			if (callPlayerInvChanged)
			{
				playerInventory.Changed();
			}
			return num;
		}

		private static int QuickStackIntoMultipleContainers(List<ItemData> trophies, List<ItemData> nonTrophies, Player player, List<Container> containers)
		{
			int num = 0;
			bool isSinglePlayer = AreaStackRestockHelper.IsTrueSingleplayer();
			foreach (Container container in containers)
			{
				if (AreaStackRestockHelper.ShouldAffectNonOwnerContainer(container, player.GetPlayerID(), isSinglePlayer))
				{
					if (CompatibilitySupport.HasPlugin("com.maxsch.valheim.MultiUserChest"))
					{
						num += QuickStackIntoThisContainer(trophies, nonTrophies, ((Humanoid)player).m_inventory, container.m_inventory, callPlayerInvChanged: false);
						continue;
					}
					container.m_nview.ClaimOwnership();
					AreaStackRestockHelper.SetNonMUCContainerInUse(container, isInUse: true);
					num += QuickStackIntoThisContainer(trophies, nonTrophies, ((Humanoid)player).m_inventory, container.m_inventory, callPlayerInvChanged: false);
					AreaStackRestockHelper.SetNonMUCContainerInUse(container, isInUse: false);
				}
			}
			((Humanoid)player).m_inventory.Changed();
			return num;
		}

		public static void ReportQuickStackResult(Player player, int movedCount)
		{
			if (QSSConfig.QuickStackConfig.ShowQuickStackResultMessage.Value)
			{
				((Character)player).Message((MessageType)2, movedCount switch
				{
					0 => LocalizationConfig.GetRelevantTranslation(LocalizationConfig.QuickStackResultMessageNone, "QuickStackResultMessageNone"), 
					1 => LocalizationConfig.GetRelevantTranslation(LocalizationConfig.QuickStackResultMessageOne, "QuickStackResultMessageOne"), 
					_ => string.Format(LocalizationConfig.GetRelevantTranslation(LocalizationConfig.QuickStackResultMessageMore, "QuickStackResultMessageMore"), movedCount), 
				}, 0, (Sprite)null);
			}
		}
	}
	[HarmonyPatch(typeof(Container))]
	public static class StackAllPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("RPC_StackResponse")]
		public static bool ContainerStackAllPatch(Container __instance, bool granted)
		{
			if (!QSSConfig.QuickStackConfig.ChangeHoldToStackFeatureToUseModdedQuickStackingLogic.Value)
			{
				return true;
			}
			if (!Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				return false;
			}
			if (granted)
			{
				QuickStackModule.DoQuickStack(Player.m_localPlayer, onlyQuickStackToCurrentContainer: true, __instance);
			}
			else
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, "$msg_inuse", 0, (Sprite)null);
			}
			return false;
		}
	}
	internal struct RestockData
	{
		internal ItemData itemData;

		internal int potentialCurrentStackSize;

		internal int maximumWantedStackSize;

		public RestockData(ItemData itemData, int potentialCurrentStackSize, int maximumWantedStackSize)
		{
			this.itemData = itemData;
			this.potentialCurrentStackSize = potentialCurrentStackSize;
			this.maximumWantedStackSize = maximumWantedStackSize;
		}
	}
	internal class RestockModule
	{
		private static bool ShouldRestockItem(ItemData item, UserConfig playerConfig, int inventoryHeight, int inventoryWidth, bool includeHotbar)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Invalid comparison between Unknown and I4
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Invalid comparison between Unknown and I4
			int configBasedMaxStackSize = GetConfigBasedMaxStackSize(item.m_shared);
			ItemType itemType = item.m_shared.m_itemType;
			return configBasedMaxStackSize > 1 && configBasedMaxStackSize > item.m_stack && (item.m_customData == null || item.m_customData.Count == 0) && (item.m_gridPos.y > 0 || includeHotbar) && (!QSSConfig.RestockConfig.RestockOnlyAmmoAndConsumables.Value || (int)itemType == 9 || (int)itemType == 2) && (!QSSConfig.RestockConfig.RestockOnlyFavoritedItems.Value || playerConfig.IsItemNameOrSlotFavorited(item)) && !CompatibilitySupport.IsEquipSlot(inventoryHeight, inventoryWidth, item.m_gridPos);
		}

		private static int GetConfigBasedMaxStackSize(SharedData shared)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Invalid comparison between Unknown and I4
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			int num = shared.m_maxStackSize;
			int num2 = 0;
			if ((int)shared.m_itemType == 9)
			{
				num2 = QSSConfig.RestockConfig.RestockStackSizeLimitAmmo.Value;
			}
			else if ((int)shared.m_itemType == 2)
			{
				num2 = QSSConfig.RestockConfig.RestockStackSizeLimitConsumables.Value;
			}
			if (num2 <= 0)
			{
				num2 = QSSConfig.RestockConfig.RestockStackSizeLimitGeneral.Value;
			}
			if (num2 > 0)
			{
				num = Math.Min(num, num2);
			}
			return num;
		}

		private static bool ShouldAreaRestock(Container currentContainer)
		{
			return QSSConfig.RestockConfig.RestockFromNearbyRange.Value > 0f && ((Object)(object)currentContainer == (Object)null || QSSConfig.RestockConfig.RestockHotkeyBehaviorWhenContainerOpen.Value != 0) && CompatibilitySupport.AllowAreaStackingRestocking();
		}

		internal static void DoRestock(Player player, bool RestockOnlyFromCurrentContainerOverride = false)
		{
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			if (((Character)player).IsTeleporting() || !Object.op_Implicit((Object)(object)InventoryGui.instance.m_container))
			{
				return;
			}
			InventoryGui.instance.SetupDragItem((ItemData)null, (Inventory)null, 0);
			UserConfig playerConfig = UserConfig.GetPlayerConfig(player.GetPlayerID());
			bool includeHotbar = QSSConfig.GeneralConfig.OverrideHotkeyBarBehavior.Value != 0 && QSSConfig.RestockConfig.RestockIncludesHotkeyBar.Value;
			List<RestockData> list = (from itemData in ((Humanoid)player).m_inventory.m_inventory
				where ShouldRestockItem(itemData, playerConfig, ((Humanoid)player).m_inventory.GetHeight(), ((Humanoid)player).m_inventory.GetWidth(), includeHotbar)
				select new RestockData(itemData, itemData.m_stack, GetConfigBasedMaxStackSize(itemData.m_shared))).ToList();
			int count = list.Count;
			if (count == 0 && QSSConfig.RestockConfig.ShowRestockResultMessage.Value)
			{
				((Character)player).Message((MessageType)2, LocalizationConfig.GetRelevantTranslation(LocalizationConfig.RestockResultMessageNothing, "RestockResultMessageNothing"), 0, (Sprite)null);
				return;
			}
			list.Sort((RestockData a, RestockData b) => -1 * Helper.CompareSlotOrder(a.itemData.m_gridPos, b.itemData.m_gridPos));
			int num = 0;
			HashSet<Vector2i> hashSet = new HashSet<Vector2i>();
			Container currentContainer = InventoryGui.instance.m_currentContainer;
			if ((Object)(object)currentContainer != (Object)null)
			{
				num = RestockFromThisContainer(list, ((Humanoid)player).m_inventory, currentContainer.m_inventory, hashSet);
			}
			if (RestockOnlyFromCurrentContainerOverride || !ShouldAreaRestock(currentContainer))
			{
				ReportRestockResult(player, num, hashSet.Count, count);
				return;
			}
			List<Container> list2 = ContainerFinder.FindContainersInRange(((Component)player).transform.position, QSSConfig.RestockConfig.RestockFromNearbyRange.Value);
			Stopwatch stopwatch = new Stopwatch();
			stopwatch.Start();
			if (list2.Count > 0)
			{
				num += RestockFromMultipleContainers(list, player, list2, hashSet);
			}
			stopwatch.Stop();
			Helper.Log($"Restocking time: {stopwatch.Elapsed}", QSSConfig.DebugSeverity.AlsoSpeedTests);
			ReportRestockResult(player, num, hashSet.Count, count);
		}

		private static int RestockFromThisContainer(List<RestockData> itemsToRestock, Inventory playerInventory, Inventory container, HashSet<Vector2i> partiallyFilledStacks, bool callPlayerInvChanged = true)
		{
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			if (itemsToRestock != null && itemsToRestock.Count <= 0)
			{
				return 0;
			}
			int num = 0;
			for (int num2 = itemsToRestock.Count - 1; num2 >= 0; num2--)
			{
				RestockData restockData = itemsToRestock[num2];
				for (int num3 = container.m_inventory.Count - 1; num3 >= 0; num3--)
				{
					ItemData val = container.m_inventory[num3];
					if ((val.m_customData == null || val.m_customData.Count <= 0) && !(val.m_shared.m_name != restockData.itemData.m_shared.m_name) && val.m_quality == restockData.itemData.m_quality)
					{
						int num4 = Math.Min(restockData.maximumWantedStackSize - restockData.potentialCurrentStackSize, val.m_stack);
						if (num4 > 0)
						{
							restockData.potentialCurrentStackSize += num4;
							partiallyFilledStacks.Add(restockData.itemData.m_gridPos);
							playerInventory.MoveItemToThis(container, val, num4, restockData.itemData.m_gridPos.x, restockData.itemData.m_gridPos.y);
						}
						if (restockData.potentialCurrentStackSize == restockData.maximumWantedStackSize)
						{
							itemsToRestock.RemoveAt(num2);
							num++;
							break;
						}
					}
				}
			}
			if (callPlayerInvChanged)
			{
				playerInventory.Changed();
			}
			return num;
		}

		private static int RestockFromMultipleContainers(List<RestockData> itemsToRestock, Player player, List<Container> containers, HashSet<Vector2i> partialRestockCounter)
		{
			int num = 0;
			bool isSinglePlayer = AreaStackRestockHelper.IsTrueSingleplayer();
			foreach (Container container in containers)
			{
				if (AreaStackRestockHelper.ShouldAffectNonOwnerContainer(container, player.GetPlayerID(), isSinglePlayer))
				{
					if (CompatibilitySupport.HasPlugin("com.maxsch.valheim.MultiUserChest"))
					{
						num += RestockFromThisContainer(itemsToRestock, ((Humanoid)player).m_inventory, container.m_inventory, partialRestockCounter, callPlayerInvChanged: false);
						continue;
					}
					container.m_nview.ClaimOwnership();
					AreaStackRestockHelper.SetNonMUCContainerInUse(container, isInUse: true);
					num += RestockFromThisContainer(itemsToRestock, ((Humanoid)player).m_inventory, container.m_inventory, partialRestockCounter, callPlayerInvChanged: false);
					AreaStackRestockHelper.SetNonMUCContainerInUse(container, isInUse: false);
				}
			}
			((Humanoid)player).m_inventory.Changed();
			return num;
		}

		public static void ReportRestockResult(Player player, int movedCount, int partiallyFilledCount, int totalCount)
		{
			if (QSSConfig.RestockConfig.ShowRestockResultMessage.Value)
			{
				string text;
				if (movedCount == 0 && partiallyFilledCount == 0)
				{
					text = string.Format(LocalizationConfig.GetRelevantTranslation(LocalizationConfig.RestockResultMessageNone, "RestockResultMessageNone"), totalCount);
				}
				else if (movedCount < totalCount)
				{
					text = string.Format(LocalizationConfig.GetRelevantTranslation(LocalizationConfig.RestockResultMessagePartial, "RestockResultMessagePartial"), partiallyFilledCount, totalCount);
				}
				else if (movedCount == totalCount)
				{
					text = string.Format(LocalizationConfig.GetRelevantTranslation(LocalizationConfig.RestockResultMessageFull, "RestockResultMessageFull"), totalCount);
				}
				else
				{
					text = $"Invalid restock: Restocked more items than we originally had ({movedCount}/{totalCount})";
					Helper.LogO(text);
				}
				((Character)player).Message((MessageType)2, text, 0, (Sprite)null);
			}
		}
	}
	[HarmonyPatch(typeof(InventoryGui))]
	internal class TakeAllPatch
	{
		[HarmonyPatch("OnTakeAll")]
		[HarmonyPrefix]
		internal static bool ContextSensitiveTakeAll(InventoryGui __instance)
		{
			if (!QSSConfig.StoreTakeAllConfig.ChestsUseImprovedTakeAllLogic.Value)
			{
				return true;
			}
			if (!Object.op_Implicit((Object)(object)__instance.m_currentContainer) || Object.op_Implicit((Object)(object)((Component)__instance.m_currentContainer).GetComponent<TombStone>()))
			{
				return true;
			}
			StoreTakeAllModule.TakeAllItemsInOrder(Player.m_localPlayer);
			return false;
		}
	}
	internal class StoreTakeAllModule
	{
		internal static void DoTakeAllWithKeybind(Player player)
		{
			if (Object.op_Implicit((Object)(object)InventoryGui.instance) && InventoryGui.IsVisible() && !((Object)(object)player != (Object)(object)Player.m_localPlayer))
			{
				InventoryGui.instance.OnTakeAll();
			}
		}

		internal static void DoStoreAllWithKeybind(Player player)
		{
			if (Object.op_Implicit((Object)(object)InventoryGui.instance) && InventoryGui.IsVisible() && !((Object)(object)player != (Object)(object)Player.m_localPlayer))
			{
				StoreAllItemsInOrder(player);
			}
		}

		private static bool ShouldStoreItem(ItemData item, UserConfig playerConfig, int inventoryHeight, int inventoryWidth, bool includeHotbar)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			return (item.m_gridPos.y > 0 || includeHotbar) && (QSSConfig.StoreTakeAllConfig.StoreAllIncludesEquippedItems.Value || !item.m_equipped) && !playerConfig.IsItemNameOrSlotFavorited(item) && !CompatibilitySupport.IsEquipOrQuickSlot(inventoryHeight, inventoryWidth, item.m_gridPos);
		}

		internal static void TakeAllItemsInOrder(Player player)
		{
			if (Object.op_Implicit((Object)(object)InventoryGui.instance.m_currentContainer))
			{
				Inventory inventory = InventoryGui.instance.m_currentContainer.m_inventory;
				Inventory inventory2 = ((Humanoid)player).m_inventory;
				MoveAllItemsInOrder(player, inventory, inventory2, takeAllOverride: true);
			}
		}

		internal static void StoreAllItemsInOrder(Player player)
		{
			if (Object.op_Implicit((Object)(object)InventoryGui.instance.m_currentContainer))
			{
				Inventory inventory = ((Humanoid)player).m_inventory;
				Inventory inventory2 = InventoryGui.instance.m_currentContainer.m_inventory;
				MoveAllItemsInOrder(player, inventory, inventory2);
			}
		}

		internal static void MoveAllItemsInOrder(Player player, Inventory fromInventory, Inventory toInventory, bool takeAllOverride = false)
		{
			if (((Character)player).IsTeleporting())
			{
				return;
			}
			InventoryGui.instance.SetupDragItem((ItemData)null, (Inventory)null, 0);
			List<ItemData> list;
			if (takeAllOverride)
			{
				list = new List<ItemData>(fromInventory.m_inventory);
			}
			else
			{
				UserConfig playerConfig = UserConfig.GetPlayerConfig(player.GetPlayerID());
				bool includeHotbar = QSSConfig.GeneralConfig.OverrideHotkeyBarBehavior.Value != 0 && QSSConfig.StoreTakeAllConfig.StoreAllIncludesHotkeyBar.Value;
				list = fromInventory.m_inventory.Where((ItemData item) => ShouldStoreItem(item, playerConfig, fromInventory.GetHeight(), fromInventory.GetWidth(), includeHotbar)).ToList();
			}
			list.Sort((ItemData a, ItemData b) => Helper.CompareSlotOrder(a.m_gridPos, b.m_gridPos));
			int num = 0;
			foreach (ItemData item in list)
			{
				if (toInventory.AddItem(item))
				{
					fromInventory.RemoveItem(item);
					num++;
					if (item.m_equipped)
					{
						((Humanoid)Player.m_localPlayer).RemoveEquipAction(item);
						((Humanoid)Player.m_localPlayer).UnequipItem(item, false);
					}
				}
			}
			if (takeAllOverride)
			{
				Helper.Log($"Moved {num} item/s from container to player inventory");
			}
			else
			{
				Helper.Log($"Moved {num} item/s from player inventory to container");
			}
			toInventory.Changed();
			fromInventory.Changed();
		}
	}
	public static class SortModule
	{
		public static int[] TypeToCategory = new int[24]
		{
			0, 2, 4, 7, 7, 8, 10, 10, 0, 6,
			0, 10, 10, 1, 7, 7, 0, 10, 9, 7,
			7, 3, 7, 5
		};

		private static bool ShouldSortItem(ItemData item, UserConfig playerConfig, int inventoryHeight, int inventoryWidth, bool includeHotbar)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			return !playerConfig.IsItemNameFavorited(item.m_shared) && ShouldSortSlot(item.m_gridPos, playerConfig, inventoryHeight, inventoryWidth, includeHotbar);
		}

		private static bool ShouldSortSlot(Vector2i slot, UserConfig playerConfig, int playerInventoryHeight, int playerInventoryWidth, bool includeHotbar)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			return (slot.y > 0 || includeHotbar) && !playerConfig.IsSlotFavorited(slot) && !CompatibilitySupport.IsEquipOrQuickSlot(playerInventoryHeight, playerInventoryWidth, slot);
		}

		public static void DoSort(Player player)
		{
			Container currentContainer = InventoryGui.instance.m_currentContainer;
			UserConfig playerConfig = UserConfig.GetPlayerConfig(player.GetPlayerID());
			if ((Object)(object)currentContainer != (Object)null)
			{
				switch (QSSConfig.SortConfig.SortHotkeyBehaviorWhenContainerOpen.Value)
				{
				case QSSConfig.SortBehavior.OnlySortContainer:
					SortContainer(InventoryGui.instance.m_currentContainer);
					break;
				case QSSConfig.SortBehavior.SortBoth:
					SortContainer(InventoryGui.instance.m_currentContainer);
					SortPlayerInv(((Humanoid)player).m_inventory, playerConfig);
					break;
				}
			}
			else
			{
				SortPlayerInv(((Humanoid)player).m_inventory, playerConfig);
			}
		}

		public static IComparable SortByGetter(ItemData item)
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Expected I4, but got Unknown
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			switch (QSSConfig.SortConfig.SortCriteria.Value)
			{
			case QSSConfig.SortCriteriaEnum.TranslatedName:
				return Localization.instance.Localize(item.m_shared.m_name);
			case QSSConfig.SortCriteriaEnum.Value:
				return item.m_shared.m_value;
			case QSSConfig.SortCriteriaEnum.Weight:
				return item.m_shared.m_weight;
			case QSSConfig.SortCriteriaEnum.Type:
			{
				int num = (int)item.m_shared.m_itemType;
				if (num < 0 || num > 23)
				{
					return num;
				}
				return TypeToCategory[item.m_shared.m_itemType];
			}
			default:
				return item.m_shared.m_name;
			}
		}

		public static int SortCompare(ItemData a, ItemData b)
		{
			int num = SortByGetter(a).CompareTo(SortByGetter(b));
			if (!QSSConfig.SortConfig.SortInAscendingOrder.Value)
			{
				num *= -1;
			}
			if (num == 0)
			{
				num = a.m_shared.m_name.CompareTo(b.m_shared.m_name);
			}
			if (num == 0)
			{
				num = -a.m_quality.CompareTo(b.m_quality);
			}
			if (num == 0)
			{
				num = -a.m_stack.CompareTo(b.m_stack);
			}
			return num;
		}

		public static void SortContainer(Container container)
		{
			if (container.m_nview.IsOwner())
			{
				SortInternal(container.m_inventory);
			}
			else
			{
				container.m_nview.InvokeRPC("QuickStackStore_RequestSort", Array.Empty<object>());
			}
		}

		public static void SortPlayerInv(Inventory inventory, UserConfig playerConfig)
		{
			SortInternal(inventory, playerConfig);
		}

		internal static void SortInternal(Inventory inventory, UserConfig playerConfig = null)
		{
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			Stopwatch stopwatch = new Stopwatch();
			stopwatch.Start();
			bool includeHotbar = playerConfig == null || (QSSConfig.GeneralConfig.OverrideHotkeyBarBehavior.Value != 0 && QSSConfig.SortConfig.SortIncludesHotkeyBar.Value);
			List<Vector2i> allowedSlots = GetAllowedSlots(inventory, includeHotbar, playerConfig);
			List<ItemData> list = ((playerConfig != null) ? inventory.m_inventory.Where((ItemData item) => ShouldSortItem(item, playerConfig, inventory.GetHeight(), inventory.GetWidth(), includeHotbar)).ToList() : new List<ItemData>(inventory.m_inventory));
			if (QSSConfig.SortConfig.SortMergesStacks.Value)
			{
				MergeStacks(list, inventory);
			}
			list.Sort((ItemData a, ItemData b) => SortCompare(a, b));
			for (int i = 0; i < list.Count; i++)
			{
				Helper.Log($"Sorting item from ({list[i].m_gridPos}) to ({allowedSlots[i]})", QSSConfig.DebugSeverity.Everything);
				list[i].m_gridPos = allowedSlots[i];
			}
			stopwatch.Stop();
			Helper.Log($"Sorting time: {stopwatch.Elapsed}", QSSConfig.DebugSeverity.AlsoSpeedTests);
			inventory.Changed();
		}

		private static List<Vector2i> GetAllowedSlots(Inventory inventory, bool includeHotbar, UserConfig playerConfig)
		{
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			List<Vector2i> list = new List<Vector2i>();
			int i;
			int num;
			if (QSSConfig.GeneralConfig.UseTopDownLogicForEverything.Value)
			{
				i = ((!includeHotbar) ? 1 : 0);
				num = inventory.GetHeight();
			}
			else
			{
				i = -inventory.GetHeight() + 1;
				num = (includeHotbar ? 1 : 0);
			}
			HashSet<Vector2i> hashSet = new HashSet<Vector2i>();
			if (playerConfig != null)
			{
				foreach (ItemData item in inventory.m_inventory)
				{
					if (playerConfig.IsItemNameFavorited(item.m_shared))
					{
						hashSet.Add(item.m_gridPos);
					}
				}
			}
			Vector2i val = default(Vector2i);
			for (; i < num; i++)
			{
				for (int j = 0; j < inventory.GetWidth(); j++)
				{
					((Vector2i)(ref val))..ctor(j, Math.Abs(i));
					if (playerConfig == null || (!hashSet.Contains(val) && (!QSSConfig.SortConfig.SortLeavesEmptyFavoritedSlotsEmpty.Value || !playerConfig.IsSlotFavorited(val)) && !CompatibilitySupport.IsEquipOrQuickSlot(inventory.GetHeight(), inventory.GetWidth(), val)))
					{
						list.Add(val);
					}
				}
			}
			return list;
		}

		internal static void MergeStacks(List<ItemData> toMerge, Inventory inventory)
		{
			List<List<ItemData>> list = (from itm in toMerge
				where itm.m_stack < itm.m_shared.m_maxStackSize && (itm.m_customData == null || itm.m_customData.Count == 0)
				group itm by new
				{
					itm.m_shared.m_name,
					itm.m_quality
				} into grouping
				select grouping.ToList()).ToList();
			foreach (List<ItemData> item in list)
			{
				if (item.Count <= 1)
				{
					continue;
				}
				int num = 0;
				foreach (ItemData item2 in item)
				{
					num += item2.m_stack;
				}
				int maxStackSize = item.First().m_shared.m_maxStackSize;
				int num2 = num;
				foreach (ItemData item3 in item)
				{
					if (num2 <= 0)
					{
						item3.m_stack = 0;
						inventory.RemoveItem(item3);
						toMerge.Remove(item3);
					}
					else
					{
						item3.m_stack = Math.Min(maxStackSize, num2);
						num2 -= item3.m_stack;
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(Container))]
	public static class ContainerPatch
	{
		internal const string rpc_requestSort = "QuickStackStore_RequestSort";

		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		public static void ContainerAwakePatch(Container __instance)
		{
			if (!Object.op_Implicit((Object)(object)__instance.m_nview))
			{
				__instance.m_nview = (Object.op_Implicit((Object)(object)__instance.m_rootObjectOverride) ? ((Component)__instance.m_rootObjectOverride).GetComponent<ZNetView>() : ((Component)__instance).GetComponent<ZNetView>());
			}
			if (Object.op_Implicit((Object)(object)__instance.m_nview))
			{
				__instance.m_nview.Unregister("QuickStackStore_RequestSort");
				__instance.m_nview.Register("QuickStackStore_RequestSort", (Action<long>)delegate(long l)
				{
					RPC_RequestSort(l, __instance);
				});
			}
		}

		public static void RPC_RequestSort(long _, Container container)
		{
			if (container.m_nview.IsOwner())
			{
				SortModule.SortInternal(container.m_inventory);
			}
		}
	}
	[HarmonyPatch(typeof(Player))]
	internal static class PlayerPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("Start")]
		internal static void StartPatch(Player __instance)
		{
			if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
			{
				QSSConfig.ResetAllFavoritingData_SettingChanged(null, null);
			}
		}
	}
	internal class QSSConfig
	{
		internal class GeneralConfig
		{
			public static ConfigEntry<ConfigTemplate> ConfigTemplate;

			public static ConfigEntry<OverrideButtonDisplay> OverrideButtonDisplay;

			public static ConfigEntry<OverrideKeybindBehavior> OverrideKeybindBehavior;

			public static ConfigEntry<OverrideHotkeyBarBehavior> OverrideHotkeyBarBehavior;

			public static ConfigEntry<bool> UseTopDownLogicForEverything;
		}

		internal class ControllerConfig
		{
			public static ConfigEntry<DPadUsage> ControllerDPadUsageInInventoryGrid;

			public static ConfigEntry<KeyboardShortcut> ControllerDPadUsageModifierKeybind;

			public static ConfigEntry<bool> RemoveControllerButtonHintFromTakeAllButton;

			public static ConfigEntry<bool> UseHardcodedControllerSupport;
		}

		internal class FavoriteConfig
		{
			public static ConfigEntry<Color> BorderColorFavoritedItem;

			public static ConfigEntry<Color> BorderColorFavoritedItemOnFavoritedSlot;

			public static ConfigEntry<Color> BorderColorFavoritedSlot;

			public static ConfigEntry<Color> BorderColorTrashFlaggedItem;

			public static ConfigEntry<Color> BorderColorTrashFlaggedItemOnFavoritedSlot;

			public static ConfigEntry<FavoritingToggling> DisplayFavoriteToggleButton;

			public static ConfigEntry<bool> DisplayTooltipHint;

			public static ConfigEntry<KeyboardShortcut> FavoritingModifierKeybind1;

			public static ConfigEntry<KeyboardShortcut> FavoritingModifierKeybind2;

			public static ConfigEntry<FavoriteToggleButtonStyle> FavoriteToggleButtonStyle;
		}

		internal class QuickStackRestockConfig
		{
			public static ConfigSync AreaStackRestockServerSync;

			public static ConfigEntry<bool> AllowAreaStackingInMultiplayerWithoutMUC;

			public static ConfigEntry<bool> AllowAreaStackingToNonPhysicalContainers;

			public static ConfigEntry<bool> AllowAreaStackingToPhysicalNonPlayerBuiltContainers;

			public static ConfigEntry<bool> SuppressContainerSoundAndVisuals;

			public static ConfigEntry<bool> ToggleAreaStackRestockConfigServerSync;
		}

		internal class QuickStackConfig
		{
			public static ConfigEntry<bool> ChangeHoldToStackFeatureToUseModdedQuickStackingLogic;

			public static ConfigEntry<ShowTwoButtons> DisplayQuickStackButtons;

			public static ConfigEntry<bool> HideBaseGamePlaceStacksButton;

			public static ConfigEntry<QuickStackBehavior> QuickStackHotkeyBehaviorWhenContainerOpen;

			public static ConfigEntry<bool> QuickStackIncludesHotkeyBar;

			public static ConfigEntry<KeyboardShortcut> QuickStackKeybind;

			public static ConfigEntry<float> QuickStackToNearbyRange;

			public static ConfigEntry<bool> QuickStackTrophiesIntoSameContainer;

			public static ConfigEntry<bool> ShowQuickStackResultMessage;
		}

		internal class RestockConfig
		{
			public static ConfigEntry<ShowTwoButtons> DisplayRestockButtons;

			public static ConfigEntry<float> RestockFromNearbyRange;

			public static ConfigEntry<RestockBehavior> RestockHotkeyBehaviorWhenContainerOpen;

			public static ConfigEntry<bool> RestockIncludesHotkeyBar;

			public static ConfigEntry<KeyboardShortcut> RestockKeybind;

			public static ConfigEntry<bool> RestockOnlyAmmoAndConsumables;

			public static ConfigEntry<bool> RestockOnlyFavoritedItems;

			public static ConfigEntry<int> RestockStackSizeLimitAmmo;

			public static ConfigEntry<int> RestockStackSizeLimitConsumables;

			public static ConfigEntry<int> RestockStackSizeLimitGeneral;

			public static ConfigEntry<bool> ShowRestockResultMessage;
		}

		internal class StoreTakeAllConfig
		{
			public static ConfigEntry<bool> ChestsUseImprovedTakeAllLogic;

			public static ConfigEntry<bool> DisplayStoreAllButton;

			public static ConfigEntry<bool> NeverMoveTakeAllButton;

			public static ConfigEntry<KeyboardShortcut> StoreAllKeybind;

			public static ConfigEntry<bool> StoreAllIncludesEquippedItems;

			public static ConfigEntry<bool> StoreAllIncludesHotkeyBar;

			public static ConfigEntry<KeyboardShortcut> TakeAllKeybind;
		}

		internal class SortConfig
		{
			public static ConfigEntry<AutoSortBehavior> AutoSort;

			public static ConfigEntry<ShowTwoButtons> DisplaySortButtons;

			public static ConfigEntry<bool> DisplaySortCriteriaInLabel;

			public static ConfigEntry<SortCriteriaEnum> SortCriteria;

			public static ConfigEntry<SortBehavior> SortHotkeyBehaviorWhenContainerOpen;

			public static ConfigEntry<bool> SortInAscendingOrder;

			public static ConfigEntry<bool> SortIncludesHotkeyBar;

			public static ConfigEntry<KeyboardShortcut> SortKeybind;

			public static ConfigEntry<bool> SortLeavesEmptyFavoritedSlotsEmpty;

			public static ConfigEntry<bool> SortMergesStacks;
		}

		internal class TrashConfig
		{
			public static ConfigEntry<bool> AlwaysConsiderTrophiesTrashFlagged;

			public static ConfigEntry<bool> DisplayTrashCanUI;

			public static ConfigEntry<bool> EnableQuickTrash;

			public static ConfigEntry<KeyboardShortcut> QuickTrashKeybind;

			public static ConfigEntry<ShowConfirmDialogOption> ShowConfirmDialogForNormalItem;

			public static ConfigEntry<bool> ShowConfirmDialogForQuickTrash;

			public static ConfigEntry<bool> TrashingCanAffectHotkeyBar;

			public static ConfigEntry<KeyboardShortcut> TrashKeybind;

			public static ConfigEntry<Color> TrashLabelColor;
		}

		internal class DebugConfig
		{
			public static ConfigEntry<DebugLevel> ShowDebugLogs;

			public static ConfigEntry<DebugSeverity> DebugSeverity;

			public static ConfigEntry<ResetFavoritingData> ResetAllFavoritingData;
		}

		public enum OverrideButtonDisplay
		{
			DisableAllNewButtons,
			UseIndividualConfigOptions
		}

		public enum OverrideKeybindBehavior
		{
			DisableAllNewHotkeys,
			UseIndividualConfigOptions
		}

		public enum OverrideHotkeyBarBehavior
		{
			NeverAffectHotkeyBar,
			UseIndividualConfigOptions
		}

		public enum ShowConfirmDialogOption
		{
			Never,
			WhenNotTrashFlagged,
			Always
		}

		public enum ShowTwoButtons
		{
			Both,
			OnlyInventoryButton,
			OnlyContainerButton,
			BothButDependingOnContext,
			Disabled
		}

		public enum QuickStackBehavior
		{
			QuickStackOnlyToCurrentContainer,
			QuickStackToBoth
		}

		public enum RestockBehavior
		{
			RestockOnlyFromCurrentContainer,
			RestockFromBoth
		}

		public enum SortBehavior
		{
			OnlySortContainer,
			SortBoth
		}

		public enum SortCriteriaEnum
		{
			InternalName,
			TranslatedName,
			Value,
			Weight,
			Type
		}

		public enum AutoSortBehavior
		{
			Never,
			SortContainerOnOpen,
			SortPlayerInventoryOnOpen,
			Both
		}

		internal enum DebugLevel
		{
			Disabled,
			Log,
			Warning
		}

		internal enum DebugSeverity
		{
			Normal,
			AlsoSpeedTests,
			Everything
		}

		internal enum ResetFavoritingData
		{
			No,
			YesDeleteAllMyFavoritingData
		}

		internal enum FavoritingToggling
		{
			Disabled,
			EnabledTopButton,
			EnabledBottomButton
		}

		internal enum FavoriteToggleButtonStyle
		{
			DefaultTextStar,
			TextStarInItemFavoriteColor
		}

		internal enum DPadUsage
		{
			InventorySlotMovement,
			Keybinds,
			KeybindsWhileHoldingModifierKey
		}

		internal enum ConfigTemplate
		{
			NotCurrentlyLoadingTemplate,
			BasicControllerKeybinds,
			CustomControllerKeybinds,
			MouseAndKeyboardWithButtons,
			MouseAndKeyboardWithHotkeys,
			GoldensChoice,
			ResetToDefault
		}

		public static ConfigFile Config;

		internal static readonly List<ConfigEntryBase> keyBinds = new List<ConfigEntryBase>();

		internal static void LoadConfig(BaseUnityPlugin plugin)
		{
			Config = plugin.Config;
			Config.SaveOnConfigSet = false;
			LoadConfigInternal(plugin);
			Config.Save();
			Config.SaveOnConfigSet = true;
		}

		private static void LoadConfigInternal(BaseUnityPlugin plugin)
		{
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Expected O, but got Unknown
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Expected O, but got Unknown
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Expected O, but got Unknown
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0308: Unknown result type (might be due to invalid IL or missing references)
			//IL_0336: Unknown result type (might be due to invalid IL or missing references)
			//IL_0364: Unknown result type (might be due to invalid IL or missing references)
			//IL_0389: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f3: Expected O, but got Unknown
			//IL_043e: Unknown result type (might be due to invalid IL or missing references)
			//IL_046e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0714: Unknown result type (might be due to invalid IL or missing references)
			//IL_0882: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a0f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a81: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ba9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0cab: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d62: Unknown result type (might be due to invalid IL or missing references)
			//IL_0db2: Unknown result type (might be due to invalid IL or missing references)
			if (Config == null)
			{
				Helper.LogO("Internal config load was called without its wrapper. This is slower but still works.");
				Config = plugin.Config;
			}
			string text = "overridden by OverrideButtonDisplay";
			string text2 = "overridden by OverrideKeybindBehavior";
			string text3 = "overridden by OverrideHotkeyBarBehavior";
			string text4 = "What to do when the hotkey is pressed while you have a container open.";
			string text5 = "Which of the two buttons to display (" + text + "). Selecting BothButDependingOnContext will hide the mini button while a container is open. The hotkey works independently.";
			string description = "How close the searched through containers have to be.";
			string text6 = "disallowing quick stacking, storing, sorting and trashing";
			string text7 = "While holding this, left clicking on items or right clicking on slots favorites them, " + text6 + ", or trash flags them if you are hovering an item on the trash can.";
			string format = "Allows to set a custom stack size limit for {0} items in case you don't want them to restock to their maximum stack size. Use zero or negative numbers disable this.";
			string text8 = "0 - General";
			GeneralConfig.ConfigTemplate = Config.Bind<ConfigTemplate>(text8, "ConfigTemplate", ConfigTemplate.NotCurrentlyLoadingTemplate, "Immediately or at the next startup, resets the config and applies the selected config template. Does not change any custom keybinds!");
			GeneralConfig.ConfigTemplate.SettingChanged += ConfigTemplate_SettingChanged;
			GeneralConfig.OverrideButtonDisplay = Config.Bind<OverrideButtonDisplay>(text8, "OverrideButtonDisplay", OverrideButtonDisplay.UseIndividualConfigOptions, "Override to disable all new UI elements no matter the current individual setting of each of them.");
			GeneralConfig.OverrideButtonDisplay.SettingChanged += delegate
			{
				ButtonRenderer.OnButtonRelevantSettingChanged(plugin, includeTrashButton: true);
			};
			GeneralConfig.OverrideHotkeyBarBehavior = Config.Bind<OverrideHotkeyBarBehavior>(text8, "OverrideHotkeyBarBehavior", OverrideHotkeyBarBehavior.NeverAffectHotkeyBar, "Override to never affect the hotkey bar with any feature no matter the individual setting of each of them. Recommended to turn off if you are actually using favoriting.");
			GeneralConfig.OverrideKeybindBehavior = Config.Bind<OverrideKeybindBehavior>(text8, "OverrideKeybindBehavior", OverrideKeybindBehavior.UseIndividualConfigOptions, "Override to disable all new keybinds no matter the current individual setting of each of them.");
			bool oldValue = false;
			if (TryGetOldConfigValue(new ConfigDefinition(text8, "DisableAllNewButtons"), ref oldValue))
			{
				GeneralConfig.OverrideButtonDisplay.Value = ((!oldValue) ? OverrideButtonDisplay.UseIndividualConfigOptions : OverrideButtonDisplay.DisableAllNewButtons);
			}
			if (TryGetOldConfigValue(new ConfigDefinition(text8, "DisableAllNewKeybinds"), ref oldValue))
			{
				GeneralConfig.OverrideKeybindBehavior.Value = ((!oldValue) ? OverrideKeybindBehavior.UseIndividualConfigOptions : OverrideKeybindBehavior.DisableAllNewHotkeys);
			}
			if (TryGetOldConfigValue(new ConfigDefinition(text8, "NeverAffectHotkeyBar"), ref oldValue))
			{
				GeneralConfig.OverrideHotkeyBarBehavior.Value = ((!oldValue) ? OverrideHotkeyBarBehavior.UseIndividualConfigOptions : OverrideHotkeyBarBehavior.NeverAffectHotkeyBar);
			}
			GeneralConfig.UseTopDownLogicForEverything = Config.Bind<bool>(text8, "UseTopDownLogicForEverything", false, "Whether to always put items into the top first row (affects the entire game) rather than top or bottom first depending on the item type (base game uses top first only for weapons and tools, bottom first for the rest). Recommended to keep off.");
			text8 = "0.1 - Controller General";
			ControllerConfig.ControllerDPadUsageInInventoryGrid = Config.Bind<DPadUsage>(text8, "ControllerDPadUsageInInventoryGrid", DPadUsage.Keybinds, "In the base game the DPad and the left stick are both used for slot movement inside the inventory grid. This allows you to exclude the DPad from this to get more keys for keybinds.");
			ControllerConfig.ControllerDPadUsageModifierKeybind = Config.Bind<KeyboardShortcut>(text8, "ControllerDPadUsageModifierKeybind", new KeyboardShortcut((KeyCode)0, Array.Empty<KeyCode>()), string.Format("When {0} is set to {1}, then holding this prevents slot movement in the inventory grid with the DPad.", "ControllerDPadUsageInInventoryGrid", DPadUsage.KeybindsWhileHoldingModifierKey));
			ControllerConfig.RemoveControllerButtonHintFromTakeAllButton = Config.Bind<bool>(text8, "RemoveControllerButtonHintFromTakeAllButton", false, "Remove the button hint from the 'Take All' button while using a controller for consistency. Especially useful when using the new keybind TakeAllKeybind.");
			ControllerConfig.RemoveControllerButtonHintFromTakeAllButton.SettingChanged += delegate
			{
				ButtonRenderer.OnButtonRelevantSettingChanged(plugin);
			};
			ControllerConfig.UseHardcodedControllerSupport = Config.Bind<bool>(text8, "UseHardcodedControllerSupport", true, "Whether to enable the hardcoded controller bindings including UI hints while a controller is used. This disables custom hotkeys.");
			ControllerConfig.UseHardcodedControllerSupport.SettingChanged += delegate
			{
				ButtonRenderer.OnButtonRelevantSettingChanged(plugin);
			};
			text8 = "1 - Favoriting";
			FavoriteConfig.BorderColorFavoritedItem = Config.Bind<Color>(text8, "BorderColorFavoritedItem", new Color(1f, 0.8482759f, 0f), "Color of the border for slots containing favorited items.");
			FavoriteConfig.BorderColorFavoritedItem.SettingChanged += delegate
			{
				FavoritingMode.RefreshDisplay();
			};
			FavoriteConfig.BorderColorFavoritedItemOnFavoritedSlot = Config.Bind<Color>(text8, "BorderColorFavoritedItemOnFavoritedSlot", new Color(0.5f, 0.67413795f, 0.5f), "Color of the border of a favorited slot that also contains a favorited item.");
			FavoriteConfig.BorderColorFavoritedSlot = Config.Bind<Color>(text8, "BorderColorFavoritedSlot", new Color(0f, 0.5f, 1f), "Color of the border for favorited slots.");
			FavoriteConfig.BorderColorTrashFlaggedItem = Config.Bind<Color>(text8, "BorderColorTrashFlaggedItem", new Color(0.5f, 0f, 0f), ConfigurationManagerAttributes.HiddenTrashingDisplay("Color of the border for slots containing trash flagged items."));
			FavoriteConfig.BorderColorTrashFlaggedItemOnFavoritedSlot = Config.Bind<Color>(text8, "BorderColorTrashFlaggedItemOnFavoritedSlot", Color.black, ConfigurationManagerAttributes.HiddenTrashingDisplay("Color of the border of a favorited slot that also contains a trash flagged item."));
			FavoriteConfig.DisplayFavoriteToggleButton = Config.Bind<FavoritingToggling>(text8, "DisplayFavoriteToggleButton", FavoritingToggling.EnabledTopButton, "Whether to display a button to toggle favoriting mode on or off, allowing to favorite without holding any hotkey (" + text + "). This can also be used to trash flag. The hotkeys work independently.");
			FavoriteConfig.DisplayFavoriteToggleButton.SettingChanged += delegate
			{
				ButtonRenderer.OnButtonRelevantSettingChanged(plugin);
			};
			if (TryGetOldConfigValue(new ConfigDefinition(text8, "FavoritingModifierToggles"), ref oldValue))
			{
				FavoriteConfig.DisplayFavoriteToggleButton.Value = (oldValue ? FavoritingToggling.EnabledTopButton : FavoritingToggling.Disabled);
			}
			FavoriteConfig.DisplayTooltipHint = Config.Bind<bool>(text8, "DisplayTooltipHint", true, "Whether to add additional info the item tooltip of a favorited or trash flagged item.");
			FavoriteConfig.FavoritingModifierKeybind1 = Config.Bind<KeyboardShortcut>(text8, "FavoritingModifierKeybind1", new KeyboardShortcut((KeyCode)308, Array.Empty<KeyCode>()), text7 + " Identical to FavoritingModifierKeybind2.");
			FavoriteConfig.FavoritingModifierKeybind2 = Config.Bind<KeyboardShortcut>(text8, "FavoritingModifierKeybind2", new KeyboardShortcut((KeyCode)307, Array.Empty<KeyCode>()), text7 + " Identical to FavoritingModifierKeybind1.");
			KeyCodeBackwardsCompatibility(FavoriteConfig.FavoritingModifierKeybind1, text8, "FavoritingModifierKey1");
			KeyCodeBackwardsCompatibility(FavoriteConfig.FavoritingModifierKeybind2, text8, "FavoritingModifierKey2");
			FavoriteConfig.FavoriteToggleButtonStyle = Config.Bind<FavoriteToggleButtonStyle>(text8, "FavoriteToggleButtonStyle", FavoriteToggleButtonStyle.TextStarInItemFavoriteColor, "The style of the favorite toggling button enabled with DisplayFavoriteToggleButton.");
			FavoriteConfig.FavoriteToggleButtonStyle.SettingChanged += delegate
			{
				FavoritingMode.RefreshDisplay();
			};
			text8 = "2 - Quick Stacking and Restocking";
			string category = "2.0 - Area Quick Stacking and Restocking";
			QuickStackRestockConfig.AreaStackRestockServerSync = new ConfigSync("goldenrevolver.quick_stack_store")
			{
				DisplayName = "Quick Stack - Store - Sort - Trash - Restock",
				CurrentVersion = "1.4.7",
				MinimumRequiredVersion = "1.4.7",
				ModRequired = false
			};
			QuickStackRestockConfig.AllowAreaStackingInMultiplayerWithoutMUC = Config.BindSynced(QuickStackRestockConfig.AreaStackRestockServerSync, text8, "AllowAreaStackingInMultiplayerWithoutMUC", value: false, ConfigurationManagerAttributes.MUCSettingDisplay("AllowAreaStackingInMultiplayer", category, "Whether you can use area quick stacking and area restocking in multiplayer while 'Multi User Chest' is not installed. While this is almost always safe, it can fail because no actual network requests are getting sent. Ship containers are inherently especially vulnerable and are therefore excluded."));
			QuickStackRestockConfig.AllowAreaStackingInMultiplayerWithoutMUC.SettingChanged += delegate
			{
				ButtonRenderer.OnButtonRelevantSettingChanged(plugin);
			};
			QuickStackRestockConfig.AllowAreaStackingToNonPhysicalContainers = Config.BindSynced(QuickStackRestockConfig.AreaStackRestockServerSync, text8, "AllowAreaStackingToNonPhysicalContainers", value: true, ConfigurationManagerAttributes.CustomCategoryWithDescription(category, "Allow stacking to or restocking from containers without a physical piece object in the world, like backpacks."));
			QuickStackRestockConfig.AllowAreaStackingToPhysicalNonPlayerBuiltContainers = Config.BindSynced(QuickStackRestockConfig.AreaStackRestockServerSync, text8, "AllowAreaStackingToPhysicalNonPlayerBuiltContainers", value: false, ConfigurationManagerAttributes.CustomCategoryWithDescription(category, "Allow stacking to or restocking from containers like dungeon chests or probably some modded containers."));
			QuickStackRestockConfig.SuppressContainerSoundAndVisuals = Config.BindSynced(QuickStackRestockConfig.AreaStackRestockServerSync, text8, "SuppressContainerSoundAndVisuals", value: true, ConfigurationManagerAttributes.CustomCategoryWithDescription(category, "Whether when a feature checks multiple containers in an area, they actually play opening sounds and visuals. Disable if the suppression causes incompatibilities."));
			QuickStackRestockConfig.ToggleAreaStackRestockConfigServerSync = Config.BindSyncLocker(QuickStackRestockConfig.AreaStackRestockServerSync, text8, "ToggleAreaStackRestockConfigServerSync", value: true, ConfigurationManagerAttributes.CustomCategoryWithDescription(category, "Whether the config settings about area quick stacking and area restocking (including range) of the host/ server get applied to all other users using this mod. Does nothing if the host/ server does not have this mod installed."));
			text8 = "2.1 - Quick Stacking";
			QuickStackConfig.ChangeHoldToStackFeatureToUseModdedQuickStackingLogic = Config.Bind<bool>(text8, "ChangeHoldToStackFeatureToUseModdedQuickStackingLogic", true, "Whether to override the behavior when holding open on a container that you are hovering on with the modded quick stacking behavior. Does not override the behavior of the default 'Place Stacks' button, if it's still enabled.");
			QuickStackConfig.DisplayQuickStackButtons = Config.Bind<ShowTwoButtons>(text8, "DisplayQuickStackButtons", ShowTwoButtons.BothButDependingOnContext, text5);
			QuickStackConfig.DisplayQuickStackButtons.SettingChanged += delegate
			{
				ButtonRenderer.OnButtonRelevantSettingChanged(plugin);
			};
			QuickStackConfig.HideBaseGamePlaceStacksButton = Config.Bind<bool>(text8, "HideBaseGamePlaceStacksButton", true, ConfigurationManagerAttributes.ForceEnabledDisplay(() => CompatibilitySupport.HasRandyPlugin() == CompatibilitySupport.RandyStatus.EnabledWithQuickSlots, "Whether to hide the 'Place Stacks' button that uses the base game quick stacking logic. Modded buttons are moved automatically based on this setting. Force enabled when using 'Randy's Equipment and Quick Slot' mod."));
			QuickStackConfig.HideBaseGamePlaceStacksButton.SettingChanged += delegate
			{
				ButtonRenderer.OnButtonRelevantSettingChanged(plugin);
			};
			QuickStackConfig.QuickStackHotkeyBehaviorWhenContainerOpen = Config.Bind<QuickStackBehavior>(text8, "QuickStackHotkeyBehaviorWhenContainerOpen", QuickStackBehavior.QuickStackOnlyToCurrentContainer, text4);
			QuickStackConfig.QuickStackIncludesHotkeyBar = Config.Bind<bool>(text8, "QuickStackIncludesHotkeyBar", true, "Whether to also quick stack items from the hotkey bar (" + text3 + ").");
			QuickStackConfig.QuickStackKeybind = Config.Bind<KeyboardShortcut>(text8, "QuickStackKeybind", new KeyboardShortcut((KeyCode)112, Array.Empty<KeyCode>()), "The hotkey to start quick stacking to the current or nearby containers (depending on QuickStackHotkeyBehaviorWhenContainerOpen, " + text2 + ").");
			KeyCodeBackwardsCompatibility(QuickStackConfig.QuickStackKeybind, text8, "QuickStackKey");
			QuickStackConfig.QuickStackToNearbyRange = Config.BindSynced(QuickStackRestockConfig.AreaStackRestockServerSync, text8, "QuickStackToNearbyRange", 10f, ConfigurationManagerAttributes.CustomCategoryWithDescription(category, description));
			QuickStackConfig.QuickStackToNearbyRange.SettingChanged += delegate
			{
				ButtonRenderer.OnButtonRelevantSettingChanged(plugin);
			};
			QuickStackConfig.QuickStackTrophiesIntoSameContainer = Config.Bind<bool>(text8, "QuickStackTrophiesIntoSameContainer", false, "Whether to put all types of trophies in the container if any trophy is found in that container.");
			QuickStackConfig.ShowQuickStackResultMessage