Decompiled source of DamageMeter v1.1.1

plugins/DamageMeter.dll

Decompiled 17 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using TMPro;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Localization;
using UnityEngine.Localization.Settings;
using UnityEngine.Localization.Tables;
using UnityEngine.UI;

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace DamageMeter
{
	public class Overlay : MonoBehaviour
	{
		private const float Width = 330f;

		private GameObject canvasGo;

		private GameObject panel;

		private GameObject tab;

		private TextMeshProUGUI spellsLabel;

		private static UnityAction hideAct;

		private static UnityAction showAct;

		private static UnityAction spellsAct;

		private RectTransform panelRt;

		private RectTransform textRt;

		private TextMeshProUGUI text;

		private float nextRefresh;

		private float nextErrorLog;

		private string lastText = "";

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

		private static readonly Dictionary<ulong, string> playerNames = new Dictionary<ulong, string>();

		private static readonly Dictionary<ulong, Color> playerColors = new Dictionary<ulong, Color>();

		private static float nextNameScan;

		private static PauseMenuManager pauseMenu;

		private static float nextPauseLookup;

		private const float HeaderHeight = 22f;

		public Overlay(IntPtr ptr)
			: base(ptr)
		{
		}

		private static Color PlayerColor(ulong id, Color fallback)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if (!playerColors.TryGetValue(id, out var value))
			{
				return fallback;
			}
			return value;
		}

		private void Update()
		{
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0312: Expected O, but got Unknown
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (Pressed(Plugin.ToggleKey.Value))
				{
					Plugin.Visible.Value = !Plugin.Visible.Value;
				}
				if (Pressed(Plugin.DetailKey.Value))
				{
					Plugin.Detailed.Value = !Plugin.Detailed.Value;
				}
				if (Pressed(Plugin.ResetKey.Value))
				{
					Tracker.Reset();
				}
				if (Time.unscaledTime < nextRefresh)
				{
					return;
				}
				nextRefresh = Time.unscaledTime + 0.25f;
				Tracker.HostTick();
				bool flag = Plugin.Enabled.Value && (Tracker.Playing || (!Tracker.InRun && Tracker.HaveData && Plugin.KeepAfterRun.Value));
				if (flag && !Plugin.ShowWhenSolo.Value && IsSolo())
				{
					flag = false;
				}
				if (flag && PauseMenuOpen())
				{
					flag = false;
				}
				bool flag2 = flag && Plugin.Visible.Value;
				bool flag3 = flag && !Plugin.Visible.Value && Plugin.ShowTab.Value;
				if (!flag2 && !flag3)
				{
					if ((Object)(object)panel != (Object)null && !((Il2CppObjectBase)panel).WasCollected && panel.activeSelf)
					{
						panel.SetActive(false);
					}
					if ((Object)(object)tab != (Object)null && !((Il2CppObjectBase)tab).WasCollected && tab.activeSelf)
					{
						tab.SetActive(false);
					}
				}
				else
				{
					if (!Build())
					{
						return;
					}
					Place();
					if (tab.activeSelf != flag3)
					{
						tab.SetActive(flag3);
					}
					if (!flag2)
					{
						if (panel.activeSelf)
						{
							panel.SetActive(false);
						}
						return;
					}
					((TMP_Text)spellsLabel).text = (Plugin.Detailed.Value ? "Spells: on" : "Spells: off");
					string text = Compose();
					if (text != lastText)
					{
						lastText = text;
						((TMP_Text)this.text).text = text;
						float num = 0f;
						try
						{
							num = ((TMP_Text)this.text).GetPreferredValues(text, 310f, 0f).y;
						}
						catch
						{
						}
						if (num <= 0f)
						{
							num = (float)text.Split('\n').Length * 18f;
						}
						panelRt.sizeDelta = new Vector2(330f, num + 16f + 22f);
						textRt.sizeDelta = new Vector2(310f, num + 4f);
						textRt.anchoredPosition = new Vector2(0f, -11f);
					}
					if (!panel.activeSelf)
					{
						panel.SetActive(true);
					}
				}
			}
			catch (Exception ex)
			{
				if (!(Time.unscaledTime < nextErrorLog))
				{
					nextErrorLog = Time.unscaledTime + 10f;
					ManualLogSource log = Plugin.Log;
					bool flag4 = default(bool);
					BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(9, 1, ref flag4);
					if (flag4)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Overlay: ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
					}
					log.LogError(val);
				}
			}
		}

		private static bool PauseMenuOpen()
		{
			try
			{
				if (pauseMenu == null || ((Il2CppObjectBase)pauseMenu).WasCollected || (Object)(object)pauseMenu == (Object)null)
				{
					if (Time.unscaledTime < nextPauseLookup)
					{
						return false;
					}
					nextPauseLookup = Time.unscaledTime + 2f;
					pauseMenu = Object.FindObjectOfType<PauseMenuManager>();
					if ((Object)(object)pauseMenu == (Object)null)
					{
						return false;
					}
				}
				GameObject pauseMenuPanel = pauseMenu.pauseMenuPanel;
				return (Object)(object)pauseMenuPanel != (Object)null && pauseMenuPanel.activeInHierarchy;
			}
			catch
			{
				return false;
			}
		}

		private static bool IsSolo()
		{
			try
			{
				NetworkManager singleton = NetworkManager.Singleton;
				return (Object)(object)singleton == (Object)null || !singleton.IsListening || (singleton.IsServer && Tracker.ClientCount(singleton) <= 1);
			}
			catch
			{
				return true;
			}
		}

		private static bool Pressed(string keyName)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			Keyboard current = Keyboard.current;
			if (current == null || string.IsNullOrEmpty(keyName))
			{
				return false;
			}
			if (!Enum.TryParse<Key>(keyName, ignoreCase: true, out Key result) || (int)result == 0)
			{
				return false;
			}
			KeyControl val = current[result];
			if (val != null)
			{
				return ((ButtonControl)val).wasPressedThisFrame;
			}
			return false;
		}

		private bool Build()
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Expected O, but got Unknown
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Expected O, but got Unknown
			//IL_027c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_031a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0344: Unknown result type (might be due to invalid IL or missing references)
			//IL_0353: 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_038b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0395: Expected O, but got Unknown
			//IL_03c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0423: Unknown result type (might be due to invalid IL or missing references)
			//IL_044b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)panel != (Object)null && !((Il2CppObjectBase)panel).WasCollected && (Object)(object)panel != (Object)null)
			{
				return true;
			}
			TMP_FontAsset val = null;
			try
			{
				TextMeshProUGUI val2 = Object.FindObjectOfType<TextMeshProUGUI>();
				if ((Object)(object)val2 != (Object)null)
				{
					val = ((TMP_Text)val2).font;
				}
				if ((Object)(object)val == (Object)null)
				{
					val = TMP_Settings.defaultFontAsset;
				}
			}
			catch
			{
			}
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			canvasGo = new GameObject("DamageMeter_Canvas");
			Object.DontDestroyOnLoad((Object)(object)canvasGo);
			Canvas obj2 = canvasGo.AddComponent<Canvas>();
			obj2.renderMode = (RenderMode)0;
			obj2.sortingOrder = 400;
			CanvasScaler obj3 = canvasGo.AddComponent<CanvasScaler>();
			obj3.uiScaleMode = (ScaleMode)1;
			obj3.referenceResolution = new Vector2(1920f, 1080f);
			obj3.matchWidthOrHeight = 0.5f;
			canvasGo.AddComponent<GraphicRaycaster>();
			if (hideAct == null)
			{
				hideAct = DelegateSupport.ConvertDelegate<UnityAction>((Delegate)(Action)delegate
				{
					Plugin.Visible.Value = false;
				});
			}
			if (showAct == null)
			{
				showAct = DelegateSupport.ConvertDelegate<UnityAction>((Delegate)(Action)delegate
				{
					Plugin.Visible.Value = true;
				});
			}
			if (spellsAct == null)
			{
				spellsAct = DelegateSupport.ConvertDelegate<UnityAction>((Delegate)(Action)delegate
				{
					Plugin.Detailed.Value = !Plugin.Detailed.Value;
				});
			}
			panel = new GameObject("Panel");
			panelRt = panel.AddComponent<RectTransform>();
			panel.transform.SetParent(canvasGo.transform, false);
			Image obj4 = panel.AddComponent<Image>();
			((Graphic)obj4).color = new Color(0.06f, 0.04f, 0.12f, Mathf.Clamp01(Plugin.BackgroundOpacity.Value));
			((Graphic)obj4).raycastTarget = false;
			GameObject val3 = new GameObject("Text");
			textRt = val3.AddComponent<RectTransform>();
			val3.transform.SetParent(panel.transform, false);
			text = val3.AddComponent<TextMeshProUGUI>();
			((TMP_Text)text).font = val;
			((TMP_Text)text).fontSize = 15f;
			((TMP_Text)text).alignment = (TextAlignmentOptions)257;
			((TMP_Text)text).textWrappingMode = (TextWrappingModes)0;
			((TMP_Text)text).overflowMode = (TextOverflowModes)0;
			((TMP_Text)text).richText = true;
			((Graphic)text).raycastTarget = false;
			((Graphic)text).color = Color.white;
			RectTransform obj5 = textRt;
			RectTransform obj6 = textRt;
			RectTransform obj7 = textRt;
			Vector2 val4 = default(Vector2);
			((Vector2)(ref val4))..ctor(0.5f, 0.5f);
			obj7.pivot = val4;
			Vector2 anchorMin = (obj6.anchorMax = val4);
			obj5.anchorMin = anchorMin;
			textRt.anchoredPosition = Vector2.zero;
			spellsLabel = MakeButton(panel.transform, val, "Spells: on", new Vector2(-40f, -4f), new Vector2(92f, 20f), spellsAct, new Color(0.3f, 0.22f, 0.5f, 0.9f));
			((TMP_Text)MakeButton(panel.transform, val, "Hide", new Vector2(-6f, -4f), new Vector2(30f, 20f), hideAct, new Color(0.5f, 0.2f, 0.25f, 0.9f))).text = "X";
			tab = new GameObject("Tab");
			RectTransform val6 = tab.AddComponent<RectTransform>();
			tab.transform.SetParent(canvasGo.transform, false);
			val6.sizeDelta = new Vector2(110f, 26f);
			Image val7 = tab.AddComponent<Image>();
			((Graphic)val7).color = new Color(0.06f, 0.04f, 0.12f, 0.85f);
			Button obj8 = tab.AddComponent<Button>();
			((Selectable)obj8).targetGraphic = (Graphic)(object)val7;
			((UnityEvent)obj8.onClick).AddListener(showAct);
			TextMeshProUGUI obj9 = new GameObject("Label").AddComponent<TextMeshProUGUI>();
			((Transform)((TMP_Text)obj9).rectTransform).SetParent(tab.transform, false);
			((TMP_Text)obj9).rectTransform.sizeDelta = val6.sizeDelta;
			((TMP_Text)obj9).font = val;
			((TMP_Text)obj9).fontSize = 14f;
			((TMP_Text)obj9).alignment = (TextAlignmentOptions)514;
			((Graphic)obj9).raycastTarget = false;
			((TMP_Text)obj9).text = "<b>DAMAGE</b>  show";
			tab.SetActive(false);
			lastText = "";
			return true;
		}

		private static TextMeshProUGUI MakeButton(Transform parent, TMP_FontAsset font, string label, Vector2 pos, Vector2 size, UnityAction act, Color color)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0032: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: 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)
			GameObject val = new GameObject("Button");
			RectTransform obj = val.AddComponent<RectTransform>();
			val.transform.SetParent(parent, false);
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(1f, 1f);
			obj.pivot = val2;
			Vector2 anchorMin = (obj.anchorMax = val2);
			obj.anchorMin = anchorMin;
			obj.anchoredPosition = pos;
			obj.sizeDelta = size;
			Image val4 = val.AddComponent<Image>();
			((Graphic)val4).color = color;
			Button obj2 = val.AddComponent<Button>();
			((Selectable)obj2).targetGraphic = (Graphic)(object)val4;
			((UnityEvent)obj2.onClick).AddListener(act);
			TextMeshProUGUI obj3 = new GameObject("Label").AddComponent<TextMeshProUGUI>();
			((Transform)((TMP_Text)obj3).rectTransform).SetParent(val.transform, false);
			((TMP_Text)obj3).rectTransform.sizeDelta = size;
			((TMP_Text)obj3).font = font;
			((TMP_Text)obj3).fontSize = 12f;
			((TMP_Text)obj3).alignment = (TextAlignmentOptions)514;
			((Graphic)obj3).raycastTarget = false;
			((TMP_Text)obj3).text = label;
			return obj3;
		}

		private void Place()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Clamp(Plugin.Scale.Value, 0.5f, 2.5f);
			((Transform)panelRt).localScale = new Vector3(num, num, 1f);
			Vector2 val = (Vector2)(Plugin.Anchor.Value switch
			{
				"TopLeft" => new Vector2(0f, 1f), 
				"TopRight" => new Vector2(1f, 1f), 
				"Right" => new Vector2(1f, 0.5f), 
				"BottomLeft" => new Vector2(0f, 0f), 
				"BottomRight" => new Vector2(1f, 0f), 
				_ => new Vector2(0f, 0.5f), 
			});
			RectTransform obj = panelRt;
			RectTransform obj2 = panelRt;
			Vector2 val2 = (panelRt.pivot = val);
			Vector2 anchorMin = (obj2.anchorMax = val2);
			obj.anchorMin = anchorMin;
			float num2 = ((val.x < 0.5f) ? Plugin.OffsetX.Value : (0f - Plugin.OffsetX.Value));
			float num3 = ((val.y > 0.5f) ? (0f - Plugin.OffsetY.Value) : ((val.y < 0.5f) ? Plugin.OffsetY.Value : Plugin.OffsetY.Value));
			panelRt.anchoredPosition = new Vector2(num2, num3);
			RectTransform component = tab.GetComponent<RectTransform>();
			((Transform)component).localScale = ((Transform)panelRt).localScale;
			val2 = (component.pivot = val);
			anchorMin = (component.anchorMax = val2);
			component.anchorMin = anchorMin;
			component.anchoredPosition = new Vector2(num2, num3);
		}

		private string Compose()
		{
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			List<Row> rows = Tracker.Rows;
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("<b>DAMAGE</b><size=80%><color=#B8B0D0>  ");
			stringBuilder.Append(TimeText((Tracker.GameRunSeconds > 0f) ? Tracker.GameRunSeconds : Tracker.RunSeconds)).Append("</color></size>");
			stringBuilder.Append("<pos=50%><size=80%><color=#B8B0D0>DPS<pos=70%>TOTAL<pos=89%>%</color></size>");
			if (rows.Count == 0)
			{
				bool flag = false;
				try
				{
					NetworkManager singleton = NetworkManager.Singleton;
					flag = (Object)(object)singleton != (Object)null && singleton.IsListening && !singleton.IsServer;
				}
				catch
				{
				}
				stringBuilder.Append("\n<size=85%><color=#B8B0D0>");
				stringBuilder.Append((flag && Time.unscaledTime - Tracker.RunStartedUnscaled > 15f) ? "No numbers from the host yet. The host needs DamageMeter too." : "No damage yet.");
				stringBuilder.Append("</color></size>");
				return stringBuilder.ToString();
			}
			double num = 0.0;
			foreach (Row item in rows)
			{
				num += item.Total;
			}
			bool value = Plugin.Detailed.Value;
			int num2 = Mathf.Clamp(Plugin.MaxSpellsPerPlayer.Value, 1, 20);
			foreach (Row item2 in rows)
			{
				string value2 = ColorUtility.ToHtmlStringRGB(Brighten(PlayerColor(item2.Id, item2.Color)));
				stringBuilder.Append('\n');
				stringBuilder.Append("<color=#").Append(value2).Append('>')
					.Append(Trim(PlayerName(item2.Id), 16))
					.Append("</color>");
				stringBuilder.Append("<pos=50%>").Append(Short(item2.Dps));
				stringBuilder.Append("<pos=70%>").Append(Short(item2.Total));
				stringBuilder.Append("<pos=89%>").Append((num > 0.0) ? Math.Round(100.0 * item2.Total / num).ToString(CultureInfo.InvariantCulture) : "0");
				if (!value)
				{
					continue;
				}
				int num3 = 0;
				double num4 = 0.0;
				foreach (KeyValuePair<int, double> source in item2.Sources)
				{
					if (num3 >= num2)
					{
						num4 += source.Value;
						continue;
					}
					num3++;
					stringBuilder.Append("\n<size=82%><color=#D8D2EA>   ").Append(Trim(SourceName(source.Key), 20)).Append("</color>");
					stringBuilder.Append("<pos=70%>").Append(Short(source.Value));
					stringBuilder.Append("<pos=89%>").Append((item2.Total > 0.0) ? Math.Round(100.0 * source.Value / item2.Total).ToString(CultureInfo.InvariantCulture) : "0");
					stringBuilder.Append("</size>");
				}
				if (num4 > 0.0)
				{
					stringBuilder.Append("\n<size=82%><color=#B8B0D0>   other<pos=70%>").Append(Short(num4)).Append("</color></size>");
				}
			}
			return stringBuilder.ToString();
		}

		private static Color Brighten(Color c)
		{
			//IL_0000: 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)
			float num = default(float);
			float num2 = default(float);
			float num3 = default(float);
			Color.RGBToHSV(c, ref num, ref num2, ref num3);
			return Color.HSVToRGB(num, Mathf.Min(num2, 0.75f), Mathf.Max(num3, 0.85f));
		}

		private static string Trim(string s, int max)
		{
			if (s.Length > max)
			{
				return s.Substring(0, max - 1) + "…";
			}
			return s;
		}

		private static string TimeText(float seconds)
		{
			int num = Mathf.Max(0, Mathf.RoundToInt(seconds));
			return $"{num / 60}:{num % 60:00}";
		}

		internal static string Short(double v)
		{
			CultureInfo invariantCulture = CultureInfo.InvariantCulture;
			if (v < 1000.0)
			{
				return Math.Round(v).ToString(invariantCulture);
			}
			if (v < 10000.0)
			{
				return (v / 1000.0).ToString("0.0", invariantCulture) + "k";
			}
			if (v < 1000000.0)
			{
				return Math.Round(v / 1000.0).ToString(invariantCulture) + "k";
			}
			if (v < 10000000.0)
			{
				return (v / 1000000.0).ToString("0.00", invariantCulture) + "M";
			}
			if (v < 1000000000.0)
			{
				return (v / 1000000.0).ToString("0.0", invariantCulture) + "M";
			}
			return (v / 1000000000.0).ToString("0.00", invariantCulture) + "B";
		}

		private static string PlayerName(ulong id)
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: 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)
			if (Time.unscaledTime >= nextNameScan || !playerNames.ContainsKey(id))
			{
				nextNameScan = Time.unscaledTime + 5f;
				try
				{
					foreach (GameplayPlayerIdentity item in Object.FindObjectsOfType<GameplayPlayerIdentity>())
					{
						if ((Object)(object)item == (Object)null || !((NetworkBehaviour)item).IsSpawned)
						{
							continue;
						}
						string value = null;
						try
						{
							value = item.GetDisplayName();
						}
						catch
						{
						}
						if (!string.IsNullOrWhiteSpace(value))
						{
							playerNames[((NetworkBehaviour)item).OwnerClientId] = value;
						}
						try
						{
							Color playerColor = item.PlayerColor;
							if (playerColor.a > 0.01f)
							{
								playerColors[((NetworkBehaviour)item).OwnerClientId] = playerColor;
							}
						}
						catch
						{
						}
					}
				}
				catch
				{
				}
			}
			if (!playerNames.TryGetValue(id, out var value2))
			{
				return $"Player {id + 1}";
			}
			return value2;
		}

		private static string SourceName(int key)
		{
			return key switch
			{
				-1 => "Infused tornado", 
				-2 => "Explosions", 
				-3 => "Other", 
				_ => SpellName(key), 
			};
		}

		private static string SpellName(int spell)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			string text;
			try
			{
				text = ((object)(SpellType)spell/*cast due to .constrained prefix*/).ToString();
			}
			catch
			{
				text = spell.ToString(CultureInfo.InvariantCulture);
			}
			string text2 = "SpellName_" + text;
			if (nameCache.TryGetValue(text2, out var value))
			{
				return value;
			}
			string text3 = null;
			try
			{
				LocalizedStringDatabase stringDatabase = LocalizationSettings.StringDatabase;
				if (stringDatabase != null)
				{
					text3 = stringDatabase.GetLocalizedString(TableEntryReference.op_Implicit(text2), (Locale)null, (FallbackBehavior)0, (Il2CppReferenceArray<Object>)null);
				}
			}
			catch
			{
			}
			if (!string.IsNullOrWhiteSpace(text3) && text3 != text2 && !text3.Contains("No translation found"))
			{
				nameCache[text2] = text3;
				return text3;
			}
			return Pretty(text);
		}

		private static string Pretty(string id)
		{
			if (id == "Smg")
			{
				return "SMG";
			}
			StringBuilder stringBuilder = new StringBuilder();
			for (int i = 0; i < id.Length; i++)
			{
				if (i > 0 && char.IsUpper(id[i]) && !char.IsUpper(id[i - 1]))
				{
					stringBuilder.Append(' ');
				}
				stringBuilder.Append(id[i]);
			}
			return stringBuilder.ToString();
		}
	}
	[BepInPlugin("girthy_mods.DamageMeter", "DamageMeter", "1.1.1")]
	public class Plugin : BasePlugin
	{
		public const string Guid = "girthy_mods.DamageMeter";

		public const string Name = "DamageMeter";

		public const string Version = "1.1.1";

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<bool> Visible;

		internal static ConfigEntry<bool> ShowTab;

		internal static ConfigEntry<bool> Detailed;

		internal static ConfigEntry<bool> ShowWhenSolo;

		internal static ConfigEntry<bool> KeepAfterRun;

		internal static ConfigEntry<int> DpsWindowSeconds;

		internal static ConfigEntry<int> MaxSpellsPerPlayer;

		internal static ConfigEntry<string> ToggleKey;

		internal static ConfigEntry<string> DetailKey;

		internal static ConfigEntry<string> ResetKey;

		internal static ConfigEntry<string> Anchor;

		internal static ConfigEntry<float> OffsetX;

		internal static ConfigEntry<float> OffsetY;

		internal static ConfigEntry<float> Scale;

		internal static ConfigEntry<float> BackgroundOpacity;

		public override void Load()
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Expected O, but got Unknown
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Expected O, but got Unknown
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Expected O, but got Unknown
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Expected O, but got Unknown
			//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f6: Expected O, but got Unknown
			Log = ((BasePlugin)this).Log;
			Enabled = ((BasePlugin)this).Config.Bind<bool>("General", "Enabled", true, "Count damage and show the meter.");
			DpsWindowSeconds = ((BasePlugin)this).Config.Bind<int>("General", "DpsWindowSeconds", 10, new ConfigDescription("DPS is the damage of the last this-many seconds (game time, so shops and pauses don't count).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 60), Array.Empty<object>()));
			Visible = ((BasePlugin)this).Config.Bind<bool>("Display", "Visible", true, "Show the meter (the toggle key flips this).");
			ShowTab = ((BasePlugin)this).Config.Bind<bool>("Display", "ShowTabWhenHidden", true, "When the meter is hidden, leave a small DAMAGE tab you can click to bring it back.");
			Detailed = ((BasePlugin)this).Config.Bind<bool>("Display", "ShowSpells", true, "Show each player's damage per spell (the detail key flips this).");
			ShowWhenSolo = ((BasePlugin)this).Config.Bind<bool>("Display", "ShowWhenSolo", true, "Show the meter in single player too.");
			KeepAfterRun = ((BasePlugin)this).Config.Bind<bool>("Display", "KeepAfterRun", true, "Keep showing the last run's numbers after it ends, until the next run starts.");
			MaxSpellsPerPlayer = ((BasePlugin)this).Config.Bind<int>("Display", "MaxSpellsPerPlayer", 8, new ConfigDescription("Spell lines per player in the detailed view; the rest are summed as \"other\".", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20), Array.Empty<object>()));
			Anchor = ((BasePlugin)this).Config.Bind<string>("Display", "Position", "Left", new ConfigDescription("Screen edge or corner for the meter.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[6] { "Left", "Right", "TopLeft", "TopRight", "BottomLeft", "BottomRight" }), Array.Empty<object>()));
			OffsetX = ((BasePlugin)this).Config.Bind<float>("Display", "OffsetX", 20f, "Distance from the left/right edge (at 1080p).");
			OffsetY = ((BasePlugin)this).Config.Bind<float>("Display", "OffsetY", 60f, "Distance from the top/bottom edge, or up from the middle for Left/Right (at 1080p).");
			Scale = ((BasePlugin)this).Config.Bind<float>("Display", "Scale", 1f, new ConfigDescription("Size of the meter.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2.5f), Array.Empty<object>()));
			BackgroundOpacity = ((BasePlugin)this).Config.Bind<float>("Display", "BackgroundOpacity", 0.7f, new ConfigDescription("0 = no background.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			ToggleKey = ((BasePlugin)this).Config.Bind<string>("Keys", "ToggleKey", "F3", "Show or hide the meter (Unity Input System key name).");
			DetailKey = ((BasePlugin)this).Config.Bind<string>("Keys", "SpellsKey", "F4", "Switch the per-spell lines on or off.");
			ResetKey = ((BasePlugin)this).Config.Bind<string>("Keys", "ResetKey", "", "Optional key to reset the numbers mid-run (host). Empty = no key.");
			new Harmony("girthy_mods.DamageMeter").PatchAll(typeof(Tracker));
			((BasePlugin)this).AddComponent<Overlay>();
			ManualLogSource log = Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(8, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("DamageMeter");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("1.1.1");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ready.");
			}
			log.LogInfo(val);
		}
	}
	internal sealed class Row
	{
		public ulong Id;

		public Color Color = Color.white;

		public double Total;

		public double Dps;

		public readonly List<KeyValuePair<int, double>> Sources = new List<KeyValuePair<int, double>>();
	}
	internal static class Sources
	{
		internal const int InfusedTornado = -1;

		internal const int Explosions = -2;

		internal const int Other = -3;
	}
	[HarmonyPatch]
	internal static class Tracker
	{
		private sealed class Acc
		{
			public double Total;

			public readonly float[] Buckets = new float[64];

			public readonly int[] BucketSecond = new int[64];

			public readonly Dictionary<int, double> BySource = new Dictionary<int, double>();

			public Color Color = Color.white;

			public bool HasColor;
		}

		private enum Kind : byte
		{
			None,
			Player,
			Spell,
			Explosion,
			Tornado
		}

		private const string MessageName = "girthy_mods.DamageMeter.Snapshot";

		private static readonly Dictionary<ulong, Acc> acc = new Dictionary<ulong, Acc>();

		private static float runStart = -1f;

		private static float nextSend;

		internal static List<Row> Rows = new List<Row>();

		internal static float RunSeconds;

		internal static bool HaveData;

		internal static bool InRun;

		internal static float RunStartedUnscaled;

		private static HandleNamedMessageDelegate handler;

		private static RunManager run;

		private static readonly Dictionary<IntPtr, Kind> kinds = new Dictionary<IntPtr, Kind>();

		private static int offClientId = -1;

		private static int offSpell = -1;

		private static int offOwner = -1;

		private static int offTornado = -1;

		private static float nextErrorLog;

		internal static bool Playing
		{
			get
			{
				if (!InRun)
				{
					return false;
				}
				if (HaveData)
				{
					return true;
				}
				try
				{
					if (run == null || ((Il2CppObjectBase)run).WasCollected || (Object)(object)run == (Object)null)
					{
						run = Object.FindObjectOfType<RunManager>();
					}
					return (Object)(object)run != (Object)null && (run.runHasStarted || run.currentRunTimeInSeconds > 0f);
				}
				catch
				{
					return false;
				}
			}
		}

		internal static float GameRunSeconds
		{
			get
			{
				try
				{
					if (run != null && !((Il2CppObjectBase)run).WasCollected && (Object)(object)run != (Object)null)
					{
						return run.currentRunTimeInSeconds;
					}
				}
				catch
				{
				}
				return 0f;
			}
		}

		[HarmonyPatch(typeof(RunManager), "OnNetworkSpawn")]
		[HarmonyPostfix]
		private static void RunSpawned()
		{
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Expected O, but got Unknown
			acc.Clear();
			Rows = new List<Row>();
			HaveData = false;
			InRun = true;
			runStart = Time.time;
			RunSeconds = 0f;
			RunStartedUnscaled = Time.unscaledTime;
			try
			{
				NetworkManager singleton = NetworkManager.Singleton;
				if ((Object)(object)singleton != (Object)null && !singleton.IsServer && singleton.CustomMessagingManager != null)
				{
					if (handler == null)
					{
						handler = DelegateSupport.ConvertDelegate<HandleNamedMessageDelegate>((Delegate)new Action<ulong, FastBufferReader>(OnSnapshot));
					}
					singleton.CustomMessagingManager.RegisterNamedMessageHandler("girthy_mods.DamageMeter.Snapshot", handler);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(8, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Listen: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				log.LogError(val);
			}
		}

		[HarmonyPatch(typeof(RunManager), "OnDestroy")]
		[HarmonyPostfix]
		private static void RunDestroyed()
		{
			InRun = false;
			run = null;
		}

		[HarmonyPatch(typeof(RunManager), "StartRunOnServerRpc")]
		[HarmonyPrefix]
		private static void StartRun_Prefix(RunManager __instance)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			try
			{
				if ((int)((NetworkBehaviour)__instance).__rpc_exec_stage == 1)
				{
					Reset();
					InRun = true;
					RunStartedUnscaled = Time.unscaledTime;
				}
			}
			catch
			{
			}
		}

		[HarmonyPatch(typeof(EnemyHealthContainer), "RecordDamageDealtToEnemy")]
		[HarmonyPostfix]
		private unsafe static void Record_Postfix(float amount, DamageInfo damageSource)
		{
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Expected O, but got Unknown
			try
			{
				if (!Plugin.Enabled.Value || amount <= 0f || float.IsNaN(amount) || float.IsInfinity(amount) || damageSource == null)
				{
					return;
				}
				IntPtr pointer = ((Il2CppObjectBase)damageSource).Pointer;
				if (pointer == IntPtr.Zero)
				{
					return;
				}
				IntPtr intPtr = IL2CPP.il2cpp_object_get_class(pointer);
				if (!kinds.TryGetValue(intPtr, out var value))
				{
					value = Classify(intPtr);
					kinds[intPtr] = value;
				}
				if (value != Kind.None)
				{
					byte* ptr = (byte*)(void*)pointer;
					ulong key;
					int key2;
					switch (value)
					{
					default:
						return;
					case Kind.Spell:
						key = *(ulong*)(ptr + offClientId);
						key2 = *(int*)(ptr + offSpell);
						break;
					case Kind.Player:
						key = *(ulong*)(ptr + offClientId);
						key2 = -3;
						break;
					case Kind.Explosion:
						key = *(ulong*)(ptr + offOwner);
						key2 = -2;
						break;
					case Kind.Tornado:
						key = *(ulong*)(ptr + offTornado);
						key2 = -1;
						break;
					}
					if (!acc.TryGetValue(key, out var value2))
					{
						value2 = new Acc();
						acc[key] = value2;
					}
					value2.Total += amount;
					value2.BySource.TryGetValue(key2, out var value3);
					value2.BySource[key2] = value3 + (double)amount;
					int num = Mathf.FloorToInt(Time.time);
					int num2 = num & 0x3F;
					if (value2.BucketSecond[num2] != num)
					{
						value2.BucketSecond[num2] = num;
						value2.Buckets[num2] = 0f;
					}
					value2.Buckets[num2] += amount;
				}
			}
			catch (Exception ex)
			{
				if (!(Time.unscaledTime < nextErrorLog))
				{
					nextErrorLog = Time.unscaledTime + 10f;
					ManualLogSource log = Plugin.Log;
					bool flag = default(bool);
					BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(17, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Counting damage: ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
					}
					log.LogError(val);
				}
			}
		}

		private static Kind Classify(IntPtr klass)
		{
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Expected O, but got Unknown
			try
			{
				if (Is(klass, Il2CppClassPointerStore<PlayerSpellDamageInfo>.NativeClassPtr))
				{
					offClientId = ((offClientId >= 0) ? offClientId : Offset(klass, "<OwnerClientId>k__BackingField"));
					offSpell = ((offSpell >= 0) ? offSpell : Offset(klass, "<Spell>k__BackingField"));
					return (offClientId > 0 && offSpell > 0) ? Kind.Spell : Kind.None;
				}
				if (Is(klass, Il2CppClassPointerStore<PlayerDamageInfo>.NativeClassPtr))
				{
					offClientId = ((offClientId >= 0) ? offClientId : Offset(klass, "<OwnerClientId>k__BackingField"));
					return (offClientId > 0) ? Kind.Player : Kind.None;
				}
				if (Is(klass, Il2CppClassPointerStore<PlayerExplosionDamageInfo>.NativeClassPtr))
				{
					offOwner = ((offOwner >= 0) ? offOwner : Offset(klass, "<OwnerClientId>k__BackingField"));
					return (offOwner > 0) ? Kind.Explosion : Kind.None;
				}
				if (Is(klass, Il2CppClassPointerStore<InfusedTornadoDamageInfo>.NativeClassPtr))
				{
					offTornado = ((offTornado >= 0) ? offTornado : Offset(klass, "InfusedByPlayerId"));
					return (offTornado > 0) ? Kind.Tornado : Kind.None;
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(19, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Damage type check: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				log.LogError(val);
			}
			return Kind.None;
		}

		private static bool Is(IntPtr klass, IntPtr target)
		{
			if (target != IntPtr.Zero)
			{
				if (!(klass == target))
				{
					return IL2CPP.il2cpp_class_is_subclass_of(klass, target, false);
				}
				return true;
			}
			return false;
		}

		private static int Offset(IntPtr klass, string field)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			IntPtr intPtr = klass;
			while (intPtr != IntPtr.Zero)
			{
				IntPtr intPtr2 = IL2CPP.il2cpp_class_get_field_from_name(intPtr, field);
				if (intPtr2 != IntPtr.Zero)
				{
					return (int)IL2CPP.il2cpp_field_get_offset(intPtr2);
				}
				intPtr = IL2CPP.il2cpp_class_get_parent(intPtr);
			}
			ManualLogSource log = Plugin.Log;
			bool flag = default(bool);
			BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(55, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Field ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(field);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" not found; that kind of damage won't be counted.");
			}
			log.LogWarning(val);
			return -1;
		}

		internal static void HostTick()
		{
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Expected O, but got Unknown
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			if (!((Object)(object)singleton != (Object)null) || !singleton.IsListening || !singleton.IsServer || !InRun)
			{
				return;
			}
			float time = Time.time;
			RunSeconds = Mathf.Max(0f, time - runStart);
			int num = Mathf.FloorToInt(time);
			int num2 = Mathf.Clamp(Plugin.DpsWindowSeconds.Value, 1, 60);
			float num3 = Mathf.Clamp(time - runStart, 0.5f, (float)num2);
			List<Row> list = new List<Row>();
			foreach (KeyValuePair<ulong, Acc> item in acc)
			{
				Acc value = item.Value;
				double num4 = 0.0;
				for (int i = 0; i < 64; i++)
				{
					if (value.BucketSecond[i] > num - num2 && value.BucketSecond[i] <= num)
					{
						num4 += (double)value.Buckets[i];
					}
				}
				Row row = new Row
				{
					Id = item.Key,
					Color = value.Color,
					Total = value.Total,
					Dps = num4 / (double)num3
				};
				foreach (KeyValuePair<int, double> item2 in value.BySource)
				{
					row.Sources.Add(new KeyValuePair<int, double>(item2.Key, item2.Value));
				}
				row.Sources.Sort((KeyValuePair<int, double> x, KeyValuePair<int, double> y) => y.Value.CompareTo(x.Value));
				list.Add(row);
			}
			list.Sort((Row x, Row y) => y.Total.CompareTo(x.Total));
			Rows = list;
			HaveData = list.Count > 0;
			if (Time.unscaledTime < nextSend)
			{
				return;
			}
			nextSend = Time.unscaledTime + 1f;
			try
			{
				if (singleton.CustomMessagingManager == null || ClientCount(singleton) <= 1)
				{
					return;
				}
				string text = Serialize(list, RunSeconds);
				FastBufferWriter val = default(FastBufferWriter);
				((FastBufferWriter)(ref val))..ctor(text.Length * 2 + 64, (Allocator)2, -1);
				try
				{
					((FastBufferWriter)(ref val)).WriteValueSafe(text, false);
					singleton.CustomMessagingManager.SendNamedMessageToAll("girthy_mods.DamageMeter.Snapshot", val, (NetworkDelivery)4);
				}
				finally
				{
					((FastBufferWriter)(ref val)).Dispose();
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(16, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Sending damage: ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
				}
				log.LogError(val2);
			}
		}

		private static string Serialize(List<Row> rows, float runSeconds)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			CultureInfo invariantCulture = CultureInfo.InvariantCulture;
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("1|").Append(Mathf.RoundToInt(runSeconds).ToString(invariantCulture));
			foreach (Row row in rows)
			{
				stringBuilder.Append('|').Append(row.Id.ToString(invariantCulture)).Append(',')
					.Append(ColorUtility.ToHtmlStringRGB(row.Color))
					.Append(',')
					.Append(Math.Round(row.Total).ToString(invariantCulture))
					.Append(',')
					.Append(Math.Round(row.Dps).ToString(invariantCulture))
					.Append(',');
				for (int i = 0; i < row.Sources.Count; i++)
				{
					if (i > 0)
					{
						stringBuilder.Append('/');
					}
					stringBuilder.Append(row.Sources[i].Key.ToString(invariantCulture)).Append(':').Append(Math.Round(row.Sources[i].Value).ToString(invariantCulture));
				}
			}
			return stringBuilder.ToString();
		}

		private static void OnSnapshot(ulong sender, FastBufferReader reader)
		{
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Expected O, but got Unknown
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				string text = default(string);
				((FastBufferReader)(ref reader)).ReadValueSafe(ref text, false);
				CultureInfo invariantCulture = CultureInfo.InvariantCulture;
				string[] array = text.Split('|');
				if (array.Length < 2 || array[0] != "1")
				{
					return;
				}
				RunSeconds = float.Parse(array[1], invariantCulture);
				List<Row> list = new List<Row>();
				for (int i = 2; i < array.Length; i++)
				{
					string[] array2 = array[i].Split(',');
					if (array2.Length < 5)
					{
						continue;
					}
					Row row = new Row
					{
						Id = ulong.Parse(array2[0], invariantCulture),
						Total = double.Parse(array2[2], invariantCulture),
						Dps = double.Parse(array2[3], invariantCulture)
					};
					row.Color = ParseHex(array2[1]);
					if (array2[4].Length > 0)
					{
						string[] array3 = array2[4].Split('/');
						foreach (string text2 in array3)
						{
							int num = text2.IndexOf(':');
							if (num > 0)
							{
								row.Sources.Add(new KeyValuePair<int, double>(int.Parse(text2.Substring(0, num), invariantCulture), double.Parse(text2.Substring(num + 1), invariantCulture)));
							}
						}
					}
					list.Add(row);
				}
				Rows = list;
				HaveData = true;
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(25, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Reading damage snapshot: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
				}
				log.LogError(val);
			}
		}

		private static Color ParseHex(string s)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: 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_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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (s == null || s.Length < 6)
				{
					return Color.white;
				}
				return new Color(H(0), H(2), H(4), 1f);
			}
			catch
			{
				return Color.white;
			}
			float H(int i)
			{
				return (float)int.Parse(s.Substring(i, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture) / 255f;
			}
		}

		internal static int ClientCount(NetworkManager nm)
		{
			try
			{
				IReadOnlyList<ulong> connectedClientsIds = nm.ConnectedClientsIds;
				List<ulong> val = ((connectedClientsIds != null) ? ((Il2CppObjectBase)connectedClientsIds).TryCast<List<ulong>>() : null);
				if (val != null)
				{
					return val.Count;
				}
			}
			catch
			{
			}
			return 2;
		}

		internal static void Reset()
		{
			acc.Clear();
			Rows = new List<Row>();
			HaveData = false;
			runStart = Time.time;
		}
	}
}