Decompiled source of PeakTextChatCN v1.0.1

PeakTextChatCN.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using UnityEngine.UI.ProceduralImage;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("PeakTextChatCN")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("PeakTextChatCN")]
[assembly: AssemblyTitle("PeakTextChatCN")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace PeakTextChatCN
{
	[BepInPlugin("com.github.peaktextchatcn", "文本聊天", "1.0.1")]
	public class Plugin : BaseUnityPlugin
	{
		internal static class PluginInfo
		{
			public const string PLUGIN_GUID = "com.github.peaktextchatcn";

			public const string PLUGIN_NAME = "文本聊天";

			public const string PLUGIN_VERSION = "1.0.1";
		}

		internal static ConfigEntry<bool> ConfigEnabled;

		internal static ConfigEntry<KeyCode> ConfigChatKey;

		internal static ConfigEntry<float> ConfigChatX;

		internal static ConfigEntry<float> ConfigChatY;

		internal static ConfigEntry<float> ConfigChatW;

		internal static ConfigEntry<float> ConfigChatH;

		internal static ConfigEntry<float> ConfigChatFontSize;

		internal static ConfigEntry<float> ConfigChatBgAlpha;

		internal static ConfigEntry<float> ConfigChatBoxHideDelay;

		internal static ConfigEntry<bool> ConfigContinuousMode;

		private Harmony _harmony;

		internal static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			ConfigEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("聊天", "启用聊天", true, "启用多人文字聊天功能");
			ConfigChatKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("聊天", "聊天快捷键", (KeyCode)47, "打开聊天输入框的按键");
			ConfigChatX = ((BaseUnityPlugin)this).Config.Bind<float>("聊天", "X坐标", 20f, "聊天窗口左下角X坐标");
			ConfigChatY = ((BaseUnityPlugin)this).Config.Bind<float>("聊天", "Y坐标", 20f, "聊天窗口左下角Y坐标");
			ConfigChatW = ((BaseUnityPlugin)this).Config.Bind<float>("聊天", "宽度", 420f, "聊天窗口宽度");
			ConfigChatH = ((BaseUnityPlugin)this).Config.Bind<float>("聊天", "高度", 300f, "聊天窗口高度");
			ConfigChatFontSize = ((BaseUnityPlugin)this).Config.Bind<float>("聊天", "字体大小", 18f, "聊天文字大小");
			ConfigChatBgAlpha = ((BaseUnityPlugin)this).Config.Bind<float>("聊天", "背景透明度", 0.3f, "聊天背景不透明度(0-1)");
			ConfigChatBoxHideDelay = ((BaseUnityPlugin)this).Config.Bind<float>("聊天", "聊天框消失延迟", 0f, "无操作多少秒后聊天框自动隐藏(0=永不消失)");
			ConfigContinuousMode = ((BaseUnityPlugin)this).Config.Bind<bool>("聊天", "连续输入模式", false, "回车发言后不关闭输入框,空输入时回车关闭");
			_harmony = new Harmony("com.github.peaktextchatcn");
			_harmony.PatchAll(typeof(GUIManagerPatch));
			((BaseUnityPlugin)this).Config.SettingChanged += OnSettingChanged;
			Log.LogInfo((object)"PeakTextChatCN v1.0.1 loaded.");
		}

		private void OnSettingChanged(object sender, SettingChangedEventArgs e)
		{
			//IL_003b: 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: Expected O, but got Unknown
			if ((object)e.ChangedSetting == ConfigEnabled)
			{
				if (ConfigEnabled.Value)
				{
					if ((Object)(object)TextChatController.Instance == (Object)null && (Object)(object)GUIManager.instance != (Object)null)
					{
						GameObject val = new GameObject("TextChatController");
						Object.DontDestroyOnLoad((Object)val);
						val.AddComponent<TextChatController>();
					}
				}
				else if ((Object)(object)TextChatController.Instance != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)TextChatController.Instance).gameObject);
				}
				Log.LogInfo((object)("[Config] 聊天 " + (ConfigEnabled.Value ? "已启用" : "已关闭")));
			}
			else if ((object)e.ChangedSetting == ConfigChatX || (object)e.ChangedSetting == ConfigChatY || (object)e.ChangedSetting == ConfigChatW || (object)e.ChangedSetting == ConfigChatH || (object)e.ChangedSetting == ConfigChatFontSize || (object)e.ChangedSetting == ConfigChatBgAlpha || (object)e.ChangedSetting == ConfigChatBoxHideDelay || (object)e.ChangedSetting == ConfigChatKey || (object)e.ChangedSetting == ConfigContinuousMode)
			{
				TextChatController.Instance?.ApplyConfig();
			}
		}

		private void OnDestroy()
		{
			((BaseUnityPlugin)this).Config.SettingChanged -= OnSettingChanged;
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	[HarmonyPatch(typeof(GUIManager), "Start")]
	public static class GUIManagerPatch
	{
		[HarmonyPostfix]
		public static void Postfix()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			if (Plugin.ConfigEnabled.Value && (Object)(object)TextChatController.Instance == (Object)null)
			{
				GameObject val = new GameObject("TextChatController");
				Object.DontDestroyOnLoad((Object)val);
				val.AddComponent<TextChatController>();
			}
		}
	}
	public class TextChatController : MonoBehaviour
	{
		[HarmonyPatch(typeof(GUIManager), "UpdateWindowStatus")]
		private static class InputBlockPatch
		{
			[HarmonyPostfix]
			public static void Postfix()
			{
				TextChatController instance = Instance;
				if (!((Object)(object)instance == (Object)null) && instance.IsInputBlocked())
				{
					GUIManager instance2 = GUIManager.instance;
					if ((Object)(object)instance2 != (Object)null)
					{
						instance2.windowBlockingInput = true;
					}
				}
			}
		}

		[HarmonyPatch(typeof(GUIManager), "UpdatePaused")]
		private static class PauseBlockPatch
		{
			[HarmonyPrefix]
			public static bool Prefix(GUIManager __instance)
			{
				TextChatController instance = Instance;
				if ((Object)(object)instance != (Object)null && instance.IsInputBlocked() && (Object)(object)__instance.pauseMenu != (Object)null && !__instance.pauseMenu.activeSelf)
				{
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(CinemaCamera), "Update")]
		private static class CinemaCamPatch
		{
			[HarmonyPrefix]
			public static bool Prefix()
			{
				TextChatController instance = Instance;
				if (!((Object)(object)instance == (Object)null))
				{
					return !instance.IsInputBlocked();
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(Character), "UpdateVariablesFixed")]
		private static class InteractBlockPatch
		{
			[HarmonyPrefix]
			public static void Prefix(Character __instance)
			{
				TextChatController instance = Instance;
				if ((Object)(object)instance != (Object)null && instance.IsInputBlocked() && (Object)(object)__instance.input != (Object)null)
				{
					__instance.input.interactIsPressed = false;
				}
			}
		}

		private const byte EVT_CODE = 81;

		private const byte PROTOCOL_V = 1;

		private const byte TYPE_CHAT = 0;

		private const int MAX_MSG = 50;

		private const float INPUT_HEIGHT = 36f;

		private const float PLACEHOLDER_ALPHA = 0.4f;

		private const string PLACEHOLDER_MSG = "按 / 聊天...";

		private Canvas _canvas;

		private GameObject _root;

		private RectTransform _rootRt;

		private TMP_InputField _input;

		private ScrollRect _scroll;

		private Transform _msgParent;

		private TMP_FontAsset _font;

		private TextMeshProUGUI _placeholderText;

		private bool _typing;

		private int _framesSinceBlock = 100;

		private float _typingStartTime;

		private readonly List<GameObject> _msgs = new List<GameObject>();

		private readonly Dictionary<int, string> _names = new Dictionary<int, string>();

		private readonly Dictionary<int, bool> _alive = new Dictionary<int, bool>();

		private readonly Dictionary<int, bool> _knocked = new Dictionary<int, bool>();

		private bool _firstFrame = true;

		private bool _rebuilding;

		private float _reinitTimer;

		private float _lastActivityTime;

		private float _chatBoxAlpha = 1f;

		private Harmony _harmony;

		private bool _loggedRunning;

		internal static TextChatController Instance { get; private set; }

		private void Awake()
		{
			Instance = this;
			((MonoBehaviour)this).StartCoroutine(Init());
		}

		private IEnumerator Init()
		{
			yield return (object)new WaitForSeconds(2f);
			if ((Object)(object)GUIManager.instance == (Object)null)
			{
				yield return (object)new WaitForSeconds(3f);
				if ((Object)(object)GUIManager.instance == (Object)null)
				{
					Plugin.Log.LogError((object)"[Chat] GUIManager null");
					Object.Destroy((Object)(object)((Component)this).gameObject);
					yield break;
				}
			}
			try
			{
				if ((Object)(object)_canvas == (Object)null)
				{
					BuildUI();
					EnsureInputModule();
				}
				PhotonNetwork.NetworkingClient.EventReceived += OnEvent;
				SceneManager.sceneLoaded += OnSceneLoaded;
				_harmony = new Harmony("com.github.peaktextchatcn.input");
				_harmony.PatchAll(typeof(InputBlockPatch));
				_harmony.PatchAll(typeof(PauseBlockPatch));
				_harmony.PatchAll(typeof(CinemaCamPatch));
				_harmony.PatchAll(typeof(InteractBlockPatch));
				Plugin.Log.LogInfo((object)"[Chat] Initialized.");
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"[Chat] Init: {arg}");
			}
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			Plugin.Log.LogInfo((object)("[Chat] Scene loaded: " + ((Scene)(ref scene)).name + ", rebuilding UI..."));
			((MonoBehaviour)this).StartCoroutine(RebuildUI());
		}

		private IEnumerator RebuildUI()
		{
			_rebuilding = true;
			yield return (object)new WaitForSeconds(2f);
			if ((Object)(object)GUIManager.instance?.hudCanvas == (Object)null)
			{
				yield return (object)new WaitForSeconds(3f);
				if ((Object)(object)GUIManager.instance?.hudCanvas == (Object)null)
				{
					Plugin.Log.LogWarning((object)"[Chat] GUIManager still null after scene load");
					_rebuilding = false;
					yield break;
				}
			}
			CleanupUI();
			_names.Clear();
			_alive.Clear();
			_knocked.Clear();
			_firstFrame = true;
			_typing = false;
			_framesSinceBlock = 100;
			BuildUI();
			EnsureInputModule();
			_rebuilding = false;
			Plugin.Log.LogInfo((object)"[Chat] UI rebuilt after scene transition.");
		}

		private void EnsureInputModule()
		{
			EventSystem current = EventSystem.current;
			if ((Object)(object)current == (Object)null)
			{
				Plugin.Log.LogWarning((object)"[Chat] No EventSystem found!");
				return;
			}
			BaseInputModule[] components = ((Component)current).GetComponents<BaseInputModule>();
			bool flag = false;
			BaseInputModule[] array = components;
			foreach (BaseInputModule val in array)
			{
				Plugin.Log.LogInfo((object)("[Chat] EventSystem module: " + ((object)val).GetType().Name));
				if (val is StandaloneInputModule)
				{
					flag = true;
				}
			}
			if (!flag)
			{
				Plugin.Log.LogInfo((object)"[Chat] Adding StandaloneInputModule for TMP_InputField compatibility");
				((Component)current).gameObject.AddComponent<StandaloneInputModule>();
			}
		}

		private void BuildUI()
		{
			//IL_0024: 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)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Expected O, but got Unknown
			//IL_0118: 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_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Expected O, but got Unknown
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: Expected O, but got Unknown
			//IL_029e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0319: Unknown result type (might be due to invalid IL or missing references)
			//IL_0323: Expected O, but got Unknown
			GUIManager instance = GUIManager.instance;
			TextMeshProUGUI heroDayText = instance.heroDayText;
			_font = ((heroDayText != null) ? ((TMP_Text)heroDayText).font : null);
			_canvas = new GameObject("ChatCanvas").AddComponent<Canvas>();
			((Component)_canvas).transform.SetParent(((Component)instance).transform, false);
			_canvas.renderMode = (RenderMode)0;
			_canvas.sortingOrder = 10;
			CanvasScaler obj = ((Component)_canvas).gameObject.AddComponent<CanvasScaler>();
			obj.uiScaleMode = (ScaleMode)1;
			obj.referenceResolution = new Vector2(1920f, 1080f);
			obj.matchWidthOrHeight = 1f;
			((Component)_canvas).gameObject.AddComponent<GraphicRaycaster>();
			Plugin.Log.LogInfo((object)("[Chat] Canvas parent=" + ((Object)((Component)instance).gameObject).name + ", renderMode=ScreenSpaceOverlay"));
			_root = new GameObject("ChatRoot");
			_rootRt = _root.AddComponent<RectTransform>();
			((Transform)_rootRt).SetParent(((Component)_canvas).transform, false);
			RectTransform rootRt = _rootRt;
			RectTransform rootRt2 = _rootRt;
			Vector2 val = (_rootRt.pivot = Vector2.zero);
			Vector2 anchorMin = (rootRt2.anchorMax = val);
			rootRt.anchorMin = anchorMin;
			_rootRt.anchoredPosition = new Vector2(Plugin.ConfigChatX.Value, Plugin.ConfigChatY.Value);
			_rootRt.sizeDelta = new Vector2(Plugin.ConfigChatW.Value, Plugin.ConfigChatH.Value);
			CanvasGroup obj2 = _root.AddComponent<CanvasGroup>();
			obj2.blocksRaycasts = true;
			obj2.interactable = true;
			ProceduralImage obj3 = _root.AddComponent<ProceduralImage>();
			obj3.ModifierType = typeof(UniformModifier);
			UniformModifier component = ((Component)obj3).GetComponent<UniformModifier>();
			if ((Object)(object)component != (Object)null)
			{
				component.Radius = 12f;
			}
			((Graphic)obj3).color = new Color(0f, 0f, 0f, Plugin.ConfigChatBgAlpha.Value);
			GameObject val3 = new GameObject("ScrollView");
			RectTransform val4 = val3.AddComponent<RectTransform>();
			((Transform)val4).SetParent(_root.transform, false);
			val4.anchorMin = Vector2.zero;
			val4.anchorMax = Vector2.one;
			val4.pivot = new Vector2(0.5f, 1f);
			val4.offsetMin = new Vector2(4f, 40f);
			val4.offsetMax = new Vector2(-4f, -4f);
			val3.AddComponent<RectMask2D>();
			GameObject val5 = new GameObject("Content");
			RectTransform val6 = val5.AddComponent<RectTransform>();
			((Transform)val6).SetParent(val3.transform, false);
			val6.anchorMin = new Vector2(0f, 0f);
			val6.anchorMax = new Vector2(1f, 0f);
			val6.pivot = new Vector2(0.5f, 0f);
			val6.sizeDelta = Vector2.zero;
			VerticalLayoutGroup obj4 = val5.AddComponent<VerticalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)obj4).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj4).childForceExpandHeight = false;
			((HorizontalOrVerticalLayoutGroup)obj4).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj4).childForceExpandWidth = true;
			((LayoutGroup)obj4).childAlignment = (TextAnchor)7;
			((HorizontalOrVerticalLayoutGroup)obj4).spacing = 2f;
			((LayoutGroup)obj4).padding = new RectOffset(4, 4, 2, 2);
			val5.AddComponent<ContentSizeFitter>().verticalFit = (FitMode)2;
			_scroll = val3.AddComponent<ScrollRect>();
			_scroll.content = val6;
			_scroll.viewport = val4;
			_scroll.horizontal = false;
			_scroll.vertical = true;
			_scroll.movementType = (MovementType)2;
			_scroll.verticalNormalizedPosition = 0f;
			_msgParent = val5.transform;
			BuildInput(_root.transform);
			_lastActivityTime = Time.time;
			_chatBoxAlpha = 1f;
		}

		private void BuildInput(Transform parent)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: 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_00dd: Expected O, but got Unknown
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: 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_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: 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_0237: 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_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			//IL_0344: Unknown result type (might be due to invalid IL or missing references)
			//IL_0349: Unknown result type (might be due to invalid IL or missing references)
			//IL_034d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0359: Unknown result type (might be due to invalid IL or missing references)
			//IL_0365: Unknown result type (might be due to invalid IL or missing references)
			//IL_0371: Unknown result type (might be due to invalid IL or missing references)
			//IL_037d: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a5: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("InputField");
			RectTransform obj = val.AddComponent<RectTransform>();
			((Transform)obj).SetParent(parent, false);
			obj.anchorMin = new Vector2(0f, 0f);
			obj.anchorMax = new Vector2(1f, 0f);
			obj.pivot = new Vector2(0.5f, 0f);
			obj.anchoredPosition = new Vector2(0f, 4f);
			obj.sizeDelta = new Vector2(-8f, 36f);
			ProceduralImage val2 = val.AddComponent<ProceduralImage>();
			val2.ModifierType = typeof(UniformModifier);
			UniformModifier component = ((Component)val2).GetComponent<UniformModifier>();
			if ((Object)(object)component != (Object)null)
			{
				component.Radius = 8f;
			}
			((Graphic)val2).color = new Color(0f, 0f, 0f, 0.4f);
			GameObject val3 = new GameObject("Text Area");
			RectTransform val4 = val3.AddComponent<RectTransform>();
			((Transform)val4).SetParent(val.transform, false);
			val4.anchorMin = Vector2.zero;
			val4.anchorMax = Vector2.one;
			val4.offsetMin = new Vector2(8f, 4f);
			val4.offsetMax = new Vector2(-8f, -4f);
			val3.AddComponent<RectMask2D>();
			GameObject val5 = new GameObject("Placeholder");
			RectTransform obj2 = val5.AddComponent<RectTransform>();
			((Transform)obj2).SetParent(val3.transform, false);
			obj2.anchorMin = Vector2.zero;
			obj2.anchorMax = Vector2.one;
			Vector2 offsetMin = (obj2.offsetMax = Vector2.zero);
			obj2.offsetMin = offsetMin;
			TextMeshProUGUI val6 = val5.AddComponent<TextMeshProUGUI>();
			if ((Object)(object)_font != (Object)null)
			{
				((TMP_Text)val6).font = _font;
			}
			((TMP_Text)val6).fontSize = Plugin.ConfigChatFontSize.Value - 2f;
			((Graphic)val6).color = new Color(1f, 1f, 1f, 0.4f);
			((TMP_Text)val6).text = "按 / 聊天...";
			((TMP_Text)val6).enableWordWrapping = false;
			((TMP_Text)val6).extraPadding = true;
			_placeholderText = val6;
			GameObject val7 = new GameObject("Text");
			RectTransform obj3 = val7.AddComponent<RectTransform>();
			((Transform)obj3).SetParent(val3.transform, false);
			obj3.anchorMin = Vector2.zero;
			obj3.anchorMax = Vector2.one;
			offsetMin = (obj3.offsetMax = Vector2.zero);
			obj3.offsetMin = offsetMin;
			TextMeshProUGUI val8 = val7.AddComponent<TextMeshProUGUI>();
			if ((Object)(object)_font != (Object)null)
			{
				((TMP_Text)val8).font = _font;
			}
			((TMP_Text)val8).fontSize = Plugin.ConfigChatFontSize.Value;
			((Graphic)val8).color = Color.white;
			((TMP_Text)val8).enableWordWrapping = false;
			((TMP_Text)val8).extraPadding = true;
			_input = val.AddComponent<TMP_InputField>();
			_input.textViewport = val4;
			_input.textComponent = (TMP_Text)(object)val8;
			_input.placeholder = (Graphic)(object)val6;
			((Selectable)_input).image = (Image)(object)val2;
			_input.pointSize = Plugin.ConfigChatFontSize.Value;
			_input.lineType = (LineType)0;
			((UnityEvent<string>)(object)_input.onEndEdit).AddListener((UnityAction<string>)OnSubmit);
			((UnityEvent<string>)(object)_input.onValueChanged).AddListener((UnityAction<string>)OnTextChanged);
			_input.onFocusSelectAll = false;
			ColorBlock colors = ((Selectable)_input).colors;
			((ColorBlock)(ref colors)).normalColor = Color.white;
			((ColorBlock)(ref colors)).highlightedColor = Color.white;
			((ColorBlock)(ref colors)).pressedColor = Color.white;
			((ColorBlock)(ref colors)).selectedColor = Color.white;
			((ColorBlock)(ref colors)).disabledColor = Color.gray;
			((ColorBlock)(ref colors)).fadeDuration = 0f;
			((ColorBlock)(ref colors)).colorMultiplier = 1f;
			((Selectable)_input).colors = colors;
		}

		private void AddMsg(string text, Color color)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Msg");
			((Transform)val.AddComponent<RectTransform>()).SetParent(_msgParent, false);
			val.AddComponent<LayoutElement>().flexibleWidth = 1f;
			TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>();
			if ((Object)(object)_font != (Object)null)
			{
				((TMP_Text)val2).font = _font;
			}
			((TMP_Text)val2).fontSize = Plugin.ConfigChatFontSize.Value;
			((Graphic)val2).color = color;
			((TMP_Text)val2).enableWordWrapping = true;
			((TMP_Text)val2).richText = true;
			((Graphic)val2).raycastTarget = false;
			((TMP_Text)val2).text = text;
			_msgs.Add(val);
			while (_msgs.Count > 50)
			{
				if ((Object)(object)_msgs[0] != (Object)null)
				{
					Object.Destroy((Object)(object)_msgs[0]);
				}
				_msgs.RemoveAt(0);
			}
			_scroll.verticalNormalizedPosition = 0f;
			Canvas.ForceUpdateCanvases();
			Transform msgParent = _msgParent;
			LayoutRebuilder.ForceRebuildLayoutImmediate((RectTransform)(object)((msgParent is RectTransform) ? msgParent : null));
			_scroll.verticalNormalizedPosition = 0f;
			_lastActivityTime = Time.time;
			_chatBoxAlpha = 1f;
			SetChatBoxAlpha(1f);
		}

		private void AddSysMsg(string text)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			AddMsg("[系统] " + text, new Color(0.6f, 0.6f, 0.6f));
		}

		private void OnTextChanged(string text)
		{
			UpdateImeCursorPos();
		}

		private void SetPlaceholderText(bool visible)
		{
			if (!((Object)(object)_placeholderText == (Object)null))
			{
				((TMP_Text)_placeholderText).text = (visible ? "按 / 聊天..." : "");
			}
		}

		private void UpdateImeCursorPos()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_input == (Object)null)
			{
				return;
			}
			try
			{
				RectTransform component = ((Component)_input).GetComponent<RectTransform>();
				if (!((Object)(object)component == (Object)null))
				{
					Vector2 val = RectTransformUtility.WorldToScreenPoint((Camera)null, ((Transform)component).position);
					float num = 0f;
					if ((Object)(object)_input.textComponent != (Object)null && !string.IsNullOrEmpty(_input.text))
					{
						num = _input.textComponent.preferredWidth;
					}
					Input.compositionCursorPos = new Vector2(val.x + num, (float)Screen.height - val.y);
				}
			}
			catch
			{
			}
		}

		private void OnSubmit(string text)
		{
			//IL_004e: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
			if (!string.IsNullOrWhiteSpace(text))
			{
				SendMsg(text);
				Character localCharacter = Character.localCharacter;
				Color? obj;
				if (localCharacter == null)
				{
					obj = null;
				}
				else
				{
					CharacterRefs refs = localCharacter.refs;
					if (refs == null)
					{
						obj = null;
					}
					else
					{
						CharacterCustomization customization = refs.customization;
						obj = ((customization != null) ? new Color?(customization.PlayerColor) : ((Color?)null));
					}
				}
				Color val = (Color)(((??)obj) ?? Color.white);
				AddMsg("<#" + ColorUtility.ToHtmlStringRGB(val) + ">" + PhotonNetwork.NickName + "</color>: " + text, Color.white);
			}
			if (Plugin.ConfigContinuousMode.Value && !string.IsNullOrWhiteSpace(text))
			{
				if ((Object)(object)_input != (Object)null)
				{
					_input.text = "";
				}
				_typing = true;
				_framesSinceBlock = 0;
				_typingStartTime = Time.unscaledTime;
				((MonoBehaviour)this).StartCoroutine(ReactivateInput());
				return;
			}
			_typing = false;
			_framesSinceBlock = 10;
			if ((Object)(object)_input != (Object)null)
			{
				_input.text = "";
			}
			SetPlaceholderText(visible: true);
			if ((Object)(object)EventSystem.current != (Object)null)
			{
				EventSystem.current.SetSelectedGameObject((GameObject)null);
			}
		}

		private IEnumerator ReactivateInput()
		{
			yield return null;
			if ((Object)(object)_input != (Object)null)
			{
				_lastActivityTime = Time.time;
				_input.ActivateInputField();
				SetPlaceholderText(visible: false);
				if ((Object)(object)EventSystem.current != (Object)null)
				{
					EventSystem.current.SetSelectedGameObject(((Component)_input).gameObject);
				}
				UpdateImeCursorPos();
			}
		}

		private void SendMsg(string text)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			PhotonNetwork.RaiseEvent((byte)81, (object)new object[4]
			{
				(byte)1,
				(byte)0,
				PhotonNetwork.NickName,
				text
			}, RaiseEventOptions.Default, SendOptions.SendReliable);
		}

		private void OnEvent(EventData data)
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: 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)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			if (data.Code != 81 || !(data.CustomData is object[] array) || array.Length < 4 || !(array[0] is byte b) || b < 1 || !(array[2] is string text) || !(array[3] is string text2))
			{
				return;
			}
			Character obj = FindCharByNick(text);
			Color? obj2;
			if (obj == null)
			{
				obj2 = null;
			}
			else
			{
				CharacterRefs refs = obj.refs;
				if (refs == null)
				{
					obj2 = null;
				}
				else
				{
					CharacterCustomization customization = refs.customization;
					obj2 = ((customization != null) ? new Color?(customization.PlayerColor) : ((Color?)null));
				}
			}
			Color val = (Color)(((??)obj2) ?? Color.white);
			AddMsg("<#" + ColorUtility.ToHtmlStringRGB(val) + ">" + text + "</color>: " + text2, Color.white);
		}

		private static Character FindCharByNick(string nick)
		{
			if (Character.AllCharacters == null)
			{
				return null;
			}
			foreach (Character allCharacter in Character.AllCharacters)
			{
				if ((Object)(object)allCharacter != (Object)null && allCharacter.characterName == nick)
				{
					return allCharacter;
				}
			}
			return null;
		}

		public void ApplyConfig()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_rootRt != (Object)null))
			{
				return;
			}
			_rootRt.anchoredPosition = new Vector2(Plugin.ConfigChatX.Value, Plugin.ConfigChatY.Value);
			_rootRt.sizeDelta = new Vector2(Plugin.ConfigChatW.Value, Plugin.ConfigChatH.Value);
			ProceduralImage component = _root.GetComponent<ProceduralImage>();
			if ((Object)(object)component != (Object)null)
			{
				((Graphic)component).color = new Color(0f, 0f, 0f, Plugin.ConfigChatBgAlpha.Value);
			}
			float value = Plugin.ConfigChatFontSize.Value;
			if ((Object)(object)_input != (Object)null)
			{
				_input.pointSize = value;
				if ((Object)(object)_input.textComponent != (Object)null)
				{
					_input.textComponent.fontSize = value;
				}
				if ((Object)(object)_placeholderText != (Object)null)
				{
					((TMP_Text)_placeholderText).fontSize = value - 2f;
				}
			}
			foreach (GameObject msg in _msgs)
			{
				if ((Object)(object)msg != (Object)null)
				{
					TextMeshProUGUI component2 = msg.GetComponent<TextMeshProUGUI>();
					if ((Object)(object)component2 != (Object)null)
					{
						((TMP_Text)component2).fontSize = value;
					}
				}
			}
			ProceduralImage[] componentsInChildren = _root.GetComponentsInChildren<ProceduralImage>(true);
			foreach (ProceduralImage obj in componentsInChildren)
			{
				((Graphic)obj).SetVerticesDirty();
				((Graphic)obj).SetLayoutDirty();
			}
			if ((Object)(object)_canvas != (Object)null)
			{
				Canvas.ForceUpdateCanvases();
			}
		}

		internal bool IsInputBlocked()
		{
			if (!_typing)
			{
				return _framesSinceBlock <= 1;
			}
			return true;
		}

		private void ActivateInput()
		{
			_typing = true;
			_framesSinceBlock = 0;
			_typingStartTime = Time.unscaledTime;
			_lastActivityTime = Time.time;
			_chatBoxAlpha = 1f;
			SetChatBoxAlpha(1f);
			if ((Object)(object)_input != (Object)null)
			{
				_input.text = "";
				_input.ActivateInputField();
				SetPlaceholderText(visible: false);
				if ((Object)(object)EventSystem.current != (Object)null)
				{
					EventSystem.current.SetSelectedGameObject(((Component)_input).gameObject);
				}
				UpdateImeCursorPos();
			}
		}

		private void HandleInput()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			if (Input.GetKeyDown(Plugin.ConfigChatKey.Value) && !_typing)
			{
				ActivateInput();
			}
			else
			{
				if (!_typing)
				{
					return;
				}
				if (Input.GetKeyDown((KeyCode)27))
				{
					DeactivateInput();
					return;
				}
				float y = Input.mouseScrollDelta.y;
				if (y != 0f && (Object)(object)_scroll != (Object)null)
				{
					_scroll.verticalNormalizedPosition = Mathf.Clamp01(_scroll.verticalNormalizedPosition + y * 0.16f);
				}
			}
		}

		private void DeactivateInput()
		{
			_typing = false;
			_framesSinceBlock = 10;
			if ((Object)(object)_input != (Object)null)
			{
				_input.text = "";
				_input.DeactivateInputField(false);
				SetPlaceholderText(visible: true);
			}
			if ((Object)(object)_scroll != (Object)null)
			{
				_scroll.verticalNormalizedPosition = 0f;
			}
			if ((Object)(object)EventSystem.current != (Object)null)
			{
				EventSystem.current.SetSelectedGameObject((GameObject)null);
			}
		}

		private void LateUpdate()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if (!_loggedRunning)
			{
				_loggedRunning = true;
				Plugin.Log.LogInfo((object)string.Format("[Chat] Running, key={0}, input={1}, root={2}, canvas={3}", Plugin.ConfigChatKey.Value, ((Object)(object)_input != (Object)null) ? "OK" : "NULL", ((Object)(object)_root != (Object)null) ? "OK" : "NULL", ((Object)(object)_canvas != (Object)null) ? "OK" : "NULL"));
			}
			if (IsInputBlocked())
			{
				_framesSinceBlock = 0;
			}
			else if (_framesSinceBlock < 100)
			{
				_framesSinceBlock++;
			}
			if (_typing)
			{
				UpdateImeCursorPos();
				if ((Object)(object)_input == (Object)null || (!_input.isFocused && Time.unscaledTime - _typingStartTime > 5f))
				{
					DeactivateInput();
				}
			}
			if ((Object)(object)_canvas == (Object)null && !_rebuilding && (Object)(object)GUIManager.instance?.hudCanvas != (Object)null)
			{
				_reinitTimer += Time.deltaTime;
				if (_reinitTimer >= 2f)
				{
					_reinitTimer = 0f;
					Plugin.Log.LogInfo((object)"[Chat] Canvas lost, rebuilding (fallback)...");
					CleanupUI();
					_names.Clear();
					_alive.Clear();
					_knocked.Clear();
					_firstFrame = true;
					_typing = false;
					_framesSinceBlock = 100;
					BuildUI();
				}
			}
			else
			{
				HandleInput();
				TrackCharacters();
				UpdateChatBoxVisibility();
			}
		}

		private void TrackCharacters()
		{
			if (Character.AllCharacters == null)
			{
				return;
			}
			if (_firstFrame)
			{
				foreach (Character allCharacter in Character.AllCharacters)
				{
					if (!((Object)(object)allCharacter == (Object)null))
					{
						int instanceID = ((Object)allCharacter).GetInstanceID();
						_names[instanceID] = allCharacter.characterName;
						_alive[instanceID] = !allCharacter.data.dead;
						_knocked[instanceID] = (Object)(object)allCharacter.refs?.afflictions != (Object)null && allCharacter.refs.afflictions.statusSum >= 1f;
					}
				}
				_firstFrame = false;
				return;
			}
			HashSet<int> hashSet = new HashSet<int>();
			foreach (Character allCharacter2 in Character.AllCharacters)
			{
				if ((Object)(object)allCharacter2 == (Object)null)
				{
					continue;
				}
				int instanceID2 = ((Object)allCharacter2).GetInstanceID();
				hashSet.Add(instanceID2);
				if (!_names.ContainsKey(instanceID2))
				{
					_names[instanceID2] = allCharacter2.characterName;
					AddSysMsg(allCharacter2.characterName + " 加入了游戏");
					_alive[instanceID2] = !allCharacter2.data.dead;
					_knocked[instanceID2] = false;
					continue;
				}
				bool flag = !allCharacter2.data.dead;
				bool flag2 = (Object)(object)allCharacter2.refs?.afflictions != (Object)null && allCharacter2.refs.afflictions.statusSum >= 1f;
				bool num = _alive[instanceID2];
				bool flag3 = _knocked[instanceID2];
				if (num && !flag)
				{
					AddSysMsg(_names[instanceID2] + " 已死亡");
				}
				else if (flag3 && !flag2 && flag)
				{
					AddSysMsg(_names[instanceID2] + " 已苏醒");
				}
				else if (!flag3 && flag2 && flag)
				{
					AddSysMsg(_names[instanceID2] + " 昏迷了");
				}
				_alive[instanceID2] = flag;
				_knocked[instanceID2] = flag2;
			}
			List<int> list = new List<int>();
			foreach (KeyValuePair<int, string> name in _names)
			{
				if (!hashSet.Contains(name.Key))
				{
					list.Add(name.Key);
				}
			}
			foreach (int item in list)
			{
				AddSysMsg(_names[item] + " 离开了游戏");
				_names.Remove(item);
				_alive.Remove(item);
				_knocked.Remove(item);
			}
		}

		private void UpdateChatBoxVisibility()
		{
			float value = Plugin.ConfigChatBoxHideDelay.Value;
			if (value <= 0f)
			{
				if (_chatBoxAlpha < 1f)
				{
					_chatBoxAlpha = 1f;
					SetChatBoxAlpha(1f);
				}
				return;
			}
			if (_typing)
			{
				_lastActivityTime = Time.time;
				if (_chatBoxAlpha < 1f)
				{
					_chatBoxAlpha = 1f;
					SetChatBoxAlpha(1f);
				}
				return;
			}
			float num = Time.time - _lastActivityTime;
			float num2 = ((num < value) ? 1f : ((!(num < value + 1f)) ? 0f : (1f - (num - value))));
			if (Mathf.Abs(_chatBoxAlpha - num2) > 0.01f)
			{
				_chatBoxAlpha = num2;
				SetChatBoxAlpha(num2);
			}
		}

		private void SetChatBoxAlpha(float alpha)
		{
			if ((Object)(object)_root != (Object)null)
			{
				CanvasGroup component = _root.GetComponent<CanvasGroup>();
				if ((Object)(object)component != (Object)null)
				{
					component.alpha = alpha;
				}
			}
		}

		private void CleanupUI()
		{
			if ((Object)(object)_canvas != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_canvas).gameObject);
			}
			_canvas = null;
			_root = null;
			_rootRt = null;
			_input = null;
			_scroll = null;
			_msgParent = null;
			_placeholderText = null;
			_msgs.Clear();
		}

		private void OnDestroy()
		{
			if (!((Object)(object)Instance != (Object)(object)this))
			{
				try
				{
					PhotonNetwork.NetworkingClient.EventReceived -= OnEvent;
				}
				catch
				{
				}
				try
				{
					SceneManager.sceneLoaded -= OnSceneLoaded;
				}
				catch
				{
				}
				CleanupUI();
				Harmony harmony = _harmony;
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
				Instance = null;
				Plugin.Log.LogInfo((object)"[Chat] Destroyed.");
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}