Decompiled source of PingSystem v1.2.0

plugins/PingSystem.dll

Decompiled 14 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Shared;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Networking;
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("PingSystem")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+d0b18f487bc4ec855fd3a19ba360d2e089f76d81")]
[assembly: AssemblyProduct("PingSystem")]
[assembly: AssemblyTitle("PingSystem")]
[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 Shared
{
	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 static class FuzzyMatcher
	{
		public static float CalculateScore(string target, string query)
		{
			if (string.IsNullOrEmpty(query))
			{
				return 0f;
			}
			if (string.IsNullOrEmpty(target))
			{
				return 0f;
			}
			string text = target.ToLowerInvariant();
			string text2 = query.ToLowerInvariant();
			if (text.StartsWith(text2))
			{
				return 2f;
			}
			if (IsAcronymMatch(text, text2))
			{
				return 1.5f;
			}
			if (text.Contains(text2))
			{
				return 0.5f;
			}
			return 0f;
		}

		private static bool IsAcronymMatch(string target, string query)
		{
			if (query.Length == 0)
			{
				return false;
			}
			if (target.Length == 0)
			{
				return false;
			}
			if (target[0] != query[0])
			{
				return false;
			}
			int i = 0;
			int num = 0;
			for (; i < target.Length; i++)
			{
				if (num >= query.Length)
				{
					break;
				}
				if (target[i] == query[num])
				{
					num++;
				}
			}
			return num == query.Length;
		}

		public static IEnumerable<T> Filter<T>(IEnumerable<T> items, Func<T, string> selector, string query)
		{
			if (string.IsNullOrEmpty(query))
			{
				return items;
			}
			return from item in items
				select new
				{
					Item = item,
					Score = CalculateScore(selector(item), query)
				} into x
				where x.Score > 0f
				orderby x.Score descending, selector(x.Item)
				select x.Item;
		}
	}
}
namespace PingSystem
{
	public static class CommandHelper
	{
		public static void Register(string name, string category, Action<string[]> handler, string desc)
		{
			try
			{
				Type type = Type.GetType("CommandAPI.CommandRegistry, CommandAPI");
				if (type == null)
				{
					return;
				}
				Type type2 = Type.GetType("CommandAPI.Parameter, CommandAPI");
				Type type3 = Type.GetType("CommandAPI.ParameterType, CommandAPI");
				if (type2 == null || type3 == null)
				{
					return;
				}
				ConstructorInfo constructorInfo = type2.GetConstructors()[0];
				ParameterInfo[] parameters = constructorInfo.GetParameters();
				object[] array = new object[parameters.Length];
				array[0] = "args";
				array[1] = Enum.Parse(type3, "String");
				for (int i = 2; i < parameters.Length; i++)
				{
					if (parameters[i].ParameterType == typeof(bool) && i == 2)
					{
						array[i] = false;
					}
					else if (parameters[i].HasDefaultValue)
					{
						array[i] = parameters[i].DefaultValue;
					}
					else
					{
						array[i] = null;
					}
				}
				object value = constructorInfo.Invoke(array);
				Array array2 = Array.CreateInstance(type2, 1);
				array2.SetValue(value, 0);
				type.GetMethod("Register", new Type[5]
				{
					typeof(string),
					typeof(string),
					typeof(Action<string[]>),
					typeof(string),
					array2.GetType()
				})?.Invoke(null, new object[5] { name, category, handler, desc, array2 });
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[PingSystem] Failed to register /" + name + ": " + ex.Message));
			}
		}

		public static void Notify(string message)
		{
			try
			{
				Type type = Type.GetType("CommandAPI.Utilities, CommandAPI");
				if (!(type == null))
				{
					type.GetMethod("Notify", new Type[1] { typeof(string) })?.Invoke(null, new object[1] { message });
				}
			}
			catch
			{
			}
		}
	}
	public class MentionDropdown : MonoBehaviour
	{
		private GameObject dropdownPanel;

		private GameObject contentContainer;

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

		private List<string> currentMatches = new List<string>();

		private int selectedIndex = -1;

		private TMP_InputField chatInput;

		private RectTransform chatInputRect;

		private const int MAX_VISIBLE_ITEMS = 8;

		private const float MAX_DROPDOWN_HEIGHT = 600f;

		private const float ITEM_HEIGHT = 55f;

		private const float DROPDOWN_GAP = 20f;

		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 MENTION_COLOR = new Color(1f, 0.84f, 0f, 1f);

		private Sprite roundedSprite;

		private ScrollRect scrollRect;

		private float _nextScrollTime;

		private const float SCROLL_REPEAT_DELAY = 0.4f;

		private const float SCROLL_REPEAT_RATE = 0.08f;

		private bool _isScrolling;

		private KeyCode _scrollDirection;

		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_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Expected O, but got Unknown
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: 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_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Expected O, but got Unknown
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: 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_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d0: Expected O, but got Unknown
			//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0311: Unknown result type (might be due to invalid IL or missing references)
			//IL_0327: Unknown result type (might be due to invalid IL or missing references)
			//IL_033d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0375: Unknown result type (might be due to invalid IL or missing references)
			//IL_037f: Expected O, but got Unknown
			//IL_03b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03dc: 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_045b: Expected O, but got Unknown
			//IL_0481: Unknown result type (might be due to invalid IL or missing references)
			//IL_0496: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0519: Unknown result type (might be due to invalid IL or missing references)
			//IL_051e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0531: Unknown result type (might be due to invalid IL or missing references)
			//IL_0538: Unknown result type (might be due to invalid IL or missing references)
			//IL_0543: Unknown result type (might be due to invalid IL or missing references)
			//IL_0558: Unknown result type (might be due to invalid IL or missing references)
			//IL_056c: Unknown result type (might be due to invalid IL or missing references)
			//IL_058f: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c9: Expected O, but got Unknown
			//IL_05e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0605: Unknown result type (might be due to invalid IL or missing references)
			//IL_0619: Unknown result type (might be due to invalid IL or missing references)
			//IL_063b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0640: Unknown result type (might be due to invalid IL or missing references)
			//IL_0653: Unknown result type (might be due to invalid IL or missing references)
			//IL_065d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0684: 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("MentionDropdown", new Type[1] { typeof(RectTransform) });
				dropdownPanel.transform.SetParent(((Component)val).transform, false);
				Canvas obj = dropdownPanel.AddComponent<Canvas>();
				obj.overrideSorting = true;
				obj.sortingOrder = 30001;
				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, 600f);
				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;
				}
				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;
				}
				GameObject val5 = new GameObject("ScrollView", new Type[1] { typeof(RectTransform) });
				val5.transform.SetParent(val3.transform, false);
				RectTransform component4 = val5.GetComponent<RectTransform>();
				component4.anchorMin = Vector2.zero;
				component4.anchorMax = Vector2.one;
				component4.offsetMin = new Vector2(5f, 5f);
				component4.offsetMax = new Vector2(-5f, -5f);
				scrollRect = val5.AddComponent<ScrollRect>();
				scrollRect.horizontal = false;
				scrollRect.vertical = true;
				scrollRect.scrollSensitivity = 20f;
				scrollRect.movementType = (MovementType)2;
				GameObject val6 = new GameObject("Viewport", new Type[1] { typeof(RectTransform) });
				val6.transform.SetParent(val5.transform, false);
				RectTransform component5 = val6.GetComponent<RectTransform>();
				component5.anchorMin = Vector2.zero;
				component5.anchorMax = Vector2.one;
				component5.pivot = new Vector2(0f, 1f);
				component5.offsetMin = new Vector2(0f, 5f);
				component5.offsetMax = new Vector2(-6f, -5f);
				val6.AddComponent<RectMask2D>();
				scrollRect.viewport = component5;
				contentContainer = new GameObject("Content", new Type[1] { typeof(RectTransform) });
				contentContainer.transform.SetParent(val6.transform, false);
				RectTransform component6 = contentContainer.GetComponent<RectTransform>();
				component6.anchorMin = new Vector2(0f, 1f);
				component6.anchorMax = new Vector2(1f, 1f);
				component6.pivot = new Vector2(0f, 1f);
				VerticalLayoutGroup obj2 = contentContainer.AddComponent<VerticalLayoutGroup>();
				((HorizontalOrVerticalLayoutGroup)obj2).spacing = 2f;
				((LayoutGroup)obj2).childAlignment = (TextAnchor)0;
				((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = true;
				((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = true;
				((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = true;
				((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = false;
				contentContainer.AddComponent<ContentSizeFitter>().verticalFit = (FitMode)2;
				scrollRect.content = component6;
				GameObject val7 = new GameObject("Scrollbar Vertical", new Type[1] { typeof(RectTransform) });
				val7.transform.SetParent(val5.transform, false);
				RectTransform component7 = val7.GetComponent<RectTransform>();
				component7.anchorMin = new Vector2(1f, 0f);
				component7.anchorMax = new Vector2(1f, 1f);
				component7.pivot = new Vector2(1f, 1f);
				component7.sizeDelta = new Vector2(5f, 0f);
				Image val8 = val7.AddComponent<Image>();
				((Graphic)val8).color = Color.black;
				if ((Object)(object)roundedSprite != (Object)null)
				{
					val8.sprite = roundedSprite;
					val8.type = (Type)1;
				}
				GameObject val9 = new GameObject("Track", new Type[1] { typeof(RectTransform) });
				val9.transform.SetParent(val7.transform, false);
				RectTransform component8 = val9.GetComponent<RectTransform>();
				component8.anchorMin = Vector2.zero;
				component8.anchorMax = Vector2.one;
				component8.offsetMin = new Vector2(1f, 1f);
				component8.offsetMax = new Vector2(-1f, -1f);
				((Graphic)val9.AddComponent<Image>()).color = new Color(0.3f, 0.22f, 0.2f, 0.3f);
				Scrollbar val10 = val7.AddComponent<Scrollbar>();
				val10.direction = (Direction)2;
				GameObject val11 = new GameObject("Sliding Area", new Type[1] { typeof(RectTransform) });
				val11.transform.SetParent(val7.transform, false);
				RectTransform component9 = val11.GetComponent<RectTransform>();
				component9.anchorMin = Vector2.zero;
				component9.anchorMax = Vector2.one;
				component9.offsetMin = new Vector2(1f, 1f);
				component9.offsetMax = new Vector2(-1f, -1f);
				GameObject val12 = new GameObject("Handle", new Type[1] { typeof(RectTransform) });
				val12.transform.SetParent(val11.transform, false);
				RectTransform component10 = val12.GetComponent<RectTransform>();
				component10.sizeDelta = Vector2.zero;
				Image val13 = val12.AddComponent<Image>();
				((Graphic)val13).color = new Color(1f, 1f, 1f, 0.9f);
				if ((Object)(object)roundedSprite != (Object)null)
				{
					val13.sprite = roundedSprite;
					val13.type = (Type)1;
				}
				val10.handleRect = component10;
				((Selectable)val10).targetGraphic = (Graphic)(object)val13;
				scrollRect.verticalScrollbar = val10;
				scrollRect.verticalScrollbarVisibility = (ScrollbarVisibility)1;
				for (int i = 0; i < 8; i++)
				{
					itemPool.Add(CreateDropdownItem());
				}
				dropdownPanel.SetActive(false);
			}
		}

		private void Update()
		{
			if ((Object)(object)chatInput == (Object)null || !IsVisible || !chatInput.isFocused)
			{
				_isScrolling = false;
				return;
			}
			if (!Input.GetKey((KeyCode)273) && !Input.GetKey((KeyCode)274))
			{
				_isScrolling = false;
			}
			HandleKeyboardInput();
		}

		private void HandleKeyboardInput()
		{
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Invalid comparison between Unknown and I4
			if (Input.GetKeyDown((KeyCode)9))
			{
				int caretPosition = chatInput.caretPosition;
				string text = chatInput.text;
				int num = text.LastIndexOf('@', Mathf.Max(0, caretPosition - 1));
				string currentQuery = ((num >= 0) ? text.Substring(num + 1, caretPosition - num - 1) : "");
				if (TryAutocomplete(currentQuery))
				{
					EventSystem.current.SetSelectedGameObject(((Component)chatInput).gameObject);
				}
			}
			else if (Input.GetKeyDown((KeyCode)273))
			{
				_isScrolling = true;
				_scrollDirection = (KeyCode)273;
				_nextScrollTime = Time.realtimeSinceStartup + 0.4f;
				NavigateUp();
				EventSystem.current.SetSelectedGameObject(((Component)chatInput).gameObject);
				chatInput.MoveTextEnd(false);
			}
			else if (Input.GetKeyDown((KeyCode)274))
			{
				_isScrolling = true;
				_scrollDirection = (KeyCode)274;
				_nextScrollTime = Time.realtimeSinceStartup + 0.4f;
				NavigateDown();
				EventSystem.current.SetSelectedGameObject(((Component)chatInput).gameObject);
				chatInput.MoveTextEnd(false);
			}
			else if (_isScrolling && Input.GetKey(_scrollDirection) && Time.realtimeSinceStartup >= _nextScrollTime)
			{
				_nextScrollTime = Time.realtimeSinceStartup + 0.08f;
				if ((int)_scrollDirection == 273)
				{
					NavigateUp();
				}
				else
				{
					NavigateDown();
				}
				EventSystem.current.SetSelectedGameObject(((Component)chatInput).gameObject);
				chatInput.MoveTextEnd(false);
			}
			else
			{
				if (Input.GetKeyDown((KeyCode)13) || Input.GetKeyDown((KeyCode)271))
				{
					Hide();
				}
				if (Input.GetKeyDown((KeyCode)27))
				{
					Hide();
				}
			}
		}

		private void UpdateDropdownPosition()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: 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>();
				component.pivot = new Vector2(0f, 0f);
				component.anchorMin = Vector2.zero;
				component.anchorMax = Vector2.zero;
				Vector3[] array = (Vector3[])(object)new Vector3[4];
				chatInputRect.GetWorldCorners(array);
				float num = array[1].y + 20f;
				((Transform)component).position = new Vector3(array[1].x, num, 0f);
				float num2 = Vector3.Distance(array[0], array[3]);
				float x = ((Transform)component).lossyScale.x;
				if (Mathf.Abs(x) > 0.001f)
				{
					float num3 = num2 / x;
					component.sizeDelta = new Vector2(num3, component.sizeDelta.y);
				}
				ClampToScreen(component);
			}
		}

		private void ClampToScreen(RectTransform dropdownRect)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: 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_0058: Unknown result type (might be due to invalid IL or missing references)
			float y = ((Transform)dropdownRect).lossyScale.y;
			if (!(Mathf.Abs(y) < 0.001f))
			{
				float y2 = ((Transform)dropdownRect).position.y;
				float num = ((float)Screen.height - y2) / y;
				if (dropdownRect.sizeDelta.y > num)
				{
					float num2 = 120f;
					dropdownRect.sizeDelta = new Vector2(dropdownRect.sizeDelta.x, Mathf.Max(num, num2));
				}
			}
		}

		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_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: 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_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: 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_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: 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);
			LayoutElement obj = val.AddComponent<LayoutElement>();
			obj.minHeight = 55f;
			obj.flexibleHeight = 0f;
			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;
			}
			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).margin = new Vector4(4f, 0f, 4f, 0f);
			((TMP_Text)val5).richText = true;
			TMP_InputField obj2 = chatInput;
			object obj3;
			if (obj2 == null)
			{
				obj3 = null;
			}
			else
			{
				TMP_Text textComponent = obj2.textComponent;
				obj3 = ((textComponent != null) ? textComponent.font : null);
			}
			if ((Object)obj3 != (Object)null)
			{
				((TMP_Text)val5).font = chatInput.textComponent.font;
			}
			((Graphic)val5).raycastTarget = false;
			((TMP_Text)val5).enableWordWrapping = false;
			((TMP_Text)val5).overflowMode = (TextOverflowModes)1;
			MentionItem mentionItem = val.AddComponent<MentionItem>();
			mentionItem.HighlightImage = val3;
			mentionItem.TextMesh = val5;
			val.SetActive(false);
			return val;
		}

		public void Show(List<string> matches, string currentQuery)
		{
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			currentMatches = matches;
			selectedIndex = ((currentMatches.Count <= 0) ? (-1) : 0);
			while (itemPool.Count < currentMatches.Count)
			{
				itemPool.Add(CreateDropdownItem());
			}
			TMP_InputField obj = chatInput;
			object obj2;
			if (obj == null)
			{
				obj2 = null;
			}
			else
			{
				TMP_Text textComponent = obj.textComponent;
				obj2 = ((textComponent != null) ? textComponent.font : null);
			}
			TMP_FontAsset val = (TMP_FontAsset)obj2;
			if ((Object)(object)val != (Object)null)
			{
				foreach (GameObject item in itemPool)
				{
					TextMeshProUGUI val2 = item.GetComponent<MentionItem>()?.TextMesh;
					if ((Object)(object)val2 != (Object)null && (Object)(object)((TMP_Text)val2).font != (Object)(object)val)
					{
						((TMP_Text)val2).font = val;
					}
				}
			}
			for (int i = 0; i < itemPool.Count; i++)
			{
				if (i < currentMatches.Count)
				{
					itemPool[i].SetActive(true);
					UpdateItemVisuals(itemPool[i], currentMatches[i], currentQuery, i == selectedIndex);
				}
				else
				{
					itemPool[i].SetActive(false);
				}
			}
			int count = currentMatches.Count;
			float num = 2f;
			float num2 = 8f;
			float num3 = (float)count * 55f + (float)((count > 1) ? (count - 1) : 0) * num + num2;
			RectTransform component = dropdownPanel.GetComponent<RectTransform>();
			component.sizeDelta = new Vector2(component.sizeDelta.x, Mathf.Min(num3 + 10f, 600f));
			UpdateDropdownPosition();
			if ((Object)(object)scrollRect != (Object)null)
			{
				scrollRect.verticalNormalizedPosition = 1f;
			}
			dropdownPanel.SetActive(true);
		}

		public bool TryAutocomplete(string currentQuery)
		{
			string selectedPlayer = GetSelectedPlayer();
			if (selectedPlayer != null && (Object)(object)chatInput != (Object)null)
			{
				int caretPosition = chatInput.caretPosition;
				string text = chatInput.text;
				int num = text.LastIndexOf('@', Mathf.Max(0, caretPosition - 1));
				if (num >= 0)
				{
					string text2 = text.Substring(0, num);
					string text3 = text.Substring(caretPosition);
					string text4 = "@" + selectedPlayer + " ";
					chatInput.text = text2 + text4 + text3;
					chatInput.caretPosition = text2.Length + text4.Length;
					Hide();
					return true;
				}
			}
			return false;
		}

		public void SelectPrevious()
		{
			NavigateUp();
		}

		public void SelectNext()
		{
			NavigateDown();
		}

		private void UpdateItemVisuals(GameObject item, string playerName, string query, bool isSelected)
		{
			//IL_0040: 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)
			MentionItem component = item.GetComponent<MentionItem>();
			if ((Object)(object)component?.HighlightImage != (Object)null)
			{
				((Graphic)component.HighlightImage).color = (Color)(isSelected ? HIGHLIGHT_COLOR : new Color(0f, 0f, 0f, 0f));
			}
			if ((Object)(object)component?.TextMesh != (Object)null)
			{
				((TMP_Text)component.TextMesh).text = HighlightMatch(playerName, query);
			}
		}

		private string HighlightMatch(string text, string query)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(query))
			{
				return text;
			}
			if (text.StartsWith(query, StringComparison.OrdinalIgnoreCase))
			{
				string text2 = text.Substring(0, query.Length);
				string text3 = text.Substring(query.Length);
				return "<color=#" + ColorUtility.ToHtmlStringRGB(MENTION_COLOR) + ">" + text2 + "</color>" + text3;
			}
			return text;
		}

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

		public bool NavigateUp()
		{
			if (currentMatches.Count == 0)
			{
				return false;
			}
			selectedIndex = (selectedIndex - 1 + currentMatches.Count) % currentMatches.Count;
			RefreshSelection();
			ScrollToSelected();
			return true;
		}

		public bool NavigateDown()
		{
			if (currentMatches.Count == 0)
			{
				return false;
			}
			selectedIndex = (selectedIndex + 1) % currentMatches.Count;
			RefreshSelection();
			ScrollToSelected();
			return true;
		}

		private void RefreshSelection()
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < currentMatches.Count; i++)
			{
				MentionItem component = itemPool[i].GetComponent<MentionItem>();
				if (!((Object)(object)component?.HighlightImage == (Object)null))
				{
					((Graphic)component.HighlightImage).color = (Color)((i == selectedIndex) ? HIGHLIGHT_COLOR : new Color(0f, 0f, 0f, 0f));
				}
			}
		}

		private void ScrollToSelected()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)scrollRect == (Object)null || currentMatches.Count == 0)
			{
				return;
			}
			Canvas.ForceUpdateCanvases();
			Rect rect = contentContainer.GetComponent<RectTransform>().rect;
			float height = ((Rect)(ref rect)).height;
			rect = scrollRect.viewport.rect;
			float height2 = ((Rect)(ref rect)).height;
			if (height <= height2)
			{
				return;
			}
			float num = height - height2;
			if (!(num <= 0.001f))
			{
				float num2 = (float)selectedIndex * 55f;
				float num3 = num2 + 55f;
				float num4 = (1f - scrollRect.verticalNormalizedPosition) * num;
				if (num2 < num4)
				{
					scrollRect.verticalNormalizedPosition = 1f - num2 / num;
				}
				else if (num3 > num4 + height2)
				{
					scrollRect.verticalNormalizedPosition = 1f - (num3 - height2) / num;
				}
			}
		}

		public string GetSelectedPlayer()
		{
			if (selectedIndex >= 0 && selectedIndex < currentMatches.Count)
			{
				return currentMatches[selectedIndex];
			}
			return null;
		}

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

		public TextMeshProUGUI TextMesh { get; set; }
	}
	public static class MentionHighlighter
	{
		public static string LocalPlayerName = "";

		public static string MentionColor = "#FFD700";

		public static string PingHighlightColor = "#9B59B6";

		private static readonly Regex RichTextTagRegex = new Regex("<[^>]+>", RegexOptions.Compiled);

		public static string GetLocalPlayerName()
		{
			if (!string.IsNullOrEmpty(LocalPlayerName))
			{
				return LocalPlayerName;
			}
			TextChannelManager i = NetworkSingleton<TextChannelManager>.I;
			if ((Object)(object)i != (Object)null && !string.IsNullOrEmpty(i.UserName))
			{
				LocalPlayerName = RichTextTagRegex.Replace(i.UserName, "").Trim();
				return LocalPlayerName;
			}
			DataManager i2 = MonoSingleton<DataManager>.I;
			if ((Object)(object)i2 != (Object)null && i2.PlayerData != null && !string.IsNullOrEmpty(i2.PlayerData.Name))
			{
				LocalPlayerName = RichTextTagRegex.Replace(i2.PlayerData.Name, "").Trim().Trim('\0');
				return LocalPlayerName;
			}
			return "";
		}

		public static void Initialize(Harmony harmony)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			harmony.Patch((MethodBase)AccessTools.Method(typeof(TextChannelManager), "AddMessageUI", (Type[])null, (Type[])null), new HarmonyMethod(typeof(MentionHighlighter), "AddMessageUI_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static void AddMessageUI_Prefix(ref string text, ref string userName, bool isLocal, int senderIndex)
		{
			if (string.IsNullOrEmpty(text) || text.StartsWith("/") || senderIndex < 0)
			{
				return;
			}
			if (!string.IsNullOrEmpty(userName))
			{
				string localPlayerName = GetLocalPlayerName();
				if (!string.IsNullOrEmpty(localPlayerName) && userName.Equals(localPlayerName, StringComparison.OrdinalIgnoreCase))
				{
					LocalPlayerName = userName;
				}
			}
			string localPlayerName2 = GetLocalPlayerName();
			string cleanMyName = (string.IsNullOrEmpty(localPlayerName2) ? "" : RichTextTagRegex.Replace(localPlayerName2, "").Trim());
			bool shouldPing = false;
			List<string> validNames = PlayerListProvider.GetAllPlayers()?.Where((string p) => !string.IsNullOrEmpty(p)).ToList() ?? new List<string>();
			Regex regex = new Regex("@(\\S+)", RegexOptions.IgnoreCase);
			text = regex.Replace(text, delegate(Match match)
			{
				string value = match.Groups[1].Value;
				foreach (string item in validNames)
				{
					string text2 = RichTextTagRegex.Replace(item, "").Trim();
					if (FuzzyMatcher.CalculateScore(text2, value) > 0f)
					{
						if (!string.IsNullOrEmpty(cleanMyName) && (text2.IndexOf(cleanMyName, StringComparison.OrdinalIgnoreCase) >= 0 || cleanMyName.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0))
						{
							shouldPing = true;
						}
						return "<size=115%><b><color=" + MentionColor + ">@" + value + "</color></b></size>";
					}
				}
				if (!string.IsNullOrEmpty(cleanMyName) && FuzzyMatcher.CalculateScore(cleanMyName, value) > 0f)
				{
					shouldPing = true;
					return "<size=115%><b><color=" + MentionColor + ">@" + value + "</color></b></size>";
				}
				return match.Value;
			});
			if (shouldPing)
			{
				text = "<mark=" + PingHighlightColor + "30>" + text + "</mark>";
				userName = "<b><color=" + MentionColor + ">" + userName + "</color></b>";
				MentionManager.Instance?.PlayPing();
			}
		}
	}
	public class MentionManager : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <InitializeWhenReady>d__17 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public MentionManager <>4__this;

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

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

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

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

			private bool MoveNext()
			{
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0038: Expected O, but got Unknown
				//IL_004e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0058: Expected O, but got Unknown
				//IL_007f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0089: Expected O, but got Unknown
				int num = <>1__state;
				MentionManager mentionManager = <>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;
					<>2__current = (object)new WaitForSeconds(0.5f);
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					break;
				case 3:
					<>1__state = -1;
					break;
				}
				while (!mentionManager.isInitialized)
				{
					mentionManager.TryInitialize();
					if (!mentionManager.isInitialized)
					{
						<>2__current = (object)new WaitForSeconds(1f);
						<>1__state = 3;
						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();
			}
		}

		[CompilerGenerated]
		private sealed class <LoadPingSound>d__14 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public MentionManager <>4__this;

			private UnityWebRequest <uwr>5__2;

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

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

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

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || num == 1)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<uwr>5__2 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0068: Unknown result type (might be due to invalid IL or missing references)
				//IL_009d: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a3: Invalid comparison between Unknown and I4
				//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b1: Invalid comparison between Unknown and I4
				try
				{
					int num = <>1__state;
					MentionManager mentionManager = <>4__this;
					switch (num)
					{
					default:
						return false;
					case 0:
					{
						<>1__state = -1;
						string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "ping.mp3");
						<uwr>5__2 = UnityWebRequestMultimedia.GetAudioClip("file://" + text, (AudioType)13);
						<>1__state = -3;
						((DownloadHandlerAudioClip)<uwr>5__2.downloadHandler).streamAudio = false;
						<>2__current = <uwr>5__2.SendWebRequest();
						<>1__state = 1;
						return true;
					}
					case 1:
						<>1__state = -3;
						if ((int)<uwr>5__2.result == 2 || (int)<uwr>5__2.result == 3)
						{
							Debug.LogError((object)("[PingSystem] Failed to load ping.mp3: " + <uwr>5__2.error));
						}
						else
						{
							mentionManager._pingClip = DownloadHandlerAudioClip.GetContent(<uwr>5__2);
						}
						<>m__Finally1();
						<uwr>5__2 = null;
						return false;
					}
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

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

			private void <>m__Finally1()
			{
				<>1__state = -1;
				if (<uwr>5__2 != null)
				{
					((IDisposable)<uwr>5__2).Dispose();
				}
			}

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

		private TMP_InputField chatInput;

		private MentionDropdown dropdown;

		private bool isInitialized;

		private string currentQuery = "";

		private AudioSource _audioSource;

		private AudioClip _pingClip;

		private float _nextScrollTime;

		private const float SCROLL_REPEAT_DELAY = 0.4f;

		private const float SCROLL_REPEAT_RATE = 0.08f;

		private bool _isScrolling;

		public static MentionManager Instance { get; private set; }

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
				SceneManager.sceneLoaded += OnSceneLoaded;
				SceneManager.sceneUnloaded += OnSceneUnloaded;
				_audioSource = ((Component)this).gameObject.AddComponent<AudioSource>();
				_audioSource.playOnAwake = false;
				_audioSource.spatialBlend = 0f;
				((MonoBehaviour)this).StartCoroutine(LoadPingSound());
			}
			else
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
			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();
			}
		}

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

		public void PlayPing()
		{
			if ((Object)(object)_pingClip != (Object)null && (Object)(object)_audioSource != (Object)null)
			{
				_audioSource.PlayOneShot(_pingClip);
			}
		}

		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;
			currentQuery = "";
		}

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

		private void Update()
		{
			if (isInitialized && !((Object)(object)chatInput == (Object)null) && !((Object)(object)dropdown == (Object)null) && chatInput.isFocused && dropdown.IsVisible)
			{
				HandleKeyboardInput();
			}
		}

		private TMP_InputField GetChatInput()
		{
			Type type = AccessTools.TypeByName("MonoSingleton`1");
			if (type == null)
			{
				return null;
			}
			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 null;
			}
			object value = property.GetValue(null);
			if (value == null)
			{
				return null;
			}
			object? obj = type2.GetProperty("MessageInput")?.GetValue(value);
			return (TMP_InputField)((obj is TMP_InputField) ? obj : null);
		}

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

		private void OnChatInputChanged(string text)
		{
			if ((Object)(object)chatInput == (Object)null)
			{
				return;
			}
			int caretPosition = chatInput.caretPosition;
			if (caretPosition <= 0 || caretPosition > text.Length)
			{
				dropdown.Hide();
				return;
			}
			int num = text.LastIndexOf('@', caretPosition - 1);
			if (num == -1)
			{
				dropdown.Hide();
				return;
			}
			if (num > 0 && !char.IsWhiteSpace(text[num - 1]))
			{
				dropdown.Hide();
				return;
			}
			currentQuery = text.Substring(num + 1, caretPosition - num - 1);
			UpdateDropdown(currentQuery);
		}

		private void UpdateDropdown(string query)
		{
			List<string> list = FuzzyMatcher.Filter(PlayerListProvider.GetAllPlayers(), (string p) => p, query).ToList();
			if (list.Count > 0)
			{
				dropdown.Show(list, query);
			}
			else
			{
				dropdown.Hide();
			}
		}

		private void HandleKeyboardInput()
		{
			if (Input.GetKeyDown((KeyCode)9))
			{
				if (dropdown.TryAutocomplete(currentQuery))
				{
					EventSystem.current.SetSelectedGameObject(((Component)chatInput).gameObject);
				}
			}
			else if (Input.GetKey((KeyCode)273) && dropdown.IsVisible)
			{
				if (Input.GetKeyDown((KeyCode)273))
				{
					_isScrolling = true;
					_nextScrollTime = Time.realtimeSinceStartup + 0.4f;
					NavigateUp();
				}
				else if (_isScrolling && Time.realtimeSinceStartup >= _nextScrollTime)
				{
					_nextScrollTime = Time.realtimeSinceStartup + 0.08f;
					NavigateUp();
				}
			}
			else if (Input.GetKey((KeyCode)274) && dropdown.IsVisible)
			{
				if (Input.GetKeyDown((KeyCode)274))
				{
					_isScrolling = true;
					_nextScrollTime = Time.realtimeSinceStartup + 0.4f;
					NavigateDown();
				}
				else if (_isScrolling && Time.realtimeSinceStartup >= _nextScrollTime)
				{
					_nextScrollTime = Time.realtimeSinceStartup + 0.08f;
					NavigateDown();
				}
			}
			else if (!Input.GetKey((KeyCode)273) && !Input.GetKey((KeyCode)274))
			{
				_isScrolling = false;
			}
			if (Input.GetKeyDown((KeyCode)13) || Input.GetKeyDown((KeyCode)271))
			{
				if (dropdown.IsVisible)
				{
					dropdown.TryAutocomplete(currentQuery);
					dropdown.Hide();
				}
			}
			else if (Input.GetKeyDown((KeyCode)27))
			{
				dropdown.Hide();
			}
		}

		private void NavigateUp()
		{
			dropdown.SelectPrevious();
			EventSystem.current.SetSelectedGameObject(((Component)chatInput).gameObject);
			chatInput.MoveTextEnd(false);
		}

		private void NavigateDown()
		{
			dropdown.SelectNext();
			EventSystem.current.SetSelectedGameObject(((Component)chatInput).gameObject);
			chatInput.MoveTextEnd(false);
		}
	}
	public static class PlayerListProvider
	{
		private static Type _playerPanelControllerType;

		private static Type _networkSingletonBaseType;

		private static Type _playerIdInfoType;

		private static PropertyInfo _singletonInstanceProperty;

		private static FieldInfo _idInfosField;

		private static FieldInfo _playerIdInfoNameField;

		private static readonly Regex RichTextTagRegex = new Regex("<[^>]+>", RegexOptions.Compiled);

		private static bool _initialized;

		private static bool _initFailed;

		public static bool IsInitialized => _initialized;

		public static bool IsInitFailed => _initFailed;

		public static void Initialize()
		{
			if (_initialized)
			{
				return;
			}
			_initFailed = false;
			try
			{
				_playerPanelControllerType = AccessTools.TypeByName("PlayerPanelController");
				if (_playerPanelControllerType == null)
				{
					_initFailed = true;
					return;
				}
				_networkSingletonBaseType = _playerPanelControllerType.BaseType;
				if (_networkSingletonBaseType == null || !_networkSingletonBaseType.Name.StartsWith("NetworkSingleton"))
				{
					_initFailed = true;
					return;
				}
				_singletonInstanceProperty = _networkSingletonBaseType.GetProperty("I", BindingFlags.Static | BindingFlags.Public);
				if (_singletonInstanceProperty == null)
				{
					_initFailed = true;
					return;
				}
				_idInfosField = _playerPanelControllerType.GetField("IDInfos", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (_idInfosField == null)
				{
					_initFailed = true;
					return;
				}
				Type fieldType = _idInfosField.FieldType;
				if (fieldType.IsGenericType)
				{
					Type[] genericArguments = fieldType.GetGenericArguments();
					if (genericArguments.Length != 0)
					{
						_playerIdInfoType = genericArguments[0];
					}
				}
				if ((object)_playerIdInfoType == null)
				{
					_playerIdInfoType = AccessTools.TypeByName("PlayerIDInfo");
				}
				if (_playerIdInfoType == null)
				{
					_initFailed = true;
					return;
				}
				_playerIdInfoNameField = _playerIdInfoType.GetField("Name", BindingFlags.Instance | BindingFlags.Public);
				if (_playerIdInfoNameField == null)
				{
					_initFailed = true;
				}
				else
				{
					_initialized = true;
				}
			}
			catch (Exception)
			{
				_initFailed = true;
				_initialized = false;
			}
		}

		public static List<string> GetAllPlayers()
		{
			if (!_initialized || _initFailed)
			{
				Initialize();
				if (!_initialized)
				{
					return new List<string>();
				}
			}
			List<string> list = new List<string>();
			try
			{
				object value = _singletonInstanceProperty.GetValue(null);
				if (value == null)
				{
					return list;
				}
				object value2 = _idInfosField.GetValue(value);
				if (value2 == null)
				{
					return list;
				}
				if (value2 is ICollection collection && collection.Count == 0)
				{
					return list;
				}
				List<object> list2 = new List<object>();
				try
				{
					if (value2 is IEnumerable enumerable)
					{
						foreach (object item in enumerable)
						{
							if (item != null)
							{
								list2.Add(item);
							}
						}
					}
				}
				catch
				{
				}
				foreach (object item2 in list2)
				{
					try
					{
						object value3 = _playerIdInfoNameField.GetValue(item2);
						string text = null;
						if (value3 is string text2)
						{
							text = text2;
						}
						else if (value3 is byte[] array && array.Length != 0)
						{
							text = Encoding.Unicode.GetString(array).Trim('\0');
						}
						if (!string.IsNullOrEmpty(text))
						{
							text = text.Trim();
							text = RichTextTagRegex.Replace(text, "").Trim();
							if (!string.IsNullOrEmpty(text))
							{
								list.Add(text);
							}
						}
					}
					catch
					{
					}
				}
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("[PingSystem] GetAllPlayers: " + ex.Message));
			}
			return list;
		}

		public static int GetPlayerCount()
		{
			if (!_initialized)
			{
				Initialize();
				if (!_initialized)
				{
					return 0;
				}
			}
			try
			{
				object value = _singletonInstanceProperty.GetValue(null);
				if (value == null)
				{
					return 0;
				}
				return (_idInfosField.GetValue(value) as ICollection)?.Count ?? 0;
			}
			catch
			{
				return 0;
			}
		}
	}
	[BepInPlugin("com.on-together-mods.playerpingmention", "PlayerPingMention", "1.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		private static ConfigEntry<string> _pingColorConfig;

		private static readonly Regex HexColorRegex = new Regex("^#?([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$", RegexOptions.Compiled);

		private void Awake()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			_pingColorConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Ping", "HighlightColorV2", "#9B59B6", "Hex color for pinged message highlights (default: soft purple)");
			MentionHighlighter.PingHighlightColor = _pingColorConfig.Value;
			MentionHighlighter.Initialize(new Harmony("com.on-together-mods.playerpingmention.highlight"));
			GameObject val = new GameObject("MentionManager");
			val.AddComponent<MentionManager>();
			Object.DontDestroyOnLoad((Object)val);
			RegisterCommands();
			((BaseUnityPlugin)this).Logger.LogInfo((object)("PingSystem loaded. Color: " + _pingColorConfig.Value));
		}

		private void RegisterCommands()
		{
			CommandHelper.Register("setpingcolor", "Ping System", delegate(string[] args)
			{
				HandleSetPingColor(args);
			}, "Usage: /setpingcolor <hex-color> e.g. FF0000 or #FF0000");
		}

		private void HandleSetPingColor(string[] args)
		{
			if (args.Length == 0)
			{
				CommandHelper.Notify("Current ping color: " + MentionHighlighter.PingHighlightColor);
				return;
			}
			string text = args[0].Trim();
			if (!HexColorRegex.IsMatch(text))
			{
				CommandHelper.Notify("Invalid hex color. Use format: #RRGGBB or #RGB");
				return;
			}
			string text2 = (text.StartsWith("#") ? text : ("#" + text));
			if (text2.Length == 4)
			{
				text2 = $"#{text2[1]}{text2[1]}{text2[2]}{text2[2]}{text2[3]}{text2[3]}";
			}
			text2 = (MentionHighlighter.PingHighlightColor = text2.ToUpper());
			_pingColorConfig.Value = text2;
			CommandHelper.Notify("Ping color set to <color=" + text2 + ">" + text2 + "</color>");
		}
	}
}