Decompiled source of BetterPlayerDistance v0.1.15

BetterPlayerDistance.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("BetterPlayerDistance")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("High Performance Distance Display")]
[assembly: AssemblyFileVersion("0.1.15.0")]
[assembly: AssemblyInformationalVersion("0.1.15+1ab1609b58ebf16f635f7263a765678f8834176e")]
[assembly: AssemblyProduct("BetterPlayerDistance")]
[assembly: AssemblyTitle("BetterPlayerDistance")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.15.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 BetterPlayerDistance
{
	public enum TriggerModeEnum
	{
		Toggle,
		Hold,
		AlwaysOn
	}
	public static class Configuration
	{
		public static ConfigEntry<bool> ShowName;

		public static ConfigEntry<bool> ShowDistance;

		public static ConfigEntry<KeyCode> ToggleKey;

		public static ConfigEntry<TriggerModeEnum> TriggerMode;

		public static ConfigEntry<float> ToggleDuration;

		public static ConfigEntry<float> HoldKeepDuration;

		public static ConfigEntry<float> MinDistance;

		public static ConfigEntry<float> MaxDistance;

		public static ConfigEntry<float> NameFontSize;

		public static ConfigEntry<float> DistFontSize;

		public static ConfigEntry<float> GlobalOpacity;

		public const float FixedShadowSpread = 1.5f;

		public const float FixedShadowAlpha = 0.8f;

		public const bool FixedHighQuality = false;

		public static readonly Color FixedShadowColor = new Color(0.267f, 0.275f, 0.216f, 1f);

		public static ConfigEntry<bool> DebugMode;

		public static ConfigEntry<KeyCode> DebugMenuKey;

		public static ConfigEntry<bool> DisableTMPWarnings;

		private const string CAT_BASIC = "1. 基础 (Basic)";

		private const string CAT_UI = "2. 界面 (UI)";

		private const string CAT_DEBUG = "3. 调试 (Debug)";

		public static void Initialize(ConfigFile config)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Expected O, but got Unknown
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Expected O, but got Unknown
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Expected O, but got Unknown
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Expected O, but got Unknown
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Expected O, but got Unknown
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Expected O, but got Unknown
			ToggleKey = config.Bind<KeyCode>("1. 基础 (Basic)", "快捷键 (Hotkey)", (KeyCode)99, "显示/隐藏玩家标签的按键(常显模式下忽略)。\nToggle player labels on/off (ignored in AlwaysOn mode).");
			TriggerMode = config.Bind<TriggerModeEnum>("1. 基础 (Basic)", "显示模式 (Display Mode)", TriggerModeEnum.Hold, new ConfigDescription("Hold=按住显示;Toggle=切换开关;AlwaysOn=常显(始终显示所有在场玩家)。\nHold = press to show; Toggle = press to switch; AlwaysOn = always display every in-game player.", (AcceptableValueBase)null, Array.Empty<object>()));
			ToggleDuration = config.Bind<float>("1. 基础 (Basic)", "切换显示时长 (Toggle Duration)", 10f, new ConfigDescription("Toggle 模式下按一次后保持显示的秒数。\nHow many seconds labels stay visible after a single press in Toggle mode.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 9999f), Array.Empty<object>()));
			HoldKeepDuration = config.Bind<float>("1. 基础 (Basic)", "松手保持时长 (Hold Release Linger)", 1f, new ConfigDescription("Hold 模式下松开按键后继续显示的秒数。\nHow many extra seconds labels linger after the key is released in Hold mode.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
			ShowName = config.Bind<bool>("2. 界面 (UI)", "显示名称 (Show Name)", true, "是否显示玩家名字。\nWhether to display the player name.");
			ShowDistance = config.Bind<bool>("2. 界面 (UI)", "显示距离 (Show Distance)", true, "是否显示距离数值。\nWhether to display the distance number.");
			MinDistance = config.Bind<float>("2. 界面 (UI)", "最小显示距离 (Min Display Distance)", 15f, new ConfigDescription("小于此距离不显示(米)。\nPlayers closer than this distance are hidden (meters).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>()));
			MaxDistance = config.Bind<float>("2. 界面 (UI)", "最大显示距离 (Max Display Distance)", 1000f, new ConfigDescription("超过此距离不显示(米)。\nPlayers farther than this distance are hidden (meters).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(50f, 1500f), Array.Empty<object>()));
			NameFontSize = config.Bind<float>("2. 界面 (UI)", "名字字号 (Name Font Size)", 16f, new ConfigDescription("玩家名字字体大小。\nFont size for the player name.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(9f, 60f), Array.Empty<object>()));
			DistFontSize = config.Bind<float>("2. 界面 (UI)", "距离字号 (Distance Font Size)", 17f, new ConfigDescription("距离数值字体大小。\nFont size for the distance number.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(9f, 60f), Array.Empty<object>()));
			GlobalOpacity = config.Bind<float>("2. 界面 (UI)", "整体透明度 (Global Opacity)", 0.85f, new ConfigDescription("整体不透明度 (0-1)。\nOverall opacity (0-1).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			DebugMode = config.Bind<bool>("3. 调试 (Debug)", "启用调试工具 (Enable Debug Tools)", true, "Insert 键呼出调试控制台。\nPress Insert to summon the debug console.");
			DebugMenuKey = config.Bind<KeyCode>("3. 调试 (Debug)", "调试菜单键 (Debug Menu Key)", (KeyCode)277, "打开调试控制台的按键。\nKey used to open the debug console.");
			DisableTMPWarnings = config.Bind<bool>("3. 调试 (Debug)", "禁用全局TMP缺字警告 (Disable TMP Missing-Glyph Warnings)", true, "开启后将禁止 TextMeshPro 向控制台输出缺字警告,可显著解决特殊字符导致的掉帧问题(开发者请关闭)。\nWhen on, suppresses TextMeshPro missing-glyph warnings to avoid console spam and frame drops (developers should disable this).");
		}
	}
	public class OverlayManager
	{
		private Canvas _canvas;

		private GameObject _labelPrefab;

		private Transform _canvasTransform;

		private List<TMP_FontAsset> _availableFonts = new List<TMP_FontAsset>();

		private int _currentFontIndex;

		private TMP_FontAsset _currentFont;

		private readonly Dictionary<int, PlayerLabel> _activeLabels = new Dictionary<int, PlayerLabel>();

		private bool _shouldShowLabels;

		private float _hideTimeTimestamp;

		private bool _initialized;

		private float _lastGlobalOpacity = -1f;

		private bool _lastDisableWarnings = true;

		private TriggerModeEnum _lastTriggerMode;

		private float _nextFontCheckTime;

		private bool _isUsingFallbackFont;

		public int ActiveCount => _activeLabels.Count;

		public string CurrentFontName
		{
			get
			{
				if (!((Object)(object)_currentFont != (Object)null))
				{
					return "None";
				}
				return ((Object)_currentFont).name;
			}
		}

		public OverlayManager()
		{
			SceneManager.sceneLoaded += OnSceneLoaded;
		}

		public void Dispose()
		{
			SceneManager.sceneLoaded -= OnSceneLoaded;
			ClearAllLabels();
			if ((Object)(object)_canvas != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_canvas).gameObject);
			}
		}

		public void TryInitialize()
		{
			if (_initialized)
			{
				return;
			}
			try
			{
				CreateCanvasSystem();
				_initialized = true;
				Plugin.Log.LogInfo((object)"OverlayManager: Initialized.");
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Init Failed: {arg}");
			}
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			ClearAllLabels();
			_availableFonts.Clear();
			_initialized = false;
		}

		private void ClearAllLabels()
		{
			foreach (PlayerLabel value in _activeLabels.Values)
			{
				value.Destroy();
			}
			_activeLabels.Clear();
		}

		public void UpdateInput()
		{
			if (!_initialized || (Object)(object)_canvas == (Object)null)
			{
				TryInitialize();
			}
			else
			{
				HandleInput();
			}
		}

		public void LateUpdate()
		{
			if (Configuration.ShowName == null || Configuration.ShowDistance == null)
			{
				return;
			}
			if (!Configuration.ShowName.Value && !Configuration.ShowDistance.Value)
			{
				if (_activeLabels.Count > 0)
				{
					ClearAllLabels();
				}
			}
			else
			{
				if (!_initialized || (Object)(object)_canvas == (Object)null)
				{
					return;
				}
				if (Configuration.DisableTMPWarnings != null && _lastDisableWarnings != Configuration.DisableTMPWarnings.Value)
				{
					ApplyTMPSettings();
					_lastDisableWarnings = Configuration.DisableTMPWarnings.Value;
				}
				if (_isUsingFallbackFont && Time.time > _nextFontCheckTime)
				{
					_nextFontCheckTime = Time.time + 1f;
					TryFindBetterFont();
				}
				bool flag = Mathf.Abs(_lastGlobalOpacity - Configuration.GlobalOpacity.Value) > 0.01f;
				foreach (int item in _activeLabels.Keys.ToList())
				{
					PlayerLabel playerLabel = _activeLabels[item];
					if (!playerLabel.IsValid())
					{
						playerLabel.SetVisible(visible: false);
						continue;
					}
					if (flag)
					{
						playerLabel.RefreshStyle();
					}
					playerLabel.UpdateState(_shouldShowLabels);
				}
				if (flag)
				{
					_lastGlobalOpacity = Configuration.GlobalOpacity.Value;
				}
			}
		}

		public void RegisterCharacter(Character c)
		{
			if (!_initialized)
			{
				TryInitialize();
			}
			if (!((Object)(object)c == (Object)null) && !((Object)(object)c == (Object)(object)Character.localCharacter))
			{
				string text = Tracking.ExtractDisplayName(((Object)c).name);
				if (!(text == "Bot"))
				{
					Transform val = ((Component)c).transform.Find("Scout/Misc/CharacterLight");
					Transform trackTarget = (((Object)(object)val != (Object)null) ? val : ((Component)c).transform);
					RegisterGenericTarget(((Component)c).gameObject, trackTarget, text);
				}
			}
		}

		public void RegisterFakeTarget(GameObject root, string customName)
		{
			if (!_initialized)
			{
				TryInitialize();
			}
			if (!((Object)(object)root == (Object)null))
			{
				Transform val = root.transform.Find("Scout/Misc/CharacterLight");
				Transform trackTarget = (((Object)(object)val != (Object)null) ? val : root.transform);
				RegisterGenericTarget(root, trackTarget, customName);
			}
		}

		private void RegisterGenericTarget(GameObject owner, Transform trackTarget, string displayName)
		{
			int instanceID = ((Object)owner).GetInstanceID();
			if (!_activeLabels.ContainsKey(instanceID))
			{
				if ((Object)(object)_currentFont == (Object)null)
				{
					InitializeFonts();
				}
				GameObject val = Object.Instantiate<GameObject>(_labelPrefab, _canvasTransform);
				val.SetActive(true);
				SetLayerRecursively(val, 5);
				PlayerLabel value = new PlayerLabel(trackTarget, val, _currentFont, displayName);
				_activeLabels.Add(instanceID, value);
			}
		}

		public void UnregisterCharacter(GameObject owner)
		{
			if (!((Object)(object)owner == (Object)null))
			{
				int instanceID = ((Object)owner).GetInstanceID();
				if (_activeLabels.TryGetValue(instanceID, out var value))
				{
					value.Destroy();
					_activeLabels.Remove(instanceID);
				}
			}
		}

		public void UnregisterTarget(GameObject owner)
		{
			UnregisterCharacter(owner);
		}

		public void CycleFont(int direction)
		{
			if (_availableFonts.Count == 0)
			{
				InitializeFonts();
			}
			if (_availableFonts.Count == 0)
			{
				return;
			}
			_currentFontIndex += direction;
			if (_currentFontIndex >= _availableFonts.Count)
			{
				_currentFontIndex = 0;
			}
			if (_currentFontIndex < 0)
			{
				_currentFontIndex = _availableFonts.Count - 1;
			}
			_currentFont = _availableFonts[_currentFontIndex];
			_isUsingFallbackFont = false;
			foreach (PlayerLabel value in _activeLabels.Values)
			{
				value.SetFont(_currentFont);
			}
			Plugin.Log.LogInfo((object)("Switched Font to: " + ((Object)_currentFont).name));
		}

		private void HandleInput()
		{
			//IL_006a: 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_0115: Unknown result type (might be due to invalid IL or missing references)
			if (Configuration.TriggerMode == null)
			{
				return;
			}
			TriggerModeEnum value = Configuration.TriggerMode.Value;
			if (value != _lastTriggerMode)
			{
				_hideTimeTimestamp = 0f;
				_shouldShowLabels = false;
				_lastTriggerMode = value;
				Plugin.Log.LogInfo((object)$"Mode changed to {value}, state reset.");
			}
			switch (value)
			{
			case TriggerModeEnum.AlwaysOn:
				_shouldShowLabels = true;
				return;
			case TriggerModeEnum.Toggle:
				if (Configuration.ToggleKey != null && Input.GetKeyDown(Configuration.ToggleKey.Value))
				{
					float num = ((Configuration.ToggleDuration != null) ? Configuration.ToggleDuration.Value : 10f);
					if (Time.time < _hideTimeTimestamp)
					{
						_hideTimeTimestamp = Time.time;
					}
					else
					{
						_hideTimeTimestamp = Time.time + num;
					}
				}
				_shouldShowLabels = Time.time < _hideTimeTimestamp;
				return;
			}
			float num2 = ((Configuration.HoldKeepDuration != null) ? Configuration.HoldKeepDuration.Value : 1f);
			if (Configuration.ToggleKey != null)
			{
				if (Input.GetKey(Configuration.ToggleKey.Value))
				{
					_hideTimeTimestamp = Time.time + num2 + 0.1f;
				}
				else if (Input.GetKeyUp(Configuration.ToggleKey.Value))
				{
					_hideTimeTimestamp = Time.time + num2;
				}
			}
			_shouldShowLabels = Time.time < _hideTimeTimestamp;
		}

		private void CreateCanvasSystem()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_canvas != (Object)null))
			{
				ApplyTMPSettings();
				InitializeFonts();
				GameObject val = new GameObject("DistanceDisplayCanvas");
				Object.DontDestroyOnLoad((Object)(object)val);
				val.layer = 5;
				_canvas = val.AddComponent<Canvas>();
				_canvas.renderMode = (RenderMode)0;
				_canvas.sortingOrder = 999;
				CanvasScaler obj = val.AddComponent<CanvasScaler>();
				obj.uiScaleMode = (ScaleMode)1;
				obj.referenceResolution = new Vector2(1920f, 1080f);
				val.AddComponent<GraphicRaycaster>();
				_canvasTransform = val.transform;
				CreateLabelPrefab();
			}
		}

		private void ApplyTMPSettings()
		{
			if (Configuration.DisableTMPWarnings == null || !Configuration.DisableTMPWarnings.Value)
			{
				return;
			}
			try
			{
				TMP_Settings val = Resources.Load<TMP_Settings>("TMP Settings");
				if ((Object)(object)val == (Object)null)
				{
					val = Resources.FindObjectsOfTypeAll<TMP_Settings>().FirstOrDefault();
				}
				if (!((Object)(object)val != (Object)null))
				{
					return;
				}
				FieldInfo field = typeof(TMP_Settings).GetField("m_warningsDisabled", BindingFlags.Instance | BindingFlags.NonPublic);
				if (field != null)
				{
					field.SetValue(val, true);
					Plugin.Log.LogInfo((object)"TMP Warnings disabled (Reflection).");
					return;
				}
				PropertyInfo property = typeof(TMP_Settings).GetProperty("warningsDisabled", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
				if (property != null && property.CanWrite)
				{
					property.SetValue(val, true);
				}
			}
			catch (Exception)
			{
			}
		}

		private void InitializeFonts()
		{
			_availableFonts.Clear();
			try
			{
				TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>();
				if (array != null)
				{
					TMP_FontAsset[] array2 = array;
					foreach (TMP_FontAsset val in array2)
					{
						if ((Object)(object)val != (Object)null && !string.IsNullOrEmpty(((Object)val).name) && (Object)(object)val.atlasTexture != (Object)null)
						{
							_availableFonts.Add(val);
						}
					}
				}
				_availableFonts.Sort((TMP_FontAsset a, TMP_FontAsset b) => string.Compare(((Object)a).name, ((Object)b).name));
			}
			catch
			{
			}
			if (_availableFonts.Count > 0)
			{
				TMP_FontAsset val2 = ((IEnumerable<TMP_FontAsset>)_availableFonts).FirstOrDefault((Func<TMP_FontAsset, bool>)((TMP_FontAsset f) => ((Object)f).name.IndexOf("Daruma", StringComparison.OrdinalIgnoreCase) >= 0)) ?? ((IEnumerable<TMP_FontAsset>)_availableFonts).FirstOrDefault((Func<TMP_FontAsset, bool>)((TMP_FontAsset f) => ((Object)f).name.IndexOf("Noto", StringComparison.OrdinalIgnoreCase) >= 0)) ?? ((IEnumerable<TMP_FontAsset>)_availableFonts).FirstOrDefault((Func<TMP_FontAsset, bool>)((TMP_FontAsset f) => ((Object)f).name.IndexOf("Liberation", StringComparison.OrdinalIgnoreCase) >= 0));
				if ((Object)(object)val2 != (Object)null)
				{
					_currentFont = val2;
					_currentFontIndex = _availableFonts.IndexOf(val2);
				}
				else
				{
					_currentFont = _availableFonts[0];
					_currentFontIndex = 0;
				}
				if (((Object)_currentFont).name.IndexOf("Daruma", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					_isUsingFallbackFont = false;
				}
				else
				{
					_isUsingFallbackFont = true;
				}
			}
		}

		private void TryFindBetterFont()
		{
			try
			{
				TMP_FontAsset val = ((IEnumerable<TMP_FontAsset>)Resources.FindObjectsOfTypeAll<TMP_FontAsset>()).FirstOrDefault((Func<TMP_FontAsset, bool>)((TMP_FontAsset f) => (Object)(object)f != (Object)null && ((Object)f).name.IndexOf("Daruma", StringComparison.OrdinalIgnoreCase) >= 0 && (Object)(object)f.atlasTexture != (Object)null));
				if (!((Object)(object)val != (Object)null))
				{
					return;
				}
				if (!_availableFonts.Contains(val))
				{
					_availableFonts.Add(val);
				}
				_availableFonts.Sort((TMP_FontAsset a, TMP_FontAsset b) => string.Compare(((Object)a).name, ((Object)b).name));
				_currentFont = val;
				_currentFontIndex = _availableFonts.IndexOf(val);
				_isUsingFallbackFont = false;
				foreach (PlayerLabel value in _activeLabels.Values)
				{
					value.SetFont(_currentFont);
				}
				Plugin.Log.LogInfo((object)("Auto-recovered Font to: " + ((Object)val).name));
			}
			catch
			{
			}
		}

		private void CreateLabelPrefab()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			_labelPrefab = new GameObject("LabelPrefab");
			_labelPrefab.transform.SetParent(_canvasTransform);
			_labelPrefab.layer = 5;
			_labelPrefab.SetActive(false);
			CanvasGroup obj = _labelPrefab.AddComponent<CanvasGroup>();
			obj.alpha = 0f;
			obj.blocksRaycasts = false;
			obj.interactable = false;
		}

		private void SetLayerRecursively(GameObject obj, int newLayer)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			if ((Object)(object)obj == (Object)null)
			{
				return;
			}
			obj.layer = newLayer;
			foreach (Transform item in obj.transform)
			{
				Transform val = item;
				if ((Object)(object)val != (Object)null)
				{
					SetLayerRecursively(((Component)val).gameObject, newLayer);
				}
			}
		}
	}
	public class PlayerLabel
	{
		private Transform _targetPoint;

		private GameObject _rootObj;

		private RectTransform _rootRect;

		private CanvasGroup _canvasGroup;

		private TextMeshProUGUI _mainText;

		private List<TextMeshProUGUI> _shadowTexts = new List<TextMeshProUGUI>();

		private string _displayName;

		private Camera _mainCam;

		private const float FADE_TIME = 0.4f;

		private static readonly Regex ColorTagRegex = new Regex("<color=.*?>|<\\/color>", RegexOptions.IgnoreCase);

		private readonly Vector2[] _offsets = (Vector2[])(object)new Vector2[8]
		{
			new Vector2(0f, 1f),
			new Vector2(0f, -1f),
			new Vector2(-1f, 0f),
			new Vector2(1f, 0f),
			new Vector2(-1f, 1f),
			new Vector2(1f, 1f),
			new Vector2(-1f, -1f),
			new Vector2(1f, -1f)
		};

		public PlayerLabel(Transform target, GameObject rootUiObj, TMP_FontAsset font, string name)
		{
			//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_0034: 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_004a: 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_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: 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_008c: 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_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: 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)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Expected O, but got Unknown
			_targetPoint = target;
			_rootObj = rootUiObj;
			_rootRect = _rootObj.GetComponent<RectTransform>();
			_canvasGroup = _rootObj.GetComponent<CanvasGroup>();
			_displayName = name;
			_mainCam = Camera.main;
			for (int i = 0; i < 8; i++)
			{
				GameObject val = new GameObject($"Shadow_{i}");
				val.transform.SetParent(_rootObj.transform);
				val.layer = 5;
				TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>();
				SetupTextCommon(val2, font);
				_shadowTexts.Add(val2);
			}
			GameObject val3 = new GameObject("MainText");
			val3.transform.SetParent(_rootObj.transform);
			val3.layer = 5;
			_mainText = val3.AddComponent<TextMeshProUGUI>();
			SetupTextCommon(_mainText, font);
			RefreshStyle();
		}

		private void SetupTextCommon(TextMeshProUGUI tmp, TMP_FontAsset font)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			((TMP_Text)tmp).alignment = (TextAlignmentOptions)514;
			((Graphic)tmp).raycastTarget = false;
			((TMP_Text)tmp).overflowMode = (TextOverflowModes)0;
			((TMP_Text)tmp).enableWordWrapping = false;
			((TMP_Text)tmp).richText = true;
			if ((Object)(object)font != (Object)null)
			{
				((TMP_Text)tmp).font = font;
			}
			((TMP_Text)tmp).rectTransform.anchoredPosition = Vector2.zero;
		}

		public bool IsValid()
		{
			if ((Object)(object)_targetPoint != (Object)null)
			{
				return ((Component)_targetPoint).gameObject.activeInHierarchy;
			}
			return false;
		}

		public void SetFont(TMP_FontAsset font)
		{
			if ((Object)(object)_mainText != (Object)null)
			{
				((TMP_Text)_mainText).font = font;
			}
			foreach (TextMeshProUGUI shadowText in _shadowTexts)
			{
				((TMP_Text)shadowText).font = font;
			}
		}

		public void RefreshStyle()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: 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_0064: 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_007c: Unknown result type (might be due to invalid IL or missing references)
			_ = Configuration.FixedShadowColor;
			Color fixedShadowColor = Configuration.FixedShadowColor;
			fixedShadowColor.a = 0.8f;
			Color color = default(Color);
			((Color)(ref color))..ctor(0.875f, 0.855f, 0.761f, 1f);
			((Graphic)_mainText).color = color;
			float num = 1.5f;
			for (int i = 0; i < 8 && i < _shadowTexts.Count; i++)
			{
				TextMeshProUGUI obj = _shadowTexts[i];
				((Graphic)obj).color = fixedShadowColor;
				((TMP_Text)obj).rectTransform.anchoredPosition = _offsets[i] * num;
			}
		}

		public void UpdateState(bool globalShow)
		{
			//IL_0070: 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)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: 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_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: 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_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: 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)_rootObj == (Object)null || (Object)(object)_canvasGroup == (Object)null)
			{
				return;
			}
			if ((Object)(object)_mainCam == (Object)null)
			{
				_mainCam = Camera.main;
			}
			if ((Object)(object)_mainCam == (Object)null || (Object)(object)_targetPoint == (Object)null)
			{
				_canvasGroup.alpha = 0f;
				SetVisible(visible: false);
				return;
			}
			Vector3 val = _targetPoint.position + Vector3.up * 1.2f;
			float num = Vector3.Distance(((Component)_mainCam).transform.position, _targetPoint.position);
			Vector3 val2 = _mainCam.WorldToViewportPoint(val);
			bool flag = globalShow;
			if (Configuration.MinDistance != null && num < Configuration.MinDistance.Value)
			{
				flag = false;
			}
			else if (Configuration.MaxDistance != null && num > Configuration.MaxDistance.Value)
			{
				flag = false;
			}
			if (val2.z <= 0f || val2.x < 0f || val2.x > 1f || val2.y < 0f || val2.y > 1f)
			{
				_canvasGroup.alpha = 0f;
				SetVisible(visible: false);
				return;
			}
			float num2 = 2.5f;
			float num3 = ((Configuration.GlobalOpacity != null && flag) ? Configuration.GlobalOpacity.Value : 0f);
			float num4 = Mathf.MoveTowards(_canvasGroup.alpha, num3, num2 * Time.deltaTime);
			bool flag2 = flag || num4 > 0.01f;
			SetVisible(flag2);
			_canvasGroup.alpha = num4;
			if (!flag2)
			{
				return;
			}
			Vector3 position = _mainCam.WorldToScreenPoint(val);
			_rootObj.transform.position = position;
			string text = "";
			if (Configuration.NameFontSize != null)
			{
				float value = Configuration.NameFontSize.Value;
				float value2 = Configuration.DistFontSize.Value;
				bool value3 = Configuration.ShowName.Value;
				bool value4 = Configuration.ShowDistance.Value;
				if (value3)
				{
					text += $"<size={value}>{_displayName}</size>";
				}
				if (value3 && value4)
				{
					text += "\n";
				}
				if (value4)
				{
					text += $"<size={value2}>{num:F0}m</size>";
				}
			}
			((TMP_Text)_mainText).text = text;
			string text2 = ColorTagRegex.Replace(text, string.Empty);
			foreach (TextMeshProUGUI shadowText in _shadowTexts)
			{
				((TMP_Text)shadowText).text = text2;
			}
		}

		public void SetVisible(bool visible)
		{
			if (!((Object)(object)_rootObj == (Object)null) && _rootObj.activeSelf != visible)
			{
				_rootObj.SetActive(visible);
			}
		}

		public void Destroy()
		{
			if ((Object)(object)_rootObj != (Object)null)
			{
				Object.Destroy((Object)(object)_rootObj);
			}
		}
	}
	[BepInPlugin("com.AiAe.betterplayerdistance", "Better Player Distance", "0.1.15")]
	public class Plugin : BaseUnityPlugin
	{
		public static Plugin Instance;

		public static ManualLogSource Log;

		public static OverlayManager Overlay;

		private Harmony _harmony;

		private bool _showDebugMenu;

		private string _debugNameInput = "测试员01";

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

		private Rect _debugWindowRect = new Rect(20f, 20f, 350f, 500f);

		private bool _hasLoggedError;

		private bool _isConfigLoaded;

		private void Awake()
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			try
			{
				Configuration.Initialize(((BaseUnityPlugin)this).Config);
				_isConfigLoaded = true;
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Config Init Failed: {arg}");
				_isConfigLoaded = false;
			}
			try
			{
				_harmony = new Harmony("com.AiAe.betterplayerdistance");
				_harmony.PatchAll();
			}
			catch
			{
			}
			Overlay = new OverlayManager();
			Log.LogInfo((object)"BetterPlayerDistance v0.1.15 (AIAE) Loaded.");
		}

		private void Start()
		{
			if (Overlay != null)
			{
				Overlay.TryInitialize();
			}
		}

		private void Update()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if (Input.GetKeyDown(Configuration.DebugMenuKey.Value))
			{
				_showDebugMenu = !_showDebugMenu;
				if (_showDebugMenu)
				{
					Cursor.visible = true;
					Cursor.lockState = (CursorLockMode)0;
				}
			}
			if (Overlay == null)
			{
				return;
			}
			try
			{
				Overlay.UpdateInput();
			}
			catch (Exception arg)
			{
				if (!_hasLoggedError)
				{
					Log.LogError((object)$"Overlay Input Error: {arg}");
					_hasLoggedError = true;
				}
			}
		}

		private void LateUpdate()
		{
			if (Overlay == null)
			{
				return;
			}
			try
			{
				Overlay.LateUpdate();
			}
			catch (Exception arg)
			{
				if (!_hasLoggedError)
				{
					Log.LogError((object)$"Overlay Render Error: {arg}");
					_hasLoggedError = true;
				}
			}
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			Overlay?.Dispose();
		}

		private void OnGUI()
		{
			//IL_003d: 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_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			if (!_showDebugMenu || !Configuration.DebugMode.Value)
			{
				return;
			}
			if (_showDebugMenu)
			{
				Cursor.visible = true;
				Cursor.lockState = (CursorLockMode)0;
			}
			GUI.backgroundColor = new Color(0.1f, 0.1f, 0.1f, 0.95f);
			try
			{
				_debugWindowRect = GUI.Window(888, _debugWindowRect, new WindowFunction(DrawDebugWindow), "调试控制台 / Debug Console [Insert]");
			}
			catch
			{
			}
		}

		private void DrawDebugWindow(int windowID)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			GUI.DragWindow(new Rect(0f, 0f, 10000f, 20f));
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			GUILayout.Label("BetterPlayerDistance (AIAE) <color=yellow>v0.1.15</color>", Array.Empty<GUILayoutOption>());
			if (!_isConfigLoaded)
			{
				GUILayout.Label("<color=red>严重错误 / Fatal: 配置文件加载失败!Config init failed.</color>", Array.Empty<GUILayoutOption>());
				GUILayout.Label("请删除 BepInEx/config 下的 .cfg 文件并重启。\nDelete the .cfg under BepInEx/config and restart.", Array.Empty<GUILayoutOption>());
			}
			else
			{
				string text = ((Configuration.TriggerMode != null) ? Configuration.TriggerMode.Value.ToString() : "Error");
				GUILayout.Label("当前模式 / Mode: <color=cyan>" + text + "</color>", Array.Empty<GUILayoutOption>());
			}
			GUILayout.Label(string.Format("状态 / State: {0} | 标签数 / Labels: {1}", (Overlay != null) ? "Active" : "Null", Overlay?.ActiveCount ?? 0), Array.Empty<GUILayoutOption>());
			GUILayout.Label("字体 / Font: " + (Overlay?.CurrentFontName ?? "Unknown"), Array.Empty<GUILayoutOption>());
			GUILayout.Space(5f);
			GUILayout.Label("--- 性能 / Performance ---", Array.Empty<GUILayoutOption>());
			if (Configuration.DisableTMPWarnings != null)
			{
				string text2 = (Configuration.DisableTMPWarnings.Value ? "开启 / On" : "关闭 / Off");
				if (GUILayout.Button("禁用TMP警告 / Disable TMP Warnings: [" + text2 + "]", Array.Empty<GUILayoutOption>()))
				{
					Configuration.DisableTMPWarnings.Value = !Configuration.DisableTMPWarnings.Value;
				}
			}
			else
			{
				GUILayout.Label("<color=red>Config Error: DisableTMPWarnings is NULL</color>", Array.Empty<GUILayoutOption>());
			}
			GUILayout.Space(5f);
			GUILayout.Label("--- 假人测试 / Fake Players ---", Array.Empty<GUILayoutOption>());
			_debugNameInput = GUILayout.TextField(_debugNameInput, 20, Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("生成-前方 / Spawn (Front)", Array.Empty<GUILayoutOption>()))
			{
				SpawnFakeSafe(_debugNameInput, isColorful: false);
			}
			if (GUILayout.Button("生成-彩名 / Spawn (Colored)", Array.Empty<GUILayoutOption>()))
			{
				SpawnFakeSafe(_debugNameInput, isColorful: true);
			}
			GUILayout.EndHorizontal();
			if (GUILayout.Button("清除所有假人 / Clear All Fakes", Array.Empty<GUILayoutOption>()))
			{
				ClearFakePlayers();
			}
			GUILayout.Space(5f);
			GUILayout.Label("--- 工具 / Tools ---", Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("扫描全图实体 / Scan Entities (see console)", Array.Empty<GUILayoutOption>()))
			{
				ScanAllCharacters();
			}
			GUILayout.Space(5f);
			GUILayout.Label("--- 实时预览 / Live Preview ---", Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("切换字体 / Cycle Font (Preview)", Array.Empty<GUILayoutOption>()))
			{
				Overlay.CycleFont(1);
			}
			GUILayout.EndVertical();
		}

		private void ScanAllCharacters()
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)Camera.main == (Object)null))
			{
				Character[] array = Object.FindObjectsOfType<Character>();
				Log.LogInfo((object)$"--- 扫描开始: 发现 {array.Length} 个 Character 对象 ---");
				Character[] array2 = array;
				foreach (Character val in array2)
				{
					float num = Vector3.Distance(((Component)Camera.main).transform.position, ((Component)val).transform.position);
					string name = ((Object)val).name;
					string text = Tracking.ExtractDisplayName(((Object)val).name);
					bool activeInHierarchy = ((Component)val).gameObject.activeInHierarchy;
					Log.LogInfo((object)$"[实体] ObjName: {name} | Display: {text} | Dist: {num:F1}m | Active: {activeInHierarchy}");
				}
				Log.LogInfo((object)"--- 扫描结束 ---");
			}
		}

		private void SpawnFakeSafe(string nickName, bool isColorful)
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: 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_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Expected O, but got Unknown
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Expected O, but got Unknown
			//IL_010e: 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_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)Camera.main == (Object)null))
			{
				GameObject val = GameObject.CreatePrimitive((PrimitiveType)1);
				int num = Random.Range(100, 999);
				((Object)val).name = $"Fake_{num}";
				Vector3 position = (isColorful ? (((Component)Camera.main).transform.position + Random.insideUnitSphere * 10f) : (((Component)Camera.main).transform.position + ((Component)Camera.main).transform.forward * 20f));
				position.y = ((Component)Camera.main).transform.position.y - 1f;
				val.transform.position = position;
				GameObject val2 = new GameObject("Scout");
				val2.transform.SetParent(val.transform, false);
				val2.transform.localPosition = Vector3.zero;
				GameObject val3 = new GameObject("Misc");
				val3.transform.SetParent(val2.transform, false);
				val3.transform.localPosition = Vector3.zero;
				GameObject val4 = new GameObject("CharacterLight");
				val4.transform.SetParent(val3.transform, false);
				val4.transform.localPosition = new Vector3(0f, 1.8f, 0f);
				string text = nickName;
				text = ((!isColorful) ? $"{nickName}:{num}" : $"<color=#FF5555>彩</color><color=#55FF55>色</color><color=#5555FF>名</color><color=#FFFF55>字</color>:{num}");
				Overlay.RegisterFakeTarget(val, text);
				_fakePlayers.Add(val);
			}
		}

		private void ClearFakePlayers()
		{
			foreach (GameObject fakePlayer in _fakePlayers)
			{
				if ((Object)(object)fakePlayer != (Object)null)
				{
					Overlay.UnregisterCharacter(fakePlayer);
					Object.Destroy((Object)(object)fakePlayer);
				}
			}
			_fakePlayers.Clear();
		}
	}
	public static class Tracking
	{
		public static string ExtractDisplayName(string objName)
		{
			if (string.IsNullOrEmpty(objName))
			{
				return "Unknown";
			}
			int num = objName.IndexOf('[');
			int num2 = objName.LastIndexOf(':');
			if (num != -1 && num2 != -1 && num2 > num)
			{
				return objName.Substring(num + 1, num2 - num - 1).Trim();
			}
			return objName;
		}
	}
	[HarmonyPatch(typeof(Character))]
	public static class CharacterPatches
	{
		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		public static void Awake_Postfix(Character __instance)
		{
			Plugin.Overlay?.RegisterCharacter(__instance);
		}

		[HarmonyPatch("OnDestroy")]
		[HarmonyPostfix]
		public static void OnDestroy_Postfix(Character __instance)
		{
			Plugin.Overlay?.UnregisterCharacter(((Component)__instance).gameObject);
		}
	}
}