Decompiled source of CommandTypeahead v1.0.0

plugins/CommandTypeahead.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("CommandTypeahead")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("CommandTypeahead")]
[assembly: AssemblyTitle("CommandTypeahead")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 CommandTypeahead
{
	public class CommandInfo
	{
		public string Name { get; set; }

		public string Description { get; set; }

		public string Category { get; set; }

		public CommandInfo(string name, string description, string category = "General")
		{
			Name = name;
			Description = description;
			Category = category;
		}
	}
	public static class CommandHelper
	{
		public static bool IsAvailable => Type.GetType("CommandAPI.CommandRegistry, CommandAPI") != null;

		public static List<CommandInfo> FindMatches(string prefix)
		{
			List<CommandInfo> list = new List<CommandInfo>();
			try
			{
				Type type = Type.GetType("CommandAPI.CommandRegistry, CommandAPI");
				if (type == null)
				{
					return list;
				}
				MethodInfo method = type.GetMethod("FindMatches", new Type[1] { typeof(string) });
				if (method == null)
				{
					return list;
				}
				if (method.Invoke(null, new object[1] { prefix }) is IEnumerable enumerable)
				{
					foreach (object item in enumerable)
					{
						if (item != null)
						{
							Type type2 = item.GetType();
							PropertyInfo property = type2.GetProperty("Name");
							PropertyInfo property2 = type2.GetProperty("Description");
							PropertyInfo? property3 = type2.GetProperty("Category");
							string text = property?.GetValue(item) as string;
							string text2 = property2?.GetValue(item) as string;
							string text3 = property3?.GetValue(item) as string;
							if (text != null)
							{
								list.Add(new CommandInfo(text, text2 ?? "", text3 ?? "General"));
							}
						}
					}
				}
			}
			catch (Exception)
			{
			}
			return list;
		}
	}
	public class CommandTypeaheadManager : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <InitializeWhenReady>d__11 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public CommandTypeaheadManager <>4__this;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <InitializeWhenReady>d__11(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_002a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0034: Expected O, but got Unknown
				//IL_005b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0065: Expected O, but got Unknown
				int num = <>1__state;
				CommandTypeaheadManager commandTypeaheadManager = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForEndOfFrame();
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					break;
				case 2:
					<>1__state = -1;
					break;
				}
				while (!commandTypeaheadManager.isInitialized)
				{
					commandTypeaheadManager.TryInitialize();
					if (!commandTypeaheadManager.isInitialized)
					{
						<>2__current = (object)new WaitForSeconds(1f);
						<>1__state = 2;
						return true;
					}
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private TMP_InputField chatInput;

		private TypeaheadDropdown dropdown;

		private bool isInitialized;

		private bool isWaitingForAPI = true;

		private float checkInterval = 1f;

		private float lastCheck;

		private void Awake()
		{
			SceneManager.sceneLoaded += OnSceneLoaded;
			SceneManager.sceneUnloaded += OnSceneUnloaded;
		}

		private void OnDestroy()
		{
			SceneManager.sceneLoaded -= OnSceneLoaded;
			SceneManager.sceneUnloaded -= OnSceneUnloaded;
			Cleanup();
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			if (((Scene)(ref scene)).name == "Island")
			{
				((MonoBehaviour)this).StopAllCoroutines();
				((MonoBehaviour)this).StartCoroutine(InitializeWhenReady());
			}
		}

		private void OnSceneUnloaded(Scene scene)
		{
			if (((Scene)(ref scene)).name == "Island")
			{
				Cleanup();
			}
		}

		private void Cleanup()
		{
			((MonoBehaviour)this).StopAllCoroutines();
			if ((Object)(object)chatInput != (Object)null)
			{
				((UnityEvent<string>)(object)chatInput.onValueChanged).RemoveListener((UnityAction<string>)OnChatInputChanged);
				chatInput = null;
			}
			if ((Object)(object)dropdown != (Object)null)
			{
				Object.Destroy((Object)(object)dropdown);
				dropdown = null;
			}
			isInitialized = false;
			isWaitingForAPI = true;
			lastCheck = 0f;
		}

		[IteratorStateMachine(typeof(<InitializeWhenReady>d__11))]
		private IEnumerator InitializeWhenReady()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <InitializeWhenReady>d__11(0)
			{
				<>4__this = this
			};
		}

		private void Update()
		{
			if (!isInitialized || (Object)(object)chatInput == (Object)null || (Object)(object)dropdown == (Object)null)
			{
				return;
			}
			if (isWaitingForAPI)
			{
				lastCheck += Time.deltaTime;
				if (lastCheck >= checkInterval)
				{
					lastCheck = 0f;
					CheckForCommandAPI();
				}
			}
			else if (chatInput.isFocused && dropdown.IsVisible)
			{
				HandleKeyboardInput();
			}
		}

		private object GetStaticPropertyOrField(Type type, string name)
		{
			PropertyInfo property = type.GetProperty(name, BindingFlags.Static | BindingFlags.Public);
			if (property != null)
			{
				return property.GetValue(null);
			}
			FieldInfo field = type.GetField(name, BindingFlags.Static | BindingFlags.Public);
			if (field != null)
			{
				return field.GetValue(null);
			}
			return null;
		}

		private TMP_InputField GetChatInput()
		{
			Type type = AccessTools.TypeByName("MonoSingleton`1");
			if (type == null)
			{
				return TryGetChatInputFallback();
			}
			Type type2 = AccessTools.TypeByName("UIManager");
			if (type2 == null)
			{
				return null;
			}
			PropertyInfo property = type.MakeGenericType(type2).GetProperty("I", BindingFlags.Static | BindingFlags.Public);
			if (property == null)
			{
				return TryGetChatInputFallback();
			}
			object value = property.GetValue(null);
			if (value == null)
			{
				return null;
			}
			PropertyInfo property2 = type2.GetProperty("MessageInput");
			if (property2 == null)
			{
				return null;
			}
			object? value2 = property2.GetValue(value);
			return (TMP_InputField)((value2 is TMP_InputField) ? value2 : null);
		}

		private TMP_InputField TryGetChatInputFallback()
		{
			Type type = AccessTools.TypeByName("UIManager");
			if (type == null)
			{
				return null;
			}
			object staticPropertyOrField = GetStaticPropertyOrField(type, "I");
			if (staticPropertyOrField == null)
			{
				return null;
			}
			PropertyInfo property = type.GetProperty("MessageInput");
			if (property == null)
			{
				return null;
			}
			object? value = property.GetValue(staticPropertyOrField);
			return (TMP_InputField)((value is TMP_InputField) ? value : null);
		}

		private bool TryInitialize()
		{
			if (isInitialized)
			{
				return true;
			}
			chatInput = GetChatInput();
			if ((Object)(object)chatInput == (Object)null)
			{
				return false;
			}
			dropdown = ((Component)this).gameObject.AddComponent<TypeaheadDropdown>();
			dropdown.Initialize(chatInput);
			((UnityEvent<string>)(object)chatInput.onValueChanged).AddListener((UnityAction<string>)OnChatInputChanged);
			isInitialized = true;
			return true;
		}

		private void CheckForCommandAPI()
		{
			if (CommandHelper.IsAvailable)
			{
				isWaitingForAPI = false;
			}
		}

		private void OnChatInputChanged(string text)
		{
			if (!isWaitingForAPI)
			{
				if (!text.StartsWith("/"))
				{
					dropdown.Hide();
					return;
				}
				((MonoBehaviour)this).CancelInvoke("UpdateDropdownDelayed");
				((MonoBehaviour)this).Invoke("UpdateDropdownDelayed", 0.15f);
			}
		}

		private void UpdateDropdownDelayed()
		{
			if (!((Object)(object)chatInput == (Object)null))
			{
				string text = chatInput.text;
				if (text.StartsWith("/"))
				{
					dropdown.UpdateSuggestions(text);
				}
			}
		}

		private void HandleKeyboardInput()
		{
			if (Input.GetKeyDown((KeyCode)9) && dropdown.TryAutocomplete())
			{
				EventSystem.current.SetSelectedGameObject(((Component)chatInput).gameObject);
			}
			if (Input.GetKeyDown((KeyCode)273) && dropdown.IsVisible)
			{
				dropdown.SelectPrevious();
				EventSystem.current.SetSelectedGameObject(((Component)chatInput).gameObject);
				chatInput.MoveTextEnd(false);
				return;
			}
			if (Input.GetKeyDown((KeyCode)274) && dropdown.IsVisible)
			{
				dropdown.SelectNext();
				EventSystem.current.SetSelectedGameObject(((Component)chatInput).gameObject);
				chatInput.MoveTextEnd(false);
				return;
			}
			if (Input.GetKeyDown((KeyCode)13) || Input.GetKeyDown((KeyCode)271))
			{
				dropdown.Hide();
			}
			if (Input.GetKeyDown((KeyCode)27))
			{
				dropdown.Hide();
			}
		}
	}
	[BepInPlugin("com.on-together-mods.commandtypeahead", "CommandTypeahead", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		private void Awake()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			Debug.Log((object)"[CommandTypeahead] Plugin loading...");
			GameObject val = new GameObject("CommandTypeaheadManager");
			val.AddComponent<CommandTypeaheadManager>();
			Object.DontDestroyOnLoad((Object)val);
			Debug.Log((object)"[CommandTypeahead] Plugin loaded successfully");
		}
	}
	public static class AccessTools
	{
		public static Type TypeByName(string name)
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			for (int i = 0; i < assemblies.Length; i++)
			{
				Type type = assemblies[i].GetType(name);
				if (type != null)
				{
					return type;
				}
			}
			return null;
		}

		public static MethodInfo Method(Type type, string name)
		{
			return type?.GetMethod(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		}

		public static FieldInfo Field(Type type, string name)
		{
			return type?.GetField(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		}

		public static PropertyInfo Property(Type type, string name)
		{
			return type?.GetProperty(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		}
	}
	public class TypeaheadDropdown : MonoBehaviour
	{
		private class DisplayItem
		{
			public bool IsHeader { get; set; }

			public string HeaderText { get; set; }

			public CommandInfo Command { get; set; }

			public static DisplayItem CreateHeader(string category)
			{
				return new DisplayItem
				{
					IsHeader = true,
					HeaderText = category
				};
			}

			public static DisplayItem CreateCommand(CommandInfo command)
			{
				return new DisplayItem
				{
					IsHeader = false,
					Command = command
				};
			}
		}

		private GameObject dropdownPanel;

		private GameObject contentContainer;

		private List<GameObject> itemPool = new List<GameObject>();

		private List<DisplayItem> displayItems = new List<DisplayItem>();

		private int selectedIndex = -1;

		private string currentInputText = "";

		private TMP_InputField chatInput;

		private RectTransform chatInputRect;

		private const int MAX_VISIBLE_ITEMS = 8;

		private const float ITEM_HEIGHT = 55f;

		private static readonly Color BACKGROUND_COLOR = new Color(0.96f, 0.9f, 0.84f, 1f);

		private static readonly Color BORDER_COLOR = new Color(0.42f, 0.3f, 0.32f, 1f);

		private static readonly Color HIGHLIGHT_COLOR = new Color(0.83f, 0.65f, 0.45f, 0.9f);

		private static readonly Color TEXT_COLOR = new Color(0.29f, 0.22f, 0.16f, 1f);

		private static readonly Color HIGHLIGHTED_TEXT_COLOR = Color.white;

		private static readonly Color DESC_COLOR = new Color(0.5f, 0.42f, 0.35f, 1f);

		private static readonly Color MATCH_HIGHLIGHT = new Color(0.76f, 0.52f, 0.25f, 1f);

		private static readonly Color HEADER_BACKGROUND_COLOR = new Color(0f, 0f, 0f, 0.05f);

		private static readonly Color HEADER_TEXT_COLOR = new Color(0.2f, 0.15f, 0.1f, 0.8f);

		private const float INDENT_WIDTH = 25f;

		private Sprite roundedSprite;

		public bool IsVisible
		{
			get
			{
				GameObject obj = dropdownPanel;
				if (obj == null)
				{
					return false;
				}
				return obj.activeSelf;
			}
		}

		public int SelectedIndex => selectedIndex;

		public void Initialize(TMP_InputField input)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			//IL_00c4: 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_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Expected O, but got Unknown
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Expected O, but got Unknown
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Unknown result type (might be due to invalid IL or missing references)
			//IL_0285: Unknown result type (might be due to invalid IL or missing references)
			chatInput = input;
			chatInputRect = ((Component)input).GetComponent<RectTransform>();
			Image component = ((Component)input).GetComponent<Image>();
			if ((Object)(object)component != (Object)null)
			{
				roundedSprite = component.sprite;
			}
			Canvas componentInParent = ((Component)input).GetComponentInParent<Canvas>();
			Canvas val = ((componentInParent != null) ? componentInParent.rootCanvas : null);
			if (!((Object)(object)val == (Object)null))
			{
				dropdownPanel = new GameObject("TypeaheadDropdown", new Type[1] { typeof(RectTransform) });
				dropdownPanel.transform.SetParent(((Component)val).transform, false);
				Canvas obj = dropdownPanel.AddComponent<Canvas>();
				obj.overrideSorting = true;
				obj.sortingOrder = 30000;
				dropdownPanel.AddComponent<GraphicRaycaster>();
				RectTransform component2 = dropdownPanel.GetComponent<RectTransform>();
				component2.pivot = new Vector2(0f, 0f);
				component2.anchorMin = Vector2.zero;
				component2.anchorMax = Vector2.zero;
				component2.sizeDelta = new Vector2(300f, 440f);
				Image val2 = dropdownPanel.AddComponent<Image>();
				((Graphic)val2).color = BORDER_COLOR;
				if ((Object)(object)roundedSprite != (Object)null)
				{
					val2.sprite = roundedSprite;
					val2.type = (Type)1;
					val2.pixelsPerUnitMultiplier = 4f;
				}
				else
				{
					val2.type = (Type)0;
				}
				GameObject val3 = new GameObject("Background", new Type[1] { typeof(RectTransform) });
				val3.transform.SetParent(dropdownPanel.transform, false);
				RectTransform component3 = val3.GetComponent<RectTransform>();
				component3.anchorMin = Vector2.zero;
				component3.anchorMax = Vector2.one;
				component3.offsetMin = new Vector2(5f, 5f);
				component3.offsetMax = new Vector2(-5f, -5f);
				Image val4 = val3.AddComponent<Image>();
				((Graphic)val4).color = BACKGROUND_COLOR;
				if ((Object)(object)roundedSprite != (Object)null)
				{
					val4.sprite = roundedSprite;
					val4.type = (Type)1;
					val4.pixelsPerUnitMultiplier = 4f;
				}
				else
				{
					val4.type = (Type)0;
				}
				contentContainer = new GameObject("Content", new Type[1] { typeof(RectTransform) });
				contentContainer.transform.SetParent(val3.transform, false);
				RectTransform component4 = contentContainer.GetComponent<RectTransform>();
				component4.anchorMin = Vector2.zero;
				component4.anchorMax = Vector2.one;
				component4.offsetMin = new Vector2(0f, 4f);
				component4.offsetMax = new Vector2(0f, -4f);
				VerticalLayoutGroup obj2 = contentContainer.AddComponent<VerticalLayoutGroup>();
				((HorizontalOrVerticalLayoutGroup)obj2).spacing = 2f;
				((LayoutGroup)obj2).childAlignment = (TextAnchor)0;
				((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = true;
				((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = false;
				((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = true;
				((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = false;
				for (int i = 0; i < 8; i++)
				{
					itemPool.Add(CreateDropdownItem());
				}
				dropdownPanel.SetActive(false);
			}
		}

		private void UpdateDropdownPosition()
		{
			//IL_0060: 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: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)chatInputRect == (Object)null) && !((Object)(object)dropdownPanel == (Object)null))
			{
				RectTransform component = dropdownPanel.GetComponent<RectTransform>();
				Vector3[] array = (Vector3[])(object)new Vector3[4];
				chatInputRect.GetWorldCorners(array);
				((Transform)component).position = new Vector3(array[0].x, array[1].y + 4f, 0f);
				float num = Vector3.Distance(array[0], array[3]);
				float x = ((Transform)component).lossyScale.x;
				if (Mathf.Abs(x) > 0.001f)
				{
					float num2 = num / x;
					component.sizeDelta = new Vector2(num2, component.sizeDelta.y);
				}
			}
		}

		private GameObject CreateDropdownItem()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: 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_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: 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_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: 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_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: 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)
			GameObject val = new GameObject("Item", new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(contentContainer.transform, false);
			val.GetComponent<RectTransform>().sizeDelta = new Vector2(0f, 55f);
			GameObject val2 = new GameObject("Highlight", new Type[1] { typeof(RectTransform) });
			val2.transform.SetParent(val.transform, false);
			RectTransform component = val2.GetComponent<RectTransform>();
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			component.offsetMin = new Vector2(2f, 2f);
			component.offsetMax = new Vector2(-2f, -2f);
			Image val3 = val2.AddComponent<Image>();
			((Graphic)val3).color = new Color(0f, 0f, 0f, 0f);
			((Graphic)val3).raycastTarget = false;
			if ((Object)(object)roundedSprite != (Object)null)
			{
				val3.sprite = roundedSprite;
				val3.type = (Type)1;
				val3.pixelsPerUnitMultiplier = 8f;
			}
			else
			{
				val3.type = (Type)0;
			}
			GameObject val4 = new GameObject("Text", new Type[1] { typeof(RectTransform) });
			val4.transform.SetParent(val.transform, false);
			RectTransform component2 = val4.GetComponent<RectTransform>();
			component2.anchorMin = Vector2.zero;
			component2.anchorMax = Vector2.one;
			component2.offsetMin = new Vector2(8f, 2f);
			component2.offsetMax = new Vector2(-6f, -2f);
			TextMeshProUGUI val5 = val4.AddComponent<TextMeshProUGUI>();
			((TMP_Text)val5).fontSize = 20f;
			((Graphic)val5).color = TEXT_COLOR;
			((TMP_Text)val5).alignment = (TextAlignmentOptions)4097;
			((TMP_Text)val5).richText = true;
			TMP_InputField obj = chatInput;
			object font;
			if (obj == null)
			{
				font = null;
			}
			else
			{
				TMP_Text textComponent = obj.textComponent;
				font = ((textComponent != null) ? textComponent.font : null);
			}
			((TMP_Text)val5).font = (TMP_FontAsset)font;
			((Graphic)val5).raycastTarget = false;
			((TMP_Text)val5).textWrappingMode = (TextWrappingModes)1;
			((TMP_Text)val5).overflowMode = (TextOverflowModes)1;
			TypeaheadItem typeaheadItem = val.AddComponent<TypeaheadItem>();
			typeaheadItem.HighlightImage = val3;
			typeaheadItem.HighlightRect = component;
			typeaheadItem.TextMesh = val5;
			typeaheadItem.TextRect = component2;
			val.SetActive(false);
			return val;
		}

		public void Show(List<CommandInfo> matches, string inputText)
		{
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			currentInputText = inputText;
			List<IGrouping<string, CommandInfo>> list = (from c in matches
				group c by c.Category).ToList();
			displayItems.Clear();
			int num = 0;
			foreach (IGrouping<string, CommandInfo> item in list)
			{
				displayItems.Add(DisplayItem.CreateHeader(item.Key));
				foreach (CommandInfo item2 in item)
				{
					if (num >= 8)
					{
						break;
					}
					displayItems.Add(DisplayItem.CreateCommand(item2));
					num++;
				}
				if (num >= 8)
				{
					break;
				}
			}
			selectedIndex = FindNextSelectableIndex(-1);
			RectTransform component = dropdownPanel.GetComponent<RectTransform>();
			float num2 = (float)Mathf.Min(displayItems.Count, 8 + list.Count) * 55f + 30f;
			component.sizeDelta = new Vector2(component.sizeDelta.x, num2);
			UpdateDropdownPosition();
			for (int i = 0; i < itemPool.Count; i++)
			{
				if (i < displayItems.Count)
				{
					itemPool[i].SetActive(true);
					UpdateItemVisuals(itemPool[i], displayItems[i], inputText, i == selectedIndex);
				}
				else
				{
					itemPool[i].SetActive(false);
				}
			}
			dropdownPanel.SetActive(true);
		}

		private int FindNextSelectableIndex(int startIndex)
		{
			for (int i = startIndex + 1; i < displayItems.Count; i++)
			{
				if (!displayItems[i].IsHeader)
				{
					return i;
				}
			}
			return -1;
		}

		private int FindPreviousSelectableIndex(int startIndex)
		{
			for (int num = startIndex - 1; num >= 0; num--)
			{
				if (!displayItems[num].IsHeader)
				{
					return num;
				}
			}
			return -1;
		}

		public void UpdateSuggestions(string text)
		{
			if (string.IsNullOrEmpty(text) || !text.StartsWith("/"))
			{
				Hide();
				return;
			}
			List<CommandInfo> list = CommandHelper.FindMatches(text.Substring(1));
			if (list.Count > 0)
			{
				Show(list, text);
			}
			else
			{
				Hide();
			}
		}

		public bool TryAutocomplete()
		{
			CommandInfo selectedCommand = GetSelectedCommand();
			if (selectedCommand != null && (Object)(object)chatInput != (Object)null)
			{
				chatInput.text = "/" + selectedCommand.Name + " ";
				chatInput.caretPosition = chatInput.text.Length;
				Hide();
				return true;
			}
			return false;
		}

		public void SelectPrevious()
		{
			NavigateUp();
		}

		public void SelectNext()
		{
			NavigateDown();
		}

		private void UpdateItemVisuals(GameObject item, DisplayItem displayItem, string inputText, bool isSelected)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: 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_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			TypeaheadItem component = item.GetComponent<TypeaheadItem>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			bool isHeader = displayItem.IsHeader;
			float num = (isHeader ? 8f : 33f);
			if ((Object)(object)component.TextRect != (Object)null)
			{
				component.TextRect.offsetMin = new Vector2(num, 2f);
			}
			if ((Object)(object)component.HighlightRect != (Object)null)
			{
				component.HighlightRect.offsetMin = new Vector2(isHeader ? 2f : 27f, 2f);
			}
			if ((Object)(object)component.HighlightImage != (Object)null)
			{
				if (isHeader)
				{
					((Graphic)component.HighlightImage).color = HEADER_BACKGROUND_COLOR;
				}
				else
				{
					((Graphic)component.HighlightImage).color = (Color)(isSelected ? HIGHLIGHT_COLOR : new Color(0f, 0f, 0f, 0f));
				}
			}
			if ((Object)(object)component.TextMesh != (Object)null)
			{
				if (isHeader)
				{
					((TMP_Text)component.TextMesh).text = "<b><color=#" + ColorUtility.ToHtmlStringRGB(HEADER_TEXT_COLOR) + ">" + displayItem.HeaderText.ToUpper() + ":</color></b>";
					((TMP_Text)component.TextMesh).fontSize = 24f;
					((Graphic)component.TextMesh).color = HEADER_TEXT_COLOR;
				}
				else
				{
					string text = HighlightMatch(displayItem.Command.Name, inputText, isSelected);
					string text2 = "<color=#" + ColorUtility.ToHtmlStringRGB(DESC_COLOR) + ">" + displayItem.Command.Description + "</color>";
					((TMP_Text)component.TextMesh).text = "<b>" + text + "</b>  " + text2;
					((TMP_Text)component.TextMesh).fontSize = 20f;
					((Graphic)component.TextMesh).color = (isSelected ? HIGHLIGHTED_TEXT_COLOR : TEXT_COLOR);
				}
			}
		}

		private string HighlightMatch(string text, string input, bool isSelected)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(input) || input.Length <= 1)
			{
				if (!isSelected)
				{
					return "<color=#" + ColorUtility.ToHtmlStringRGB(MATCH_HIGHLIGHT) + ">" + text + "</color>";
				}
				return text;
			}
			int num = Mathf.Min(input.Length - 1, text.Length);
			if (num > 0 && text.Substring(0, num).Equals(input.Substring(1, num), StringComparison.OrdinalIgnoreCase))
			{
				string text2 = text.Substring(0, num);
				string text3 = text.Substring(num);
				if (isSelected)
				{
					return text;
				}
				return "<color=#" + ColorUtility.ToHtmlStringRGB(MATCH_HIGHLIGHT) + ">" + text2 + "</color>" + text3;
			}
			return text;
		}

		public void Hide()
		{
			GameObject obj = dropdownPanel;
			if (obj != null)
			{
				obj.SetActive(false);
			}
			selectedIndex = -1;
			displayItems.Clear();
		}

		public bool NavigateUp()
		{
			if (displayItems.Count == 0)
			{
				return false;
			}
			int num = FindPreviousSelectableIndex(selectedIndex);
			if (num < 0)
			{
				num = FindPreviousSelectableIndex(displayItems.Count);
			}
			if (num >= 0)
			{
				selectedIndex = num;
				RefreshSelection();
				return true;
			}
			return false;
		}

		public bool NavigateDown()
		{
			if (displayItems.Count == 0)
			{
				return false;
			}
			int num = FindNextSelectableIndex(selectedIndex);
			if (num < 0)
			{
				num = FindNextSelectableIndex(-1);
			}
			if (num >= 0)
			{
				selectedIndex = num;
				RefreshSelection();
				return true;
			}
			return false;
		}

		private void RefreshSelection()
		{
			for (int i = 0; i < displayItems.Count; i++)
			{
				UpdateItemVisuals(itemPool[i], displayItems[i], currentInputText, i == selectedIndex);
			}
		}

		public CommandInfo GetSelectedCommand()
		{
			if (selectedIndex >= 0 && selectedIndex < displayItems.Count && !displayItems[selectedIndex].IsHeader)
			{
				return displayItems[selectedIndex].Command;
			}
			return null;
		}

		public void OnDestroy()
		{
			if ((Object)(object)dropdownPanel != (Object)null)
			{
				Object.Destroy((Object)(object)dropdownPanel);
			}
		}
	}
	public class TypeaheadItem : MonoBehaviour
	{
		public Image HighlightImage { get; set; }

		public RectTransform HighlightRect { get; set; }

		public TextMeshProUGUI TextMesh { get; set; }

		public RectTransform TextRect { get; set; }
	}
}