Decompiled source of RunicInventory v1.1.11

plugins/RunicInventory/RunicInventory.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization.Json;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Runic.Foundation.Core;
using Runic.Localization;
using RunicInventory.Api;
using RunicInventory.Core;
using RunicInventory.Integration;
using UnityEngine;
using UnityEngine.EventSystems;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Runic Inventory")]
[assembly: AssemblyDescription("Labeled native-row equipment and quick slots with automatic empty-role equip, lossless armor swaps, locks, sort, and pickup controls for Valheim.")]
[assembly: AssemblyCompany("Chazman")]
[assembly: AssemblyProduct("Runic Inventory")]
[assembly: AssemblyCopyright("Copyright © 2026")]
[assembly: AssemblyFileVersion("1.1.10.0")]
[assembly: AssemblyInformationalVersion("1.1.10")]
[assembly: InternalsVisibleTo("RunicInventory.Tests")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyVersion("1.1.10.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[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 Runic.Localization
{
	internal sealed class LanguageCatalog
	{
		private readonly Dictionary<string, string> _english;

		private Dictionary<string, string> _selected = new Dictionary<string, string>();

		private readonly Func<string, string> _read;

		private string _language;

		internal LanguageCatalog(string english, Func<string, string> read)
		{
			_english = Parse(english);
			_read = read;
		}

		internal static Dictionary<string, string> Parse(string json)
		{
			if (string.IsNullOrWhiteSpace(json))
			{
				return new Dictionary<string, string>();
			}
			if (json.Length > 2097152)
			{
				throw new InvalidDataException("Language file exceeds 2 MiB.");
			}
			DataContractJsonSerializer dataContractJsonSerializer = new DataContractJsonSerializer(typeof(Dictionary<string, string>), new DataContractJsonSerializerSettings
			{
				UseSimpleDictionaryFormat = true
			});
			using MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(json.TrimStart('\ufeff')));
			return ((Dictionary<string, string>)dataContractJsonSerializer.ReadObject(stream)) ?? new Dictionary<string, string>();
		}

		internal void Select(string language)
		{
			language = (string.IsNullOrWhiteSpace(language) ? "English" : language);
			if (string.Equals(language, _language, StringComparison.Ordinal))
			{
				return;
			}
			_language = language;
			_selected = new Dictionary<string, string>();
			if (language.IndexOfAny(new char[4] { '/', '\\', ':', '\0' }) >= 0 || language == "." || language == "..")
			{
				return;
			}
			try
			{
				_selected = Parse(_read(language));
			}
			catch (Exception)
			{
			}
		}

		internal string Get(string key)
		{
			_english.TryGetValue(key, out var value);
			if (_selected.TryGetValue(key, out var value2) && !string.IsNullOrWhiteSpace(value2) && (value == null || SameFields(value, value2)))
			{
				return value2;
			}
			return value ?? key;
		}

		internal string English(string key)
		{
			if (!_english.TryGetValue(key, out var value))
			{
				return key;
			}
			return value;
		}

		internal string TranslateEnglish(string text)
		{
			foreach (KeyValuePair<string, string> item in _english)
			{
				if (item.Value == text)
				{
					return Get(item.Key);
				}
			}
			return text;
		}

		internal string Format(string key, params object[] args)
		{
			_english.TryGetValue(key, out var value);
			string text = Get(key);
			if (value != null && !SameFields(value, text))
			{
				text = value;
			}
			try
			{
				return string.Format(CultureInfo.CurrentCulture, text, args);
			}
			catch (FormatException)
			{
				try
				{
					return string.Format(CultureInfo.CurrentCulture, value ?? key, args);
				}
				catch (FormatException)
				{
					return value ?? key;
				}
			}
		}

		private static bool SameFields(string a, string b)
		{
			try
			{
				return Fields(a).SetEquals(Fields(b));
			}
			catch (FormatException)
			{
				return false;
			}
		}

		private static HashSet<int> Fields(string text)
		{
			HashSet<int> hashSet = new HashSet<int>();
			for (int i = 0; i < text.Length; i++)
			{
				if (text[i] == '}')
				{
					if (i + 1 >= text.Length || text[i + 1] != '}')
					{
						throw new FormatException();
					}
					i++;
				}
				else
				{
					if (text[i] != '{')
					{
						continue;
					}
					if (i + 1 < text.Length && text[i + 1] == '{')
					{
						i++;
						continue;
					}
					int num = ++i;
					for (; i < text.Length && char.IsDigit(text[i]); i++)
					{
					}
					if (num == i || !int.TryParse(text.Substring(num, i - num), out var result))
					{
						throw new FormatException();
					}
					hashSet.Add(result);
					for (; i < text.Length && text[i] != '}'; i++)
					{
						if (text[i] == '{')
						{
							throw new FormatException();
						}
					}
					if (i == text.Length)
					{
						throw new FormatException();
					}
				}
			}
			return hashSet;
		}
	}
	internal static class RunicText
	{
		private static readonly Assembly Owner = typeof(RunicText).Assembly;

		private static readonly string Module = Owner.GetName().Name;

		private static readonly LanguageCatalog Catalog = Create();

		private static LanguageCatalog Create()
		{
			using Stream stream = Owner.GetManifestResourceStream("Runic.Localization.English.json");
			using StreamReader streamReader = ((stream == null) ? null : new StreamReader(stream));
			return new LanguageCatalog(streamReader?.ReadToEnd() ?? "{}", ReadLanguage);
		}

		private static string ReadLanguage(string language)
		{
			string path = Path.Combine(Path.Combine(Path.GetDirectoryName(Owner.Location), "Translations", Module), language + ".json");
			if (!File.Exists(path))
			{
				return null;
			}
			return File.ReadAllText(path);
		}

		private static void SelectLanguage()
		{
			string language = "English";
			try
			{
				Localization instance = Localization.instance;
				language = ((instance != null) ? instance.GetSelectedLanguage() : null) ?? "English";
			}
			catch
			{
			}
			Catalog.Select(language);
		}

		internal static string Get(string key)
		{
			SelectLanguage();
			return Catalog.Get(key);
		}

		internal static string English(string key)
		{
			return Catalog.English(key);
		}

		internal static string TranslateEnglish(string text)
		{
			SelectLanguage();
			return Catalog.TranslateEnglish(text);
		}

		internal static string Format(string key, params object[] args)
		{
			SelectLanguage();
			return Catalog.Format(key, args);
		}
	}
}
namespace Runic.Foundation.Core
{
	public static class RunicIdentifier
	{
		public static bool IsValid(string value)
		{
			if (string.IsNullOrEmpty(value) || value.Length > 128)
			{
				return false;
			}
			bool flag = false;
			bool flag2 = false;
			foreach (char c in value)
			{
				if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'))
				{
					flag = true;
					flag2 = false;
					continue;
				}
				switch (c)
				{
				case '-':
					if (!flag || flag2)
					{
						return false;
					}
					flag2 = true;
					break;
				case '.':
					if (!flag || flag2)
					{
						return false;
					}
					flag = false;
					flag2 = false;
					break;
				default:
					return false;
				}
			}
			if (flag)
			{
				return !flag2;
			}
			return false;
		}

		public static string Require(string value, string parameterName)
		{
			if (!IsValid(value))
			{
				throw new ArgumentException("Runic identifiers must be lowercase dot-separated tokens containing only ASCII letters, digits, and internal hyphens.", parameterName);
			}
			return value;
		}
	}
	public sealed class InputChord : IEquatable<InputChord>
	{
		private readonly IReadOnlyList<string> _modifiers;

		public string DeviceId { get; }

		public string PrimaryControl { get; }

		public IReadOnlyList<string> Modifiers => _modifiers;

		public string CanonicalId { get; }

		public InputChord(string deviceId, string primaryControl, IEnumerable<string> modifiers = null)
		{
			DeviceId = RunicIdentifier.Require(deviceId, "deviceId");
			PrimaryControl = RequireControl(primaryControl, "primaryControl");
			string text = CanonicalizeControl(PrimaryControl);
			SortedDictionary<string, string> sortedDictionary = new SortedDictionary<string, string>(StringComparer.Ordinal);
			if (modifiers != null)
			{
				foreach (string modifier in modifiers)
				{
					string text2 = RequireControl(modifier, "modifiers");
					string text3 = CanonicalizeControl(text2);
					if (string.Equals(text3, text, StringComparison.Ordinal))
					{
						throw new ArgumentException("The primary control cannot also be a modifier.", "modifiers");
					}
					if (sortedDictionary.ContainsKey(text3))
					{
						throw new ArgumentException("Duplicate input modifier: " + text2, "modifiers");
					}
					sortedDictionary.Add(text3, text2);
				}
			}
			string[] array = new string[sortedDictionary.Count];
			int num = 0;
			foreach (string value in sortedDictionary.Values)
			{
				array[num++] = value;
			}
			_modifiers = Array.AsReadOnly(array);
			StringBuilder stringBuilder = new StringBuilder(DeviceId).Append(':');
			foreach (string key in sortedDictionary.Keys)
			{
				stringBuilder.Append(key).Append('+');
			}
			stringBuilder.Append(text);
			CanonicalId = stringBuilder.ToString();
		}

		public bool Equals(InputChord other)
		{
			if (other != null)
			{
				return string.Equals(CanonicalId, other.CanonicalId, StringComparison.Ordinal);
			}
			return false;
		}

		public override bool Equals(object obj)
		{
			return Equals(obj as InputChord);
		}

		public override int GetHashCode()
		{
			return StringComparer.Ordinal.GetHashCode(CanonicalId);
		}

		public override string ToString()
		{
			StringBuilder stringBuilder = new StringBuilder();
			for (int i = 0; i < _modifiers.Count; i++)
			{
				if (i > 0)
				{
					stringBuilder.Append(" + ");
				}
				stringBuilder.Append(_modifiers[i]);
			}
			if (_modifiers.Count > 0)
			{
				stringBuilder.Append(" + ");
			}
			return stringBuilder.Append(PrimaryControl).Append(" [").Append(DeviceId)
				.Append(']')
				.ToString();
		}

		private static string RequireControl(string value, string parameterName)
		{
			if (string.IsNullOrWhiteSpace(value))
			{
				throw new ArgumentException("An input control name is required.", parameterName);
			}
			string text = value.Trim();
			if (text.Length > 64)
			{
				throw new ArgumentException("Input control names cannot exceed 64 characters.", parameterName);
			}
			string text2 = text;
			foreach (char c in text2)
			{
				if (char.IsControl(c) || c == ':' || c == '+' || c == '|')
				{
					throw new ArgumentException("The input control name contains a reserved character.", parameterName);
				}
			}
			if (CanonicalizeControl(text).Length == 0)
			{
				throw new ArgumentException("The input control name has no canonical characters.", parameterName);
			}
			return text;
		}

		private static string CanonicalizeControl(string value)
		{
			StringBuilder stringBuilder = new StringBuilder(value.Length);
			foreach (char c in value)
			{
				if (!char.IsWhiteSpace(c) && c != '_' && c != '-')
				{
					stringBuilder.Append(char.ToLowerInvariant(c));
				}
			}
			return stringBuilder.ToString();
		}
	}
	public sealed class KeybindingDescriptor
	{
		public string ModuleId { get; }

		public string BindingId { get; }

		public string QualifiedId => ModuleId + "/" + BindingId;

		public string DisplayName { get; }

		public InputChord Chord { get; }

		public string Context { get; }

		public KeybindingDescriptor(string moduleId, string bindingId, string displayName, InputChord chord, string context = "gameplay")
		{
			ModuleId = RunicIdentifier.Require(moduleId, "moduleId");
			BindingId = RunicIdentifier.Require(bindingId, "bindingId");
			Context = RunicIdentifier.Require(context, "context");
			if (string.IsNullOrWhiteSpace(displayName))
			{
				throw new ArgumentException("A keybinding display name is required.", "displayName");
			}
			Chord = chord ?? throw new ArgumentNullException("chord");
			DisplayName = displayName.Trim();
		}
	}
	public sealed class KeybindingConflict
	{
		public InputChord Chord { get; }

		public IReadOnlyList<KeybindingDescriptor> Bindings { get; }

		internal KeybindingConflict(InputChord chord, IReadOnlyList<KeybindingDescriptor> bindings)
		{
			Chord = chord;
			Bindings = bindings;
		}
	}
	public enum KeybindingChangeKind
	{
		Registered,
		Unregistered
	}
	public sealed class KeybindingsChangedEventArgs : EventArgs
	{
		public KeybindingChangeKind Kind { get; }

		public KeybindingDescriptor Binding { get; }

		public KeybindingConflict Conflict { get; }

		internal KeybindingsChangedEventArgs(KeybindingChangeKind kind, KeybindingDescriptor binding, KeybindingConflict conflict)
		{
			Kind = kind;
			Binding = binding;
			Conflict = conflict;
		}
	}
	public sealed class KeybindingConflictRegistry
	{
		private sealed class BindingEntry
		{
			internal KeybindingDescriptor Binding { get; }

			internal long Token { get; }

			internal BindingEntry(KeybindingDescriptor binding, long token)
			{
				Binding = binding;
				Token = token;
			}
		}

		private readonly object _sync = new object();

		private readonly Dictionary<string, BindingEntry> _byQualifiedId = new Dictionary<string, BindingEntry>(StringComparer.Ordinal);

		private readonly Dictionary<string, List<BindingEntry>> _byChord = new Dictionary<string, List<BindingEntry>>(StringComparer.Ordinal);

		private long _nextToken;

		public event EventHandler<KeybindingsChangedEventArgs> Changed;

		public KeybindingRegistration Register(KeybindingDescriptor binding)
		{
			if (binding == null)
			{
				throw new ArgumentNullException("binding");
			}
			long token;
			KeybindingConflict conflict;
			lock (_sync)
			{
				if (_byQualifiedId.ContainsKey(binding.QualifiedId))
				{
					throw new InvalidOperationException("A keybinding is already registered as '" + binding.QualifiedId + "'.");
				}
				if (_nextToken == long.MaxValue)
				{
					throw new InvalidOperationException("The keybinding registration token space is exhausted.");
				}
				token = ++_nextToken;
				BindingEntry bindingEntry = new BindingEntry(binding, token);
				_byQualifiedId.Add(binding.QualifiedId, bindingEntry);
				if (!_byChord.TryGetValue(binding.Chord.CanonicalId, out var value))
				{
					value = new List<BindingEntry>();
					_byChord.Add(binding.Chord.CanonicalId, value);
				}
				value.Add(bindingEntry);
				conflict = CreateConflictLocked(binding.Chord.CanonicalId);
			}
			RaiseChanged(new KeybindingsChangedEventArgs(KeybindingChangeKind.Registered, binding, conflict));
			return new KeybindingRegistration(this, binding, token);
		}

		public bool Unregister(string moduleId, string bindingId)
		{
			RunicIdentifier.Require(moduleId, "moduleId");
			RunicIdentifier.Require(bindingId, "bindingId");
			return Unregister(moduleId + "/" + bindingId, (long?)null);
		}

		public bool TryGetBinding(string moduleId, string bindingId, out KeybindingDescriptor binding)
		{
			binding = null;
			if (!RunicIdentifier.IsValid(moduleId) || !RunicIdentifier.IsValid(bindingId))
			{
				return false;
			}
			lock (_sync)
			{
				if (!_byQualifiedId.TryGetValue(moduleId + "/" + bindingId, out var value))
				{
					return false;
				}
				binding = value.Binding;
				return true;
			}
		}

		public IReadOnlyList<KeybindingDescriptor> GetBindings()
		{
			lock (_sync)
			{
				List<KeybindingDescriptor> list = new List<KeybindingDescriptor>(_byQualifiedId.Count);
				foreach (BindingEntry value in _byQualifiedId.Values)
				{
					list.Add(value.Binding);
				}
				list.Sort((KeybindingDescriptor left, KeybindingDescriptor right) => StringComparer.Ordinal.Compare(left.QualifiedId, right.QualifiedId));
				return list.AsReadOnly();
			}
		}

		public IReadOnlyList<KeybindingConflict> GetConflicts()
		{
			lock (_sync)
			{
				List<KeybindingConflict> list = new List<KeybindingConflict>();
				foreach (string key in _byChord.Keys)
				{
					KeybindingConflict keybindingConflict = CreateConflictLocked(key);
					if (keybindingConflict != null)
					{
						list.Add(keybindingConflict);
					}
				}
				list.Sort((KeybindingConflict left, KeybindingConflict right) => StringComparer.Ordinal.Compare(left.Chord.CanonicalId, right.Chord.CanonicalId));
				return list.AsReadOnly();
			}
		}

		public IReadOnlyList<KeybindingConflict> GetConflictsFor(string moduleId)
		{
			RunicIdentifier.Require(moduleId, "moduleId");
			IReadOnlyList<KeybindingConflict> conflicts = GetConflicts();
			List<KeybindingConflict> list = new List<KeybindingConflict>();
			foreach (KeybindingConflict item in conflicts)
			{
				foreach (KeybindingDescriptor binding in item.Bindings)
				{
					if (string.Equals(binding.ModuleId, moduleId, StringComparison.Ordinal))
					{
						list.Add(item);
						break;
					}
				}
			}
			return list.AsReadOnly();
		}

		internal bool IsActive(string qualifiedId, long token)
		{
			lock (_sync)
			{
				BindingEntry value;
				return _byQualifiedId.TryGetValue(qualifiedId, out value) && value.Token == token;
			}
		}

		internal bool Unregister(string qualifiedId, long? requiredToken)
		{
			KeybindingDescriptor binding;
			KeybindingConflict conflict;
			lock (_sync)
			{
				if (!_byQualifiedId.TryGetValue(qualifiedId, out var entry) || (requiredToken.HasValue && entry.Token != requiredToken.Value))
				{
					return false;
				}
				binding = entry.Binding;
				_byQualifiedId.Remove(qualifiedId);
				List<BindingEntry> list = _byChord[binding.Chord.CanonicalId];
				list.RemoveAll((BindingEntry candidate) => candidate.Token == entry.Token);
				if (list.Count == 0)
				{
					_byChord.Remove(binding.Chord.CanonicalId);
				}
				conflict = CreateConflictLocked(binding.Chord.CanonicalId);
			}
			RaiseChanged(new KeybindingsChangedEventArgs(KeybindingChangeKind.Unregistered, binding, conflict));
			return true;
		}

		private KeybindingConflict CreateConflictLocked(string chordId)
		{
			if (!_byChord.TryGetValue(chordId, out var value) || value.Count < 2)
			{
				return null;
			}
			List<KeybindingDescriptor> list = new List<KeybindingDescriptor>(value.Count);
			foreach (BindingEntry item in value)
			{
				list.Add(item.Binding);
			}
			list.Sort((KeybindingDescriptor left, KeybindingDescriptor right) => StringComparer.Ordinal.Compare(left.QualifiedId, right.QualifiedId));
			return new KeybindingConflict(list[0].Chord, list.AsReadOnly());
		}

		private void RaiseChanged(KeybindingsChangedEventArgs arguments)
		{
			EventHandler<KeybindingsChangedEventArgs> eventHandler = this.Changed;
			if (eventHandler == null)
			{
				return;
			}
			Delegate[] invocationList = eventHandler.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				EventHandler<KeybindingsChangedEventArgs> eventHandler2 = (EventHandler<KeybindingsChangedEventArgs>)invocationList[i];
				try
				{
					eventHandler2(this, arguments);
				}
				catch (Exception)
				{
				}
			}
		}
	}
	public sealed class KeybindingRegistration : IDisposable
	{
		private readonly KeybindingConflictRegistry _registry;

		private readonly long _token;

		public KeybindingDescriptor Binding { get; }

		public bool IsActive => _registry.IsActive(Binding.QualifiedId, _token);

		internal KeybindingRegistration(KeybindingConflictRegistry registry, KeybindingDescriptor binding, long token)
		{
			_registry = registry;
			Binding = binding;
			_token = token;
		}

		public void Dispose()
		{
			_registry.Unregister(Binding.QualifiedId, _token);
		}
	}
}
namespace RunicInventory
{
	internal static class Diagnostics
	{
		private static ManualLogSource _log;

		internal static void Initialize(ManualLogSource log)
		{
			_log = log;
		}

		internal static void Info(string value)
		{
			ManualLogSource log = _log;
			if (log != null)
			{
				log.LogInfo((object)Bound(value));
			}
		}

		internal static void Warn(string value)
		{
			ManualLogSource log = _log;
			if (log != null)
			{
				log.LogWarning((object)Bound(value));
			}
		}

		internal static void Error(Exception exception, string context)
		{
			ManualLogSource log = _log;
			if (log != null)
			{
				log.LogError((object)(Bound(context) + " " + ((exception == null) ? "unknown" : (exception.GetType().Name + ": " + Bound(exception.Message)))));
			}
		}

		internal static void Trace(string value)
		{
			ConfigEntry<bool> verboseDiagnostics = InventoryConfig.VerboseDiagnostics;
			if (verboseDiagnostics != null && verboseDiagnostics.Value)
			{
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogInfo((object)Bound(value));
				}
			}
		}

		private static string Bound(string value)
		{
			string text = value ?? string.Empty;
			if (text.Length > 512)
			{
				return text.Substring(0, 512);
			}
			return text;
		}
	}
	internal static class InventoryConfig
	{
		internal static ConfigEntry<bool> Enabled { get; private set; }

		internal static ConfigEntry<bool> ShowInventoryStatus { get; private set; }

		internal static ConfigEntry<bool> ShowRoleLabels { get; private set; }

		internal static ConfigEntry<bool> ShowPickupPreview { get; private set; }

		internal static ConfigEntry<bool> CompactQuiverLayout { get; private set; }

		internal static ConfigEntry<string> FilteredPickupItems { get; private set; }

		internal static ConfigEntry<string> SortRows { get; private set; }

		internal static ConfigEntry<KeyboardShortcut> Quick1 { get; private set; }

		internal static ConfigEntry<KeyboardShortcut> Quick2 { get; private set; }

		internal static ConfigEntry<KeyboardShortcut> Quick3 { get; private set; }

		internal static ConfigEntry<KeyboardShortcut> Sort { get; private set; }

		internal static ConfigEntry<KeyboardShortcut> ToggleLock { get; private set; }

		internal static ConfigEntry<bool> ControllerEnabled { get; private set; }

		internal static ConfigEntry<string> ControllerModifier { get; private set; }

		internal static ConfigEntry<string> ControllerQuick1 { get; private set; }

		internal static ConfigEntry<string> ControllerQuick2 { get; private set; }

		internal static ConfigEntry<string> ControllerQuick3 { get; private set; }

		internal static ConfigEntry<string> ControllerSort { get; private set; }

		internal static ConfigEntry<string> ControllerToggleLock { get; private set; }

		internal static ConfigEntry<bool> VerboseDiagnostics { get; private set; }

		internal static void Bind(ConfigFile config)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			//IL_0117: 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_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			Enabled = config.Bind<bool>("General", "Enabled", true, new ConfigDescription(RunicText.Get("text_8d4aa0761bf8"), (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes()
			}));
			ShowInventoryStatus = config.Bind<bool>("UI", "ShowInventoryStatus", false, RunicText.Get("text_3c4bb869b3e0"));
			ShowRoleLabels = config.Bind<bool>("UI", "ShowRoleLabels", true, RunicText.Get("text_10dc0db42044"));
			ShowPickupPreview = config.Bind<bool>("UI", "ShowPickupPreview", true, RunicText.Get("text_9aeb1688941e"));
			CompactQuiverLayout = config.Bind<bool>("UI", "CompactQuiverLayout", true, RunicText.Get("text_90beaaeae893"));
			FilteredPickupItems = config.Bind<string>("Pickup Filter", "Items", string.Empty, RunicText.Get("text_c2e4efc127e7"));
			SortRows = config.Bind<string>("Sort", "Rows", "1,2", RunicText.Get("text_cfd403f31628"));
			Quick1 = config.Bind<KeyboardShortcut>("Keyboard", "UseQuickSlot1", new KeyboardShortcut((KeyCode)49, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), RunicText.Get("text_c19bc8ec2e08"));
			Quick2 = config.Bind<KeyboardShortcut>("Keyboard", "UseQuickSlot2", new KeyboardShortcut((KeyCode)50, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), RunicText.Get("text_4a213600b47c"));
			Quick3 = config.Bind<KeyboardShortcut>("Keyboard", "UseQuickSlot3", new KeyboardShortcut((KeyCode)51, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), RunicText.Get("text_dfce180bc2ee"));
			Sort = config.Bind<KeyboardShortcut>("Keyboard", "SortSelectedRows", new KeyboardShortcut((KeyCode)105, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), RunicText.Get("text_6c6419e7f4d1"));
			ToggleLock = config.Bind<KeyboardShortcut>("Keyboard", "ToggleFocusedSlotLock", new KeyboardShortcut((KeyCode)108, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), RunicText.Get("text_31d0dc2a5d57"));
			ControllerEnabled = config.Bind<bool>("Controller", "Enabled", true, RunicText.Get("text_d760c9e83479"));
			ControllerModifier = config.Bind<string>("Controller", "ModifierAction", "JoyAltKeys", RunicText.Get("text_0040e54c0301"));
			ControllerQuick1 = config.Bind<string>("Controller", "UseQuickSlot1Action", "JoyMap", RunicText.Get("text_21358e79d50b"));
			ControllerQuick2 = config.Bind<string>("Controller", "UseQuickSlot2Action", "JoyButtonY", RunicText.Get("text_78efbbf396ce"));
			ControllerQuick3 = config.Bind<string>("Controller", "UseQuickSlot3Action", "JoyRBumper", RunicText.Get("text_d88ee291d981"));
			ControllerSort = config.Bind<string>("Controller", "SortSelectedRowsAction", "JoyButtonA", RunicText.Get("text_454da9489f48"));
			ControllerToggleLock = config.Bind<string>("Controller", "ToggleFocusedSlotLockAction", "JoyButtonB", RunicText.Get("text_cece443edf13"));
			VerboseDiagnostics = config.Bind<bool>("Diagnostics", "Verbose", false, RunicText.Get("text_00bba4d37a51"));
		}
	}
	[BepInPlugin("chazman.RunicInventory", "Runic Inventory", "1.1.10")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Guid = "chazman.RunicInventory";

		public const string Name = "Runic Inventory";

		public const string Version = "1.1.10";

		public const string ModuleId = "runic.inventory";

		public const string ProtocolVersion = "1.0";

		private readonly List<KeybindingRegistration> _bindings = new List<KeybindingRegistration>();

		private readonly KeybindingConflictRegistry _keybindings = new KeybindingConflictRegistry();

		private Harmony _harmony;

		private InventoryRuntime _runtime;

		private bool _configurationSubscribed;

		private bool _inputLayoutSubscribed;

		private bool _shuttingDown;

		internal static Plugin Instance { get; private set; }

		internal static bool RuntimeReady { get; private set; }

		internal InventoryRuntime Runtime => _runtime;

		private void Awake()
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Expected O, but got Unknown
			Instance = this;
			Diagnostics.Initialize(((BaseUnityPlugin)this).Logger);
			InventoryIntegrationApi.BeginInitialization();
			try
			{
				InventoryConfig.Bind(((BaseUnityPlugin)this).Config);
				((BaseUnityPlugin)this).Config.SettingChanged += OnSettingChanged;
				_configurationSubscribed = true;
				ZInput.OnInputLayoutChanged += OnInputLayoutChanged;
				_inputLayoutSubscribed = true;
				if (!ValheimContracts.Initialize(out var problem))
				{
					throw new MissingMethodException(problem);
				}
				_runtime = new InventoryRuntime(batch: false);
				_harmony = new Harmony("chazman.RunicInventory");
				_harmony.PatchAll(typeof(Plugin).Assembly);
				BetterArcheryCompatibility.Initialize(_harmony);
				RegisterBindings();
				_runtime.Initialize();
				InventoryIntegrationApi.Attach(_runtime);
				RuntimeReady = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Runic Inventory v1.1.10 ready. Native owner-local topology, locks, sort, quick use, equipment relocation, saves, and tombstones remain Valheim-owned.");
				if (Application.isBatchMode)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)"Batch transport detected: only an exact owning local Player can activate Inventory; a true dedicated server remains inert.");
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Runic Inventory startup failed: " + ex));
				ShutdownRuntime();
				InventoryIntegrationApi.MarkStartupFailed();
			}
		}

		private void Update()
		{
			if (!RuntimeReady || _runtime == null)
			{
				return;
			}
			try
			{
				_runtime.Tick();
			}
			catch (Exception exception)
			{
				Diagnostics.Error(exception, RunicText.Get("text_6586951ebeea"));
				_runtime.FailClosed("runtime.exception");
			}
		}

		private void OnGUI()
		{
			if (!RuntimeReady || _runtime == null)
			{
				return;
			}
			try
			{
				_runtime.Draw();
			}
			catch (Exception exception)
			{
				Diagnostics.Error(exception, RunicText.Get("text_634f4fd622aa"));
			}
		}

		private void OnSettingChanged(object sender, SettingChangedEventArgs arguments)
		{
			if (!RuntimeReady || _runtime == null || (object)((arguments != null) ? arguments.ChangedSetting : null) == InventoryConfig.CompactQuiverLayout)
			{
				return;
			}
			try
			{
				_runtime.OnConfigurationChanged();
			}
			catch (Exception exception)
			{
				Diagnostics.Error(exception, RunicText.Get("text_c0e41f8a2d26"));
				_runtime.FailClosed("config.refresh-failed");
			}
			try
			{
				RefreshBindings();
			}
			catch (Exception exception2)
			{
				Diagnostics.Error(exception2, RunicText.Get("text_7c7aad401442"));
			}
		}

		private void OnInputLayoutChanged()
		{
			ControllerChordSession.Reset();
			Diagnostics.Trace("Controller input layout changed; Inventory bindings will be re-resolved.");
		}

		private void OnDestroy()
		{
			ShutdownRuntime();
			Diagnostics.Initialize(null);
			Instance = null;
		}

		private void RegisterBindings()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
			ConfigEntry<bool> enabled = InventoryConfig.Enabled;
			if (enabled != null && enabled.Value)
			{
				RegisterKeyboard("quick-1", "Use quick slot 1", InventoryConfig.Quick1.Value, "gameplay");
				RegisterKeyboard("quick-2", "Use quick slot 2", InventoryConfig.Quick2.Value, "gameplay");
				RegisterKeyboard("quick-3", "Use quick slot 3", InventoryConfig.Quick3.Value, "gameplay");
				RegisterKeyboard("sort", "Sort selected safe inventory rows", InventoryConfig.Sort.Value, "inventory");
				RegisterKeyboard("lock", "Toggle focused inventory slot lock", InventoryConfig.ToggleLock.Value, "inventory");
				ConfigEntry<bool> controllerEnabled = InventoryConfig.ControllerEnabled;
				if (controllerEnabled != null && controllerEnabled.Value)
				{
					string modifier = BoundControllerAction(InventoryConfig.ControllerModifier.Value);
					string quick = BoundControllerAction(InventoryConfig.ControllerQuick1.Value);
					string text = BoundControllerAction(InventoryConfig.ControllerQuick2.Value);
					string text2 = BoundControllerAction(InventoryConfig.ControllerQuick3.Value);
					string text3 = BoundControllerAction(InventoryConfig.ControllerSort.Value);
					string text4 = BoundControllerAction(InventoryConfig.ControllerToggleLock.Value);
					quick = ControllerBindingPolicy.EffectiveQuick1Action(modifier, quick, text, text2, text3, text4, out var _);
					RegisterController("controller-quick-1", "Use quick slot 1", quick, modifier, "gameplay");
					RegisterController("controller-quick-2", "Use quick slot 2", text, modifier, "gameplay");
					RegisterController("controller-quick-3", "Use quick slot 3", text2, modifier, "gameplay");
					RegisterController("controller-sort", "Sort selected safe inventory rows", text3, modifier, "inventory");
					RegisterController("controller-lock", "Toggle focused inventory slot lock", text4, modifier, "inventory");
				}
			}
		}

		private void RefreshBindings()
		{
			DisposeBindings();
			try
			{
				RegisterBindings();
			}
			catch
			{
				DisposeBindings();
				throw;
			}
		}

		private void DisposeBindings()
		{
			for (int num = _bindings.Count - 1; num >= 0; num--)
			{
				try
				{
					_bindings[num].Dispose();
				}
				catch (Exception exception)
				{
					Diagnostics.Error(exception, RunicText.Get("text_bee5ee3f3cbd"));
				}
			}
			_bindings.Clear();
		}

		private unsafe void RegisterKeyboard(string id, string display, KeyboardShortcut shortcut, string context)
		{
			//IL_0002: 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_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0)
			{
				return;
			}
			List<string> list = new List<string>();
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers)
			{
				if (list.Count >= 8)
				{
					throw new InvalidOperationException("A keyboard chord may contain at most eight modifiers.");
				}
				list.Add(((object)(*(KeyCode*)(&modifier))/*cast due to .constrained prefix*/).ToString());
			}
			_bindings.Add(_keybindings.Register(new KeybindingDescriptor("runic.inventory", id, display, new InputChord("keyboard", ((object)((KeyboardShortcut)(ref shortcut)).MainKey/*cast due to .constrained prefix*/).ToString(), list), context)));
		}

		private void RegisterController(string id, string display, string action, string modifier, string context)
		{
			if (action.Length == 0 || modifier.Length == 0)
			{
				return;
			}
			try
			{
				_bindings.Add(_keybindings.Register(new KeybindingDescriptor("runic.inventory", id, display, new InputChord("controller", action, new string[1] { modifier }), context)));
			}
			catch (ArgumentException)
			{
				Diagnostics.Warn("Inventory skipped invalid controller route: " + id + ".");
			}
		}

		private static string BoundControllerAction(string value)
		{
			string text = value ?? string.Empty;
			if (text.Length == 0 || text.Length > 64)
			{
				return string.Empty;
			}
			string text2 = text.Trim();
			if (!text2.StartsWith("Joy", StringComparison.Ordinal))
			{
				return string.Empty;
			}
			for (int i = 0; i < text2.Length; i++)
			{
				if (!char.IsLetterOrDigit(text2[i]) && text2[i] != '_' && text2[i] != '-')
				{
					return string.Empty;
				}
			}
			return text2;
		}

		private void ShutdownRuntime()
		{
			if (_shuttingDown)
			{
				return;
			}
			_shuttingDown = true;
			RuntimeReady = false;
			InventoryRuntime runtime = _runtime;
			InventoryIntegrationApi.Detach(runtime);
			if (_configurationSubscribed)
			{
				((BaseUnityPlugin)this).Config.SettingChanged -= OnSettingChanged;
				_configurationSubscribed = false;
			}
			if (_inputLayoutSubscribed)
			{
				ZInput.OnInputLayoutChanged -= OnInputLayoutChanged;
				_inputLayoutSubscribed = false;
			}
			ControllerChordSession.Reset();
			DisposeBindings();
			try
			{
				runtime?.Dispose();
			}
			catch (Exception exception)
			{
				Diagnostics.Error(exception, RunicText.Get("text_bf7b364b87ab"));
			}
			_runtime = null;
			try
			{
				Harmony harmony = _harmony;
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
			}
			catch (Exception exception2)
			{
				Diagnostics.Error(exception2, RunicText.Get("text_749140dc00e4"));
			}
			_harmony = null;
			BetterArcheryCompatibility.Reset();
		}
	}
}
namespace RunicInventory.Integration
{
	internal static class BetterArcheryCompatibility
	{
		internal const string Guid = "ishid4.mods.betterarchery";

		internal const string AuditedHash = "549B3B6AC69C512E4B3BA1EEECD34687ACB72712A3B068BD1D2783B06BE1F823";

		private static ConfigEntry<bool> _enabled;

		private static FieldInfo _row;

		private static MethodInfo _equipped;

		private static MethodInfo _getElement;

		private static MethodInfo _binding;

		private static ConfigEntry<KeyboardShortcut> _holdingKey;

		private static FieldInfo _hasAuga;

		internal static bool Active
		{
			get
			{
				ConfigEntry<bool> enabled = _enabled;
				if (enabled != null && enabled.Value)
				{
					return _row != null;
				}
				return false;
			}
		}

		internal static int QuiverRow
		{
			get
			{
				if (!Active)
				{
					return -1;
				}
				return (int)_row.GetValue(null);
			}
		}

		internal static bool Equipped
		{
			get
			{
				if (Active)
				{
					return (bool)_equipped.Invoke(null, null);
				}
				return false;
			}
		}

		internal static void Initialize(Harmony harmony)
		{
			//IL_02eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f9: Expected O, but got Unknown
			//IL_030d: Unknown result type (might be due to invalid IL or missing references)
			//IL_031b: Expected O, but got Unknown
			//IL_032f: Unknown result type (might be due to invalid IL or missing references)
			//IL_033d: Expected O, but got Unknown
			//IL_0351: Unknown result type (might be due to invalid IL or missing references)
			//IL_035f: Expected O, but got Unknown
			//IL_0373: Unknown result type (might be due to invalid IL or missing references)
			//IL_0381: Expected O, but got Unknown
			//IL_0395: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a3: Expected O, but got Unknown
			//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cf: Expected O, but got Unknown
			if (!Chainloader.PluginInfos.TryGetValue("ishid4.mods.betterarchery", out var value) || (Object)(object)value.Instance == (Object)null)
			{
				return;
			}
			Assembly assembly = ((object)value.Instance).GetType().Assembly;
			using (FileStream inputStream = File.OpenRead(assembly.Location))
			{
				using SHA256 sHA = SHA256.Create();
				if (BitConverter.ToString(sHA.ComputeHash(inputStream)).Replace("-", "") != "549B3B6AC69C512E4B3BA1EEECD34687ACB72712A3B068BD1D2783B06BE1F823")
				{
					Diagnostics.Warn("Better Archery binary is not the audited quiver build; automatic layout integration was not enabled.");
					return;
				}
			}
			Type type = assembly.GetType("BetterArchery.BetterArchery", throwOnError: true);
			FieldInfo fieldInfo = AccessTools.Field(type, "QuiverRowIndex");
			ConfigEntry<bool> val = AccessTools.Field(type, "ConfigQuiverEnabled")?.GetValue(null) as ConfigEntry<bool>;
			MethodInfo methodInfo = AccessTools.Method(type, "IsQuiverEquipped", Type.EmptyTypes, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(type, "GetBindingKeycode", new Type[1] { typeof(int) }, (Type[])null);
			ConfigEntry<KeyboardShortcut> val2 = AccessTools.Field(type, "HoldingKeyCode")?.GetValue(null) as ConfigEntry<KeyboardShortcut>;
			MethodInfo methodInfo3 = AccessTools.Method(assembly.GetType("BetterArchery.InventoryGrid_UpdateGui_Patch", throwOnError: true), "HideModRows", (Type[])null, (Type[])null);
			MethodInfo methodInfo4 = AccessTools.Method(assembly.GetType("BetterArchery.InventoryGrid_UpdateGui_Patch", throwOnError: true), "Postfix", (Type[])null, (Type[])null);
			MethodInfo methodInfo5 = AccessTools.Method(assembly.GetType("BetterArchery.Tombstone+TombStone_OnTakeAllSuccess_Patch", throwOnError: true), "Postfix", (Type[])null, (Type[])null);
			MethodInfo methodInfo6 = AccessTools.Method(assembly.GetType("BetterArchery.TerminalAwake_Patch+<>c", throwOnError: true), "<Postfix>b__0_0", (Type[])null, (Type[])null);
			MethodInfo methodInfo7 = AccessTools.Method(assembly.GetType("BetterArchery.Player_SetInventorySize_Patch", throwOnError: true), "Prefix", (Type[])null, (Type[])null);
			MethodInfo methodInfo8 = AccessTools.Method(assembly.GetType("BetterArchery.Inventory_FindEmptySlot_Patch", throwOnError: true), "Prefix", (Type[])null, (Type[])null);
			MethodInfo methodInfo9 = AccessTools.Method(assembly.GetType("BetterArchery.Inventory_HaveEmptySlot_Patch", throwOnError: true), "Prefix", (Type[])null, (Type[])null);
			MethodInfo methodInfo10 = AccessTools.Method(typeof(InventoryGrid), "GetElement", new Type[3]
			{
				typeof(int),
				typeof(int),
				typeof(int)
			}, (Type[])null);
			if (fieldInfo?.FieldType != typeof(int) || val == null || methodInfo?.ReturnType != typeof(bool) || methodInfo3 == null || methodInfo5 == null || methodInfo6 == null || methodInfo7 == null || methodInfo8 == null || methodInfo9 == null || methodInfo10 == null || methodInfo2?.ReturnType != typeof(KeyCode) || val2 == null)
			{
				throw new MissingMemberException("Better Archery quiver contract changed.");
			}
			harmony.Patch((MethodBase)methodInfo3, new HarmonyMethod(typeof(BetterArcheryCompatibility), "HideRows", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)methodInfo5, new HarmonyMethod(typeof(BetterArcheryCompatibility), "AllowLegacyRecovery", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)methodInfo6, new HarmonyMethod(typeof(BetterArcheryCompatibility), "AllowDebugCommand", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)methodInfo7, new HarmonyMethod(typeof(BetterArcheryCompatibility), "AllowArcheryResize", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)methodInfo8, new HarmonyMethod(typeof(BetterArcheryCompatibility), "AllowArcheryFind", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)methodInfo9, new HarmonyMethod(typeof(BetterArcheryCompatibility), "AllowArcheryCapacity", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			try
			{
				if (methodInfo4 != null)
				{
					harmony.Patch((MethodBase)methodInfo4, (HarmonyMethod)null, new HarmonyMethod(typeof(BetterArcheryCompatibility), "CompactPanel", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
			catch (Exception exception)
			{
				CompactQuiverPanel.Fault(exception);
			}
			_hasAuga = AccessTools.Field(type, "HasAuga");
			_row = fieldInfo;
			_equipped = methodInfo;
			_getElement = methodInfo10;
			_enabled = val;
			_binding = methodInfo2;
			_holdingKey = val2;
			Diagnostics.Info("Better Archery quiver compatibility ready with HarmonyX resize/slot guards. Quiver and Runic roles use separate reserved rows. Configure distinct quiver/quick-slot hotkeys if needed.");
		}

		private static bool AllowArcheryResize(Player __0, ref bool __result)
		{
			if (Plugin.Instance?.Runtime?.HandlesNativeInventorySize(__0) != true)
			{
				return true;
			}
			__result = false;
			return false;
		}

		private static bool AllowArcheryFind(Inventory __0, ref Vector2i __1, bool __2, ref bool __result)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			InventoryRuntime inventoryRuntime = Plugin.Instance?.Runtime;
			if (inventoryRuntime == null || !inventoryRuntime.TryFindEmptySlot(__0, __2, out var result))
			{
				return true;
			}
			__1 = result;
			__result = false;
			return false;
		}

		private static bool AllowArcheryCapacity(Inventory __0, ref bool __1, ref bool __result)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			InventoryRuntime inventoryRuntime = Plugin.Instance?.Runtime;
			if (inventoryRuntime == null || !inventoryRuntime.TryFindEmptySlot(__0, topFirst: true, out var result))
			{
				return true;
			}
			__1 = result.x >= 0 && result.y >= 0;
			__result = false;
			return false;
		}

		internal static void SetQuiverRow(int row)
		{
			if (Active)
			{
				_row.SetValue(null, row);
			}
		}

		internal static bool QuiverShortcutDown()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			if (!Equipped)
			{
				return false;
			}
			KeyboardShortcut value = _holdingKey.Value;
			KeyCode mainKey = ((KeyboardShortcut)(ref value)).MainKey;
			if ((int)mainKey != 0 && !Input.GetKey(mainKey))
			{
				return false;
			}
			for (int i = 0; i < 3; i++)
			{
				if (Input.GetKeyDown((KeyCode)_binding.Invoke(null, new object[1] { i })))
				{
					return true;
				}
			}
			return false;
		}

		internal static void Reset()
		{
			CompactQuiverPanel.Restore();
			_enabled = null;
			_holdingKey = null;
			_row = null;
			_equipped = (_getElement = (_binding = null));
			_hasAuga = null;
		}

		private static void CompactPanel(InventoryGrid __0)
		{
			try
			{
				if ((Object)(object)__0 == (Object)null || ((Object)__0).name != "PlayerGrid")
				{
					return;
				}
				if (!OwnsLayout(__0.GetInventory()) || __0.GetInventory().GetHeight() != QuiverRow + 2 || (bool?)_hasAuga?.GetValue(null) == true)
				{
					CompactQuiverPanel.Restore();
					return;
				}
				CompactQuiverPanel.Apply(__0, delegate(int x, int y)
				{
					object? obj = _getElement.Invoke(__0, new object[3] { x, y, 8 });
					return (Component)((obj is Component) ? obj : null);
				}, Equipped);
			}
			catch (Exception exception)
			{
				CompactQuiverPanel.Fault(exception);
			}
		}

		private static bool OwnsLayout(Inventory inventory)
		{
			if (Active && (Object)(object)Player.m_localPlayer != (Object)null && ((Humanoid)Player.m_localPlayer).GetInventory() == inventory)
			{
				Dictionary<string, string> customData = Player.m_localPlayer.m_customData;
				if (customData != null && customData.ContainsKey("runic.inventory.betterarchery.v1"))
				{
					return Player.m_localPlayer.m_customData.ContainsKey("runic.inventory.extra-row.v1");
				}
			}
			return false;
		}

		private static bool HideRows(InventoryGrid __0, IList __1)
		{
			Inventory val = ((__0 != null) ? __0.GetInventory() : null);
			if (!OwnsLayout(val))
			{
				return true;
			}
			int quiverRow = QuiverRow;
			if (quiverRow < 5 || quiverRow + 1 != val.GetHeight() - 1)
			{
				return false;
			}
			bool equipped = Equipped;
			for (int i = quiverRow - 1; i <= quiverRow + 1; i++)
			{
				for (int j = 0; j < 8; j++)
				{
					object? obj = _getElement.Invoke(__0, new object[3]
					{
						j,
						i,
						val.GetWidth()
					});
					Component val2 = (Component)((obj is Component) ? obj : null);
					if ((Object)(object)val2 != (Object)null)
					{
						val2.gameObject.SetActive(i == quiverRow + 1 || (i == quiverRow && j < 3 && equipped));
					}
				}
			}
			return false;
		}

		private static bool AllowLegacyRecovery()
		{
			Player localPlayer = Player.m_localPlayer;
			return !OwnsLayout((localPlayer != null) ? ((Humanoid)localPlayer).GetInventory() : null);
		}

		private static bool AllowDebugCommand(ConsoleEventArgs __0)
		{
			Player localPlayer = Player.m_localPlayer;
			if (!OwnsLayout((localPlayer != null) ? ((Humanoid)localPlayer).GetInventory() : null) || __0.Length < 2 || __0.FullLine.Substring(__0[0].Length + 1) != "drop")
			{
				return true;
			}
			__0.Context.AddString("Runic Inventory: ba drop assumes extra rows are invalid. Move items manually while the combined quiver layout is active.");
			return false;
		}
	}
	internal static class CompactQuiverPanel
	{
		private static readonly RectTransform[] Cells = (RectTransform[])(object)new RectTransform[8];

		private static FieldInfo _baseHeight;

		private static FieldInfo _rowHeight;

		private static RectTransform _panel;

		private static float _originalY;

		private static float _appliedY;

		private static float _originalHeight;

		private static float _appliedHeight;

		private static bool _warned;

		internal static void Apply(InventoryGrid grid, Func<int, int, Component> element, bool equipped)
		{
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: 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_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: 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_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02df: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0294: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
			Inventory inventory = grid.GetInventory();
			InventoryGui instance = InventoryGui.instance;
			if (inventory == null || (Object)(object)instance == (Object)null || (Object)(object)instance.m_player == (Object)null)
			{
				Restore();
				return;
			}
			Component obj = element(0, 0);
			Transform obj2 = ((obj != null) ? obj.transform : null);
			RectTransform val = (RectTransform)(object)((obj2 is RectTransform) ? obj2 : null);
			if ((Object)(object)val == (Object)null)
			{
				Restore();
				return;
			}
			int num = inventory.GetHeight() - 1;
			float? num2 = null;
			if (equipped)
			{
				for (int i = 0; i < 3; i++)
				{
					Component obj3 = element(i, num - 1);
					Transform obj4 = ((obj3 != null) ? obj3.transform : null);
					RectTransform val2 = (RectTransform)(object)((obj4 is RectTransform) ? obj4 : null);
					if ((Object)(object)val2 == (Object)null || !((Component)val2).gameObject.activeSelf || (Object)(object)((Transform)val2).parent != (Object)(object)((Transform)val).parent)
					{
						Restore();
						return;
					}
					num2 = Math.Min(num2 ?? val2.anchoredPosition.y, val2.anchoredPosition.y);
				}
			}
			if (!QuiverPanelLayout.TryPlan(num - 2, grid.m_elementSpace, val.anchoredPosition.y, num2, InventoryConfig.CompactQuiverLayout.Value, out var equipmentY, out var removedHeight))
			{
				Restore();
				return;
			}
			_baseHeight = _baseHeight ?? AccessTools.Field(typeof(InventoryGui), "m_playerHeight");
			_rowHeight = _rowHeight ?? AccessTools.Field(typeof(InventoryGui), "m_invGridHeight");
			float num3 = (float)_baseHeight.GetValue(instance) + (float)(inventory.GetHeight() - 4) * (float)_rowHeight.GetValue(instance);
			if (num3 <= removedHeight || float.IsNaN(num3) || float.IsInfinity(num3))
			{
				Restore();
				return;
			}
			for (int j = 0; j < 8; j++)
			{
				Component obj5 = element(j, num);
				Transform obj6 = ((obj5 != null) ? obj5.transform : null);
				RectTransform val3 = (RectTransform)(object)((obj6 is RectTransform) ? obj6 : null);
				if ((Object)(object)val3 == (Object)null || (Object)(object)((Transform)val3).parent != (Object)(object)((Transform)val).parent)
				{
					Restore();
					return;
				}
			}
			_originalY = val.anchoredPosition.y - (float)num * grid.m_elementSpace;
			_appliedY = equipmentY;
			for (int k = 0; k < 8; k++)
			{
				ref RectTransform reference = ref Cells[k];
				Transform transform = element(k, num).transform;
				reference = (RectTransform)(object)((transform is RectTransform) ? transform : null);
				Vector2 anchoredPosition = Cells[k].anchoredPosition;
				anchoredPosition.y = equipmentY;
				if (Cells[k].anchoredPosition != anchoredPosition)
				{
					Cells[k].anchoredPosition = anchoredPosition;
				}
			}
			_panel = instance.m_player;
			_originalHeight = num3;
			_appliedHeight = num3 - removedHeight;
			Vector2 sizeDelta = _panel.sizeDelta;
			sizeDelta.y = _appliedHeight;
			if (_panel.sizeDelta != sizeDelta)
			{
				_panel.sizeDelta = sizeDelta;
			}
		}

		internal static void Fault(Exception exception)
		{
			Restore();
			if (!_warned)
			{
				_warned = true;
				Diagnostics.Error(exception, RunicText.Get("text_2e2ca90ffe5a"));
			}
		}

		internal static void Restore()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: 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_0034: 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_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: 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)
			RectTransform[] cells = Cells;
			foreach (RectTransform val in cells)
			{
				if ((Object)(object)val != (Object)null && Mathf.Approximately(val.anchoredPosition.y, _appliedY))
				{
					Vector2 anchoredPosition = val.anchoredPosition;
					anchoredPosition.y = _originalY;
					val.anchoredPosition = anchoredPosition;
				}
			}
			if ((Object)(object)_panel != (Object)null && Mathf.Approximately(_panel.sizeDelta.y, _appliedHeight))
			{
				Vector2 sizeDelta = _panel.sizeDelta;
				sizeDelta.y = _originalHeight;
				_panel.sizeDelta = sizeDelta;
			}
			Array.Clear(Cells, 0, Cells.Length);
			_panel = null;
		}
	}
	internal sealed class ControllerBindingState
	{
		internal const int DefinitionCount = 6;

		internal ButtonDef Modifier { get; }

		internal ButtonDef Quick1 { get; }

		internal ButtonDef Quick2 { get; }

		internal ButtonDef Quick3 { get; }

		internal ButtonDef Sort { get; }

		internal ButtonDef ToggleLock { get; }

		internal string ReasonCode { get; }

		internal bool LegacyQuick1Mapped { get; }

		internal int ValidRouteCount { get; }

		internal bool Ready
		{
			get
			{
				if (Modifier != null)
				{
					return ValidRouteCount > 0;
				}
				return false;
			}
		}

		internal bool AllValid
		{
			get
			{
				if (Modifier != null)
				{
					return ValidRouteCount == 5;
				}
				return false;
			}
		}

		internal ControllerBindingState(ButtonDef modifier, ButtonDef quick1, ButtonDef quick2, ButtonDef quick3, ButtonDef sort, ButtonDef toggleLock, string reasonCode, bool legacyQuick1Mapped)
		{
			Modifier = modifier;
			Quick1 = quick1;
			Quick2 = quick2;
			Quick3 = quick3;
			Sort = sort;
			ToggleLock = toggleLock;
			ReasonCode = reasonCode ?? "controller.invalid";
			LegacyQuick1Mapped = legacyQuick1Mapped;
			ValidRouteCount = ((quick1 != null) ? 1 : 0) + ((quick2 != null) ? 1 : 0) + ((quick3 != null) ? 1 : 0) + ((sort != null) ? 1 : 0) + ((toggleLock != null) ? 1 : 0);
		}

		internal ButtonDef Definition(int index)
		{
			return (ButtonDef)(index switch
			{
				0 => Modifier, 
				1 => Quick1, 
				2 => Quick2, 
				3 => Quick3, 
				4 => Sort, 
				5 => ToggleLock, 
				_ => throw new ArgumentOutOfRangeException("index"), 
			});
		}
	}
	internal static class ControllerBindings
	{
		private static ZInput _instance;

		private static ControllerBindingState _cached;

		internal static ControllerBindingState Resolve()
		{
			if (_cached != null && _instance == ZInput.instance)
			{
				return _cached;
			}
			string text = Name(InventoryConfig.ControllerModifier?.Value);
			string quick = Name(InventoryConfig.ControllerQuick1?.Value);
			string text2 = Name(InventoryConfig.ControllerQuick2?.Value);
			string text3 = Name(InventoryConfig.ControllerQuick3?.Value);
			string text4 = Name(InventoryConfig.ControllerSort?.Value);
			string text5 = Name(InventoryConfig.ControllerToggleLock?.Value);
			quick = ControllerBindingPolicy.EffectiveQuick1Action(text, quick, text2, text3, text4, text5, out var legacyMapped);
			_instance = ZInput.instance;
			if (_instance == null)
			{
				return _cached = new ControllerBindingState(null, null, null, null, null, null, "controller.zinput-unavailable", legacyMapped);
			}
			string path;
			ButtonDef val = ResolveAction(text, out path);
			string[] array = new string[5] { quick, text2, text3, text4, text5 };
			string[] array2 = new string[5];
			ButtonDef[] array3 = (ButtonDef[])(object)new ButtonDef[5];
			for (int i = 0; i < 5; i++)
			{
				array3[i] = ResolveAction(array[i], out array2[i]);
			}
			int num = ControllerBindingPolicy.ValidRouteMask(text, path, array, array2);
			for (int j = 0; j < 5; j++)
			{
				if (!ControllerBindingPolicy.RouteIsValid(num, j))
				{
					array3[j] = null;
				}
			}
			string reasonCode = ((val == null) ? "controller.modifier-invalid" : (num switch
			{
				0 => "controller.no-valid-routes", 
				31 => "ok", 
				_ => "controller.one-or-more-routes-invalid", 
			}));
			return _cached = new ControllerBindingState(val, array3[0], array3[1], array3[2], array3[3], array3[4], reasonCode, legacyMapped);
		}

		internal static void Invalidate()
		{
			_instance = null;
			_cached = null;
		}

		internal static bool ShouldReserveAction(string action)
		{
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Invalid comparison between Unknown and I4
			ConfigEntry<bool> controllerEnabled = InventoryConfig.ControllerEnabled;
			if (controllerEnabled == null || !controllerEnabled.Value || string.IsNullOrEmpty(action) || ZInput.instance == null)
			{
				return false;
			}
			ControllerBindingState controllerBindingState = Resolve();
			if (controllerBindingState.Ready && controllerBindingState.Modifier.Held)
			{
				ButtonDef quick = controllerBindingState.Quick1;
				if (quick == null || !quick.Pressed)
				{
					ButtonDef quick2 = controllerBindingState.Quick2;
					if (quick2 == null || !quick2.Pressed)
					{
						ButtonDef quick3 = controllerBindingState.Quick3;
						if (quick3 == null || !quick3.Pressed)
						{
							ButtonDef sort = controllerBindingState.Sort;
							if (sort == null || !sort.Pressed)
							{
								ButtonDef toggleLock = controllerBindingState.ToggleLock;
								if (toggleLock == null || !toggleLock.Pressed)
								{
									goto IL_00a3;
								}
							}
						}
					}
				}
				ButtonDef buttonDef;
				try
				{
					buttonDef = ZInput.instance.GetButtonDef(action);
				}
				catch (Exception)
				{
					return false;
				}
				if (buttonDef == null || (int)buttonDef.Source != 180)
				{
					return false;
				}
				string actionPath;
				try
				{
					actionPath = buttonDef.GetActionPath(true);
				}
				catch (Exception)
				{
					return false;
				}
				if (!SamePath(actionPath, controllerBindingState.Modifier) && !SamePath(actionPath, controllerBindingState.Quick1) && !SamePath(actionPath, controllerBindingState.Quick2) && !SamePath(actionPath, controllerBindingState.Quick3) && !SamePath(actionPath, controllerBindingState.Sort))
				{
					return SamePath(actionPath, controllerBindingState.ToggleLock);
				}
				return true;
			}
			goto IL_00a3;
			IL_00a3:
			return false;
		}

		private static ButtonDef ResolveAction(string action, out string path)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Invalid comparison between Unknown and I4
			path = string.Empty;
			if (action.Length == 0 || action.Length > 64 || !action.StartsWith("Joy", StringComparison.Ordinal))
			{
				return null;
			}
			ButtonDef buttonDef;
			try
			{
				buttonDef = ZInput.instance.GetButtonDef(action);
			}
			catch (Exception)
			{
				return null;
			}
			if (buttonDef == null || (int)buttonDef.Source != 180)
			{
				return null;
			}
			try
			{
				path = buttonDef.GetActionPath(true)?.Trim() ?? string.Empty;
			}
			catch (Exception)
			{
				return null;
			}
			if (path.Length != 0)
			{
				return buttonDef;
			}
			return null;
		}

		private static string Name(string value)
		{
			string text = value ?? string.Empty;
			if (text.Length == 0 || text.Length > 64)
			{
				return string.Empty;
			}
			string text2 = text.Trim();
			for (int i = 0; i < text2.Length; i++)
			{
				if (!char.IsLetterOrDigit(text2[i]) && text2[i] != '_' && text2[i] != '-')
				{
					return string.Empty;
				}
			}
			return text2;
		}

		private static bool SamePath(string path, ButtonDef definition)
		{
			if (string.IsNullOrEmpty(path) || definition == null)
			{
				return false;
			}
			try
			{
				return string.Equals(path, definition.GetActionPath(true), StringComparison.Ordinal);
			}
			catch (Exception)
			{
				return false;
			}
		}
	}
	internal static class KeyboardInput
	{
		private static readonly KeyCode[] ModifierKeys;

		internal static bool ShortcutDown(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_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_0041: 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_0052: 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;
			}
			int num = 0;
			int num2 = 0;
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers)
			{
				if (++num2 > 8)
				{
					return false;
				}
				if ((int)modifier == 0 || !ZInput.GetKey(modifier, false))
				{
					return false;
				}
				int num3 = ModifierIndex(modifier);
				if (num3 >= 0)
				{
					num |= 1 << num3;
				}
			}
			for (int i = 0; i < ModifierKeys.Length; i++)
			{
				if ((num & (1 << i)) == 0 && ZInput.GetKey(ModifierKeys[i], false))
				{
					return false;
				}
			}
			return true;
		}

		internal static bool ShouldReserveVanillaAction(string action)
		{
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: 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_010b: 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_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: 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_00ed: 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_0123: Unknown result type (might be due to invalid IL or missing references)
			KeyCode val = (KeyCode)(action switch
			{
				"Hotbar1" => 49, 
				"Hotbar2" => 50, 
				"Hotbar3" => 51, 
				"Hotbar4" => 52, 
				"Hotbar5" => 53, 
				"Hotbar6" => 54, 
				"Hotbar7" => 55, 
				"Hotbar8" => 56, 
				_ => 0, 
			});
			if ((int)val == 0)
			{
				return false;
			}
			if (!IsChordFor(val, InventoryConfig.Quick1.Value) && !IsChordFor(val, InventoryConfig.Quick2.Value))
			{
				return IsChordFor(val, InventoryConfig.Quick3.Value);
			}
			return true;
		}

		private static bool IsChordFor(KeyCode key, KeyboardShortcut shortcut)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (((KeyboardShortcut)(ref shortcut)).MainKey == key)
			{
				return ShortcutDown(shortcut);
			}
			return false;
		}

		private static int ModifierIndex(KeyCode value)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Invalid comparison between I4 and Unknown
			for (int i = 0; i < ModifierKeys.Length; i++)
			{
				if ((int)ModifierKeys[i] == (int)value)
				{
					return i;
				}
			}
			return -1;
		}

		static KeyboardInput()
		{
			KeyCode[] array = new KeyCode[8];
			RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
			ModifierKeys = (KeyCode[])(object)array;
		}
	}
	internal static class InputReservation
	{
		internal static bool ShouldSuppress(string action)
		{
			InventoryRuntime inventoryRuntime = Plugin.Instance?.Runtime;
			if (!Plugin.RuntimeReady || inventoryRuntime == null || !inventoryRuntime.AcceptsInput)
			{
				return false;
			}
			if (!ControllerChordSession.ShouldSuppress(action) && !ControllerBindings.ShouldReserveAction(action))
			{
				return KeyboardInput.ShouldReserveVanillaAction(action);
			}
			return true;
		}
	}
	internal static class ControllerInput
	{
		private static ControllerBindingState _loggedBindings;

		internal static void Tick(InventoryRuntime runtime, bool inventoryVisible, bool gameplayInput)
		{
			if (runtime == null)
			{
				return;
			}
			ConfigEntry<bool> controllerEnabled = InventoryConfig.ControllerEnabled;
			if (controllerEnabled == null || !controllerEnabled.Value || ZInput.instance == null)
			{
				return;
			}
			ControllerBindingState controllerBindingState = ControllerBindings.Resolve();
			if (_loggedBindings != controllerBindingState)
			{
				_loggedBindings = controllerBindingState;
				if (controllerBindingState.AllValid)
				{
					Diagnostics.Info(controllerBindingState.LegacyQuick1Mapped ? "Inventory controller chords validated by six unique effective gamepad paths; the exact legacy default Quick 1 route is using JoyMap." : "Inventory controller chords validated by six unique effective gamepad paths.");
				}
				else if (controllerBindingState.Ready)
				{
					Diagnostics.Warn("Inventory controller chords partially available (" + controllerBindingState.ValidRouteCount + "/5 routes): " + controllerBindingState.ReasonCode + ".");
				}
				else
				{
					Diagnostics.Warn("Inventory controller chords disabled: " + controllerBindingState.ReasonCode + ".");
				}
			}
			bool active = ControllerChordSession.Active;
			if (!controllerBindingState.Ready || active || !controllerBindingState.Modifier.Held)
			{
				return;
			}
			if (inventoryVisible)
			{
				ButtonDef toggleLock = controllerBindingState.ToggleLock;
				if (toggleLock != null && toggleLock.Pressed)
				{
					ControllerChordSession.Begin(controllerBindingState);
					runtime.ToggleFocusedLock("controller");
					return;
				}
			}
			if (inventoryVisible)
			{
				ButtonDef sort = controllerBindingState.Sort;
				if (sort != null && sort.Pressed)
				{
					ControllerChordSession.Begin(controllerBindingState);
					runtime.SortSelectedRows("controller");
					return;
				}
			}
			if (!gameplayInput)
			{
				return;
			}
			ButtonDef quick = controllerBindingState.Quick1;
			if (quick != null && quick.Pressed)
			{
				ControllerChordSession.Begin(controllerBindingState);
				runtime.UseQuick(InventoryRoleKind.Quick1, "controller");
				return;
			}
			ButtonDef quick2 = controllerBindingState.Quick2;
			if (quick2 != null && quick2.Pressed)
			{
				ControllerChordSession.Begin(controllerBindingState);
				runtime.UseQuick(InventoryRoleKind.Quick2, "controller");
				return;
			}
			ButtonDef quick3 = controllerBindingState.Quick3;
			if (quick3 != null && quick3.Pressed)
			{
				ControllerChordSession.Begin(controllerBindingState);
				runtime.UseQuick(InventoryRoleKind.Quick3, "controller");
			}
		}

		internal static void ResetLog()
		{
			_loggedBindings = null;
		}
	}
	internal static class ControllerChordSession
	{
		private static ControllerBindingState _bindings;

		private static readonly HashSet<string> Paths = new HashSet<string>(StringComparer.Ordinal);

		private static int _releasedFrame = -1;

		internal static bool Active
		{
			get
			{
				UpdateRelease();
				return _bindings != null;
			}
		}

		internal static void Begin(ControllerBindingState bindings)
		{
			if (bindings == null || !bindings.Ready || _bindings != null)
			{
				return;
			}
			_bindings = bindings;
			Paths.Clear();
			for (int i = 0; i < 6; i++)
			{
				ButtonDef obj = bindings.Definition(i);
				string text = ((obj != null) ? obj.GetActionPath(true) : null);
				if (!string.IsNullOrEmpty(text))
				{
					Paths.Add(text);
				}
			}
			_releasedFrame = -1;
		}

		internal static bool ShouldSuppress(string action)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Invalid comparison between Unknown and I4
			UpdateRelease();
			if (_bindings == null || ZInput.instance == null || string.IsNullOrEmpty(action))
			{
				return false;
			}
			ButtonDef buttonDef;
			try
			{
				buttonDef = ZInput.instance.GetButtonDef(action);
			}
			catch (Exception)
			{
				return false;
			}
			if (buttonDef == null || (int)buttonDef.Source != 180)
			{
				return false;
			}
			string actionPath;
			try
			{
				actionPath = buttonDef.GetActionPath(true);
			}
			catch (Exception)
			{
				return false;
			}
			if (!string.IsNullOrEmpty(actionPath))
			{
				return Paths.Contains(actionPath);
			}
			return false;
		}

		internal static void Reset()
		{
			_bindings = null;
			Paths.Clear();
			_releasedFrame = -1;
			ControllerBindings.Invalidate();
			ControllerInput.ResetLog();
		}

		private static void UpdateRelease()
		{
			if (_bindings == null)
			{
				return;
			}
			bool flag = false;
			for (int i = 0; i < 6; i++)
			{
				ButtonDef obj = _bindings.Definition(i);
				if (obj != null && obj.Held)
				{
					flag = true;
					break;
				}
			}
			if (flag)
			{
				_releasedFrame = -1;
			}
			else if (_releasedFrame < 0)
			{
				_releasedFrame = Time.frameCount;
			}
			else if (_releasedFrame != Time.frameCount)
			{
				_bindings = null;
				Paths.Clear();
				_releasedFrame = -1;
			}
		}
	}
	internal sealed class InventoryRuntime : IInventoryTopologyService, IInventoryProtectionService, IInventoryStatusService, IItemProtectionQuery, IDisposable
	{
		private sealed class MutationScope : IDisposable
		{
			private InventoryRuntime _owner;

			internal MutationScope(InventoryRuntime owner)
			{
				_owner = owner;
			}

			public void Dispose()
			{
				InventoryRuntime inventoryRuntime = Interlocked.Exchange(ref _owner, null);
				if (inventoryRuntime != null)
				{
					Interlocked.Exchange(ref inventoryRuntime._mutationActive, 0);
				}
			}
		}

		private bool _rowMigration;

		private bool _restoringEnabled;

		private const int MaximumProtectionDiagnostics = 32;

		private readonly bool _batch;

		private readonly int _mainThreadId;

		private readonly Dictionary<StackCapacityKey, int> _stackCapacity = new Dictionary<StackCapacityKey, int>();

		private readonly HashSet<string> _protectionDiagnostics = new HashSet<string>(StringComparer.Ordinal);

		private readonly object _protectionDiagnosticGate = new object();

		private Player _player;

		private Inventory _inventory;

		private TopologyLayout _layout;

		private PersistedTopologyState _persisted;

		private InventoryTopologySnapshot _snapshot;

		private PickupFilterSet _filters;

		private InventoryAuthorityMode _mode;

		private string _reasonCode = "runtime.not-initialized";

		private string _statusText = "Runic Inventory: waiting for the local player.";

		private long _generation;

		private int _freePickupSlots;

		private float _cachedWeight;

		private bool _topologyActive;

		private bool _playerLoadInProgress;

		private bool _loadMetadataRefreshed;

		private int _equipmentTransitionDepth;

		private int _repairAllowanceDepth;

		private int _mutationActive;

		private bool _equipmentRefreshPending;

		private bool _equipmentTransitionFaulted;

		private bool _disableCleanupPending;

		private bool _rebuilding;

		private bool _disposed;

		private float _nextMessageTime;

		private readonly Rect[] _roleSlotRects = (Rect[])(object)new Rect[8];

		private bool HasQuiverLayout
		{
			get
			{
				if (BetterArcheryCompatibility.Active && _player?.m_customData != null && _player.m_customData.ContainsKey("runic.inventory.betterarchery.v1"))
				{
					return _player.m_customData.ContainsKey("runic.inventory.extra-row.v1");
				}
				return false;
			}
		}

		private static string[] RoleLabels => new string[8]
		{
			RunicText.Get("text_a47fdf6415fc"),
			RunicText.Get("text_378d83808237"),
			RunicText.Get("text_38557594d0fc"),
			RunicText.Get("text_4f646b9c50e7"),
			RunicText.Get("text_9450d833fa77"),
			RunicText.Get("text_e7f59d22563b"),
			RunicText.Get("text_cb419c95c437"),
			RunicText.Get("text_6cdf4136acbe")
		};

		public string ProviderId => "runic.inventory";

		internal bool TopologyActive
		{
			get
			{
				if (_topologyActive && !_disposed && !_playerLoadInProgress && _mode == InventoryAuthorityMode.AuthoritativeLocal && IsAuthoritativeLocal(_player))
				{
					return LiveDimensionsMatch();
				}
				return false;
			}
		}

		internal InventoryAuthorityMode Mode => _mode;

		internal bool AcceptsInput => CanEnforceLocks();

		internal bool CanDisable(out string message)
		{
			message = string.Empty;
			if (Object.op_Implicit((Object)(object)_player) && (Object)(object)_player == (Object)(object)Player.m_localPlayer && _playerLoadInProgress)
			{
				message = RunicText.Get("text_66b7c7710d67");
				return false;
			}
			if (Object.op_Implicit((Object)(object)_player) && !((Object)(object)_player != (Object)(object)Player.m_localPlayer))
			{
				Dictionary<string, string> customData = _player.m_customData;
				if (customData != null && customData.ContainsKey("runic.inventory.extra-row.v1"))
				{
					message = RunicText.Get("text_76aa803deabb");
					if (_playerLoadInProgress || _rowMigration || !IsAuthoritativeLocal(_player) || _inventory == null)
					{
						return false;
					}
					if (!int.TryParse(_player.m_customData["runic.inventory.extra-row.v1"], NumberStyles.None, CultureInfo.InvariantCulture, out var result) || result < 4 || result > 9)
					{
						return false;
					}
					List<DedicatedRowItem> list = new List<DedicatedRowItem>();
					foreach (ItemData allItem in _inventory.GetAllItems())
					{
						if (allItem == null)
						{
							return false;
						}
						list.Add(new DedicatedRowItem(new InventorySlotCoordinate(allItem.m_gridPos.x, allItem.m_gridPos.y), ValheimContracts.Category(allItem), allItem.m_equipped));
					}
					bool active = BetterArcheryCompatibility.Active;
					if (DedicatedRowPlan.TryCreate(result, enabled: false, _layout?.SpecialRow ?? result, list, null, out var _, out var _, out var reason, active, active ? (result + 1) : (-1)))
					{
						message = string.Empty;
						return true;
					}
					message = ((reason == "extra-row.clear-space-before-shrinking") ? RunicText.Get("text_6c143e4755b6") : RunicText.Get("text_9a609316cd7a"));
					return false;
				}
			}
			return true;
		}

		private void RestoreEnabled(string message)
		{
			_restoringEnabled = true;
			try
			{
				InventoryConfig.Enabled.Value = true;
			}
			finally
			{
				_restoringEnabled = false;
			}
			_disableCleanupPending = false;
			Notify(message);
		}

		internal bool HandlesNativeInventorySize(Player player)
		{
			if (!_disposed && !_batch && Object.op_Implicit((Object)(object)player) && (Object)(object)player == (Object)(object)Player.m_localPlayer)
			{
				ConfigEntry<bool> enabled = InventoryConfig.Enabled;
				if (enabled == null || !enabled.Value)
				{
					return player.m_customData?.ContainsKey("runic.inventory.extra-row.v1") ?? false;
				}
				return true;
			}
			return false;
		}

		internal void SetNativeInventorySize(Player player, int rows)
		{
			Rebind(player, "native-pocket-size", rows);
		}

		internal bool AllowInvalidItemCleanup(Humanoid actor)
		{
			if (!_disposed && !_batch && Object.op_Implicit((Object)(object)actor) && !((Object)(object)actor != (Object)(object)Player.m_localPlayer) && !((Object)(object)actor != (Object)(object)_player))
			{
				Dictionary<string, string> customData = _player.m_customData;
				if (customData != null && customData.ContainsKey("runic.inventory.extra-row.v1"))
				{
					Inventory inventory = actor.GetInventory();
					if (inventory == null || inventory != _inventory)
					{
						return false;
					}
					List<CleanupCoordinate> list = new List<CleanupCoordinate>();
					foreach (ItemData allItem in inventory.GetAllItems())
					{
						list.Add((allItem == null) ? new CleanupCoordinate(-1, -1) : new CleanupCoordinate(allItem.m_gridPos.x, allItem.m_gridPos.y));
					}
					int retainedHeight;
					switch (InventoryCleanupPolicy.Evaluate(inventory.GetWidth(), inventory.GetHeight(), list, out retainedHeight))
					{
					case InventoryCleanupDecision.NativeAllowed:
						return true;
					case InventoryCleanupDecision.RetainAndExpand:
					{
						inventory.SetHeight(retainedHeight);
						InventoryGui instance = InventoryGui.instance;
						if (instance != null)
						{
							instance.SetInventorySize(retainedHeight);
						}
						break;
					}
					}
					FailClosed("topology.external-resize-cleanup-prevented");
					Diagnostics.Warn("Prevented automatic item ejection after an inventory dimension change. Items retained; height=" + inventory.GetHeight() + ".");
					return false;
				}
			}
			return true;
		}

		private bool EnsureDedicatedRow(int? requestedNativeRows, out string reason)
		{
			//IL_03f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fe: Unknown result type (might be due to invalid IL or missing references)
			reason = "extra-row.not-ready";
			if (_rowMigration || _playerLoadInProgress || !IsAuthoritativeLocal(_player) || _inventory == null || _inventory.GetWidth() != 8 || _player.m_customData == null)
			{
				return false;
			}
			bool flag = InventoryConfig.Enabled?.Value ?? false;
			Dictionary<string, string> customData = _player.m_customData;
			string value;
			bool flag2 = customData.TryGetValue("runic.inventory.extra-row.v1", out value);
			if (!flag && !flag2)
			{
				return true;
			}
			int result = 4;
			string s = default(string);
			if (_player.TryGetUniqueKeyValue("invrows", ref s) && !int.TryParse(s, NumberStyles.None, CultureInfo.InvariantCulture, out result))
			{
				reason = "extra-row.invalid-native-size";
				return false;
			}
			int num = result;
			if (requestedNativeRows.HasValue)
			{
				result = requestedNativeRows.Value;
			}
			if (result < 4 || result > 9)
			{
				reason = "extra-row.unsupported-native-size";
				return false;
			}
			int result2 = -1;
			if (flag2 && (!int.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out result2) || result2 < 4 || result2 > 9))
			{
				reason = "extra-row.invalid-marker";
				return false;
			}
			bool active = BetterArcheryCompatibility.Active;
			string value2;
			bool flag3 = customData.TryGetValue("runic.inventory.betterarchery.v1", out value2);
			int quiverRow = BetterArcheryCompatibility.QuiverRow;
			int previousQuiverRow = -1;
			if (flag3)
			{
				if (!int.TryParse(value2, NumberStyles.None, CultureInfo.InvariantCulture, out var result3) || result3 < 4 || result3 > 9 || (flag2 && result2 != result3))
				{
					reason = "extra-row.invalid-quiver-marker";
					return false;
				}
				previousQuiverRow = result3 + 1;
				if (flag2)
				{
					result2 += 2;
				}
			}
			else if (active)
			{
				previousQuiverRow = num + 1;
			}
			string value3;
			bool flag4 = customData.TryGetValue("runic.inventory.topology.v1", out value3);
			PersistedTopologyState state = null;
			if (flag4 && !TopologyPersistenceCodec.TryDecode(value3, out state, out reason))
			{
				return false;
			}
			if (flag2 && state != null && state.Height != result2 + 1)
			{
				reason = "extra-row.metadata-mismatch";
				return false;
			}
			if (!flag2 && state != null)
			{
				result2 = state.Height - 1;
			}
			int height = result + (active ? 2 : 0) + (flag ? 1 : 0);
			int height2 = _inventory.GetHeight();
			if (height2 < 4 || height2 > 12)
			{
				reason = "extra-row.unsupported-live-size";
				return false;
			}
			List<ItemData> allItems = _inventory.GetAllItems();
			int num2 = height2;
			foreach (ItemData item in allItems)
			{
				if (item == null || item.m_gridPos.y < 0 || item.m_gridPos.y >= 12)
				{
					reason = "extra-row.invalid-item-position";
					return false;
				}
				num2 = Math.Max(num2, item.m_gridPos.y + 1);
			}
			List<DedicatedRowItem> list = new List<DedicatedRowItem>();
			foreach (ItemData item2 in allItems)
			{
				list.Add(new DedicatedRowItem(new InventorySlotCoordinate(item2.m_gridPos.x, item2.m_gridPos.y), ValheimContracts.Category(item2), item2.m_equipped));
			}
			if (!DedicatedRowPlan.TryCreate(result, flag, result2, list, state?.LockedSlots(), out var positions, out var mappedLocks, out reason, active, previousQuiverRow))
			{
				_inventory.SetHeight(num2);
				InventoryGui instance = InventoryGui.instance;
				if (instance != null)
				{
					instance.SetInventorySize(num2);
				}
				return false;
			}
			string payload = null;
			if (flag && (!TopologyLayout.TryCreate(8, height, out var layout, out reason) || !TopologyPersistenceCodec.TryEncode(layout, mappedLocks, out payload, out reason)))
			{
				return false;
			}
			if (!TryEnterMutation("runic.inventory/dedicated-row", out var lease))
			{
				reason = "extra-row.transaction-busy";
				return false;
			}
			IReadOnlyList<ItemMutationEvidence> evidence = null;
			_rowMigration = true;
			Inventory inventory = _inventory;
			inventory.m_onChanged = (Action)Delegate.Remove(inventory.m_onChanged, new Action(OnInventoryChanged));
			try
			{
				using (lease)
				{
					_inventory.SetHeight(num2);
					if (!InventoryEvidence.TryCaptureMutation(_inventory, out evidence, out reason))
					{
						throw new InvalidOperationException(reason);
					}
					_inventory.SetHeight(height);
					for (int i = 0; i < allItems.Count; i++)
					{
						allItems[i].m_gridPos = new Vector2i(positions[i].X, positions[i].Y);
					}
					if (!InventoryEvidence.VerifyUnchangedExceptPosition(_inventory, evidence, out reason))
					{
						throw new InvalidOperationException(reason);
					}
					if (flag)
					{
						customData["runic.inventory.extra-row.v1"] = result.ToString(CultureInfo.InvariantCulture);
						customData["runic.inventory.topology.v1"] = payload;
					}
					else
					{
						customData.Remove("runic.inventory.extra-row.v1");
						customData.Remove("runic.inventory.topology.v1");
					}
					if (active)
					{
						customData["runic.inventory.betterarchery.v1"] = result.ToString(CultureInfo.InvariantCulture);
						BetterArcheryCompatibility.SetQuiverRow(result + 1);
					}
					else
					{
						customData.Remove("runic.inventory.betterarchery.v1");
					}
					if (requestedNativeRows.HasValue)
					{
						_player.AddUniqueKeyValue("invrows", result.ToString(CultureInfo.InvariantCulture));
					}
				}
			}
			catch (Exception exception)
			{
				InventoryEvidence.RestorePositions(evidence);
				_inventory.SetHeight(num2);
				if (flag2)
				{
					customData["runic.inventory.extra-row.v1"] = value;
				}
				else
				{
					customData.Remove("runic.inventory.extra-row.v1");
				}
				if (flag4)
				{
					customData["runic.inventory.topology.v1"] = value3;
				}
				else
				{
					customData.Remove("runic.inventory.topology.v1");
				}
				if (flag3)
				{
					customData["runic.inventory.betterarchery.v1"] = value2;
				}
				else
				{
					customData.Remove("runic.inventory.betterarchery.v1");
				}
				if (active)
				{
					BetterArcheryCompatibility.SetQuiverRow(quiverRow);
				}
				reason = "extra-row.migration-failed";
				Diagnostics.Error(exception, RunicText.Get("text_7506f8257cce"));
				return false;
			}
			finally
			{
				Inventory inventory2 = _inventory;
				inventory2.m_onChanged = (Action)Delegate.Combine(inventory2.m_onChanged, new Action(OnInventoryChanged));
				_rowMigration = false;
				InventoryGui instance2 = InventoryGui.instance;
				if (instance2 != null)
				{
					instance2.SetInventorySize(_inventory.GetHeight());
				}
			}
			reason = "ok";
			return true;
		}

		private bool HasDedicatedRow(Inventory inventory)
		{
			if (!_disposed && !_playerLoadInProgress && !_rowMigration)
			{
				ConfigEntry<bool> enabled = InventoryConfig.Enabled;
				if (enabled != null && enabled.Value && (Object)(object)_player == (Object)(object)Player.m_localPlayer && inventory == _inventory)
				{
					Player player = _player;
					if (player == null)
					{
						return false;
					}
					return player.m_customData?.ContainsKey("runic.inventory.extra-row.v1") == true;
				}
			}
			return false;
		}

		internal bool AllowPositionedAddition(Inventory inventory, ItemData item, int x, int y, bool loading)
		{
			//IL_005f: 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_0073: Invalid comparison between Unknown and I4
			if (loading || !HasDedicatedRow(inventory))
			{
				return true;
			}
			if (x < 0 || x >= inventory.GetWidth() || y < 0 || y >= inventory.GetHeight())
			{
				return false;
			}
			if (IsQuiverReservedRow(y))
			{
				if (y == inventory.GetHeight() - 2 && x < 3 && item != null && (int)(item.m_shared?.m_itemType).GetValueOrDefault() == 9)
				{
					return BetterArcheryCompatibility.Equipped;
				}
				return false;
			}
			if (y == inventory.GetHeight() - 1)
			{
				if (item != null)
				{
					return TopologyLayout.Accepts((InventoryRoleKind)(x + 1), ValheimContracts.Category(item));
				}
				return false;
			}
			return true;
		}

		private bool IsQuiverReservedRow(int y)
		{
			if (HasQuiverLayout && _inventory != null)
			{
				if (y != _inventory.GetHeight() - 3)
				{
					return y == _inventory.GetHeight() - 2;
				}
				return true;
			}
			return false;
		}

		internal InventoryRuntime(bool batch)
		{
			_batch = batch;
			_mainThreadId = Thread.CurrentThread.ManagedThreadId;
			_filters = PickupFilterSet.Parse(InventoryConfig.FilteredPickupItems?.Value ?? string.Empty);
			_mode = (batch ? InventoryAuthorityMode.BatchInert : InventoryAuthorityMode.Unavailable);
			_reasonCode = (batch ? "authority.batch-inert" : "player.not-loaded");
		}

		internal void Initialize()
		{
			if (_batch)
			{
				RebuildStatusOnly();
			}
			else
			{
				Rebind(Player.m_localPlayer, "startup");
			}
		}

		internal void Tick()
		{
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			if (_disposed || _batch)
			{
				return;
			}
			if (_player != Player.m_localPlayer)
			{
				Rebind(Player.m_localPlayer, "local-player-changed");
			}
			if (!Object.op_Implicit((Object)(object)_player) || _inventory == null)
			{
				return;
			}
			if (_disableCleanupPending)
			{
				ConfigEntry<bool> enabled = InventoryConfig.Enabled;
				if (enabled != null && enabled.Value)
				{
					_disableCleanupPending = false;
					Rebind(Player.m_localPlayer, "disable-cleanup-cancelled");
				}
				else
				{
					if (!TryCompleteDisableCleanup())
					{
						return;
					}
					Rebind(Player.m_localPlayer, "disable-cleanup-completed");
				}
				if (!Object.op_Implicit((Object)(object)_player) || _inventory == null)
				{
					return;
				}
			}
			if (_layout != null && !LiveDimensionsMatch())
			{
				FailClosed("topology.runtime-dimension-changed");
				return;
			}
			bool flag = IsAuthoritativeLocal(_player);
			if ((_mode == InventoryAuthorityMode.AuthoritativeLocal && !flag) || (_mode == InventoryAuthorityMode.RemoteDedicatedCompatibility && flag))
			{
				Rebind(_player, "authority-changed");
				if (!Object.op_Implicit((Object)(object)_player) || _inventory == null)
				{
					return;
				}
			}
			if (!AcceptsInput)
			{
				return;
			}
			bool flag2 = (Object)(object)InventoryGui.instance != (Object)null && InventoryGui.IsVisible();
			if (flag2)
			{
				if (KeyboardInput.ShortcutDown(InventoryConfig.Sort.Value))
				{
					SortSelectedRows("keyboard");
				}
				if (KeyboardInput.ShortcutDown(InventoryConfig.ToggleLock.Value))
				{
					ToggleFocusedLock("keyboard");
				}
			}
			else if (ValheimContracts.PlayerMayTakeInput(_player))
			{
				if (KeyboardInput.ShortcutDown(InventoryConfig.Quick1.Value))
				{
					UseQuick(InventoryRoleKind.Quick1, "keyboard");
				}
				else if (KeyboardInput.ShortcutDown(InventoryConfig.Quick2.Value))
				{
					UseQuick(InventoryRoleKind.Quick2, "keyboard");
				}
				else if (KeyboardInput.ShortcutDown(InventoryConfig.Quick3.Value))
				{
					UseQuick(InventoryRoleKind.Quick3, "keyboard");
				}
			}
			ControllerInput.Tick(this, flag2, !flag2 && ValheimContracts.PlayerMayTakeInput(_player));
		}

		internal void Draw()
		{
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			if (_disposed || _batch || (Object)(object)InventoryGui.instance == (Object)null || !InventoryGui.IsVisible() || ValheimContracts.InventoryModalVisible())
			{
				return;
			}
			if (TopologyActive)
			{
				ConfigEntry<bool> showRoleLabels = InventoryConfig.ShowRoleLabels;
				if (showRoleLabels == null || showRoleLabels.Value)
				{
					DrawRoleOverlay();
				}
			}
			if (CanEnforceLocks())
			{
				DrawLockedSlotOverlay();
			}
			ConfigEntry<bool> showInventoryStatus = InventoryConfig.ShowInventoryStatus;
			if (showInventoryStatus != null && showInventoryStatus.Value)
			{
				float num = Math.Min(500f, Math.Max(300f, (float)Screen.width - 20f));
				GUI.Box(new Rect(Math.Max(10f, (float)Screen.width - num - 10f), 72f, num, 190f), _statusText);
			}
		}

		private void DrawRoleOverlay()
		{
			//IL_035c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: 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_014c: 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_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: 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_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Expected O, but got Unknown
			//IL_021b: 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_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_032a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0334: Unknown result type (might be due to invalid IL or missing references)
			InventoryGrid val = InventoryGui.instance?.m_playerGrid;
			if (!Object.op_Implicit((Object)(object)val) || _layout == null || !ValheimContracts.TryBottomRowScreenRects(val, _layout.SpecialRow, _roleSlotRects))
			{
				return;
			}
			Color color = GUI.color;
			int depth = GUI.depth;
			try
			{
				GUI.depth = -650;
				Rect val2 = _roleSlotRects[0];
				Rect val3 = _roleSlotRects[_roleSlotRects.Length - 1];
				Rect val4 = default(Rect);
				((Rect)(ref val4))..ctor(((Rect)(ref val2)).xMin - 2f, Math.Min(((Rect)(ref val2)).yMin, ((Rect)(ref val3)).yMin) - 2f, ((Rect)(ref val3)).xMax - ((Rect)(ref val2)).xMin + 4f, Math.Max(((Rect)(ref val2)).yMax, ((Rect)(ref val3)).yMax) - Math.Min(((Rect)(ref val2)).yMin, ((Rect)(ref val3)).yMin) + 4f);
				GUI.color = new Color(0.7f, 0.43f, 0.13f, 0.48f);
				GUI.DrawTexture(new Rect(((Rect)(ref val4)).xMin, ((Rect)(ref val4)).yMin, ((Rect)(ref val4)).width, 1f), (Texture)(object)Texture2D.whiteTexture);
				GUI.DrawTexture(new Rect(((Rect)(ref val4)).xMin, ((Rect)(ref val4)).yMax - 1f, ((Rect)(ref val4)).width, 1f), (Texture)(object)Texture2D.whiteTexture);
				GUI.DrawTexture(new Rect(((Rect)(ref val4)).xMin, ((Rect)(ref val4)).yMin, 1f, ((Rect)(ref val4)).height), (Texture)(object)Texture2D.whiteTexture);
				GUI.DrawTexture(new Rect(((Rect)(ref val4)).xMax - 1f, ((Rect)(ref val4)).yMin, 1f, ((Rect)(ref val4)).height), (Texture)(object)Texture2D.whiteTexture);
				GUIStyle val5 = new GUIStyle(GUI.skin.label)
				{
					alignment = (TextAnchor)7,
					fontStyle = (FontStyle)1,
					fontSize = Math.Max(8, Math.Min(11, (int)(((Rect)(ref _roleSlotRects[0])).width / 7f))),
					clipping = (TextClipping)1,
					wordWrap = false
				};
				Rect val7 = default(Rect);
				for (int i = 0; i < _roleSlotRects.Length; i++)
				{
					Rect val6 = _roleSlotRects[i];
					GUI.color = new Color(0f, 0f, 0f, 0.7f);
					GUI.DrawTexture(new Rect(((Rect)(ref val6)).x + 1f, ((Rect)(ref val6)).y + 1f, ((Rect)(ref val6)).width - 2f, 17f), (Texture)(object)Texture2D.whiteTexture);
					((Rect)(ref val7))..ctor(((Rect)(ref val6)).x + 2f, ((Rect)(ref val6)).y + 1f, ((Rect)(ref val6)).width - 4f, 16f);
					val5.normal.textColor = new Color(0.05f, 0.03f, 0.01f, 0.92f);
					GUI.Label(new Rect(((Rect)(ref val7)).x + 1f, ((Rect)(ref val7)).y + 1f, ((Rect)(ref val7)).width, ((Rect)(ref val7)).height), RoleLabels[i], val5);
					val5.normal.textColor = new Color(1f, 0.78f, 0.34f, 0.98f);
					GUI.Label(val7, RoleLabels[i], val5);
				}
			}
			finally
			{
				GUI.color = color;
				GUI.depth = depth;
			}
		}

		private void DrawLockedSlotOverlay()
		{
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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_00c6: Unknown result type (might be due to invalid IL or missing references)
			InventoryGrid val = InventoryGui.instance?.m_playerGrid;
			if (!Object.op_Implicit((Object)(object)val) || _layout == null || _persisted == null)
			{
				return;
			}
			Color color = GUI.color;
			int depth = GUI.depth;
			try
			{
				GUI.depth = -660;
				GUI.color = new Color(1f, 0.84f, 0.08f, 1f);
				foreach (InventorySlotCoordinate item in _persisted.LockedSlots())
				{
					if (ValheimContracts.TrySlotScreenRect(val, item.X, item.Y, out var slot))
					{
						DrawOutline(new Rect(((Rect)(ref slot)).xMin - 2f, ((Rect)(ref slot)).yMin - 2f, ((Rect)(ref slot)).width + 4f, ((Rect)(ref slot)).height + 4f), 4f);
					}
				}
			}
			finally
			{
				GUI.color = color;
				GUI.depth = depth;
			}
		}

		private static void DrawOutline(Rect rect, float thickness)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			GUI.DrawTexture(new Rect(((Rect)(ref rect)).xMin, ((Rect)(ref rect)).yMin, ((Rect)(ref rect)).width, thickness), (Texture)(object)Texture2D.whiteTexture);
			GUI.DrawTexture(new Rect(((Rect)(ref rect)).xMin, ((Rect)(ref rect)).yMax - thickness, ((Rect)(ref rect)).width, thickness), (Texture)(object)Texture2D.whiteTexture);
			GUI.DrawTexture(new Rect(((Rect)(ref rect)).xMin, ((Rect)(ref rect)).yMin, thickness, ((Rect)(ref rect)).height), (Texture)(object)Texture2D.whiteTexture);
			GUI.DrawTexture(new Rect(((Rect)(ref rect)).xMax - thickness, ((Rect)(ref rect)).yMin, thickness, ((Rect)(ref rect)).height), (Texture)(object)Texture2D.whiteTexture);
		}

		internal void OnConfigurationChanged()
		{
			if (_disposed || _restoringEnabled)
			{
				return;
			}
			ConfigEntry<bool> enabled = InventoryConfig.Enabled;
			if ((enabled == null || !enabled.Value) && !CanDisable(out var message))
			{
				RestoreEnabled(message);
				return;
			}
			if ((_filters = PickupFilterSet.Parse(InventoryConfig.FilteredPickupItems.Value)).Truncated)
			{
				Diagnostics.Warn("Pickup filter exceeded 128 safe unique rules; additional entries were ignored.");
			}
			ControllerBindings.Invalidate();
			ControllerChordSession.Reset();
			ConfigEntry<bool> enabled2 = InventoryConfig.Enabled;
			if (enabled2 != null && enabled2.Value)
			{
				_disableCleanupPending = false;
			}
			Rebind(Player.m_localPlayer, "configuration-changed");
		}

		internal void OnLocalPlayerChanged(Player player)
		{
			Rebind(player, "set-local-player");
		}

		internal void OnPlayerLoadStarted(Player player)
		{
			if (!_disposed && !((Object)(object)player != (Object)(object)_player) && !((Object)(object)player != (Object)(object)Player.m_localPlayer))
			{
				_playerLoadInProgress = true;
				_loadMetadataRefreshed = false;
				player.m_customData?.Remove("runic.inventory.extra-row.v1");
				player.m_customData?.Remove("runic.inventory.betterarchery.v1");
				player.m_customData?.Remove("runic.inventory.topology.v1");
			}
		}

		internal void OnPlayerLoadCompleted(Player player)
		{
			if (!_disposed && !((Object)(object)player != (Object)(object)Player.m_localPlayer))
			{
				_playerLoadInProgress = false;
				_loadMetadataRefreshed = false;
				Rebind(player, "player-load-completed");
			}
		}

		internal void OnPlayerLoadFaulted(Player player)
		{
			if (!_disposed && !((Object)(object)player != (Object)(object)_player))
			{
				_playerLoadInProgress = false;
				_loadMetadataRefreshed = false;
				FailClosed("player.load-faulted");
			}
		}

		internal void OnNativeInventorySizeChanged(Player player, int previousHeight)
		{
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b9: Unknown result type (might be due to invalid