Decompiled source of ProMLGStats v1.0.5

ProMLGStats.dll

Decompiled an hour ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using ProMLGStats.Stats;
using ProMLGStats.UI;
using ProMLGStats.Utils;
using TMPro;
using UnboundLib;
using UnboundLib.GameModes;
using UnboundLib.Utils.UI;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
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("ProMLGStats")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.5+55b73cdce38371846b742abe42a0fd48a4a387b1")]
[assembly: AssemblyProduct("ProMLGStats")]
[assembly: AssemblyTitle("ProMLGStats")]
[assembly: AssemblyVersion("1.0.0.0")]
[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 ProMLGStats
{
	internal class Configs
	{
		public ConfigEntry<bool> EnableStatsHud { get; }

		public ConfigEntry<bool> StatsHudVisible { get; }

		public ConfigEntry<bool> StatsHudCollapsed { get; }

		public ConfigEntry<bool> StatsHudSimpleMode { get; }

		public ConfigEntry<bool> StatsHudUltraCompact { get; }

		public ConfigEntry<bool> StatsHudPeekMode { get; }

		public ConfigEntry<KeyCode> StatsHudPeekKey { get; }

		public ConfigEntry<bool> HideStatsHudDuringPick { get; }

		public ConfigEntry<bool> HideStatsHudDuringBattle { get; }

		public ConfigEntry<KeyCode> StatsHudToggleKey { get; }

		public ConfigEntry<float> StatsHudOpacity { get; }

		public ConfigEntry<float> StatsHudFontScale { get; }

		public ConfigEntry<float> StatsHudColorR { get; }

		public ConfigEntry<float> StatsHudColorG { get; }

		public ConfigEntry<float> StatsHudColorB { get; }

		public ConfigEntry<bool> ShowPickDeltasOnHud { get; }

		public ConfigEntry<bool> EnableStatsTab { get; }

		public ConfigEntry<KeyCode> StatsTabKey { get; }

		public ConfigEntry<KeyCode> TabCompareKey { get; }

		public ConfigEntry<bool> EnableTabCompare { get; }

		public ConfigEntry<float> TabPanelWidth { get; }

		public ConfigEntry<float> TabPanelHeightFraction { get; }

		public ConfigEntry<float> TabPanelOpacity { get; }

		public ConfigEntry<float> TabPosX { get; }

		public ConfigEntry<float> TabPosY { get; }

		public ConfigEntry<bool> ShowPing { get; }

		public ConfigEntry<bool> AutoCloseTabDuringPick { get; }

		public ConfigEntry<bool> ShowTabInfoStats { get; }

		public ConfigEntry<float> StatsPanelScale { get; }

		public ConfigEntry<float> StatsHudOffsetX { get; }

		public ConfigEntry<float> StatsHudOffsetY { get; }

		public ConfigEntry<float> StatsAccentR { get; }

		public ConfigEntry<float> StatsAccentG { get; }

		public ConfigEntry<float> StatsAccentB { get; }

		public Configs(ConfigFile config)
		{
			EnableStatsHud = config.Bind<bool>("Stats HUD", "Enabled", true, "Always-on stats panel in the bottom-left corner.");
			StatsHudVisible = config.Bind<bool>("Stats HUD", "Visible", true, "Whether the HUD is currently shown (toggle in-game with ToggleKey).");
			StatsHudCollapsed = config.Bind<bool>("Stats HUD", "Collapsed", false, "Show the HUD as a minimal strip instead of the full panel.");
			StatsHudSimpleMode = config.Bind<bool>("Stats HUD", "SimpleMode", true, "Show a compact stat list instead of every stat.");
			StatsHudUltraCompact = config.Bind<bool>("Stats HUD", "UltraCompact", false, "Narrow HUD with fewer lines.");
			StatsHudPeekMode = config.Bind<bool>("Stats HUD", "PeekMode", false, "Only show the HUD while holding the peek key.");
			StatsHudPeekKey = config.Bind<KeyCode>("Stats HUD", "PeekKey", (KeyCode)308, "Hold to show HUD when PeekMode is enabled.");
			HideStatsHudDuringPick = config.Bind<bool>("Stats HUD", "HideDuringPick", false, "Hide the always-on HUD during card pick.");
			HideStatsHudDuringBattle = config.Bind<bool>("Stats HUD", "HideDuringBattle", false, "Hide the always-on HUD during battle rounds.");
			StatsHudToggleKey = config.Bind<KeyCode>("Stats HUD", "ToggleKey", (KeyCode)111, "Toggle the always-on HUD visibility. Set to None to disable the shortcut.");
			StatsHudOpacity = config.Bind<float>("Stats HUD", "Opacity", 0f, "Background opacity for the HUD panel (0 = text only).");
			StatsHudFontScale = config.Bind<float>("Stats HUD", "FontScale", 1f, "Text scale multiplier (auto-scales with resolution too).");
			StatsHudColorR = config.Bind<float>("Stats HUD", "ColorR", 1f, "HUD text red channel.");
			StatsHudColorG = config.Bind<float>("Stats HUD", "ColorG", 1f, "HUD text green channel.");
			StatsHudColorB = config.Bind<float>("Stats HUD", "ColorB", 1f, "HUD text blue channel.");
			ShowPickDeltasOnHud = config.Bind<bool>("Stats HUD", "ShowPickDeltas", true, "During picks, show card deltas on the HUD for whoever is picking (hover a card to preview).");
			EnableStatsTab = config.Bind<bool>("Stats Tab", "Enabled", true, "Full-player Tab overlay. Press the Tab key in-game.");
			StatsTabKey = config.Bind<KeyCode>("Stats Tab", "OpenKey", (KeyCode)9, "Opens the Tab overlay. Rebind if another mod already uses Tab. None disables it.");
			TabCompareKey = config.Bind<KeyCode>("Stats Tab", "CompareKey", (KeyCode)99, "Toggles compare mode while the Tab overlay is open.");
			EnableTabCompare = config.Bind<bool>("Stats Tab", "EnableCompare", true, "Compare mode inside the Tab overlay ([ and ] switch opponent).");
			TabPanelWidth = config.Bind<float>("Stats Tab", "PanelWidth", 480f, "Tab overlay width in pixels (before scale).");
			TabPanelHeightFraction = config.Bind<float>("Stats Tab", "PanelHeightFraction", 0.82f, "Tab overlay height as a fraction of screen height.");
			TabPanelOpacity = config.Bind<float>("Stats Tab", "PanelOpacity", 0.94f, "Tab overlay background opacity.");
			TabPosX = config.Bind<float>("Stats Tab", "PosX", -1f, "Tab overlay X in canvas pixels. Negative = default centered.");
			TabPosY = config.Bind<float>("Stats Tab", "PosY", -1f, "Tab overlay Y in canvas pixels. Negative = default centered.");
			ShowPing = config.Bind<bool>("Stats Tab", "ShowPing", true, "Show Photon ping next to player names (online games).");
			AutoCloseTabDuringPick = config.Bind<bool>("Stats Tab", "AutoCloseDuringPick", true, "Close the Tab overlay automatically when a card pick starts.");
			ShowTabInfoStats = config.Bind<bool>("Stats Tab", "ShowTabInfoStats", true, "If willuwontu's TabInfo is installed, also show stats other mods registered with it.");
			StatsPanelScale = config.Bind<float>("Stats Layout", "PanelScale", 1f, "Global UI scale multiplier.");
			StatsHudOffsetX = config.Bind<float>("Stats Layout", "HudOffsetX", 14f, "HUD distance from left edge.");
			StatsHudOffsetY = config.Bind<float>("Stats Layout", "HudOffsetY", 14f, "HUD distance from bottom edge.");
			StatsAccentR = config.Bind<float>("Stats Layout", "AccentR", 0.35f, "Accent color red.");
			StatsAccentG = config.Bind<float>("Stats Layout", "AccentG", 0.82f, "Accent color green.");
			StatsAccentB = config.Bind<float>("Stats Layout", "AccentB", 0.72f, "Accent color blue.");
		}
	}
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("com.ljindustries.rounds.promlgstats", "Pro MLG Stats", "1.0.5")]
	[BepInProcess("Rounds.exe")]
	public class Plugin : BaseUnityPlugin
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static UnityAction <>9__9_0;

			internal void <Start>b__9_0()
			{
			}
		}

		public const string ModId = "com.ljindustries.rounds.promlgstats";

		public const string ModName = "Pro MLG Stats";

		public const string Version = "1.0.5";

		internal static Configs Configs;

		public static Plugin Instance { get; private set; }

		private void Awake()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			Instance = this;
			Configs = new Configs(((BaseUnityPlugin)this).Config);
			try
			{
				Harmony val = new Harmony("com.ljindustries.rounds.promlgstats");
				Type[] types;
				try
				{
					types = typeof(Plugin).Assembly.GetTypes();
				}
				catch (ReflectionTypeLoadException ex)
				{
					types = ex.Types;
					ManualLogSource logger = ((BaseUnityPlugin)this).Logger;
					Exception?[] loaderExceptions = ex.LoaderExceptions;
					logger.LogWarning((object)$"GetTypes partial load: {((loaderExceptions != null) ? loaderExceptions.Length : 0)} loader error(s)");
				}
				Type[] array = types;
				foreach (Type type in array)
				{
					if (!(type == null))
					{
						try
						{
							val.CreateClassProcessor(type).Patch();
						}
						catch (Exception ex2)
						{
							((BaseUnityPlugin)this).Logger.LogWarning((object)("Harmony skip " + type.FullName + ": " + ex2.GetType().Name + ": " + ex2.Message));
						}
					}
				}
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Harmony patching failed: {arg}");
			}
		}

		private void Start()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			Unbound.RegisterClientSideMod("com.ljindustries.rounds.promlgstats");
			object obj = <>c.<>9__9_0;
			if (obj == null)
			{
				UnityAction val = delegate
				{
				};
				<>c.<>9__9_0 = val;
				obj = (object)val;
			}
			Unbound.RegisterMenu("Pro MLG Stats", (UnityAction)obj, (Action<GameObject>)MenuBuilder.Build, (GameObject)null, true);
			ExtensionMethods.GetOrAddComponent<StatsController>(((Component)this).gameObject, false);
			StatsController.RegisterHooks();
		}

		internal void Log(string message)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[Pro MLG Stats] " + message));
		}

		internal void LogWarn(string message)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("[Pro MLG Stats] " + message));
		}
	}
	[HarmonyPatch(typeof(CardChoice), "StartPick")]
	internal static class StartPickTrackerPatch
	{
		private static void Postfix(int pickerIDToSet)
		{
			PickPhase.NoteActingPicker(pickerIDToSet);
		}
	}
}
namespace ProMLGStats.Utils
{
	internal static class PickPhase
	{
		private static readonly FieldInfo PickerTypeField = AccessTools.Field(typeof(CardChoice), "pickerType");

		private static readonly FieldInfo SpawnedCardsField = AccessTools.Field(typeof(CardChoice), "spawnedCards");

		private static int _actingPickerId = -1;

		internal static void NoteActingPicker(int pickerId)
		{
			_actingPickerId = pickerId;
		}

		internal static void ClearActingPicker()
		{
			_actingPickerId = -1;
		}

		internal static Player GetCurrentPicker()
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			CardChoice instance = CardChoice.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return null;
			}
			if (instance.IsPicking && _actingPickerId >= 0)
			{
				Player val = FindPlayer(_actingPickerId);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			if (PickerTypeField != null && (int)(PickerType)PickerTypeField.GetValue(instance) == 0)
			{
				Player[] array = (((Object)(object)PlayerManager.instance != (Object)null) ? PlayerManager.instance.GetPlayersInTeam(instance.pickrID) : null);
				if (array != null && array.Length != 0)
				{
					return DesignateFromTeam(array);
				}
			}
			return FindPlayer(instance.pickrID);
		}

		internal static Player FindPlayer(int playerId)
		{
			List<Player> list = PlayerManager.instance?.players;
			if (list == null)
			{
				return null;
			}
			foreach (Player item in list)
			{
				if ((Object)(object)item != (Object)null && item.playerID == playerId)
				{
					return item;
				}
			}
			return null;
		}

		internal static List<GameObject> GetSpawnedCards()
		{
			CardChoice instance = CardChoice.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return null;
			}
			return SpawnedCardsField?.GetValue(instance) as List<GameObject>;
		}

		internal static bool PickerHoldsCardNamed(string cardName)
		{
			if (string.IsNullOrEmpty(cardName))
			{
				return false;
			}
			Player currentPicker = GetCurrentPicker();
			if ((Object)(object)currentPicker == (Object)null || !PlayerStatsSnapshot.IsLocallyControlled(currentPicker))
			{
				return false;
			}
			List<CardInfo> list = currentPicker.data?.currentCards;
			if (list == null)
			{
				return false;
			}
			foreach (CardInfo item in list)
			{
				if (!((Object)(object)item == (Object)null) && string.Equals(item.cardName, cardName, StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
			}
			return false;
		}

		private static Player DesignateFromTeam(Player[] team)
		{
			if (team == null || team.Length == 0)
			{
				return null;
			}
			Player val = null;
			Player val2 = null;
			foreach (Player val3 in team)
			{
				if (!((Object)(object)val3 == (Object)null))
				{
					if ((Object)(object)val2 == (Object)null || val3.playerID < val2.playerID)
					{
						val2 = val3;
					}
					if ((Object)(object)val == (Object)null && PlayerStatsSnapshot.IsLocallyControlled(val3))
					{
						val = val3;
					}
				}
			}
			return val ?? val2;
		}
	}
	internal static class RoundsWithBotsBridge
	{
		private const string ExtensionTypeName = "RoundsWithBots.Extensions.CharacterDataExtension";

		private const string AdditionalDataTypeName = "RoundsWithBots.Extensions.CharacterDataAdditionalData";

		private static bool _probed;

		private static bool _logged;

		private static MethodInfo _getAdditionalData;

		private static PropertyInfo _isBot;

		private static Type _playerAiPhilip;

		internal static bool IsAvailable
		{
			get
			{
				Probe();
				if (_getAdditionalData != null)
				{
					return _isBot != null;
				}
				return false;
			}
		}

		internal static bool IsBot(Player player)
		{
			if ((Object)(object)player?.data == (Object)null)
			{
				return false;
			}
			Probe();
			if (_getAdditionalData != null && _isBot != null)
			{
				try
				{
					object obj = _getAdditionalData.Invoke(null, new object[1] { player.data });
					if (obj != null)
					{
						object value = _isBot.GetValue(obj);
						if (value is bool && (bool)value)
						{
							return true;
						}
					}
				}
				catch
				{
				}
			}
			return HasEnabledAi(player);
		}

		internal static string DisplayName(Player player, string fallback)
		{
			if ((Object)(object)player == (Object)null || !IsBot(player))
			{
				if (!string.IsNullOrEmpty(fallback))
				{
					return fallback;
				}
				return "?";
			}
			return $"<color=#07e0f0>[BOT]</color> P{player.playerID + 1}";
		}

		private static bool HasEnabledAi(Player player)
		{
			if (_playerAiPhilip == null || (Object)(object)player == (Object)null)
			{
				return false;
			}
			try
			{
				Component component = ((Component)player).GetComponent(_playerAiPhilip);
				Behaviour val = (Behaviour)(((object)((component is Behaviour) ? component : null)) ?? ((object)/*isinst with value type is only supported in some contexts*/));
				return (Object)(object)val != (Object)null && val.enabled;
			}
			catch
			{
				return false;
			}
		}

		private static void Probe()
		{
			if (_probed)
			{
				return;
			}
			_probed = true;
			try
			{
				Type type = AccessTools.TypeByName("RoundsWithBots.Extensions.CharacterDataExtension");
				if (type != null)
				{
					_getAdditionalData = AccessTools.Method(type, "GetAdditionalData", new Type[1] { typeof(CharacterData) }, (Type[])null);
					Type type2 = AccessTools.TypeByName("RoundsWithBots.Extensions.CharacterDataAdditionalData") ?? _getAdditionalData?.ReturnType;
					_isBot = ((type2 == null) ? null : AccessTools.Property(type2, "IsBot"));
				}
			}
			catch
			{
				_getAdditionalData = null;
				_isBot = null;
			}
			_playerAiPhilip = AccessTools.TypeByName("PlayerAIPhilip");
			if (!_logged && _getAdditionalData != null && _isBot != null)
			{
				_logged = true;
				Plugin.Instance?.Log("RoundsWithBots detected - bots are listed separately and are not treated as the local player.");
			}
		}
	}
	internal static class TabInfoBridge
	{
		private const string ManagerTypeName = "TabInfo.Utils.TabInfoManager";

		private static bool _probed;

		private static MethodInfo _getVisibleStats;

		private static object _basicStats;

		private static FieldInfo _rowCategory;

		private static FieldInfo _rowStat;

		private static FieldInfo _rowValue;

		private static FieldInfo _categoryName;

		private static FieldInfo _statName;

		internal static bool IsAvailable
		{
			get
			{
				Probe();
				return _getVisibleStats != null;
			}
		}

		internal static IEnumerable<(string category, string label, string value)> GetExtensionStats(Player player)
		{
			if ((Object)(object)player == (Object)null || (Plugin.Configs != null && !Plugin.Configs.ShowTabInfoStats.Value))
			{
				yield break;
			}
			Probe();
			if (_getVisibleStats == null)
			{
				yield break;
			}
			IEnumerable enumerable;
			try
			{
				enumerable = _getVisibleStats.Invoke(null, new object[1] { player }) as IEnumerable;
			}
			catch (Exception ex)
			{
				Plugin.Instance?.LogWarn("TabInfo GetVisibleStats failed: " + ex.Message);
				yield break;
			}
			if (enumerable == null)
			{
				yield break;
			}
			foreach (object item in enumerable)
			{
				if (item == null)
				{
					continue;
				}
				string text;
				string text2;
				string text3;
				try
				{
					object obj = _rowCategory?.GetValue(item);
					if (obj == null || (_basicStats != null && obj == _basicStats))
					{
						continue;
					}
					object obj2 = _rowStat?.GetValue(item);
					text = _categoryName?.GetValue(obj) as string;
					text2 = ((obj2 != null) ? (_statName?.GetValue(obj2) as string) : null);
					text3 = _rowValue?.GetValue(item) as string;
					goto IL_0191;
				}
				catch
				{
				}
				continue;
				IL_0191:
				if (!string.IsNullOrEmpty(text2))
				{
					yield return (category: text ?? string.Empty, label: text2, value: text3 ?? string.Empty);
				}
			}
		}

		private static void Probe()
		{
			if (_probed)
			{
				return;
			}
			_probed = true;
			Type type = AccessTools.TypeByName("TabInfo.Utils.TabInfoManager");
			if (type == null)
			{
				return;
			}
			_getVisibleStats = AccessTools.Method(type, "GetVisibleStats", new Type[1] { typeof(Player) }, (Type[])null);
			if (_getVisibleStats == null)
			{
				return;
			}
			try
			{
				_basicStats = AccessTools.Field(type, "basicStats")?.GetValue(null) ?? AccessTools.Property(type, "basicStats")?.GetValue(null);
			}
			catch
			{
				_basicStats = null;
			}
			Type type2 = (_getVisibleStats.ReturnType.IsGenericType ? _getVisibleStats.ReturnType.GetGenericArguments()[0] : null);
			if (type2 == null)
			{
				_getVisibleStats = null;
				return;
			}
			_rowCategory = AccessTools.Field(type2, "category");
			_rowStat = AccessTools.Field(type2, "stat");
			_rowValue = AccessTools.Field(type2, "value");
			if (_rowCategory == null || _rowStat == null || _rowValue == null)
			{
				_getVisibleStats = null;
				return;
			}
			_categoryName = AccessTools.Field(_rowCategory.FieldType, "name");
			_statName = AccessTools.Field(_rowStat.FieldType, "name");
			Plugin.Instance?.Log("TabInfo detected — extension stats will be shown in the Tab panel.");
		}
	}
}
namespace ProMLGStats.UI
{
	internal static class MenuBuilder
	{
		public static void Build(GameObject menu)
		{
			//IL_048f: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a4: Unknown result type (might be due to invalid IL or missing references)
			Configs cfg = Plugin.Configs;
			TextMeshProUGUI val = default(TextMeshProUGUI);
			MenuHandler.CreateText("Pro MLG Stats", menu, ref val, 60, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
			MenuHandler.CreateText("Client-side only. Other players do not need this mod.", menu, ref val, 26, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
			MenuHandler.CreateText("Stats HUD", menu, ref val, 40, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
			MenuHandler.CreateToggle(cfg.EnableStatsHud.Value, "Enable HUD", menu, (UnityAction<bool>)delegate(bool v)
			{
				cfg.EnableStatsHud.Value = v;
				StatsController.Instance?.RebuildHud();
			}, 32, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
			MenuHandler.CreateToggle(cfg.StatsHudSimpleMode.Value, "Compact stat list", menu, (UnityAction<bool>)delegate(bool v)
			{
				cfg.StatsHudSimpleMode.Value = v;
				StatsController.Instance?.RebuildHud();
			}, 32, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
			MenuHandler.CreateToggle(cfg.HideStatsHudDuringPick.Value, "Hide HUD during pick", menu, (UnityAction<bool>)delegate(bool v)
			{
				cfg.HideStatsHudDuringPick.Value = v;
			}, 32, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
			MenuHandler.CreateToggle(cfg.HideStatsHudDuringBattle.Value, "Hide HUD during battle", menu, (UnityAction<bool>)delegate(bool v)
			{
				cfg.HideStatsHudDuringBattle.Value = v;
			}, 32, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
			MenuHandler.CreateToggle(cfg.ShowPickDeltasOnHud.Value, "Show card deltas while picking", menu, (UnityAction<bool>)delegate(bool v)
			{
				cfg.ShowPickDeltasOnHud.Value = v;
			}, 32, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
			Slider val2 = default(Slider);
			MenuHandler.CreateSlider("HUD opacity", menu, 30, 0f, 1f, cfg.StatsHudOpacity.Value, (UnityAction<float>)delegate(float v)
			{
				cfg.StatsHudOpacity.Value = v;
				StatsController.Instance?.RebuildHud();
			}, ref val2, false, (Color?)null, (Direction)0, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
			MenuHandler.CreateSlider("HUD text scale", menu, 30, 0.6f, 2f, cfg.StatsHudFontScale.Value, (UnityAction<float>)delegate(float v)
			{
				cfg.StatsHudFontScale.Value = v;
				StatsController.Instance?.RebuildHud();
			}, ref val2, false, (Color?)null, (Direction)0, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
			MenuHandler.CreateText("Tab overlay", menu, ref val, 40, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
			MenuHandler.CreateToggle(cfg.EnableStatsTab.Value, "Enable Tab overlay", menu, (UnityAction<bool>)delegate(bool v)
			{
				cfg.EnableStatsTab.Value = v;
				StatsController.Instance?.RebuildTab();
			}, 32, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
			MenuHandler.CreateToggle(cfg.EnableTabCompare.Value, "Enable compare mode", menu, (UnityAction<bool>)delegate(bool v)
			{
				cfg.EnableTabCompare.Value = v;
			}, 32, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
			MenuHandler.CreateToggle(cfg.AutoCloseTabDuringPick.Value, "Close automatically on pick", menu, (UnityAction<bool>)delegate(bool v)
			{
				cfg.AutoCloseTabDuringPick.Value = v;
			}, 32, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
			MenuHandler.CreateToggle(cfg.ShowPing.Value, "Show ping", menu, (UnityAction<bool>)delegate(bool v)
			{
				cfg.ShowPing.Value = v;
			}, 32, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
			if (TabInfoBridge.IsAvailable)
			{
				MenuHandler.CreateToggle(cfg.ShowTabInfoStats.Value, "Include TabInfo stats", menu, (UnityAction<bool>)delegate(bool v)
				{
					cfg.ShowTabInfoStats.Value = v;
					StatsController.Instance?.RebuildTab();
				}, 32, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
			}
			MenuHandler.CreateSlider("Tab panel width", menu, 30, 280f, 640f, cfg.TabPanelWidth.Value, (UnityAction<float>)delegate(float v)
			{
				cfg.TabPanelWidth.Value = v;
				StatsController.Instance?.RebuildTab();
			}, ref val2, false, (Color?)null, (Direction)0, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
			MenuHandler.CreateSlider("Global UI scale", menu, 30, 0.6f, 1.8f, cfg.StatsPanelScale.Value, (UnityAction<float>)delegate(float v)
			{
				cfg.StatsPanelScale.Value = v;
				StatsController.Instance?.RebuildHud();
				StatsController.Instance?.RebuildTab();
			}, ref val2, false, (Color?)null, (Direction)0, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
			MenuHandler.CreateText("Keys are rebindable in BepInEx/config/com.ljindustries.rounds.promlgstats.cfg " + $"(currently {cfg.StatsTabKey.Value} for the panel, {cfg.StatsHudToggleKey.Value} for the HUD).", menu, ref val, 24, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
		}
	}
	internal sealed class OverlayDrag : MonoBehaviour, IBeginDragHandler, IEventSystemHandler, IDragHandler, IEndDragHandler
	{
		internal RectTransform Target;

		internal bool ResizeWidth;

		private Vector2 _startPointer;

		private Vector2 _startPos;

		private Vector2 _startSize;

		public void OnBeginDrag(PointerEventData eventData)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)Target == (Object)null))
			{
				_startPos = Target.anchoredPosition;
				_startSize = Target.sizeDelta;
				ScreenToParent(eventData, out _startPointer);
			}
		}

		public void OnDrag(PointerEventData eventData)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00e6: 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_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: 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_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)Target == (Object)null))
			{
				ScreenToParent(eventData, out var local);
				Vector2 val = local - _startPointer;
				Vector2 overlaySize = StatsUiHelper.OverlaySize;
				if (ResizeWidth)
				{
					float num = Mathf.Min(640f, overlaySize.x * 0.55f);
					float num2 = Mathf.Clamp(_startSize.x - val.x, 280f, num);
					float num3 = _startSize.x - num2;
					Target.sizeDelta = new Vector2(num2, _startSize.y);
					Target.anchoredPosition = Clamp(_startPos + new Vector2(num3, 0f), Target.sizeDelta, overlaySize);
				}
				else
				{
					Target.anchoredPosition = Clamp(_startPos + val, _startSize, overlaySize);
				}
			}
		}

		public void OnEndDrag(PointerEventData eventData)
		{
			//IL_0026: 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_0064: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)Target == (Object)null) && Plugin.Configs != null)
			{
				Plugin.Configs.TabPosX.Value = Target.anchoredPosition.x;
				Plugin.Configs.TabPosY.Value = Target.anchoredPosition.y;
				Plugin.Configs.TabPanelWidth.Value = Target.sizeDelta.x;
			}
		}

		private void ScreenToParent(PointerEventData eventData, out Vector2 local)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			Transform parent = ((Transform)Target).parent;
			RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)(object)((parent is RectTransform) ? parent : null), eventData.position, eventData.pressEventCamera, ref local);
		}

		private static Vector2 Clamp(Vector2 pos, Vector2 size, Vector2 canvas)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			float num = 8f;
			pos.x = Mathf.Clamp(pos.x, num, Mathf.Max(num, canvas.x - size.x - num));
			pos.y = Mathf.Clamp(pos.y, num, Mathf.Max(num, canvas.y - size.y - num));
			return pos;
		}
	}
	internal sealed class StatsController : MonoBehaviour
	{
		private const string BlindDraftCardName = "Blind Draft";

		private StatsHudPanel _hud;

		private StatsTabOverlay _tab;

		private CardInfo _hoveredCard;

		private CardInfo _hoveredVisual;

		private PlayerStatsSnapshot _previewDelta;

		private readonly Dictionary<int, PlayerStatsSnapshot> _pickBaselines = new Dictionary<int, PlayerStatsSnapshot>();

		private float _refreshTimer;

		private static float _readyCacheUntil;

		private static bool _readyCache;

		private static readonly FieldInfo SpawnedCardsField = AccessTools.Field(typeof(CardChoice), "spawnedCards");

		private static readonly FieldInfo IsHoveredField = AccessTools.Field(typeof(CardVisuals), "isHovered");

		private static readonly FieldInfo IsSelectedField = AccessTools.Field(typeof(CardVisuals), "isSelected");

		private static readonly FieldInfo CurrentlySelectedCardField = AccessTools.Field(typeof(CardChoice), "currentlySelectedCard");

		private static readonly PropertyInfo CurrentlySelectedCardProp = AccessTools.Property(typeof(CardChoice), "currentlySelectedCard");

		internal static StatsController Instance { get; private set; }

		internal static bool InPickPhase { get; private set; }

		internal static bool InBattlePhase { get; private set; }

		internal static bool MatchSessionActive { get; private set; }

		internal static int CurrentRound { get; private set; }

		internal static int CurrentPoint { get; private set; }

		internal static string HoveredCardName => Instance?._hoveredCard?.cardName;

		internal static bool IsCardPickActive
		{
			get
			{
				if (InPickPhase && (Object)(object)CardChoice.instance != (Object)null)
				{
					return CardChoice.instance.IsPicking;
				}
				return false;
			}
		}

		private void Awake()
		{
			Instance = this;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			_hud = ((Component)this).gameObject.AddComponent<StatsHudPanel>();
			_tab = ((Component)this).gameObject.AddComponent<StatsTabOverlay>();
		}

		internal static void RegisterHooks()
		{
			GameModeManager.AddHook("GameStart", (Func<IGameModeHandler, IEnumerator>)OnGameStart);
			GameModeManager.AddHook("GameEnd", (Func<IGameModeHandler, IEnumerator>)OnGameEnd);
			GameModeManager.AddHook("PickStart", (Func<IGameModeHandler, IEnumerator>)OnPickStart);
			GameModeManager.AddHook("PickEnd", (Func<IGameModeHandler, IEnumerator>)OnPickEnd);
			GameModeManager.AddHook("PlayerPickStart", (Func<IGameModeHandler, IEnumerator>)OnPlayerPickStart);
			GameModeManager.AddHook("RoundStart", (Func<IGameModeHandler, IEnumerator>)OnRoundStart);
			GameModeManager.AddHook("PointStart", (Func<IGameModeHandler, IEnumerator>)OnPointStart);
			GameModeManager.AddHook("BattleStart", (Func<IGameModeHandler, IEnumerator>)OnBattleStart);
		}

		private static IEnumerator OnGameStart(IGameModeHandler gm)
		{
			MatchSessionActive = true;
			CurrentRound = 0;
			CurrentPoint = 0;
			InPickPhase = false;
			InBattlePhase = false;
			Instance?._tab?.SetOpen(open: false);
			Instance?.ClearPickBaselines();
			yield break;
		}

		private static IEnumerator OnGameEnd(IGameModeHandler gm)
		{
			MatchSessionActive = false;
			InPickPhase = false;
			InBattlePhase = false;
			Instance?._tab?.SetOpen(open: false);
			Instance?.ClearPickBaselines();
			yield break;
		}

		private static IEnumerator OnPickStart(IGameModeHandler gm)
		{
			InPickPhase = true;
			InBattlePhase = false;
			Instance?.CaptureAllPickBaselines();
			yield break;
		}

		private static IEnumerator OnPickEnd(IGameModeHandler gm)
		{
			InPickPhase = false;
			Instance?.ClearPreview();
			yield break;
		}

		private static IEnumerator OnPlayerPickStart(IGameModeHandler gm)
		{
			Instance?.CapturePickBaseline();
			Instance?.ClearPreview();
			yield return null;
			Instance?.CapturePickBaseline();
		}

		private static IEnumerator OnRoundStart(IGameModeHandler gm)
		{
			CurrentRound++;
			CurrentPoint = 0;
			InPickPhase = false;
			yield break;
		}

		private static IEnumerator OnPointStart(IGameModeHandler gm)
		{
			CurrentPoint++;
			yield break;
		}

		private static IEnumerator OnBattleStart(IGameModeHandler gm)
		{
			InBattlePhase = true;
			InPickPhase = false;
			yield break;
		}

		private void CapturePickBaseline()
		{
			Player val = PickPhase.GetCurrentPicker() ?? PlayerStatsSnapshot.LocalPlayer();
			if (!((Object)(object)val == (Object)null) && PlayerStatsSnapshot.TryFrom(val, out var snapshot))
			{
				_pickBaselines[val.playerID] = snapshot;
			}
		}

		private void CaptureAllPickBaselines()
		{
			foreach (Player item in PlayerStatsSnapshot.ActivePlayers())
			{
				if (PlayerStatsSnapshot.TryFrom(item, out var snapshot))
				{
					_pickBaselines[item.playerID] = snapshot;
				}
			}
		}

		private void CaptureMissingPickBaselines()
		{
			foreach (Player item in PlayerStatsSnapshot.ActivePlayers())
			{
				if (!_pickBaselines.ContainsKey(item.playerID) && PlayerStatsSnapshot.TryFrom(item, out var snapshot))
				{
					_pickBaselines[item.playerID] = snapshot;
				}
			}
		}

		private void ClearPickBaselines()
		{
			_pickBaselines.Clear();
		}

		private PlayerStatsSnapshot GetPickBaselineFor(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return null;
			}
			if (!_pickBaselines.TryGetValue(player.playerID, out var value))
			{
				return null;
			}
			return value;
		}

		internal static Player GetHudPlayer()
		{
			if (InPickPhase && (Object)(object)CardChoice.instance != (Object)null && CardChoice.instance.IsPicking)
			{
				return PickPhase.GetCurrentPicker() ?? PlayerStatsSnapshot.LocalPlayer();
			}
			return PlayerStatsSnapshot.LocalPlayer();
		}

		internal static bool IsWatchingOtherPicker()
		{
			if (!InPickPhase || (Object)(object)CardChoice.instance == (Object)null || !CardChoice.instance.IsPicking)
			{
				return false;
			}
			Player currentPicker = PickPhase.GetCurrentPicker();
			Player val = PlayerStatsSnapshot.LocalPlayer();
			if ((Object)(object)currentPicker == (Object)null || (Object)(object)val == (Object)null)
			{
				return false;
			}
			return currentPicker.playerID != val.playerID;
		}

		internal void NotifyHoveredCard(Player picker, CardInfo cardInfo, CardInfo pickVisual = null)
		{
			if ((Object)(object)picker == (Object)null || (Object)(object)cardInfo == (Object)null)
			{
				ClearPreview();
			}
			else if (!((Object)(object)_hoveredCard == (Object)(object)cardInfo) || !((Object)(object)_hoveredVisual == (Object)(object)pickVisual) || _previewDelta == null)
			{
				_hoveredCard = cardInfo;
				_hoveredVisual = pickVisual;
				if (CardStatPreview.TryPreview(picker, cardInfo, out var delta, pickVisual))
				{
					_previewDelta = delta;
				}
				else
				{
					_previewDelta = null;
				}
				_hud?.SetPreviewDelta(_previewDelta);
				_refreshTimer = 0f;
			}
		}

		internal void ClearPreview()
		{
			bool num = (Object)(object)_hoveredCard != (Object)null || _previewDelta != null;
			_hoveredCard = null;
			_hoveredVisual = null;
			_previewDelta = null;
			_hud?.SetPreviewDelta(null);
			if (num)
			{
				_refreshTimer = 0f;
			}
		}

		internal static bool InActiveMatch()
		{
			if (!HasReadyPlayers())
			{
				return false;
			}
			if (MatchSessionActive)
			{
				return true;
			}
			return IsSandboxMode();
		}

		private static bool HasReadyPlayers()
		{
			if (Time.unscaledTime < _readyCacheUntil)
			{
				return _readyCache;
			}
			List<Player> list = PlayerManager.instance?.players;
			bool flag = false;
			if (list != null && list.Count > 0)
			{
				foreach (Player item in list)
				{
					if ((Object)(object)item?.data?.weaponHandler?.gun != (Object)null && (Object)(object)item.data.block != (Object)null)
					{
						flag = true;
						break;
					}
				}
			}
			_readyCache = flag;
			_readyCacheUntil = Time.unscaledTime + 0.25f;
			return flag;
		}

		private static bool IsSandboxMode()
		{
			try
			{
				if (GameModeManager.CurrentHandler is SandboxHandler)
				{
					return true;
				}
				string currentHandlerID = GameModeManager.CurrentHandlerID;
				if (!string.IsNullOrEmpty(currentHandlerID) && currentHandlerID.IndexOf("Sandbox", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return true;
				}
			}
			catch
			{
			}
			return false;
		}

		internal void RebuildHud()
		{
			_hud?.Rebuild();
		}

		internal void RebuildTab()
		{
			_tab?.RebuildLayout();
		}

		private void Update()
		{
			HandleTabToggle();
			HandleHudToggle();
			_tab?.HandleShortcuts();
			PollHoveredCard();
			PingTracker.Tick();
			_refreshTimer -= Time.unscaledDeltaTime;
			if (!(_refreshTimer > 0f))
			{
				_refreshTimer = (((Object)(object)_tab != (Object)null && _tab.IsOpen) ? 0.25f : 0.2f);
				if (InPickPhase)
				{
					CaptureMissingPickBaselines();
				}
				Player hudPlayer = GetHudPlayer();
				_hud?.Refresh(GetPickBaselineFor(hudPlayer), hudPlayer, IsWatchingOtherPicker());
				if ((Object)(object)_tab != (Object)null && _tab.IsOpen)
				{
					_tab.Refresh();
				}
			}
		}

		private static void HandleTabToggle()
		{
			//IL_004d: 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)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Instance?._tab == (Object)null)
			{
				return;
			}
			if (!InActiveMatch())
			{
				if (Instance._tab.IsOpen)
				{
					Instance._tab.SetOpen(open: false);
				}
				return;
			}
			KeyCode value = Plugin.Configs.StatsTabKey.Value;
			if ((int)value != 0 && Input.GetKeyDown(value))
			{
				Instance._tab.Toggle();
			}
			if (Input.GetKeyDown((KeyCode)27) && Instance._tab.IsOpen)
			{
				Instance._tab.SetOpen(open: false);
			}
		}

		internal static void HandleHudToggle()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)Instance == (Object)null))
			{
				KeyCode value = Plugin.Configs.StatsHudToggleKey.Value;
				if ((int)value != 0 && Input.GetKeyDown(value))
				{
					Plugin.Configs.StatsHudVisible.Value = !Plugin.Configs.StatsHudVisible.Value;
				}
			}
		}

		private void PollHoveredCard()
		{
			if (!InPickPhase)
			{
				if (_previewDelta != null)
				{
					ClearPreview();
				}
				return;
			}
			if ((Object)(object)CardChoice.instance == (Object)null || !CardChoice.instance.IsPicking)
			{
				if (_previewDelta != null)
				{
					ClearPreview();
				}
				return;
			}
			Player currentPicker = PickPhase.GetCurrentPicker();
			CardInfo source;
			CardInfo visual;
			if ((Object)(object)currentPicker == (Object)null)
			{
				if (_previewDelta != null)
				{
					ClearPreview();
				}
			}
			else if (PickPhase.PickerHoldsCardNamed("Blind Draft"))
			{
				if (_previewDelta != null || (Object)(object)_hoveredCard != (Object)null)
				{
					ClearPreview();
				}
			}
			else if (!TryGetHighlightedCard(out source, out visual))
			{
				if (_previewDelta != null || (Object)(object)_hoveredCard != (Object)null)
				{
					ClearPreview();
				}
			}
			else
			{
				NotifyHoveredCard(currentPicker, source, visual);
			}
		}

		private static bool TryGetHighlightedCard(out CardInfo source, out CardInfo visual)
		{
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			source = null;
			visual = null;
			CardChoice instance = CardChoice.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return false;
			}
			object raw = CurrentlySelectedCardField?.GetValue(instance) ?? CurrentlySelectedCardProp?.GetValue(instance);
			if (TryResolveCard(instance, raw, out source, out visual))
			{
				return true;
			}
			if (!(SpawnedCardsField?.GetValue(instance) is IList list))
			{
				return false;
			}
			CardInfo val = null;
			CardInfo val2 = null;
			float num = 1.04f;
			foreach (object item in list)
			{
				GameObject val3 = (GameObject)((item is GameObject) ? item : null);
				if (val3 == null || (Object)(object)val3 == (Object)null)
				{
					continue;
				}
				CardInfo component = val3.GetComponent<CardInfo>();
				if (!((Object)(object)component == (Object)null))
				{
					CardVisuals componentInChildren = val3.GetComponentInChildren<CardVisuals>(true);
					if ((Object)(object)componentInChildren != (Object)null && (ReadFlag(componentInChildren, IsHoveredField) || ReadFlag(componentInChildren, IsSelectedField)))
					{
						visual = component;
						source = instance.GetSourceCard(component) ?? component.sourceCard ?? component;
						return (Object)(object)source != (Object)null;
					}
					float x = val3.transform.localScale.x;
					if (!(x < num))
					{
						num = x;
						val2 = component;
						val = instance.GetSourceCard(component) ?? component.sourceCard ?? component;
					}
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			source = val;
			visual = val2;
			return true;
		}

		private static bool TryResolveCard(CardChoice choice, object raw, out CardInfo source, out CardInfo visual)
		{
			source = null;
			visual = null;
			if (raw == null)
			{
				return false;
			}
			GameObject val = (GameObject)((raw is GameObject) ? raw : null);
			CardInfo val2 = (CardInfo)((raw is CardInfo) ? raw : null);
			if (val2 != null)
			{
				visual = val2;
				if (val == null)
				{
					val = ((Component)val2).gameObject;
				}
			}
			if ((Object)(object)visual == (Object)null && (Object)(object)val != (Object)null)
			{
				visual = val.GetComponent<CardInfo>() ?? val.GetComponentInChildren<CardInfo>();
			}
			if ((Object)(object)visual == (Object)null)
			{
				return false;
			}
			source = choice.GetSourceCard(visual) ?? visual.sourceCard ?? visual;
			return (Object)(object)source != (Object)null;
		}

		private static bool ReadFlag(CardVisuals visuals, FieldInfo field)
		{
			if (field == null || (Object)(object)visuals == (Object)null)
			{
				return false;
			}
			try
			{
				object value = field.GetValue(visuals);
				return value is bool && (bool)value;
			}
			catch
			{
				return false;
			}
		}
	}
	internal sealed class StatsHudPanel : MonoBehaviour
	{
		private const float HorizontalPadding = 12f;

		private const float VerticalPadding = 12f;

		private GameObject _root;

		private TextMeshProUGUI _body;

		private PlayerStatsSnapshot _previewDelta;

		internal void Rebuild()
		{
			if ((Object)(object)_root != (Object)null)
			{
				Object.Destroy((Object)(object)_root);
				_root = null;
				_body = null;
			}
		}

		internal void EnsureBuilt()
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: 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_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_root != (Object)null) && StatsUiHelper.OverlayReady)
			{
				float uiScale = StatsUiHelper.UiScale;
				float num = GetPanelWidth() * uiScale;
				Vector2 anchoredPos = default(Vector2);
				((Vector2)(ref anchoredPos))..ctor(Plugin.Configs.StatsHudOffsetX.Value * uiScale, Plugin.Configs.StatsHudOffsetY.Value * uiScale);
				_root = StatsUiHelper.CreateModernPanel(StatsUiHelper.OverlayRoot, "MM_StatsHud", new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(0f, 0f), anchoredPos, new Vector2(num, 160f * uiScale), 0f);
				Image component = _root.GetComponent<Image>();
				if ((Object)(object)component != (Object)null)
				{
					((Graphic)component).color = new Color(0f, 0f, 0f, 0f);
					((Graphic)component).raycastTarget = false;
				}
				_body = StatsUiHelper.CreateText(_root.transform, "Body", "", StatsUiHelper.BaseFont, (TextAlignmentOptions)257);
				RectTransform rectTransform = ((TMP_Text)_body).rectTransform;
				rectTransform.anchorMin = Vector2.zero;
				rectTransform.anchorMax = Vector2.one;
				rectTransform.offsetMin = new Vector2(12f, 12f);
				rectTransform.offsetMax = new Vector2(-12f, -12f);
				((TMP_Text)_body).enableWordWrapping = true;
				((TMP_Text)_body).overflowMode = (TextOverflowModes)0;
				((Graphic)_body).raycastTarget = false;
			}
		}

		internal void SetPreviewDelta(PlayerStatsSnapshot delta)
		{
			_previewDelta = delta;
		}

		internal void Refresh(PlayerStatsSnapshot pickBaseline, Player hudPlayer, bool watchingPicker)
		{
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			bool value = Plugin.Configs.StatsHudVisible.Value;
			bool flag = StatsController.InActiveMatch();
			if ((Object)(object)hudPlayer == (Object)null || !PlayerStatsSnapshot.TryFrom(hudPlayer, out var snapshot))
			{
				if ((Object)(object)_root != (Object)null)
				{
					_root.SetActive(false);
				}
				return;
			}
			if (!value || !flag)
			{
				if ((Object)(object)_root != (Object)null)
				{
					_root.SetActive(false);
				}
				return;
			}
			EnsureBuilt();
			if (!((Object)(object)_root == (Object)null) && !((Object)(object)_body == (Object)null))
			{
				_root.SetActive(true);
				((TMP_Text)_body).lineSpacing = 2f;
				((TMP_Text)_body).fontSize = StatsUiHelper.BaseFont;
				((Graphic)_body).color = Color.white;
				((TMP_Text)_body).outlineWidth = 0.35f;
				((TMP_Text)_body).outlineColor = Color32.op_Implicit(new Color(0f, 0f, 0f, 0.95f));
				((TMP_Text)_body).fontMaterial.EnableKeyword("OUTLINE_ON");
				bool isCardPickActive = StatsController.IsCardPickActive;
				string text = (watchingPicker ? " · picking" : "");
				if (isCardPickActive && !string.IsNullOrEmpty(StatsController.HoveredCardName))
				{
					text = text + " · " + StatsController.HoveredCardName;
				}
				string text2 = StatsViewBuilder.BuildHud(snapshot, simple: true, isCardPickActive ? null : pickBaseline, isCardPickActive ? _previewDelta : null, null, string.IsNullOrEmpty(text) ? null : text, StatsController.InBattlePhase, isCardPickActive);
				if (((TMP_Text)_body).text != text2)
				{
					((TMP_Text)_body).text = text2;
					LayoutToContent();
				}
			}
		}

		private void LayoutToContent()
		{
			//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_0052: 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_00a2: 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_0102: 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_0120: 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_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			float uiScale = StatsUiHelper.UiScale;
			Vector2 overlaySize = StatsUiHelper.OverlaySize;
			float num = GetPanelWidth() * uiScale;
			float num2 = 0.72f;
			bool visible = false;
			((TMP_Text)_body).ForceMeshUpdate();
			float num3 = Mathf.Max(((TMP_Text)_body).preferredHeight, 36f) + 24f + 6f;
			num3 = Mathf.Min(num3, Mathf.Max(64f, overlaySize.y - 24f));
			num = Mathf.Min(num, Mathf.Max(120f, overlaySize.x - 24f));
			float num4 = Mathf.Clamp(Plugin.Configs.StatsHudOffsetX.Value * uiScale, 8f, Mathf.Max(8f, overlaySize.x - num - 8f));
			float num5 = Mathf.Clamp(Plugin.Configs.StatsHudOffsetY.Value * uiScale, 8f, Mathf.Max(8f, overlaySize.y - num3 - 8f));
			StatsUiHelper.ApplyRect(_root, new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(num4, num5), new Vector2(num, num3));
			Image component = _root.GetComponent<Image>();
			if ((Object)(object)component != (Object)null)
			{
				((Graphic)component).color = new Color(0.02f, 0.03f, 0.05f, num2);
				((Graphic)component).raycastTarget = false;
			}
			StatsUiHelper.SetAccentVisible(_root, visible);
			Transform val = _root.transform.Find("AccentTop") ?? _root.transform.Find("Accent");
			Transform val2 = _root.transform.Find("AccentBottom");
			if ((Object)(object)val != (Object)null)
			{
				((Graphic)((Component)val).GetComponent<Image>()).color = StatsUiHelper.AccentColor;
			}
			if ((Object)(object)val2 != (Object)null)
			{
				((Graphic)((Component)val2).GetComponent<Image>()).color = StatsUiHelper.AccentColor;
			}
		}

		private static float GetPanelWidth()
		{
			return 260f;
		}
	}
	internal sealed class StatsTabOverlay : MonoBehaviour
	{
		private GameObject _root;

		private TextMeshProUGUI _title;

		private TextMeshProUGUI _hint;

		private RectTransform _content;

		private readonly List<TextMeshProUGUI> _playerBlocks = new List<TextMeshProUGUI>();

		private bool _compareMode;

		private int _compareTargetPlayerId = -1;

		private PlayerStatsSnapshot _pinnedLocal;

		private int _pinnedLocalPlayerId = -1;

		internal bool IsOpen { get; private set; }

		internal void EnsureBuilt()
		{
			//IL_003d: 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_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: 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_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Expected O, but got Unknown
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Expected O, but got Unknown
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b9: Expected O, but got Unknown
			//IL_02e1: 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_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_031f: 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_0386: Unknown result type (might be due to invalid IL or missing references)
			//IL_038c: Expected O, but got Unknown
			//IL_03a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_043a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0440: Expected O, but got Unknown
			//IL_046e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0488: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f8: Expected O, but got Unknown
			if (!((Object)(object)_root != (Object)null) && StatsUiHelper.OverlayReady)
			{
				ApplyPanelLayout();
				_title = StatsUiHelper.CreateText(_root.transform, "Title", "Player Stats", StatsUiHelper.TitleFont, (TextAlignmentOptions)257, StatsUiHelper.TitleColor);
				RectTransform rectTransform = ((TMP_Text)_title).rectTransform;
				rectTransform.anchorMin = new Vector2(0f, 1f);
				rectTransform.anchorMax = new Vector2(1f, 1f);
				rectTransform.pivot = new Vector2(0f, 1f);
				rectTransform.anchoredPosition = new Vector2(18f, -12f);
				rectTransform.sizeDelta = new Vector2(-18f, 26f);
				_hint = StatsUiHelper.CreateText(_root.transform, "Hint", "", StatsUiHelper.BaseFont * 0.78f, (TextAlignmentOptions)257, StatsUiHelper.HintColor);
				RectTransform rectTransform2 = ((TMP_Text)_hint).rectTransform;
				rectTransform2.anchorMin = new Vector2(0f, 1f);
				rectTransform2.anchorMax = new Vector2(1f, 1f);
				rectTransform2.pivot = new Vector2(0f, 1f);
				rectTransform2.anchoredPosition = new Vector2(18f, -36f);
				rectTransform2.sizeDelta = new Vector2(-18f, 16f);
				RectTransform component = ((Component)StatsUiHelper.CreateGhostButton(_root.transform, "Close", (UnityAction)delegate
				{
					SetOpen(open: false);
				}, new Vector2(72f, 24f))).GetComponent<RectTransform>();
				component.anchorMin = new Vector2(1f, 1f);
				component.anchorMax = new Vector2(1f, 1f);
				component.pivot = new Vector2(1f, 1f);
				component.anchoredPosition = new Vector2(-14f, -12f);
				RectTransform component2 = ((Component)StatsUiHelper.CreateGhostButton(_root.transform, "Compare", new UnityAction(ToggleCompareMode), new Vector2(78f, 24f))).GetComponent<RectTransform>();
				component2.anchorMin = new Vector2(1f, 1f);
				component2.anchorMax = new Vector2(1f, 1f);
				component2.pivot = new Vector2(1f, 1f);
				component2.anchoredPosition = new Vector2(-92f, -12f);
				GameObject val = new GameObject("Scroll", new Type[3]
				{
					typeof(RectTransform),
					typeof(ScrollRect),
					typeof(Image)
				});
				val.transform.SetParent(_root.transform, false);
				RectTransform component3 = val.GetComponent<RectTransform>();
				component3.anchorMin = new Vector2(0f, 0f);
				component3.anchorMax = new Vector2(1f, 1f);
				component3.offsetMin = new Vector2(8f, 10f);
				component3.offsetMax = new Vector2(-8f, -56f);
				Image component4 = val.GetComponent<Image>();
				((Graphic)component4).color = new Color(1f, 1f, 1f, 0f);
				((Graphic)component4).raycastTarget = false;
				GameObject val2 = new GameObject("Viewport", new Type[3]
				{
					typeof(RectTransform),
					typeof(Image),
					typeof(Mask)
				});
				val2.transform.SetParent(val.transform, false);
				RectTransform component5 = val2.GetComponent<RectTransform>();
				component5.anchorMin = Vector2.zero;
				component5.anchorMax = Vector2.one;
				component5.offsetMin = Vector2.zero;
				component5.offsetMax = Vector2.zero;
				Image component6 = val2.GetComponent<Image>();
				((Graphic)component6).color = new Color(1f, 1f, 1f, 0.01f);
				((Graphic)component6).raycastTarget = true;
				val2.GetComponent<Mask>().showMaskGraphic = false;
				GameObject val3 = new GameObject("Content", new Type[3]
				{
					typeof(RectTransform),
					typeof(VerticalLayoutGroup),
					typeof(ContentSizeFitter)
				});
				val3.transform.SetParent(val2.transform, false);
				_content = val3.GetComponent<RectTransform>();
				_content.anchorMin = new Vector2(0f, 1f);
				_content.anchorMax = new Vector2(1f, 1f);
				_content.pivot = new Vector2(0.5f, 1f);
				_content.anchoredPosition = Vector2.zero;
				_content.sizeDelta = new Vector2(0f, 0f);
				VerticalLayoutGroup component7 = val3.GetComponent<VerticalLayoutGroup>();
				((HorizontalOrVerticalLayoutGroup)component7).spacing = 8f;
				((LayoutGroup)component7).padding = new RectOffset(10, 10, 4, 8);
				((HorizontalOrVerticalLayoutGroup)component7).childControlHeight = true;
				((HorizontalOrVerticalLayoutGroup)component7).childControlWidth = true;
				((HorizontalOrVerticalLayoutGroup)component7).childForceExpandHeight = false;
				((HorizontalOrVerticalLayoutGroup)component7).childForceExpandWidth = true;
				((LayoutGroup)component7).childAlignment = (TextAnchor)0;
				val3.GetComponent<ContentSizeFitter>().verticalFit = (FitMode)2;
				ScrollRect component8 = val.GetComponent<ScrollRect>();
				component8.viewport = component5;
				component8.content = _content;
				component8.horizontal = false;
				component8.vertical = true;
				component8.scrollSensitivity = 28f;
				component8.movementType = (MovementType)2;
				component8.verticalScrollbar = null;
				component8.horizontalScrollbar = null;
				component8.inertia = true;
				Image component9 = _root.GetComponent<Image>();
				if ((Object)(object)component9 != (Object)null)
				{
					((Graphic)component9).raycastTarget = false;
				}
				AddDragHandles();
				_root.SetActive(false);
			}
		}

		internal void RebuildLayout()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_root == (Object)null))
			{
				ApplyPanelLayout();
				Image component = _root.GetComponent<Image>();
				if ((Object)(object)component != (Object)null)
				{
					StatsUiHelper.ApplyRounded(component, StatsUiHelper.PanelColor);
					((Graphic)component).raycastTarget = false;
				}
				StatsUiHelper.SetAccentVisible(_root, visible: false);
			}
		}

		private void ApplyPanelLayout()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: 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_0050: 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_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_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: 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_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: 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_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			if (StatsUiHelper.OverlayReady)
			{
				Vector2 overlaySize = StatsUiHelper.OverlaySize;
				float num = 16f;
				float num2 = Mathf.Clamp(Plugin.Configs.TabPanelWidth.Value, 280f, Mathf.Min(640f, overlaySize.x * 0.55f));
				float num3 = Mathf.Min(overlaySize.y * 0.74f, overlaySize.y - num * 2f);
				Vector2 savedOrDefaultPosition = GetSavedOrDefaultPosition(overlaySize, num2, num3);
				if ((Object)(object)_root == (Object)null)
				{
					_root = StatsUiHelper.CreateGlassPanel(StatsUiHelper.OverlayRoot, "MM_StatsTab", savedOrDefaultPosition, new Vector2(num2, num3), StatsUiHelper.PanelColor.a);
				}
				else
				{
					StatsUiHelper.ApplyRect(_root, Vector2.zero, Vector2.zero, Vector2.zero, savedOrDefaultPosition, new Vector2(num2, num3));
				}
			}
		}

		private static Vector2 GetSavedOrDefaultPosition(Vector2 canvas, float width, float height)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: 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_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.Configs.TabPosX.Value < 0f || Plugin.Configs.TabPosY.Value < 0f)
			{
				return new Vector2((canvas.x - width) * 0.5f, (canvas.y - height) * 0.5f);
			}
			return new Vector2(Mathf.Clamp(Plugin.Configs.TabPosX.Value, 8f, Mathf.Max(8f, canvas.x - width - 8f)), Mathf.Clamp(Plugin.Configs.TabPosY.Value, 8f, Mathf.Max(8f, canvas.y - height - 8f)));
		}

		private void AddDragHandles()
		{
			//IL_0077: 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)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: 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_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: 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_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: 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)
			if (!((Object)(object)_root == (Object)null) && !((Object)(object)_root.transform.Find("HeaderDrag") != (Object)null))
			{
				RectTransform component = _root.GetComponent<RectTransform>();
				GameObject val = new GameObject("HeaderDrag", new Type[4]
				{
					typeof(RectTransform),
					typeof(CanvasRenderer),
					typeof(Image),
					typeof(OverlayDrag)
				});
				val.transform.SetParent(_root.transform, false);
				val.transform.SetSiblingIndex(0);
				RectTransform component2 = val.GetComponent<RectTransform>();
				component2.anchorMin = new Vector2(0f, 1f);
				component2.anchorMax = new Vector2(1f, 1f);
				component2.pivot = new Vector2(0.5f, 1f);
				component2.anchoredPosition = Vector2.zero;
				component2.sizeDelta = new Vector2(0f, 58f);
				Image component3 = val.GetComponent<Image>();
				((Graphic)component3).color = new Color(1f, 1f, 1f, 0.01f);
				((Graphic)component3).raycastTarget = true;
				val.GetComponent<OverlayDrag>().Target = component;
				GameObject val2 = new GameObject("Resize", new Type[4]
				{
					typeof(RectTransform),
					typeof(CanvasRenderer),
					typeof(Image),
					typeof(OverlayDrag)
				});
				val2.transform.SetParent(_root.transform, false);
				RectTransform component4 = val2.GetComponent<RectTransform>();
				component4.anchorMin = new Vector2(0f, 0f);
				component4.anchorMax = new Vector2(0f, 1f);
				component4.pivot = new Vector2(0f, 0.5f);
				component4.offsetMin = new Vector2(0f, 0f);
				component4.offsetMax = new Vector2(12f, -58f);
				Image component5 = val2.GetComponent<Image>();
				((Graphic)component5).color = new Color(1f, 1f, 1f, 0.01f);
				((Graphic)component5).raycastTarget = true;
				OverlayDrag component6 = val2.GetComponent<OverlayDrag>();
				component6.Target = component;
				component6.ResizeWidth = true;
				Transform obj = _root.transform.Find("Close_Btn");
				if (obj != null)
				{
					obj.SetAsLastSibling();
				}
				Transform obj2 = _root.transform.Find("Compare_Btn");
				if (obj2 != null)
				{
					obj2.SetAsLastSibling();
				}
			}
		}

		internal void SetOpen(bool open)
		{
			bool flag = open && StatsController.InActiveMatch();
			if (flag)
			{
				EnsureBuilt();
			}
			IsOpen = flag;
			if ((Object)(object)_root != (Object)null)
			{
				_root.SetActive(flag);
			}
			if (flag)
			{
				RebuildLayout();
				EnsureCompareTarget();
				Refresh();
			}
		}

		internal void Toggle()
		{
			SetOpen(!IsOpen);
		}

		internal void ToggleCompareMode()
		{
			_compareMode = !_compareMode;
			EnsureCompareTarget();
			Refresh();
		}

		internal void CycleCompareTarget(int direction)
		{
			if (!_compareMode)
			{
				return;
			}
			List<Player> otherPlayers = GetOtherPlayers();
			if (otherPlayers.Count != 0)
			{
				int num = otherPlayers.FindIndex((Player p) => p.playerID == _compareTargetPlayerId);
				if (num < 0)
				{
					num = 0;
				}
				num = (num + direction + otherPlayers.Count) % otherPlayers.Count;
				_compareTargetPlayerId = otherPlayers[num].playerID;
				Refresh();
			}
		}

		internal void PinLocalBaseline()
		{
			Player val = PlayerStatsSnapshot.LocalPlayer();
			if (!((Object)(object)val == (Object)null) && PlayerStatsSnapshot.TryFrom(val, out var snapshot))
			{
				_pinnedLocal = snapshot;
				_pinnedLocalPlayerId = val.playerID;
			}
		}

		internal void ResetPinnedBaseline()
		{
			_pinnedLocal = null;
			_pinnedLocalPlayerId = -1;
		}

		internal void HandleShortcuts()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			if (!IsOpen)
			{
				return;
			}
			KeyCode value = Plugin.Configs.TabCompareKey.Value;
			if ((int)value != 0 && Input.GetKeyDown(value))
			{
				ToggleCompareMode();
			}
			if (_compareMode)
			{
				if (Input.GetKeyDown((KeyCode)91) || Input.GetKeyDown((KeyCode)44))
				{
					CycleCompareTarget(-1);
				}
				if (Input.GetKeyDown((KeyCode)93) || Input.GetKeyDown((KeyCode)46))
				{
					CycleCompareTarget(1);
				}
			}
			if (Input.GetKeyDown((KeyCode)112))
			{
				PinLocalBaseline();
			}
			if (Input.GetKeyDown((KeyCode)8) || Input.GetKeyDown((KeyCode)127))
			{
				ResetPinnedBaseline();
			}
		}

		internal void Refresh()
		{
			if (!((Object)(object)_root == (Object)null) && _root.activeSelf)
			{
				if (_compareMode)
				{
					RefreshCompareView();
				}
				else
				{
					RefreshAllPlayersView();
				}
			}
		}

		private void RefreshAllPlayersView()
		{
			List<Player> list = new List<Player>();
			foreach (Player item in PlayerStatsSnapshot.ActivePlayers())
			{
				list.Add(item);
			}
			EnsureBlockCount(list.Count);
			bool flag = false;
			for (int i = 0; i < _playerBlocks.Count; i++)
			{
				bool flag2 = i < list.Count;
				GameObject gameObject = ((Component)((TMP_Text)_playerBlocks[i]).transform.parent).gameObject;
				if (gameObject.activeSelf != flag2)
				{
					gameObject.SetActive(flag2);
					flag = true;
				}
				if (flag2)
				{
					if (!PlayerStatsSnapshot.TryFrom(list[i], out var snapshot))
					{
						flag |= AssignBlockText(_playerBlocks[i], "Unavailable");
						continue;
					}
					PlayerStatsSnapshot pinnedBaselineFor = GetPinnedBaselineFor(list[i]);
					string text = ((pinnedBaselineFor != null) ? StatsViewBuilder.BuildHud(snapshot, simple: false, pinnedBaselineFor, null, TabInfoBridge.GetExtensionStats(list[i])) : StatsViewBuilder.BuildTabBlock(snapshot, TabInfoBridge.GetExtensionStats(list[i])));
					flag |= AssignBlockText(_playerBlocks[i], text);
				}
			}
			if (flag)
			{
				RelayoutBlocks();
			}
			((TMP_Text)_title).text = FormatAllPlayersTitle();
			((TMP_Text)_hint).text = "Drag the header to move";
		}

		private void RefreshCompareView()
		{
			Player val = PlayerStatsSnapshot.LocalPlayer();
			if ((Object)(object)val == (Object)null)
			{
				using IEnumerator<Player> enumerator = PlayerStatsSnapshot.ActivePlayers().GetEnumerator();
				if (enumerator.MoveNext())
				{
					val = enumerator.Current;
				}
			}
			List<Player> otherPlayers = GetOtherPlayers();
			Player val2 = otherPlayers.Find((Player p) => p.playerID == _compareTargetPlayerId) ?? ((otherPlayers.Count > 0) ? otherPlayers[0] : null);
			if ((Object)(object)val2 != (Object)null)
			{
				_compareTargetPlayerId = val2.playerID;
			}
			EnsureBlockCount((!((Object)(object)val2 != (Object)null)) ? 1 : 2);
			for (int num = 0; num < _playerBlocks.Count; num++)
			{
				((Component)((TMP_Text)_playerBlocks[num]).transform.parent).gameObject.SetActive(num < ((!((Object)(object)val2 != (Object)null)) ? 1 : 2));
			}
			PlayerStatsSnapshot snapshot2;
			if ((Object)(object)val == (Object)null || !PlayerStatsSnapshot.TryFrom(val, out var snapshot))
			{
				AssignBlockText(_playerBlocks[0], "Local player unavailable");
				RelayoutBlocks();
				((TMP_Text)_title).text = "Compare";
				((TMP_Text)_hint).text = "No local player";
			}
			else if ((Object)(object)val2 == (Object)null || !PlayerStatsSnapshot.TryFrom(val2, out snapshot2))
			{
				AssignBlockText(_playerBlocks[0], StatsViewBuilder.BuildTabBlock(snapshot, TabInfoBridge.GetExtensionStats(val)));
				RelayoutBlocks();
				((TMP_Text)_title).text = "Compare";
				((TMP_Text)_hint).text = "Need another player to compare";
			}
			else
			{
				PlayerStatsSnapshot opponent = snapshot2;
				PlayerStatsSnapshot pinnedLocal = ((_pinnedLocal != null && _pinnedLocalPlayerId == val.playerID) ? _pinnedLocal : null);
				AssignBlockText(_playerBlocks[0], StatsViewBuilder.BuildTabCompare(snapshot, opponent, pinnedLocal, TabInfoBridge.GetExtensionStats(val)));
				AssignBlockText(_playerBlocks[1], StatsViewBuilder.BuildTabBlock(snapshot2, TabInfoBridge.GetExtensionStats(val2)));
				RelayoutBlocks();
				((TMP_Text)_title).text = "You vs " + snapshot2.PlayerName;
				((TMP_Text)_hint).text = "[ ] switch player · C back to all";
			}
		}

		private static string FormatAllPlayersTitle()
		{
			string text = $"All players · R{StatsController.CurrentRound} P{StatsController.CurrentPoint}";
			int num = PingTracker.LocalPing();
			if (num < 0)
			{
				return text;
			}
			return $"{text} · you {num}ms";
		}

		private static bool AssignBlockText(TextMeshProUGUI block, string text)
		{
			if ((Object)(object)block == (Object)null)
			{
				return false;
			}
			((TMP_Text)block).lineSpacing = 4f;
			if (((TMP_Text)block).text == text)
			{
				return false;
			}
			((TMP_Text)block).text = text;
			return true;
		}

		private PlayerStatsSnapshot GetPinnedBaselineFor(Player player)
		{
			Player val = PlayerStatsSnapshot.LocalPlayer();
			if ((Object)(object)val == (Object)null || player.playerID != val.playerID)
			{
				return null;
			}
			if (_pinnedLocal == null || _pinnedLocalPlayerId != val.playerID)
			{
				return null;
			}
			return _pinnedLocal;
		}

		private void EnsureCompareTarget()
		{
			if (_compareMode)
			{
				List<Player> otherPlayers = GetOtherPlayers();
				if (otherPlayers.Count == 0)
				{
					_compareTargetPlayerId = -1;
				}
				else if (otherPlayers.All((Player p) => p.playerID != _compareTargetPlayerId))
				{
					_compareTargetPlayerId = otherPlayers[0].playerID;
				}
			}
		}

		private static List<Player> GetOtherPlayers()
		{
			Player val = PlayerStatsSnapshot.LocalPlayer();
			List<Player> list = new List<Player>();
			foreach (Player item in PlayerStatsSnapshot.ActivePlayers())
			{
				if (!((Object)(object)val != (Object)null) || item.playerID != val.playerID)
				{
					list.Add(item);
				}
			}
			if ((Object)(object)val == (Object)null && list.Count > 1)
			{
				list.RemoveAt(0);
			}
			return list;
		}

		private void EnsureBlockCount(int count)
		{
			//IL_0059: 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_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: 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_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			while (_playerBlocks.Count < count)
			{
				GameObject val = new GameObject($"Player_{_playerBlocks.Count}", new Type[4]
				{
					typeof(RectTransform),
					typeof(CanvasRenderer),
					typeof(Image),
					typeof(LayoutElement)
				});
				val.transform.SetParent((Transform)(object)_content, false);
				RectTransform component = val.GetComponent<RectTransform>();
				component.anchorMin = new Vector2(0f, 1f);
				component.anchorMax = new Vector2(1f, 1f);
				component.pivot = new Vector2(0.5f, 1f);
				component.sizeDelta = new Vector2(0f, 120f);
				Image component2 = val.GetComponent<Image>();
				StatsUiHelper.ApplyRounded(component2, StatsUiHelper.BlockColor);
				((Graphic)component2).raycastTarget = false;
				LayoutElement component3 = val.GetComponent<LayoutElement>();
				component3.minHeight = 96f;
				component3.preferredHeight = 120f;
				component3.flexibleWidth = 1f;
				component3.flexibleHeight = 0f;
				TextMeshProUGUI val2 = StatsUiHelper.CreateText(val.transform, "Text", "", StatsUiHelper.BaseFont, (TextAlignmentOptions)257);
				((TMP_Text)val2).enableWordWrapping = true;
				((TMP_Text)val2).overflowMode = (TextOverflowModes)0;
				((TMP_Text)val2).lineSpacing = 4f;
				((TMP_Text)val2).rectTransform.anchorMin = new Vector2(0f, 0f);
				((TMP_Text)val2).rectTransform.anchorMax = new Vector2(1f, 1f);
				((TMP_Text)val2).rectTransform.offsetMin = new Vector2(10f, 8f);
				((TMP_Text)val2).rectTransform.offsetMax = new Vector2(-10f, -8f);
				_playerBlocks.Add(val2);
			}
		}

		private void RelayoutBlocks()
		{
			if ((Object)(object)_content == (Object)null)
			{
				return;
			}
			LayoutRebuilder.ForceRebuildLayoutImmediate(_content);
			foreach (TextMeshProUGUI playerBlock in _playerBlocks)
			{
				if (!((Object)(object)playerBlock == (Object)null) && ((Component)playerBlock).gameObject.activeInHierarchy)
				{
					UpdateBlockHeight(((Component)((TMP_Text)playerBlock).transform.parent).gameObject, playerBlock);
				}
			}
			LayoutRebuilder.ForceRebuildLayoutImmediate(_content);
		}

		private static void UpdateBlockHeight(GameObject block, TextMeshProUGUI text)
		{
			((TMP_Text)text).ForceMeshUpdate();
			LayoutElement component = block.GetComponent<LayoutElement>();
			if ((Object)(object)component != (Object)null)
			{
				float preferredHeight = (component.minHeight = Mathf.Max(96f, ((TMP_Text)text).preferredHeight + 20f));
				component.preferredHeight = preferredHeight;
			}
		}
	}
	internal static class StatsUiHelper
	{
		private static Canvas _overlay;

		private static Sprite _roundedSprite;

		internal static float UiScale => 1f;

		internal static float BaseFont => 13.5f * UiScale;

		internal static float HeaderFont => 15f * UiScale;

		internal static float TitleFont => 18f * UiScale;

		internal static float HeroFont => 15.5f * UiScale;

		internal static Color AccentColor => new Color(0.78f, 0.8f, 0.84f);

		internal static Color TitleColor => new Color(0.93f, 0.94f, 0.96f, 0.98f);

		internal static Color HintColor => new Color(0.84f, 0.87f, 0.92f, 0.96f);

		internal static Color PanelColor => new Color(0.07f, 0.08f, 0.1f, 0.9f);

		internal static Color BlockColor => new Color(1f, 1f, 1f, 0.04f);

		internal static Color ButtonFill => new Color(1f, 1f, 1f, 0.07f);

		internal static Transform OverlayRoot
		{
			get
			{
				EnsureOverlayCanvas();
				return ((Component)_overlay).transform;
			}
		}

		internal static Vector2 OverlaySize
		{
			get
			{
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0041: Unknown result type (might be due to invalid IL or missing references)
				//IL_002a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0047: Unknown result type (might be due to invalid IL or missing references)
				EnsureOverlayCanvas();
				Rect rect = ((Component)_overlay).GetComponent<RectTransform>().rect;
				Vector2 size = ((Rect)(ref rect)).size;
				if (size.x < 8f || size.y < 8f)
				{
					return new Vector2(1920f, 1080f);
				}
				return size;
			}
		}

		internal static bool OverlayReady
		{
			get
			{
				EnsureOverlayCanvas();
				return (Object)(object)_overlay != (Object)null;
			}
		}

		internal static Sprite RoundedSprite
		{
			get
			{
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0025: Unknown result type (might be due to invalid IL or missing references)
				//IL_002d: Expected O, but got Unknown
				//IL_00af: Unknown result type (might be due to invalid IL or missing references)
				//IL_00be: Unknown result type (might be due to invalid IL or missing references)
				//IL_00de: 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_0074: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)_roundedSprite != (Object)null)
				{
					return _roundedSprite;
				}
				Texture2D val = new Texture2D(64, 64, (TextureFormat)5, false)
				{
					wrapMode = (TextureWrapMode)1,
					filterMode = (FilterMode)1
				};
				Color[] array = (Color[])(object)new Color[4096];
				for (int i = 0; i < 64; i++)
				{
					for (int j = 0; j < 64; j++)
					{
						array[i * 64 + j] = new Color(1f, 1f, 1f, RoundedAlpha((float)j + 0.5f, (float)i + 0.5f, 64, 14));
					}
				}
				val.SetPixels(array);
				val.Apply(false, false);
				_roundedSprite = Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, new Vector4(14f, 14f, 14f, 14f));
				((Object)_roundedSprite).name = "MM_RoundedPanel";
				return _roundedSprite;
			}
		}

		private static void EnsureOverlayCanvas()
		{
			//IL_004d: 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)
			//IL_0058: Expected O, but got Unknown
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_overlay != (Object)null))
			{
				GameObject val = new GameObject("MM_StatsOverlay", new Type[4]
				{
					typeof(RectTransform),
					typeof(Canvas),
					typeof(CanvasScaler),
					typeof(GraphicRaycaster)
				});
				Object.DontDestroyOnLoad((Object)val);
				_overlay = val.GetComponent<Canvas>();
				_overlay.renderMode = (RenderMode)0;
				_overlay.sortingOrder = 300;
				_overlay.pixelPerfect = false;
				CanvasScaler component = val.GetComponent<CanvasScaler>();
				component.uiScaleMode = (ScaleMode)1;
				component.referenceResolution = new Vector2(1920f, 1080f);
				component.screenMatchMode = (ScreenMatchMode)0;
				component.matchWidthOrHeight = 1f;
			}
		}

		private static float RoundedAlpha(float x, float y, int size, int radius)
		{
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			int num = size - radius;
			int num2 = size - radius;
			if (x >= (float)radius && x <= (float)num)
			{
				if (!(x >= 0f) || !(x <= (float)size) || !(y >= 0f) || !(y <= (float)size))
				{
					return 0f;
				}
				return 1f;
			}
			if (y >= (float)radius && y <= (float)num2)
			{
				if (!(x >= 0f) || !(x <= (float)size) || !(y >= 0f) || !(y <= (float)size))
				{
					return 0f;
				}
				return 1f;
			}
			int num3 = ((x < (float)radius) ? radius : num);
			int num4 = ((y < (float)radius) ? radius : num2);
			float num5 = Vector2.Distance(new Vector2(x, y), new Vector2((float)num3, (float)num4));
			return Mathf.Clamp01((float)radius - num5 + 0.5f);
		}

		internal static void ApplyRounded(Image image, Color color)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)image == (Object)null))
			{
				image.sprite = RoundedSprite;
				image.type = (Type)1;
				((Graphic)image).color = color;
			}
		}

		internal static GameObject CreateModernPanel(Transform parent, string name, Vector2 anchorMin, Vector2 anchorMax, Vector2 pivot, Vector2 anchoredPos, Vector2 sizeDelta, float alpha = 0.88f)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: 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_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = CreatePanel(parent, name, anchorMin, anchorMax, pivot, anchoredPos, sizeDelta, new Color(0.05f, 0.07f, 0.1f), alpha);
			CreateAccentBar(obj.transform, "AccentTop", top: true);
			CreateAccentBar(obj.transform, "AccentBottom", top: false);
			return obj;
		}

		internal static GameObject CreateGlassPanel(Transform parent, string name, Vector2 anchoredPos, Vector2 sizeDelta, float alpha = 0.9f)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: 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_0039: 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)
			GameObject obj = CreatePanel(parent, name, Vector2.zero, Vector2.zero, Vector2.zero, anchoredPos, sizeDelta, PanelColor, alpha);
			ApplyRounded(obj.GetComponent<Image>(), new Color(PanelColor.r, PanelColor.g, PanelColor.b, alpha));
			((Graphic)obj.GetComponent<Image>()).raycastTarget = false;
			return obj;
		}

		internal static void SetAccentVisible(GameObject root, bool visible)
		{
			if (!((Object)(object)root == (Object)null))
			{
				Transform val = root.transform.Find("AccentTop") ?? root.transform.Find("Accent");
				Transform val2 = root.transform.Find("AccentBottom");
				if ((Object)(object)val != (Object)null)
				{
					((Component)val).gameObject.SetActive(visible);
				}
				if ((Object)(object)val2 != (Object)null)
				{
					((Component)val2).gameObject.SetActive(visible);
				}
			}
		}

		private static void CreateAccentBar(Transform parent, string name, bool top)
		{
			//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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: 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_00cb: 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_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(Image)
			});
			val.transform.SetParent(parent, false);
			RectTransform component = val.GetComponent<RectTransform>();
			if (top)
			{
				component.anchorMin = new Vector2(0f, 1f);
				component.anchorMax = new Vector2(1f, 1f);
				component.pivot = new Vector2(0.5f, 1f);
			}
			else
			{
				component.anchorMin = new Vector2(0f, 0f);
				component.anchorMax = new Vector2(1f, 0f);
				component.pivot = new Vector2(0.5f, 0f);
			}
			component.anchoredPosition = Vector2.zero;
			component.sizeDelta = new Vector2(0f, 3f);
			((Graphic)val.GetComponent<Image>()).color = AccentColor;
			((Graphic)val.GetComponent<Image>()).raycastTarget = false;
		}

		internal static GameObject CreatePanel(Transform parent, string name, Vector2 anchorMin, Vector2 anchorMax, Vector2 pivot, Vector2 anchoredPos, Vector2 sizeDelta, Color bg, float alpha = 0.82f)
		{
			//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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: 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_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: 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_0080: 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_009a: Expected O, but got Unknown
			GameObject val = new GameObject(name, new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(Image)
			});
			val.transform.SetParent(parent, false);
			RectTransform component = val.GetComponent<RectTransform>();
			component.anchorMin = anchorMin;
			component.anchorMax = anchorMax;
			component.pivot = pivot;
			component.anchoredPosition = anchoredPos;
			component.sizeDelta = sizeDelta;
			Image component2 = val.GetComponent<Image>();
			((Graphic)component2).color = new Color(bg.r, bg.g, bg.b, alpha);
			((Graphic)component2).raycastTarget = false;
			return val;
		}

		internal static TextMeshProUGUI CreateText(Transform parent, string name, string text, float fontSize, TextAlignmentOptions align = (TextAlignmentOptions)257, Color? color = null)
		{
			//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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: 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_0085: 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_0099: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(TextMeshProUGUI)
			});
			val.transform.SetParent(parent, false);
			RectTransform component = val.GetComponent<RectTransform>();
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			component.offsetMin = Vector2.zero;
			component.offsetMax = Vector2.zero;
			TextMeshProUGUI component2 = val.GetComponent<TextMeshProUGUI>();
			((TMP_Text)component2).text = text;
			((TMP_Text)component2).fontSize = fontSize;
			((TMP_Text)component2).alignment = align;
			((Graphic)component2).color = (Color)(((??)color) ?? Color.white);
			((Graphic)component2).raycastTarget = false;
			((TMP_Text)component2).richText = true;
			((TMP_Text)component2).enableWordWrapping = true;
			((TMP_Text)component2).lineSpacing = 0f;
			((TMP_Text)component2).overflowMode = (TextOverflowModes)0;
			return component2;
		}

		internal static Button CreateButton(Transform parent, string label, UnityAction onClick, Vector2 size)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			return CreateGhostButton(parent, label, onClick, size);
		}

		internal static Button CreateGhostButton(Transform parent, string label, UnityAction onClick, Vector2 size)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			//IL_005e: 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_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_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: 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_0119: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(label + "_Btn", new Type[4]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(Image),
				typeof(Button)
			});
			val.transform.SetParent(parent, false);
			val.GetComponent<RectTransform>().sizeDelta = size;
			Image component = val.GetComponent<Image>();
			ApplyRounded(component, ButtonFill);
			Button component2 = val.GetComponent<Button>();
			((Selectable)component2).targetGraphic = (Graphic)(object)component;
			ColorBlock colors = ((Selectable)component2).colors;
			((ColorBlock)(ref colors)).normalColor = Color.white;
			((ColorBlock)(ref colors)).highlightedColor = new Color(1f, 1f, 1f, 1f);
			((ColorBlock)(ref colors)).pressedColor = new Color(0.85f, 0.85f, 0.85f, 1f);
			((Selectable)component2).colors = colors;
			((UnityEvent)component2.onClick).AddListener(onClick);
			CreateText(val.transform, "Label", label, BaseFont * 0.88f, (TextAlignmentOptions)514, (Color?)new Color(0.86f, 0.88f, 0.91f, 0.95f));
			return component2;
		}

		internal static void ApplyRect(GameObject root, Vector2 anchorMin, Vector2 anchorMax, Vector2 pivot, Vector2 anchoredPos, Vector2 sizeDelta)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)root == (Object)null))
			{
				RectTransform component = root.GetComponent<RectTransform>();
				component.anchorMin = anchorMin;
				component.anchorMax = anchorMax;
				component.pivot = pivot;
				component.anchoredPosition = anchoredPos;
				component.sizeDelta = sizeDelta;
			}
		}
	}
	internal static class StatsViewBuilder
	{
		private static readonly Color LabelColor = new Color(1f, 1f, 1f, 1f);

		private static readonly Color ValueColor = new Color(1f, 1f, 1f, 1f);

		private static readonly Color SectionColor = new Color(0.94f, 0.95f, 0.97f, 1f);

		private static readonly (string label, string key)[] PreviewExtraStats = new(string, string)[12]
		{
			("Lives", "Lives"),
			("Regen", "Regen"),
			("Blocks", "BlockCount"),
			("Projectiles", "Bullets"),
			("Knockback", "Knockback"),
			("Life Steal", "LifeSteal"),
			("Jump", "Jump"),
			("Size", "Size"),
			("Bullet SPD", "BulletSPD"),
			("Range", "Range"),
			("Bursts", "Bursts"),
			("Gravity", "Gravity")
		};

		internal static string BuildHud(PlayerStatsSnapshot snap, bool simple, PlayerStatsSnapshot baseline, PlayerStatsSnapshot preview, IEnumerable<(string category, string label, string value)> extensions, string headerSuffix = null, bool omitHealthDelta = false, bool pickHoverMode = false)
		{
			StringBuilder stringBuilder = new StringBuilder();
			string value = (string.IsNullOrEmpty(headerSuffix) ? "" : headerSuffix);
			stringBuilder.Append("<size=105%><b>").Append(snap.PlayerName).Append(value)
				.Append("</b>");
			AppendPing(stringBuilder, snap.PingMs);
			stringBuilder.Append("</size>").AppendLine();
			PlayerStatsSnapshot baseline2 = (omitHealthDelta ? null : baseline);
			AppendHeroRow(stringBuilder, "HP", snap.GetDisplay("HP"), snap, baseline2, preview, isHero: true, pickHoverMode);
			AppendHeroRow(stringBuilder, "DMG", snap.GetDisplay("DMG"), snap, baseline, preview, isHero: true, pickHoverMode);
			if (HasCount(snap, "Nulls"))
			{
				AppendRow(stringBuilder, "Nulls", snap.GetDisplay("Nulls"), "Nulls", snap, baseline, preview, pickHoverMode);
			}
			if (HasCount(snap, "NullCards"))
			{
				AppendRow(stringBuilder, "Null cards", snap.GetDisplay("NullCards"), "NullCards", snap, baseline, preview, pickHoverMode);
			}
			if (!simple)
			{
				AppendSection(stringBuilder, "Survival");
				AppendRow(stringBuilder, "Lives", snap.GetDisplay("Lives"), "Lives", snap, baseline, preview, pickHoverMode);
				AppendRow(stringBuilder, "Block CD", snap.GetDisplay("BlockCD"), "BlockCD", snap, baseline, preview, pickHoverMode);
				AppendRow(stringBuilder, "Blocks", snap.GetDisplay("BlockCount"), "BlockCount", snap, baseline, preview, pickHoverMode);
				if (HasCount(snap, "Regen"))
				{
					AppendRow(stringBuilder, "Regen", snap.GetDisplay("Regen"), "Regen", snap, baseline, preview, pickHoverMode);
				}
			}
			else
			{
				AppendRow(stringBuilder, "Block CD", snap.GetDisplay("BlockCD"), "BlockCD", snap, baseline, preview, pickHoverMode);
				if (HasNonDefault(snap, "BlockCount", 1f))
				{
					AppendRow(stringBuilder, "Blocks", snap.GetDisplay("BlockCount"), "BlockCoun