Decompiled source of TidyChests v1.5.0

plugins/TidyChests/TidyChests.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GUIFramework;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Muindor.ServerConfig;
using Muindor.Windows;
using TMPro;
using TidyChests.Compat;
using TidyChests.Containers;
using TidyChests.Find;
using TidyChests.Hud;
using TidyChests.Index;
using TidyChests.Knowledge;
using TidyChests.Restock;
using TidyChests.Sort;
using TidyChests.Stash;
using TidyChests.Ui;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: AssemblyCompany("Egor Fadeev")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Quick stack into nearby chests and restock marked slots, food and arrows from them, a Sort button for the open chest (works with MultiUserChest), a find hotkey, Ctrl+O to search nearby chests, and recipes unlocked by team mates' materials.")]
[assembly: AssemblyFileVersion("1.5.0.0")]
[assembly: AssemblyInformationalVersion("1.5.0+83b717fd24ecc11ef701c15d7850f6bd10da341a")]
[assembly: AssemblyProduct("Tidy Chests")]
[assembly: AssemblyTitle("TidyChests")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.5.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Muindor.Windows
{
	public static class CursorRelease
	{
		public enum Step
		{
			RunVanilla,
			Release,
			SkipVanilla
		}

		public static Step Decide(bool windowOpen, bool cursorFree)
		{
			if (!windowOpen)
			{
				return Step.RunVanilla;
			}
			if (!cursorFree)
			{
				return Step.Release;
			}
			return Step.SkipVanilla;
		}
	}
}
namespace Muindor.ServerConfig
{
	public static class ConfigChannel
	{
		private static ConfigSync? _sync;

		private static ManualLogSource? _log;

		private static string _rpcName = string.Empty;

		public static void Activate(ConfigSync sync, ManualLogSource log)
		{
			_sync = sync;
			_log = log;
			_rpcName = sync.PluginGuid + ".ServerConfig";
			sync.Changed += Broadcast;
		}

		internal static void OnNewConnection(ZNet net, ZNetPeer peer)
		{
			if (_sync != null && !net.IsServer() && peer != null && peer.m_server && peer.m_rpc != null)
			{
				_sync.Clear();
				peer.m_rpc.Register<string>(_rpcName, (Action<ZRpc, string>)Receive);
			}
		}

		internal static void OnPeerInfo(ZNet net, ZRpc rpc)
		{
			if (_sync == null || !net.IsServer())
			{
				return;
			}
			ZNetPeer peer = net.GetPeer(rpc);
			if (peer != null && peer.IsReady() && peer.m_rpc != null)
			{
				peer.m_rpc.Invoke(_rpcName, new object[1] { _sync.BuildPayload().Serialize() });
				ManualLogSource? log = _log;
				if (log != null)
				{
					log.LogInfo((object)("Sent the configuration to " + peer.m_playerName + " (ConfigPriority " + (_sync.Priority.Value ? "on" : "off") + ")"));
				}
			}
		}

		internal static void OnSessionEnd()
		{
			_sync?.Clear();
		}

		internal static void PatchFailed(string patch, Exception exception)
		{
			ManualLogSource? log = _log;
			if (log != null)
			{
				log.LogError((object)$"{patch} failed, the configuration channel may be inactive: {exception}");
			}
		}

		private static void Broadcast()
		{
			ZNet instance = ZNet.instance;
			if (_sync == null || (Object)(object)instance == (Object)null || !instance.IsServer())
			{
				return;
			}
			string text = _sync.BuildPayload().Serialize();
			int num = 0;
			foreach (ZNetPeer peer in instance.GetPeers())
			{
				if (peer.IsReady() && peer.m_rpc != null)
				{
					peer.m_rpc.Invoke(_rpcName, new object[1] { text });
					num++;
				}
			}
			if (num > 0)
			{
				ManualLogSource? log = _log;
				if (log != null)
				{
					log.LogInfo((object)$"A setting changed; sent the configuration to {num} player(s)");
				}
			}
		}

		private static void Receive(ZRpc rpc, string text)
		{
			if (_sync == null)
			{
				return;
			}
			ZNet instance = ZNet.instance;
			ConfigPayload payload;
			string error;
			if ((Object)(object)instance != (Object)null && instance.IsServer())
			{
				ManualLogSource? log = _log;
				if (log != null)
				{
					log.LogWarning((object)"Ignored a configuration sent to this server by a client");
				}
			}
			else if (!ConfigPayload.TryParse(text, out payload, out error))
			{
				ManualLogSource? log2 = _log;
				if (log2 != null)
				{
					log2.LogWarning((object)("Ignored the configuration from the server, keeping the local settings: " + error));
				}
			}
			else
			{
				_sync.Apply(payload);
			}
		}
	}
	[HarmonyPatch(typeof(ZNet), "OnNewConnection")]
	internal static class ZNet_OnNewConnection_Patch
	{
		private static void Postfix(ZNet __instance, ZNetPeer peer)
		{
			try
			{
				ConfigChannel.OnNewConnection(__instance, peer);
			}
			catch (Exception exception)
			{
				ConfigChannel.PatchFailed("OnNewConnection", exception);
			}
		}
	}
	[HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")]
	internal static class ZNet_RPC_PeerInfo_Patch
	{
		private static void Postfix(ZNet __instance, ZRpc rpc)
		{
			try
			{
				ConfigChannel.OnPeerInfo(__instance, rpc);
			}
			catch (Exception exception)
			{
				ConfigChannel.PatchFailed("RPC_PeerInfo", exception);
			}
		}
	}
	[HarmonyPatch(typeof(ZNet), "OnDestroy")]
	internal static class ZNet_OnDestroy_Patch
	{
		private static void Postfix()
		{
			try
			{
				ConfigChannel.OnSessionEnd();
			}
			catch (Exception exception)
			{
				ConfigChannel.PatchFailed("OnDestroy", exception);
			}
		}
	}
	public sealed class ConfigPayload
	{
		public const string Header = "muindor.config/1";

		public string ModVersion { get; }

		public bool Priority { get; }

		public IList<KeyValuePair<string, string>> Values { get; }

		public ConfigPayload(string modVersion, bool priority, IEnumerable<KeyValuePair<string, string>>? values = null)
		{
			ModVersion = modVersion ?? string.Empty;
			Priority = priority;
			List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
			if (values != null)
			{
				list.AddRange(values);
			}
			Values = list;
		}

		public string Serialize()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("muindor.config/1").Append('\n');
			stringBuilder.Append(Escape(ModVersion, escapeEquals: false)).Append('\n');
			stringBuilder.Append(Priority ? "true" : "false").Append('\n');
			foreach (KeyValuePair<string, string> value in Values)
			{
				stringBuilder.Append(Escape(value.Key, escapeEquals: true)).Append('=').Append(Escape(value.Value ?? string.Empty, escapeEquals: false))
					.Append('\n');
			}
			return stringBuilder.ToString();
		}

		public static bool TryParse(string? text, out ConfigPayload? payload, out string error)
		{
			payload = null;
			if (string.IsNullOrEmpty(text))
			{
				error = "the payload is empty";
				return false;
			}
			string[] array = text.Split(new char[1] { '\n' });
			if (array.Length < 3)
			{
				error = "the payload is truncated";
				return false;
			}
			if (Trim(array[0]) != "muindor.config/1")
			{
				error = "unknown format \"" + Trim(array[0]) + "\", expected \"muindor.config/1\"";
				return false;
			}
			string modVersion = Unescape(Trim(array[1]));
			string text2 = Trim(array[2]);
			if (text2 != "true" && text2 != "false")
			{
				error = "\"" + text2 + "\" is not a valid priority flag";
				return false;
			}
			List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
			for (int i = 3; i < array.Length; i++)
			{
				string text3 = Trim(array[i]);
				if (text3.Length != 0)
				{
					int num = IndexOfSeparator(text3);
					if (num < 0)
					{
						error = $"line {i + 1} has no key/value separator";
						return false;
					}
					string text4 = Unescape(text3.Substring(0, num));
					if (text4.Length == 0)
					{
						error = $"line {i + 1} has an empty key";
						return false;
					}
					list.Add(new KeyValuePair<string, string>(text4, Unescape(text3.Substring(num + 1))));
				}
			}
			payload = new ConfigPayload(modVersion, text2 == "true", list);
			error = string.Empty;
			return true;
		}

		private static string Trim(string line)
		{
			if (!line.EndsWith("\r", StringComparison.Ordinal))
			{
				return line;
			}
			return line.Substring(0, line.Length - 1);
		}

		private static int IndexOfSeparator(string line)
		{
			for (int i = 0; i < line.Length; i++)
			{
				if (line[i] == '\\')
				{
					i++;
				}
				else if (line[i] == '=')
				{
					return i;
				}
			}
			return -1;
		}

		private static string Escape(string value, bool escapeEquals)
		{
			StringBuilder stringBuilder = new StringBuilder(value.Length);
			foreach (char c in value)
			{
				switch (c)
				{
				case '\\':
					stringBuilder.Append("\\\\");
					continue;
				case '\n':
					stringBuilder.Append("\\n");
					continue;
				case '\r':
					stringBuilder.Append("\\r");
					continue;
				case '=':
					if (escapeEquals)
					{
						stringBuilder.Append("\\=");
						continue;
					}
					break;
				}
				stringBuilder.Append(c);
			}
			return stringBuilder.ToString();
		}

		private static string Unescape(string value)
		{
			if (value.IndexOf('\\') < 0)
			{
				return value;
			}
			StringBuilder stringBuilder = new StringBuilder(value.Length);
			for (int i = 0; i < value.Length; i++)
			{
				if (value[i] != '\\' || i + 1 >= value.Length)
				{
					stringBuilder.Append(value[i]);
					continue;
				}
				char c = value[++i];
				switch (c)
				{
				case 'n':
					stringBuilder.Append('\n');
					break;
				case 'r':
					stringBuilder.Append('\r');
					break;
				default:
					stringBuilder.Append(c);
					break;
				}
			}
			return stringBuilder.ToString();
		}
	}
	public sealed class ConfigSync
	{
		private const string SyncedNote = "[synced] ";

		private readonly Dictionary<string, ISyncedEntry> _byKey = new Dictionary<string, ISyncedEntry>(StringComparer.Ordinal);

		private readonly List<ISyncedEntry> _entries = new List<ISyncedEntry>();

		private readonly HashSet<ConfigEntryBase> _watched = new HashSet<ConfigEntryBase>();

		private readonly ConfigFile _config;

		private readonly ManualLogSource _log;

		public string PluginGuid { get; }

		public string ModName { get; }

		public string ModVersion { get; }

		public ConfigEntry<bool> Priority { get; }

		public bool Locked { get; private set; }

		public string? ServerVersion { get; private set; }

		public int LockedCount { get; private set; }

		public event Action? Changed;

		public ConfigSync(ConfigFile config, string pluginGuid, string modName, string modVersion, ManualLogSource log)
		{
			_config = config;
			_log = log;
			PluginGuid = pluginGuid;
			ModName = modName;
			ModVersion = modVersion;
			Priority = config.Bind<bool>("Server", "ConfigPriority", false, "Server only, and off by default. Turn it on in the configuration of a dedicated server, or of the player hosting the session, to have every client that also has the mod run on the settings marked [synced] below instead of its own. The clients' own config files are never touched: their settings come back the moment they disconnect. This never makes the mod required on either side - players without it are unaffected, and a player with it can still join a server that does not have it.");
			_watched.Add((ConfigEntryBase)(object)Priority);
			config.SettingChanged += OnSettingChanged;
		}

		public SyncedEntry<T> Bind<T>(string section, string key, T defaultValue, string description)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			return Bind(section, key, defaultValue, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()));
		}

		public SyncedEntry<T> Bind<T>(string section, string key, T defaultValue, ConfigDescription description)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			ConfigDescription val = new ConfigDescription("[synced] " + description.Description, description.AcceptableValues, description.Tags);
			ConfigEntry<T> val2 = _config.Bind<T>(section, key, defaultValue, val);
			SyncedEntry<T> syncedEntry = new SyncedEntry<T>(val2);
			_byKey.Add(syncedEntry.Key, syncedEntry);
			_entries.Add(syncedEntry);
			_watched.Add((ConfigEntryBase)(object)val2);
			return syncedEntry;
		}

		public ConfigPayload BuildPayload()
		{
			bool value = Priority.Value;
			List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>(value ? _entries.Count : 0);
			if (value)
			{
				foreach (ISyncedEntry entry in _entries)
				{
					try
					{
						list.Add(new KeyValuePair<string, string>(entry.Key, entry.LocalAsString()));
					}
					catch (Exception ex)
					{
						_log.LogWarning((object)(entry.Key + " could not be sent to the clients: " + ex.Message));
					}
				}
			}
			return new ConfigPayload(ModVersion, value, list);
		}

		public void Apply(ConfigPayload payload)
		{
			ClearValues();
			if (!payload.Priority)
			{
				Locked = false;
				ServerVersion = null;
				LockedCount = 0;
				_log.LogInfo((object)("The server runs " + ModName + " " + payload.ModVersion + " with ConfigPriority off; keeping the local settings"));
				return;
			}
			int num = 0;
			List<string> list = new List<string>();
			foreach (KeyValuePair<string, string> value2 in payload.Values)
			{
				string error;
				if (!_byKey.TryGetValue(value2.Key, out ISyncedEntry value))
				{
					list.Add(value2.Key);
				}
				else if (value.ApplyServerValue(value2.Value, out error))
				{
					num++;
				}
				else
				{
					_log.LogWarning((object)("Keeping the local " + value2.Key + ": the server sent a value this version cannot read, " + error));
				}
			}
			Locked = true;
			ServerVersion = payload.ModVersion;
			LockedCount = num;
			int num2 = _entries.Count - num;
			string text = ((list.Count > 0) ? string.Format(", {0} unknown here ({1})", list.Count, string.Join(", ", list.ToArray())) : string.Empty);
			string text2 = ((num2 > 0) ? $", {num2} kept local" : string.Empty);
			_log.LogInfo((object)$"The server ({ModName} {payload.ModVersion}) decides the settings: {num} applied{text2}{text}");
		}

		public void Clear()
		{
			if (Locked || LockedCount != 0)
			{
				ClearValues();
				Locked = false;
				ServerVersion = null;
				LockedCount = 0;
				_log.LogInfo((object)"Back to the local settings");
			}
		}

		public string Describe()
		{
			if (!Locked)
			{
				return "local settings";
			}
			return $"settings from the server ({ModName} {ServerVersion}, {LockedCount} values)";
		}

		private void ClearValues()
		{
			foreach (ISyncedEntry entry in _entries)
			{
				entry.ClearServerValue();
			}
		}

		private void OnSettingChanged(object sender, SettingChangedEventArgs args)
		{
			if (this.Changed != null)
			{
				ConfigEntryBase changedSetting = args.ChangedSetting;
				if (changedSetting != null && _watched.Contains(changedSetting))
				{
					this.Changed();
				}
			}
		}
	}
	public interface ISyncedEntry
	{
		string Key { get; }

		string LocalAsString();

		bool ApplyServerValue(string text, out string error);

		void ClearServerValue();
	}
	public sealed class SyncedEntry<T> : ISyncedEntry
	{
		private T _serverValue;

		private bool _hasServerValue;

		public ConfigEntry<T> Local { get; }

		public string Key { get; }

		public T Value
		{
			get
			{
				if (!_hasServerValue)
				{
					return Local.Value;
				}
				return _serverValue;
			}
		}

		public T LocalValue
		{
			get
			{
				return Local.Value;
			}
			set
			{
				Local.Value = value;
			}
		}

		public bool IsLocked => _hasServerValue;

		internal SyncedEntry(ConfigEntry<T> local)
		{
			Local = local;
			Key = ((ConfigEntryBase)local).Definition.Section + "." + ((ConfigEntryBase)local).Definition.Key;
		}

		public string LocalAsString()
		{
			return TomlTypeConverter.ConvertToString((object)Local.Value, typeof(T));
		}

		public bool ApplyServerValue(string text, out string error)
		{
			object obj;
			try
			{
				obj = TomlTypeConverter.ConvertToValue(text, typeof(T));
			}
			catch (Exception ex)
			{
				error = "\"" + text + "\" is not a valid " + typeof(T).Name + " (" + ex.Message + ")";
				return false;
			}
			ConfigDescription description = ((ConfigEntryBase)Local).Description;
			AcceptableValueBase val = ((description != null) ? description.AcceptableValues : null);
			if (val != null && !val.IsValid(obj))
			{
				obj = val.Clamp(obj);
			}
			_serverValue = (T)obj;
			_hasServerValue = true;
			error = string.Empty;
			return true;
		}

		public void ClearServerValue()
		{
			_hasServerValue = false;
			_serverValue = default(T);
		}

		public override string ToString()
		{
			T value = Value;
			return ((value != null) ? value.ToString() : null) ?? string.Empty;
		}
	}
}
namespace TidyChests
{
	public sealed class ModConfig
	{
		private static readonly string[] ItemTypeNames = Enum.GetNames(typeof(ItemType));

		public const string DefaultItemTypes = "Material, Consumable, Ammo, AmmoNonEquipable, Trophy, Misc, Fish";

		private readonly ConfigFile _config;

		public ConfigSync Sync { get; }

		public SyncedEntry<bool> Enabled { get; }

		public ConfigEntry<bool> IsDebug { get; }

		public SyncedEntry<float> Radius { get; }

		public SyncedEntry<bool> IncludeHotbar { get; }

		public SyncedEntry<string> ItemTypes { get; }

		public SyncedEntry<string> Blacklist { get; }

		public ConfigEntry<bool> ShowMessage { get; }

		public ConfigEntry<bool> PlaceInSortOrder { get; }

		public ConfigEntry<KeyCode> RevealKey { get; }

		public ConfigEntry<KeyboardShortcut> LockItemKey { get; }

		public ConfigEntry<KeyboardShortcut> LockSlotKey { get; }

		public ConfigEntry<string> LockedItems { get; }

		public ConfigEntry<string> LockedSlots { get; }

		public ConfigEntry<bool> ShowRestockButton { get; }

		public ConfigEntry<Vector2> RestockButtonOffset { get; }

		public ConfigEntry<KeyboardShortcut> RestockSlotKey { get; }

		public ConfigEntry<string> RestockSlots { get; }

		public ConfigEntry<int> HalfPercent { get; }

		public ConfigEntry<int> ModSlotFood { get; }

		public ConfigEntry<int> ModSlotMeads { get; }

		public ConfigEntry<int> ModSlotAmmo { get; }

		public ConfigEntry<int> ModSlotOther { get; }

		public ConfigEntry<KeyboardShortcut> FindKey { get; }

		public ConfigEntry<float> HighlightDuration { get; }

		public ConfigEntry<bool> ScreenMarker { get; }

		public ConfigEntry<bool> Light { get; }

		public ConfigEntry<bool> Glow { get; }

		public ConfigEntry<bool> CloseInventory { get; }

		public ConfigEntry<bool> ShowButton { get; }

		public ConfigEntry<Vector2> ButtonOffset { get; }

		public ConfigEntry<Vector2> ButtonSize { get; }

		public ConfigEntry<bool> ShowSortButton { get; }

		public ConfigEntry<ChestSortOrder> SortOrder { get; }

		public ConfigEntry<ChestSortLayout> SortLayout { get; }

		public ConfigEntry<Vector2> SortButtonOffset { get; }

		public SyncedEntry<float> ScanRadius { get; }

		public SyncedEntry<float> ScanInterval { get; }

		public SyncedEntry<bool> LearnFromChests { get; }

		public ConfigEntry<KeyboardShortcut> BrowserKey { get; }

		public ConfigEntry<Vector2> BrowserSize { get; }

		public ConfigEntry<BrowserSort> Sort { get; }

		public ConfigEntry<string> Favorites { get; }

		public ModConfig(ConfigFile config)
		{
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Expected O, but got Unknown
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e1: Expected O, but got Unknown
			//IL_0306: Unknown result type (might be due to invalid IL or missing references)
			//IL_0310: Expected O, but got Unknown
			//IL_0334: Unknown result type (might be due to invalid IL or missing references)
			//IL_033e: Expected O, but got Unknown
			//IL_0363: Unknown result type (might be due to invalid IL or missing references)
			//IL_036d: Expected O, but got Unknown
			//IL_0391: Unknown result type (might be due to invalid IL or missing references)
			//IL_039b: Expected O, but got Unknown
			//IL_03b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fb: Expected O, but got Unknown
			//IL_04a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0540: Unknown result type (might be due to invalid IL or missing references)
			//IL_0583: Unknown result type (might be due to invalid IL or missing references)
			//IL_058d: Expected O, but got Unknown
			//IL_05c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_05cb: Expected O, but got Unknown
			//IL_060d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0637: Unknown result type (might be due to invalid IL or missing references)
			_config = config;
			string text = string.Join(", ", ItemTypeNames);
			Sync = new ConfigSync(config, "muindor.TidyChests", "Tidy Chests", "1.5.0", Plugin.Log);
			Enabled = Sync.Bind("General", "Enabled", defaultValue: true, "Enable this mod: the Stash button and the find key.");
			IsDebug = config.Bind<bool>("General", "IsDebug", false, "Log every item decision and every chest that is considered when stashing.");
			Radius = Sync.Bind("Stash", "Radius", 10f, new ConfigDescription("Chests within this many metres of the player are used, both by the Stash button and by the find key.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 20f), Array.Empty<object>()));
			IncludeHotbar = Sync.Bind("Stash", "IncludeHotbar", defaultValue: false, "Also stash items from the first inventory row (the hotbar).");
			ItemTypes = Sync.Bind("Stash", "ItemTypes", "Material, Consumable, Ammo, AmmoNonEquipable, Trophy, Misc, Fish", "Item types that may be stashed (comma-separated). Equipment, tools and weapons are left out by default. Valid types: " + text);
			Blacklist = Sync.Bind("Stash", "Blacklist", "", "Items that are never stashed (comma-separated). Use prefab names or item names, for example: Wood, $item_coal, Resin");
			ShowMessage = config.Bind<bool>("Stash", "ShowMessage", true, "Show a message with the result after stashing.");
			PlaceInSortOrder = config.Bind<bool>("Stash", "PlaceInSortOrder", true, "When the Stash button needs an empty cell in a chest, pick the one where the item fits [Sort] SortOrder and SortLayout best, next to the same item when there is room. Nothing already in the chest is moved; only the Sort button does that. Off: the first empty cell, like the game's own buttons.");
			RevealKey = config.Bind<KeyCode>("Locks", "RevealKey", (KeyCode)304, "Hold this key with the inventory open to see the locks: a grey padlock on a locked item, a red one on a locked slot. Pointing at a slot while holding it shows the lock keys.");
			LockItemKey = config.Bind<KeyboardShortcut>("Locks", "LockItemKey", new KeyboardShortcut((KeyCode)108, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "With the inventory open, point at an item and press this to lock or unlock it: a locked item is never stashed, wherever it lies. Modifiers are allowed.");
			LockSlotKey = config.Bind<KeyboardShortcut>("Locks", "LockSlotKey", new KeyboardShortcut((KeyCode)107, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "With the inventory open, point at a slot and press this to lock or unlock it: whatever lies in a locked slot is never stashed. Modifiers are allowed.");
			LockedItems = config.Bind<string>("Locks", "LockedItems", "", "Items locked with the lock key, comma-separated, saved here as you press it. The names are the game's own item names: $item_wood, $item_coal");
			LockedSlots = config.Bind<string>("Locks", "LockedSlots", "", "Inventory slots locked with the lock key, comma-separated as column:row counted from 0, the top row (the hotbar) being row 0: 0:1, 7:3. Saved here as you press the key.");
			ShowRestockButton = config.Bind<bool>("Restock", "ShowRestockButton", true, "Show the Restock button in the inventory, under the Stash button. It fills the marked slots and the slot mods' slots from the chests within [Stash] Radius. The console command 'tidychests restock' works without it.");
			RestockButtonOffset = config.Bind<Vector2>("Restock", "RestockButtonOffset", new Vector2(0f, -42f), "Position of the Restock button relative to the Stash button, in UI pixels (x right, y up). It has the Stash button's size.");
			RestockSlotKey = config.Bind<KeyboardShortcut>("Restock", "RestockSlotKey", new KeyboardShortcut((KeyCode)114, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "With the inventory open, point at a slot and press this to mark it for the Restock button: the first press keeps a full stack there, the second HalfPercent of a stack, the third removes the mark. Hold [Locks] RevealKey to see the marks: a green arrow for a full stack, a red one for less. Modifiers are allowed.");
			RestockSlots = config.Bind<string>("Restock", "RestockSlots", "", "Slots marked with the restock key, comma-separated as column:row=percent, then the item last seen there so an emptied slot is refilled with it: 0:1=100:$item_arrow_wood, 3:2=50:$item_cookedmeat. Rows are counted from 0, the top row (the hotbar) being row 0. Saved here as you press the key. What lies in a marked slot is never stashed.");
			HalfPercent = config.Bind<int>("Restock", "HalfPercent", 50, new ConfigDescription("The second press of the restock key keeps this many percent of a stack in the slot.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 99), Array.Empty<object>()));
			ModSlotFood = config.Bind<int>("Restock", "ModSlotFood", 50, new ConfigDescription("Food lying in a slot mod's slot (Extra Slots quick and food slots, EquipmentAndQuickSlots quick slots) is kept at this many percent of a stack. 0 leaves it alone.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			ModSlotMeads = config.Bind<int>("Restock", "ModSlotMeads", 0, new ConfigDescription("Meads and other consumables that do not feed, lying in a slot mod's slot, are kept at this many percent of a stack. 0 leaves them alone.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			ModSlotAmmo = config.Bind<int>("Restock", "ModSlotAmmo", 100, new ConfigDescription("Arrows, bolts and other ammo lying in a slot mod's slot (Extra Slots ammo and quick slots, the Better Archery quiver) are kept at this many percent of a stack. 0 leaves them alone.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			ModSlotOther = config.Bind<int>("Restock", "ModSlotOther", 0, new ConfigDescription("Any other stackable item lying in a slot mod's slot is kept at this many percent of a stack. 0 leaves it alone.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			FindKey = config.Bind<KeyboardShortcut>("Find", "FindKey", new KeyboardShortcut((KeyCode)116, Array.Empty<KeyCode>()), "With the inventory open, point at an item (in the inventory, or an ingredient or recipe in the crafting panel) and press this key: the inventory closes and every chest in range that holds the item is highlighted. Modifiers are allowed, e.g. \"T + LeftControl\".");
			HighlightDuration = config.Bind<float>("Find", "HighlightDuration", 8f, new ConfigDescription("Seconds the found chests stay highlighted.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 60f), Array.Empty<object>()));
			ScreenMarker = config.Bind<bool>("Find", "ScreenMarker", true, "Draw an arrow with the item count and the distance over each found chest (at the screen edge when the chest is out of view).");
			Light = config.Bind<bool>("Find", "Light", true, "Light up each found chest with a pulsing light.");
			Glow = config.Bind<bool>("Find", "Glow", true, "Tint each found chest with an emissive glow. Only works for materials whose shader has an emission colour.");
			CloseInventory = config.Bind<bool>("Find", "CloseInventory", true, "Close the inventory when chests are found, so the highlights are visible right away. When nothing is found the inventory stays open.");
			ShowButton = config.Bind<bool>("Button", "ShowButton", true, "Show the Stash button in the inventory. The console command 'tidychests stash' works without it.");
			ButtonOffset = config.Bind<Vector2>("Button", "ButtonOffset", new Vector2(41f, -56f), "Position of the Stash button relative to the weight display of the inventory panel, in UI pixels (x right, y up).");
			ButtonSize = config.Bind<Vector2>("Button", "ButtonSize", new Vector2(120f, 38f), "Width and height of the Stash button in UI pixels.");
			ShowSortButton = config.Bind<bool>("Sort", "ShowSortButton", true, "Show the Sort button on the chest panel. It sorts the open chest only, and only when pressed. The console command 'tidychests sort' works without it.");
			SortOrder = config.Bind<ChestSortOrder>("Sort", "SortOrder", ChestSortOrder.Id, "Order of the items in a sorted chest. Id: by the item's prefab name (Coal, Stone, Wood), the same in every language. Name: by the name shown in the current language. Type: weapons, shields, tools, armour, ammo, food, materials, trophies, then the rest, each group by Id. The better quality and the higher world level come first within the same item.");
			SortLayout = config.Bind<ChestSortLayout>("Sort", "SortLayout", ChestSortLayout.Columns, "How a sorted chest is laid out. Columns: every item starts a new column, filled top to bottom. Rows: every item starts a new row, filled left to right. Sequential: everything packed left to right with no gaps. When there are more items than columns (or rows), the rest is packed without gaps.");
			SortButtonOffset = config.Bind<Vector2>("Sort", "SortButtonOffset", Vector2.zero, "Shift of the Sort button from its own place, next to the chest panel's \"stack all\" button, in UI pixels (x right, y up).");
			ScanRadius = Sync.Bind("Scan", "ScanRadius", 50f, new ConfigDescription("Chests within this many metres are read by the chest list and by the knowledge scan. Reading costs nothing on the network: the game already keeps the contents of every loaded chest on your client. Above roughly 90 m the chests are no longer loaded, so nothing more is found.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 90f), Array.Empty<object>()));
			ScanInterval = Sync.Bind("Scan", "ScanInterval", 5f, new ConfigDescription("Seconds between two scans of the chests in range. Chests whose contents did not change are skipped, so a short interval is cheap.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 60f), Array.Empty<object>()));
			LearnFromChests = Sync.Bind("Knowledge", "LearnFromChests", defaultValue: true, "Count the items lying in the chests in range as found, so their recipes unlock without carrying every stack yourself. Meant for co-op, where a team mate gathers a material you have never held. Trophies count too. This cannot be undone: turning the option off later does not lock a recipe again.");
			BrowserKey = config.Bind<KeyboardShortcut>("Browser", "BrowserKey", new KeyboardShortcut((KeyCode)111, (KeyCode[])(object)new KeyCode[1] { (KeyCode)306 }), "Opens and closes the list of everything in the chests in range, with a search box. Modifiers are allowed; set it to \"None\" to disable the panel.");
			BrowserSize = config.Bind<Vector2>("Browser", "BrowserSize", new Vector2(520f, 560f), "Width and height of the chest list panel in UI pixels.");
			Sort = config.Bind<BrowserSort>("Browser", "Sort", BrowserSort.CountDescending, "Order of the chest list while its search box is empty. Click the Name or Count header in the list to change it, and click the active one again to flip it; the choice is saved here. While something is typed in the search box the best matches come first and this decides the order among equally good ones.");
			Favorites = config.Bind<string>("Browser", "Favorites", "", "Items pinned to the top of the chest list, comma-separated. Click the diamond on the left of a row to pin or unpin it; the list is saved here as you click. A pinned item stays in the list even when no chest in range holds it any more, shown with a count of 0, so you can see that it ran out. Pinning is ignored while you are searching. The names are the game's own item names: $item_wood, $item_coal, $item_ironscrap");
		}

		public void Reload()
		{
			_config.Reload();
		}

		public StashRules BuildRules()
		{
			return StashRules.Parse(new StashRuleSettings
			{
				IncludeHotbar = IncludeHotbar.Value,
				ItemTypes = ItemTypes.Value,
				Blacklist = Blacklist.Value,
				LockedItems = LockedItems.Value,
				LockedSlots = LockedSlots.Value,
				RestockSlots = RestockSlots.Value
			}, ItemTypeNames, delegate(string warning)
			{
				Plugin.Log.LogWarning((object)warning);
			});
		}

		public StashLocks BuildLocks()
		{
			return StashLocks.Parse(LockedItems.Value, LockedSlots.Value);
		}

		public void SaveLocks(StashLocks locks)
		{
			LockedItems.Value = locks.FormatItems();
			LockedSlots.Value = locks.FormatSlots();
		}

		public RestockMarks BuildRestockMarks()
		{
			return RestockMarks.Parse(RestockSlots.Value);
		}

		public void SaveRestockMarks(RestockMarks marks)
		{
			string text = marks.Format();
			if (text != RestockSlots.Value)
			{
				RestockSlots.Value = text;
			}
		}

		public RestockLevels BuildRestockLevels()
		{
			return new RestockLevels(ModSlotFood.Value, ModSlotMeads.Value, ModSlotAmmo.Value, ModSlotOther.Value);
		}

		public HighlightOptions ToHighlightOptions()
		{
			return new HighlightOptions(HighlightDuration.Value, Light.Value, Glow.Value);
		}

		public string Describe()
		{
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			CultureInfo invariantCulture = CultureInfo.InvariantCulture;
			return (Enabled.Value ? "enabled" : "disabled") + ", radius " + Radius.Value.ToString("0.#", invariantCulture) + " m, hotbar " + (IncludeHotbar.Value ? "included" : "excluded") + ", " + BuildRules().Describe() + ", new stacks " + (PlaceInSortOrder.Value ? "in sort order" : "in the first empty cell") + ", " + string.Format("restock button {0}, restock key {1} (half {2}%), {3}, ", ShowRestockButton.Value ? "shown" : "hidden", RestockSlotKey.Value, HalfPercent.Value, BuildRestockLevels().Describe()) + string.Format("find key {0}, lock keys {1} / {2} (shown while {3} is held), highlight {4} s, ", FindKey.Value, LockItemKey.Value, LockSlotKey.Value, RevealKey.Value, HighlightDuration.Value.ToString("0.#", invariantCulture)) + "button " + (ShowButton.Value ? "shown" : "hidden") + ", " + string.Format("sort button {0} ({1}, {2}), ", ShowSortButton.Value ? "shown" : "hidden", SortOrder.Value, SortLayout.Value) + "scan " + ScanRadius.Value.ToString("0.#", invariantCulture) + " m every " + ScanInterval.Value.ToString("0.#", invariantCulture) + " s, " + string.Format("learning from chests {0}, browser key {1}, ", LearnFromChests.Value ? "on" : "off", BrowserKey.Value) + $"list sorted by {Sort.Value}, {FavoriteList.Parse(Favorites.Value).Count} pinned, {Sync.Describe()}";
		}
	}
	[BepInPlugin("muindor.TidyChests", "Tidy Chests", "1.5.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		private Harmony? _harmony;

		public static ManualLogSource Log { get; private set; } = null;

		public static ModConfig Settings { get; private set; } = null;

		public static ChestFinder? Finder { get; private set; }

		public static ChestBrowser? Browser { get; private set; }

		public static KnowledgeScanner? Scanner { get; private set; }

		internal static ChestIndex Index { get; } = new ChestIndex();

		public static bool Enabled
		{
			get
			{
				if (Settings != null)
				{
					return Settings.Enabled.Value;
				}
				return false;
			}
		}

		private void Awake()
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Settings = new ModConfig(((BaseUnityPlugin)this).Config);
			ConfigChannel.Activate(Settings.Sync, Log);
			Finder = ((Component)this).gameObject.AddComponent<ChestFinder>();
			Browser = ((Component)this).gameObject.AddComponent<ChestBrowser>();
			Scanner = ((Component)this).gameObject.AddComponent<KnowledgeScanner>();
			_harmony = new Harmony("muindor.TidyChests");
			_harmony.PatchAll(typeof(Plugin).Assembly);
			Translations.ApplyIfLoaded();
			Log.LogInfo((object)("Tidy Chests 1.5.0 loaded: " + Settings.Describe()));
			SlotMods.Report();
			ChestMods.Report();
		}

		private void OnDestroy()
		{
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		public static void Debug(string message)
		{
			if (Settings != null && Settings.IsDebug.Value)
			{
				Log.LogInfo((object)message);
			}
		}
	}
	internal static class Shortcut
	{
		public static bool IsPressed(KeyboardShortcut shortcut)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			if (!IsTyping())
			{
				return WentDown(shortcut);
			}
			return false;
		}

		public static bool IsPressedWhileSearching(KeyboardShortcut shortcut)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			if (!IsGameTextFieldOpen())
			{
				return WentDown(shortcut);
			}
			return false;
		}

		public static bool IsTyping()
		{
			if (!IsGameTextFieldOpen())
			{
				return ChestBrowser.IsSearchFocused;
			}
			return true;
		}

		private static bool WentDown(KeyboardShortcut shortcut)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0 || !ZInput.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey, false))
			{
				return false;
			}
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers)
			{
				if (!ZInput.GetKey(modifier, false))
				{
					return false;
				}
			}
			return true;
		}

		private static bool IsGameTextFieldOpen()
		{
			if (!Console.IsVisible() && !TextInput.IsVisible())
			{
				if ((Object)(object)Chat.instance != (Object)null)
				{
					return Chat.instance.HasFocus();
				}
				return false;
			}
			return true;
		}
	}
	internal static class Translations
	{
		public const string Button = "tidychests_button";

		public const string Stashed = "tidychests_stashed";

		public const string Nothing = "tidychests_nothing";

		public const string NoChests = "tidychests_no_chests";

		public const string Found = "tidychests_found";

		public const string NotFound = "tidychests_not_found";

		public const string Hover = "tidychests_hover";

		public const string LockTopic = "tidychests_lock_topic";

		public const string LockHint = "tidychests_lock_hint";

		public const string LockStateOn = "tidychests_lock_on";

		public const string LockStateOff = "tidychests_lock_off";

		public const string ItemLocked = "tidychests_item_locked";

		public const string ItemUnlocked = "tidychests_item_unlocked";

		public const string SlotLocked = "tidychests_slot_locked";

		public const string SlotUnlocked = "tidychests_slot_unlocked";

		public const string BrowserTitle = "tidychests_browser_title";

		public const string BrowserSearch = "tidychests_browser_search";

		public const string BrowserChests = "tidychests_browser_chests";

		public const string BrowserEmpty = "tidychests_browser_empty";

		public const string BrowserNoMatch = "tidychests_browser_no_match";

		public const string BrowserMissing = "tidychests_browser_missing";

		public const string SortName = "tidychests_sort_name";

		public const string SortNameUp = "tidychests_sort_name_up";

		public const string SortNameDown = "tidychests_sort_name_down";

		public const string SortCount = "tidychests_sort_count";

		public const string SortCountUp = "tidychests_sort_count_up";

		public const string SortCountDown = "tidychests_sort_count_down";

		public const string SortLabel = "tidychests_sort_button";

		public const string SortInUse = "tidychests_sort_in_use";

		public const string RestockLabel = "tidychests_restock_button";

		public const string Restocked = "tidychests_restocked";

		public const string RestockStocked = "tidychests_restock_stocked";

		public const string RestockNotFound = "tidychests_restock_not_found";

		public const string RestockNoSlots = "tidychests_restock_no_slots";

		public const string RestockSlot = "tidychests_restock_slot";

		public const string RestockStateFull = "tidychests_restock_full";

		public const string RestockStatePart = "tidychests_restock_part";

		public const string RestockStateOff = "tidychests_restock_off";

		private const string DefaultLanguage = "English";

		private static readonly Dictionary<string, Dictionary<string, string>> Words = new Dictionary<string, Dictionary<string, string>>
		{
			["English"] = new Dictionary<string, string>
			{
				["tidychests_button"] = "Stash",
				["tidychests_stashed"] = "Stashed {0} items into {1} chests",
				["tidychests_nothing"] = "Nothing to stash: no chest nearby holds these items",
				["tidychests_no_chests"] = "No usable chest within {0} m",
				["tidychests_found"] = "{0}: found in {1} chests",
				["tidychests_not_found"] = "{0}: not in any chest within {1} m",
				["tidychests_hover"] = "Point at an item in the inventory or the crafting panel and press {0} to find it in nearby chests",
				["tidychests_lock_topic"] = "Locks and restock",
				["tidychests_lock_hint"] = "Item: {0} [{1}]\nSlot: {2} [{3}]\nRestock: {4} [{5}]",
				["tidychests_lock_on"] = "locked",
				["tidychests_lock_off"] = "not locked",
				["tidychests_item_locked"] = "{0}: locked, the Stash button leaves it",
				["tidychests_item_unlocked"] = "{0}: unlocked",
				["tidychests_slot_locked"] = "Slot locked: whatever lies here stays",
				["tidychests_slot_unlocked"] = "Slot unlocked",
				["tidychests_browser_title"] = "Chests nearby",
				["tidychests_browser_search"] = "Search by name",
				["tidychests_browser_chests"] = "chests: {0} · {1} m",
				["tidychests_browser_empty"] = "No chest within {0} m holds anything",
				["tidychests_browser_no_match"] = "Nothing matches \"{0}\"",
				["tidychests_browser_missing"] = "none nearby",
				["tidychests_sort_name"] = "Name",
				["tidychests_sort_name_up"] = "Name A-Z",
				["tidychests_sort_name_down"] = "Name Z-A",
				["tidychests_sort_count"] = "Count",
				["tidychests_sort_count_up"] = "Count 1-9",
				["tidychests_sort_count_down"] = "Count 9-1",
				["tidychests_sort_button"] = "Sort",
				["tidychests_sort_in_use"] = "Another player has this chest open: it cannot be sorted now",
				["tidychests_restock_button"] = "Restock",
				["tidychests_restocked"] = "Restocked {0} items into {1} slots",
				["tidychests_restock_stocked"] = "Everything is stocked",
				["tidychests_restock_not_found"] = "Nothing to restock with: no chest within {0} m holds these items",
				["tidychests_restock_no_slots"] = "Nothing to restock: point at a slot and press {0} to mark it",
				["tidychests_restock_slot"] = "Restock: {0}",
				["tidychests_restock_full"] = "full stack",
				["tidychests_restock_part"] = "{0}% of a stack",
				["tidychests_restock_off"] = "off"
			},
			["Russian"] = new Dictionary<string, string>
			{
				["tidychests_button"] = "Убрать",
				["tidychests_stashed"] = "Убрано предметов: {0}, в сундуков: {1}",
				["tidychests_nothing"] = "Нечего убирать: поблизости нет сундуков с такими предметами",
				["tidychests_no_chests"] = "В радиусе {0} м нет подходящих сундуков",
				["tidychests_found"] = "{0}: есть в сундуках ({1})",
				["tidychests_not_found"] = "{0}: нет ни в одном сундуке в радиусе {1} м",
				["tidychests_hover"] = "Наведите курсор на предмет в инвентаре или в крафте и нажмите {0}, чтобы найти его в сундуках",
				["tidychests_lock_topic"] = "Замки и пополнение",
				["tidychests_lock_hint"] = "Предмет: {0} [{1}]\nЯчейка: {2} [{3}]\nПополнение: {4} [{5}]",
				["tidychests_lock_on"] = "под замком",
				["tidychests_lock_off"] = "без замка",
				["tidychests_item_locked"] = "{0}: заперт, кнопка «Убрать» его не тронет",
				["tidychests_item_unlocked"] = "{0}: отперт",
				["tidychests_slot_locked"] = "Ячейка заперта: всё, что в ней лежит, остаётся",
				["tidychests_slot_unlocked"] = "Ячейка отперта",
				["tidychests_browser_title"] = "Сундуки рядом",
				["tidychests_browser_search"] = "Поиск по названию",
				["tidychests_browser_chests"] = "сундуков: {0} · {1} м",
				["tidychests_browser_empty"] = "В радиусе {0} м нет сундуков с предметами",
				["tidychests_browser_no_match"] = "Ничего не найдено по запросу «{0}»",
				["tidychests_browser_missing"] = "рядом нет",
				["tidychests_sort_name"] = "Название",
				["tidychests_sort_name_up"] = "Название А-Я",
				["tidychests_sort_name_down"] = "Название Я-А",
				["tidychests_sort_count"] = "Количество",
				["tidychests_sort_count_up"] = "Количество 1-9",
				["tidychests_sort_count_down"] = "Количество 9-1",
				["tidychests_sort_button"] = "Сортировать",
				["tidychests_sort_in_use"] = "Сундук открыт другим игроком: сейчас его не отсортировать",
				["tidychests_restock_button"] = "Пополнить",
				["tidychests_restocked"] = "Пополнено предметов: {0}, ячеек: {1}",
				["tidychests_restock_stocked"] = "Всё уже пополнено",
				["tidychests_restock_not_found"] = "Нечем пополнить: в сундуках в радиусе {0} м этого нет",
				["tidychests_restock_no_slots"] = "Нечего пополнять: наведите курсор на ячейку и нажмите {0}",
				["tidychests_restock_slot"] = "Пополнение: {0}",
				["tidychests_restock_full"] = "полный стак",
				["tidychests_restock_part"] = "{0}% стака",
				["tidychests_restock_off"] = "выключено"
			}
		};

		public static string Get(string key, params object[] args)
		{
			string text = Localization.instance.Localize("$" + key);
			if (args.Length != 0)
			{
				return string.Format(text, args);
			}
			return text;
		}

		public static void ApplyIfLoaded()
		{
			Localization instance = Localization.m_instance;
			if (instance != null)
			{
				Apply(instance, instance.GetSelectedLanguage());
			}
		}

		public static void Apply(Localization localization, string language)
		{
			Dictionary<string, string> dictionary = Words["English"];
			Words.TryGetValue(language ?? "", out Dictionary<string, string> value);
			foreach (KeyValuePair<string, string> item in dictionary)
			{
				string value2;
				string text = ((value != null && value.TryGetValue(item.Key, out value2)) ? value2 : item.Value);
				localization.AddWord(item.Key, text);
			}
		}
	}
	[HarmonyPatch(typeof(Localization), "SetupLanguage")]
	internal static class Localization_SetupLanguage_Patch
	{
		private static void Postfix(Localization __instance, string language)
		{
			Translations.Apply(__instance, language);
			StashButton.RefreshLabel();
			RestockButton.RefreshLabel();
			SortButton.RefreshLabel();
			ChestBrowser.RefreshLabels();
			Plugin.Index.Clear();
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "muindor.TidyChests";

		public const string PLUGIN_NAME = "Tidy Chests";

		public const string PLUGIN_VERSION = "1.5.0";
	}
}
namespace TidyChests.Ui
{
	internal static class ButtonClone
	{
		public static Button Create(Button template, Transform parent, string name, UnityAction onClick, out TMP_Text? label)
		{
			UIGamePad component = ((Component)template).GetComponent<UIGamePad>();
			bool enabled = (Object)(object)component != (Object)null && ((Behaviour)component).enabled;
			if ((Object)(object)component != (Object)null)
			{
				((Behaviour)component).enabled = false;
			}
			Button val;
			try
			{
				val = Object.Instantiate<Button>(template, parent);
			}
			finally
			{
				if ((Object)(object)component != (Object)null)
				{
					((Behaviour)component).enabled = enabled;
				}
			}
			((Object)val).name = name;
			UIGamePad component2 = ((Component)val).GetComponent<UIGamePad>();
			if ((Object)(object)component2 != (Object)null)
			{
				if ((Object)(object)component2.m_hint != (Object)null)
				{
					component2.m_hint.SetActive(false);
				}
				Object.Destroy((Object)(object)component2);
			}
			((UnityEventBase)val.onClick).RemoveAllListeners();
			((UnityEvent)val.onClick).AddListener(onClick);
			label = ((Component)val).GetComponentInChildren<TMP_Text>(true);
			if ((Object)(object)label != (Object)null)
			{
				label.enableAutoSizing = true;
				label.fontSizeMax = label.fontSize;
				label.fontSizeMin = Mathf.Min(10f, label.fontSize);
			}
			return val;
		}
	}
	public sealed class ChestBrowser : MonoBehaviour
	{
		private sealed class Row
		{
			public RectTransform Rect { get; }

			public Button Button { get; }

			public Image Mark { get; }

			public Image Icon { get; }

			public TMP_Text Name { get; }

			public TMP_Text Amount { get; }

			public TMP_Text Chests { get; }

			public ItemTotal? Total { get; set; }

			public Row(RectTransform rect, Button button, Image mark, Image icon, TMP_Text name, TMP_Text amount, TMP_Text chests)
			{
				Rect = rect;
				Button = button;
				Mark = mark;
				Icon = icon;
				Name = name;
				Amount = amount;
				Chests = chests;
			}
		}

		private const float Padding = 16f;

		private const float Gap = 8f;

		private const float TitleHeight = 28f;

		private const float SearchHeight = 34f;

		private const float RowHeight = 40f;

		private const float IconSize = 32f;

		private const float ScrollbarWidth = 14f;

		private const float MarkColumn = 26f;

		private const float MarkSize = 14f;

		private const float HeaderHeight = 22f;

		private const float NameColumn = 66f;

		private const float AmountColumn = 250f;

		private const float ChestsColumn = 160f;

		private static readonly Color MarkOn = new Color(1f, 0.82f, 0.35f, 1f);

		private static readonly Color MarkOff = new Color(1f, 1f, 1f, 0.2f);

		private const float ScrollStepRows = 3f;

		private const float RefreshInterval = 0.4f;

		private static ChestBrowser? _instance;

		private static int _enterHandledFrame = -1;

		private readonly List<ItemTotal> _totals = new List<ItemTotal>();

		private readonly List<ItemTotal> _visible = new List<ItemTotal>();

		private readonly List<Row> _rows = new List<Row>();

		private RectTransform? _panel;

		private RectTransform? _content;

		private ScrollRect? _scroll;

		private GuiInputField? _search;

		private TMP_Text? _title;

		private TMP_Text? _status;

		private TMP_Text? _sortByName;

		private TMP_Text? _sortByCount;

		private FavoriteList _favorites = FavoriteList.Parse("");

		private string _favoritesSource = "";

		private TMP_FontAsset? _font;

		private Material? _fontMaterial;

		private Color _fontColor = Color.white;

		private string _query = "";

		private float _nextRefresh;

		private float _wheel;

		private float _acceptScreenLossAfter;

		private bool _failed;

		private bool _warnedAboutSearch;

		public static bool IsPanelOpen
		{
			get
			{
				if ((Object)(object)_instance != (Object)null)
				{
					return _instance.IsOpen;
				}
				return false;
			}
		}

		public static bool IsSearchFocused
		{
			get
			{
				if ((Object)(object)_instance != (Object)null && (Object)(object)_instance._search != (Object)null)
				{
					return ((TMP_InputField)_instance._search).isFocused;
				}
				return false;
			}
		}

		public static bool OwnsChatAction
		{
			get
			{
				if (!IsPanelOpen)
				{
					return _enterHandledFrame == Time.frameCount;
				}
				return true;
			}
		}

		public bool IsOpen
		{
			get
			{
				if ((Object)(object)_panel != (Object)null)
				{
					return ((Component)_panel).gameObject.activeSelf;
				}
				return false;
			}
		}

		public int RowCount => _visible.Count;

		public static void FeedScrollWheel(float delta)
		{
			if ((Object)(object)_instance != (Object)null && Mathf.Abs(delta) > Mathf.Abs(_instance._wheel))
			{
				_instance._wheel = delta;
			}
		}

		public static void RefreshLabels()
		{
			if ((Object)(object)_instance == (Object)null)
			{
				return;
			}
			if ((Object)(object)_instance._title != (Object)null)
			{
				_instance._title.text = Translations.Get("tidychests_browser_title");
			}
			if ((Object)(object)_instance._search != (Object)null)
			{
				Graphic placeholder = ((TMP_InputField)_instance._search).placeholder;
				TMP_Text val = (TMP_Text)(object)((placeholder is TMP_Text) ? placeholder : null);
				if (val != null)
				{
					val.text = Translations.Get("tidychests_browser_search");
				}
			}
			_instance.UpdateHeader();
		}

		public void Toggle()
		{
			if (IsOpen)
			{
				Close();
			}
			else
			{
				Open();
			}
		}

		public void Open()
		{
			if (!Menu.IsVisible() && !Minimap.IsOpen() && !Console.IsVisible() && !TextInput.IsVisible() && EnsureUi() && !((Object)(object)_panel == (Object)null))
			{
				InventoryGui instance = InventoryGui.instance;
				if ((Object)(object)instance != (Object)null && InventoryGui.IsVisible())
				{
					instance.Hide();
				}
				_query = "";
				((Component)_panel).gameObject.SetActive(true);
				if ((Object)(object)_search != (Object)null)
				{
					((TMP_InputField)_search).text = "";
					((Selectable)_search).Select();
					_search.ActivateInputField();
				}
				_nextRefresh = Time.time + 0.4f;
				_acceptScreenLossAfter = Time.time + 0.3f;
				UpdateHeader();
				Refresh();
				ScrollToTop();
			}
		}

		public void Close()
		{
			if (!((Object)(object)_panel == (Object)null) && ((Component)_panel).gameObject.activeSelf)
			{
				if ((Object)(object)_search != (Object)null)
				{
					((TMP_InputField)_search).DeactivateInputField(false);
				}
				((Component)_panel).gameObject.SetActive(false);
			}
		}

		private void Awake()
		{
			_instance = this;
		}

		private void OnDestroy()
		{
			Close();
			if ((Object)(object)_instance == (Object)(object)this)
			{
				_instance = null;
			}
		}

		private void Update()
		{
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Player localPlayer = Player.m_localPlayer;
				if (!Plugin.Enabled || (Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead())
				{
					Close();
					return;
				}
				if (IsOpen)
				{
					if (Time.time >= _acceptScreenLossAfter && (InventoryGui.IsVisible() || Menu.IsVisible() || Minimap.IsOpen() || Console.IsVisible()))
					{
						Close();
						return;
					}
					KeepSearchFocused();
					ConsumeScrollWheel();
					if (Time.time >= _nextRefresh)
					{
						_nextRefresh = Time.time + 0.4f;
						Refresh();
					}
					if (HandleEnter())
					{
						return;
					}
				}
				KeyboardShortcut value = Plugin.Settings.BrowserKey.Value;
				if (IsOpen ? Shortcut.IsPressedWhileSearching(value) : Shortcut.IsPressed(value))
				{
					Toggle();
				}
			}
			catch (Exception arg)
			{
				Close();
				Plugin.Log.LogError((object)$"The chest list was closed after an error: {arg}");
			}
		}

		private void KeepSearchFocused()
		{
			if (!((Object)(object)_search == (Object)null) && !((TMP_InputField)_search).isFocused && !ZInput.GetMouseButton(0) && !ZInput.GetMouseButton(1))
			{
				_search.ActivateInputField();
				((TMP_InputField)_search).caretPosition = ((TMP_InputField)_search).text.Length;
				((TMP_InputField)_search).selectionAnchorPosition = ((TMP_InputField)_search).text.Length;
			}
		}

		private bool HandleEnter()
		{
			if (!ZInput.GetKeyDown((KeyCode)13, false) && !ZInput.GetKeyDown((KeyCode)271, false))
			{
				return false;
			}
			_enterHandledFrame = Time.frameCount;
			for (int i = 0; i < _visible.Count && i < _rows.Count; i++)
			{
				if (_visible[i].Count > 0)
				{
					OnRowClicked(_rows[i]);
					break;
				}
			}
			return true;
		}

		private void ConsumeScrollWheel()
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			float wheel = _wheel;
			_wheel = 0f;
			if (wheel != 0f && !((Object)(object)_scroll == (Object)null) && !((Object)(object)_content == (Object)null) && !((Object)(object)_scroll.viewport == (Object)null))
			{
				Rect rect = _content.rect;
				float height = ((Rect)(ref rect)).height;
				rect = _scroll.viewport.rect;
				float num = height - ((Rect)(ref rect)).height;
				if (!(num <= 1f))
				{
					float num2 = Mathf.Sign(wheel) * 3f * 40f / num;
					_scroll.verticalNormalizedPosition = Mathf.Clamp01(_scroll.verticalNormalizedPosition + num2);
				}
			}
		}

		private void Refresh()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null))
			{
				ChestIndex index = Plugin.Index;
				index.Refresh(((Component)localPlayer).transform.position, Plugin.Settings.ScanRadius.Value);
				SyncFavorites();
				_totals.Clear();
				_totals.AddRange(ItemSearch.Summarize(index.Chests));
				AddMissingFavorites(index);
				ApplyQuery();
			}
		}

		private void ApplyQuery()
		{
			_visible.Clear();
			_visible.AddRange(ItemSearch.Arrange(_totals, _query, Plugin.Settings.Sort.Value, _favorites));
			FillRows();
			UpdateStatus();
		}

		private void SyncFavorites()
		{
			string text = Plugin.Settings.Favorites.Value ?? "";
			if (!(text == _favoritesSource))
			{
				_favoritesSource = text;
				_favorites = FavoriteList.Parse(text);
			}
		}

		private void AddMissingFavorites(ChestIndex index)
		{
			if (_favorites.Count == 0)
			{
				return;
			}
			foreach (string name in _favorites.Names)
			{
				if (!HasRow(name))
				{
					_totals.Add(new ItemTotal(name, index.DisplayNameOf(name), 0, 0, 0f));
				}
			}
		}

		private bool HasRow(string name)
		{
			foreach (ItemTotal total in _totals)
			{
				if (string.Equals(total.Name, name, StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
			}
			return false;
		}

		private void OnQueryChanged(string query)
		{
			_query = query ?? "";
			ApplyQuery();
		}

		private void UpdateStatus()
		{
			if (!((Object)(object)_status == (Object)null))
			{
				CultureInfo invariantCulture = CultureInfo.InvariantCulture;
				if (_totals.Count == 0)
				{
					_status.text = Translations.Get("tidychests_browser_empty", Plugin.Settings.ScanRadius.Value.ToString("0.#", invariantCulture));
				}
				else if (_visible.Count == 0)
				{
					_status.text = Translations.Get("tidychests_browser_no_match", _query.Trim());
				}
				else
				{
					_status.text = "";
				}
				((Component)_status).gameObject.SetActive(_status.text.Length > 0);
			}
		}

		private void FillRows()
		{
			//IL_0271: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: 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_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_content == (Object)null)
			{
				return;
			}
			while (_rows.Count < _visible.Count)
			{
				_rows.Add(CreateRow(_content));
			}
			CultureInfo invariantCulture = CultureInfo.InvariantCulture;
			for (int i = 0; i < _rows.Count; i++)
			{
				Row row = _rows[i];
				if (i >= _visible.Count)
				{
					((Component)row.Rect).gameObject.SetActive(false);
					row.Total = null;
					continue;
				}
				ItemTotal itemTotal = _visible[i];
				bool flag = itemTotal.Count <= 0;
				row.Total = itemTotal;
				((Component)row.Rect).gameObject.SetActive(true);
				row.Rect.anchoredPosition = new Vector2(0f, (float)(-i) * 40f);
				((Selectable)row.Button).interactable = !flag;
				row.Name.text = itemTotal.DisplayName;
				((Graphic)row.Name).color = Fade(_fontColor, flag ? 0.45f : 1f);
				row.Amount.text = "×" + itemTotal.Count.ToString(invariantCulture);
				((Graphic)row.Amount).color = Fade(_fontColor, flag ? 0.45f : 1f);
				row.Chests.text = (flag ? Translations.Get("tidychests_browser_missing") : Translations.Get("tidychests_browser_chests", itemTotal.ChestCount.ToString(invariantCulture), itemTotal.NearestDistance.ToString("0.#", invariantCulture)));
				((Graphic)row.Mark).color = (_favorites.Contains(itemTotal.Name) ? MarkOn : MarkOff);
				ItemData item;
				Sprite val = (Plugin.Index.TryGetKnownItem(itemTotal.Name, out item) ? IconOf(item) : null);
				row.Icon.sprite = val;
				((Behaviour)row.Icon).enabled = (Object)(object)val != (Object)null;
				((Graphic)row.Icon).color = Fade(Color.white, flag ? 0.45f : 1f);
			}
			_content.sizeDelta = new Vector2(_content.sizeDelta.x, (float)_visible.Count * 40f);
		}

		private void OnRowClicked(Row row)
		{
			ItemTotal total = row.Total;
			if (total != null && total.Count > 0)
			{
				float value = Plugin.Settings.ScanRadius.Value;
				Close();
				ChestFinder finder = Plugin.Finder;
				Player localPlayer = Player.m_localPlayer;
				if (!((Object)(object)finder == (Object)null) && !((Object)(object)localPlayer == (Object)null))
				{
					int num = finder.Find(total.Name, total.DisplayName, value);
					string text = ((num > 0) ? Translations.Get("tidychests_found", total.DisplayName, num) : Translations.Get("tidychests_not_found", total.DisplayName, value.ToString("0.#", CultureInfo.InvariantCulture)));
					((Character)localPlayer).Message((MessageType)2, text, 0, (Sprite)null, false);
				}
			}
		}

		private void OnMarkClicked(Row row)
		{
			ItemTotal total = row.Total;
			if (total != null && !string.IsNullOrEmpty(total.Name))
			{
				bool flag = _favorites.Toggle(total.Name);
				_favoritesSource = _favorites.Format();
				Plugin.Settings.Favorites.Value = _favoritesSource;
				Plugin.Debug(total.DisplayName + " (" + total.Name + ") " + (flag ? "pinned" : "unpinned"));
				Refresh();
			}
		}

		private void OnSortClicked(bool byName)
		{
			BrowserSort value = Plugin.Settings.Sort.Value;
			BrowserSort value2 = ((!byName) ? ((value == BrowserSort.CountDescending) ? BrowserSort.CountAscending : BrowserSort.CountDescending) : ((value == BrowserSort.NameAscending) ? BrowserSort.NameDescending : BrowserSort.NameAscending));
			Plugin.Settings.Sort.Value = value2;
			UpdateHeader();
			ApplyQuery();
			ScrollToTop();
		}

		private void UpdateHeader()
		{
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_sortByName == (Object)null) && !((Object)(object)_sortByCount == (Object)null))
			{
				BrowserSort value = Plugin.Settings.Sort.Value;
				bool flag = value == BrowserSort.NameAscending || value == BrowserSort.NameDescending;
				_sortByName.text = Translations.Get(value switch
				{
					BrowserSort.NameDescending => "tidychests_sort_name_down", 
					BrowserSort.NameAscending => "tidychests_sort_name_up", 
					_ => "tidychests_sort_name", 
				});
				_sortByCount.text = Translations.Get(value switch
				{
					BrowserSort.CountDescending => "tidychests_sort_count_down", 
					BrowserSort.CountAscending => "tidychests_sort_count_up", 
					_ => "tidychests_sort_count", 
				});
				((Graphic)_sortByName).color = Fade(_fontColor, flag ? 1f : 0.5f);
				((Graphic)_sortByCount).color = Fade(_fontColor, flag ? 0.5f : 1f);
			}
		}

		private void ScrollToTop()
		{
			if ((Object)(object)_scroll != (Object)null)
			{
				_scroll.verticalNormalizedPosition = 1f;
			}
		}

		private static Color Fade(Color color, float factor)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: 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 new Color(color.r, color.g, color.b, color.a * factor);
		}

		private static Sprite? IconOf(ItemData item)
		{
			Sprite[] icons = item.m_shared.m_icons;
			if (icons == null || icons.Length == 0)
			{
				return null;
			}
			return icons[Mathf.Clamp(item.m_variant, 0, icons.Length - 1)];
		}

		private bool EnsureUi()
		{
			if (_failed)
			{
				return false;
			}
			if ((Object)(object)_panel != (Object)null)
			{
				return true;
			}
			try
			{
				Build();
			}
			catch (Exception arg)
			{
				_failed = true;
				if ((Object)(object)_panel != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)_panel).gameObject);
					_panel = null;
				}
				Plugin.Log.LogError((object)$"Could not build the chest list; it stays disabled until restart: {arg}");
				return false;
			}
			return (Object)(object)_panel != (Object)null;
		}

		private void Build()
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Expected O, but got Unknown
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Expected O, but got Unknown
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			_rows.Clear();
			_content = null;
			_scroll = null;
			_search = null;
			_title = null;
			_status = null;
			_sortByName = null;
			_sortByCount = null;
			InventoryGui instance = InventoryGui.instance;
			Transform val = FindCanvas(instance);
			if ((Object)(object)instance == (Object)null || (Object)(object)val == (Object)null)
			{
				Plugin.Debug("The chest list waits for the game UI");
				return;
			}
			ReadStyle(instance);
			Vector2 value = Plugin.Settings.BrowserSize.Value;
			GameObject val2 = new GameObject("TidyChests Browser", new Type[4]
			{
				typeof(RectTransform),
				typeof(Canvas),
				typeof(GraphicRaycaster),
				typeof(Image)
			});
			_panel = (RectTransform)val2.transform;
			((Transform)_panel).SetParent(val, false);
			_panel.anchorMin = new Vector2(0.5f, 0.5f);
			_panel.anchorMax = new Vector2(0.5f, 0.5f);
			_panel.pivot = new Vector2(0.5f, 0.5f);
			_panel.anchoredPosition = Vector2.zero;
			_panel.sizeDelta = new Vector2(Mathf.Max(320f, value.x), Mathf.Max(240f, value.y));
			Canvas component = val2.GetComponent<Canvas>();
			component.overrideSorting = true;
			component.sortingOrder = 100;
			StyleBackground(val2.GetComponent<Image>(), instance);
			_title = CreateText("Title", _panel, 28f, 20f, (TextAlignmentOptions)514, 0f);
			_search = CreateSearch(_panel);
			CreateHeader(_panel);
			CreateList(_panel, instance);
			RefreshLabels();
			val2.SetActive(false);
			Plugin.Debug($"Chest list built ({_panel.sizeDelta.x}x{_panel.sizeDelta.y})");
		}

		private void ReadStyle(InventoryGui gui)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			TMP_Text val = (((Object)(object)gui.m_takeAllButton != (Object)null) ? ((Component)gui.m_takeAllButton).GetComponentInChildren<TMP_Text>(true) : null);
			if (!((Object)(object)val == (Object)null))
			{
				_font = val.font;
				_fontMaterial = val.fontSharedMaterial;
				_fontColor = ((Graphic)val).color;
			}
		}

		private void StyleBackground(Image image, InventoryGui gui)
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			Image val = (((Object)(object)gui.m_player != (Object)null) ? ((Component)gui.m_player).GetComponent<Image>() : null);
			if ((Object)(object)val != (Object)null && (Object)(object)val.sprite != (Object)null)
			{
				image.sprite = val.sprite;
				image.type = val.type;
				((Graphic)image).color = ((Graphic)val).color;
			}
			else
			{
				((Graphic)image).color = new Color(0.08f, 0.07f, 0.06f, 0.94f);
			}
		}

		private static Transform? FindCanvas(InventoryGui? gui)
		{
			Hud instance = Hud.instance;
			if ((Object)(object)instance != (Object)null)
			{
				Canvas componentInParent = ((Component)instance).GetComponentInParent<Canvas>();
				if ((Object)(object)componentInParent != (Object)null)
				{
					return ((Component)componentInParent).transform;
				}
			}
			if ((Object)(object)gui != (Object)null)
			{
				Canvas componentInParent2 = ((Component)gui).GetComponentInParent<Canvas>();
				if ((Object)(object)componentInParent2 != (Object)null)
				{
					return ((Component)componentInParent2).transform;
				}
			}
			return null;
		}

		private GuiInputField? CreateSearch(RectTransform panel)
		{
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			TextInput instance = TextInput.instance;
			GuiInputField val = (((Object)(object)instance != (Object)null) ? instance.m_inputField : null);
			if ((Object)(object)val == (Object)null)
			{
				if (!_warnedAboutSearch)
				{
					_warnedAboutSearch = true;
					Plugin.Log.LogWarning((object)"No text field to copy for the chest list; the list is shown without a search box.");
				}
				return null;
			}
			GuiInputField obj = Object.Instantiate<GuiInputField>(val, (Transform)(object)panel);
			((Object)obj).name = "Search";
			((Component)obj).gameObject.SetActive(true);
			((UnityEventBase)((TMP_InputField)obj).onValueChanged).RemoveAllListeners();
			((TMP_InputField)obj).characterLimit = 0;
			((TMP_InputField)obj).lineType = (LineType)0;
			((TMP_InputField)obj).contentType = (ContentType)0;
			((TMP_InputField)obj).onFocusSelectAll = false;
			((TMP_InputField)obj).resetOnDeActivation = false;
			((TMP_InputField)obj).text = "";
			((UnityEvent<string>)(object)((TMP_InputField)obj).onValueChanged).AddListener((UnityAction<string>)OnQueryChanged);
			RectTransform val2 = (RectTransform)((Component)obj).transform;
			val2.anchorMin = new Vector2(0f, 1f);
			val2.anchorMax = new Vector2(1f, 1f);
			val2.pivot = new Vector2(0.5f, 1f);
			val2.sizeDelta = new Vector2(-32f, 34f);
			val2.anchoredPosition = new Vector2(0f, -52f);
			return obj;
		}

		private void CreateHeader(RectTransform panel)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Expected O, but got Unknown
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Expected O, but got Unknown
			float num = 16f;
			float num2 = 34f;
			RectTransform val = (RectTransform)new GameObject("Header", new Type[1] { typeof(RectTransform) }).transform;
			((Transform)val).SetParent((Transform)(object)panel, false);
			val.anchorMin = new Vector2(0f, 1f);
			val.anchorMax = new Vector2(1f, 1f);
			val.pivot = new Vector2(0.5f, 1f);
			val.sizeDelta = new Vector2(0f - (num + num2), 22f);
			val.anchoredPosition = new Vector2((num - num2) * 0.5f, -94f);
			StretchHorizontally(CreateHeaderButton(val, "SortByName", (TextAlignmentOptions)513, out _sortByName, (UnityAction)delegate
			{
				OnSortClicked(byName: true);
			}), 66f, 250f);
			PinRight(CreateHeaderButton(val, "SortByCount", (TextAlignmentOptions)516, out _sortByCount, (UnityAction)delegate
			{
				OnSortClicked(byName: false);
			}), 250f, 160f);
		}

		private RectTransform CreateHeaderButton(RectTransform parent, string name, TextAlignmentOptions alignment, out TMP_Text label, UnityAction onClick)
		{
			//IL_002e: 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)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Button)
			});
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent((Transform)(object)parent, false);
			Image component = val.GetComponent<Image>();
			((Graphic)component).color = new Color(1f, 1f, 1f, 0f);
			Button component2 = val.GetComponent<Button>();
			((Selectable)component2).targetGraphic = (Graphic)(object)component;
			ColorBlock colors = ((Selectable)component2).colors;
			((ColorBlock)(ref colors)).normalColor = new Color(1f, 1f, 1f, 0f);
			((ColorBlock)(ref colors)).highlightedColor = new Color(1f, 1f, 1f, 0.14f);
			((ColorBlock)(ref colors)).pressedColor = new Color(1f, 1f, 1f, 0.24f);
			((ColorBlock)(ref colors)).selectedColor = new Color(1f, 1f, 1f, 0f);
			((ColorBlock)(ref colors)).disabledColor = new Color(1f, 1f, 1f, 0f);
			((Selectable)component2).colors = colors;
			((UnityEvent)component2.onClick).AddListener(onClick);
			label = CreateText("Label", val2, 0f, 15f, alignment, 0f);
			return val2;
		}

		private void CreateList(RectTransform panel, InventoryGui gui)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Expected O, but got Unknown
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Expected O, but got Unknown
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: 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_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Expected O, but got Unknown
			float top = 120f;
			GameObject val = new GameObject("Scroll", new Type[2]
			{
				typeof(RectTransform),
				typeof(ScrollRect)
			});
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent((Transform)(object)panel, false);
			Stretch(val2, 16f, 16f, top, 16f);
			GameObject val3 = new GameObject("Viewport", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(RectMask2D)
			});
			RectTransform val4 = (RectTransform)val3.transform;
			((Transform)val4).SetParent((Transform)(object)val2, false);
			Stretch(val4, 0f, 18f, 0f, 0f);
			((Graphic)val3.GetComponent<Image>()).color = new Color(0f, 0f, 0f, 0f);
			GameObject val5 = new GameObject("Content", new Type[1] { typeof(RectTransform) });
			_content = (RectTransform)val5.transform;
			((Transform)_content).SetParent((Transform)(object)val4, false);
			_content.anchorMin = new Vector2(0f, 1f);
			_content.anchorMax = new Vector2(1f, 1f);
			_content.pivot = new Vector2(0.5f, 1f);
			_content.anchoredPosition = Vector2.zero;
			_content.sizeDelta = new Vector2(0f, 0f);
			_scroll = val.GetComponent<ScrollRect>();
			_scroll.content = _content;
			_scroll.viewport = val4;
			_scroll.horizontal = false;
			_scroll.vertical = true;
			_scroll.movementType = (MovementType)2;
			_scroll.inertia = false;
			_scroll.scrollSensitivity = 0f;
			Scrollbar val6 = CreateScrollbar(val2, gui);
			if ((Object)(object)val6 != (Object)null)
			{
				_scroll.verticalScrollbar = val6;
				_scroll.verticalScrollbarVisibility = (ScrollbarVisibility)1;
			}
			_status = CreateText("Status", val2, 0f, 17f, (TextAlignmentOptions)258, 0f);
			Stretch((RectTransform)_status.transform, 0f, 0f, 8f, 0f);
			((Component)_status).gameObject.SetActive(false);
		}

		private Scrollbar? CreateScrollbar(RectTransform scrollRect, InventoryGui gui)
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			Scrollbar recipeListScroll = gui.m_recipeListScroll;
			if ((Object)(object)recipeListScroll == (Object)null)
			{
				Plugin.Log.LogWarning((object)"No scrollbar to copy for the chest list; use the mouse wheel to scroll it.");
				return null;
			}
			Scrollbar val = Object.Instantiate<Scrollbar>(recipeListScroll, (Transform)(object)scrollRect);
			((Object)val).name = "Scrollbar";
			((Component)val).gameObject.SetActive(true);
			((UnityEventBase)val.onValueChanged).RemoveAllListeners();
			for (int i = 0; i < ((UnityEventBase)val.onValueChanged).GetPersistentEventCount(); i++)
			{
				((UnityEventBase)val.onValueChanged).SetPersistentListenerState(i, (UnityEventCallState)0);
			}
			val.direction = (Direction)2;
			RectTransform val2 = (RectTransform)((Component)val).transform;
			val2.anchorMin = new Vector2(1f, 0f);
			val2.anchorMax = new Vector2(1f, 1f);
			val2.pivot = new Vector2(1f, 0.5f);
			val2.offsetMin = new Vector2(-14f, 0f);
			val2.offsetMax = Vector2.zero;
			return val;
		}

		private Row CreateRow(RectTransform content)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			//IL_0063: 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)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: 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)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Expected O, but got Unknown
			//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cf: Expected O, but got Unknown
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Expected O, but got Unknown
			//IL_0330: Unknown result type (might be due to invalid IL or missing references)
			//IL_033a: Expected O, but got Unknown
			//IL_0348: Unknown result type (might be due to invalid IL or missing references)
			//IL_0352: Expected O, but got Unknown
			GameObject val = new GameObject("Row", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Button)
			});
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent((Transform)(object)content, false);
			val2.anchorMin = new Vector2(0f, 1f);
			val2.anchorMax = new Vector2(1f, 1f);
			val2.pivot = new Vector2(0.5f, 1f);
			val2.sizeDelta = new Vector2(0f, 40f);
			Image component = val.GetComponent<Image>();
			((Graphic)component).color = new Color(1f, 1f, 1f, 0f);
			Button component2 = val.GetComponent<Button>();
			((Selectable)component2).targetGraphic = (Graphic)(object)component;
			ColorBlock colors = ((Selectable)component2).colors;
			((ColorBlock)(ref colors)).normalColor = new Color(1f, 1f, 1f, 0f);
			((ColorBlock)(ref colors)).highlightedColor = new Color(1f, 1f, 1f, 0.14f);
			((ColorBlock)(ref colors)).pressedColor = new Color(1f, 1f, 1f, 0.24f);
			((ColorBlock)(ref colors)).selectedColor = new Color(1f, 1f, 1f, 0f);
			((ColorBlock)(ref colors)).disabledColor = new Color(1f, 1f, 1f, 0f);
			((Selectable)component2).colors = colors;
			Button button;
			Image mark = CreateMark(val2, out button);
			GameObject val3 = new GameObject("Icon", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			RectTransform val4 = (RectTransform)val3.transform;
			((Transform)val4).SetParent((Transform)(object)val2, false);
			val4.anchorMin = new Vector2(0f, 0.5f);
			val4.anchorMax = new Vector2(0f, 0.5f);
			val4.pivot = new Vector2(0f, 0.5f);
			val4.anchoredPosition = new Vector2(26f, 0f);
			val4.sizeDelta = new Vector2(32f, 32f);
			Image component3 = val3.GetComponent<Image>();
			((Graphic)component3).raycastTarget = false;
			component3.preserveAspect = true;
			TMP_Text val5 = CreateText("Name", val2, 0f, 18f, (TextAlignmentOptions)513, 0f);
			StretchHorizontally((RectTransform)val5.transform, 66f, 250f);
			TMP_Text val6 = CreateText("Amount", val2, 0f, 18f, (TextAlignmentOptions)516, 0f);
			PinRight((RectTransform)val6.transform, 250f, 160f);
			TMP_Text val7 = CreateText("Chests", val2, 0f, 15f, (TextAlignmentOptions)516, 0.65f);
			PinRight((RectTransform)val7.transform, 160f, 8f);
			Row row = new Row(val2, component2, mark, component3, val5, val6, val7);
			((UnityEvent)component2.onClick).AddListener((UnityAction)delegate
			{
				OnRowClicked(row);
			});
			((UnityEvent)button.onClick).AddListener((UnityAction)delegate
			{
				OnMarkClicked(row);
			});
			return row;
		}

		private static Image CreateMark(RectTransform row, out Button button)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Mark", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Button)
			});
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent((Transform)(object)row, false);
			val2.anchorMin = new Vector2(0f, 0f);
			val2.anchorMax = new Vector2(0f, 1f);
			val2.pivot = new Vector2(0f, 0.5f);
			val2.offsetMin = Vector2.zero;
			val2.offsetMax = new Vector2(26f, 0f);
			Image component = val.GetComponent<Image>();
			((Graphic)component).color = new Color(1f, 1f, 1f, 0f);
			button = val.GetComponent<Button>();
			((Selectable)button).targetGraphic = (Graphic)(object)component;
			ColorBlock colors = ((Selectable)button).colors;
			((ColorBlock)(ref colors)).normalColor = new Color(1f, 1f, 1f, 0f);
			((ColorBlock)(ref colors)).highlightedColor = new Color(1f, 1f, 1f, 0.2f);
			((ColorBlock)(ref colors)).pressedColor = new Color(1f, 1f, 1f, 0.32f);
			((ColorBlock)(ref colors)).selectedColor = new Color(1f, 1f, 1f, 0f);
			((ColorBlock)(ref colors)).disabledColor = new Color(1f, 1f, 1f, 0f);
			((Selectable)button).colors = colors;
			GameObject val3 = new GameObject("Diamond", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			RectTransform val4 = (RectTransform)val3.transform;
			((Transform)val4).SetParent((Transform)(object)val2, false);
			val4.anchorMin = new Vector2(0.5f, 0.5f);
			val4.anchorMax = new Vector2(0.5f, 0.5f);
			val4.pivot = new Vector2(0.5f, 0.5f);
			val4.anchoredPosition = Vector2.zero;
			val4.sizeDelta = new Vector2(14f, 14f);
			((Transform)val4).localRotation = Quaternion.Euler(0f, 0f, 45f);
			Image component2 = val3.GetComponent<Image>();
			((Graphic)component2).raycastTarget = false;
			((Graphic)component2).color = MarkOff;
			return component2;
		}

		private TMP_Text CreateText(string name, RectTransform parent, float height, float fontSize, TextAlignmentOptions alignment, float dim)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: 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_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent((Transform)(object)parent, false);
			TextMeshProUGUI val3 = val.AddComponent<TextMeshProUGUI>();
			if ((Object)(object)_font != (Object)null)
			{
				((TMP_Text)val3).font = _font;
				if ((Object)(object)_fontMaterial != (Object)null)
				{
					((TMP_Text)val3).fontSharedMaterial = _fontMaterial;
				}
			}
			((TMP_Text)val3).fontSize = fontSize;
			((TMP_Text)val3).alignment = alignment;
			((TMP_Text)val3).textWrappingMode = (TextWrappingModes)0;
			((TMP_Text)val3).overflowMode = (TextOverflowModes)1;
			((Graphic)val3).raycastTarget = false;
			((Graphic)val3).color = (Color)((dim > 0f) ? new Color(_fontColor.r, _fontColor.g, _fontColor.b, _fontColor.a * (1f - dim)) : _fontColor);
			if (height > 0f)
			{
				val2.anchorMin = new Vector2(0f, 1f);
				val2.anchorMax = new Vector2(1f, 1f);
				val2.pivot = new Vector2(0.5f, 1f);
				val2.sizeDelta = new Vector2(-32f, height);
				val2.anchoredPosition = new Vector2(0f, -16f);
			}
			else
			{
				Stretch(val2, 0f, 0f, 0f, 0f);
			}
			return (TMP_Text)(object)val3;
		}

		private static void Stretch(RectTransform rect, float left, float right, float top, float bottom)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			rect.anchorMin = Vector2.zero;
			rect.anchorMax = Vector2.one;
			rect.pivot = new Vector2(0.5f, 0.5f);
			rect.offsetMin = new Vector2(left, bottom);
			rect.offsetMax = new Vector2(0f - right, 0f - top);
		}

		private static void StretchHorizontally(RectTransform rect, float left, float right)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: 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)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			rect.anchorMin = new Vector2(0f, 0f);
			rect.anchorMax = new Vector2(1f, 1f);
			rect.pivot = new Vector2(0.5f, 0.5f);
			rect.offsetMin = new Vector2(left, 0f);
			rect.offsetMax = new Vector2(0f - right, 0f);
		}

		private static void PinRight(RectTransform rect, float from, float to)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: 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)
			//IL_0047: 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)
			rect.anchorMin = new Vector2(1f, 0f);
			rect.anchorMax = new Vector2(1f, 1f);
			rect.pivot = new Vector2(0.5f, 0.5f);
			rect.offsetMin = new Vector2(0f - from, 0f);
			rect.offsetMax = new Vector2(0f - to, 0f);
		}
	}
	internal static class LockOverlay
	{
		private const string BadgeName = "TidyChests Lock";

		private const string RestockBadgeName = "TidyChests Restock";

		private const float BadgeSize = 16f;

		private const float BadgeInset = 3f;

		private static readonly Color ItemLockColor = new Color(0.85f, 0.85f, 0.85f, 0.6f);

		private static readonly Color SlotLockColor = new Color(1f, 0.3f, 0.3f, 0.7f);

		private static readonly Color RestockFullColor = new Color(0.35f, 0.9f, 0.35f, 0.9f);

		private static readonly Colo