Decompiled source of ControllerOnscreenKeyboard v1.3.0

BepInEx/plugins/ValheimControllerKeyboard/ValheimControllerKeyboard.dll

Decompiled 21 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BepInEx;
using GUIFramework;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.TextCore.LowLevel;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Valheim Controller Keyboard")]
[assembly: AssemblyDescription("In-game controller keyboard for Valheim text fields")]
[assembly: AssemblyVersion("1.0.16.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 ControllerKeyboard
{
	[BepInPlugin("scribestable.valheim.controllerkeyboard", "Valheim Controller Keyboard", "1.0.16")]
	public sealed class ControllerKeyboardPlugin : BaseUnityPlugin
	{
		internal static ControllerKeyboardPlugin Instance;

		private Harmony _harmony;

		internal static void Warn(string message)
		{
			if ((Object)(object)Instance != (Object)null)
			{
				((BaseUnityPlugin)Instance).Logger.LogWarning((object)message);
			}
		}

		private void Awake()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			Instance = this;
			_harmony = new Harmony("scribestable.valheim.controllerkeyboard");
			_harmony.PatchAll();
			((Component)this).gameObject.AddComponent<KeyboardOverlay>();
			((Component)this).gameObject.AddComponent<StartupFocus>();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Valheim Controller Keyboard 1.0.16 loaded. Extended keyboard symbols.");
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			Instance = null;
		}
	}
	[HarmonyPatch(typeof(Minimap), "ShowPinNameInput")]
	internal static class EditExistingMapPin
	{
		private static readonly MethodInfo Closest = AccessTools.Method(typeof(Minimap), "GetClosestPin", (Type[])null, (Type[])null);

		private static readonly MethodInfo Radius = AccessTools.PropertyGetter(typeof(Minimap), "PinInteractRadius");

		private static readonly MethodInfo Subscribe = AccessTools.Method(typeof(Minimap), "SubscribeToVirtualKeyboardChange", (Type[])null, (Type[])null);

		private static bool Prefix(Minimap __instance, Vector3 pos, ref PinData ___m_namePin, ref bool ___m_wasFocused)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Invalid comparison between Unknown and I4
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Invalid comparison between Unknown and I4
			//IL_00d6: 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_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			if (ZInput.IsTouchActive())
			{
				return true;
			}
			float num = (float)Radius.Invoke(__instance, null);
			PinData val = (PinData)Closest.Invoke(__instance, new object[3] { pos, num, true });
			if (val == null || !val.m_save || val.m_ownerID != 0L)
			{
				return true;
			}
			PinType type = val.m_type;
			if ((int)type > 3 && (int)type != 6)
			{
				return true;
			}
			___m_namePin = val;
			GuiInputField nameInput = __instance.m_nameInput;
			((TMP_InputField)nameInput).text = val.m_name ?? string.Empty;
			((Component)nameInput).gameObject.SetActive(true);
			if (ZInput.IsExclusiveGamepadActive())
			{
				((Component)nameInput).transform.localPosition = new Vector3(0f, -30f, 0f);
			}
			else
			{
				Vector2 val2 = default(Vector2);
				RectTransformUtility.ScreenPointToLocalPointInRectangle(((Component)((Component)nameInput).transform.parent).GetComponent<RectTransform>(), Vector2.op_Implicit(ZInput.pointerPosition), (Camera)null, ref val2);
				((Component)nameInput).transform.localPosition = new Vector3(val2.x, val2.y - 30f, 0f);
			}
			((Selectable)nameInput).Select();
			nameInput.ActivateInputField();
			Subscribe.Invoke(__instance, null);
			___m_wasFocused = true;
			return false;
		}
	}
	[HarmonyPatch(typeof(Minimap), "OnPinTextEntered")]
	internal static class RefreshEditedMapPin
	{
		private static void Prefix(PinData ___m_namePin, out PinData __state)
		{
			__state = ___m_namePin;
		}

		private static void Postfix(PinData __state)
		{
			PinNameData val = __state?.m_NamePinData;
			if ((Object)(object)((val != null) ? val.PinNameGameObject : null) != (Object)null)
			{
				AccessTools.Method(typeof(PinNameData), "SetTextAndGameObject", (Type[])null, (Type[])null).Invoke(val, new object[1] { val.PinNameGameObject });
			}
		}
	}
	internal sealed class StartupFocus : MonoBehaviour
	{
		private float _readyAt = -1f;

		private bool _attempted;

		[DllImport("user32.dll")]
		private static extern bool SetForegroundWindow(IntPtr window);

		private void Update()
		{
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Invalid comparison between Unknown and I4
			if (_attempted || (Object)(object)FejdStartup.instance == (Object)null)
			{
				return;
			}
			EventSystem current = EventSystem.current;
			if ((Object)(object)current == (Object)null)
			{
				return;
			}
			if (_readyAt < 0f)
			{
				_readyAt = Time.unscaledTime + 1f;
			}
			else
			{
				if (Time.unscaledTime < _readyAt)
				{
					return;
				}
				_attempted = true;
				ControllerKeyboardPlugin.Warn("Startup focus: focused=" + Application.isFocused + ", selected=" + (((Object)(object)current.currentSelectedGameObject != (Object)null) ? ((Object)current.currentSelectedGameObject).name : "none"));
				if (!Application.isFocused && (int)Application.platform == 2)
				{
					try
					{
						using Process process = Process.GetCurrentProcess();
						IntPtr mainWindowHandle = process.MainWindowHandle;
						ControllerKeyboardPlugin.Warn("One-time startup focus request accepted=" + (mainWindowHandle != IntPtr.Zero && SetForegroundWindow(mainWindowHandle)));
					}
					catch (Exception ex)
					{
						ControllerKeyboardPlugin.Warn("Startup focus request: " + ex.Message);
					}
				}
				if ((Object)(object)current.currentSelectedGameObject == (Object)null && (Object)(object)current.firstSelectedGameObject != (Object)null && current.firstSelectedGameObject.activeInHierarchy)
				{
					current.SetSelectedGameObject(current.firstSelectedGameObject);
				}
			}
		}

		private void OnApplicationFocus(bool focused)
		{
			ControllerKeyboardPlugin.Warn("Application focus=" + focused);
		}
	}
	[DefaultExecutionOrder(-10000)]
	internal sealed class KeyboardOverlay : MonoBehaviour
	{
		private sealed class KeySpec
		{
			internal readonly string Label;

			internal readonly string Value;

			internal readonly int Row;

			internal readonly float Column;

			internal readonly float Width;

			internal KeySpec(string label, string value, int row, float column, float width = 1f)
			{
				Label = label;
				Value = value;
				Row = row;
				Column = column;
				Width = width;
			}
		}

		private static KeyboardOverlay _instance;

		private EventSystem _events;

		private bool _navigationBefore;

		private int _releaseFrame = -1;

		private bool _armed;

		private bool _fontFailed;

		private readonly List<KeySpec> _keys = new List<KeySpec>();

		private readonly List<Image> _keyImages = new List<Image>();

		private TMP_InputField _target;

		private TMP_InputField _dismissedTarget;

		private string _originalText;

		private float _damageCooldown;

		private TMP_FontAsset _font;

		private TMP_FontAsset _readableFont;

		private string _fontCachePath;

		private TMP_Text _mode;

		private readonly List<Vector2> _keyPositions = new List<Vector2>();

		private int _pressed = -1;

		private float _pressedUntil;

		private GameObject _root;

		private RectTransform _keyRoot;

		private TMP_Text _preview;

		private TMP_Text _hint;

		private int _selected;

		private float _navigationColumn = 0.5f;

		private bool _upper;

		private bool _capsLock;

		private bool _symbols;

		private Vector2Int _lastDirection;

		private float _nextRepeat;

		private static MethodInfo _leftStickXMethod;

		private static MethodInfo _leftStickYMethod;

		private static bool _axisLookupLogged;

		private TMP_InputField _perfPreviewTarget;

		private string _perfPreviewText;

		private int _perfPreviewCaret;

		private ContentType _perfPreviewContent;

		private InputType _perfPreviewInput;

		private bool _perfVisualValid;

		private int _perfVisual_selected;

		private bool _perfVisual_upper;

		private bool _perfVisual_capsLock;

		private int _perfVisual_pressed;

		private float _perfVisual_pressedUntil;

		private bool _extraSymbols;

		internal static bool IsOpen { get; private set; }

		internal static bool Capturing
		{
			get
			{
				if ((Object)(object)_instance != (Object)null && ((Behaviour)_instance).isActiveAndEnabled && Application.isFocused && (Object)(object)_instance._root != (Object)null && _instance._root.activeInHierarchy && (Object)(object)_instance._target != (Object)null)
				{
					return ((Component)_instance._target).gameObject.activeInHierarchy;
				}
				return false;
			}
		}

		internal static bool BlocksMenu
		{
			get
			{
				if (!Capturing)
				{
					if ((Object)(object)_instance != (Object)null && ((Behaviour)_instance).isActiveAndEnabled)
					{
						return Time.frameCount <= _instance._releaseFrame;
					}
					return false;
				}
				return true;
			}
		}

		internal static bool Owns(TMP_InputField field)
		{
			if (Capturing)
			{
				return (Object)(object)_instance._target == (Object)(object)field;
			}
			return false;
		}

		private void Awake()
		{
			_instance = this;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
		}

		private void Update()
		{
			if (Time.unscaledTime < _damageCooldown)
			{
				return;
			}
			if (!Application.isFocused)
			{
				if (IsOpen)
				{
					Hide();
				}
				RestoreNavigation();
				return;
			}
			if (IsOpen && (Object)(object)_target != (Object)null && ((Component)_target).gameObject.activeInHierarchy && ((Selectable)_target).IsInteractable())
			{
				if (!_target.isFocused)
				{
					_target.ActivateInputField();
				}
				HoldNavigation();
				UpdateKeyboard();
				return;
			}
			if (IsOpen)
			{
				Hide();
			}
			if (Time.frameCount > _releaseFrame)
			{
				RestoreNavigation();
			}
			TMP_InputField val = FindFocusedInput();
			if ((Object)(object)val == (Object)null)
			{
				_dismissedTarget = null;
				if (IsOpen)
				{
					Hide();
				}
				return;
			}
			if ((Object)(object)val == (Object)(object)_dismissedTarget)
			{
				if (IsOpen)
				{
					Hide();
				}
				return;
			}
			if (!IsOpen || (Object)(object)_target != (Object)(object)val)
			{
				if (!EnsureOverlay(val))
				{
					return;
				}
				_target = val;
				_originalText = val.text;
				val.caretPosition = val.text.Length;
				val.selectionStringAnchorPosition = val.text.Length;
				val.selectionStringFocusPosition = val.text.Length;
				_selected = 0;
				_navigationColumn = 0.5f;
				_upper = string.IsNullOrEmpty(val.text);
				_capsLock = false;
				_symbols = false;
				RebuildKeys();
				Show();
			}
			UpdateKeyboard();
		}

		private void UpdateKeyboard()
		{
			if (!_armed)
			{
				_armed = !ReadButton("JoyButtonA") && !ReadButton("JoyButtonB") && !ReadButton("JoyStart");
				return;
			}
			HandleInput();
			if (IsOpen && (Object)(object)_target != (Object)null)
			{
				UpdatePreview();
			}
		}

		private void UpdatePreview()
		{
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Invalid comparison between Unknown and I4
			//IL_005e: 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_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Invalid comparison between Unknown and I4
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_target == (Object)null))
			{
				if (!((Object)(object)_target != (Object)(object)_perfPreviewTarget) && _target.text == _perfPreviewText && _target.selectionStringFocusPosition == _perfPreviewCaret && _target.contentType == _perfPreviewContent && _target.inputType == _perfPreviewInput)
				{
					return;
				}
				_perfPreviewTarget = _target;
				_perfPreviewText = _target.text;
				_perfPreviewCaret = _target.selectionStringFocusPosition;
				_perfPreviewContent = _target.contentType;
				_perfPreviewInput = _target.inputType;
			}
			if (!((Object)(object)_target == (Object)null) && !((Object)(object)_preview == (Object)null))
			{
				string text = _target.text ?? string.Empty;
				int num = Mathf.Clamp(_target.selectionStringFocusPosition, 0, text.Length);
				if ((int)_target.contentType == 7 || (int)_target.inputType == 2)
				{
					text = new string('*', text.Length);
				}
				if (text.Length == 0)
				{
					_preview.text = "|  Enter text...";
					((Graphic)_preview).color = new Color(0.8f, 0.75f, 0.64f, 1f);
					return;
				}
				int num2 = Mathf.Max(0, num - 30);
				int num3 = Mathf.Min(text.Length, num2 + 40);
				string text2 = text.Substring(num2, num3 - num2).Insert(num - num2, "|");
				_preview.text = ((num2 > 0) ? "…" : "") + text2 + ((num3 < text.Length) ? "…" : "");
				((Graphic)_preview).color = new Color(1f, 0.97f, 0.83f, 1f);
			}
		}

		private static TMP_InputField FindFocusedInput()
		{
			EventSystem current = EventSystem.current;
			if (!((Object)(object)current == (Object)null))
			{
				GameObject currentSelectedGameObject = current.currentSelectedGameObject;
				if (!((Object)(object)currentSelectedGameObject == (Object)null))
				{
					TMP_InputField component = currentSelectedGameObject.GetComponent<TMP_InputField>();
					if (!((Object)(object)component == (Object)null) && currentSelectedGameObject.activeInHierarchy && ((Selectable)component).IsInteractable() && component.isFocused)
					{
						return component;
					}
				}
			}
			return null;
		}

		private bool EnsureOverlay(TMP_InputField source)
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_root != (Object)null)
			{
				return true;
			}
			if (_fontFailed)
			{
				return false;
			}
			TMP_Text textComponent = source.textComponent;
			_font = (((Object)(object)textComponent != (Object)null) ? textComponent.font : null);
			if ((Object)(object)_font == (Object)null)
			{
				TMP_Text[] array = Resources.FindObjectsOfTypeAll<TMP_Text>();
				foreach (TMP_Text val in array)
				{
					if ((Object)(object)val != (Object)null && (Object)(object)val.font != (Object)null)
					{
						Scene scene = ((Component)val).gameObject.scene;
						if (((Scene)(ref scene)).IsValid())
						{
							_font = val.font;
							break;
						}
					}
				}
			}
			if ((Object)(object)_font == (Object)null)
			{
				ControllerKeyboardPlugin.Warn("Keyboard overlay is waiting for Valheim's UI font.");
				return false;
			}
			try
			{
				using (Stream stream = typeof(ControllerKeyboardPlugin).Assembly.GetManifestResourceStream("ControllerKeyboard.KeyboardSans.ttf"))
				{
					if (stream == null)
					{
						throw new InvalidOperationException("Embedded font is missing");
					}
					_fontCachePath = Path.GetTempFileName();
					using FileStream destination = new FileStream(_fontCachePath, FileMode.Truncate, FileAccess.Write, FileShare.None);
					stream.CopyTo(destination);
				}
				string fontCachePath = _fontCachePath;
				_readableFont = TMP_FontAsset.CreateFontAsset(fontCachePath, 0, 64, 8, (GlyphRenderMode)4165, 1024, 1024);
				if ((Object)(object)_readableFont == (Object)null)
				{
					throw new InvalidOperationException("Bundled font could not be loaded");
				}
				string text = "";
				for (int j = 32; j < 127; j++)
				{
					text += (char)j;
				}
				string text2 = default(string);
				if (!_readableFont.TryAddCharacters(text + "€…", ref text2, false))
				{
					throw new InvalidOperationException("Missing keyboard glyphs: " + text2);
				}
				if (((TMP_TextElement)_readableFont.characterLookupTable[97u]).glyphIndex == ((TMP_TextElement)_readableFont.characterLookupTable[65u]).glyphIndex)
				{
					throw new InvalidOperationException("Lowercase glyph validation failed");
				}
				_readableFont.atlasPopulationMode = (AtlasPopulationMode)0;
			}
			catch (Exception ex)
			{
				_fontFailed = true;
				ReleaseFontCache();
				ControllerKeyboardPlugin.Warn("Keyboard not opened: " + ex.Message + ". Check that the system temporary folder is writable.");
				return false;
			}
			BuildOverlay();
			return true;
		}

		private void BuildOverlay()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: 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_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: 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_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_030f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0314: Unknown result type (might be due to invalid IL or missing references)
			//IL_0335: Unknown result type (might be due to invalid IL or missing references)
			//IL_0347: Unknown result type (might be due to invalid IL or missing references)
			//IL_0349: Unknown result type (might be due to invalid IL or missing references)
			//IL_034a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0351: Unknown result type (might be due to invalid IL or missing references)
			//IL_0363: Unknown result type (might be due to invalid IL or missing references)
			//IL_036e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0387: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0408: Unknown result type (might be due to invalid IL or missing references)
			//IL_040d: Unknown result type (might be due to invalid IL or missing references)
			//IL_040e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0415: Unknown result type (might be due to invalid IL or missing references)
			//IL_0454: Unknown result type (might be due to invalid IL or missing references)
			//IL_0487: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0504: Unknown result type (might be due to invalid IL or missing references)
			//IL_0542: Unknown result type (might be due to invalid IL or missing references)
			//IL_0557: Unknown result type (might be due to invalid IL or missing references)
			//IL_0562: Unknown result type (might be due to invalid IL or missing references)
			//IL_0567: Unknown result type (might be due to invalid IL or missing references)
			//IL_0568: Unknown result type (might be due to invalid IL or missing references)
			//IL_056f: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0612: Unknown result type (might be due to invalid IL or missing references)
			//IL_0627: Unknown result type (might be due to invalid IL or missing references)
			//IL_0632: Unknown result type (might be due to invalid IL or missing references)
			//IL_0637: Unknown result type (might be due to invalid IL or missing references)
			//IL_0638: Unknown result type (might be due to invalid IL or missing references)
			//IL_063f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0660: Unknown result type (might be due to invalid IL or missing references)
			//IL_0692: Unknown result type (might be due to invalid IL or missing references)
			//IL_0698: Expected O, but got Unknown
			//IL_06c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_06fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_06fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0703: Unknown result type (might be due to invalid IL or missing references)
			//IL_073d: Unknown result type (might be due to invalid IL or missing references)
			//IL_075c: Unknown result type (might be due to invalid IL or missing references)
			//IL_077c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0781: Unknown result type (might be due to invalid IL or missing references)
			//IL_0782: Unknown result type (might be due to invalid IL or missing references)
			//IL_0789: Unknown result type (might be due to invalid IL or missing references)
			//IL_07aa: Unknown result type (might be due to invalid IL or missing references)
			_root = new GameObject("ControllerKeyboardOverlay", new Type[4]
			{
				typeof(RectTransform),
				typeof(Canvas),
				typeof(CanvasScaler),
				typeof(GraphicRaycaster)
			});
			Object.DontDestroyOnLoad((Object)(object)_root);
			Canvas component = _root.GetComponent<Canvas>();
			component.renderMode = (RenderMode)0;
			component.sortingOrder = 32000;
			CanvasScaler component2 = _root.GetComponent<CanvasScaler>();
			component2.uiScaleMode = (ScaleMode)1;
			component2.referenceResolution = new Vector2(1920f, 1080f);
			RectTransform component3 = Box(_root.transform, "Shadow", new Color(0f, 0f, 0f, 0.72f)).GetComponent<RectTransform>();
			component3.anchorMin = new Vector2(0.5f, 0f);
			component3.anchorMax = new Vector2(0.5f, 0f);
			component3.pivot = new Vector2(0.5f, 0f);
			component3.anchoredPosition = new Vector2(0f, 28f);
			component3.sizeDelta = new Vector2(1148f, 548f);
			GameObject val = Box(_root.transform, "Panel", new Color(0.12f, 0.075f, 0.042f, 1f));
			RectTransform component4 = val.GetComponent<RectTransform>();
			component4.anchorMin = new Vector2(0.5f, 0f);
			component4.anchorMax = new Vector2(0.5f, 0f);
			component4.pivot = new Vector2(0.5f, 0f);
			component4.anchoredPosition = new Vector2(0f, 42f);
			component4.sizeDelta = new Vector2(1120f, 520f);
			Outline obj = val.AddComponent<Outline>();
			((Shadow)obj).effectColor = new Color(0.66f, 0.43f, 0.16f, 1f);
			((Shadow)obj).effectDistance = new Vector2(3f, -3f);
			for (int i = 1; i < 8; i++)
			{
				GameObject obj2 = Box(val.transform, "PlankSeam", new Color(0.03f, 0.018f, 0.008f, 0.45f));
				RectTransform component5 = obj2.GetComponent<RectTransform>();
				component5.anchorMin = new Vector2(0.01f, (float)i / 8f);
				component5.anchorMax = new Vector2(0.99f, (float)i / 8f);
				component5.sizeDelta = new Vector2(0f, 2f);
				component5.anchoredPosition = Vector2.zero;
				((Graphic)obj2.GetComponent<Image>()).raycastTarget = false;
			}
			Vector2[] array = (Vector2[])(object)new Vector2[4]
			{
				new Vector2(0.013f, 0.03f),
				new Vector2(0.987f, 0.03f),
				new Vector2(0.013f, 0.97f),
				new Vector2(0.987f, 0.97f)
			};
			Vector2 anchorMin;
			foreach (Vector2 val2 in array)
			{
				GameObject obj3 = Box(val.transform, "BronzeStud", new Color(0.78f, 0.55f, 0.24f, 1f));
				RectTransform component6 = obj3.GetComponent<RectTransform>();
				anchorMin = (component6.anchorMax = val2);
				component6.anchorMin = anchorMin;
				component6.sizeDelta = new Vector2(9f, 9f);
				component6.anchoredPosition = Vector2.zero;
				((Transform)component6).localRotation = Quaternion.Euler(0f, 0f, 45f);
				((Graphic)obj3.GetComponent<Image>()).raycastTarget = false;
			}
			GameObject val4 = Box(val.transform, "Header", new Color(0.2f, 0.12f, 0.045f, 1f));
			RectTransform component7 = val4.GetComponent<RectTransform>();
			component7.anchorMin = new Vector2(0.02f, 0.88f);
			component7.anchorMax = new Vector2(0.98f, 0.98f);
			anchorMin = (component7.offsetMax = Vector2.zero);
			component7.offsetMin = anchorMin;
			TMP_Text obj4 = Text(val4.transform, "Title", 34, (TextAlignmentOptions)514);
			obj4.text = "THE SCRIBE'S TABLE";
			((Graphic)obj4).color = new Color(1f, 0.78f, 0.29f, 1f);
			Stretch(obj4.rectTransform);
			GameObject obj5 = Box(val.transform, "InputPreview", new Color(0.025f, 0.03f, 0.035f, 1f));
			RectTransform component8 = obj5.GetComponent<RectTransform>();
			component8.anchorMin = new Vector2(0.05f, 0.755f);
			component8.anchorMax = new Vector2(0.95f, 0.875f);
			anchorMin = (component8.offsetMax = Vector2.zero);
			component8.offsetMin = anchorMin;
			Outline obj6 = obj5.AddComponent<Outline>();
			((Shadow)obj6).effectColor = new Color(0.85f, 0.62f, 0.24f, 1f);
			((Shadow)obj6).effectDistance = new Vector2(2f, -2f);
			_preview = Text(val.transform, "Preview", 35, (TextAlignmentOptions)513);
			RectTransform rectTransform = _preview.rectTransform;
			rectTransform.anchorMin = new Vector2(0.07f, 0.765f);
			rectTransform.anchorMax = new Vector2(0.93f, 0.865f);
			anchorMin = (rectTransform.offsetMax = Vector2.zero);
			rectTransform.offsetMin = anchorMin;
			_preview.textWrappingMode = (TextWrappingModes)0;
			_preview.overflowMode = (TextOverflowModes)1;
			_preview.enableAutoSizing = true;
			_preview.fontSizeMin = 24f;
			_preview.fontSizeMax = 35f;
			((Graphic)_preview).color = new Color(1f, 0.93f, 0.75f, 1f);
			_hint = Text(val.transform, "Hint", 18, (TextAlignmentOptions)514);
			RectTransform rectTransform2 = _hint.rectTransform;
			rectTransform2.anchorMin = new Vector2(0.05f, 0.68f);
			rectTransform2.anchorMax = new Vector2(0.95f, 0.74f);
			anchorMin = (rectTransform2.offsetMax = Vector2.zero);
			rectTransform2.offsetMin = anchorMin;
			((Graphic)_hint).color = new Color(0.78f, 0.83f, 0.86f, 1f);
			_hint.text = "Stick: Move    D-pad: Move (console: commands)    A: Choose    X: Backspace    Y: Caps    Start: Done    B: Cancel";
			GameObject val5 = new GameObject("Keys", new Type[1] { typeof(RectTransform) });
			val5.transform.SetParent(val.transform, false);
			_keyRoot = val5.GetComponent<RectTransform>();
			_keyRoot.anchorMin = new Vector2(0.05f, 0.08f);
			_keyRoot.anchorMax = new Vector2(0.95f, 0.65f);
			RectTransform keyRoot = _keyRoot;
			anchorMin = (_keyRoot.offsetMax = Vector2.zero);
			keyRoot.offsetMin = anchorMin;
			_mode = Text(val.transform, "CaseMode", 20, (TextAlignmentOptions)514);
			_mode.rectTransform.anchorMin = new Vector2(0.1f, 0.01f);
			_mode.rectTransform.anchorMax = new Vector2(0.9f, 0.065f);
			RectTransform rectTransform3 = _mode.rectTransform;
			anchorMin = (_mode.rectTransform.offsetMax = Vector2.zero);
			rectTransform3.offsetMin = anchorMin;
			((Graphic)_mode).color = new Color(1f, 0.8f, 0.43f, 1f);
			_root.SetActive(false);
		}

		private static void Stretch(RectTransform rectTransform)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			rectTransform.anchorMin = Vector2.zero;
			rectTransform.anchorMax = Vector2.one;
			rectTransform.offsetMin = Vector2.zero;
			rectTransform.offsetMax = Vector2.zero;
		}

		private static GameObject Box(Transform parent, string name, Color color)
		{
			//IL_0021: 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)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			GameObject val = new GameObject(name, new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val.transform.SetParent(parent, false);
			((Graphic)val.GetComponent<Image>()).color = color;
			return val;
		}

		private TMP_Text Text(Transform parent, string name, int size, TextAlignmentOptions alignment)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			//IL_0081: 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)
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			val.SetActive(false);
			val.transform.SetParent(parent, false);
			TextMeshProUGUI obj = val.AddComponent<TextMeshProUGUI>();
			TMP_FontAsset val2 = (((TMP_Text)obj).font = ((name == "Title") ? _font : _readableFont));
			((TMP_Text)obj).fontSharedMaterial = ((TMP_Asset)val2).material;
			((TMP_Text)obj).fontStyle = (FontStyles)0;
			((Graphic)obj).raycastTarget = false;
			((TMP_Text)obj).richText = false;
			((TMP_Text)obj).fontSize = size;
			((TMP_Text)obj).alignment = alignment;
			((Graphic)obj).color = Color.white;
			val.SetActive(true);
			return (TMP_Text)(object)obj;
		}

		private void RebuildKeys()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			_perfVisualValid = false;
			foreach (Transform item in (Transform)_keyRoot)
			{
				Object.Destroy((Object)(object)((Component)item).gameObject);
			}
			_keys.Clear();
			_keyImages.Clear();
			_keyPositions.Clear();
			_pressed = -1;
			_mode.text = (_capsLock ? ChooseSymbolsText("CAPS LOCK ON  |  All letters capital", "Symbols | More symbols / Y: switch symbols", _symbols) : (_upper ? ChooseSymbolsText("Caps ON  |  Next letter capital, then lowercase", "Symbols | More symbols / Y: switch symbols", _symbols) : ChooseSymbolsText("abc  |  Lowercase", "Symbols | More symbols / Y: switch symbols", _symbols)));
			string[] array = ((!_symbols) ? new string[3] { "QWERTYUIOP", "ASDFGHJKL'", "ZXCVBNM,.?" } : new string[3]
			{
				ChooseSymbolsText("1234567890", "!@#$%^&*()", _extraSymbols),
				ChooseSymbolsText("-_=+[]{}\\|", "-_=+[]{}\\|", _extraSymbols),
				ChooseSymbolsText(";:'\",.<>/?", "`~€£;:'\"?!", _extraSymbols)
			});
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i];
				for (int j = 0; j < text.Length; j++)
				{
					string text2 = text[j].ToString();
					string label = (_symbols ? text2 : ((_upper || _capsLock) ? text2 : text2.ToLowerInvariant()));
					AddKey(label, text2, i, j);
				}
			}
			AddKey("Backspace", "back", 0, 10f, 2f);
			AddKey(_capsLock ? "Lock ON" : "Caps Lock", "lock", 1, 10f, 2f);
			AddKey("Done", "done", 2, 10f, 2f);
			AddKey(_upper ? ChooseSymbolsText("Caps ON", "More symbols", _symbols) : ChooseSymbolsText("Caps", "More symbols", _symbols), "caps", 3, 0f, 2f);
			AddKey(_symbols ? "ABC" : "123", "symbols", 3, 2f);
			AddKey("Space", "space", 3, 3f, 7f);
			AddKey("Cancel", "cancel", 3, 10f, 2f);
			_selected = Mathf.Clamp(_selected, 0, _keys.Count - 1);
			UpdateSelection();
		}

		private void AddKey(string label, string value, int row, float column, float width = 1f)
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: 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_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: 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_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Expected O, but got Unknown
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: 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_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			KeySpec spec = new KeySpec(label, value, row, column, width);
			int index = _keys.Count;
			_keys.Add(spec);
			GameObject val = Box((Transform)(object)_keyRoot, "Key_" + label, new Color(0.2f, 0.14f, 0.085f, 1f));
			Outline obj = val.AddComponent<Outline>();
			((Shadow)obj).effectColor = new Color(0.56f, 0.37f, 0.16f, 1f);
			((Shadow)obj).effectDistance = new Vector2(1.5f, -1.5f);
			Shadow obj2 = val.AddComponent<Shadow>();
			obj2.effectColor = new Color(0.025f, 0.015f, 0.008f, 1f);
			obj2.effectDistance = new Vector2(0f, -5f);
			RectTransform component = val.GetComponent<RectTransform>();
			float num = 78f;
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0.5f, 1f);
			component.anchorMax = val2;
			component.anchorMin = val2;
			component.pivot = new Vector2(0.5f, 1f);
			component.sizeDelta = new Vector2(num * width - 8f, 62f);
			component.anchoredPosition = new Vector2(-468f + (column + width * 0.5f) * num, (float)(-row) * 72f);
			_keyPositions.Add(component.anchoredPosition);
			Button obj3 = val.AddComponent<Button>();
			Navigation navigation = default(Navigation);
			((Navigation)(ref navigation)).mode = (Mode)0;
			((Selectable)obj3).navigation = navigation;
			ColorBlock colors = ((Selectable)obj3).colors;
			((ColorBlock)(ref colors)).normalColor = Color.white;
			((ColorBlock)(ref colors)).highlightedColor = Color.white;
			((ColorBlock)(ref colors)).pressedColor = Color.white;
			((ColorBlock)(ref colors)).selectedColor = Color.white;
			((Selectable)obj3).colors = colors;
			((UnityEvent)obj3.onClick).AddListener((UnityAction)delegate
			{
				_selected = index;
				_navigationColumn = spec.Column + spec.Width * 0.5f;
				ActivateSelected();
			});
			TMP_Text obj4 = Text(val.transform, "Label", (label.Length > 1) ? 23 : 40, (TextAlignmentOptions)514);
			obj4.text = label;
			obj4.enableAutoSizing = label.Length > 1;
			obj4.fontSizeMin = 17f;
			obj4.fontSizeMax = 23f;
			obj4.textWrappingMode = (TextWrappingModes)0;
			RectTransform rectTransform = obj4.rectTransform;
			rectTransform.anchorMin = Vector2.zero;
			rectTransform.anchorMax = Vector2.one;
			val2 = (rectTransform.offsetMin = (rectTransform.offsetMax = Vector2.zero));
			((Graphic)obj4).color = new Color(0.94f, 0.94f, 0.88f, 1f);
			_keyImages.Add(val.GetComponent<Image>());
		}

		private void Show()
		{
			IsOpen = true;
			_armed = false;
			_root.SetActive(true);
			HoldNavigation();
			UpdateSelection();
		}

		private void Hide()
		{
			IsOpen = false;
			_releaseFrame = Time.frameCount + 1;
			_root.SetActive(false);
			_target = null;
		}

		private void OnDisable()
		{
			RestoreNavigation();
			_releaseFrame = -1;
			IsOpen = false;
			if ((Object)(object)_root != (Object)null)
			{
				_root.SetActive(false);
			}
			_target = null;
		}

		private void OnDestroy()
		{
			RestoreNavigation();
			_instance = null;
			IsOpen = false;
			if ((Object)(object)_root != (Object)null)
			{
				Object.Destroy((Object)(object)_root);
			}
			if ((Object)(object)_readableFont != (Object)null && (Object)(object)_readableFont != (Object)(object)_font)
			{
				Object.Destroy((Object)(object)_readableFont);
			}
			ReleaseFontCache();
		}

		private void ReleaseFontCache()
		{
			if (!string.IsNullOrEmpty(_fontCachePath))
			{
				try
				{
					File.Delete(_fontCachePath);
				}
				catch (IOException)
				{
				}
				catch (UnauthorizedAccessException)
				{
				}
				_fontCachePath = null;
			}
		}

		private void LateUpdate()
		{
			if (IsOpen)
			{
				HoldNavigation();
				UpdateSelection();
			}
			else if (Time.frameCount > _releaseFrame)
			{
				RestoreNavigation();
			}
		}

		private void HoldNavigation()
		{
			if (!Capturing)
			{
				RestoreNavigation();
				return;
			}
			if ((Object)(object)_events != (Object)(object)EventSystem.current)
			{
				RestoreNavigation();
				_events = EventSystem.current;
				if ((Object)(object)_events != (Object)null)
				{
					_navigationBefore = _events.sendNavigationEvents | (_target is GuiInputField);
				}
			}
			if ((Object)(object)_events != (Object)null)
			{
				_events.sendNavigationEvents = false;
			}
		}

		private void RestoreNavigation()
		{
			if ((Object)(object)_events != (Object)null)
			{
				_events.sendNavigationEvents = _navigationBefore;
			}
			_events = null;
		}

		private void HandleInput()
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: 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)
			Vector2Int val = default(Vector2Int);
			((Vector2Int)(ref val))..ctor((ReadKeyboardDPad("JoyDPadRight") || ReadStickX(1)) ? 1 : ((ReadKeyboardDPad("JoyDPadLeft") || ReadStickX(-1)) ? (-1) : 0), (ReadKeyboardDPad("JoyDPadUp") || ReadStickY(1)) ? (-1) : ((ReadKeyboardDPad("JoyDPadDown") || ReadStickY(-1)) ? 1 : 0));
			if (val != Vector2Int.zero && (val != _lastDirection || Time.unscaledTime >= _nextRepeat))
			{
				Move(val);
				_nextRepeat = Time.unscaledTime + ((_lastDirection == Vector2Int.zero) ? 0.26f : 0.085f);
			}
			_lastDirection = val;
			if (ReadButtonDown("JoyButtonB"))
			{
				Cancel();
				return;
			}
			if (ReadButtonDown("JoyStart") || ReadButtonDown("JoyMenu"))
			{
				Done();
				return;
			}
			if (ReadButtonDown("JoyButtonA"))
			{
				ActivateSelected();
				return;
			}
			if (ReadButtonDown("JoyButtonX"))
			{
				Backspace();
			}
			if (ReadButtonDown("JoyButtonY"))
			{
				ToggleCaps();
			}
		}

		private static bool ReadStickX(int sign)
		{
			return (float)sign * ReadStickAxis(ref _leftStickXMethod, "GetJoyLeftStickX") > 0.65f;
		}

		private static bool ReadStickY(int sign)
		{
			return (float)sign * ReadStickAxis(ref _leftStickYMethod, "GetJoyLeftStickY") > 0.65f;
		}

		private static float ReadStickAxis(ref MethodInfo method, string name)
		{
			try
			{
				if (method == null)
				{
					MethodInfo[] methods = typeof(ZInput).GetMethods(BindingFlags.Static | BindingFlags.Public);
					foreach (MethodInfo methodInfo in methods)
					{
						if (!(methodInfo.Name != name) && !(methodInfo.ReturnType != typeof(float)))
						{
							ParameterInfo[] parameters = methodInfo.GetParameters();
							if (parameters.Length == 0 || (parameters.Length == 1 && parameters[0].ParameterType == typeof(bool)))
							{
								method = methodInfo;
								break;
							}
						}
					}
				}
				if (method == null)
				{
					return 0f;
				}
				return (((method.GetParameters().Length == 0) ? method.Invoke(null, null) : method.Invoke(null, new object[1] { false })) is float num) ? num : 0f;
			}
			catch (Exception ex)
			{
				if (!_axisLookupLogged)
				{
					_axisLookupLogged = true;
					ControllerKeyboardPlugin.Warn("Controller stick input unavailable: " + ex.GetType().Name);
				}
				return 0f;
			}
		}

		private static bool ReadButton(string button)
		{
			return ZInput.GetButton(button);
		}

		private static bool ReadButtonDown(string button)
		{
			return ZInput.GetButtonDown(button);
		}

		private void Move(Vector2Int direction)
		{
			if (_keys.Count == 0)
			{
				return;
			}
			if (((Vector2Int)(ref direction)).y != 0)
			{
				((Vector2Int)(ref direction)).x = 0;
			}
			KeySpec keySpec = _keys[_selected];
			int num = keySpec.Row + ((Vector2Int)(ref direction)).y;
			if (num < 0)
			{
				num = 3;
			}
			if (num > 3)
			{
				num = 0;
			}
			int num2 = _selected;
			float num3 = float.MaxValue;
			for (int i = 0; i < _keys.Count; i++)
			{
				KeySpec keySpec2 = _keys[i];
				if ((((Vector2Int)(ref direction)).y != 0 && keySpec2.Row != num) || (((Vector2Int)(ref direction)).x != 0 && keySpec2.Row != keySpec.Row))
				{
					continue;
				}
				if (((Vector2Int)(ref direction)).x != 0)
				{
					float num4 = keySpec2.Column - keySpec.Column;
					if ((((Vector2Int)(ref direction)).x <= 0 || !(num4 <= 0f)) && (((Vector2Int)(ref direction)).x >= 0 || !(num4 >= 0f)))
					{
						float num5 = Mathf.Abs(num4);
						if (num5 < num3)
						{
							num3 = num5;
							num2 = i;
						}
					}
				}
				else
				{
					float num6 = Mathf.Abs(_navigationColumn - Mathf.Clamp(_navigationColumn, keySpec2.Column, keySpec2.Column + keySpec2.Width));
					if (num6 < num3)
					{
						num3 = num6;
						num2 = i;
					}
				}
			}
			if (num2 == _selected && ((Vector2Int)(ref direction)).x != 0)
			{
				float num7 = float.MaxValue;
				float num8 = float.MinValue;
				for (int j = 0; j < _keys.Count; j++)
				{
					if (_keys[j].Row == keySpec.Row)
					{
						num7 = Mathf.Min(num7, _keys[j].Column);
						num8 = Mathf.Max(num8, _keys[j].Column);
					}
				}
				float num9 = ((((Vector2Int)(ref direction)).x > 0) ? num7 : num8);
				for (int k = 0; k < _keys.Count; k++)
				{
					if (_keys[k].Row == keySpec.Row && _keys[k].Column == num9)
					{
						num2 = k;
						break;
					}
				}
			}
			_selected = num2;
			if (((Vector2Int)(ref direction)).x != 0)
			{
				_navigationColumn = _keys[num2].Column + _keys[num2].Width * 0.5f;
			}
			UpdateSelection();
		}

		private void UpdateSelection()
		{
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: 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_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: 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)
			if (!_perfVisualValid || _selected != _perfVisual_selected || _upper != _perfVisual_upper || _capsLock != _perfVisual_capsLock || _pressed != _perfVisual_pressed || _pressedUntil != _perfVisual_pressedUntil)
			{
				for (int i = 0; i < _keyImages.Count; i++)
				{
					float num = ((i == _pressed) ? Mathf.Clamp01((_pressedUntil - Time.unscaledTime) / 0.16f) : 0f);
					Image obj = _keyImages[i];
					string value = _keys[i].Value;
					bool flag = (value == "caps" && _upper) || (value == "lock" && _capsLock);
					Color val = ((value == "done") ? new Color(0.2f, 0.28f, 0.19f, 1f) : (flag ? new Color(0.38f, 0.25f, 0.08f, 1f) : ((value.Length > 1) ? new Color(0.15f, 0.105f, 0.07f, 1f) : new Color(0.2f, 0.14f, 0.085f, 1f))));
					((Graphic)obj).color = (Color)((num > 0f) ? new Color(0.86f, 0.61f, 0.25f, 1f) : ((i == _selected) ? new Color(0.48f, 0.29f, 0.1f, 1f) : val));
					((Graphic)obj).rectTransform.anchoredPosition = _keyPositions[i] + new Vector2(0f, -5f * num);
					((Transform)((Graphic)obj).rectTransform).localScale = Vector3.one * (1f - 0.055f * num);
				}
				_perfVisual_selected = _selected;
				_perfVisual_upper = _upper;
				_perfVisual_capsLock = _capsLock;
				_perfVisual_pressed = _pressed;
				_perfVisual_pressedUntil = _pressedUntil;
				_perfVisualValid = !(Time.unscaledTime < _pressedUntil);
			}
		}

		private void ActivateSelected()
		{
			if (_selected >= 0 && _selected < _keys.Count)
			{
				_pressed = _selected;
				_pressedUntil = Time.unscaledTime + 0.16f;
				string value = _keys[_selected].Value;
				switch (value)
				{
				case "caps":
					ToggleCaps();
					break;
				case "lock":
					_capsLock = !_capsLock;
					_upper = false;
					RebuildKeys();
					break;
				case "symbols":
					_symbols = !_symbols;
					RebuildKeys();
					break;
				case "space":
					Insert(" ");
					break;
				case "back":
					Backspace();
					break;
				case "done":
					Done();
					break;
				case "cancel":
					Cancel();
					break;
				default:
					Insert(_symbols ? value : ((_upper || _capsLock) ? value : value.ToLowerInvariant()));
					break;
				}
				if (IsOpen)
				{
					_pressed = _selected;
					_pressedUntil = Time.unscaledTime + 0.16f;
				}
			}
		}

		private void ToggleCaps()
		{
			if (_symbols)
			{
				_extraSymbols = !_extraSymbols;
				RebuildKeys();
			}
			else
			{
				_capsLock = false;
				_upper = !_upper;
				RebuildKeys();
			}
		}

		private void Insert(string value)
		{
			if (!((Object)(object)_target == (Object)null))
			{
				string text = _target.text;
				ReplaceSelection(value);
				if (_upper && !_capsLock && value.Length > 0 && char.IsLetter(value[0]) && _target.text != text)
				{
					_upper = false;
					RebuildKeys();
				}
				UpdatePreview();
			}
		}

		private void Backspace()
		{
			if (!((Object)(object)_target == (Object)null))
			{
				int num = Mathf.Min(_target.selectionStringAnchorPosition, _target.selectionStringFocusPosition);
				int num2 = Mathf.Max(_target.selectionStringAnchorPosition, _target.selectionStringFocusPosition);
				if (num == num2 && num > 0)
				{
					num--;
				}
				ReplaceRange(num, num2, string.Empty);
			}
		}

		private void Delete()
		{
			if (!((Object)(object)_target == (Object)null))
			{
				int num = Mathf.Min(_target.selectionStringAnchorPosition, _target.selectionStringFocusPosition);
				int num2 = Mathf.Max(_target.selectionStringAnchorPosition, _target.selectionStringFocusPosition);
				if (num == num2 && num2 < _target.text.Length)
				{
					num2++;
				}
				ReplaceRange(num, num2, string.Empty);
			}
		}

		private void ReplaceSelection(string value)
		{
			int start = Mathf.Min(_target.selectionStringAnchorPosition, _target.selectionStringFocusPosition);
			int end = Mathf.Max(_target.selectionStringAnchorPosition, _target.selectionStringFocusPosition);
			ReplaceRange(start, end, value);
		}

		private void ReplaceRange(int start, int end, string value)
		{
			string text = _target.text ?? string.Empty;
			start = Mathf.Clamp(start, 0, text.Length);
			end = Mathf.Clamp(end, start, text.Length);
			if (_target.characterLimit > 0)
			{
				int num = _target.characterLimit - (text.Length - (end - start));
				if (num <= 0 && value.Length > 0)
				{
					return;
				}
				if (value.Length > num)
				{
					value = value.Substring(0, num);
				}
			}
			_target.text = text.Substring(0, start) + value + text.Substring(end);
			int num2 = start + value.Length;
			_target.caretPosition = num2;
			_target.selectionStringAnchorPosition = num2;
			_target.selectionStringFocusPosition = num2;
			_target.ForceLabelUpdate();
		}

		private void Done()
		{
			if (!((Object)(object)_target == (Object)null))
			{
				TMP_InputField target = _target;
				string text = target.text;
				bool num = (Object)(object)TextInput.instance != (Object)null && (Object)(object)TextInput.instance.m_inputField == (Object)(object)target && TextInput.IsVisible();
				Dismiss();
				if (num)
				{
					TextInput.instance.OnEnter();
				}
				else
				{
					((UnityEvent<string>)(object)target.onSubmit)?.Invoke(text);
				}
			}
		}

		private void Cancel()
		{
			bool flag = (Object)(object)TextInput.instance != (Object)null && (Object)(object)TextInput.instance.m_inputField == (Object)(object)_target && TextInput.IsVisible();
			bool num = (Object)(object)Minimap.instance != (Object)null && (Object)(object)Minimap.instance.m_nameInput == (Object)(object)_target;
			if ((Object)(object)_target != (Object)null)
			{
				_target.SetTextWithoutNotify(_originalText ?? string.Empty);
			}
			Dismiss();
			if (flag)
			{
				TextInput.instance.OnCancel();
			}
			if (num)
			{
				AccessTools.Method(typeof(Minimap), "HidePinTextInput", (Type[])null, (Type[])null)?.Invoke(Minimap.instance, new object[1] { true });
			}
		}

		internal static void OnLocalPlayerDamaged()
		{
			if ((Object)(object)_instance == (Object)null || !IsOpen)
			{
				return;
			}
			try
			{
				_instance.DismissForDamage();
			}
			catch (Exception ex)
			{
				_instance.OnDisable();
				ControllerKeyboardPlugin.Warn("Damage-dismiss cleanup: " + ex.Message);
			}
		}

		private void DismissForDamage()
		{
			TMP_InputField target = _target;
			bool flag = (Object)(object)TextInput.instance != (Object)null && (Object)(object)TextInput.instance.m_inputField == (Object)(object)target;
			bool num = (Object)(object)Minimap.instance != (Object)null && (Object)(object)Minimap.instance.m_nameInput == (Object)(object)target;
			bool flag2 = (Object)(object)Chat.instance != (Object)null && (Object)(object)((Terminal)Chat.instance).m_input == (Object)(object)target;
			_damageCooldown = Time.unscaledTime + 0.5f;
			if ((Object)(object)target != (Object)null)
			{
				target.SetTextWithoutNotify(_originalText ?? string.Empty);
			}
			Dismiss();
			_releaseFrame = -1;
			RestoreNavigation();
			if ((Object)(object)EventSystem.current != (Object)null && (Object)(object)target != (Object)null && (Object)(object)EventSystem.current.currentSelectedGameObject == (Object)(object)((Component)target).gameObject)
			{
				EventSystem.current.SetSelectedGameObject((GameObject)null);
			}
			if (flag)
			{
				TextInput.instance.OnCancel();
			}
			if (num)
			{
				AccessTools.Method(typeof(Minimap), "HidePinTextInput", (Type[])null, (Type[])null)?.Invoke(Minimap.instance, new object[1] { true });
				Minimap.instance.SetMapMode((MapMode)1);
			}
			if (flag2 && (Object)(object)target != (Object)null)
			{
				((Component)target).gameObject.SetActive(false);
				Chat.instance.Hide();
			}
			ControllerKeyboardPlugin.Warn("Keyboard dismissed after local player damage; draft not submitted.");
		}

		private void Dismiss()
		{
			_dismissedTarget = _target;
			if (_target is GuiInputField)
			{
				_navigationBefore = true;
			}
			if ((Object)(object)_target != (Object)null)
			{
				_target.DeactivateInputField(false);
			}
			Hide();
		}

		private static string Truncate(string value, int max)
		{
			value = value ?? string.Empty;
			if (value.Length <= max)
			{
				return value;
			}
			return value.Substring(0, max - 1) + "…";
		}

		private static bool ReadKeyboardDPad(string button)
		{
			if (Console.IsVisible())
			{
				return false;
			}
			return ReadButton(button);
		}

		internal static bool KeepKeyboardPointerFocus(EventSystem eventSystem, BaseEventData data)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			if (Capturing)
			{
				PointerEventData val = (PointerEventData)(object)((data is PointerEventData) ? data : null);
				if (val != null && (Object)(object)eventSystem.currentSelectedGameObject == (Object)(object)((Component)_instance._target).gameObject)
				{
					RaycastResult pointerCurrentRaycast = val.pointerCurrentRaycast;
					GameObject gameObject = ((RaycastResult)(ref pointerCurrentRaycast)).gameObject;
					if ((Object)(object)gameObject != (Object)null)
					{
						return gameObject.transform.IsChildOf(_instance._root.transform);
					}
				}
			}
			return false;
		}

		private static string ChooseSymbolsText(string P_0, string P_1, bool P_2)
		{
			if (!P_2)
			{
				return P_0;
			}
			return P_1;
		}
	}
	[HarmonyPatch(typeof(HotkeyBar), "Update")]
	internal static class KeyboardHotbarGuard
	{
		private static readonly MethodInfo UpdateIcons = AccessTools.Method(typeof(HotkeyBar), "UpdateIcons", (Type[])null, (Type[])null);

		private static bool Prefix(HotkeyBar __instance)
		{
			if (!KeyboardOverlay.BlocksMenu)
			{
				return true;
			}
			UpdateIcons.Invoke(__instance, new object[1] { Player.m_localPlayer });
			return false;
		}
	}
	[HarmonyPatch(typeof(HotkeyBar), "ElementClicked")]
	internal static class KeyboardHotbarClickGuard
	{
		private static bool Prefix()
		{
			return !KeyboardOverlay.BlocksMenu;
		}
	}
	[HarmonyPatch(typeof(UIGamePad), "ButtonPressed")]
	internal static class KeyboardMenuGuard
	{
		private static bool Prefix(ref bool __result)
		{
			if (!KeyboardOverlay.BlocksMenu)
			{
				return true;
			}
			__result = false;
			return false;
		}
	}
	[HarmonyPatch(typeof(GuiInputField), "Update")]
	internal static class KeyboardFieldGuard
	{
		private static bool Prefix(GuiInputField __instance)
		{
			return !KeyboardOverlay.Owns((TMP_InputField)(object)__instance);
		}
	}
	[HarmonyPatch(typeof(GuiInputField), "OnSubmit")]
	internal static class KeyboardSubmitGuard
	{
		private static bool Prefix(GuiInputField __instance)
		{
			return !KeyboardOverlay.Owns((TMP_InputField)(object)__instance);
		}
	}
	[HarmonyPatch(typeof(Character), "ApplyDamage")]
	internal static class KeyboardDamageGuard
	{
		private static void Prefix(Character __instance, out float __state)
		{
			__state = ((KeyboardOverlay.IsOpen && (Object)(object)Player.m_localPlayer != (Object)null && (Object)(object)__instance == (Object)(object)Player.m_localPlayer) ? __instance.GetHealth() : (-1f));
		}

		private static void Postfix(Character __instance, float __state)
		{
			if (__state >= 0f && (Object)(object)__instance == (Object)(object)Player.m_localPlayer && __instance.GetHealth() < __state)
			{
				KeyboardOverlay.OnLocalPlayerDamaged();
			}
		}
	}
	[HarmonyPatch(typeof(EventSystem), "SetSelectedGameObject", new Type[]
	{
		typeof(GameObject),
		typeof(BaseEventData)
	})]
	internal static class KeyboardPointerFocusGuard
	{
		private static bool Prefix(EventSystem __instance, BaseEventData __1)
		{
			return !KeyboardOverlay.KeepKeyboardPointerFocus(__instance, __1);
		}
	}
}