Decompiled source of ValheimHotKeys v1.4.0

ValheimHotKeys.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using malafein.Valheim.Shared;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: AssemblyCompany("ValheimHotKeys")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Configurable hotkeys for various Valheim actions.")]
[assembly: AssemblyFileVersion("1.4.0.0")]
[assembly: AssemblyInformationalVersion("1.4.0+3560bd0f298915b4c1fd9c10de33e8043a8c5e30")]
[assembly: AssemblyProduct("ValheimHotKeys")]
[assembly: AssemblyTitle("ValheimHotKeys")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.4.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace malafein.Valheim.Shared
{
	internal enum ModifierMatch
	{
		Exact,
		AtLeast
	}
	[HarmonyPatch]
	internal static class Keybinds
	{
		private class Binding
		{
			public string Name;

			public Func<KeyboardShortcut> Shortcut;

			public string Context;
		}

		private const string DefaultContext = "";

		private static readonly MethodInfo TakeInputMethod = AccessTools.Method(typeof(Player), "TakeInput", (Type[])null, (Type[])null);

		private static readonly FieldInfo ButtonsField = AccessTools.Field(typeof(ZInput), "m_buttons");

		private static readonly MethodInfo KeyCodeToPathMethod = AccessTools.Method(typeof(ZInput), "KeyCodeToPath", (Type[])null, (Type[])null);

		private static readonly KeyCode[] ModifierKeys;

		private static readonly Dictionary<KeyCode, string> ModifierLabels;

		private static readonly string[] RawMouseButtons;

		private static readonly List<Binding> s_bindings;

		private static readonly HashSet<string> s_ignoredVanillaButtons;

		private static List<string> s_lastConflicts;

		internal static void Init(ConfigFile config, params string[] ignoredVanillaButtons)
		{
			s_ignoredVanillaButtons.UnionWith(ignoredVanillaButtons);
			config.SettingChanged += delegate
			{
				CheckConflicts();
			};
		}

		internal static void Add(ConfigEntry<KeyboardShortcut> entry, string context = null)
		{
			Add(((ConfigEntryBase)entry).Definition.Key, () => entry.Value, context);
		}

		internal static void Add(string name, Func<KeyboardShortcut> shortcut, string context = null)
		{
			s_bindings.Add(new Binding
			{
				Name = name,
				Shortcut = shortcut,
				Context = (context ?? "")
			});
			CheckConflicts();
		}

		internal static bool IsDown(KeyboardShortcut shortcut, ModifierMatch match = ModifierMatch.Exact)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			KeyCode mainKey = ((KeyboardShortcut)(ref shortcut)).MainKey;
			if ((int)mainKey == 0 || !ZInput.IsKeyCodeValid(mainKey))
			{
				return false;
			}
			if (!ZInput.GetKeyDown(mainKey, false))
			{
				return false;
			}
			if (!((KeyboardShortcut)(ref shortcut)).Modifiers.All((KeyCode key) => ZInput.GetKey(key, false)))
			{
				return false;
			}
			if (match == ModifierMatch.AtLeast)
			{
				return true;
			}
			return ModifierKeys.All((KeyCode key) => ((KeyboardShortcut)(ref shortcut)).Modifiers.Contains(key) || !ZInput.GetKey(key, false));
		}

		internal static KeyCode[] HeldModifiers()
		{
			return ModifierKeys.Where((KeyCode key) => ZInput.GetKey(key, false)).ToArray();
		}

		internal static bool CanTakeInput(Player player)
		{
			return (bool)TakeInputMethod.Invoke(player, null);
		}

		internal unsafe static string Format(KeyboardShortcut shortcut)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0)
			{
				return "Not set";
			}
			List<string> list = new List<string>();
			list.AddRange(from key in ModifierKeys
				where ((KeyboardShortcut)(ref shortcut)).Modifiers.Contains(key)
				select ModifierLabels[key]);
			list.AddRange(from key in ((KeyboardShortcut)(ref shortcut)).Modifiers
				where !ModifierLabels.ContainsKey(key)
				select ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString());
			list.Add(((object)((KeyboardShortcut)(ref shortcut)).MainKey/*cast due to .constrained prefix*/).ToString());
			return string.Join(" + ", list);
		}

		private static string GetBoundPath(ButtonDef button)
		{
			try
			{
				return button.GetActionPath(true);
			}
			catch (ArgumentOutOfRangeException)
			{
				return null;
			}
		}

		[HarmonyPatch(typeof(ZInput), "Load")]
		[HarmonyPostfix]
		private static void Postfix_ZInputLoad(ZInput __instance)
		{
			CheckConflicts(__instance);
		}

		[HarmonyPatch(typeof(ZInput), "Save")]
		[HarmonyPostfix]
		private static void Postfix_ZInputSave(ZInput __instance)
		{
			CheckConflicts(__instance);
		}

		[HarmonyPatch(typeof(ZInput), "ResetToDefault")]
		[HarmonyPostfix]
		private static void Postfix_ZInputResetToDefault(ZInput __instance)
		{
			CheckConflicts(__instance);
		}

		internal static void CheckConflicts(ZInput input = null)
		{
			try
			{
				FindAndLogConflicts(input ?? ZInput.instance);
			}
			catch (Exception ex)
			{
				Log.Warn("Keybinding conflict check failed: " + ex.Message);
			}
		}

		private static void FindAndLogConflicts(ZInput input)
		{
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			if (input == null || ButtonsField == null || KeyCodeToPathMethod == null || !(ButtonsField.GetValue(input) is Dictionary<string, ButtonDef> dictionary))
			{
				return;
			}
			List<string> list = new List<string>();
			var list2 = s_bindings.Select((Binding b) => new
			{
				Binding = b,
				Shortcut = b.Shortcut()
			}).Where(b =>
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: Invalid comparison between Unknown and I4
				KeyboardShortcut shortcut2 = b.Shortcut;
				return (int)((KeyboardShortcut)(ref shortcut2)).MainKey > 0;
			}).ToList();
			foreach (var item in list2)
			{
				Binding binding = item.Binding;
				KeyboardShortcut shortcut = item.Shortcut;
				KeyCode mainKey = ((KeyboardShortcut)(ref shortcut)).MainKey;
				if (!ZInput.IsKeyCodeValid(mainKey))
				{
					list.Add($"{binding.Name} ({Format(shortcut)}) uses {mainKey}, which Valheim cannot read. The shortcut will never fire.");
					continue;
				}
				string path = (string)KeyCodeToPathMethod.Invoke(null, new object[2] { mainKey, false });
				foreach (string item2 in (from b in dictionary.Values
					where !s_ignoredVanillaButtons.Contains(b.Name)
					where string.Equals(GetBoundPath(b), path, StringComparison.OrdinalIgnoreCase)
					select b.Name).Distinct())
				{
					list.Add($"{binding.Name} ({Format(shortcut)}) shares {mainKey} with the game's \"{item2}\" binding. Both will trigger.");
				}
			}
			foreach (var item3 in from b in list2
				group b by new
				{
					Context = b.Binding.Context,
					Keys = Format(b.Shortcut)
				} into g
				where g.Count() > 1
				select g)
			{
				string text = string.Join(" and ", item3.Select(b => b.Binding.Name));
				list.Add(text + " are bound to the same keys (" + item3.Key.Keys + "). They will trigger at once.");
			}
			if (list.SequenceEqual(s_lastConflicts))
			{
				return;
			}
			foreach (string item4 in list)
			{
				Log.Warn("Keybinding conflict: " + item4);
			}
			if (list.Count == 0 && s_lastConflicts.Count > 0)
			{
				Log.Info("Keybinding conflicts resolved.");
			}
			s_lastConflicts = list;
		}

		static Keybinds()
		{
			KeyCode[] array = new KeyCode[6];
			RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
			ModifierKeys = (KeyCode[])(object)array;
			ModifierLabels = new Dictionary<KeyCode, string>
			{
				{
					(KeyCode)306,
					"Left Ctrl"
				},
				{
					(KeyCode)305,
					"Right Ctrl"
				},
				{
					(KeyCode)304,
					"Left Shift"
				},
				{
					(KeyCode)303,
					"Right Shift"
				},
				{
					(KeyCode)308,
					"Left Alt"
				},
				{
					(KeyCode)307,
					"Right Alt"
				}
			};
			RawMouseButtons = new string[5] { "MouseLeft", "MouseRight", "MouseMiddle", "MouseForward", "MouseBack" };
			s_bindings = new List<Binding>();
			s_ignoredVanillaButtons = new HashSet<string>(RawMouseButtons);
			s_lastConflicts = new List<string>();
		}
	}
	internal static class Log
	{
		private static ManualLogSource s_logger;

		private static Func<bool> s_debugEnabled;

		private static ManualLogSource Logger
		{
			get
			{
				if (s_logger == null)
				{
					s_logger = Logger.CreateLogSource(typeof(Log).Assembly.GetName().Name);
				}
				return s_logger;
			}
		}

		internal static void Init(ManualLogSource logger, Func<bool> debugEnabled = null)
		{
			s_logger = logger;
			s_debugEnabled = debugEnabled;
		}

		internal static void Info(string message)
		{
			Logger.LogInfo((object)message);
		}

		internal static void Warn(string message)
		{
			Logger.LogWarning((object)message);
		}

		internal static void Error(string message)
		{
			Logger.LogError((object)message);
		}

		internal static void Debug(string message)
		{
			if (s_debugEnabled == null || s_debugEnabled())
			{
				Logger.LogDebug((object)message);
			}
		}
	}
}
namespace ValheimHotKeys
{
	[HarmonyPatch]
	public static class HotKeyPatches
	{
		[HarmonyPatch(typeof(Hud), "Update")]
		[HarmonyPrefix]
		public static void Hud_Update_Prefix(Hud __instance)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if (Keybinds.IsDown(Plugin.ToggleHUDConfig.Value))
			{
				__instance.m_userHidden = !__instance.m_userHidden;
			}
		}

		[HarmonyPatch(typeof(Player), "Update")]
		[HarmonyPostfix]
		public static void Player_Update_Postfix(Player __instance)
		{
			//IL_0022: 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_0081: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			RepairHotkey.Update(__instance);
			if (!Keybinds.CanTakeInput(__instance) || (Keybinds.IsDown(Plugin.RepairHammerConfig.Value, ModifierMatch.AtLeast) && RepairHotkey.HandlePress(__instance)))
			{
				return;
			}
			for (int i = 0; i < Plugin.HotbarConfigs.Length; i++)
			{
				if (Keybinds.IsDown(Plugin.HotbarConfigs[i].Value, ModifierMatch.AtLeast))
				{
					__instance.UseHotbarItem(i + 1);
					return;
				}
			}
			for (int j = 0; j < Plugin.CustomItemBindings.Count; j++)
			{
				Plugin.ItemBinding value = Plugin.CustomItemBindings[j].Value;
				if (!Keybinds.IsDown(value.Shortcut, ModifierMatch.AtLeast))
				{
					continue;
				}
				string itemName = value.ItemName;
				if (string.IsNullOrEmpty(itemName))
				{
					continue;
				}
				Inventory inventory = ((Humanoid)__instance).GetInventory();
				List<ItemData> allItems = inventory.GetAllItems();
				string searchName = itemName.ToLower();
				List<ItemData> list = allItems.FindAll((ItemData iData) => Localization.instance.Localize(iData.m_shared.m_name).ToLower().Contains(searchName) || iData.m_shared.m_name.ToLower().Contains(searchName));
				if (list.Count > 0)
				{
					ItemData val = list[0];
					if (list.Count > 1)
					{
						int num = list.FindIndex((ItemData m) => m.m_equipped);
						if (num != -1)
						{
							val = list[(num + 1) % list.Count];
						}
					}
					((Humanoid)__instance).UseItem(inventory, val, true);
					break;
				}
				Log.Debug("No item matching '" + itemName + "' found in inventory.");
			}
		}
	}
	[BepInPlugin("com.malafein.valheimhotkeys", "Valheim HotKeys", "1.4.0")]
	public class Plugin : BaseUnityPlugin
	{
		public class ItemBinding
		{
			public string ItemName = "";

			public KeyboardShortcut Shortcut = KeyboardShortcut.Empty;

			public string Serialize()
			{
				if (string.IsNullOrEmpty(ItemName))
				{
					return "";
				}
				return ItemName + "|" + ((KeyboardShortcut)(ref Shortcut)).Serialize();
			}

			public static ItemBinding Deserialize(string str)
			{
				//IL_004e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0053: Unknown result type (might be due to invalid IL or missing references)
				//IL_0040: Unknown result type (might be due to invalid IL or missing references)
				//IL_0045: Unknown result type (might be due to invalid IL or missing references)
				ItemBinding itemBinding = new ItemBinding();
				if (string.IsNullOrEmpty(str))
				{
					return itemBinding;
				}
				int num = str.LastIndexOf('|');
				if (num == -1)
				{
					itemBinding.ItemName = str;
					return itemBinding;
				}
				itemBinding.ItemName = str.Substring(0, num);
				string text = str.Substring(num + 1);
				try
				{
					itemBinding.Shortcut = KeyboardShortcut.Deserialize(text);
				}
				catch
				{
					itemBinding.Shortcut = KeyboardShortcut.Empty;
				}
				return itemBinding;
			}
		}

		public class ConfigurationManagerAttributes
		{
			public Action<ConfigEntryBase> CustomDrawer;

			public bool? ShowMultilineText;

			public string DispName;

			public int? Order;

			public bool? HideDefaultButton;

			public bool? HideSettingName;
		}

		public const string ModGUID = "com.malafein.valheimhotkeys";

		public const string ModName = "Valheim HotKeys";

		public const string ModVersion = "1.4.0";

		public static ConfigEntry<KeyboardShortcut> ToggleHUDConfig;

		public static ConfigEntry<KeyboardShortcut> RepairHammerConfig;

		public static ConfigEntry<KeyboardShortcut>[] HotbarConfigs = new ConfigEntry<KeyboardShortcut>[8];

		private const string ItemBindingsSection = "Custom Item Bindings";

		public static List<ConfigEntry<ItemBinding>> CustomItemBindings = new List<ConfigEntry<ItemBinding>>();

		private readonly Harmony harmony = new Harmony("com.malafein.valheimhotkeys");

		private static ConfigEntryBase _waitingEntry;

		private static int _activationFrame = -1;

		private static int _forbiddenFrame = -1;

		private void Awake()
		{
			//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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Expected O, but got Unknown
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			Log.Init(((BaseUnityPlugin)this).Logger);
			TomlTypeConverter.AddConverter(typeof(ItemBinding), new TypeConverter
			{
				ConvertToObject = (string str, Type type) => ItemBinding.Deserialize(str),
				ConvertToString = (object obj, Type type) => ((ItemBinding)obj).Serialize()
			});
			ToggleHUDConfig = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "ToggleHUD", new KeyboardShortcut((KeyCode)284, Array.Empty<KeyCode>()), "Hotkey to toggle the HUD visibility.");
			RepairHammerConfig = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Actions", "RepairHammer", new KeyboardShortcut((KeyCode)0, Array.Empty<KeyCode>()), "Equips your hammer with repair mode selected. Press again while repairing to put the hammer away.");
			Keybinds.Init(((BaseUnityPlugin)this).Config);
			Keybinds.Add(ToggleHUDConfig);
			Keybinds.Add(RepairHammerConfig);
			for (int num = 0; num < 8; num++)
			{
				int num2 = num + 1;
				ConfigEntry<KeyboardShortcut> entry = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hotbar", $"Slot{num2}", new KeyboardShortcut((KeyCode)0, Array.Empty<KeyCode>()), $"Hotkey for hotbar slot {num2}, for shortcuts with modifier keys (e.g. Alt + {num2}). For a single key, use the alternate key in Valheim's own Controls menu.");
				HotbarConfigs[num] = entry;
				Keybinds.Add($"Hotbar slot {num2}", () => entry.Value);
			}
			MigrateSlotKeys();
			for (int num3 = 0; num3 < 8; num3++)
			{
				int num4 = num3 + 1;
				ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes
				{
					CustomDrawer = DrawItemBindingElement,
					HideDefaultButton = false
				};
				ItemBinding itemBinding = new ItemBinding();
				switch (num3)
				{
				case 0:
					itemBinding.ItemName = "Healing Mead";
					itemBinding.Shortcut = new KeyboardShortcut((KeyCode)326, Array.Empty<KeyCode>());
					break;
				case 1:
					itemBinding.ItemName = "Arrow";
					itemBinding.Shortcut = new KeyboardShortcut((KeyCode)327, Array.Empty<KeyCode>());
					break;
				}
				ConfigEntry<ItemBinding> entry2 = ((BaseUnityPlugin)this).Config.Bind<ItemBinding>("Custom Item Bindings", $"Item {num4}", itemBinding, new ConfigDescription($"Custom item binding {num4}.", (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }));
				CustomItemBindings.Add(entry2);
				Keybinds.Add($"Item {num4}", () => (!string.IsNullOrEmpty(entry2.Value.ItemName)) ? entry2.Value.Shortcut : KeyboardShortcut.Empty);
			}
			Log.Info("Valheim HotKeys 1.4.0 is loading...");
			harmony.PatchAll();
			Log.Info("Valheim HotKeys loaded!");
		}

		private void MigrateSlotKeys()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			try
			{
				Dictionary<ConfigDefinition, string> dictionary = (Dictionary<ConfigDefinition, string>)AccessTools.Property(typeof(ConfigFile), "OrphanedEntries").GetValue(((BaseUnityPlugin)this).Config, null);
				for (int i = 1; i <= 8; i++)
				{
					ConfigDefinition key = new ConfigDefinition("Custom Item Bindings", $"Slot {i}");
					ConfigDefinition key2 = new ConfigDefinition("Custom Item Bindings", $"Item {i}");
					if (dictionary.TryGetValue(key, out var value))
					{
						dictionary.Remove(key);
						if (!dictionary.ContainsKey(key2))
						{
							dictionary[key2] = value;
						}
					}
				}
			}
			catch (Exception ex)
			{
				Log.Warn("Could not carry over item bindings saved by an older version: " + ex.Message);
			}
		}

		private void DrawItemBindingElement(ConfigEntryBase entry)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Invalid comparison between Unknown and I4
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Invalid comparison between Unknown and I4
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Invalid comparison between Unknown and I4
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Invalid comparison between Unknown and I4
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Invalid comparison between Unknown and I4
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Invalid comparison between Unknown and I4
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Invalid comparison between Unknown and I4
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Invalid comparison between Unknown and I4
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Invalid comparison between Unknown and I4
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Invalid comparison between Unknown and I4
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Invalid comparison between Unknown and I4
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Invalid comparison between Unknown and I4
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Invalid comparison between Unknown and I4
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Invalid comparison between Unknown and I4
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: Invalid comparison between Unknown and I4
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Invalid comparison between Unknown and I4
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			ConfigEntry<ItemBinding> val = (ConfigEntry<ItemBinding>)(object)entry;
			ItemBinding value = val.Value;
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			string text = GUILayout.TextField(value.ItemName, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(200f) });
			if (text != value.ItemName)
			{
				val.Value = new ItemBinding
				{
					ItemName = text,
					Shortcut = value.Shortcut
				};
			}
			GUILayout.Space(10f);
			bool flag = _waitingEntry == entry;
			GUI.enabled = !flag;
			string text2 = (flag ? "Press any key..." : Keybinds.Format(value.Shortcut));
			if (!flag && (int)((KeyboardShortcut)(ref value.Shortcut)).MainKey == 0)
			{
				text2 = "Click to bind";
			}
			if (GUILayout.Button(text2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) }))
			{
				_waitingEntry = entry;
				_activationFrame = Time.frameCount;
			}
			GUI.enabled = true;
			if (flag)
			{
				if (GUILayout.Button("Cancel", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }))
				{
					_waitingEntry = null;
					_forbiddenFrame = Time.frameCount;
					Event.current.Use();
				}
				else
				{
					Event current = Event.current;
					if (Time.frameCount > _activationFrame && ((int)current.type == 4 || (int)current.type == 0 || (int)current.type == 12) && ((int)current.type == 12 || ((int)current.type != 1 && (int)current.type != 3 && (int)current.type != 6)))
					{
						KeyCode val2 = (KeyCode)0;
						if ((int)current.keyCode != 0)
						{
							val2 = current.keyCode;
						}
						else if (current.button >= 0 && current.button <= 4)
						{
							val2 = (KeyCode)(323 + current.button);
						}
						if ((int)val2 != 0 && (int)val2 != 323)
						{
							if ((int)val2 == 27)
							{
								_waitingEntry = null;
								current.Use();
							}
							else if ((int)val2 != 306 && (int)val2 != 305 && (int)val2 != 304 && (int)val2 != 303 && (int)val2 != 308 && (int)val2 != 307 && (int)val2 != 310 && (int)val2 != 309)
							{
								KeyCode[] array = Keybinds.HeldModifiers();
								val.Value = new ItemBinding
								{
									ItemName = value.ItemName,
									Shortcut = new KeyboardShortcut(val2, array)
								};
								_waitingEntry = null;
								current.Use();
							}
						}
					}
				}
			}
			else if (GUILayout.Button("Clear", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }) && Time.frameCount != _forbiddenFrame)
			{
				val.Value = new ItemBinding
				{
					ItemName = "",
					Shortcut = KeyboardShortcut.Empty
				};
				Event.current.Use();
			}
			GUILayout.EndHorizontal();
		}
	}
	public static class RepairHotkey
	{
		private static ItemData _pendingTool;

		public static bool HandlePress(Player player)
		{
			Inventory inventory = ((Humanoid)player).GetInventory();
			ItemData val = FindRepairTool(player, inventory);
			if (val == null)
			{
				Log.Debug("No build tool with a repair piece found in inventory.");
				return false;
			}
			if (((Humanoid)player).IsItemEquiped(val) && ((Character)player).InPlaceMode())
			{
				Piece selectedPiece = player.GetSelectedPiece();
				if ((Object)(object)selectedPiece != (Object)null && selectedPiece.m_repairPiece)
				{
					_pendingTool = null;
					((Humanoid)player).UseItem(inventory, val, true);
				}
				else
				{
					SelectRepair(player, val.m_shared.m_buildPieces);
				}
				return true;
			}
			((Humanoid)player).UseItem(inventory, val, true);
			_pendingTool = val;
			Update(player);
			return true;
		}

		public static void Update(Player player)
		{
			if (_pendingTool != null)
			{
				if (((Humanoid)player).IsItemEquiped(_pendingTool) && ((Character)player).InPlaceMode())
				{
					SelectRepair(player, _pendingTool.m_shared.m_buildPieces);
					_pendingTool = null;
				}
				else if (!((Humanoid)player).IsItemEquiped(_pendingTool) && !player.IsEquipActionQueued(_pendingTool))
				{
					_pendingTool = null;
				}
			}
		}

		private static ItemData FindRepairTool(Player player, Inventory inventory)
		{
			ItemData val = null;
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (!((Object)(object)FindRepairPiece(allItem.m_shared.m_buildPieces) == (Object)null))
				{
					if (((Humanoid)player).IsItemEquiped(allItem))
					{
						return allItem;
					}
					if (val == null)
					{
						val = allItem;
					}
				}
			}
			return val;
		}

		private static Piece FindRepairPiece(PieceTable table)
		{
			if ((Object)(object)table == (Object)null)
			{
				return null;
			}
			foreach (GameObject piece in table.m_pieces)
			{
				if (!((Object)(object)piece == (Object)null))
				{
					Piece component = piece.GetComponent<Piece>();
					if ((Object)(object)component != (Object)null && component.m_repairPiece)
					{
						return component;
					}
				}
			}
			return null;
		}

		private static void SelectRepair(Player player, PieceTable table)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			List<Piece> piecesInSelectedCategory = table.GetPiecesInSelectedCategory();
			for (int i = 0; i < piecesInSelectedCategory.Count; i++)
			{
				if (piecesInSelectedCategory[i].m_repairPiece)
				{
					player.SetSelectedPiece(new Vector2Int(i % 15, i / 15));
					return;
				}
			}
			Piece val = FindRepairPiece(table);
			if ((Object)(object)val == (Object)null || !player.SetSelectedPiece(val))
			{
				Log.Warn("Could not select the repair piece in the equipped build tool.");
			}
		}
	}
}