Decompiled source of ChatX v3.1.0

ChatX.dll

Decompiled 2 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mirror;
using Nessie.ATLYSS.EasySettings;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ChatX")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("3.1.0.0")]
[assembly: AssemblyInformationalVersion("3.1.0+4c913a7c0d55f8366ddcb3969839b76de08d1c83")]
[assembly: AssemblyProduct("ChatX")]
[assembly: AssemblyTitle("ChatX")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("3.1.0.0")]
[module: UnverifiableCode]
[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 ChatX
{
	internal sealed class ChatLinkClickHandler : MonoBehaviour, IPointerClickHandler, IEventSystemHandler, IPointerDownHandler, IPointerUpHandler, IInitializePotentialDragHandler, IBeginDragHandler, IDragHandler, IEndDragHandler, IScrollHandler
	{
		private ChatBehaviourAssets _assets;

		private ScrollRect _scrollRect;

		private TextMeshProUGUI _chatText;

		private bool _dragInProgress;

		internal void Bind(ChatBehaviourAssets assets, ScrollRect scrollRect, TextMeshProUGUI chatText)
		{
			_assets = assets;
			_scrollRect = scrollRect;
			_chatText = chatText;
		}

		public void OnPointerClick(PointerEventData eventData)
		{
			//IL_0005: 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)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			if (eventData == null || (int)eventData.button != 0 || _dragInProgress || (Object)(object)_chatText == (Object)null || ChatX.IsChatLinkPromptOpen)
			{
				return;
			}
			Camera val = eventData.pressEventCamera ?? eventData.enterEventCamera;
			int num = TMP_TextUtilities.FindIntersectingLink((TMP_Text)(object)_chatText, Vector2.op_Implicit(eventData.position), val);
			if (num >= 0 && num < ((TMP_Text)_chatText).textInfo.linkCount)
			{
				string linkID = ((TMP_LinkInfo)(ref ((TMP_Text)_chatText).textInfo.linkInfo[num])).GetLinkID();
				if (!string.IsNullOrWhiteSpace(linkID))
				{
					ChatX.ShowChatLinkPrompt(_assets, linkID);
				}
			}
		}

		public void OnPointerDown(PointerEventData eventData)
		{
			_dragInProgress = false;
		}

		public void OnPointerUp(PointerEventData eventData)
		{
			_dragInProgress = false;
		}

		public void OnInitializePotentialDrag(PointerEventData eventData)
		{
			ForwardToScrollRect<IInitializePotentialDragHandler>((BaseEventData)(object)eventData, ExecuteEvents.initializePotentialDrag);
		}

		public void OnBeginDrag(PointerEventData eventData)
		{
			_dragInProgress = true;
			ForwardToScrollRect<IBeginDragHandler>((BaseEventData)(object)eventData, ExecuteEvents.beginDragHandler);
		}

		public void OnDrag(PointerEventData eventData)
		{
			_dragInProgress = true;
			ForwardToScrollRect<IDragHandler>((BaseEventData)(object)eventData, ExecuteEvents.dragHandler);
		}

		public void OnEndDrag(PointerEventData eventData)
		{
			ForwardToScrollRect<IEndDragHandler>((BaseEventData)(object)eventData, ExecuteEvents.endDragHandler);
			_dragInProgress = false;
		}

		public void OnScroll(PointerEventData eventData)
		{
			ForwardToScrollRect<IScrollHandler>((BaseEventData)(object)eventData, ExecuteEvents.scrollHandler);
		}

		private void ForwardToScrollRect<T>(BaseEventData eventData, EventFunction<T> handler) where T : IEventSystemHandler
		{
			if (!((Object)(object)_scrollRect == (Object)null) && eventData != null)
			{
				ExecuteEvents.Execute<T>(((Component)_scrollRect).gameObject, eventData, handler);
			}
		}
	}
	[BepInPlugin("ChatX", "ChatX", "3.1.0")]
	public class ChatX : BaseUnityPlugin
	{
		private enum PromptButtonIconKind
		{
			Confirm,
			Copy,
			Cancel
		}

		private sealed class ProtectedChatLink
		{
			public string Token;

			public string DisplayText;

			public string CanonicalUrl;
		}

		internal sealed class ChatScrollbarState
		{
			public CanvasGroup Scrollbar;

			public GameObject ScrollbarObject;

			public Scrollbar ScrollbarComponent;

			public ScrollRect ScrollRect;

			public GameObject ChatContainer;

			public bool? CachedChatContainerActive;

			public bool? CachedChannelDockActive;
		}

		[HarmonyPatch(typeof(ChatBehaviour), "New_ChatMessage")]
		private static class ChatBehaviour_New_ChatMessage_PrefixAndBlock
		{
			[HarmonyPrefix]
			[HarmonyPriority(800)]
			private static bool Prefix(ref string __0)
			{
				//IL_0087: Unknown result type (might be due to invalid IL or missing references)
				ConfigEntry<bool> blockChat = ChatX.blockChat;
				if (blockChat != null && blockChat.Value)
				{
					return false;
				}
				__0 = ProtectChatLinks(__0, out var protectedLinks);
				string badge = ExtractRenderedOocBadge(ref __0);
				ConfigEntry<bool> asteriskItalic = ChatX.asteriskItalic;
				if (asteriskItalic != null && asteriskItalic.Value)
				{
					__0 = ApplyAsteriskFormatting(__0);
				}
				string prefix = string.Empty;
				ConfigEntry<bool> chatPrefix = ChatX.chatPrefix;
				if (chatPrefix != null && chatPrefix.Value && !LooksPrefixed(__0) && TryExtractChatChannel(__0, out var channel))
				{
					prefix = BuildMessagePrefix(channel);
				}
				string text = CombinePrefixSegments(prefix, badge);
				if (!string.IsNullOrEmpty(text))
				{
					__0 = InsertPrefix(__0, text);
				}
				ApplyMentionEffects(ref __0);
				__0 = RestoreProtectedChatLinks(__0, protectedLinks);
				return true;
			}

			[HarmonyPostfix]
			[HarmonyPriority(0)]
			private static void Postfix(ChatBehaviour __instance)
			{
				if (Object.op_Implicit((Object)(object)__instance))
				{
					EnsureChatLinkUi(__instance._chatAssets);
					ApplyOpacityCap(__instance._chatAssets);
				}
			}
		}

		[HarmonyPatch(typeof(ChatBehaviour), "Init_GameLogicMessage")]
		private static class ChatBehaviour_Init_GameLogicMessage_Block
		{
			[HarmonyPrefix]
			[HarmonyPriority(800)]
			private static bool Prefix()
			{
				ConfigEntry<bool> blockGameFeed = ChatX.blockGameFeed;
				return blockGameFeed == null || !blockGameFeed.Value;
			}
		}

		[HarmonyPatch(typeof(PatternInstanceManager), "On_DungeonKeyChange")]
		private static class PatternInstanceManager_OnDungeonKeyChange_Reroute
		{
			private static readonly MethodInfo NewChatMessage = AccessTools.Method(typeof(ChatBehaviour), "New_ChatMessage", (Type[])null, (Type[])null);

			private static readonly MethodInfo PushGameFeed = AccessTools.Method(typeof(ChatX), "PushGameFeedMessage", (Type[])null, (Type[])null);

			private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
			{
				return ReplaceMethodCalls(instructions, NewChatMessage, PushGameFeed, 2, "PatternInstanceManager.On_DungeonKeyChange reroute");
			}
		}

		[HarmonyPatch(typeof(PlayerQuesting), "Accept_Quest")]
		private static class PlayerQuesting_AcceptQuest_RerouteObjectivePickup
		{
			private static readonly MethodInfo NewChatMessage = AccessTools.Method(typeof(ChatBehaviour), "New_ChatMessage", (Type[])null, (Type[])null);

			private static readonly MethodInfo PushGameFeed = AccessTools.Method(typeof(ChatX), "PushGameFeedMessage", (Type[])null, (Type[])null);

			private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
			{
				return ReplaceMethodCalls(instructions, NewChatMessage, PushGameFeed, 1, "PlayerQuesting.Accept_Quest reroute");
			}
		}

		[HarmonyPatch(typeof(WorldPortalWaypoint), "OnTriggerEnter")]
		private static class WorldPortalWaypoint_OnTriggerEnter_RerouteAttuneChat
		{
			private static readonly MethodInfo NewChatMessage = AccessTools.Method(typeof(ChatBehaviour), "New_ChatMessage", (Type[])null, (Type[])null);

			private static readonly MethodInfo RouteAttune = AccessTools.Method(typeof(ChatX), "RouteWaypointAttuneMessage", (Type[])null, (Type[])null);

			private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
			{
				return ReplaceMethodCalls(instructions, NewChatMessage, RouteAttune, 1, "WorldPortalWaypoint.OnTriggerEnter reroute");
			}
		}

		[HarmonyPatch(typeof(NetTrigger))]
		private static class NetTrigger_OnTriggerStay_RerouteDungeonKeyMessage
		{
			private static readonly MethodInfo TargetReceive = AccessTools.Method(typeof(ChatBehaviour), "Target_RecieveMessage", (Type[])null, (Type[])null);

			private static readonly MethodInfo RouteTarget = AccessTools.Method(typeof(ChatX), "PushTargetedGameFeedMessage", (Type[])null, (Type[])null);

			private static MethodBase TargetMethod()
			{
				return AccessTools.Method(typeof(NetTrigger), "OnTriggerStay", (Type[])null, (Type[])null);
			}

			private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
			{
				return ReplaceMethodCalls(instructions, TargetReceive, RouteTarget, 1, "NetTrigger.OnTriggerStay reroute");
			}
		}

		[HarmonyPatch(typeof(ChatBehaviour), "UserCode_Target_RecieveMessage__String")]
		private static class ChatBehaviour_TargetReceiveMessage_RerouteDungeonKey
		{
			private const string DoorLockedMessage = "The door is locked. It requires a Dungeon Key.";

			private static bool Prefix(ChatBehaviour __instance, string _message)
			{
				if (!ShouldPushGameFeed())
				{
					return true;
				}
				if (!Object.op_Implicit((Object)(object)__instance) || string.IsNullOrEmpty(_message))
				{
					return true;
				}
				if (!string.Equals(_message, "The door is locked. It requires a Dungeon Key.", StringComparison.Ordinal))
				{
					return true;
				}
				PushGameFeedMessage(__instance, _message);
				return false;
			}
		}

		[HarmonyPatch(typeof(ChatBehaviour), "Display_Chat")]
		private static class ChatBehaviourDisplayPatch
		{
			private static void Postfix(ChatBehaviour __instance)
			{
				if (Object.op_Implicit((Object)(object)__instance))
				{
					ApplyOpacityCap(__instance._chatAssets);
				}
			}
		}

		[HarmonyPatch(typeof(ChatBehaviour), "Client_HandleChatboxUpdate")]
		private static class ChatBehaviour_CapOpacity_Postfix
		{
			[HarmonyPostfix]
			private static void Postfix(ChatBehaviour __instance)
			{
				if (Object.op_Implicit((Object)(object)__instance))
				{
					ApplyOpacityCap(__instance._chatAssets);
				}
			}
		}

		[HarmonyPatch(typeof(ChatBehaviour), "Client_HandleChatboxUpdate")]
		private static class ChatBehaviour_HandleChatControls_PreOpen
		{
			[HarmonyPrefix]
			[HarmonyPriority(800)]
			private static void Prefix(ChatBehaviour __instance)
			{
				if (Object.op_Implicit((Object)(object)__instance) && ((NetworkBehaviour)__instance).isLocalPlayer && ChatBehaviour._current == __instance && IsChatSubmitKeyPressed())
				{
					ChatBehaviourAssets chatAssets = __instance._chatAssets;
					bool flag = ChatInputResolver.TryGet(chatAssets)?.IsFocused ?? false;
					CanvasGroup val = (Object.op_Implicit((Object)(object)chatAssets) ? chatAssets._generalCanvasGroup : null);
					bool flag2 = Object.op_Implicit((Object)(object)val) && val.blocksRaycasts && val.interactable;
					bool flag3 = Object.op_Implicit((Object)(object)val) && val.alpha <= 0.001f && !flag2;
					if (!(__instance._focusedInChat || flag) && flag3)
					{
						pendingRestore = true;
						ResetChatFocus();
					}
				}
			}
		}

		[HarmonyPatch(typeof(SettingsManager), "Load_SettingsData")]
		private static class ChatInputLimit_OnLoad
		{
			private static void Postfix()
			{
				ChatInputCharacterLimiter.ApplyCharacterLimit();
				ChatWindowResizer.ApplyAll();
			}
		}

		[HarmonyPatch(typeof(SettingsManager), "Save_SettingsData")]
		private static class ChatInputLimit_OnSave
		{
			private static void Postfix()
			{
				ChatInputCharacterLimiter.ApplyCharacterLimit();
				ChatWindowResizer.ApplyAll();
			}
		}

		[HarmonyPatch(typeof(ChatBehaviourAssets), "Start")]
		private static class ChatInputLimit_OnChatAssetsStart
		{
			private static void Postfix(ChatBehaviourAssets __instance)
			{
				ChatWindowResizer.Register(__instance);
				EnsureChatLinkUi(__instance);
				ChatInputHandle chatInputHandle = ChatInputResolver.TryGet(__instance);
				if (chatInputHandle != null)
				{
					chatInputHandle.CharacterLimit = GetMaxMessageLength();
				}
			}
		}

		[HarmonyPatch(typeof(ChatBehaviour), "OnStartAuthority")]
		private static class ChatBehaviour_OnStartAuthority_Patch
		{
			private static void Postfix(ChatBehaviour __instance)
			{
				((MonoBehaviour)__instance).StartCoroutine(ChatInputCharacterLimiter.ApplyWhenReady(__instance));
			}
		}

		[HarmonyPatch(typeof(InGameUI), "RefreshParams_LocatePlayer")]
		private static class ApplyLimit_AfterPlayerLocated
		{
			private static void Postfix()
			{
				ChatInputCharacterLimiter.ApplyCharacterLimit();
				ChatWindowResizer.ApplyAll();
				EnsureChatLinkUi(ChatBehaviourAssets._current);
			}
		}

		[HarmonyPatch(typeof(ChatBehaviour), "Send_ChatMessage")]
		private static class ChatBehaviour_SendMessage_Ooc
		{
			[HarmonyPrefix]
			[HarmonyPriority(800)]
			private static bool Prefix(ChatBehaviour __instance, ref string __0, out string __state)
			{
				__state = null;
				if (!ShouldInterceptOutgoingChat(__0))
				{
					return true;
				}
				if (TryHandleLocalOocToggle(__instance, __0))
				{
					return false;
				}
				string transformedMessage;
				string errorPrompt;
				switch (PrepareOutgoingChatMessage(__0, out transformedMessage, out errorPrompt))
				{
				case OutgoingChatPreparationStatus.Suppressed:
					FinalizeLocalChatCommand(__instance);
					return false;
				case OutgoingChatPreparationStatus.Invalid:
					ShowOutgoingChatValidationError(__instance, errorPrompt, __0);
					return false;
				case OutgoingChatPreparationStatus.Transformed:
					__state = __0;
					__0 = transformedMessage;
					break;
				}
				return true;
			}

			[HarmonyPostfix]
			private static void Postfix(ChatBehaviour __instance, string __state)
			{
				if (!string.IsNullOrEmpty(__state))
				{
					RestoreLastTypedChatMessage(__instance, __state);
				}
			}
		}

		[HarmonyPatch(typeof(ChatBehaviour), "Send_ChatMessage")]
		private static class ChatBehaviour_SendMessage_Transpiler
		{
			private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instrs)
			{
				return ReplaceMaxLengthGuards(instrs, 1, "ChatBehaviour.Send_ChatMessage max length");
			}
		}

		[HarmonyPatch(typeof(ChatBehaviour), "UserCode_Cmd_SendChatMessage__String__ChatChannel")]
		private static class ChatBehaviour_CmdSendMessage_Transpiler
		{
			private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instrs)
			{
				return ReplaceMaxLengthGuards(instrs, 1, "ChatBehaviour.UserCode_Cmd_SendChatMessage__String__ChatChannel max length");
			}
		}

		private enum OutgoingChatPreparationStatus
		{
			Unchanged,
			Transformed,
			Suppressed,
			Invalid
		}

		public enum MentionClip
		{
			LexiconBell,
			UIClick01,
			UIHover,
			Lockout
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__OpenPendingChatLink;

			public static UnityAction <1>__CopyPendingChatLink;

			public static UnityAction <2>__CancelPendingChatLink;

			public static EventHandler <3>__OnChatTallWindowChanged;

			public static EventHandler <4>__OnTransparentScrollbarChanged;

			public static EventHandler <5>__OnMentionPingChanged;

			public static EventHandler <6>__OnMentionPingClipChanged;

			public static EventHandler <7>__OnMentionPingVolumeChanged;

			public static EventHandler <8>__OnOocEnabledChanged;
		}

		private static readonly Type PartyUiManagerType = typeof(Player).Assembly.GetType("PartyUIManager");

		private static readonly FieldInfo PartyUiCurrentField = AccessTools.Field(PartyUiManagerType, "_current");

		private static readonly FieldInfo PartyInviteElementField = AccessTools.Field(PartyUiManagerType, "_partyInviteElement");

		private static readonly FieldInfo PartyAcceptInviteButtonField = AccessTools.Field(PartyUiManagerType, "_acceptInviteButton");

		private static readonly FieldInfo PartyDeclineInviteButtonField = AccessTools.Field(PartyUiManagerType, "_declineInviteButton");

		private static readonly FieldInfo PartyInvitePromptField = AccessTools.Field(PartyUiManagerType, "_invitedByPrompt");

		private static readonly FieldInfo PartyPanelGroupField = AccessTools.Field(PartyUiManagerType, "_partyPanelGroup");

		private static readonly FieldInfo MenuElementRectField = AccessTools.Field(typeof(MenuElement), "menuRect");

		private static readonly FieldInfo MenuElementCanvasGroupField = AccessTools.Field(typeof(MenuElement), "_canvasGroup");

		private static GameObject _chatLinkPromptRoot;

		private static MenuElement _chatLinkPromptElement;

		private static CanvasGroup _chatLinkPromptCanvasGroup;

		private static TextMeshProUGUI _chatLinkPromptText;

		private static Text _chatLinkPromptTextLegacy;

		private static Button _chatLinkOpenButton;

		private static Button _chatLinkCopyButton;

		private static Button _chatLinkCancelButton;

		private static string _pendingChatLinkUrl;

		private static bool _chatLinkPromptOpen;

		private const string ChatLinkOverlayName = "ChatX_LinkClickOverlay";

		private static readonly Regex UrlRegex = new Regex("\\b(?:https?://|www\\.)[^\\s<]+", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant);

		internal static readonly ConditionalWeakTable<ChatBehaviourAssets, ChatScrollbarState> _scrollbarStates = new ConditionalWeakTable<ChatBehaviourAssets, ChatScrollbarState>();

		private static bool _dialogSuppressed;

		private static bool pendingRestore;

		private static bool _chatWasHidden;

		internal static readonly FieldInfo ChatInputBufferField = typeof(ChatBehaviour).GetField("_inputBuffer", BindingFlags.Instance | BindingFlags.NonPublic);

		private static bool _loggedMissingInputBufferField;

		private static bool _chatHidden;

		internal static ManualLogSource Log;

		private static readonly MethodInfo GetMaxMessageLengthMethod = AccessTools.Method(typeof(ChatX), "GetMaxMessageLength", (Type[])null, (Type[])null);

		private static readonly MethodInfo StringLengthGetter = AccessTools.PropertyGetter(typeof(string), "Length");

		internal static AudioClip _mentionAudioClip;

		private static float _nextMentionPingAllowedAt;

		private static readonly Dictionary<string, AudioClip> _mentionClipCache = new Dictionary<string, AudioClip>(StringComparer.OrdinalIgnoreCase);

		private static Type _cachedPlayerSoundType;

		private static FieldInfo[] _cachedPlayerSoundClipFields;

		private static Type _cachedButtonSoundType;

		private static FieldInfo _cachedButtonSoundHoverField;

		private static FieldInfo _cachedButtonSoundClickField;

		private static string _lastMissingMentionClipName;

		private const string OocToken = "[OOC]";

		private const string OocPrefix = "[OOC] ";

		private const string OocToggleCommand = "/ooc";

		private static readonly FieldInfo ChatLastMessageField = AccessTools.Field(typeof(ChatBehaviour), "_lastMessage");

		private static readonly Type ErrorPromptManagerType = typeof(Player).Assembly.GetType("ErrorPromptTextManager");

		private static readonly FieldInfo ErrorPromptCurrentField = AccessTools.Field(ErrorPromptManagerType, "current");

		private static readonly MethodInfo ErrorPromptInitMethod = AccessTools.Method(ErrorPromptManagerType, "Init_ErrorPrompt", (Type[])null, (Type[])null);

		private static bool _oocModeEnabled;

		internal static ConfigEntry<float> chatOpacity;

		internal static ConfigEntry<bool> blockChat;

		internal static ConfigEntry<bool> blockGameFeed;

		internal static ConfigEntry<bool> chatPrefix;

		internal static ConfigEntry<bool> chatTimestamp;

		internal static ConfigEntry<bool> timestampFormat;

		internal static ConfigEntry<bool> asteriskItalic;

		internal static ConfigEntry<bool> oocEnabled;

		internal static ConfigEntry<bool> chatTallWindow;

		internal static ConfigEntry<KeyCode> clearChatKey;

		internal static ConfigEntry<KeyCode> toggleChatVisibilityKey;

		internal static ConfigEntry<bool> messageLimit;

		internal static ConfigEntry<bool> pushGameMessage;

		internal static ConfigEntry<bool> mentionUnderline;

		internal static ConfigEntry<bool> mentionPing;

		internal static ConfigEntry<string> mentionPingClip;

		internal static ConfigEntry<MentionClip> mentionPingClipEnum;

		internal static ConfigEntry<float> mentionPingVolume;

		internal static ConfigEntry<bool> transparentScrollbar;

		private static bool _settingsRegistered;

		private const string SettingsTabName = "Chat";

		private static readonly MethodInfo GetOrAddCustomTabMethod = typeof(Settings).GetMethod("GetOrAddCustomTab", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(string) }, null);

		private static bool _loggedMissingCustomTabApi;

		private static readonly string[] ClipNames = new string[4] { "_lexiconBell", "_uiClick01", "_uiHover", "lockout" };

		internal static bool IsChatLinkPromptOpen => _chatLinkPromptOpen;

		private static string NormalizeChannelColorToken(string token)
		{
			if (string.IsNullOrWhiteSpace(token))
			{
				return string.Empty;
			}
			token = token.Trim();
			if (token.StartsWith("#", StringComparison.Ordinal) && token.Length >= 7)
			{
				token = token.Substring(0, 7);
			}
			return token.ToUpperInvariant();
		}

		private static bool TryExtractChatChannel(string message, out ChatChannel channel)
		{
			channel = (ChatChannel)0;
			if (string.IsNullOrEmpty(message))
			{
				return false;
			}
			int num = message.IndexOf("</color>: <color=", StringComparison.OrdinalIgnoreCase);
			if (num < 0)
			{
				return false;
			}
			int num2 = num + "</color>: <color=".Length;
			if (num2 >= message.Length)
			{
				return false;
			}
			int num3 = message.IndexOf('>', num2);
			if (num3 < 0)
			{
				return false;
			}
			int num4 = num2;
			string token = message.Substring(num4, num3 - num4);
			string text = NormalizeChannelColorToken(token);
			if (string.IsNullOrEmpty(text))
			{
				return false;
			}
			switch (text)
			{
			case "YELLOW":
			case "#FFFF00":
			case "#FFD700":
				channel = (ChatChannel)0;
				return true;
			case "#B2EC5D":
				channel = (ChatChannel)1;
				return true;
			case "#FF8A90":
				channel = (ChatChannel)2;
				return true;
			default:
				return false;
			}
		}

		private static int SkipTimestampPrefix(string msg, int startIndex = 0)
		{
			if (string.IsNullOrEmpty(msg) || startIndex >= msg.Length)
			{
				return startIndex;
			}
			if (msg[startIndex] != '[')
			{
				return startIndex;
			}
			int num = startIndex + 1;
			if (num >= msg.Length || !char.IsDigit(msg[num]))
			{
				return startIndex;
			}
			num++;
			if (num < msg.Length && char.IsDigit(msg[num]))
			{
				num++;
			}
			if (num >= msg.Length || msg[num] != ':')
			{
				return startIndex;
			}
			num++;
			if (num + 1 >= msg.Length || !char.IsDigit(msg[num]) || !char.IsDigit(msg[num + 1]))
			{
				return startIndex;
			}
			num += 2;
			if (num < msg.Length && msg[num] == ' ')
			{
				if (num + 2 >= msg.Length || (msg[num + 1] != 'A' && msg[num + 1] != 'a' && msg[num + 1] != 'P' && msg[num + 1] != 'p') || (msg[num + 2] != 'M' && msg[num + 2] != 'm'))
				{
					return startIndex;
				}
				num += 3;
			}
			if (num >= msg.Length || msg[num] != ']')
			{
				return startIndex;
			}
			num++;
			if (num < msg.Length && msg[num] == ' ')
			{
				num++;
			}
			return num;
		}

		public static string BuildColoredPrefixFromEnum(ChatChannel ch)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected I4, but got Unknown
			if (1 == 0)
			{
			}
			string result = (int)ch switch
			{
				0 => "<color=yellow>(G)</color>", 
				1 => "<color=#B2EC5D>(P)</color>", 
				2 => "<color=#FF8A90>(Z)</color>", 
				_ => string.Empty, 
			};
			if (1 == 0)
			{
			}
			return result;
		}

		public static string BuildMessagePrefix(ChatChannel ch)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			string text = null;
			ConfigEntry<bool> obj = chatTimestamp;
			if (obj != null && obj.Value)
			{
				string text2 = (timestampFormat.Value ? "HH:mm" : "h:mm tt");
				text = "[" + DateTime.Now.ToString(text2, CultureInfo.InvariantCulture) + "]";
			}
			string text3 = BuildColoredPrefixFromEnum(ch);
			if (string.IsNullOrEmpty(text3))
			{
				text3 = null;
			}
			if (text == null && text3 == null)
			{
				return string.Empty;
			}
			if (text != null && text3 != null)
			{
				return text + " " + text3 + " ";
			}
			return (text ?? text3) + " ";
		}

		public static string BuildOocBadge()
		{
			return "<color=yellow>[</color><color=#A7FC00>OOC</color><color=yellow>]</color>";
		}

		public static string ExtractRenderedOocBadge(ref string message)
		{
			if (!IsOocFeatureEnabled() || string.IsNullOrEmpty(message))
			{
				return string.Empty;
			}
			int num = message.IndexOf("</color>: <color=", StringComparison.OrdinalIgnoreCase);
			if (num < 0)
			{
				return string.Empty;
			}
			int startIndex = num + "</color>: <color=".Length;
			int num2 = message.IndexOf('>', startIndex);
			if (num2 < 0)
			{
				return string.Empty;
			}
			int startIndex2 = num2 + 1;
			if (!TryFindLeadingOocToken(message, startIndex2, out var tokenStart, out var tokenLength, out var trailingSpaceStart, out var trailingSpaceLength))
			{
				return string.Empty;
			}
			if (trailingSpaceLength > 0)
			{
				message = message.Remove(trailingSpaceStart, trailingSpaceLength);
			}
			message = message.Remove(tokenStart, tokenLength);
			return BuildOocBadge();
		}

		public static string CombinePrefixSegments(string prefix, string badge)
		{
			bool flag = !string.IsNullOrWhiteSpace(prefix);
			bool flag2 = !string.IsNullOrWhiteSpace(badge);
			if (!flag && !flag2)
			{
				return string.Empty;
			}
			prefix = (flag ? prefix.TrimEnd() : string.Empty);
			badge = (flag2 ? badge.Trim() : string.Empty);
			if (!flag)
			{
				return badge + " ";
			}
			if (!flag2)
			{
				return prefix.EndsWith(" ", StringComparison.Ordinal) ? prefix : (prefix + " ");
			}
			return prefix + " " + badge + " ";
		}

		public static bool LooksPrefixed(string msg)
		{
			if (string.IsNullOrEmpty(msg))
			{
				return false;
			}
			int num = SkipTimestampPrefix(msg);
			if (msg.Length - num >= 4 && msg[num] == '(' && (msg[num + 1] == 'G' || msg[num + 1] == 'P' || msg[num + 1] == 'Z') && msg[num + 2] == ')' && msg[num + 3] == ' ')
			{
				return true;
			}
			if (num < msg.Length && msg.IndexOf("<color", num, StringComparison.OrdinalIgnoreCase) == num)
			{
				int num2 = msg.IndexOf('>', num);
				if (num2 >= 0)
				{
					int num3 = msg.IndexOf("</color>", num2 + 1, StringComparison.OrdinalIgnoreCase);
					if (num3 > num2 + 1)
					{
						int num4 = num2 + 1;
						string text = msg.Substring(num4, num3 - num4);
						if (text.StartsWith("(G)") || text.StartsWith("(P)") || text.StartsWith("(Z)"))
						{
							return true;
						}
					}
				}
			}
			return false;
		}

		public static string InsertPrefix(string line, string prefix)
		{
			if (string.IsNullOrEmpty(prefix) || string.IsNullOrEmpty(line))
			{
				return line;
			}
			return prefix + line;
		}

		public static string ApplyAsteriskFormatting(string s)
		{
			ConfigEntry<bool> obj = asteriskItalic;
			if (obj == null || !obj.Value || string.IsNullOrEmpty(s) || s.IndexOf('*') < 0)
			{
				return s;
			}
			StringBuilder stringBuilder = new StringBuilder(s.Length + 16);
			ReadOnlySpan<char> readOnlySpan = s.AsSpan();
			bool flag = false;
			bool flag2 = false;
			bool flag3 = false;
			int num = -1;
			int num2 = -1;
			for (int i = 0; i < readOnlySpan.Length; i++)
			{
				char c = readOnlySpan[i];
				if (c == '<')
				{
					flag3 = true;
					stringBuilder.Append(c);
				}
				else if (c == '>' && flag3)
				{
					flag3 = false;
					stringBuilder.Append(c);
				}
				else if (c == '\\' && i + 1 < readOnlySpan.Length && readOnlySpan[i + 1] == '*')
				{
					stringBuilder.Append('*');
					i++;
				}
				else if (c == '*' && !flag3)
				{
					int j;
					for (j = i + 1; j < readOnlySpan.Length && readOnlySpan[j] == '*'; j++)
					{
					}
					int num3 = j - i;
					if (num3 >= 2)
					{
						int num4;
						for (num4 = num3; num4 >= 2; num4 -= 2)
						{
							if (flag2)
							{
								stringBuilder.Append("</b>");
								flag2 = false;
								num2 = -1;
							}
							else
							{
								num2 = stringBuilder.Length;
								stringBuilder.Append("<b>");
								flag2 = true;
							}
						}
						if (num4 == 1)
						{
							if (flag)
							{
								stringBuilder.Append("</i>");
								flag = false;
								num = -1;
							}
							else
							{
								num = stringBuilder.Length;
								stringBuilder.Append("<i>");
								flag = true;
							}
						}
					}
					else if (flag)
					{
						stringBuilder.Append("</i>");
						flag = false;
						num = -1;
					}
					else
					{
						num = stringBuilder.Length;
						stringBuilder.Append("<i>");
						flag = true;
					}
					i = j - 1;
				}
				else
				{
					stringBuilder.Append(c);
				}
			}
			if (flag2 && num2 >= 0)
			{
				stringBuilder.Remove(num2, 3).Insert(num2, "**");
				if (num > num2)
				{
					num += -1;
				}
			}
			if (flag && num >= 0)
			{
				stringBuilder.Remove(num, 3).Insert(num, "*");
			}
			return stringBuilder.ToString();
		}

		private static bool IsChatSubmitKeyPressed()
		{
			return Input.GetKeyDown((KeyCode)13) || Input.GetKeyDown((KeyCode)271);
		}

		internal static Transform FindDescendantTransformByName(Transform root, string name)
		{
			if ((Object)(object)root == (Object)null || string.IsNullOrEmpty(name))
			{
				return null;
			}
			Queue<Transform> queue = new Queue<Transform>();
			queue.Enqueue(root);
			while (queue.Count > 0)
			{
				Transform val = queue.Dequeue();
				if (!((Object)(object)val == (Object)null))
				{
					if (((Object)val).name == name)
					{
						return val;
					}
					for (int i = 0; i < val.childCount; i++)
					{
						queue.Enqueue(val.GetChild(i));
					}
				}
			}
			return null;
		}

		internal static T FindDescendantComponentByName<T>(Transform root, string name) where T : Component
		{
			Transform val = FindDescendantTransformByName(root, name);
			return ((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<T>() : default(T);
		}

		internal static void ResetLinkPromptRuntimeState()
		{
			_pendingChatLinkUrl = null;
			_chatLinkPromptOpen = false;
			_chatLinkPromptElement = null;
			_chatLinkPromptText = null;
			_chatLinkPromptTextLegacy = null;
			_chatLinkOpenButton = null;
			_chatLinkCopyButton = null;
			_chatLinkCancelButton = null;
			_chatLinkPromptCanvasGroup = null;
			if ((Object)(object)_chatLinkPromptRoot != (Object)null && !((object)_chatLinkPromptRoot).Equals((object?)null))
			{
				Object.Destroy((Object)(object)_chatLinkPromptRoot);
			}
			_chatLinkPromptRoot = null;
		}

		internal static bool PollLinkPromptHotkeys()
		{
			if (!_chatLinkPromptOpen)
			{
				return false;
			}
			if (Input.GetKeyDown((KeyCode)27))
			{
				CancelPendingChatLink();
				return true;
			}
			if (IsChatSubmitKeyPressed())
			{
				OpenPendingChatLink();
				return true;
			}
			return false;
		}

		internal static void ShowChatLinkPrompt(ChatBehaviourAssets assets, string url)
		{
			if (_chatLinkPromptOpen)
			{
				return;
			}
			if (!TryCanonicalizeUrl(url, out var canonicalUrl))
			{
				ShowErrorPrompt("That link is invalid.");
				return;
			}
			EnsureChatLinkPrompt(assets ?? ChatBehaviourAssets._current);
			if ((Object)(object)_chatLinkPromptRoot == (Object)null || ((object)_chatLinkPromptRoot).Equals((object?)null))
			{
				ShowErrorPrompt("Chat link prompts are unavailable right now.");
				return;
			}
			_pendingChatLinkUrl = canonicalUrl;
			SetChatLinkPromptText(canonicalUrl);
			SetChatLinkPromptVisible(visible: true);
			EventSystem current = EventSystem.current;
			if (current != null)
			{
				current.SetSelectedGameObject(((Object)(object)_chatLinkOpenButton != (Object)null) ? ((Component)_chatLinkOpenButton).gameObject : null);
			}
		}

		private static void OpenPendingChatLink()
		{
			string pendingChatLinkUrl = _pendingChatLinkUrl;
			HideChatLinkPrompt();
			if (!TryCanonicalizeUrl(pendingChatLinkUrl, out var canonicalUrl))
			{
				ShowErrorPrompt("That link is invalid.");
			}
			else
			{
				Application.OpenURL(canonicalUrl);
			}
		}

		private static void CopyPendingChatLink()
		{
			string pendingChatLinkUrl = _pendingChatLinkUrl;
			HideChatLinkPrompt();
			if (!TryCanonicalizeUrl(pendingChatLinkUrl, out var canonicalUrl))
			{
				ShowErrorPrompt("That link is invalid.");
				return;
			}
			try
			{
				GUIUtility.systemCopyBuffer = canonicalUrl;
				PushLocalChatStatus(ChatBehaviour._current, "Link copied to clipboard.");
			}
			catch (Exception ex)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogDebug((object)("ChatX could not copy the pending link: " + ex.Message));
				}
				ShowErrorPrompt("Could not copy that link.");
			}
		}

		private static void CancelPendingChatLink()
		{
			HideChatLinkPrompt();
		}

		private static void HideChatLinkPrompt()
		{
			_pendingChatLinkUrl = null;
			SetChatLinkPromptVisible(visible: false);
			EventSystem current = EventSystem.current;
			if (current != null)
			{
				current.SetSelectedGameObject((GameObject)null);
			}
		}

		private static void SetChatLinkPromptVisible(bool visible)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			_chatLinkPromptOpen = visible;
			if ((Object)(object)_chatLinkPromptRoot == (Object)null || ((object)_chatLinkPromptRoot).Equals((object?)null))
			{
				return;
			}
			if ((Object)(object)_chatLinkPromptElement != (Object)null)
			{
				_chatLinkPromptRoot.SetActive(true);
				RectTransform menuElementRect = GetMenuElementRect(_chatLinkPromptElement);
				if ((Object)(object)menuElementRect != (Object)null)
				{
					menuElementRect.anchoredPosition = Vector2.zero;
				}
				_chatLinkPromptElement.isEnabled = visible;
			}
			if ((Object)(object)_chatLinkPromptCanvasGroup != (Object)null)
			{
				_chatLinkPromptCanvasGroup.alpha = (visible ? 1f : 0f);
				_chatLinkPromptCanvasGroup.blocksRaycasts = visible;
				_chatLinkPromptCanvasGroup.interactable = visible;
			}
			if ((Object)(object)_chatLinkPromptElement == (Object)null)
			{
				_chatLinkPromptRoot.SetActive(visible);
			}
			if (visible)
			{
				Transform transform = _chatLinkPromptRoot.transform;
				RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null);
				if (val != null)
				{
					((Transform)val).SetAsLastSibling();
					LayoutRebuilder.ForceRebuildLayoutImmediate(val);
				}
			}
		}

		private static void SetChatLinkPromptText(string canonicalUrl)
		{
			string text = "Open this link in your browser?\n" + canonicalUrl;
			if ((Object)(object)_chatLinkPromptText != (Object)null)
			{
				((TMP_Text)_chatLinkPromptText).text = text;
			}
			if ((Object)(object)_chatLinkPromptTextLegacy != (Object)null)
			{
				_chatLinkPromptTextLegacy.text = text;
			}
		}

		private static void EnsureChatLinkPrompt(ChatBehaviourAssets assets)
		{
			if (!((Object)(object)_chatLinkPromptRoot != (Object)null) || ((object)_chatLinkPromptRoot).Equals((object?)null))
			{
				Transform val = ResolveChatLinkPromptParent(assets);
				if (!((Object)(object)val == (Object)null))
				{
					int layer = (((Object)(object)assets != (Object)null) ? ((Component)assets).gameObject.layer : ((Component)val).gameObject.layer);
					TryCreatePromptFromPartyInvite(val, layer);
				}
			}
		}

		private static bool TryCreatePromptFromPartyInvite(Transform parent, int layer)
		{
			//IL_00c4: 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_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: 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_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_029d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: 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_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: 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_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: 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_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0401: Unknown result type (might be due to invalid IL or missing references)
			//IL_040b: Expected O, but got Unknown
			//IL_043c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0446: Expected O, but got Unknown
			//IL_0426: Unknown result type (might be due to invalid IL or missing references)
			//IL_042b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0431: Expected O, but got Unknown
			//IL_0477: Unknown result type (might be due to invalid IL or missing references)
			//IL_0481: Expected O, but got Unknown
			//IL_0461: Unknown result type (might be due to invalid IL or missing references)
			//IL_0466: Unknown result type (might be due to invalid IL or missing references)
			//IL_046c: Expected O, but got Unknown
			//IL_049c: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a7: Expected O, but got Unknown
			try
			{
				object obj = PartyUiCurrentField?.GetValue(null);
				object? obj2 = PartyInviteElementField?.GetValue(obj);
				MenuElement val = (MenuElement)((obj2 is MenuElement) ? obj2 : null);
				if (obj == null || (Object)(object)val == (Object)null || (Object)(object)((Component)val).gameObject == (Object)null)
				{
					return false;
				}
				_chatLinkPromptRoot = Object.Instantiate<GameObject>(((Component)val).gameObject, parent, false);
				((Object)_chatLinkPromptRoot).name = "ChatX_LinkPrompt";
				_chatLinkPromptRoot.SetActive(true);
				SetLayerRecursive(_chatLinkPromptRoot, layer);
				RectTransform component = ((Component)val).GetComponent<RectTransform>();
				RectTransform component2 = _chatLinkPromptRoot.GetComponent<RectTransform>();
				Rect rect;
				if ((Object)(object)component2 != (Object)null)
				{
					Vector2 val2 = default(Vector2);
					((Vector2)(ref val2))..ctor(720f, 230f);
					Vector2 val3 = val2;
					if ((Object)(object)component != (Object)null)
					{
						rect = component.rect;
						val3 = ((Rect)(ref rect)).size;
						if (val3.x <= 1f || val3.y <= 1f)
						{
							val3 = component.sizeDelta;
						}
					}
					if (val3.x <= 1f || val3.y <= 1f)
					{
						val3 = val2;
					}
					component2.anchorMin = new Vector2(0.5f, 0.5f);
					component2.anchorMax = new Vector2(0.5f, 0.5f);
					component2.pivot = (Vector2)(((Object)(object)component != (Object)null) ? component.pivot : new Vector2(0.5f, 0.5f));
					component2.sizeDelta = val3 * 2f;
					component2.anchoredPosition = Vector2.zero;
					((Transform)component2).localScale = Vector3.one;
					((Transform)component2).localRotation = Quaternion.identity;
					((Transform)component2).SetAsLastSibling();
				}
				_chatLinkPromptElement = _chatLinkPromptRoot.GetComponent<MenuElement>();
				RectTransform menuElementRect = GetMenuElementRect(_chatLinkPromptElement);
				if ((Object)(object)menuElementRect != (Object)null)
				{
					if ((Object)(object)component2 == (Object)null || menuElementRect != component2)
					{
						rect = menuElementRect.rect;
						Vector2 val4 = ((Rect)(ref rect)).size;
						if (val4.x <= 1f || val4.y <= 1f)
						{
							val4 = menuElementRect.sizeDelta;
						}
						if (val4.x > 1f && val4.y > 1f)
						{
							menuElementRect.sizeDelta = val4 * 2f;
						}
					}
					menuElementRect.anchoredPosition = Vector2.zero;
				}
				_chatLinkPromptCanvasGroup = GetMenuElementCanvasGroup(_chatLinkPromptElement) ?? _chatLinkPromptRoot.GetComponentInChildren<CanvasGroup>(true) ?? _chatLinkPromptRoot.GetComponent<CanvasGroup>();
				object? obj3 = PartyInvitePromptField?.GetValue(obj);
				Component originalComponent = (Component)((obj3 is Component) ? obj3 : null);
				object? obj4 = PartyAcceptInviteButtonField?.GetValue(obj);
				Component originalComponent2 = (Component)((obj4 is Component) ? obj4 : null);
				object? obj5 = PartyDeclineInviteButtonField?.GetValue(obj);
				Component originalComponent3 = (Component)((obj5 is Component) ? obj5 : null);
				_chatLinkPromptText = FindClonedComponent<TextMeshProUGUI>(((Component)val).transform, originalComponent, _chatLinkPromptRoot.transform);
				_chatLinkPromptTextLegacy = FindClonedComponent<Text>(((Component)val).transform, originalComponent, _chatLinkPromptRoot.transform) ?? _chatLinkPromptRoot.GetComponentInChildren<Text>(true);
				_chatLinkOpenButton = FindClonedComponent<Button>(((Component)val).transform, originalComponent2, _chatLinkPromptRoot.transform);
				_chatLinkCancelButton = FindClonedComponent<Button>(((Component)val).transform, originalComponent3, _chatLinkPromptRoot.transform);
				_chatLinkCopyButton = ClonePromptButton(_chatLinkOpenButton, "Button_Copy", layer);
				if ((Object)(object)_chatLinkOpenButton == (Object)null || (Object)(object)_chatLinkCopyButton == (Object)null || (Object)(object)_chatLinkCancelButton == (Object)null)
				{
					Object.Destroy((Object)(object)_chatLinkPromptRoot);
					ResetLinkPromptRuntimeState();
					return false;
				}
				_chatLinkOpenButton.onClick = new ButtonClickedEvent();
				ButtonClickedEvent onClick = _chatLinkOpenButton.onClick;
				object obj6 = <>O.<0>__OpenPendingChatLink;
				if (obj6 == null)
				{
					UnityAction val5 = OpenPendingChatLink;
					<>O.<0>__OpenPendingChatLink = val5;
					obj6 = (object)val5;
				}
				((UnityEvent)onClick).AddListener((UnityAction)obj6);
				_chatLinkCopyButton.onClick = new ButtonClickedEvent();
				ButtonClickedEvent onClick2 = _chatLinkCopyButton.onClick;
				object obj7 = <>O.<1>__CopyPendingChatLink;
				if (obj7 == null)
				{
					UnityAction val6 = CopyPendingChatLink;
					<>O.<1>__CopyPendingChatLink = val6;
					obj7 = (object)val6;
				}
				((UnityEvent)onClick2).AddListener((UnityAction)obj7);
				_chatLinkCancelButton.onClick = new ButtonClickedEvent();
				ButtonClickedEvent onClick3 = _chatLinkCancelButton.onClick;
				object obj8 = <>O.<2>__CancelPendingChatLink;
				if (obj8 == null)
				{
					UnityAction val7 = CancelPendingChatLink;
					<>O.<2>__CancelPendingChatLink = val7;
					obj8 = (object)val7;
				}
				((UnityEvent)onClick3).AddListener((UnityAction)obj8);
				ConfigurePromptButtonContent(((Component)_chatLinkOpenButton).gameObject, "Open", PromptButtonIconKind.Confirm, _chatLinkPromptText, iconOnly: true);
				ConfigurePromptButtonContent(((Component)_chatLinkCopyButton).gameObject, "Copy", PromptButtonIconKind.Copy, _chatLinkPromptText, iconOnly: true);
				ConfigurePromptButtonContent(((Component)_chatLinkCancelButton).gameObject, "Cancel", PromptButtonIconKind.Cancel, _chatLinkPromptText, iconOnly: true);
				LayoutPromptButtons(menuElementRect ?? component2, _chatLinkOpenButton, _chatLinkCopyButton, _chatLinkCancelButton);
				SetChatLinkPromptVisible(visible: false);
				return true;
			}
			catch (Exception ex)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogDebug((object)("ChatX could not clone the party invite modal for link prompts: " + ex.Message));
				}
				ResetLinkPromptRuntimeState();
				return false;
			}
		}

		private static Transform ResolveChatLinkPromptParent(ChatBehaviourAssets assets)
		{
			Transform val = Resolve(assets) ?? Resolve(ChatBehaviourAssets._current);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			try
			{
				object obj = PartyUiCurrentField?.GetValue(null);
				if (obj != null)
				{
					object? obj2 = PartyPanelGroupField?.GetValue(obj);
					CanvasGroup val2 = (CanvasGroup)((obj2 is CanvasGroup) ? obj2 : null);
					if (val2 != null)
					{
						Canvas componentInParent = ((Component)val2).GetComponentInParent<Canvas>();
						if ((Object)(object)componentInParent != (Object)null)
						{
							return ((Component)componentInParent).transform;
						}
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogDebug((object)("ChatX could not resolve link prompt canvas parent: " + ex.Message));
				}
			}
			return null;
			static Transform Resolve(ChatBehaviourAssets candidate)
			{
				if ((Object)(object)candidate == (Object)null)
				{
					return null;
				}
				Canvas val3 = null;
				if ((Object)(object)candidate._chatText != (Object)null)
				{
					val3 = ((Graphic)candidate._chatText).canvas;
				}
				if (val3 == null)
				{
					val3 = ((Component)candidate).GetComponentInParent<Canvas>();
				}
				if ((Object)(object)val3 != (Object)null)
				{
					return ((Component)val3).transform;
				}
				return ((Component)candidate).transform;
			}
		}

		private static T FindClonedComponent<T>(Transform originalRoot, Component originalComponent, Transform clonedRoot) where T : Component
		{
			if ((Object)(object)originalRoot == (Object)null || (Object)(object)originalComponent == (Object)null || (Object)(object)clonedRoot == (Object)null)
			{
				return default(T);
			}
			string relativeTransformPath = GetRelativeTransformPath(originalRoot, originalComponent.transform);
			Transform val = (string.IsNullOrEmpty(relativeTransformPath) ? clonedRoot : clonedRoot.Find(relativeTransformPath));
			return ((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<T>() : default(T);
		}

		private static string GetRelativeTransformPath(Transform root, Transform target)
		{
			if ((Object)(object)root == (Object)null || (Object)(object)target == (Object)null)
			{
				return null;
			}
			if (root == target)
			{
				return string.Empty;
			}
			Stack<string> stack = new Stack<string>();
			Transform val = target;
			while ((Object)(object)val != (Object)null && val != root)
			{
				stack.Push(((Object)val).name);
				val = val.parent;
			}
			if (val != root)
			{
				return null;
			}
			return string.Join("/", stack);
		}

		private static RectTransform GetMenuElementRect(MenuElement element)
		{
			return (RectTransform)(((Object)(object)element != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
		}

		private static CanvasGroup GetMenuElementCanvasGroup(MenuElement element)
		{
			return (CanvasGroup)(((Object)(object)element != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
		}

		private static Button ClonePromptButton(Button template, string objectName, int layer)
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)template == (Object)null || (Object)(object)((Component)template).gameObject == (Object)null)
			{
				return null;
			}
			Transform parent = ((Component)template).transform.parent;
			if ((Object)(object)parent == (Object)null)
			{
				return null;
			}
			GameObject val = Object.Instantiate<GameObject>(((Component)template).gameObject, parent, false);
			((Object)val).name = objectName;
			SetLayerRecursive(val, layer);
			RectTransform component = val.GetComponent<RectTransform>();
			if ((Object)(object)component != (Object)null)
			{
				((Transform)component).localScale = Vector3.one;
				((Transform)component).localRotation = Quaternion.identity;
			}
			Button component2 = val.GetComponent<Button>();
			return ((Object)(object)component2 != (Object)null) ? component2 : val.AddComponent<Button>();
		}

		private static void UpdateButtonLabel(GameObject buttonObject, string label, TextMeshProUGUI fallback)
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)buttonObject == (Object)null)
			{
				return;
			}
			TMP_Text componentInChildren = buttonObject.GetComponentInChildren<TMP_Text>(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				componentInChildren.text = label;
				TextMeshProUGUI val = (TextMeshProUGUI)(object)((componentInChildren is TextMeshProUGUI) ? componentInChildren : null);
				if (val != null)
				{
					ApplyPromptTextStyle(val, null, fallback);
				}
				return;
			}
			Text componentInChildren2 = buttonObject.GetComponentInChildren<Text>(true);
			if ((Object)(object)componentInChildren2 != (Object)null)
			{
				componentInChildren2.text = label;
				if ((Object)(object)fallback != (Object)null)
				{
					((Graphic)componentInChildren2).color = ((Graphic)fallback).color;
					componentInChildren2.fontSize = Mathf.RoundToInt(Mathf.Max(18f, ((TMP_Text)fallback).fontSize));
					componentInChildren2.alignment = (TextAnchor)4;
				}
			}
		}

		private static void ConfigurePromptButtonContent(GameObject buttonObject, string label, PromptButtonIconKind iconKind, TextMeshProUGUI fallback, bool iconOnly = false)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)buttonObject == (Object)null))
			{
				UpdateButtonLabel(buttonObject, iconOnly ? string.Empty : label, fallback);
				SuppressPromptButtonChildIcons(buttonObject);
				SetPromptButtonLabelVisible(buttonObject, !iconOnly);
				if (!iconOnly)
				{
					AdjustPromptButtonLabelLayout(buttonObject);
				}
				BuildPromptButtonIcon(buttonObject, iconKind, ((Object)(object)fallback != (Object)null) ? ((Graphic)fallback).color : Color.white, iconOnly);
			}
		}

		private static void LayoutPromptButtons(RectTransform hostRect, params Button[] buttons)
		{
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Expected O, but got Unknown
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: 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_02df: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_030d: Unknown result type (might be due to invalid IL or missing references)
			//IL_031d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0331: Unknown result type (might be due to invalid IL or missing references)
			//IL_033e: Unknown result type (might be due to invalid IL or missing references)
			//IL_034b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)hostRect == (Object)null || buttons == null || buttons.Length == 0)
			{
				return;
			}
			List<Button> list = new List<Button>(buttons.Length);
			foreach (Button val in buttons)
			{
				if (!((Object)(object)val == (Object)null) && !((object)val).Equals((object?)null))
				{
					list.Add(val);
				}
			}
			if (list.Count == 0)
			{
				return;
			}
			Transform val2 = ((Transform)hostRect).Find("ChatX_ButtonRow");
			RectTransform val3;
			if ((Object)(object)val2 != (Object)null)
			{
				val3 = (RectTransform)(object)((val2 is RectTransform) ? val2 : null);
			}
			else
			{
				GameObject val4 = new GameObject("ChatX_ButtonRow", new Type[1] { typeof(RectTransform) });
				val4.layer = ((Component)hostRect).gameObject.layer;
				SetLayerRecursive(val4, ((Component)hostRect).gameObject.layer);
				val3 = val4.GetComponent<RectTransform>();
				((Transform)val3).SetParent((Transform)(object)hostRect, false);
			}
			float num = 0f;
			foreach (Button item in list)
			{
				RectTransform component = ((Component)item).GetComponent<RectTransform>();
				if (!((Object)(object)component == (Object)null))
				{
					Rect rect = component.rect;
					float num2 = Mathf.Abs(((Rect)(ref rect)).height);
					if (num2 <= 1f)
					{
						num2 = Mathf.Abs(component.sizeDelta.y);
					}
					if (num2 > 1f)
					{
						num = num2;
						break;
					}
				}
			}
			if (num <= 1f)
			{
				num = 44f;
			}
			float num3 = Mathf.Max(num * 1.7f, 78f);
			float num4 = Mathf.Clamp(num * 0.2f, 8f, 14f);
			float num5 = num3 * (float)list.Count + num4 * (float)(list.Count - 1);
			val3.anchorMin = new Vector2(0.5f, 0f);
			val3.anchorMax = new Vector2(0.5f, 0f);
			val3.pivot = new Vector2(0.5f, 0f);
			val3.sizeDelta = new Vector2(num5, num);
			val3.anchoredPosition = new Vector2(0f, Mathf.Clamp(num * 0.5f, 18f, 30f));
			((Transform)val3).SetAsLastSibling();
			for (int j = 0; j < list.Count; j++)
			{
				Button val5 = list[j];
				RectTransform component2 = ((Component)val5).GetComponent<RectTransform>();
				if (!((Object)(object)component2 == (Object)null))
				{
					((Component)val5).transform.SetParent((Transform)(object)val3, false);
					float num6 = 0f - (num5 - num3) * 0.5f;
					float num7 = num6 + (float)j * (num3 + num4);
					component2.anchorMin = new Vector2(0.5f, 0.5f);
					component2.anchorMax = new Vector2(0.5f, 0.5f);
					component2.pivot = new Vector2(0.5f, 0.5f);
					component2.sizeDelta = new Vector2(num3, num);
					component2.anchoredPosition = new Vector2(num7, 0f);
					((Transform)component2).localScale = Vector3.one;
					((Transform)component2).localRotation = Quaternion.identity;
					LayoutElement component3 = ((Component)val5).GetComponent<LayoutElement>();
					if ((Object)(object)component3 != (Object)null)
					{
						component3.ignoreLayout = true;
					}
				}
			}
			LayoutRebuilder.ForceRebuildLayoutImmediate(val3);
			LayoutRebuilder.ForceRebuildLayoutImmediate(hostRect);
		}

		private static void SetPromptButtonLabelVisible(GameObject buttonObject, bool visible)
		{
			if ((Object)(object)buttonObject == (Object)null)
			{
				return;
			}
			TMP_Text[] componentsInChildren = buttonObject.GetComponentsInChildren<TMP_Text>(true);
			foreach (TMP_Text val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !(((Object)((Component)val).gameObject).name == "ChatX_Icon"))
				{
					val.text = (visible ? val.text : string.Empty);
					((Behaviour)val).enabled = visible;
				}
			}
			Text[] componentsInChildren2 = buttonObject.GetComponentsInChildren<Text>(true);
			foreach (Text val2 in componentsInChildren2)
			{
				if (!((Object)(object)val2 == (Object)null) && !(((Object)((Component)val2).gameObject).name == "ChatX_Icon"))
				{
					val2.text = (visible ? val2.text : string.Empty);
					((Behaviour)val2).enabled = visible;
				}
			}
		}

		private static void SuppressPromptButtonChildIcons(GameObject buttonObject)
		{
			//IL_002d: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)buttonObject == (Object)null)
			{
				return;
			}
			RectTransform component = buttonObject.GetComponent<RectTransform>();
			float num = 0f;
			Rect rect;
			if ((Object)(object)component != (Object)null)
			{
				rect = component.rect;
				Vector2 size = ((Rect)(ref rect)).size;
				num = Mathf.Abs(size.x * size.y);
			}
			Image component2 = buttonObject.GetComponent<Image>();
			Image[] componentsInChildren = buttonObject.GetComponentsInChildren<Image>(true);
			foreach (Image val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)component2) && !((Object)(object)((Component)val).transform.parent != (Object)(object)buttonObject.transform))
				{
					RectTransform rectTransform = ((Graphic)val).rectTransform;
					float num2;
					if (!((Object)(object)rectTransform != (Object)null))
					{
						num2 = 0f;
					}
					else
					{
						rect = rectTransform.rect;
						float width = ((Rect)(ref rect)).width;
						rect = rectTransform.rect;
						num2 = Mathf.Abs(width * ((Rect)(ref rect)).height);
					}
					float num3 = num2;
					if (!(num > 0f) || !(num3 >= num * 0.7f))
					{
						((Behaviour)val).enabled = false;
						((Graphic)val).raycastTarget = false;
					}
				}
			}
		}

		private static void AdjustPromptButtonLabelLayout(GameObject buttonObject)
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)buttonObject == (Object)null)
			{
				return;
			}
			TextMeshProUGUI[] componentsInChildren = buttonObject.GetComponentsInChildren<TextMeshProUGUI>(true);
			foreach (TextMeshProUGUI val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !(((Object)((Component)val).gameObject).name == "ChatX_Icon"))
				{
					RectTransform rectTransform = ((TMP_Text)val).rectTransform;
					if ((Object)(object)rectTransform != (Object)null)
					{
						rectTransform.offsetMin = new Vector2(Mathf.Max(rectTransform.offsetMin.x, 34f), rectTransform.offsetMin.y);
						rectTransform.offsetMax = new Vector2(Mathf.Min(rectTransform.offsetMax.x, -8f), rectTransform.offsetMax.y);
					}
					((TMP_Text)val).alignment = (TextAlignmentOptions)4097;
					return;
				}
			}
			Text[] componentsInChildren2 = buttonObject.GetComponentsInChildren<Text>(true);
			foreach (Text val2 in componentsInChildren2)
			{
				if (!((Object)(object)val2 == (Object)null) && !(((Object)((Component)val2).gameObject).name == "ChatX_Icon"))
				{
					Transform transform = ((Component)val2).transform;
					RectTransform val3 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
					if (val3 != null)
					{
						val3.offsetMin = new Vector2(Mathf.Max(val3.offsetMin.x, 34f), val3.offsetMin.y);
						val3.offsetMax = new Vector2(Mathf.Min(val3.offsetMax.x, -8f), val3.offsetMax.y);
					}
					val2.alignment = (TextAnchor)3;
					break;
				}
			}
		}

		private static void BuildPromptButtonIcon(GameObject buttonObject, PromptButtonIconKind iconKind, Color baseColor, bool centered = false)
		{
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Expected O, but got Unknown
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: 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_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: 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_017e: 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_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0242: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)buttonObject == (Object)null)
			{
				return;
			}
			Transform val = buttonObject.transform.Find("ChatX_Icon");
			GameObject val2;
			if ((Object)(object)val != (Object)null)
			{
				val2 = ((Component)val).gameObject;
				for (int num = val2.transform.childCount - 1; num >= 0; num--)
				{
					Object.Destroy((Object)(object)((Component)val2.transform.GetChild(num)).gameObject);
				}
			}
			else
			{
				val2 = new GameObject("ChatX_Icon", new Type[1] { typeof(RectTransform) });
				SetLayerRecursive(val2, buttonObject.layer);
				RectTransform component = val2.GetComponent<RectTransform>();
				((Transform)component).SetParent(buttonObject.transform, false);
			}
			RectTransform component2 = val2.GetComponent<RectTransform>();
			component2.anchorMin = new Vector2(0.5f, 0.5f);
			component2.anchorMax = new Vector2(0.5f, 0.5f);
			component2.pivot = new Vector2(0.5f, 0.5f);
			component2.sizeDelta = new Vector2(24f, 24f);
			component2.anchoredPosition = (Vector2)(centered ? Vector2.zero : new Vector2(-18f, 0f));
			((Transform)component2).SetAsFirstSibling();
			Color val3 = baseColor;
			if (iconKind == PromptButtonIconKind.Confirm)
			{
				((Color)(ref val3))..ctor(Mathf.Clamp01(baseColor.r + 0.08f), Mathf.Clamp01(baseColor.g + 0.12f), Mathf.Clamp01(baseColor.b), baseColor.a);
			}
			switch (iconKind)
			{
			case PromptButtonIconKind.Confirm:
				CreatePromptIconStroke(val2.transform, new Vector2(5f, 12f), new Vector2(-5.5f, -3.5f), 42f, val3);
				CreatePromptIconStroke(val2.transform, new Vector2(5f, 22f), new Vector2(4.5f, 1.5f), -44f, val3);
				break;
			case PromptButtonIconKind.Copy:
				CreatePromptIconOutline(val2.transform, new Vector2(10f, 12f), new Vector2(-2.5f, 2.5f), 2f, new Color(val3.r, val3.g, val3.b, val3.a * 0.72f));
				CreatePromptIconOutline(val2.transform, new Vector2(10f, 12f), new Vector2(2.5f, -1.5f), 2f, val3);
				break;
			case PromptButtonIconKind.Cancel:
				CreatePromptIconStroke(val2.transform, new Vector2(5f, 22f), Vector2.zero, 45f, val3);
				CreatePromptIconStroke(val2.transform, new Vector2(5f, 22f), Vector2.zero, -45f, val3);
				break;
			}
		}

		private static void CreatePromptIconOutline(Transform parent, Vector2 size, Vector2 position, float thickness, Color color)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: 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)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: 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_009b: 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)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: 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_00d8: 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_00e7: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)parent == (Object)null))
			{
				float num = Mathf.Max(0f, (size.x - thickness) * 0.5f);
				float num2 = Mathf.Max(0f, (size.y - thickness) * 0.5f);
				CreatePromptIconStroke(parent, new Vector2(size.x, thickness), position + new Vector2(0f, num2), 0f, color);
				CreatePromptIconStroke(parent, new Vector2(size.x, thickness), position - new Vector2(0f, num2), 0f, color);
				CreatePromptIconStroke(parent, new Vector2(thickness, size.y), position + new Vector2(num, 0f), 0f, color);
				CreatePromptIconStroke(parent, new Vector2(thickness, size.y), position - new Vector2(num, 0f), 0f, color);
			}
		}

		private static void CreatePromptIconStroke(Transform parent, Vector2 size, Vector2 position, float rotation, Color color)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			//IL_0069: 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_0095: 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)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)parent == (Object)null))
			{
				GameObject val = new GameObject("Stroke", new Type[2]
				{
					typeof(RectTransform),
					typeof(Image)
				})
				{
					layer = ((Component)parent).gameObject.layer
				};
				RectTransform component = val.GetComponent<RectTransform>();
				((Transform)component).SetParent(parent, false);
				component.anchorMin = new Vector2(0.5f, 0.5f);
				component.anchorMax = new Vector2(0.5f, 0.5f);
				component.pivot = new Vector2(0.5f, 0.5f);
				component.sizeDelta = size;
				component.anchoredPosition = position;
				((Transform)component).localRotation = Quaternion.Euler(0f, 0f, rotation);
				Image component2 = val.GetComponent<Image>();
				((Graphic)component2).color = color;
				((Graphic)component2).raycastTarget = false;
			}
		}

		private static void ApplyPromptTextStyle(TextMeshProUGUI target, Component template, TextMeshProUGUI fallback)
		{
			//IL_0030: 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_00d5: 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_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)target == (Object)null)
			{
				return;
			}
			TMP_Text val = (TMP_Text)(object)((template is TMP_Text) ? template : null);
			if (val != null)
			{
				((TMP_Text)target).font = val.font;
				((TMP_Text)target).fontStyle = val.fontStyle;
				((TMP_Text)target).fontMaterial = val.fontMaterial;
				((Graphic)target).color = ((Graphic)val).color;
				((TMP_Text)target).fontSize = val.fontSize;
			}
			else
			{
				Text val2 = (Text)(object)((template is Text) ? template : null);
				if (val2 != null)
				{
					if ((Object)(object)TMP_Settings.defaultFontAsset != (Object)null)
					{
						((TMP_Text)target).font = TMP_Settings.defaultFontAsset;
					}
					((Graphic)target).color = ((Graphic)val2).color;
					((TMP_Text)target).fontSize = val2.fontSize;
				}
				else if ((Object)(object)fallback != (Object)null)
				{
					((TMP_Text)target).font = ((TMP_Text)fallback).font;
					((TMP_Text)target).fontStyle = ((TMP_Text)fallback).fontStyle;
					((TMP_Text)target).fontMaterial = ((TMP_Text)fallback).fontMaterial;
					((Graphic)target).color = ((Graphic)fallback).color;
					((TMP_Text)target).fontSize = ((TMP_Text)fallback).fontSize;
				}
				else if ((Object)(object)TMP_Settings.defaultFontAsset != (Object)null)
				{
					((TMP_Text)target).font = TMP_Settings.defaultFontAsset;
					((Graphic)target).color = Color.white;
					((TMP_Text)target).fontSize = 24f;
				}
			}
			((TMP_Text)target).alignment = (TextAlignmentOptions)514;
			((TMP_Text)target).enableWordWrapping = true;
			((TMP_Text)target).overflowMode = (TextOverflowModes)0;
			((Graphic)target).raycastTarget = false;
		}

		internal static void EnsureChatLinkUi(ChatBehaviourAssets assets)
		{
			if (!Object.op_Implicit((Object)(object)assets) || (Object)(object)assets._chatText == (Object)null)
			{
				return;
			}
			ScrollRect componentInParent = ((Component)assets._chatText).GetComponentInParent<ScrollRect>();
			if ((Object)(object)componentInParent == (Object)null)
			{
				return;
			}
			GameObject val = ResolveChatLinkOverlay(componentInParent, assets._chatText);
			if (!((Object)(object)val == (Object)null))
			{
				ChatLinkClickHandler chatLinkClickHandler = val.GetComponent<ChatLinkClickHandler>();
				if ((Object)(object)chatLinkClickHandler == (Object)null)
				{
					chatLinkClickHandler = val.AddComponent<ChatLinkClickHandler>();
				}
				chatLinkClickHandler.Bind(assets, componentInParent, assets._chatText);
				((Graphic)assets._chatText).raycastTarget = false;
			}
		}

		private static GameObject ResolveChatLinkOverlay(ScrollRect scrollRect, TextMeshProUGUI chatText)
		{
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Expected O, but got Unknown
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: 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_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: 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_01cc: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)scrollRect == (Object)null)
			{
				return null;
			}
			RectTransform val = scrollRect.viewport;
			if ((Object)(object)val == (Object)null && (Object)(object)chatText != (Object)null)
			{
				Transform parent = ((TMP_Text)chatText).transform.parent;
				val = (RectTransform)(object)((parent is RectTransform) ? parent : null);
			}
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)scrollRect).GetComponent<RectTransform>();
			}
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Transform val2 = ((Transform)val).Find("ChatX_LinkClickOverlay");
			GameObject val3 = (((Object)(object)val2 != (Object)null) ? ((Component)val2).gameObject : null);
			if ((Object)(object)val3 == (Object)null)
			{
				val3 = new GameObject("ChatX_LinkClickOverlay", new Type[2]
				{
					typeof(RectTransform),
					typeof(Image)
				})
				{
					layer = ((Component)val).gameObject.layer
				};
				SetLayerRecursive(val3, ((Component)val).gameObject.layer);
				RectTransform component = val3.GetComponent<RectTransform>();
				((Transform)component).SetParent((Transform)(object)val, false);
				component.anchorMin = Vector2.zero;
				component.anchorMax = Vector2.one;
				component.offsetMin = Vector2.zero;
				component.offsetMax = Vector2.zero;
				((Transform)component).localScale = Vector3.one;
			}
			Image val4 = val3.GetComponent<Image>();
			if ((Object)(object)val4 == (Object)null)
			{
				val4 = val3.AddComponent<Image>();
			}
			((Graphic)val4).color = new Color(0f, 0f, 0f, 0f);
			((Graphic)val4).raycastTarget = true;
			((MaskableGraphic)val4).maskable = true;
			RectTransform component2 = val3.GetComponent<RectTransform>();
			component2.anchorMin = Vector2.zero;
			component2.anchorMax = Vector2.one;
			component2.offsetMin = Vector2.zero;
			component2.offsetMax = Vector2.zero;
			((Transform)component2).localScale = Vector3.one;
			((Transform)component2).SetAsLastSibling();
			return val3;
		}

		private static string ProtectChatLinks(string message, out List<ProtectedChatLink> protectedLinks)
		{
			protectedLinks = null;
			if (string.IsNullOrEmpty(message))
			{
				return message;
			}
			StringBuilder stringBuilder = new StringBuilder(message.Length);
			int num = 0;
			int num2 = -1;
			bool flag = false;
			for (int i = 0; i < message.Length; i++)
			{
				char c = message[i];
				if (!flag && c == '<')
				{
					AppendProtectedPlainText(stringBuilder, message, num, i - num, ref protectedLinks);
					flag = true;
					num2 = i;
				}
				else if (flag && c == '>')
				{
					stringBuilder.Append(message, num2, i - num2 + 1);
					flag = false;
					num = i + 1;
				}
			}
			if (flag && num2 >= 0)
			{
				stringBuilder.Append(message, num2, message.Length - num2);
			}
			else if (num < message.Length)
			{
				AppendProtectedPlainText(stringBuilder, message, num, message.Length - num, ref protectedLinks);
			}
			return (protectedLinks == null || protectedLinks.Count == 0) ? message : stringBuilder.ToString();
		}

		private static string RestoreProtectedChatLinks(string message, List<ProtectedChatLink> protectedLinks)
		{
			if (string.IsNullOrEmpty(message) || protectedLinks == null || protectedLinks.Count == 0)
			{
				return message;
			}
			foreach (ProtectedChatLink protectedLink in protectedLinks)
			{
				if (protectedLink != null && !string.IsNullOrEmpty(protectedLink.Token))
				{
					string newValue = "<link=\"" + protectedLink.CanonicalUrl + "\"><u>" + protectedLink.DisplayText + "</u></link>";
					message = message.Replace(protectedLink.Token, newValue, StringComparison.Ordinal);
				}
			}
			return message;
		}

		private static void AppendProtectedPlainText(StringBuilder output, string source, int startIndex, int length, ref List<ProtectedChatLink> protectedLinks)
		{
			if (length <= 0)
			{
				return;
			}
			string text = source.Substring(startIndex, length);
			int num = 0;
			foreach (Match item in UrlRegex.Matches(text))
			{
				if (!item.Success)
				{
					continue;
				}
				output.Append(text, num, item.Index - num);
				string candidate = item.Value;
				string value = TrimTrailingUrlPunctuation(ref candidate);
				if (!TryCanonicalizeUrl(candidate, out var canonicalUrl))
				{
					output.Append(item.Value);
					num = item.Index + item.Length;
					continue;
				}
				if (protectedLinks == null)
				{
					protectedLinks = new List<ProtectedChatLink>();
				}
				string text2 = $"CHATX_LINK_TOKEN_{protectedLinks.Count}_";
				protectedLinks.Add(new ProtectedChatLink
				{
					Token = text2,
					DisplayText = candidate,
					CanonicalUrl = canonicalUrl
				});
				output.Append(text2);
				if (!string.IsNullOrEmpty(value))
				{
					output.Append(value);
				}
				num = item.Index + item.Length;
			}
			if (num < text.Length)
			{
				output.Append(text, num, text.Length - num);
			}
		}

		private static string TrimTrailingUrlPunctuation(ref string candidate)
		{
			if (string.IsNullOrEmpty(candidate))
			{
				return string.Empty;
			}
			int num = candidate.Length;
			while (num > 0 && IsTrimmedUrlPunctuation(candidate[num - 1]))
			{
				num--;
			}
			string text;
			if (num >= candidate.Length)
			{
				text = string.Empty;
			}
			else
			{
				string text2 = candidate;
				int num2 = num;
				text = text2.Substring(num2, text2.Length - num2);
			}
			string result = text;
			candidate = candidate.Substring(0, num);
			return result;
		}

		private static bool IsTrimmedUrlPunctuation(char c)
		{
			if (1 == 0)
			{
			}
			bool result;
			switch (c)
			{
			case '!':
			case '"':
			case '\'':
			case ')':
			case ',':
			case '.':
			case ':':
			case ';':
			case '?':
			case ']':
			case '}':
				result = true;
				break;
			default:
				result = false;
				break;
			}
			if (1 == 0)
			{
			}
			return result;
		}

		private static bool TryCanonicalizeUrl(string value, out string canonicalUrl)
		{
			canonicalUrl = null;
			if (string.IsNullOrWhiteSpace(value))
			{
				return false;
			}
			string uriString = (value.StartsWith("www.", StringComparison.OrdinalIgnoreCase) ? ("https://" + value) : value);
			if (!Uri.TryCreate(uriString, UriKind.Absolute, out Uri result))
			{
				return false;
			}
			if (!string.Equals(result.Scheme, Uri.UriSchemeHttp, StringComparison.OrdinalIgnoreCase) && !string.Equals(result.Scheme, Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase))
			{
				return false;
			}
			canonicalUrl = result.AbsoluteUri;
			return true;
		}

		private static void SetLayerRecursive(GameObject root, int layer)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			if ((Object)(object)root == (Object)null)
			{
				return;
			}
			root.layer = layer;
			foreach (Transform item in root.transform)
			{
				Transform val = item;
				SetLayerRecursive(((Component)val).gameObject, layer);
			}
		}

		private static ChatScrollbarState GetScrollbarState(ChatBehaviourAssets assets)
		{
			if (!Object.op_Implicit((Object)(object)assets))
			{
				return null;
			}
			if (!_scrollbarStates.TryGetValue(assets, out var value))
			{
				value = new ChatScrollbarState();
				_scrollbarStates.Add(assets, value);
			}
			if ((Object)(object)value.ScrollRect == (Object)null)
			{
				value.ScrollRect = TryGetChatScrollRect(assets);
			}
			if ((Object)(object)value.Scrollbar == (Object)null || (Object)(object)value.ScrollbarObject == (Object)null || (Object)(object)value.ScrollbarComponent == (Object)null)
			{
				CanvasGroup val = TryGetScrollbarGroup(assets, value);
				if ((Object)(object)val != (Object)null)
				{
					value.Scrollbar = val;
				}
			}
			if ((Object)(object)value.ChatContainer == (Object)null)
			{
				value.ChatContainer = ResolveChatContainer(assets);
			}
			return value;
		}

		internal static void RegisterScrollbarTargets(ChatBehaviourAssets assets, ScrollRect chatScrollRect)
		{
			if (!Object.op_Implicit((Object)(object)assets))
			{
				return;
			}
			ChatScrollbarState orCreateValue = _scrollbarStates.GetOrCreateValue(assets);
			if (!((Object)(object)chatScrollRect != (Object)null))
			{
				return;
			}
			orCreateValue.ScrollRect = chatScrollRect;
			Scrollbar verticalScrollbar = chatScrollRect.verticalScrollbar;
			if ((Object)(object)verticalScrollbar != (Object)null)
			{
				orCreateValue.ScrollbarComponent = verticalScrollbar;
				orCreateValue.ScrollbarObject = ((Component)verticalScrollbar).gameObject;
				if ((Object)(object)orCreateValue.Scrollbar == (Object)null)
				{
					orCreateValue.Scrollbar = ((Component)verticalScrollbar).GetComponent<CanvasGroup>() ?? orCreateValue.ScrollbarObject.AddComponent<CanvasGroup>();
				}
			}
		}

		private static ScrollRect TryGetChatScrollRect(ChatBehaviourAssets assets)
		{
			TextMeshProUGUI val = assets?._chatText;
			if (!Object.op_Implicit((Object)(object)val))
			{
				return null;
			}
			try
			{
				return ((Component)val).GetComponentInParent<ScrollRect>();
			}
			catch
			{
				return null;
			}
		}

		private static GameObject ResolveChatContainer(ChatBehaviourAssets assets)
		{
			if (!Object.op_Implicit((Object)(object)assets))
			{
				return null;
			}
			if ((Object)(object)assets._chatboxTextGroup != (Object)null)
			{
				return ((Component)assets._chatboxTextGroup).gameObject;
			}
			Transform val = FindDescendantTransformByName(((Component)assets).transform, "_chatbox_textField");
			if ((Object)(object)val != (Object)null)
			{
				return ((Component)val).gameObject;
			}
			TextMeshProUGUI chatText = assets._chatText;
			return ((Object)(object)chatText != (Object)null) ? ((Component)chatText).gameObject : null;
		}

		private static bool ShouldHoldChatForExternalUI()
		{
			DialogManager current = DialogManager._current;
			if (Object.op_Implicit((Object)(object)current) && current._isDialogEnabled)
			{
				_dialogSuppressed = true;
				return true;
			}
			if (_dialogSuppressed)
			{
				_dialogSuppressed = false;
				pendingRestore = true;
			}
			return false;
		}

		private static void ResetChatFocus()
		{
			ChatBehaviour current = ChatBehaviour._current;
			if (!Object.op_Implicit((Object)(object)current))
			{
				return;
			}
			current._focusedInChat = false;
			ChatInputResolver.TryGet(current._chatAssets)?.Deactivate();
			if (ChatInputBufferField != null)
			{
				try
				{
					ChatInputBufferField.SetValue(current, 0f);
				}
				catch
				{
				}
			}
			else if (!_loggedMissingInputBufferField)
			{
				_loggedMissingInputBufferField = true;
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogWarning((object)"ChatX could not resolve ChatBehaviour._inputBuffer. Hidden-chat focus restoration may be limited.");
				}
			}
			current.Display_Chat(true);
			current._textFadeTimer = Mathf.Max(current._textFadeTimer, 1f);
			current._logicFadeTimer = Mathf.Max(current._logicFadeTimer, 1f);
			if (Object.op_Implicit((Object)(object)current._chatAssets))
			{
				CanvasGroup generalCanvasGroup = current._chatAssets._generalCanvasGroup;
				if (Object.op_Implicit((Object)(object)generalCanvasGroup))
				{
					generalCanvasGroup.alpha = 1f;
					generalCanvasGroup.blocksRaycasts = true;
					generalCanvasGroup.interactable = true;
				}
			}
		}

		internal static void ResetUiRuntimeState()
		{
			_dialogSuppressed = false;
			pendingRestore = false;
			_chatWasHidden = false;
			_loggedMissingInputBufferField = false;
			ChatWindowResizer.Reset();
		}

		private static void SyncChatVisibility(ChatBehaviourAssets assets, ChatScrollbarState state, bool chatHidden, bool allFaded)
		{
			if (state == null)
			{
				return;
			}
			GameObject val = state.ChatContainer;
			if ((Object)(object)val == (Object)null)
			{
				val = (state.ChatContainer = ResolveChatContainer(assets));
			}
			if ((Object)(object)val != (Object)null)
			{
				if (chatHidden)
				{
					if (!state.CachedChatContainerActive.HasValue)
					{
						state.CachedChatContainerActive = val.activeSelf;
					}
					if (val.activeSelf)
					{
						val.SetActive(false);
					}
				}
				else if (state.CachedChatContainerActive.HasValue)
				{
					bool value = state.CachedChatContainerActive.Value;
					state.CachedChatContainerActive = null;
					if (val.activeSelf != value)
					{
						val.SetActive(value);
					}
				}
			}
			GameObject val2 = assets?._chatChannelDockObject;
			if ((Object)(object)val2 != (Object)null)
			{
				if (chatHidden)
				{
					if (!state.CachedChannelDockActive.HasValue)
					{
						state.CachedChannelDockActive = val2.activeSelf;
					}
					if (val2.activeSelf)
					{
						val2.SetActive(false);
					}
				}
				else if (state.CachedChannelDockActive.HasValue)
				{
					bool value2 = state.CachedChannelDockActive.Value;
					state.CachedChannelDockActive = null;
					if (val2.activeSelf != value2)
					{
						val2.SetActive(value2);
					}
				}
			}
			CanvasGroup val3 = assets?._generalCanvasGroup;
			if ((Object)(object)val3 != (Object)null)
			{
				bool interactable = (val3.blocksRaycasts = !allFaded);
				val3.interactable = interactable;
			}
			if ((Object)(object)state.ScrollRect != (Object)null)
			{
				bool enabled = !allFaded;
				((Behaviour)state.ScrollRect).enabled = enabled;
			}
		}

		private static CanvasGroup TryGetScrollbarGroup(ChatBehaviourAssets assets, ChatScrollbarState state)
		{
			if (state == null)
			{
				return null;
			}
			ScrollRect val = (state.ScrollRect = state.ScrollRect ?? TryGetChatScrollRect(assets));
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Scrollbar verticalScrollbar = val.verticalScrollbar;
			if ((Object)(object)verticalScrollbar == (Object)null)
			{
				return null;
			}
			state.ScrollbarComponent = verticalScrollbar;
			state.ScrollbarObject = ((Component)verticalScrollbar).gameObject;
			CanvasGroup val2 = ((Component)verticalScrollbar).GetComponent<CanvasGroup>();
			if ((Object)(object)val2 == (Object)null)
			{
				val2 = state.ScrollbarObject.AddComponent<CanvasGroup>();
			}
			return val2;
		}

		private static void UpdateScrollbarState(ChatBehaviourAssets assets, ChatScrollbarState state, bool chatHidden, float visualAlpha, bool transparentOverride, bool allFaded)
		{
			if (state == null)
			{
				return;
			}
			if ((Object)(object)state.ScrollRect == (Object)null)
			{
				state.ScrollRect = TryGetChatScrollRect(assets);
			}
			if ((Object)(object)state.ScrollRect == (Object)null)
			{
				return;
			}
			if ((Object)(object)state.Scrollbar == (Object)null || (Object)(object)state.ScrollbarObject == (Object)null || (Object)(object)state.ScrollbarComponent == (Object)null)
			{
				state.Scrollbar = TryGetScrollbarGroup(assets, state);
				if ((Object)(object)state.ScrollRect == (Object)null)
				{
					return;
				}
			}
			bool flag = !chatHidden && !allFaded && ShouldShowScrollbar(state);
			float num = (transparentOverride ? 0f : visualAlpha);
			if ((Object)(object)state.Scrollbar != (Object)null)
			{
				state.Scrollbar.alpha = (flag ? num : 0f);
				state.Scrollbar.blocksRaycasts = flag;
				state.Scrollbar.interactable = flag;
			}
			if ((Object)(object)state.ScrollbarComponent != (Object)null)
			{
				((Selectable)state.ScrollbarComponent).interactable = flag;
			}
		}

		private static void UpdateEffectiveAlpha(ref float alpha, ref bool sawNonZero, float candidate)
		{
			if (candidate > 0.001f)
			{
				sawNonZero = true;
				alpha = Mathf.Min(alpha, candidate);
			}
		}

		private static bool HasExternalHudOverlay(ChatBehaviourAssets assets)
		{
			TextMeshProUGUI val = assets?._triggerMessageText;
			return (Object)(object)val != (Object)null && ((Behaviour)val).enabled && ((Component)val).gameObject.activeInHierarchy && !string.IsNullOrWhiteSpace(((TMP_Text)val).text);
		}

		private static bool ShouldShowScrollbar(ChatScrollbarState state)
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			ScrollRect val = state?.ScrollRect;
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			RectTransform content = val.content;
			RectTransform val2 = (((Object)(object)val.viewport != (Object)null) ? val.viewport : ((Component)val).GetComponent<RectTransform>());
			if ((Object)(object)content == (Object)null || (Object)(object)val2 == (Object)null)
			{
				return false;
			}
			Rect rect = content.rect;
			float num = ((Rect)(ref rect)).height;
			rect = val2.rect;
			float height = ((Rect)(ref rect)).height;
			if (num <= 0f)
			{
				num = content.sizeDelta.y;
			}
			return num - height > 1f;
		}

		internal static void ApplyOpacityCap(ChatBehaviourAssets assets, bool force = false)
		{
			if (!Object.op_Implicit((Object)(object)assets))
			{
				return;
			}
			bool flag = ShouldHoldChatForExternalUI();
			bool flag2 = _chatHidden || flag;
			bool chatWasHidden = _chatWasHidden;
			_chatWasHidden = flag2;
			if (chatWasHidden && !flag2)
			{
				pendingRestore = true;
			}
			bool flag3 = pendingRestore && !flag2;
			if (flag3)
			{
				pendingRestore = false;
			}
			float num = (flag2 ? 0f : Mathf.Clamp01(chatOpacity?.Value ?? 1f));
			float alpha = num;
			bool sawNonZero = false;
			CanvasGroup generalCanvasGroup = assets._generalCanvasGroup;
			float num2 = (flag2 ? 0f : 1f);
			CanvasGroup[] chatTextGroups = assets._chatTextGroups;
			if (chatTextGroups != null)
			{
				foreach (CanvasGroup val in chatTextGroups)
				{
					if (Object.op_Implicit((Object)(object)val))
					{
						float alpha2 = val.alpha;
						float num3 = (flag2 ? 0f : (flag3 ? num : Mathf.Min(alpha2, num)));
						if (force || flag3 || !Mathf.Approximately(alpha2, num3))
						{
							val.alpha = num3;
						}
						UpdateEffectiveAlpha(ref alpha, ref sawNonZero, val.alpha);
					}
				}
			}
			if (Object.op_Implicit((Object)(object)assets._chatboxTextGroup))
			{
				float alpha3 = assets._chatboxTextGroup.alpha;
				float num4 = (flag2 ? 0f : (flag3 ? num : Mathf.Min(alpha3, num)));
				if (force || flag3 || !Mathf.Approximately(alpha3, num4))
				{
					assets._chatboxTextGroup.alpha = num4;
				}
				UpdateEffectiveAlpha(ref alpha, ref sawNonZero, assets._chatboxTextGroup.alpha);
			}
			if (Object.op_Implicit((Object)(object)assets._gameLogicGroup))
			{
				float alpha4 = assets._gameLogicGroup.alpha;
				float num5 = (flag2 ? 0f : (flag3 ? num : Mathf.Min(alpha4, num)));
				if (force || flag3 || !Mathf.Approximately(alpha4, num5))
				{
					assets._gameLogicGroup.alpha = num5;
				}
				UpdateEffectiveAlpha(ref alpha, ref sawNonZero, assets._gameLogicGroup.alpha);
			}
			bool flag4 = flag2 || !sawNonZero;
			bool flag5 = HasExternalHudOverlay(assets);
			if (flag4)
			{
				alpha = 0f;
			}
			alpha = Mathf.Clamp01(alpha);
			bool transparentOverride = transparentScrollbar?.Value ?? false;
			if (Object.op_Implicit((Object)(object)generalCanvasGroup))
			{
				float num6 = (flag5 ? 1f : (flag4 ? 0f : num2));
				if (force || !Mathf.Approximately(generalCanvasGroup.alpha, num6))
				{
					generalCanvasGroup.alpha = num6;
				}
				bool flag6 = !flag4;
				if (generalCanvasGroup.blocksRaycasts != flag6)
				{
					generalCanvasGroup.blocksRaycasts = flag6;
				}
				if (generalCanvasGroup.interactable != flag6)
				{
					generalCanvasGroup.interactable = flag6;
				}
			}
			ChatScrollbarState scrollbarState = GetScrollbarState(assets);
			if (scrollbarState != null)
			{
				UpdateScrollbarState(assets, scrollbarState, flag2, alpha, transparentOverride, flag4);
				SyncChatVisibility(assets, scrollbarState, flag2, flag4);
			}
		}

		public static void ClearChatNow()
		{
			ChatBehaviour val = Player._mainPlayer?._chatBehaviour;
			ChatBehaviourAssets val2 = val?._chatAssets;
			if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val2))
			{
				val._chatMessages?.Clear();
				if (Object.op_Implicit((Object)(object)val2._chatText))
				{
					((TMP_Text)val2._chatText).text = string.Empty;
				}
				ApplyOpacityCap(val2);
			}
		}

		public static void ClearGameFeedNow()
		{
			ChatBehaviour val = Player._mainPlayer?._chatBehaviour;
			ChatBehaviourAssets val2 = val?._chatAssets;
			if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val2))
			{
				val._gameLogicMessages?.Clear();
				if (Object.op_Implicit((Object)(object)val2._gameLogicText))
				{
					((TMP_Text)val2._gameLogicText).text = string.Empty;
				}
				ApplyOpacityCap(val2);
			}
		}

		public static void ClearAllNow()
		{
			ClearChatNow();
			ClearGameFeedNow();
		}

		private static void TryHandleHotkeys()
		{
			//IL_003a: 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_0040: 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_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_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			Player mainPlayer = Player._mainPlayer;
			if (Object.op_Implicit((Object)(object)mainPlayer))
			{
				bool flag = ChatInputResolver.TryGetCurrent()?.IsFocused ?? false;
				ConfigEntry<KeyCode> obj = clearChatKey;
				KeyCode val = (KeyCode)((obj != null) ? ((int)obj.Value) : 0);
				if ((int)val != 0 && !flag && Input.GetKeyDown(val))
				{
					ClearAllNow();
				}
				ConfigEntry<KeyCode> obj2 = toggleChatVisibilityKey;
				KeyCode val2 = (KeyCode)((obj2 != null) ? ((int)obj2.Value) : 0);
				if ((int)val2 != 0 && !flag && Input.GetKeyDown(val2))
				{
					_chatHidden = !_chatHidden;
					ChatBehaviourAssets assets = mainPlayer?._chatBehaviour?._chatAssets ?? ChatBehaviourAssets._current;
					ApplyOpacityCap(assets, force: true);
				}
			}
		}

		private static bool ShouldPushGameFeed()
		{
			return pushGameMessage?.Value ?? false;
		}

		private static string StripRichTextTags(string message)
		{
			if (string.IsNullOrEmpty(message))
			{
				return message;
			}
			StringBuilder stringBuilder = new StringBuilder(message.Length);
			bool flag = false;
			foreach (char c in message)
			{
				if (c == '<')
				{
					flag = true;
				}
				else if (c == '>' && flag)
				{
					flag = false;
				}
				else if (!flag)
				{
					stringBuilder.Append(c);
				}
			}
			return stringBuilder.ToString();
		}

		internal static void RouteWaypointAttuneMessage(ChatBehaviour chat, string message)
		{
			if (!ShouldPushGameFeed())
			{
				if (chat != null)
				{
					chat.New_ChatMessage(message);
				}
			}
			else if (Object.op_Implicit((Object)(object)chat) && !string.IsNullOrEmpty(message))
			{
				PushGameFeedMessage(chat, StripRichTextTags(message));
			}
		}

		internal static void PushGameFeedMessage(ChatBehaviour chat, string message)
		{
			if (Object.op_Implicit((Object)(object)chat) && !string.IsNullOrEmpty(message))
			{
				if (ShouldPushGameFeed())
				{
					chat.Init_GameLogicMessage(message);
				}
				else
				{
					chat.New_ChatMessage(message);
				}
			}
		}

		internal static void PushTargetedGameFeedMessage(ChatBehaviour chat, string message)
		{
			if (Object.op_Implicit((Object)(object)chat) && !string.IsNullOrEmpty(message))
			{
				if (ShouldPushGameFeed())
				{
					chat.Target_GameLogicMessage(message);
				}
				else
				{
					chat.Target_RecieveMessage(message);
				}
			}
		}

		private void Awake()
		{
			//IL_001e: Unknown result