Decompiled source of RepoDeathCounter v1.4.6

Matsu.RepoDeathCounter.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("Matsu.RepoDeathCounter")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.4.6.0")]
[assembly: AssemblyInformationalVersion("1.4.6")]
[assembly: AssemblyProduct("Matsu.RepoDeathCounter")]
[assembly: AssemblyTitle("Matsu.RepoDeathCounter")]
[assembly: AssemblyVersion("1.4.6.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 Matsu.RepoDeathCounter
{
	internal static class DeathCounterCore
	{
		internal static bool ShouldCountDeath(bool isShop)
		{
			return !isShop;
		}

		internal static bool ShouldResetForGameOver(bool isArena)
		{
			return isArena;
		}

		internal static bool TryRecordDeath(Dictionary<string, int> counts, Dictionary<string, string> names, Dictionary<string, float> lastAcceptedDeathTime, string stableId, string playerName, float now, float duplicateWindowSeconds, out string key, out int newCount)
		{
			key = ResolvePlayerKey(stableId, playerName);
			newCount = 0;
			if (string.IsNullOrEmpty(key))
			{
				return false;
			}
			if (duplicateWindowSeconds < 0f)
			{
				duplicateWindowSeconds = 0f;
			}
			if (lastAcceptedDeathTime.TryGetValue(key, out var value))
			{
				float num = now - value;
				if (num >= 0f && num < duplicateWindowSeconds)
				{
					counts.TryGetValue(key, out newCount);
					return false;
				}
			}
			lastAcceptedDeathTime[key] = now;
			counts.TryGetValue(key, out var value2);
			if (value2 < 0)
			{
				value2 = 0;
			}
			newCount = ((value2 == int.MaxValue) ? int.MaxValue : (value2 + 1));
			counts[key] = newCount;
			if (!string.IsNullOrWhiteSpace(playerName))
			{
				names[key] = CleanTsvField(playerName).Trim();
			}
			return true;
		}

		internal static string ResolvePlayerKey(string stableId, string playerName)
		{
			if (!string.IsNullOrWhiteSpace(stableId))
			{
				return CleanTsvField(stableId).Trim();
			}
			if (!string.IsNullOrWhiteSpace(playerName))
			{
				return "name:" + CleanTsvField(playerName).Trim();
			}
			return "";
		}

		internal static List<KeyValuePair<string, int>> BuildDisplayEntries(Dictionary<string, int> counts, Dictionary<string, string> visiblePlayers)
		{
			List<KeyValuePair<string, int>> list = new List<KeyValuePair<string, int>>(counts.Count + visiblePlayers.Count);
			foreach (KeyValuePair<string, int> count in counts)
			{
				if (!string.IsNullOrWhiteSpace(count.Key) && count.Value >= 0)
				{
					list.Add(count);
				}
			}
			foreach (KeyValuePair<string, string> visiblePlayer in visiblePlayers)
			{
				if (!string.IsNullOrWhiteSpace(visiblePlayer.Key) && !counts.ContainsKey(visiblePlayer.Key))
				{
					list.Add(new KeyValuePair<string, int>(visiblePlayer.Key, 0));
				}
			}
			return list;
		}

		internal static string SanitizeFileName(string value, char[] invalidCharacters)
		{
			string text = value ?? "";
			foreach (char oldChar in invalidCharacters)
			{
				text = text.Replace(oldChar, '_');
			}
			if (!string.IsNullOrWhiteSpace(text))
			{
				return text;
			}
			return "_";
		}

		internal static void BuildSnapshot(Dictionary<string, int> counts, Dictionary<string, string> names, out string[] ids, out int[] deathCounts, out string[] playerNames)
		{
			List<string> list = new List<string>();
			foreach (KeyValuePair<string, int> count in counts)
			{
				if (!string.IsNullOrWhiteSpace(count.Key) && count.Value >= 0)
				{
					list.Add(count.Key);
				}
			}
			list.Sort(StringComparer.Ordinal);
			ids = new string[list.Count];
			deathCounts = new int[list.Count];
			playerNames = new string[list.Count];
			for (int i = 0; i < list.Count; i++)
			{
				string text = list[i];
				ids[i] = text;
				deathCounts[i] = counts[text];
				playerNames[i] = (names.TryGetValue(text, out string value) ? value : "");
			}
		}

		internal static void ApplySnapshot(string[] ids, int[] deathCounts, string[] playerNames, Dictionary<string, int> counts, Dictionary<string, string> names)
		{
			counts.Clear();
			names.Clear();
			int num = Math.Min(ids.Length, deathCounts.Length);
			for (int i = 0; i < num; i++)
			{
				string text = ids[i];
				int num2 = deathCounts[i];
				if (!string.IsNullOrWhiteSpace(text) && num2 >= 0)
				{
					counts[text] = num2;
					if (i < playerNames.Length && !string.IsNullOrWhiteSpace(playerNames[i]))
					{
						names[text] = playerNames[i];
					}
				}
			}
		}

		internal static void CalculateOverlayPage(int itemCount, int rowsPerColumn, int maxColumns, int requestedPage, out int pageIndex, out int pageCount, out int startIndex, out int visibleCount, out int visibleColumns)
		{
			itemCount = Math.Max(0, itemCount);
			rowsPerColumn = Math.Max(1, rowsPerColumn);
			maxColumns = Math.Max(1, maxColumns);
			long num = (long)rowsPerColumn * (long)maxColumns;
			int num2 = (int)((num > int.MaxValue) ? int.MaxValue : num);
			pageCount = (int)((itemCount == 0) ? 1 : (((long)itemCount + (long)num2 - 1) / num2));
			pageIndex = requestedPage % pageCount;
			if (pageIndex < 0)
			{
				pageIndex += pageCount;
			}
			long num3 = (long)pageIndex * (long)num2;
			startIndex = (int)((num3 > int.MaxValue) ? int.MaxValue : num3);
			visibleCount = Math.Min(num2, Math.Max(0, itemCount - startIndex));
			visibleColumns = Math.Max(1, (visibleCount + rowsPerColumn - 1) / rowsPerColumn);
		}

		internal static string Serialize(Dictionary<string, int> counts, Dictionary<string, string> names)
		{
			List<string> list = new List<string>(counts.Keys);
			list.Sort(StringComparer.Ordinal);
			StringBuilder stringBuilder = new StringBuilder();
			foreach (string item in list)
			{
				if (counts.TryGetValue(item, out var value) && value >= 0)
				{
					string value2 = CleanTsvField(item).Trim();
					if (!string.IsNullOrEmpty(value2))
					{
						string value4;
						string value3 = (names.TryGetValue(item, out value4) ? CleanTsvField(value4).Trim() : "");
						stringBuilder.Append(value2).Append('\t').Append(value.ToString(CultureInfo.InvariantCulture))
							.Append('\t')
							.Append(value3)
							.Append('\n');
					}
				}
			}
			return stringBuilder.ToString();
		}

		internal static void Deserialize(string contents, Dictionary<string, int> counts, Dictionary<string, string> names)
		{
			counts.Clear();
			names.Clear();
			if (string.IsNullOrEmpty(contents))
			{
				return;
			}
			using StringReader stringReader = new StringReader(contents);
			string text;
			while ((text = stringReader.ReadLine()) != null)
			{
				if (string.IsNullOrWhiteSpace(text))
				{
					continue;
				}
				string[] array = text.Split(new char[1] { '\t' });
				if (array.Length < 2 || string.IsNullOrWhiteSpace(array[0]) || !int.TryParse(array[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) || result < 0)
				{
					continue;
				}
				string text2 = CleanTsvField(array[0]).Trim();
				if (!string.IsNullOrEmpty(text2))
				{
					counts[text2] = result;
					if (array.Length >= 3 && !string.IsNullOrWhiteSpace(array[2]))
					{
						names[text2] = CleanTsvField(array[2]).Trim();
					}
				}
			}
		}

		private static string CleanTsvField(string? value)
		{
			return (value ?? "").Replace('\t', ' ').Replace('\n', ' ').Replace('\r', ' ');
		}
	}
	internal sealed class DeathCounterOverlay : MonoBehaviour
	{
		private sealed class RowView
		{
			internal GameObject Root;

			internal Image Background;

			internal Image SelfBar;

			internal Image Badge;

			internal Text Name;

			internal Text Count;
		}

		private const float Margin = 20f;

		private const float TruckHudSafeTop = 100f;

		private const float Padding = 12f;

		private const float ColumnGap = 8f;

		private const float RowGap = 4f;

		private const float PageSeconds = 8f;

		private const int PreferredRowsPerColumn = 10;

		private const int MaxColumnsPerPage = 2;

		private readonly List<RowView> rows = new List<RowView>();

		private Canvas? canvas;

		private RectTransform? panel;

		private Image? panelImage;

		private Image? headerImage;

		private Image? accentImage;

		private Image? totalImage;

		private Image? emptyImage;

		private Image? dividerImage;

		private Text? titleText;

		private Text? subtitleText;

		private Text? totalText;

		private Text? emptyText;

		private Text? pageText;

		private Texture2D? pixel;

		private Sprite? sprite;

		private Font? font;

		private float nextPoll;

		private ulong lastSignature;

		private bool hasSignature;

		private static float TopMargin
		{
			get
			{
				if (Screen.height < 620)
				{
					return 20f;
				}
				return 100f;
			}
		}

		private void Awake()
		{
			CreateUi();
		}

		private void Update()
		{
			if (Time.unscaledTime < nextPoll)
			{
				return;
			}
			nextPoll = Time.unscaledTime + 0.1f;
			try
			{
				bool flag = Plugin.showOverlay.Value && Plugin.IsInTruckLobby();
				if ((Object)(object)canvas == (Object)null)
				{
					CreateUi();
				}
				if ((Object)(object)canvas == (Object)null)
				{
					return;
				}
				if (!flag)
				{
					((Behaviour)canvas).enabled = false;
					hasSignature = false;
					return;
				}
				((Behaviour)canvas).enabled = true;
				ulong num = Signature();
				if (!hasSignature || num != lastSignature)
				{
					Render();
					lastSignature = num;
					hasSignature = true;
				}
			}
			catch (Exception ex)
			{
				Plugin.TrackerErr("[DeathCounter] Scoreboard refresh failed: " + ex);
				if ((Object)(object)canvas != (Object)null)
				{
					((Behaviour)canvas).enabled = false;
				}
				hasSignature = false;
				nextPoll = Time.unscaledTime + 3f;
			}
		}

		private ulong Signature()
		{
			ulong hash = 1469598103934665603uL;
			Add(Screen.width);
			Add(Screen.height);
			GetPageCapacity(out var rowsPerColumn, out var maxColumns);
			Add((Plugin.DeathCountsBySteamId.Count > rowsPerColumn * maxColumns) ? Mathf.FloorToInt(Time.unscaledTime / 8f) : 0);
			Add((int)Plugin.overlayCorner.Value);
			Add((int)Plugin.sortMode.Value);
			Add(Plugin.titleFontSize.Value);
			Add(Plugin.itemFontSize.Value);
			Add(Plugin.showTotal.Value ? 1 : 0);
			Add(Plugin.highlightSelf.Value ? 1 : 0);
			AddString(Plugin.titleColorHex.Value);
			AddString(Plugin.itemColorHex.Value);
			AddString(Plugin.selfColorHex.Value);
			AddString(Plugin.GetLocalSteamId());
			Add(Plugin.DeathCountsBySteamId.Count);
			foreach (KeyValuePair<string, int> item in Plugin.DeathCountsBySteamId)
			{
				AddString(item.Key);
				Add(item.Value);
				Plugin.PlayerNamesBySteamId.TryGetValue(item.Key, out string value);
				AddString(value);
			}
			return hash;
			void Add(int num)
			{
				hash = (hash ^ (uint)num) * 1099511628211L;
			}
			void AddString(string? text)
			{
				if (text == null)
				{
					Add(-1);
				}
				else
				{
					for (int i = 0; i < text.Length; i++)
					{
						Add(text[i]);
					}
					Add(0);
				}
			}
		}

		private void CreateUi()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Expected O, but got Unknown
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)canvas != (Object)null))
			{
				font = Resources.GetBuiltinResource<Font>("Arial.ttf");
				if ((Object)(object)font == (Object)null)
				{
					throw new InvalidOperationException("Unity built-in Arial font unavailable");
				}
				pixel = new Texture2D(1, 1, (TextureFormat)4, false)
				{
					name = "DeathCounter shared UI pixel",
					filterMode = (FilterMode)0,
					wrapMode = (TextureWrapMode)1
				};
				pixel.SetPixel(0, 0, Color.white);
				pixel.Apply(false, true);
				sprite = Sprite.Create(pixel, new Rect(0f, 0f, 1f, 1f), new Vector2(0.5f, 0.5f));
				((Object)sprite).name = "DeathCounter shared UI sprite";
				GameObject val = new GameObject("DeathCounter Canvas", new Type[2]
				{
					typeof(RectTransform),
					typeof(Canvas)
				});
				val.transform.SetParent(((Component)this).transform, false);
				canvas = val.GetComponent<Canvas>();
				canvas.renderMode = (RenderMode)0;
				canvas.sortingOrder = 32000;
				canvas.pixelPerfect = true;
				((Behaviour)canvas).enabled = false;
				panelImage = MakeImage(val.transform, "Scoreboard panel", new Color(0.025f, 0.03f, 0.04f, 0.94f));
				panel = ((Graphic)panelImage).rectTransform;
				accentImage = MakeImage((Transform)(object)panel, "Red accent", new Color(0.92f, 0.1f, 0.12f, 1f));
				headerImage = MakeImage((Transform)(object)panel, "Header", new Color(0.065f, 0.075f, 0.095f, 0.98f));
				titleText = MakeText((Transform)(object)panel, "Title", (TextAnchor)3, (FontStyle)1);
				subtitleText = MakeText((Transform)(object)panel, "Player count", (TextAnchor)3, (FontStyle)0);
				totalImage = MakeImage((Transform)(object)panel, "Total badge", new Color(0.48f, 0.045f, 0.065f, 0.96f));
				totalText = MakeText(((Component)totalImage).transform, "Total text", (TextAnchor)4, (FontStyle)1);
				emptyImage = MakeImage((Transform)(object)panel, "Empty row", new Color(1f, 1f, 1f, 0.045f));
				emptyText = MakeText(((Component)emptyImage).transform, "Empty text", (TextAnchor)4, (FontStyle)0);
				dividerImage = MakeImage((Transform)(object)panel, "Page divider", new Color(1f, 1f, 1f, 0.14f));
				pageText = MakeText((Transform)(object)panel, "Page text", (TextAnchor)4, (FontStyle)0);
			}
		}

		private Image MakeImage(Transform parent, string name, Color color)
		{
			//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_0059: 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);
			Image component = val.GetComponent<Image>();
			component.sprite = sprite;
			component.type = (Type)0;
			((Graphic)component).color = color;
			((Graphic)component).raycastTarget = false;
			return component;
		}

		private Text MakeText(Transform parent, string name, TextAnchor alignment, FontStyle style = (FontStyle)0)
		{
			//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_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(Text)
			});
			val.transform.SetParent(parent, false);
			Text component = val.GetComponent<Text>();
			component.font = font;
			component.fontStyle = style;
			component.fontSize = 20;
			component.alignment = alignment;
			component.horizontalOverflow = (HorizontalWrapMode)0;
			component.verticalOverflow = (VerticalWrapMode)0;
			component.supportRichText = false;
			((Graphic)component).raycastTarget = false;
			return component;
		}

		private RowView MakeRow()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			Image val = MakeImage((Transform)(object)panel, "Player row", new Color(1f, 1f, 1f, 0.045f));
			Image selfBar = MakeImage(((Component)val).transform, "Self marker", Color.yellow);
			Image val2 = MakeImage(((Component)val).transform, "Death badge", new Color(0.48f, 0.045f, 0.065f, 0.96f));
			return new RowView
			{
				Root = ((Component)val).gameObject,
				Background = val,
				SelfBar = selfBar,
				Badge = val2,
				Name = MakeText(((Component)val).transform, "Player name", (TextAnchor)3, (FontStyle)0),
				Count = MakeText(((Component)val2).transform, "Death count", (TextAnchor)4, (FontStyle)1)
			};
		}

		private static void GetPageCapacity(out int rowsPerColumn, out int maxColumns)
		{
			int num = Mathf.Clamp(Plugin.titleFontSize.Value, 6, 100);
			int num2 = Mathf.Clamp(Plugin.itemFontSize.Value, 6, 100);
			float num3 = Mathf.Max(30f, (float)num2 + 14f);
			float num4 = Mathf.Max(72f, (float)num + 46f);
			float num5 = (float)Screen.height - TopMargin - 20f - num4 - 52f;
			int num6 = Mathf.Max(1, Mathf.FloorToInt((num5 + 4f) / (num3 + 4f)));
			rowsPerColumn = Mathf.Min(10, num6);
			float num7 = Mathf.Max(180f, (float)Screen.width - 40f);
			int num8 = Mathf.Max(1, Mathf.FloorToInt((num7 - 24f + 8f) / 248f));
			maxColumns = Mathf.Min(2, num8);
		}

		private void Render()
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: 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_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)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_034a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0448: Unknown result type (might be due to invalid IL or missing references)
			//IL_04eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0505: Unknown result type (might be due to invalid IL or missing references)
			//IL_0872: Unknown result type (might be due to invalid IL or missing references)
			//IL_066b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0650: Unknown result type (might be due to invalid IL or missing references)
			//IL_0635: Unknown result type (might be due to invalid IL or missing references)
			//IL_0693: Unknown result type (might be due to invalid IL or missing references)
			//IL_0726: Unknown result type (might be due to invalid IL or missing references)
			//IL_0722: Unknown result type (might be due to invalid IL or missing references)
			//IL_0789: Unknown result type (might be due to invalid IL or missing references)
			List<(string, string, int)> list = Plugin.BuildSortedLines();
			long num = 0L;
			foreach (var item in list)
			{
				num += item.Item3;
			}
			int num2 = Mathf.Clamp(Plugin.titleFontSize.Value, 6, 100);
			int num3 = Mathf.Clamp(Plugin.itemFontSize.Value, 6, 100);
			Color color = Plugin.ParseColor(Plugin.titleColorHex.Value, Color.red);
			Color val = Plugin.ParseColor(Plugin.itemColorHex.Value, Color.white);
			Color val2 = Plugin.ParseColor(Plugin.selfColorHex.Value, val);
			bool flag = Plugin.overlayCorner.Value == OverlayCorner.TopRight || Plugin.overlayCorner.Value == OverlayCorner.BottomRight;
			bool num4 = Plugin.overlayCorner.Value == OverlayCorner.BottomLeft || Plugin.overlayCorner.Value == OverlayCorner.BottomRight;
			float num5 = Mathf.Max(30f, (float)num3 + 14f);
			float num6 = Mathf.Max(72f, (float)num2 + 46f);
			float num7 = Mathf.Max(180f, (float)Screen.width - 40f);
			GetPageCapacity(out var rowsPerColumn, out var maxColumns);
			DeathCounterCore.CalculateOverlayPage(list.Count, rowsPerColumn, maxColumns, Mathf.FloorToInt(Time.unscaledTime / 8f), out var pageIndex, out var pageCount, out var startIndex, out var visibleCount, out var visibleColumns);
			float num8 = Mathf.Min(280f, (num7 - 24f - 8f * (float)(visibleColumns - 1)) / (float)visibleColumns);
			num8 = Mathf.Max(140f, num8);
			int num9 = ((list.Count == 0) ? 1 : Mathf.Max(1, Mathf.CeilToInt((float)visibleCount / (float)visibleColumns)));
			float num10 = ((list.Count == 0) ? 52f : ((float)num9 * num5 + (float)(num9 - 1) * 4f));
			float num11 = ((pageCount > 1) ? 28f : 0f);
			float num12 = 24f + (float)visibleColumns * num8 + (float)(visibleColumns - 1) * 8f;
			float num13 = num6 + 8f + num10 + num11 + 12f;
			float num14 = (flag ? ((float)Screen.width - num12 - 20f) : 20f);
			float num15 = (num4 ? ((float)Screen.height - num13 - 20f) : TopMargin);
			SetRect(panel, Mathf.Max(4f, num14), Mathf.Max(4f, num15), num12, num13);
			((Graphic)panelImage).color = new Color(0.025f, 0.03f, 0.04f, 0.94f);
			SetRect((Graphic)(object)accentImage, 0f, 0f, num12, 3f);
			SetRect((Graphic)(object)headerImage, 0f, 3f, num12, num6 - 3f);
			titleText.fontSize = num2;
			((Graphic)titleText).color = color;
			titleText.text = "PLAYER DEATHS";
			SetRect((Graphic)(object)titleText, 16f, 8f, num12 - 24f - 8f, (float)num2 + 8f);
			subtitleText.fontSize = Mathf.Clamp(num3 - 7, 9, 16);
			((Graphic)subtitleText).color = new Color(0.75f, 0.78f, 0.83f, 1f);
			subtitleText.text = ((list.Count == 1) ? "1 PLAYER RECORDED" : (list.Count + " PLAYERS RECORDED"));
			float num16 = Mathf.Min(104f, num12 * 0.36f);
			SetRect((Graphic)(object)subtitleText, 16f, num6 - 29f, num12 - 24f - (Plugin.showTotal.Value ? (num16 + 12f) : 0f), 22f);
			((Component)totalImage).gameObject.SetActive(Plugin.showTotal.Value);
			if (Plugin.showTotal.Value)
			{
				SetRect((Graphic)(object)totalImage, num12 - 12f - num16, num6 - 34f, num16, 25f);
				totalText.fontSize = Mathf.Clamp(num3 - 3, 10, 23);
				((Graphic)totalText).color = Color.white;
				totalText.text = "TOTAL  " + num;
				SetRect((Graphic)(object)totalText, 0f, 0f, num16, 25f);
			}
			float num17 = num6 + 8f;
			((Component)emptyImage).gameObject.SetActive(list.Count == 0);
			if (list.Count == 0)
			{
				SetRect((Graphic)(object)emptyImage, 12f, num17, num8, num10);
				emptyText.fontSize = Mathf.Clamp(num3 - 2, 10, 28);
				((Graphic)emptyText).color = new Color(val.r, val.g, val.b, 0.85f);
				emptyText.text = "NO DEATHS RECORDED";
				SetRect((Graphic)(object)emptyText, 3f, 0f, num8 - 6f, num10);
			}
			while (rows.Count < visibleCount)
			{
				rows.Add(MakeRow());
			}
			string localSteamId = Plugin.GetLocalSteamId();
			for (int i = 0; i < rows.Count; i++)
			{
				RowView rowView = rows[i];
				rowView.Root.SetActive(i < visibleCount);
				if (i < visibleCount)
				{
					int num18 = startIndex + i;
					(string, string, int) tuple = list[num18];
					int num19 = i / num9;
					int num20 = i % num9;
					float x = 12f + (float)num19 * (num8 + 8f);
					float y = num17 + (float)num20 * (num5 + 4f);
					SetRect((Graphic)(object)rowView.Background, x, y, num8, num5);
					bool flag2 = Plugin.highlightSelf.Value && tuple.Item1 == localSteamId;
					((Graphic)rowView.Background).color = (flag2 ? new Color(1f, 0.65f, 0.05f, 0.16f) : (((num18 & 1) == 0) ? new Color(1f, 1f, 1f, 0.045f) : new Color(1f, 1f, 1f, 0.075f)));
					((Component)rowView.SelfBar).gameObject.SetActive(flag2);
					if (flag2)
					{
						((Graphic)rowView.SelfBar).color = val2;
						SetRect((Graphic)(object)rowView.SelfBar, 0f, 0f, 3f, num5);
					}
					float num21 = Mathf.Clamp((float)num3 * 2.35f, 42f, 74f);
					SetRect((Graphic)(object)rowView.Badge, num8 - num21 - 8f, 5f, num21, num5 - 10f);
					rowView.Name.fontSize = num3;
					rowView.Name.fontStyle = (FontStyle)(flag2 ? 1 : 0);
					((Graphic)rowView.Name).color = (flag2 ? val2 : val);
					float width = num8 - num21 - 28f;
					SetRect((Graphic)(object)rowView.Name, 12f, 0f, width, num5);
					rowView.Name.text = FitName(tuple.Item2, rowView.Name, width);
					rowView.Count.fontSize = num3;
					((Graphic)rowView.Count).color = Color.white;
					rowView.Count.text = tuple.Item3.ToString();
					SetRect((Graphic)(object)rowView.Count, 0f, 0f, num21, num5 - 10f);
				}
			}
			((Component)dividerImage).gameObject.SetActive(pageCount > 1);
			((Component)pageText).gameObject.SetActive(pageCount > 1);
			if (pageCount > 1)
			{
				float num22 = num17 + num10 + 7f;
				SetRect((Graphic)(object)dividerImage, 12f, num22, num12 - 24f, 1f);
				pageText.fontSize = Mathf.Clamp(num3 - 7, 9, 16);
				((Graphic)pageText).color = new Color(0.75f, 0.78f, 0.83f, 1f);
				pageText.text = "PAGE " + (pageIndex + 1) + "/" + pageCount + "  |  PLAYERS " + (startIndex + 1) + "-" + (startIndex + visibleCount) + " OF " + list.Count;
				SetRect((Graphic)(object)pageText, 12f, num22 + 3f, num12 - 24f, 20f);
			}
		}

		private static string FitName(string name, Text label, float width)
		{
			if (string.IsNullOrEmpty(name))
			{
				return "UNKNOWN PLAYER";
			}
			label.text = name;
			if (label.preferredWidth <= width)
			{
				return name;
			}
			int num = name.Length;
			do
			{
				num--;
				label.text = name.Substring(0, num).TrimEnd(Array.Empty<char>()) + "...";
			}
			while (num > 1 && label.preferredWidth > width);
			return label.text;
		}

		private static void SetRect(Graphic graphic, float x, float y, float width, float height)
		{
			SetRect(graphic.rectTransform, x, y, width, height);
		}

		private static void SetRect(RectTransform rect, float x, float y, float width, float height)
		{
			//IL_0013: 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_002a: 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_0046: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(0f, 1f);
			rect.anchorMax = val;
			rect.anchorMin = val;
			rect.pivot = new Vector2(0f, 1f);
			rect.anchoredPosition = new Vector2(x, 0f - y);
			rect.sizeDelta = new Vector2(width, height);
		}

		private void OnDestroy()
		{
			if ((Object)(object)sprite != (Object)null)
			{
				Object.Destroy((Object)(object)sprite);
			}
			if ((Object)(object)pixel != (Object)null)
			{
				Object.Destroy((Object)(object)pixel);
			}
		}
	}
	internal sealed class DeathCounterOverlayLite : MonoBehaviour
	{
		private const float Margin = 20f;

		private const float TruckHudSafeTop = 100f;

		private const float Padding = 12f;

		private const float ColumnGap = 8f;

		private const float RowGap = 4f;

		private const float PageSeconds = 8f;

		private const int PreferredRowsPerColumn = 10;

		private const int MaxColumnsPerPage = 2;

		private readonly Image[] columnBackground = (Image[])(object)new Image[2];

		private readonly Image[] countBackground = (Image[])(object)new Image[2];

		private readonly Image[] selfHighlight = (Image[])(object)new Image[2];

		private readonly Text[] names = (Text[])(object)new Text[2];

		private readonly Text[] counts = (Text[])(object)new Text[2];

		private readonly Dictionary<(int Size, FontStyle Style), HashSet<char>> requestedGlyphs = new Dictionary<(int, FontStyle), HashSet<char>>();

		private Canvas? canvas;

		private Image? panelImage;

		private Image? headerImage;

		private Image? awardImage;

		private Image? accentImage;

		private Image? totalImage;

		private Image? dividerImage;

		private Text? titleText;

		private Text? subtitleText;

		private Text? awardLinesText;

		private Text? totalText;

		private Text? pageText;

		private Font? font;

		private bool ownsFont;

		private Font? awardFont;

		private bool ownsAwardFont;

		private Font? totalFont;

		private bool ownsTotalFont;

		private Texture2D? pixel;

		private Sprite? sprite;

		private float nextPoll;

		private ulong lastSignature;

		private bool hasSignature;

		private bool followupRenderPending;

		private bool hotkeyVisible = true;

		private int renderedLineCount;

		private static float TopMargin
		{
			get
			{
				if (Screen.height < 620)
				{
					return 20f;
				}
				return 100f;
			}
		}

		private static bool HasAwards
		{
			get
			{
				if (Plugin.MvpInstalled && !string.IsNullOrEmpty(Plugin.LastLevelAwardName))
				{
					if (string.IsNullOrEmpty(Plugin.LastMvpAward))
					{
						return !string.IsNullOrEmpty(Plugin.LastReverseAward);
					}
					return true;
				}
				return false;
			}
		}

		private static float AwardHeight
		{
			get
			{
				if (HasAwards)
				{
					if (string.IsNullOrEmpty(Plugin.LastMvpRankings))
					{
						if (string.IsNullOrEmpty(Plugin.LastMvpScoreDetails))
						{
							return 74f;
						}
						return 90f;
					}
					return 110f;
				}
				return 0f;
			}
		}

		private void Awake()
		{
			CreateUi();
		}

		private void Update()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				KeyboardShortcut value = Plugin.toggleKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					hotkeyVisible = !hotkeyVisible;
					hasSignature = false;
					nextPoll = 0f;
				}
				if (Time.unscaledTime < nextPoll)
				{
					return;
				}
				nextPoll = Time.unscaledTime + 0.5f;
				bool flag = Plugin.showOverlay.Value && hotkeyVisible && Plugin.IsInTruckLobby();
				if ((Object)(object)canvas == (Object)null)
				{
					CreateUi();
				}
				if ((Object)(object)canvas == (Object)null)
				{
					return;
				}
				if (((Behaviour)canvas).enabled != flag)
				{
					((Behaviour)canvas).enabled = flag;
				}
				if (!flag)
				{
					hasSignature = false;
					followupRenderPending = false;
					return;
				}
				ulong num = Signature();
				bool flag2 = !hasSignature || num != lastSignature;
				if (flag2 || followupRenderPending)
				{
					bool rebindText = followupRenderPending;
					followupRenderPending = false;
					Render(rebindText);
					lastSignature = num;
					hasSignature = true;
					if (flag2 && (Object)(object)font != (Object)null && font.dynamic)
					{
						followupRenderPending = true;
						nextPoll = Time.unscaledTime + 0.05f;
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.TrackerErr("[DeathCounter] Compact scoreboard refresh failed: " + ex);
				if ((Object)(object)canvas != (Object)null)
				{
					((Behaviour)canvas).enabled = false;
				}
				hasSignature = false;
				nextPoll = Time.unscaledTime + 3f;
			}
		}

		private ulong Signature()
		{
			ulong hash = 1469598103934665603uL;
			Add(Screen.width);
			Add(Screen.height);
			GetPageCapacity(out var rowsPerColumn, out var maxColumns);
			Add((renderedLineCount > rowsPerColumn * maxColumns) ? Mathf.FloorToInt(Time.unscaledTime / 8f) : 0);
			Add((int)Plugin.overlayCorner.Value);
			Add((int)Plugin.sortMode.Value);
			Add(Plugin.titleFontSize.Value);
			Add(Plugin.itemFontSize.Value);
			Add(Mathf.RoundToInt(Plugin.backgroundOpacity.Value * 1000f));
			Add(Plugin.showTotal.Value ? 1 : 0);
			Add(Plugin.highlightSelf.Value ? 1 : 0);
			if (Plugin.MvpInstalled)
			{
				Add(Plugin.AwardRevision);
			}
			Add(Plugin.UiRevision);
			AddString(Plugin.titleColorHex.Value);
			AddString(Plugin.itemColorHex.Value);
			AddString(Plugin.selfColorHex.Value);
			AddString(Plugin.GetLocalSteamId());
			return hash;
			void Add(int value)
			{
				hash = (hash ^ (uint)value) * 1099511628211L;
			}
			void AddString(string? value)
			{
				if (value == null)
				{
					Add(-1);
				}
				else
				{
					for (int i = 0; i < value.Length; i++)
					{
						Add(value[i]);
					}
					Add(0);
				}
			}
		}

		private static void GetPageCapacity(out int rowsPerColumn, out int maxColumns)
		{
			int num = Mathf.Clamp(Plugin.titleFontSize.Value, 6, 100);
			int num2 = Mathf.Clamp(Plugin.itemFontSize.Value, 6, 100);
			float num3 = Mathf.Max(30f, (float)num2 + 10f);
			float num4 = Mathf.Max(72f, (float)num + 46f);
			float awardHeight = AwardHeight;
			float num5 = (float)Screen.height - TopMargin - 20f - num4 - awardHeight - 74f;
			int num6 = Mathf.Max(1, Mathf.FloorToInt((num5 + 4f) / (num3 + 4f)));
			rowsPerColumn = Mathf.Min(10, num6);
			float num7 = Mathf.Max(180f, (float)Screen.width - 40f);
			int num8 = Mathf.Max(1, Mathf.FloorToInt((num7 - 24f + 8f) / 248f));
			maxColumns = Mathf.Min(2, num8);
		}

		private void CreateUi()
		{
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Expected O, but got Unknown
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Expected O, but got Unknown
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_036d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_0430: Unknown result type (might be due to invalid IL or missing references)
			//IL_049c: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0526: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)canvas != (Object)null)
			{
				return;
			}
			font = Font.CreateDynamicFontFromOSFont(new string[4] { "Arial", "Yu Gothic UI", "Meiryo", "Liberation Sans" }, 20);
			ownsFont = (Object)(object)font != (Object)null;
			if ((Object)(object)font == (Object)null)
			{
				font = Resources.GetBuiltinResource<Font>("Arial.ttf");
			}
			if ((Object)(object)font == (Object)null)
			{
				throw new InvalidOperationException("Unity built-in Arial font unavailable");
			}
			pixel = new Texture2D(1, 1, (TextureFormat)4, false)
			{
				name = "DeathCounter compact UI pixel",
				filterMode = (FilterMode)0,
				wrapMode = (TextureWrapMode)1
			};
			pixel.SetPixel(0, 0, Color.white);
			pixel.Apply(false, true);
			sprite = Sprite.Create(pixel, new Rect(0f, 0f, 1f, 1f), new Vector2(0.5f, 0.5f));
			((Object)sprite).name = "DeathCounter compact UI sprite";
			GameObject val = new GameObject("DeathCounter Compact Canvas", new Type[2]
			{
				typeof(RectTransform),
				typeof(Canvas)
			});
			val.transform.SetParent(((Component)this).transform, false);
			canvas = val.GetComponent<Canvas>();
			canvas.renderMode = (RenderMode)0;
			canvas.sortingOrder = 32000;
			canvas.pixelPerfect = false;
			((Behaviour)canvas).enabled = false;
			panelImage = MakeImage(val.transform, "Scoreboard panel", new Color(0.025f, 0.03f, 0.04f, 0.94f));
			accentImage = MakeImage(((Component)panelImage).transform, "Red accent", new Color(0.92f, 0.1f, 0.12f, 1f));
			headerImage = MakeImage(((Component)panelImage).transform, "Header", new Color(0.065f, 0.075f, 0.095f, 0.98f));
			if (Plugin.MvpInstalled)
			{
				awardImage = MakeImage(((Component)panelImage).transform, "Last level awards", new Color(0.12f, 0.11f, 0.085f, 0.98f));
				awardLinesText = MakeText(((Component)awardImage).transform, "Last level award lines", (TextAnchor)0, (FontStyle)0);
				awardFont = Font.CreateDynamicFontFromOSFont(new string[4] { "Arial", "Yu Gothic UI", "Meiryo", "Liberation Sans" }, 20);
				ownsAwardFont = (Object)(object)awardFont != (Object)null;
				if ((Object)(object)awardFont == (Object)null)
				{
					awardFont = font;
				}
				awardLinesText.font = awardFont;
				awardLinesText.supportRichText = true;
			}
			titleText = MakeText(((Component)panelImage).transform, "Title", (TextAnchor)3, (FontStyle)1);
			subtitleText = MakeText(((Component)panelImage).transform, "Player count", (TextAnchor)3, (FontStyle)0);
			totalImage = MakeImage(((Component)panelImage).transform, "Total badge", new Color(0.48f, 0.045f, 0.065f, 0.96f));
			totalText = MakeText(((Component)totalImage).transform, "Total text", (TextAnchor)4, (FontStyle)1);
			totalFont = Font.CreateDynamicFontFromOSFont(new string[4] { "Arial", "Yu Gothic UI", "Meiryo", "Liberation Sans" }, 20);
			ownsTotalFont = (Object)(object)totalFont != (Object)null;
			if ((Object)(object)totalFont == (Object)null)
			{
				totalFont = font;
			}
			totalText.font = totalFont;
			dividerImage = MakeImage(((Component)panelImage).transform, "Page divider", new Color(1f, 1f, 1f, 0.14f));
			pageText = MakeText(((Component)panelImage).transform, "Page text", (TextAnchor)4, (FontStyle)0);
			for (int i = 0; i < 2; i++)
			{
				columnBackground[i] = MakeImage(((Component)panelImage).transform, "Player column " + i, new Color(1f, 1f, 1f, 0.055f));
				selfHighlight[i] = MakeImage(((Component)columnBackground[i]).transform, "Self highlight " + i, new Color(1f, 0.65f, 0.05f, 0.13f));
				countBackground[i] = MakeImage(((Component)columnBackground[i]).transform, "Count strip " + i, new Color(0.48f, 0.045f, 0.065f, 0.85f));
				names[i] = MakeText(((Component)columnBackground[i]).transform, "Player names " + i, (TextAnchor)0, (FontStyle)0);
				counts[i] = MakeText(((Component)countBackground[i]).transform, "Death counts " + i, (TextAnchor)2, (FontStyle)1);
				names[i].supportRichText = true;
				counts[i].supportRichText = true;
			}
		}

		private Image MakeImage(Transform parent, string name, Color color)
		{
			//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_0052: 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);
			Image component = val.GetComponent<Image>();
			component.sprite = sprite;
			((Graphic)component).color = color;
			((Graphic)component).raycastTarget = false;
			return component;
		}

		private Text MakeText(Transform parent, string name, TextAnchor alignment, FontStyle style = (FontStyle)0)
		{
			//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_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(Text)
			});
			val.transform.SetParent(parent, false);
			Text component = val.GetComponent<Text>();
			component.font = font;
			component.fontStyle = style;
			component.fontSize = 20;
			component.alignment = alignment;
			component.horizontalOverflow = (HorizontalWrapMode)1;
			component.verticalOverflow = (VerticalWrapMode)0;
			((Graphic)component).raycastTarget = false;
			return component;
		}

		private void Render(bool rebindText)
		{
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: 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_0363: Unknown result type (might be due to invalid IL or missing references)
			//IL_0394: Unknown result type (might be due to invalid IL or missing references)
			//IL_061a: Unknown result type (might be due to invalid IL or missing references)
			//IL_068d: Unknown result type (might be due to invalid IL or missing references)
			//IL_06b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_06bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_06bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_044f: 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)
			//IL_083d: Unknown result type (might be due to invalid IL or missing references)
			//IL_07a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0cbe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ad5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0af4: Unknown result type (might be due to invalid IL or missing references)
			if (rebindText)
			{
				titleText.text = "";
				subtitleText.text = "";
				totalText.text = "";
				pageText.text = "";
				if ((Object)(object)awardLinesText != (Object)null)
				{
					awardLinesText.text = "";
				}
				for (int i = 0; i < 2; i++)
				{
					names[i].text = "";
					counts[i].text = "";
				}
			}
			List<(string, string, int)> list = Plugin.BuildSortedLines();
			renderedLineCount = list.Count;
			long num = 0L;
			foreach (var item in list)
			{
				num += item.Item3;
			}
			int num2 = Mathf.Clamp(Plugin.titleFontSize.Value, 6, 100);
			int num3 = Mathf.Clamp(Plugin.itemFontSize.Value, 6, 100);
			WarmGlyphs(list, num2, num3);
			Color color = Plugin.ParseColor(Plugin.titleColorHex.Value, Color.red);
			Color val = Plugin.ParseColor(Plugin.itemColorHex.Value, Color.white);
			Color val2 = Plugin.ParseColor(Plugin.selfColorHex.Value, val);
			bool flag = Plugin.overlayCorner.Value == OverlayCorner.TopRight || Plugin.overlayCorner.Value == OverlayCorner.BottomRight;
			bool num4 = Plugin.overlayCorner.Value == OverlayCorner.BottomLeft || Plugin.overlayCorner.Value == OverlayCorner.BottomRight;
			float num5 = Mathf.Max(30f, (float)num3 + 10f);
			float num6 = num5 + 4f;
			float num7 = Mathf.Max(72f, (float)num2 + 46f);
			float awardHeight = AwardHeight;
			float num8 = Mathf.Max(180f, (float)Screen.width - 40f);
			GetPageCapacity(out var rowsPerColumn, out var maxColumns);
			DeathCounterCore.CalculateOverlayPage(list.Count, rowsPerColumn, maxColumns, Mathf.FloorToInt(Time.unscaledTime / 8f), out var pageIndex, out var pageCount, out var startIndex, out var visibleCount, out var visibleColumns);
			float num9 = Mathf.Min(Plugin.MvpInstalled ? 440f : 280f, (num8 - 24f - 8f * (float)(visibleColumns - 1)) / (float)visibleColumns);
			num9 = Mathf.Max(140f, num9);
			int num10 = ((list.Count == 0) ? 1 : Mathf.Max(1, Mathf.CeilToInt((float)visibleCount / (float)visibleColumns)));
			float num11 = ((list.Count == 0) ? 52f : ((float)num10 * num6 + 18f));
			float num12 = ((pageCount > 1) ? 28f : 0f);
			float num13 = 24f + (float)visibleColumns * num9 + (float)(visibleColumns - 1) * 8f;
			float num14 = num7 + awardHeight + 8f + num11 + num12 + 12f;
			float num15 = (flag ? ((float)Screen.width - num13 - 20f) : 20f);
			float num16 = (num4 ? ((float)Screen.height - num14 - 20f) : TopMargin);
			SetRect((Graphic)(object)panelImage, Mathf.Max(4f, num15), Mathf.Max(4f, num16), num13, num14);
			float num17 = Mathf.Clamp(Plugin.backgroundOpacity.Value, 0.55f, 0.95f);
			((Graphic)panelImage).color = new Color(0.025f, 0.03f, 0.04f, num17);
			((Graphic)headerImage).color = new Color(0.065f, 0.075f, 0.095f, Mathf.Min(0.95f, num17 + 0.06f));
			SetRect((Graphic)(object)accentImage, 0f, 0f, num13, 3f);
			SetRect((Graphic)(object)headerImage, 0f, 3f, num13, num7 - 3f);
			if ((Object)(object)awardImage != (Object)null)
			{
				((Component)awardImage).gameObject.SetActive(HasAwards);
			}
			if (HasAwards && (Object)(object)awardImage != (Object)null && (Object)(object)awardLinesText != (Object)null)
			{
				((Graphic)awardImage).color = new Color(0.12f, 0.11f, 0.085f, Mathf.Min(0.95f, num17 + 0.04f));
				SetRect((Graphic)(object)awardImage, 12f, num7 + 4f, num13 - 24f, awardHeight - 8f);
				float num18 = num13 - 24f - 16f;
				awardLinesText.fontSize = 14;
				((Graphic)awardLinesText).color = Color.white;
				string text = FitName("LAST LEVEL / " + Plugin.LastLevelAwardName, awardLinesText, num18);
				string text2 = FitName(Plugin.LastMvpAward, awardLinesText, num18 * 14f / 17f);
				string text3 = (string.IsNullOrEmpty(Plugin.LastMvpScoreDetails) ? "" : FitName("TOP SCORES  " + Plugin.LastMvpScoreDetails, awardLinesText, num18));
				string text4 = FitName("NEXT  " + Plugin.LastMvpRankings, awardLinesText, num18);
				string text5 = FitName(Plugin.LastReverseAward, awardLinesText, num18);
				awardLinesText.text = "<size=12><color=#C7CCD6>" + text + "</color></size>\n<size=17><color=#FFD64C><b>" + text2 + "</b></color></size>" + (string.IsNullOrEmpty(text3) ? "" : ("\n<size=13><color=#CDE0FF>" + text3 + "</color></size>")) + (string.IsNullOrEmpty(Plugin.LastMvpRankings) ? "" : ("\n<size=13><color=#C7CCD6>" + text4 + "</color></size>")) + "\n<size=14>" + text5 + "</size>";
				SetRect((Graphic)(object)awardLinesText, 8f, 3f, num18, awardHeight - 15f);
			}
			titleText.fontSize = num2;
			((Graphic)titleText).color = color;
			titleText.text = "PLAYER DEATHS";
			SetRect((Graphic)(object)titleText, 16f, 8f, num13 - 24f - 8f, (float)num2 + 8f);
			subtitleText.fontSize = Mathf.Clamp(num3 - 7, 9, 16);
			((Graphic)subtitleText).color = new Color(0.75f, 0.78f, 0.83f, 1f);
			Text? obj = subtitleText;
			string text6 = list.Count.ToString();
			KeyboardShortcut value = Plugin.toggleKey.Value;
			obj.text = text6 + " PLAYERS  |  " + ((object)((KeyboardShortcut)(ref value)).MainKey/*cast due to .constrained prefix*/).ToString().ToUpperInvariant() + " HIDE";
			float num19 = Mathf.Min(104f, num13 * 0.36f);
			SetRect((Graphic)(object)subtitleText, 16f, num7 - 29f, num13 - 24f - (Plugin.showTotal.Value ? (num19 + 12f) : 0f), 22f);
			((Component)totalImage).gameObject.SetActive(Plugin.showTotal.Value);
			if (Plugin.showTotal.Value)
			{
				SetRect((Graphic)(object)totalImage, num13 - 12f - num19, num7 - 34f, num19, 25f);
				totalText.fontSize = Mathf.Clamp(num3 - 3, 10, 23);
				((Graphic)totalText).color = Color.white;
				totalText.text = "TOTAL  " + num;
				SetRect((Graphic)(object)totalText, 0f, 0f, num19, 25f);
			}
			float num20 = num7 + awardHeight + 8f;
			StringBuilder[] array = new StringBuilder[2]
			{
				new StringBuilder(),
				new StringBuilder()
			};
			StringBuilder[] array2 = new StringBuilder[2]
			{
				new StringBuilder(),
				new StringBuilder()
			};
			int[] array3 = new int[2] { -1, -1 };
			string localSteamId = Plugin.GetLocalSteamId();
			string value2 = ColorUtility.ToHtmlStringRGB(val2);
			float num21 = Mathf.Clamp((float)num3 * 2.35f, 42f, 74f);
			float num22 = num9 - num21 - 28f;
			for (int j = 0; j < 2; j++)
			{
				names[j].fontSize = num3;
			}
			for (int k = 0; k < visibleCount; k++)
			{
				(string, string, int) tuple = list[startIndex + k];
				int num23 = k / num10;
				int num24 = k % num10;
				if (num24 != 0)
				{
					array[num23].Append('\n');
					array2[num23].Append('\n');
				}
				bool flag2 = Plugin.highlightSelf.Value && tuple.Item1 == localSteamId;
				if (flag2)
				{
					array3[num23] = num24;
				}
				string value3 = FitName(tuple.Item2.Replace('<', '‹').Replace('>', '›'), names[num23], num22 - (flag2 ? 20f : 0f));
				if (flag2)
				{
					array[num23].Append("<color=#").Append(value2).Append("><b>★ ")
						.Append(value3)
						.Append("</b></color>");
					array2[num23].Append("<color=#").Append(value2).Append(">")
						.Append(tuple.Item3)
						.Append("</color>");
				}
				else
				{
					array[num23].Append(value3);
					array2[num23].Append(tuple.Item3);
				}
			}
			for (int l = 0; l < 2; l++)
			{
				bool flag3 = l < visibleColumns;
				((Component)columnBackground[l]).gameObject.SetActive(flag3);
				if (flag3)
				{
					float x = 12f + (float)l * (num9 + 8f);
					SetRect((Graphic)(object)columnBackground[l], x, num20, num9, num11);
					bool flag4 = list.Count > 0;
					((Component)countBackground[l]).gameObject.SetActive(flag4);
					if (flag4)
					{
						SetRect((Graphic)(object)countBackground[l], num9 - num21 - 8f, 4f, num21, num11 - 8f);
					}
					bool flag5 = array3[l] >= 0;
					((Component)selfHighlight[l]).gameObject.SetActive(flag5);
					if (flag5)
					{
						SetRect((Graphic)(object)selfHighlight[l], 0f, (float)array3[l] * num6, num9, num5);
					}
					names[l].fontSize = num3;
					((Graphic)names[l]).color = val;
					counts[l].fontSize = num3;
					((Graphic)counts[l]).color = Color.white;
					float num25 = Mathf.Max(1f, (float)font.lineHeight * (float)num3 / (float)Mathf.Max(1, font.fontSize));
					float lineSpacing = num6 / num25;
					names[l].lineSpacing = lineSpacing;
					counts[l].lineSpacing = lineSpacing;
					names[l].text = (flag4 ? array[l].ToString() : "NO PLAYERS YET");
					names[l].alignment = (TextAnchor)((!flag4) ? 4 : 0);
					counts[l].text = (flag4 ? array2[l].ToString() : "");
					if (flag4)
					{
						SetRect((Graphic)(object)names[l], 12f, 6f, num22, num11 - 8f);
						SetRect((Graphic)(object)counts[l], 4f, 2f, num21 - 8f, num11 - 8f);
					}
					else
					{
						SetRect((Graphic)(object)names[l], 4f, 0f, num9 - 8f, num11);
					}
				}
			}
			((Component)dividerImage).gameObject.SetActive(pageCount > 1);
			((Component)pageText).gameObject.SetActive(pageCount > 1);
			if (pageCount > 1)
			{
				float num26 = num20 + num11 + 7f;
				SetRect((Graphic)(object)dividerImage, 12f, num26, num13 - 24f, 1f);
				pageText.fontSize = Mathf.Clamp(num3 - 7, 9, 16);
				((Graphic)pageText).color = new Color(0.75f, 0.78f, 0.83f, 1f);
				pageText.text = "PAGE " + (pageIndex + 1) + "/" + pageCount + "  |  PLAYERS " + (startIndex + 1) + "-" + (startIndex + visibleCount) + " OF " + list.Count;
				SetRect((Graphic)(object)pageText, 12f, num26 + 3f, num13 - 24f, 20f);
			}
			((Graphic)titleText).SetAllDirty();
			((Graphic)subtitleText).SetAllDirty();
			((Graphic)totalText).SetAllDirty();
			if (HasAwards && (Object)(object)awardLinesText != (Object)null)
			{
				((Graphic)awardLinesText).SetAllDirty();
			}
			for (int m = 0; m < visibleColumns; m++)
			{
				((Graphic)names[m]).SetAllDirty();
				((Graphic)counts[m]).SetAllDirty();
			}
			if (pageCount > 1)
			{
				((Graphic)pageText).SetAllDirty();
			}
		}

		private static string FitName(string name, Text label, float width)
		{
			if (string.IsNullOrEmpty(name))
			{
				return "UNKNOWN PLAYER";
			}
			label.text = name;
			if (label.preferredWidth <= width)
			{
				return name;
			}
			int num = name.Length;
			do
			{
				num--;
				label.text = name.Substring(0, num).TrimEnd(Array.Empty<char>()) + "...";
			}
			while (num > 1 && label.preferredWidth > width);
			return label.text;
		}

		private void WarmGlyphs(List<(string SteamId, string Name, int Deaths)> lines, int titleSize, int itemSize)
		{
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: 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)
			if ((Object)(object)font == (Object)null || !font.dynamic)
			{
				return;
			}
			StringBuilder stringBuilder = new StringBuilder("★ ... ‹› 0123456789");
			foreach (var line in lines)
			{
				stringBuilder.Append(' ').Append(line.Name);
			}
			string characters = stringBuilder.ToString();
			string text = "LAST LEVEL / TOP SCORES NEXT MVP OOPS CHAMP PTS SETBACK " + Plugin.LastLevelAwardName + Plugin.LastMvpAward + Plugin.LastReverseAward + Plugin.LastMvpScoreDetails + Plugin.LastMvpRankings;
			RequestNewGlyphs(characters, itemSize, (FontStyle)0);
			RequestNewGlyphs(characters, itemSize, (FontStyle)1);
			if (HasAwards)
			{
				Font? obj = awardFont ?? font;
				obj.RequestCharactersInTexture(text, 12, (FontStyle)0);
				obj.RequestCharactersInTexture(text, 13, (FontStyle)0);
				obj.RequestCharactersInTexture(text, 14, (FontStyle)0);
				obj.RequestCharactersInTexture(text, 17, (FontStyle)1);
			}
			RequestNewGlyphs("PLAYER DEATHS", titleSize, (FontStyle)1);
			KeyboardShortcut value = Plugin.toggleKey.Value;
			RequestNewGlyphs("0123456789 PLAYERS  |  " + ((object)((KeyboardShortcut)(ref value)).MainKey/*cast due to .constrained prefix*/).ToString().ToUpperInvariant() + " HIDE", Mathf.Clamp(itemSize - 7, 9, 16), (FontStyle)0);
			(totalFont ?? font).RequestCharactersInTexture("TOTAL  0123456789", Mathf.Clamp(itemSize - 3, 10, 23), (FontStyle)1);
		}

		private void RequestNewGlyphs(string characters, int size, FontStyle style)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)font == (Object)null || !font.dynamic)
			{
				return;
			}
			(int, FontStyle) key = (size, style);
			if (!requestedGlyphs.TryGetValue(key, out HashSet<char> value))
			{
				value = new HashSet<char>();
				requestedGlyphs[key] = value;
			}
			StringBuilder stringBuilder = new StringBuilder();
			HashSet<char> hashSet = new HashSet<char>();
			string text = characters;
			foreach (char c in text)
			{
				if (!value.Contains(c) && hashSet.Add(c))
				{
					stringBuilder.Append(c);
				}
			}
			if (stringBuilder.Length != 0)
			{
				string text2 = stringBuilder.ToString();
				font.RequestCharactersInTexture(text2, size, style);
				text = text2;
				foreach (char item in text)
				{
					value.Add(item);
				}
			}
		}

		private static void SetRect(Graphic graphic, float x, float y, float width, float height)
		{
			SetRect(graphic.rectTransform, x, y, width, height);
		}

		private static void SetRect(RectTransform rect, float x, float y, float width, float height)
		{
			//IL_0013: 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_002a: 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_0046: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(0f, 1f);
			rect.anchorMax = val;
			rect.anchorMin = val;
			rect.pivot = new Vector2(0f, 1f);
			rect.anchoredPosition = new Vector2(x, 0f - y);
			rect.sizeDelta = new Vector2(width, height);
		}

		private void OnDestroy()
		{
			if ((Object)(object)sprite != (Object)null)
			{
				Object.Destroy((Object)(object)sprite);
			}
			if ((Object)(object)pixel != (Object)null)
			{
				Object.Destroy((Object)(object)pixel);
			}
			if (ownsTotalFont && (Object)(object)totalFont != (Object)null)
			{
				Object.Destroy((Object)(object)totalFont);
			}
			if (ownsAwardFont && (Object)(object)awardFont != (Object)null)
			{
				Object.Destroy((Object)(object)awardFont);
			}
			if (ownsFont && (Object)(object)font != (Object)null)
			{
				Object.Destroy((Object)(object)font);
			}
		}
	}
	internal sealed class DeathSyncBehaviour : MonoBehaviour, IInRoomCallbacks, IOnEventCallback
	{
		internal const byte DeathSyncEventCode = 77;

		internal const byte DeathReportEventCode = 78;

		private const float DuplicateWindowSeconds = 2f;

		private static MethodInfo? isMasterOrSpMethod;

		private static bool isMasterResolved;

		private static FieldInfo? statsInstanceField;

		private static FieldInfo? saveFileCurrentField;

		private static bool statsResolved;

		private static readonly Dictionary<string, float> LastAcceptedDeathTime = new Dictionary<string, float>();

		private string? loadedSaveFile;

		private float pollTimer;

		private bool callbacksRegistered;

		private static string SaveDir => Path.Combine(Application.persistentDataPath, "MatsuDeathCounter");

		private void OnDestroy()
		{
			if (callbacksRegistered)
			{
				try
				{
					PhotonNetwork.RemoveCallbackTarget((object)this);
				}
				catch
				{
				}
				callbacksRegistered = false;
			}
		}

		private void Update()
		{
			try
			{
				bool flag = false;
				try
				{
					flag = PhotonNetwork.InRoom && !PhotonNetwork.OfflineMode;
				}
				catch
				{
				}
				if (flag && !callbacksRegistered)
				{
					try
					{
						PhotonNetwork.AddCallbackTarget((object)this);
						callbacksRegistered = true;
					}
					catch (Exception ex)
					{
						Plugin.TrackerErr("[DeathCounter] AddCallbackTarget failed: " + ex.Message);
					}
				}
				else if (!flag && callbacksRegistered)
				{
					try
					{
						PhotonNetwork.RemoveCallbackTarget((object)this);
					}
					catch
					{
					}
					callbacksRegistered = false;
				}
				pollTimer += Time.deltaTime;
				if (pollTimer < 1f)
				{
					return;
				}
				pollTimer = 0f;
				Plugin.RefreshVisiblePlayers();
				if (!IsHost())
				{
					return;
				}
				string saveFileCurrent = GetSaveFileCurrent();
				if (!(saveFileCurrent == loadedSaveFile))
				{
					loadedSaveFile = saveFileCurrent;
					Plugin.DeathCountsBySteamId.Clear();
					Plugin.PlayerNamesBySteamId.Clear();
					LastAcceptedDeathTime.Clear();
					if (!string.IsNullOrEmpty(saveFileCurrent))
					{
						LoadFromDisk(saveFileCurrent);
						BroadcastDeaths();
					}
					Plugin.MarkUiDirty();
				}
			}
			catch (Exception ex2)
			{
				Plugin.TrackerErr("[DeathCounter] Update error: " + ex2.Message);
			}
		}

		public void OnEvent(EventData photonEvent)
		{
			if (photonEvent.Code == 78)
			{
				if (IsHost())
				{
					HandleDeathReport(photonEvent);
				}
			}
			else
			{
				if (photonEvent.Code != 77 || IsHost())
				{
					return;
				}
				try
				{
					if (photonEvent.CustomData is object[] array && array.Length >= 3 && array[0] is string[] ids && array[1] is int[] deathCounts && array[2] is string[] playerNames)
					{
						DeathCounterCore.ApplySnapshot(ids, deathCounts, playerNames, Plugin.DeathCountsBySteamId, Plugin.PlayerNamesBySteamId);
						Plugin.MarkUiDirty();
					}
				}
				catch (Exception ex)
				{
					Plugin.TrackerErr("[DeathCounter] Snapshot apply failed: " + ex.Message);
				}
			}
		}

		private static void HandleDeathReport(EventData photonEvent)
		{
			try
			{
				if (!(photonEvent.CustomData is int num) || num <= 0)
				{
					return;
				}
				PhotonView val = PhotonView.Find(num);
				if ((Object)(object)val == (Object)null || val.Owner == null || val.Owner.ActorNumber != photonEvent.Sender)
				{
					Plugin.TrackerErr("[DeathCounter] Rejected a death report whose sender did not own its avatar ViewID.");
					return;
				}
				Component component = ((Component)val).GetComponent("PlayerAvatar");
				if ((Object)(object)component == (Object)null || !Plugin.TryGetPlayerIdentity(component, out string steamId, out string playerName, out int _))
				{
					Plugin.TrackerErr("[DeathCounter] Rejected a death report without a resolvable PlayerAvatar identity.");
				}
				else
				{
					OnHostDeath(steamId, playerName, "player report");
				}
			}
			catch (Exception ex)
			{
				Plugin.TrackerErr("[DeathCounter] Death report failed: " + ex.Message);
			}
		}

		public void OnPlayerEnteredRoom(Player newPlayer)
		{
			if (IsHost())
			{
				BroadcastDeaths();
			}
		}

		public void OnPlayerLeftRoom(Player otherPlayer)
		{
		}

		public void OnRoomPropertiesUpdate(Hashtable propertiesThatChanged)
		{
		}

		public void OnPlayerPropertiesUpdate(Player targetPlayer, Hashtable changedProps)
		{
		}

		public void OnMasterClientSwitched(Player newMasterClient)
		{
		}

		internal static void ReportLocalDeath(string steamId, string playerName, int photonViewId)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			if (!DeathCounterCore.ShouldCountDeath(Plugin.IsInShop()))
			{
				return;
			}
			if (IsHost())
			{
				OnHostDeath(steamId, playerName, "local host");
				return;
			}
			try
			{
				if (!PhotonNetwork.InRoom || PhotonNetwork.OfflineMode || photonViewId <= 0)
				{
					Plugin.TrackerErr("[DeathCounter] Could not report a client death: no joined room or avatar ViewID. The host RPC fallback may still record it.");
					return;
				}
				PhotonNetwork.RaiseEvent((byte)78, (object)photonViewId, new RaiseEventOptions
				{
					Receivers = (ReceiverGroup)2
				}, SendOptions.SendReliable);
			}
			catch (Exception ex)
			{
				Plugin.TrackerErr("[DeathCounter] Client death report failed: " + ex.Message);
			}
		}

		internal static void RecordRpcFallback(string steamId, string playerName, int photonViewId)
		{
			OnHostDeath(steamId, playerName, "RPC fallback");
		}

		internal static void ResetTallyForGameOver()
		{
			Plugin.DeathCountsBySteamId.Clear();
			Plugin.PlayerNamesBySteamId.Clear();
			LastAcceptedDeathTime.Clear();
			Plugin.MarkUiDirty();
			if (IsHost())
			{
				SaveToDisk();
				BroadcastDeaths();
			}
		}

		private static void OnHostDeath(string steamId, string playerName, string source)
		{
			if (!IsHost() || !DeathCounterCore.ShouldCountDeath(Plugin.IsInShop()))
			{
				return;
			}
			if (!DeathCounterCore.TryRecordDeath(Plugin.DeathCountsBySteamId, Plugin.PlayerNamesBySteamId, LastAcceptedDeathTime, steamId, playerName, Time.unscaledTime, 2f, out string key, out int newCount))
			{
				if (!string.IsNullOrEmpty(key))
				{
					Plugin.TrackerLog("[DeathCounter] Ignored duplicate death for " + key + " (" + source + ").");
				}
			}
			else
			{
				Plugin.TrackerLog($"[DeathCounter] {(string.IsNullOrWhiteSpace(playerName) ? key : playerName)} died ({source}). Total: {newCount}");
				Plugin.MarkUiDirty();
				SaveToDisk();
				BroadcastDeaths();
			}
		}

		private static void BroadcastDeaths()
		{
			//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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			try
			{
				if (PhotonNetwork.InRoom && !PhotonNetwork.OfflineMode)
				{
					PhotonNetwork.RaiseEvent((byte)77, (object)Pack(), new RaiseEventOptions
					{
						Receivers = (ReceiverGroup)0
					}, SendOptions.SendReliable);
				}
			}
			catch (Exception ex)
			{
				Plugin.TrackerErr("[DeathCounter] Broadcast failed: " + ex.Message);
			}
		}

		private static object[] Pack()
		{
			DeathCounterCore.BuildSnapshot(Plugin.DeathCountsBySteamId, Plugin.PlayerNamesBySteamId, out string[] ids, out int[] deathCounts, out string[] playerNames);
			return new object[3] { ids, deathCounts, playerNames };
		}

		private static string SavePathFor(string saveFile)
		{
			return Path.Combine(SaveDir, DeathCounterCore.SanitizeFileName(saveFile, Path.GetInvalidFileNameChars()) + ".tsv");
		}

		internal static void SaveToDisk()
		{
			string saveFileCurrent = GetSaveFileCurrent();
			if (string.IsNullOrEmpty(saveFileCurrent))
			{
				return;
			}
			try
			{
				Directory.CreateDirectory(SaveDir);
				File.WriteAllText(SavePathFor(saveFileCurrent), DeathCounterCore.Serialize(Plugin.DeathCountsBySteamId, Plugin.PlayerNamesBySteamId));
			}
			catch (Exception ex)
			{
				Plugin.TrackerErr("[DeathCounter] Save failed: " + ex.Message);
			}
		}

		private static void LoadFromDisk(string saveFile)
		{
			try
			{
				string path = SavePathFor(saveFile);
				if (File.Exists(path))
				{
					DeathCounterCore.Deserialize(File.ReadAllText(path), Plugin.DeathCountsBySteamId, Plugin.PlayerNamesBySteamId);
				}
			}
			catch (Exception ex)
			{
				Plugin.TrackerErr("[DeathCounter] Load failed: " + ex.Message);
			}
		}

		internal static bool IsHost()
		{
			if (!isMasterResolved)
			{
				Type type = AccessTools.TypeByName("SemiFunc");
				isMasterOrSpMethod = ((type == null) ? null : AccessTools.Method(type, "IsMasterClientOrSingleplayer", (Type[])null, (Type[])null));
				isMasterResolved = true;
			}
			if (isMasterOrSpMethod != null)
			{
				try
				{
					return (bool)isMasterOrSpMethod.Invoke(null, null);
				}
				catch
				{
				}
			}
			try
			{
				return PhotonNetwork.OfflineMode || !PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient;
			}
			catch
			{
				return true;
			}
		}

		private static string GetSaveFileCurrent()
		{
			if (!statsResolved)
			{
				Type type = AccessTools.TypeByName("StatsManager");
				statsInstanceField = ((type == null) ? null : AccessTools.Field(type, "instance"));
				saveFileCurrentField = ((type == null) ? null : AccessTools.Field(type, "saveFileCurrent"));
				statsResolved = true;
			}
			try
			{
				object obj = statsInstanceField?.GetValue(null);
				return (saveFileCurrentField?.GetValue(obj) as string) ?? "";
			}
			catch
			{
				return "";
			}
		}
	}
	public enum OverlayCorner
	{
		TopRight,
		TopLeft,
		BottomRight,
		BottomLeft
	}
	public enum SortMode
	{
		DeathsAscending,
		DeathsDescending,
		NameAscending,
		NameDescending
	}
	[BepInPlugin("matsu.repo.deathcounter", "REPO Death Counter", "1.4.6")]
	public sealed class Plugin : BaseUnityPlugin
	{
		private const float OverlayMargin = 20f;

		private const float ColumnGap = 8f;

		private const float RowGap = 4f;

		private const float PanelPadding = 12f;

		private const float PageSeconds = 8f;

		private const int PreferredRowsPerColumn = 10;

		private const int MaximumColumnsPerPage = 4;

		public const string PluginGuid = "matsu.repo.deathcounter";

		public const string PluginName = "REPO Death Counter";

		public const string PluginVersion = "1.4.6";

		private const string MvpPluginGuid = "matsu.repo.mvp";

		internal static string LastLevelAwardName = "";

		internal static string LastMvpAward = "";

		internal static string LastReverseAward = "";

		internal static string LastMvpScoreDetails = "";

		internal static string LastMvpRankings = "";

		internal static int AwardRevision;

		internal static int UiRevision;

		internal static ManualLogSource? Log;

		public static readonly Dictionary<string, int> DeathCountsBySteamId = new Dictionary<string, int>();

		public static readonly Dictionary<string, string> PlayerNamesBySteamId = new Dictionary<string, string>();

		internal static readonly Dictionary<string, string> VisiblePlayerNamesBySteamId = new Dictionary<string, string>();

		internal static ConfigEntry<bool> showOverlay = null;

		internal static ConfigEntry<OverlayCorner> overlayCorner = null;

		internal static ConfigEntry<int> titleFontSize = null;

		internal static ConfigEntry<int> itemFontSize = null;

		internal static ConfigEntry<string> titleColorHex = null;

		internal static ConfigEntry<string> itemColorHex = null;

		internal static ConfigEntry<SortMode> sortMode = null;

		internal static ConfigEntry<bool> showTotal = null;

		internal static ConfigEntry<bool> highlightSelf = null;

		internal static ConfigEntry<string> selfColorHex = null;

		internal static ConfigEntry<float> backgroundOpacity = null;

		internal static ConfigEntry<KeyboardShortcut> toggleKey = null;

		private static GameObject? runtimeRoot;

		private static bool gameDirectorReflectionResolved;

		private static FieldInfo? gameDirectorInstanceField;

		private static FieldInfo? gameDirectorPlayerListField;

		private static bool runManagerReflectionResolved;

		private static FieldInfo? runManagerInstanceField;

		private static FieldInfo? runManagerLevelCurrentField;

		private static FieldInfo? runManagerLevelLobbyField;

		private static FieldInfo? runManagerLevelIsShopField;

		private static bool playerReflectionResolved;

		private static FieldInfo? playerAvatarInstanceField;

		private static FieldInfo? playerIsLocalField;

		private static FieldInfo? playerSteamIdField;

		private static FieldInfo? playerNameField;

		private static FieldInfo? playerPhotonViewField;

		private static FieldInfo? playerDeadSetField;

		private static bool shopReflectionResolved;

		private static MethodInfo? runIsShopMethod;

		private static bool gameOverReflectionResolved;

		private static MethodInfo? runIsArenaMethod;

		private Harmony harmony;

		private Texture2D? panelTexture;

		private Texture2D? headerTexture;

		private Texture2D? rowTexture;

		private Texture2D? alternateRowTexture;

		private Texture2D? selfRowTexture;

		private Texture2D? accentTexture;

		private Texture2D? countBadgeTexture;

		private Texture2D? dividerTexture;

		private Texture2D? solidTexture;

		internal static bool MvpInstalled { get; private set; }

		public static void SetLastLevelAwards(string levelName, string mvp, string reverse)
		{
			SetLastLevelAwardsDetailed(levelName, mvp, reverse, "", "");
		}

		public static void SetLastLevelAwardsDetailed(string levelName, string mvp, string reverse, string scoreDetails, string rankings)
		{
			if (MvpInstalled)
			{
				levelName = TrimAward(levelName, 80);
				mvp = TrimAward(mvp, 160);
				reverse = TrimAward(reverse, 160);
				scoreDetails = TrimAward(scoreDetails, 160);
				rankings = TrimAward(rankings, 160);
				if (!(levelName == LastLevelAwardName) || !(mvp == LastMvpAward) || !(reverse == LastReverseAward) || !(scoreDetails == LastMvpScoreDetails) || !(rankings == LastMvpRankings))
				{
					LastLevelAwardName = levelName;
					LastMvpAward = mvp;
					LastReverseAward = reverse;
					LastMvpScoreDetails = scoreDetails;
					LastMvpRankings = rankings;
					AwardRevision++;
					MarkUiDirty();
				}
			}
		}

		internal static void MarkUiDirty()
		{
			UiRevision++;
		}

		private static string TrimAward(string? value, int maximum)
		{
			value = (value ?? "").Replace('\n', ' ').Replace('\r', ' ').Replace('<', '‹')
				.Replace('>', '›');
			if (value.Length > maximum)
			{
				return value.Substring(0, maximum);
			}
			return value;
		}

		private void Awake()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			harmony = new Harmony("matsu.repo.deathcounter");
			showOverlay = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowOverlay", true, "Show the death-count overlay in the truck lobby.");
			overlayCorner = ((BaseUnityPlugin)this).Config.Bind<OverlayCorner>("Display", "Corner", OverlayCorner.TopRight, "Which screen corner the overlay is anchored to.");
			titleFontSize = ((BaseUnityPlugin)this).Config.Bind<int>("Display", "TitleFontSize", 24, "Font size of the header.");
			itemFontSize = ((BaseUnityPlugin)this).Config.Bind<int>("Display", "FontSize", 20, "Font size of each player line.");
			titleColorHex = ((BaseUnityPlugin)this).Config.Bind<string>("Display", "TitleColorHex", "FF3333", "Header text color, hex RGB (for example FF3333). '#' is optional.");
			itemColorHex = ((BaseUnityPlugin)this).Config.Bind<string>("Display", "TextColorHex", "FFFFFF", "Player-line text color, hex RGB (for example FFFFFF). '#' is optional.");
			sortMode = ((BaseUnityPlugin)this).Config.Bind<SortMode>("Display", "SortMode", SortMode.DeathsAscending, "List order. DeathsAscending puts the fewest deaths on top.");
			showTotal = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowTotal", true, "Show a total-deaths badge in the scoreboard header.");
			highlightSelf = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "HighlightSelf", true, "Draw your own row in a different color so it is easy to spot.");
			selfColorHex = ((BaseUnityPlugin)this).Config.Bind<string>("Display", "SelfColorHex", "FFD700", "Your own row's text color, hex RGB. Only used when HighlightSelf is on.");
			backgroundOpacity = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "BackgroundOpacity", 0.82f, "Truck scoreboard background opacity, from 0.55 (more transparent) to 0.95.");
			toggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Display", "ToggleKey", new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()), "Press this key to show or hide the truck scoreboard for this session.");
			TryPatchPlayerMethod("PlayerDeath", "PlayerAvatar_PlayerDeath_Prefix", "primary local death reporter");
			TryPatchPlayerMethod("PlayerDeathRPC", "PlayerDeathRpcPrefix", "host RPC fallback");
			TryPatchRunManagerMethod("ResetProgress", "RunManager_ResetProgress_Postfix", "game-over tally reset");
			SceneManager.sceneLoaded += OnInitialSceneLoaded;
			Log.LogInfo((object)"REPO Death Counter 1.4.6 loaded. BepInEx is the only required dependency.");
		}

		private static void OnInitialSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			SceneManager.sceneLoaded -= OnInitialSceneLoaded;
			MvpInstalled = Chainloader.PluginInfos.ContainsKey("matsu.repo.mvp");
			if ((Object)(object)runtimeRoot == (Object)null)
			{
				runtimeRoot = new GameObject("REPO Death Counter Runtime");
				Object.DontDestroyOnLoad((Object)(object)runtimeRoot);
				runtimeRoot.AddComponent<DeathSyncBehaviour>();
				runtimeRoot.AddComponent<DeathCounterOverlayLite>();
			}
		}

		private void TryPatchPlayerMethod(string methodName, string prefixName, string label)
		{
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Expected O, but got Unknown
			try
			{
				Type type = AccessTools.TypeByName("PlayerAvatar");
				MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, methodName, (Type[])null, (Type[])null));
				MethodInfo methodInfo2 = AccessTools.Method(typeof(Plugin), prefixName, (Type[])null, (Type[])null);
				if (methodInfo == null || methodInfo2 == null)
				{
					ManualLogSource? log = Log;
					if (log != null)
					{
						log.LogWarning((object)("[DeathCounter] PlayerAvatar." + methodName + " was not found; " + label + " is unavailable."));
					}
					return;
				}
				harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				ManualLogSource? log2 = Log;
				if (log2 != null)
				{
					log2.LogInfo((object)("[DeathCounter] Patched PlayerAvatar." + methodName + " (" + label + ")."));
				}
			}
			catch (Exception arg)
			{
				ManualLogSource? log3 = Log;
				if (log3 != null)
				{
					log3.LogError((object)$"[DeathCounter] Failed to patch PlayerAvatar.{methodName} ({label}): {arg}");
				}
			}
		}

		private void TryPatchRunManagerMethod(string methodName, string postfixName, string label)
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Expected O, but got Unknown
			try
			{
				Type type = AccessTools.TypeByName("RunManager");
				MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, methodName, (Type[])null, (Type[])null));
				MethodInfo methodInfo2 = AccessTools.Method(typeof(Plugin), postfixName, (Type[])null, (Type[])null);
				if (methodInfo == null || methodInfo2 == null)
				{
					ManualLogSource? log = Log;
					if (log != null)
					{
						log.LogWarning((object)("[DeathCounter] RunManager." + methodName + " was not found; " + label + " is unavailable."));
					}
					return;
				}
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				ManualLogSource? log2 = Log;
				if (log2 != null)
				{
					log2.LogInfo((object)("[DeathCounter] Patched RunManager." + methodName + " (" + label + ")."));
				}
			}
			catch (Exception arg)
			{
				ManualLogSource? log3 = Log;
				if (log3 != null)
				{
					log3.LogError((object)$"[DeathCounter] Failed to patch RunManager.{methodName} ({label}): {arg}");
				}
			}
		}

		private void DrawLegacyOverlay()
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: 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_0069: 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)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0301: Unknown result type (might be due to invalid IL or missing references)
			//IL_0313: Unknown result type (might be due to invalid IL or missing references)
			//IL_032e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0352: Unknown result type (might be due to invalid IL or missing references)
			//IL_036c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0371: Unknown result type (might be due to invalid IL or missing references)
			//IL_0378: Unknown result type (might be due to invalid IL or missing references)
			//IL_037f: 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_038d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0396: Expected O, but got Unknown
			//IL_039d: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e2: Expected O, but got Unknown
			//IL_03fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0486: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_05af: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_05bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d9: Expected O, but got Unknown
			//IL_05e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f6: Expected O, but got Unknown
			//IL_05fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_060e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0613: Unknown result type (might be due to invalid IL or missing references)
			//IL_061a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0621: Unknown result type (might be due to invalid IL or missing references)
			//IL_0628: Unknown result type (might be due to invalid IL or missing references)
			//IL_062f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0638: Expected O, but got Unknown
			//IL_063f: Unknown result type (might be due to invalid IL or missing references)
			//IL_052c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0531: Unknown result type (might be due to invalid IL or missing references)
			//IL_0547: Unknown result type (might be due to invalid IL or missing references)
			//IL_054c: Unknown result type (might be due to invalid IL or missing references)
			//IL_055e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0565: Unknown result type (might be due to invalid IL or missing references)
			//IL_056c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0573: Unknown result type (might be due to invalid IL or missing references)
			//IL_057c: Expected O, but got Unknown
			//IL_0583: Unknown result type (might be due to invalid IL or missing references)
			//IL_0683: Unknown result type (might be due to invalid IL or missing references)
			//IL_0688: Unknown result type (might be due to invalid IL or missing references)
			//IL_0696: Unknown result type (might be due to invalid IL or missing references)
			//IL_069b: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_06b6: Expected O, but got Unknown
			//IL_06bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_06d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_074e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0937: Unknown result type (might be due to invalid IL or missing references)
			//IL_0898: Unknown result type (might be due to invalid IL or missing references)
			//IL_08aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_08af: Unknown result type (might be due to invalid IL or missing references)
			//IL_08b8: Expected O, but got Unknown
			//IL_08e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0807: Unknown result type (might be due to invalid IL or missing references)
			//IL_080c: Unknown result type (might be due to invalid IL or missing references)
			//IL_082f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0795: Unknown result type (might be due to invalid IL or missing references)
			//IL_07a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_07b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_07c4: Unknown result type (might be due to invalid IL or missing references)
			if (!showOverlay.Value || !IsInTruckLobby())
			{
				return;
			}
			EnsureUiTextures();
			int num = Mathf.Clamp(titleFontSize.Value, 6, 100);
			int num2 = Mathf.Clamp(itemFontSize.Value, 6, 100);
			Color textColor = ParseColor(titleColorHex.Value, Color.red);
			Color val = ParseColor(itemColorHex.Value, Color.white);
			Color val2 = ParseColor(selfColorHex.Value, val);
			bool flag = overlayCorner.Value == OverlayCorner.TopRight || overlayCorner.Value == OverlayCorner.BottomRight;
			bool flag2 = overlayCorner.Value == OverlayCorner.BottomLeft || overlayCorner.Value == OverlayCorner.BottomRight;
			List<(string, string, int)> list = BuildSortedLines();
			long num3 = 0L;
			foreach (var item in list)
			{
				num3 += item.Item3;
			}
			float num4 = Mathf.Max(30f, (float)num2 + 14f);
			float num5 = Mathf.Max(62f, (float)num + 36f);
			float num6 = Mathf.Max(180f, (float)Screen.width - 40f);
			float num7 = (float)Screen.height - 40f - num5 - 52f;
			int num8 = Mathf.Max(1, Mathf.FloorToInt((num7 + 4f) / (num4 + 4f)));
			int rowsPerColumn = Mathf.Min(10, num8);
			int num9 = Mathf.Max(1, Mathf.FloorToInt((num6 - 24f + 8f) / 248f));
			int maxColumns = Mathf.Min(4, num9);
			int requestedPage = Mathf.FloorToInt(Time.unscaledTime / 8f);
			DeathCounterCore.CalculateOverlayPage(list.Count, rowsPerColumn, maxColumns, requestedPage, out var pageIndex, out var pageCount, out var startIndex, out var visibleCount, out var visibleColumns);
			float num10 = Mathf.Min(300f, (num6 - 24f - 8f * (float)(visibleColumns - 1)) / (float)visibleColumns);
			num10 = Mathf.Max(140f, num10);
			int num11 = ((list.Count == 0) ? 1 : Mathf.Max(1, Mathf.CeilToInt((float)visibleCount / (float)visibleColumns)));
			int num12 = ((list.Count == 0) ? 1 : num11);
			float num13 = ((list.Count == 0) ? 52f : ((float)num12 * num4 + (float)Mathf.Max(0, num12 - 1) * 4f));
			float num14 = ((pageCount > 1) ? 28f : 0f);
			float num15 = 24f + (float)visibleColumns * num10 + (float)(visibleColumns - 1) * 8f;
			float num16 = num5 + 8f + num13 + num14 + 12f;
			float num17 = (flag ? ((float)Screen.width - num15 - 20f) : 20f);
			float num18 = (flag2 ? ((float)Screen.height - num16 - 20f) : 20f);
			num17 = Mathf.Max(4f, num17);
			num18 = Mathf.Max(4f, num18);
			Color color = GUI.color;
			GUI.color = Color.white;
			GUI.DrawTexture(new Rect(num17, num18, num15, num16), (Texture)(object)panelTexture);
			GUI.DrawTexture(new Rect(num17, num18, num15, 3f), (Texture)(object)accentTexture);
			GUI.DrawTexture(new Rect(num17, num18 + 3f, num15, num5 - 3f), (Texture)(object)headerTexture);
			GUIStyle val3 = new GUIStyle(GUI.skin.label)
			{
				fontSize = num,
				fontStyle = (FontStyle)1,
				alignment = (TextAnchor)3,
				clipping = (TextClipping)1,
				richText = false
			};
			val3.normal.textColor = textColor;
			GUIStyle val4 = new GUIStyle(GUI.skin.label)
			{
				fontSize = Mathf.Clamp(num2 - 7, 9, 16),
				fontStyle = (FontStyle)0,
				alignment = (TextAnchor)3,
				clipping = (TextClipping)1,
				richText = false
			};
			val4.normal.textColor = new Color(0.72f, 0.75f, 0.8f, 1f);
			float num19 = (showTotal.Value ? Mathf.Min(104f, num15 * 0.34f) : 0f);
			float num20 = num17 + num15 - 12f - num19 - (showTotal.Value ? 10f : 0f);
			GUI.Label(new Rect(num17 + 12f + 4f, num18 + 8f, num20 - num17 - 12f - 4f, (float)num + 8f), "PLAYER DEATHS", val3);
			string text = ((list.Count == 1) ? "1 PLAYER RECORDED" : $"{list.Count} PLAYERS RECORDED");
			GUI.Label(new Rect(num17 + 12f + 4f, num18 + num5 - 25f, num20 - num17 - 12f - 4f, 18f), text, val4);
			if (showTotal.Value)
			{
				Rect val5 = new Rect(num17 + num15 - 12f - num19, num18 + 13f, num19, num5 - 23f);
				GUI.DrawTexture(val5, (Texture)(object)countBadgeTexture);
				GUIStyle val6 = new GUIStyle(GUI.skin.label)
				{
					fontSize = Mathf.Clamp(num2 - 2, 10, 28),
					fontStyle = (FontStyle)1,
					alignment = (TextAnchor)4,
					clipping = (TextClipping)1,
					richText = false
				};
				val6.normal.textColor = Color.white;
				GUI.Label(val5, $"TOTAL  {num3}", val6);
			}
			GUIStyle val7 = new GUIStyle(GUI.skin.label)
			{
				fontSize = num2,
				fontStyle = (FontStyle)0,
				alignment = (TextAnchor)3,
				clipping = (TextClipping)1,
				richText = false
			};
			val7.normal.textColor = val;
			GUIStyle val8 = new GUIStyle(val7)
			{
				fontStyle = (FontStyle)1
			};
			val8.normal.textColor = val2;
			GUIStyle val9 = new GUIStyle(GUI.skin.label)
			{
				fontSize = num2,
				fontStyle = (FontStyle)1,
				alignment = (TextAnchor)4,
				clipping = (TextClipping)1,
				richText = false
			};
			val9.normal.textColor = Color.white;
			string text2 = (highlightSelf.Value ? GetLocalSteamId() : null);
			float num21 = num18 + num5 + 8f;
			if (list.Count == 0)
			{
				Rect val10 = new Rect(num17 + 12f, num21, num10, num13);
				GUI.DrawTexture(val10, (Texture)(object)rowTexture);
				GUIStyle val11 = new GUIStyle(val7)
				{
					fontSize = Mathf.Clamp(num2 - 2, 10, 28),
					alignment = (TextAnchor)4
				};
				val11.normal.textColor = new Color(val.r, val.g, val.b, 0.72f);
				GUI.Label(val10, "NO DEATHS RECORDED", val11);
			}
			else
			{
				Rect val12 = default(Rect);
				for (int i = 0; i < visibleCount; i++)
				{
					int num22 = startIndex + i;
					(string, string, int) tuple = list[num22];
					int num23 = i / num11;
					int num24 = i % num11;
					float num25 = num17 + 12f + (float)num23 * (num10 + 8f);
					float num26 = num21 + (float)num24 * (num4 + 4f);
					((Rect)(ref val12))..ctor(num25, num26, num10, num4);
					GUI.DrawTexture(val12, (Texture)(object)(((num22 & 1) == 0) ? rowTexture : alternateRowTexture));
					bool flag3 = highlightSelf.Value && !string.IsNullOrEmpty(text2) && tuple.Item1 == text2;
					if (flag3)
					{
						GUI.DrawTexture(val12, (Texture)(object)selfRowTexture);
						GUI.color = val2;
						GUI.DrawTexture(new Rect(num25, num26, 3f, num4), (Texture)(object)solidTexture);
						GUI.color = Color.white;
					}
					float num27 = Mathf.Clamp((float)num2 * 2.35f, 42f, 74f);
					Rect val13 = new Rect(num25 + num10 - num27 - 8f, num26 + 5f, num27, num4 - 10f);
					GUI.DrawTexture(val13, (Texture)(object)countBadgeTexture);
					GUI.Label(new Rect(num25 + 12f, num26, num10 - num27 - 28f, num4), tuple.Item2, flag3 ? val8 : val7);
					GUI.Label(val13, tuple.Item3.ToString(), val9);
				}
			}
			if (pageCount > 1)
			{
				float num28 = num21 + num13 + 7f;
				GUI.DrawTexture(new Rect(num17 + 12f, num28, num15 - 24f, 1f), (Texture)(object)dividerTexture);
				GUIStyle val14 = new GUIStyle(val4)
				{
					alignment = (TextAnchor)4
				};
				int num29 = startIndex + 1;
				int num30 = startIndex + visibleCount;
				GUI.Label(new Rect(num17 + 12f, num28 + 3f, num15 - 24f, 20f), $"PAGE {pageIndex + 1}/{pageCount}  |  PLAYERS {num29}-{num30} OF {list.Count}", val14);
			}
			GUI.color = color;
		}

		private void EnsureUiTextures()
		{
			//IL_0029: 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_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: 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)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)panelTexture != (Object)null))
			{
				panelTexture = CreateUiTexture("DeathCounter Panel", new Color(0.025f, 0.03f, 0.04f, 0.94f));
				headerTexture = CreateUiTexture("DeathCounter Header", new Color(0.065f, 0.075f, 0.095f, 0.98f));
				rowTexture = CreateUiTexture("DeathCounter Row", new Color(1f, 1f, 1f, 0.045f));
				alternateRowTexture = CreateUiTexture("DeathCounter Alternate Row", new Color(1f, 1f, 1f, 0.075f));
				selfRowTexture = CreateUiTexture("DeathCounter Self Row", new Color(1f, 0.65f, 0.05f, 0.14f));
				accentTexture = CreateUiTexture("DeathCounter Accent", new Color(0.92f, 0.1f, 0.12f, 1f));
				countBadgeTexture = CreateUiTexture("DeathCounter Count Badge", new Color(0.48f, 0.045f, 0.065f, 0.96f));
				dividerTexture = CreateUiTexture("DeathCounter Divider", new Color(1f, 1f, 1f, 0.14f));
				solidTexture = CreateUiTexture("DeathCounter Solid", Color.white);
			}
		}

		private static Texture2D CreateUiTexture(string textureName, Color color)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: 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_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_0029: 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_0038: Expected O, but got Unknown
			Texture2D val = new Texture2D(1, 1, (TextureFormat)4, false)
			{
				name = textureName,
				hideFlags = (HideFlags)61,
				filterMode = (FilterMode)0,
				wrapMode = (TextureWrapMode)1
			};
			val.SetPixel(0, 0, color);
			val.Apply(false, true);
			return val;
		}

		internal static List<(string SteamId, string Name, int Deaths)> BuildSortedLines()
		{
			List<KeyValuePair<string, int>> list = DeathCounterCore.BuildDisplayEntries(DeathCountsBySteamId, VisiblePlayerNamesBySteamId);
			switch (sortMode.Value)
			{
			case SortMode.DeathsAscending:
				list.Sort(delegate(KeyValuePair<string, int> a, KeyValuePair<string, int> b)
				{
					int num = a.Value.CompareTo(b.Value);
					return (num == 0) ? string.Compare(NameOf(a.Key), NameOf(b.Key), StringComparison.OrdinalIgnoreCase) : num;
				});
				break;
			case SortMode.DeathsDescending:
				list.Sort(delegate(KeyValuePair<string, int> a, KeyValuePair<string, int> b)
				{
					int num = b.Value.CompareTo(a.Value);
					return (num == 0) ? string.Compare(NameOf(a.Key), NameOf(b.Key), StringComparison.OrdinalIgnoreCase) : num;
				});
				break;
			case SortMode.NameAscending:
				list.Sort(delegate(KeyValuePair<string, int> a, KeyValuePair<string, int> b)
				{
					int num = string.Compare(NameOf(a.Key), NameOf(b.Key), StringComparison.OrdinalIgnoreCase);
					return (num == 0) ? string.Compare(a.Key, b.Key, StringComparison.Ordinal) : num;
				});
				break;
			case SortMode.NameDescending:
				list.Sort(delegate(KeyValuePair<string, int> a, KeyValuePair<string, int> b)
				{
					int num = string.Compare(NameOf(b.Key), NameOf(a.Key), StringComparison.OrdinalIgnoreCase);
					return (num == 0) ? string.Compare(a.Key, b.Key, StringComparison.Ordinal) : num;
				});
				break;
			}
			List<(string, string, int)> list2 = new List<(string, string, int)>(list.Count);
			foreach (KeyValuePair<string, int> item in list)
			{
				list2.Add((item.Key, NameOf(item.Key), item.Value));
			}
			return list2;
		}

		private static string NameOf(string steamId)
		{
			if (!VisiblePlayerNamesBySteamId.TryGetValue(steamId, out string value) || string.IsNullOrWhiteSpace(value))
			{
				if (!PlayerNamesBySteamId.TryGetValue(steamId, out string value2) || string.IsNullOrWhiteSpace(value2))
				{
					return steamId;
				}
				return value2;
			}
			return value;
		}

		internal static void RefreshVisiblePlayers()
		{
			try
			{
				if (!gameDirectorReflectionResolved)
				{
					Type type = AccessTools.TypeByName("GameDirector");
					gameDirectorInstanceField = ((type == null) ? null : AccessTools.Field(type, "instance"));
					gameDirectorPlayerListField = ((type == null) ? null : AccessTools.Field(type, "PlayerList"));
					gameDirectorReflectionResolved = true;
				}
				Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.Ordinal);
				object obj = gameDirectorInstanceField?.GetValue(null);
				if (obj != null && gameDirectorPlayerListField?.GetValue(obj) is IEnumerable enumerable)
				{
					foreach (object item in enumerable)
					{
						if (item != null)
						{
							Object val = (Object)((item is Object) ? item : null);
							if ((val == null || Object.op_Implicit(val)) && TryGetPlayerIdentity(item, out string steamId, out string playerName, out int _))
							{
								dictionary[steamId] = (string.IsNullOrWhiteSpace(playerName) ? steamId : playerName);
							}
						}
					}
				}
				if (dictionary.Count == VisiblePlayerNamesBySteamId.Count && dictionary.All((KeyValuePair<string, string> entry) => VisiblePlayerNamesBySteamId.TryGetValue(entry.Key, out string value) && value == entry.Value))
				{
					return;
				}
				VisiblePlayerNamesBySteamId.Clear();
				foreach (KeyValuePair<string, string> item2 in dictionary)
				{
					VisiblePlayerNamesBySteamId[item2.Key] = item2.Value;
				}
				MarkUiDirty();
			}
			catch (Exception ex)
			{
				TrackerErr("[DeathCounter] Player roster refresh failed: " + ex.Message);
			}
		}

		internal static Color ParseColor(string hex, Color fallback)
		{
			//IL_0008: 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_002e: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrWhiteSpace(hex))
			{
				return fallback;
			}
			if (!hex.StartsWith("#"))
			{
				hex = "#" + hex;
			}
			Color result = default(Color);
			if (!ColorUtility.TryParseHtmlString(hex, ref result))
			{
				return fallback;
			}
			return result;
		}

		private static void ResolveRunManagerFields()
		{
			if (!runManagerReflectionResolved)
			{
				Type type = AccessTools.TypeByName("RunManager");
				if (type != null)
				{
					runManagerInstanceField = AccessTools.Field(type, "instance");
					runManagerLevelCurrentField = AccessTools.Field(type, "levelCurrent");
					runManagerLevelLobbyField = AccessTools.Field(type, "levelLobby");
					runManagerLevelIsShopField = AccessTools.Field(type, "levelIsShop");
				}
				runManagerReflectionResolved = true;
			}
		}

		internal static bool IsInTruckLobby()
		{
			try
			{
				ResolveRunManagerFields();
				object obj = runManagerInstanceField?.GetValue(null);
				object obj2 = runManagerLevelCurrentField?.GetValue(obj);
				object obj3 = runManagerLevelLobbyField?.GetValue(obj);