Decompiled source of Netstat v1.0.7

Graphlib.dll

Decompiled 3 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using Graphlib.Config;
using Graphlib.Grapher;
using Graphlib.UI;
using Il2CppInterop.Runtime.Injection;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("Graphlib")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Graphlib")]
[assembly: AssemblyTitle("Graphlib")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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;
		}
	}
}
namespace Graphlib
{
	public class StatGraph : MonoBehaviour
	{
		public struct DataSource
		{
			public string Label;

			public Func<float> ValueProvider;

			public Color? Color;
		}

		private static readonly List<Color> PlotLineColors = new List<Color>
		{
			new Color(0.12f, 0.47f, 0.71f),
			new Color(1f, 0.5f, 0.05f),
			new Color(0.17f, 0.63f, 0.17f),
			new Color(0.84f, 0.15f, 0.16f),
			new Color(0.58f, 0.4f, 0.74f),
			new Color(0.55f, 0.34f, 0.29f)
		};

		private RectTransform? _rt;

		private bool _dirty;

		private DataSource[] _dataSources = Array.Empty<DataSource>();

		private readonly List<TextMeshProUGUI?> _labelTexts = new List<TextMeshProUGUI>();

		private readonly List<TextMeshProUGUI?> _valueTexts = new List<TextMeshProUGUI>();

		private TextMeshProUGUI? _graphMaxText;

		private TextMeshProUGUI? _graphMinText;

		private TextMeshProUGUI? _graphTimeText;

		private Plotter? _plot;

		private Color32 _textColor = new Color32((byte)227, (byte)227, (byte)227, (byte)227);

		private const float BlockHeight = 12f;

		private const float ElementSpacing = 4f;

		private float _sampleRate = 2f;

		private float _sampleInterval = 0.5f;

		private float _timeSinceLastSample;

		public RectTransform RT
		{
			get
			{
				if ((Object)(object)_rt == (Object)null)
				{
					_rt = ((Component)this).GetComponent<RectTransform>();
				}
				return _rt;
			}
		}

		public Plotter Plot => _plot ?? throw new NullReferenceException("StatGraph[" + ((Object)this).name + "] No plotter assigned.");

		public Vector2 Size => RT.sizeDelta;

		public Vector2 PlotSize
		{
			get
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				return Plot.PlotSize;
			}
			set
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				Plot.PlotSize = value;
			}
		}

		public Color32 TextColor
		{
			get
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				return _textColor;
			}
			set
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				_textColor = value;
				_dirty = true;
			}
		}

		public string Unit { get; set; }

		public uint Precision { get; set; } = 1u;


		public bool AbbreviateWithSIUnit { get; set; }

		public float SampleRate
		{
			get
			{
				return _sampleRate;
			}
			set
			{
				_sampleRate = value;
				_sampleInterval = 1f / _sampleRate;
			}
		}

		private float DesiredClearance => (float)_dataSources.Length * 16f;

		public StatGraph(IntPtr ptr)
			: base(ptr)
		{
			//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)
			Unit = "";
		}

		public static StatGraph Create(Transform parent, Vector2 graphSize, StatGraphConfig config)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			return Create(parent, config.Sources, config.Unit, graphSize, config.PlotMin, config.PlotMax, config.PlotAutoScale, config.PlotAutoScaleIncrement, config.ObjectName, config.AbbreviateWithSIPrefix, config.SampleRate, config.Precision);
		}

		public static StatGraph Create(Transform parent, DataSource[] sources, string unit, Vector2 plotSize, float min = 0f, float max = 1f, bool autoScale = true, float autoScaleInc = -1f, string objName = "", bool abbrValWithSI = false, float sampleRate = 2f, uint precision = 0u)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: 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_012a: 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_014a: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject((objName == "") ? ("StatGraph." + sources.Select((DataSource s) => s.Label).Aggregate((string str0, string str1) => str0 + "_" + str1)) : objName);
			RectTransform val2 = val.AddComponent<RectTransform>();
			((Transform)val2).SetParent(parent, false);
			StatGraph statGraph = val.AddComponent<StatGraph>();
			statGraph._rt = val2;
			statGraph._dataSources = sources;
			statGraph.Unit = unit;
			statGraph.AbbreviateWithSIUnit = abbrValWithSI;
			statGraph.SampleRate = sampleRate;
			statGraph.Precision = precision;
			Plotter plotter = ((Component)statGraph).gameObject.AddComponent<Plotter>();
			plotter.PlotSize = plotSize;
			plotter.AutoScale = autoScale;
			plotter.MinY = min;
			plotter.MaxY = max;
			plotter.AutoScaleIncrement = autoScaleInc;
			plotter.AfterPopulateMesh += statGraph.DrawLegendIdentifiers;
			plotter.AfterPopulateMesh += statGraph.DrawMaxTick;
			statGraph._plot = plotter;
			val2.anchorMin = new Vector2(0.5f, 0.5f);
			val2.anchorMax = new Vector2(0.5f, 0.5f);
			val2.pivot = new Vector2(1f, 0f);
			val2.anchoredPosition3D = Vector3.zero;
			statGraph.Recreate();
			if (TMPUtil.CreateTMPUGUI("GraphMax", (Transform?)(object)statGraph.RT, out TextMeshProUGUI tp))
			{
				statGraph._graphMaxText = tp;
			}
			if (TMPUtil.CreateTMPUGUI("GraphMin", (Transform?)(object)statGraph.RT, out TextMeshProUGUI tp2))
			{
				statGraph._graphMinText = tp2;
			}
			if (TMPUtil.CreateTMPUGUI("Time", (Transform?)(object)statGraph.RT, out TextMeshProUGUI tp3))
			{
				statGraph._graphTimeText = tp3;
			}
			statGraph.Reconfigure();
			return statGraph;
		}

		public void UpdateSources(DataSource[] sources)
		{
			if (sources.Length != _dataSources.Length)
			{
				_dataSources = sources;
				Recreate();
				Reconfigure();
			}
			else
			{
				_dataSources = sources;
				Reconfigure();
			}
		}

		private void Update()
		{
			if ((Object)(object)_plot == (Object)null)
			{
				Logger.Error("StatGraph[" + ((Object)this).name + "] No plotter assigned. Disabling graph.");
				((Component)this).gameObject.SetActive(false);
				return;
			}
			_timeSinceLastSample += Time.deltaTime;
			if (_timeSinceLastSample >= _sampleInterval)
			{
				for (int i = 0; i < _dataSources.Length; i++)
				{
					float value = _dataSources[i].ValueProvider();
					_plot.PushSample(value, i);
					if ((Object)(object)_valueTexts[i] != (Object)null)
					{
						string text = (AbbreviateWithSIUnit ? Util.Value2SIAbbrStr(value) : value.ToString($"F{Precision}"));
						((TMP_Text)_valueTexts[i]).text = text + Unit;
					}
				}
				_timeSinceLastSample = 0f;
			}
			TextMeshProUGUI? graphMinText = _graphMinText;
			if (graphMinText != null)
			{
				((TMP_Text)graphMinText).SetText(AbbreviateWithSIUnit ? Util.Value2SIAbbrStr(_plot.MinY) : _plot.MinY.ToString($"F{Precision}"), true);
			}
			TextMeshProUGUI? graphMaxText = _graphMaxText;
			if (graphMaxText != null)
			{
				((TMP_Text)graphMaxText).SetText(AbbreviateWithSIUnit ? Util.Value2SIAbbrStr(_plot.DisplayMaxY) : _plot.DisplayMaxY.ToString($"F{Precision}"), true);
			}
			TextMeshProUGUI? graphTimeText = _graphTimeText;
			if (graphTimeText != null)
			{
				((TMP_Text)graphTimeText).SetText($"{(float)_plot.Capacity * _sampleInterval:F0}s", true);
			}
			if (_dirty)
			{
				Reconfigure();
			}
		}

		private void Recreate()
		{
			foreach (TextMeshProUGUI labelText in _labelTexts)
			{
				if ((Object)(object)labelText != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)labelText).gameObject);
				}
			}
			foreach (TextMeshProUGUI valueText in _valueTexts)
			{
				if ((Object)(object)valueText != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)valueText).gameObject);
				}
			}
			_labelTexts.Clear();
			_valueTexts.Clear();
			for (int i = 0; i < _dataSources.Length; i++)
			{
				if (TMPUtil.CreateTMPUGUI($"Label.C{i}", (Transform?)(object)RT, out TextMeshProUGUI tp))
				{
					((TMP_Text)tp).text = _dataSources[i].Label;
					_labelTexts.Add(tp);
				}
				if (TMPUtil.CreateTMPUGUI($"Value.C{i}", (Transform?)(object)RT, out TextMeshProUGUI tp2))
				{
					_valueTexts.Add(tp2);
				}
			}
		}

		private void Reconfigure()
		{
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0414: Unknown result type (might be due to invalid IL or missing references)
			//IL_041c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0424: Unknown result type (might be due to invalid IL or missing references)
			//IL_0432: Unknown result type (might be due to invalid IL or missing references)
			//IL_0441: Unknown result type (might be due to invalid IL or missing references)
			//IL_0455: Unknown result type (might be due to invalid IL or missing references)
			//IL_045a: Unknown result type (might be due to invalid IL or missing references)
			//IL_045c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0461: Unknown result type (might be due to invalid IL or missing references)
			//IL_0465: Unknown result type (might be due to invalid IL or missing references)
			//IL_046f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0474: Unknown result type (might be due to invalid IL or missing references)
			//IL_0476: Unknown result type (might be due to invalid IL or missing references)
			//IL_047d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0268: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			//IL_02af: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0315: Unknown result type (might be due to invalid IL or missing references)
			//IL_031c: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0545: Unknown result type (might be due to invalid IL or missing references)
			//IL_054d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0555: Unknown result type (might be due to invalid IL or missing references)
			//IL_0563: Unknown result type (might be due to invalid IL or missing references)
			//IL_0572: Unknown result type (might be due to invalid IL or missing references)
			//IL_0595: Unknown result type (might be due to invalid IL or missing references)
			//IL_059c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0605: Unknown result type (might be due to invalid IL or missing references)
			//IL_0616: Unknown result type (might be due to invalid IL or missing references)
			//IL_0664: Unknown result type (might be due to invalid IL or missing references)
			//IL_066c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0674: Unknown result type (might be due to invalid IL or missing references)
			//IL_0682: Unknown result type (might be due to invalid IL or missing references)
			//IL_0691: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_06b3: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_plot == (Object)null)
			{
				Logger.Error("StatGraph[" + ((Object)this).name + "] No plotter assigned.");
				return;
			}
			_plot.SetClearance(DesiredClearance);
			_plot.AllocateChannels(_dataSources.Length);
			for (int i = 0; i < _dataSources.Length; i++)
			{
				Color c = (Color)(((??)_dataSources[i].Color) ?? PlotLineColors[i % PlotLineColors.Count]);
				_plot.SetColor(Plotter.PlotComponent.Line, c, i);
			}
			string fmt = "StatGraph[" + ((Object)this).name + "]->{0} UI reconfigure failed, is null.";
			Vector2 val2 = default(Vector2);
			Vector2 v = default(Vector2);
			Vector2 val4 = default(Vector2);
			Vector2 v2 = default(Vector2);
			for (int j = 0; j < _dataSources.Length; j++)
			{
				TextMeshProUGUI val = _labelTexts[j];
				if ((Object)(object)val != (Object)null)
				{
					((TMP_Text)val).SetText(_dataSources[j].Label, true);
					((Vector2)(ref val2))..ctor(0f, 1f);
					((TMP_Text)val).alignment = (TextAlignmentOptions)513;
					((Graphic)val).color = Color.white;
					((TMP_Text)val).faceColor = TextColor;
					((TMP_Text)val).autoSizeTextContainer = false;
					((TMP_Text)val).enableAutoSizing = true;
					((TMP_Text)val).fontSizeMax = 20f;
					((TMP_Text)val).fontSizeMin = 16f;
					RectTransform rectTransform = ((TMP_Text)val).rectTransform;
					rectTransform.anchorMax = val2;
					rectTransform.anchorMin = val2;
					rectTransform.pivot = new Vector2(0f, 0.5f);
					rectTransform.sizeDelta = new Vector2(_plot.Size.x - 12f - 4f, 12f);
					((Vector2)(ref v))..ctor(16f, 0f - ((float)j * 16f + 4f + 6f));
					rectTransform.anchoredPosition3D = v.Extend();
				}
				else
				{
					Logger.Warn(fmt, $"C{j}:Label");
				}
				TextMeshProUGUI val3 = _valueTexts[j];
				if ((Object)(object)val3 != (Object)null)
				{
					((Vector2)(ref val4))..ctor(1f, 1f);
					((TMP_Text)val3).alignment = (TextAlignmentOptions)516;
					((Graphic)val3).color = Color.white;
					((TMP_Text)val3).faceColor = TextColor;
					((TMP_Text)val3).autoSizeTextContainer = false;
					((TMP_Text)val3).enableAutoSizing = true;
					((TMP_Text)val3).fontSizeMax = 20f;
					((TMP_Text)val3).fontSizeMin = 16f;
					RectTransform rectTransform2 = ((TMP_Text)val3).rectTransform;
					rectTransform2.anchorMax = val4;
					rectTransform2.anchorMin = val4;
					rectTransform2.pivot = new Vector2(1f, 0.5f);
					rectTransform2.sizeDelta = new Vector2(_plot.Size.x, 12f);
					((Vector2)(ref v2))..ctor(-4f, 0f - ((float)j * 16f + 4f + 6f));
					rectTransform2.anchoredPosition3D = v2.Extend();
				}
				else
				{
					Logger.Warn(fmt, $"C{j}:Value");
				}
			}
			if ((Object)(object)_graphTimeText != (Object)null)
			{
				Vector2 val5 = default(Vector2);
				((Vector2)(ref val5))..ctor(0f, 0f);
				((TMP_Text)_graphTimeText).alignment = (TextAlignmentOptions)1025;
				((Graphic)_graphTimeText).color = Color.white;
				((TMP_Text)_graphTimeText).faceColor = TextColor;
				((TMP_Text)_graphTimeText).autoSizeTextContainer = false;
				((TMP_Text)_graphTimeText).enableAutoSizing = true;
				((TMP_Text)_graphTimeText).fontSizeMax = 20f;
				((TMP_Text)_graphTimeText).fontSizeMin = 16f;
				RectTransform rectTransform3 = ((TMP_Text)_graphTimeText).rectTransform;
				rectTransform3.anchorMax = val5;
				rectTransform3.anchorMin = val5;
				rectTransform3.pivot = val5;
				rectTransform3.sizeDelta = new Vector2(_plot.Size.x, 12f);
				Vector2 val6 = new Vector2(0.5f, 0.5f) - val5;
				Vector2 v3 = ((Vector2)(ref val6)).normalized * 4f;
				rectTransform3.anchoredPosition3D = v3.Extend();
			}
			else
			{
				Logger.Warn(fmt, "GraphTime");
			}
			if ((Object)(object)_graphMaxText != (Object)null)
			{
				Vector2 val7 = default(Vector2);
				((Vector2)(ref val7))..ctor(0f, 1f);
				Vector2 pivot = default(Vector2);
				((Vector2)(ref pivot))..ctor(1f, 1f);
				((TMP_Text)_graphMaxText).alignment = (TextAlignmentOptions)516;
				((Graphic)_graphMaxText).color = Color.white;
				((TMP_Text)_graphMaxText).faceColor = TextColor;
				((TMP_Text)_graphMaxText).autoSizeTextContainer = false;
				((TMP_Text)_graphMaxText).enableAutoSizing = true;
				((TMP_Text)_graphMaxText).fontSizeMax = 20f;
				((TMP_Text)_graphMaxText).fontSizeMin = 16f;
				RectTransform rectTransform4 = ((TMP_Text)_graphMaxText).rectTransform;
				rectTransform4.anchorMax = val7;
				rectTransform4.anchorMin = val7;
				rectTransform4.pivot = pivot;
				rectTransform4.sizeDelta = new Vector2(_plot.Size.x, 12f);
				Vector2 v4 = default(Vector2);
				((Vector2)(ref v4))..ctor(-4f, 0f - (DesiredClearance - 6f));
				rectTransform4.anchoredPosition3D = v4.Extend();
			}
			else
			{
				Logger.Warn(fmt, "GraphMax");
			}
			if ((Object)(object)_graphMinText != (Object)null)
			{
				Vector2 val8 = default(Vector2);
				((Vector2)(ref val8))..ctor(0f, 0f);
				Vector2 pivot2 = default(Vector2);
				((Vector2)(ref pivot2))..ctor(1f, 0f);
				((TMP_Text)_graphMinText).alignment = (TextAlignmentOptions)1028;
				((Graphic)_graphMinText).color = Color.white;
				((TMP_Text)_graphMinText).faceColor = TextColor;
				((TMP_Text)_graphMinText).autoSizeTextContainer = false;
				((TMP_Text)_graphMinText).enableAutoSizing = true;
				((TMP_Text)_graphMinText).fontSizeMax = 20f;
				((TMP_Text)_graphMinText).fontSizeMin = 16f;
				RectTransform rectTransform5 = ((TMP_Text)_graphMinText).rectTransform;
				rectTransform5.anchorMax = val8;
				rectTransform5.anchorMin = val8;
				rectTransform5.pivot = pivot2;
				rectTransform5.sizeDelta = new Vector2(_plot.Size.x, 12f);
				Vector2 v5 = default(Vector2);
				((Vector2)(ref v5))..ctor(-4f, 0f);
				rectTransform5.anchoredPosition3D = v5.Extend();
			}
			else
			{
				Logger.Warn(fmt, "GraphMin");
			}
			_dirty = false;
		}

		private void DrawLegendIdentifiers(Graphic graphic, VertexHelper vh)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: 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)
			Rect pixelAdjustedRect = graphic.GetPixelAdjustedRect();
			Vector2 val = default(Vector2);
			Rect r = default(Rect);
			for (int i = 0; i < _dataSources.Length; i++)
			{
				Color c = (Color)(((??)_dataSources[i].Color) ?? PlotLineColors[i % PlotLineColors.Count]);
				float num = Mathf.Floor(6f);
				float num2 = (12f - num) / 2f;
				((Vector2)(ref val))..ctor(((Rect)(ref pixelAdjustedRect)).xMin + 4f + num2, ((Rect)(ref pixelAdjustedRect)).yMax - (float)(i + 1) * 16f + num2);
				((Rect)(ref r))..ctor(val, new Vector2(num, num));
				VhUtil.AddRect(vh, r, c);
			}
		}

		private void DrawMaxTick(Graphic graphic, VertexHelper vh)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			Rect pixelAdjustedRect = graphic.GetPixelAdjustedRect();
			Rect r = default(Rect);
			((Rect)(ref r))..ctor(((Rect)(ref pixelAdjustedRect)).xMin, ((Rect)(ref pixelAdjustedRect)).yMax - DesiredClearance, 4f, 1f);
			VhUtil.AddRect(vh, r, (Color)(((??)_plot?.BorderColor) ?? new Color(1f, 1f, 1f, 0.35f)));
		}
	}
	public struct StatGraphConfig
	{
		public StatGraph.DataSource[] Sources;

		public string Unit;

		public float PlotMin;

		public float PlotMax;

		public bool PlotAutoScale;

		public float PlotAutoScaleIncrement;

		public string ObjectName;

		public uint Precision;

		public float SampleRate;

		public bool AbbreviateWithSIPrefix;

		public StatGraphConfig()
		{
			Sources = new StatGraph.DataSource[0];
			Unit = "";
			PlotMin = 0f;
			PlotMax = 1f;
			PlotAutoScale = true;
			PlotAutoScaleIncrement = -1f;
			ObjectName = "";
			Precision = 0u;
			SampleRate = 2f;
			AbbreviateWithSIPrefix = false;
		}
	}
	internal static class Logger
	{
		private static ManualLogSource _mLogSource;

		public static bool Ready => _mLogSource != null;

		public static void Setup()
		{
			_mLogSource = Logger.CreateLogSource("io.takina.gtfo.Graphlib");
		}

		public static void SetupFromInit(ManualLogSource logSource)
		{
			_mLogSource = logSource;
		}

		private static string Format(object data)
		{
			return data.ToString();
		}

		public static void Debug(object msg)
		{
			if (ConfigMgr.Debug)
			{
				_mLogSource.LogInfo((object)(" [DEBUG] " + Format(msg)));
			}
		}

		public static void Debug(string fmt, params object[] args)
		{
			if (ConfigMgr.Debug)
			{
				_mLogSource.LogInfo((object)("[DEBUG] " + Format(string.Format(fmt, args))));
			}
			else
			{
				_mLogSource.LogDebug((object)Format(string.Format(fmt, args)));
			}
		}

		public static void Info(object msg)
		{
			_mLogSource.LogInfo((object)Format(msg));
		}

		public static void Info(string fmt, params object[] args)
		{
			_mLogSource.LogInfo((object)Format(string.Format(fmt, args)));
		}

		public static void Warn(object msg)
		{
			_mLogSource.LogWarning((object)Format(msg));
		}

		public static void Warn(string fmt, params object[] args)
		{
			_mLogSource.LogWarning((object)Format(string.Format(fmt, args)));
		}

		public static void Error(object msg)
		{
			_mLogSource.LogError((object)Format(msg));
		}

		public static void Error(string fmt, params object[] args)
		{
			_mLogSource.LogError((object)Format(string.Format(fmt, args)));
		}

		public static void Fatal(object msg)
		{
			_mLogSource.LogFatal((object)Format(msg));
		}

		public static void Fatal(string fmt, params object[] args)
		{
			_mLogSource.LogFatal((object)Format(string.Format(fmt, args)));
		}
	}
	[BepInPlugin("io.takina.gtfo.Graphlib", "Graphlib", "1.0.0")]
	public class Plugin : BasePlugin
	{
		public const string NAME = "Graphlib";

		public const string GUID = "io.takina.gtfo.Graphlib";

		public const string VERSION = "1.0.0";

		public override void Load()
		{
			Logger.Setup();
			Logger.Info("Graphlib [io.takina.gtfo.Graphlib @ 1.0.0]");
			ConfigMgr.Init();
			ClassInjector.RegisterTypeInIl2Cpp<Plotter>();
			ClassInjector.RegisterTypeInIl2Cpp<StatGraph>();
		}
	}
	public static class Util
	{
		private static readonly string[] _siAbbrs = new string[7] { "", "K", "M", "G", "T", "P", "E" };

		public static Vector3 Extend(this Vector2 v, float z = 0f)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(v.x, v.y, z);
		}

		public static int TrueMod(int n, int m)
		{
			return (n % m + m) % m;
		}

		public static string Value2SIAbbrStr(float value, bool includeOneDecimalWhenValueLessThan10 = true)
		{
			bool flag = value < 1000f;
			int num = 0;
			while (value >= 1000f && num < _siAbbrs.Length - 1)
			{
				value /= 1000f;
				num++;
			}
			string text = ((!flag && includeOneDecimalWhenValueLessThan10 && value < 10f) ? "0.0" : "0");
			return value.ToString(text) + _siAbbrs[num];
		}
	}
}
namespace Graphlib.UI
{
	public static class TMPUtil
	{
		public static bool CreateTMP(string name, Transform? parent, [NotNullWhen(true)] out TextMeshPro? tp)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			WatermarkGuiLayer watermarkLayer = GuiManager.WatermarkLayer;
			object obj;
			if (watermarkLayer == null)
			{
				obj = null;
			}
			else
			{
				PUI_Watermark watermark = watermarkLayer.m_watermark;
				obj = ((watermark != null) ? watermark.m_fpsText : null);
			}
			TextMeshPro val = (TextMeshPro)obj;
			if ((Object)(object)parent == (Object)null || (Object)(object)val == (Object)null)
			{
				tp = null;
				return false;
			}
			tp = Object.Instantiate<TextMeshPro>(val, parent, false);
			((Object)tp).name = name;
			((TMP_Text)tp).rectTransform.anchorMax = new Vector2(0.5f, 0.5f);
			((TMP_Text)tp).rectTransform.anchorMin = new Vector2(0.5f, 0.5f);
			((TMP_Text)tp).rectTransform.pivot = new Vector2(1f, 0f);
			((TMP_Text)tp).rectTransform.anchoredPosition3D = new Vector3(0f, 2f, 0f);
			((Transform)((TMP_Text)tp).rectTransform).localRotation = Quaternion.Euler(0f, 0f, 0f);
			((TMP_Text)tp).enableAutoSizing = false;
			((TMP_Text)tp).overflowMode = (TextOverflowModes)0;
			((TMP_Text)tp).alignment = (TextAlignmentOptions)513;
			((TMP_Text)tp).fontSize = 16f;
			return true;
		}

		public static bool CreateTMPUGUI(string name, Transform? parent, [NotNullWhen(true)] out TextMeshProUGUI? tp)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: 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)
			WatermarkGuiLayer watermarkLayer = GuiManager.WatermarkLayer;
			object obj;
			if (watermarkLayer == null)
			{
				obj = null;
			}
			else
			{
				PUI_Watermark watermark = watermarkLayer.m_watermark;
				obj = ((watermark != null) ? watermark.m_fpsText : null);
			}
			TextMeshPro val = (TextMeshPro)obj;
			GameObject val2 = new GameObject();
			val2.transform.SetParent(parent, false);
			tp = val2.AddComponent<TextMeshProUGUI>();
			((Object)tp).name = name;
			((TMP_Text)tp).rectTransform.anchorMax = new Vector2(0.5f, 0.5f);
			((TMP_Text)tp).rectTransform.anchorMin = new Vector2(0.5f, 0.5f);
			((TMP_Text)tp).rectTransform.pivot = new Vector2(1f, 0f);
			((TMP_Text)tp).rectTransform.anchoredPosition3D = new Vector3(0f, 2f, 0f);
			((Transform)((TMP_Text)tp).rectTransform).localRotation = Quaternion.Euler(0f, 0f, 0f);
			((TMP_Text)tp).enableAutoSizing = false;
			((TMP_Text)tp).overflowMode = (TextOverflowModes)0;
			((TMP_Text)tp).alignment = (TextAlignmentOptions)513;
			((TMP_Text)tp).fontSize = 16f;
			if ((Object)(object)val != (Object)null)
			{
				((TMP_Text)tp).font = ((TMP_Text)val).font;
				((TMP_Text)tp).fontSharedMaterial = ((TMP_Text)val).fontSharedMaterial;
			}
			return true;
		}
	}
	public static class VhUtil
	{
		public static void AddRect(VertexHelper vh, Rect r, Color c)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: 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_0015: 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_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: 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_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			int currentVertCount = vh.currentVertCount;
			UIVertex simpleVert = UIVertex.simpleVert;
			simpleVert.color = Color32.op_Implicit(c);
			simpleVert.position = Vector2.op_Implicit(new Vector2(((Rect)(ref r)).xMin, ((Rect)(ref r)).yMin));
			vh.AddVert(simpleVert);
			simpleVert.position = Vector2.op_Implicit(new Vector2(((Rect)(ref r)).xMin, ((Rect)(ref r)).yMax));
			vh.AddVert(simpleVert);
			simpleVert.position = Vector2.op_Implicit(new Vector2(((Rect)(ref r)).xMax, ((Rect)(ref r)).yMax));
			vh.AddVert(simpleVert);
			simpleVert.position = Vector2.op_Implicit(new Vector2(((Rect)(ref r)).xMax, ((Rect)(ref r)).yMin));
			vh.AddVert(simpleVert);
			vh.AddTriangle(currentVertCount, currentVertCount + 1, currentVertCount + 2);
			vh.AddTriangle(currentVertCount + 2, currentVertCount + 3, currentVertCount);
		}

		public static void AddBorder(VertexHelper vh, Rect r, float thickness, Color c)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: 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)
			AddRect(vh, Rect.MinMaxRect(((Rect)(ref r)).xMin, ((Rect)(ref r)).yMax - thickness, ((Rect)(ref r)).xMax, ((Rect)(ref r)).yMax), c);
			AddRect(vh, Rect.MinMaxRect(((Rect)(ref r)).xMin, ((Rect)(ref r)).yMin, ((Rect)(ref r)).xMax, ((Rect)(ref r)).yMin + thickness), c);
			AddRect(vh, Rect.MinMaxRect(((Rect)(ref r)).xMin, ((Rect)(ref r)).yMin, ((Rect)(ref r)).xMin + thickness, ((Rect)(ref r)).yMax), c);
			AddRect(vh, Rect.MinMaxRect(((Rect)(ref r)).xMax - thickness, ((Rect)(ref r)).yMin, ((Rect)(ref r)).xMax, ((Rect)(ref r)).yMax), c);
		}

		public static void AddThickSegment(VertexHelper vh, Vector2 a, Vector2 b, float halfThickness, Color c)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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_0052: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = b - a;
			float magnitude = ((Vector2)(ref val)).magnitude;
			if (!(magnitude < 0.0001f))
			{
				val /= magnitude;
				Vector2 val2 = new Vector2(0f - val.y, val.x) * halfThickness;
				Vector2 val3 = a - val2;
				Vector2 val4 = a + val2;
				Vector2 val5 = b + val2;
				Vector2 val6 = b - val2;
				int currentVertCount = vh.currentVertCount;
				UIVertex simpleVert = UIVertex.simpleVert;
				simpleVert.color = Color32.op_Implicit(c);
				simpleVert.position = Vector2.op_Implicit(val3);
				vh.AddVert(simpleVert);
				simpleVert.position = Vector2.op_Implicit(val4);
				vh.AddVert(simpleVert);
				simpleVert.position = Vector2.op_Implicit(val5);
				vh.AddVert(simpleVert);
				simpleVert.position = Vector2.op_Implicit(val6);
				vh.AddVert(simpleVert);
				vh.AddTriangle(currentVertCount, currentVertCount + 1, currentVertCount + 2);
				vh.AddTriangle(currentVertCount + 2, currentVertCount + 3, currentVertCount);
			}
		}
	}
}
namespace Graphlib.Grapher
{
	public sealed class Plotter : Graphic
	{
		[Flags]
		public enum PlotComponent
		{
			None = 0,
			Line = 1,
			Fill = 2,
			Background = 4,
			Border = 8,
			PerChannel = 3,
			Standard = 0xD,
			StandardFill = 0xF,
			StandardNoBg = 9
		}

		private struct ChannelStyle
		{
			public bool DrawLine;

			public float LineThickness;

			public Color LineColor;

			public bool DrawFill;

			public float FillChunkWidth;

			public Color FillColor;

			public ChannelStyle()
			{
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				//IL_002c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0058: Unknown result type (might be due to invalid IL or missing references)
				//IL_005d: Unknown result type (might be due to invalid IL or missing references)
				DrawLine = true;
				LineThickness = 2f;
				LineColor = new Color(0.85f, 0.85f, 0.85f, 1f);
				DrawFill = false;
				FillChunkWidth = 3f;
				FillColor = new Color(1f, 1f, 1f, 0.25f);
			}
		}

		private Vector2 _plotSize = new Vector2(200f, 100f);

		private float _minY;

		private float _maxY = 1f;

		private bool _autoScale;

		private float _autoscaleInc = -1f;

		private float _autoScaleLerp = 0.35f;

		private bool _useLogScale;

		private int _lineResolution = 1;

		private float _clearance;

		private bool _dirty;

		private ChannelStyle[] _styles = new ChannelStyle[0];

		private int _capacity = 120;

		private float _dispMax;

		private int _channelCount = 1;

		private float[,] _samples = new float[0, 0];

		private int[] _heads = new int[0];

		private int[] _counts = new int[0];

		private float[] _maxObserved = new float[0];

		public int Capacity => _capacity;

		public Vector2 Size => ((Graphic)this).rectTransform.sizeDelta;

		public Vector2 PlotSize
		{
			get
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				return _plotSize;
			}
			set
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: 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)
				_plotSize = value;
				((Graphic)this).rectTransform.sizeDelta = new Vector2(_plotSize.x, _plotSize.y + _clearance);
				MarkDirty();
			}
		}

		public float Clearance => _clearance;

		public float MinY
		{
			get
			{
				return _minY;
			}
			set
			{
				_minY = value;
				MarkDirty();
			}
		}

		public float MaxY
		{
			get
			{
				return _maxY;
			}
			set
			{
				_maxY = value;
				_dispMax = value;
				MarkDirty();
			}
		}

		public float DisplayMaxY => _dispMax;

		public bool LogScale
		{
			get
			{
				return _useLogScale;
			}
			set
			{
				_useLogScale = value;
				MarkDirty();
			}
		}

		public bool AutoScale
		{
			get
			{
				return _autoScale;
			}
			set
			{
				_autoScale = value;
				MarkDirty();
			}
		}

		public float AutoScaleIncrement
		{
			get
			{
				return _autoscaleInc;
			}
			set
			{
				_autoscaleInc = value;
				MarkDirty();
			}
		}

		public float AutoScaleLerpFactor
		{
			get
			{
				return _autoScaleLerp;
			}
			set
			{
				_autoScaleLerp = Mathf.Clamp01(value);
				MarkDirty();
			}
		}

		public bool DrawBackground { get; set; } = true;


		public Color BgColor { get; private set; } = new Color(0f, 0f, 0f, 0.35f);


		public bool DrawBorder { get; set; } = true;


		public float BorderThickness { get; set; } = 1f;


		public Color BorderColor { get; private set; } = new Color(1f, 1f, 1f, 0.35f);


		public event Action<Graphic, VertexHelper>? AfterPopulateMesh;

		public override void Awake()
		{
			EnsureBuffer();
			_dispMax = _maxY;
		}

		public void AllocateChannels(int channelCount)
		{
			_channelCount = Mathf.Max(1, channelCount);
			EnsureBuffer();
		}

		public void SetCapacity(int cap)
		{
			_capacity = Mathf.Max(8, cap);
			EnsureBuffer();
			MarkDirty();
		}

		public void SetStyle(PlotComponent style, int channel = 0, bool affectBackgroundAndBorder = false)
		{
			_styles[channel].DrawLine = style.HasFlag(PlotComponent.Line);
			_styles[channel].DrawFill = style.HasFlag(PlotComponent.Fill);
			if (affectBackgroundAndBorder)
			{
				DrawBackground = style.HasFlag(PlotComponent.Background);
				DrawBorder = style.HasFlag(PlotComponent.Border);
			}
			MarkDirty();
		}

		public void SetColor(PlotComponent comp, Color c, int channel = 0)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			if (comp.HasFlag(PlotComponent.Line))
			{
				_styles[channel].LineColor = c;
			}
			if (comp.HasFlag(PlotComponent.Fill))
			{
				_styles[channel].FillColor = c;
			}
			if (comp.HasFlag(PlotComponent.Background))
			{
				BgColor = c;
			}
			if (comp.HasFlag(PlotComponent.Border))
			{
				BorderColor = c;
			}
			MarkDirty();
		}

		public void SetThickness(PlotComponent comp, float thickness, int channel = 0, bool affectBackgroundAndBorder = false)
		{
			if (comp.HasFlag(PlotComponent.Line))
			{
				_styles[channel].LineThickness = Mathf.Max(1f, thickness);
			}
			if (comp.HasFlag(PlotComponent.Fill))
			{
				_styles[channel].FillChunkWidth = Mathf.Max(0f, thickness);
			}
			if (affectBackgroundAndBorder && comp.HasFlag(PlotComponent.Border))
			{
				BorderThickness = Mathf.Max(0f, thickness);
			}
			MarkDirty();
		}

		public void SetClearance(float clearance)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			_clearance = clearance;
			((Graphic)this).rectTransform.sizeDelta = new Vector2(_plotSize.x, _plotSize.y + _clearance);
			MarkDirty();
		}

		public void PushSample(float value, int channel = 0)
		{
			EnsureBuffer();
			_heads[channel] = (_heads[channel] + 1) % _capacity;
			_samples[channel, _heads[channel]] = value;
			if (_counts[channel] < _capacity)
			{
				_counts[channel]++;
			}
			if (_autoScale)
			{
				float num = _minY + 0.0001f;
				for (int i = 0; i < _counts[channel]; i++)
				{
					float sampleReverse = GetSampleReverse(i, channel);
					if (sampleReverse > num)
					{
						num = sampleReverse;
					}
				}
				_maxObserved[channel] = Mathf.Max(num, _minY + 0.0001f);
				float num2 = _minY + 0.0001f;
				for (int j = 0; j < _channelCount; j++)
				{
					if (_maxObserved[j] > num2)
					{
						num2 = _maxObserved[j];
					}
				}
				float num3 = num2;
				if (_autoscaleInc > 0f)
				{
					num3 = Mathf.Ceil((num2 - _minY) / _autoscaleInc) * _autoscaleInc + _minY;
				}
				_dispMax = Mathf.Lerp(_dispMax, num3, _autoScaleLerp);
				_dispMax = Mathf.Max(Mathf.Max(_dispMax, _minY + 0.0001f), _maxY);
			}
			MarkDirty();
		}

		public void Clear()
		{
			Array.Clear(_samples);
			for (int i = 0; i < _channelCount; i++)
			{
				_heads[i] = _capacity - 1;
				_counts[i] = 0;
				_maxObserved[i] = _minY;
			}
			MarkDirty();
		}

		private void EnsureBuffer()
		{
			if (_styles.Length != _channelCount || _samples.Length != _capacity * _channelCount)
			{
				_styles = new ChannelStyle[_channelCount];
				for (int i = 0; i < _styles.Length; i++)
				{
					_styles[i] = new ChannelStyle();
				}
				_samples = new float[_channelCount, _capacity];
				_heads = new int[_channelCount];
				Array.Fill(_heads, _capacity - 1);
				_counts = new int[_channelCount];
				_maxObserved = new float[_channelCount];
				_dirty = true;
			}
		}

		private void MarkDirty()
		{
			if (!_dirty)
			{
				_dirty = true;
				((Graphic)this).SetVerticesDirty();
			}
		}

		private float GetSample(int i, int channel = 0)
		{
			int n = _heads[channel] + 1 + i;
			n = Util.TrueMod(n, _capacity);
			if (!_useLogScale)
			{
				return _samples[channel, n];
			}
			return Mathf.Log(_samples[channel, n]);
		}

		private float GetSampleReverse(int i, int channel = 0)
		{
			int n = _heads[channel] - i;
			n = Util.TrueMod(n, _capacity);
			if (!_useLogScale)
			{
				return _samples[channel, n];
			}
			return Mathf.Log(_samples[channel, n]);
		}

		public override void OnPopulateMesh(VertexHelper vh)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: 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_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			vh.Clear();
			_dirty = false;
			Rect pixelAdjustedRect = ((Graphic)this).GetPixelAdjustedRect();
			if (((Rect)(ref pixelAdjustedRect)).width <= 1f || ((Rect)(ref pixelAdjustedRect)).height <= 1f)
			{
				return;
			}
			if (DrawBackground)
			{
				VhUtil.AddRect(vh, pixelAdjustedRect, BgColor);
			}
			Vector2 val2 = default(Vector2);
			for (int i = 0; i < _channelCount; i++)
			{
				ChannelStyle channelStyle = _styles[i];
				if (_counts[i] <= 1)
				{
					continue;
				}
				float num = (_autoScale ? _dispMax : _maxY);
				num = Mathf.Max(num, _minY + 0.0001f);
				float xMin = ((Rect)(ref pixelAdjustedRect)).xMin;
				float xMax = ((Rect)(ref pixelAdjustedRect)).xMax;
				float yMin = ((Rect)(ref pixelAdjustedRect)).yMin;
				float num2 = ((Rect)(ref pixelAdjustedRect)).yMax - _clearance;
				int capacity = _capacity;
				float num3 = (xMax - xMin) / (float)(capacity - 1);
				float num4 = 1f / (num - _minY);
				if (channelStyle.DrawFill)
				{
					float num5 = Mathf.Min(channelStyle.FillChunkWidth * 0.5f, num3 * 0.5f);
					for (int j = 0; j < capacity; j++)
					{
						float num6 = Mathf.Clamp01((GetSample(j, i) - _minY) * num4);
						float num7 = xMin + num3 * (float)j;
						float num8 = Mathf.Lerp(yMin, num2, num6);
						Rect r = Rect.MinMaxRect(num7 - num5, yMin, num7 + num5, num8);
						VhUtil.AddRect(vh, r, channelStyle.FillColor);
					}
				}
				if (!channelStyle.DrawLine)
				{
					continue;
				}
				float halfThickness = channelStyle.LineThickness * 0.5f;
				Vector2 val = default(Vector2);
				for (int k = 0; k < capacity; k++)
				{
					float num9 = Mathf.Clamp01((GetSample(k, i) - _minY) * num4);
					float num10 = xMin + num3 * (float)k;
					float num11 = Mathf.Lerp(yMin, num2, num9);
					((Vector2)(ref val2))..ctor(num10, num11);
					if (k > 0)
					{
						for (int l = 1; l <= _lineResolution; l++)
						{
							float num12 = (float)l / (float)_lineResolution;
							Vector2 b = Vector2.Lerp(val, val2, num12);
							Vector2 a = Vector2.Lerp(val, val2, (float)(l - 1) / (float)_lineResolution);
							VhUtil.AddThickSegment(vh, a, b, halfThickness, channelStyle.LineColor);
						}
					}
					val = val2;
				}
			}
			if (DrawBorder && BorderThickness > 0f)
			{
				VhUtil.AddBorder(vh, pixelAdjustedRect, BorderThickness, BorderColor);
			}
			this.AfterPopulateMesh?.Invoke((Graphic)(object)this, vh);
		}
	}
}
namespace Graphlib.Config
{
	public enum ConfigEntryRule
	{
		Min,
		Max
	}
	public class ConfigEntryExtended<T>
	{
		private Dictionary<ConfigEntryRule, T> _rules = new Dictionary<ConfigEntryRule, T>();

		private ConfigEntry<T> _entry;

		public T Value
		{
			get
			{
				return _entry.Value;
			}
			set
			{
				_entry.Value = Enforce(value);
			}
		}

		public object BoxedValue
		{
			get
			{
				return ((ConfigEntryBase)_entry).BoxedValue;
			}
			set
			{
				((ConfigEntryBase)_entry).BoxedValue = Enforce((T)value);
			}
		}

		public ConfigEntryExtended(ConfigEntry<T> entry)
		{
			_entry = entry;
		}

		public bool AddRule(ConfigEntryRule rule, T ruleValue)
		{
			if (_rules.TryAdd(rule, ruleValue))
			{
				Enforce(rule);
				return true;
			}
			return false;
		}

		private void Enforce()
		{
			T val = Enforce(_entry.Value);
			if (val != null && !val.Equals(_entry.Value))
			{
				_entry.Value = val;
			}
		}

		private T Enforce(T val)
		{
			foreach (var (configEntryRule2, val3) in _rules)
			{
				switch (configEntryRule2)
				{
				case ConfigEntryRule.Min:
					if (Comparer<T>.Default.Compare(val, val3) < 0)
					{
						val = val3;
					}
					break;
				case ConfigEntryRule.Max:
					if (Comparer<T>.Default.Compare(val, val3) > 0)
					{
						val = val3;
					}
					break;
				}
			}
			return val;
		}

		private void Enforce(ConfigEntryRule rule)
		{
			T value = _entry.Value;
			value = Enforce(value, rule);
			if (value != null && !value.Equals(_entry.Value))
			{
				_entry.Value = value;
			}
		}

		private T Enforce(T val, ConfigEntryRule rule)
		{
			if (!_rules.TryGetValue(rule, out var value))
			{
				return val;
			}
			switch (rule)
			{
			case ConfigEntryRule.Min:
				if (Comparer<T>.Default.Compare(val, value) < 0)
				{
					val = value;
				}
				break;
			case ConfigEntryRule.Max:
				if (Comparer<T>.Default.Compare(val, value) > 0)
				{
					val = value;
				}
				break;
			}
			return val;
		}

		public static implicit operator ConfigEntryExtended<T>(ConfigEntry<T> entry)
		{
			return new ConfigEntryExtended<T>(entry);
		}
	}
	internal static class ConfigMgr
	{
		private static readonly ConfigFile Conf;

		private static readonly FileSystemWatcher? ConfigWatcher;

		private static readonly ConfigEntryExtended<bool> DebugConf;

		public static bool Debug => DebugConf.Value;

		public static void Init()
		{
			Logger.Info($"debug={Debug}");
		}

		static ConfigMgr()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			string text = "Graphlib.cfg";
			string text2 = Path.Combine(Paths.ConfigPath, text);
			Logger.Info("cfgPath = " + text2);
			Conf = new ConfigFile(text2, true);
			ConfigWatcher = new FileSystemWatcher(Paths.ConfigPath, text)
			{
				NotifyFilter = NotifyFilters.LastWrite,
				EnableRaisingEvents = true
			};
			ConfigWatcher.Changed += async delegate
			{
				ConfigWatcher.EnableRaisingEvents = false;
				await Task.Delay(500);
				Logger.Debug("Reloading config...");
				Conf.Reload();
				await Task.Delay(250);
				ConfigWatcher.EnableRaisingEvents = true;
			};
			string sectionHeader = default(string);
			HeaderSp('Z', "Dev");
			DebugConf = Conf.Bind<bool>(sectionHeader, "Enable Debug Logs", false, "debug logging");
			void HeaderSp(char prefix, string header)
			{
				sectionHeader = $"({prefix}) {header}";
			}
		}
	}
}

Netstat.dll

Decompiled 3 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using Globals;
using Graphlib;
using Graphlib.UI;
using HarmonyLib;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using Netstat.Config;
using Netstat.Telemetry;
using Netstat.UI;
using Player;
using SNetwork;
using Steamworks;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("Netstat")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Netstat")]
[assembly: AssemblyTitle("Netstat")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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;
		}
	}
}
namespace Netstat
{
	public class CuteBehaviour : MonoBehaviour
	{
		public CuteBehaviour(IntPtr ptr)
			: base(ptr)
		{
		}
	}
	internal static class Logger
	{
		private static ManualLogSource _mLogSource;

		public static bool Ready => _mLogSource != null;

		public static void Setup()
		{
			_mLogSource = Logger.CreateLogSource("food.randomuser.gtfo.Netstat");
		}

		public static void SetupFromInit(ManualLogSource logSource)
		{
			_mLogSource = logSource;
		}

		private static string Format(object data)
		{
			return data.ToString();
		}

		public static void Debug(object msg)
		{
			if (ConfigMgr.Debug)
			{
				_mLogSource.LogInfo((object)(" [DEBUG] " + Format(msg)));
			}
		}

		public static void Debug(string fmt, params object[] args)
		{
			if (ConfigMgr.Debug)
			{
				_mLogSource.LogInfo((object)("[DEBUG] " + Format(string.Format(fmt, args))));
			}
			else
			{
				_mLogSource.LogDebug((object)Format(string.Format(fmt, args)));
			}
		}

		public static void Info(object msg)
		{
			_mLogSource.LogInfo((object)Format(msg));
		}

		public static void Info(string fmt, params object[] args)
		{
			_mLogSource.LogInfo((object)Format(string.Format(fmt, args)));
		}

		public static void Warn(object msg)
		{
			_mLogSource.LogWarning((object)Format(msg));
		}

		public static void Warn(string fmt, params object[] args)
		{
			_mLogSource.LogWarning((object)Format(string.Format(fmt, args)));
		}

		public static void Error(object msg)
		{
			_mLogSource.LogError((object)Format(msg));
		}

		public static void Error(string fmt, params object[] args)
		{
			_mLogSource.LogError((object)Format(string.Format(fmt, args)));
		}

		public static void Fatal(object msg)
		{
			_mLogSource.LogFatal((object)Format(msg));
		}

		public static void Fatal(string fmt, params object[] args)
		{
			_mLogSource.LogFatal((object)Format(string.Format(fmt, args)));
		}
	}
	public static class NetstatAPI
	{
		public enum PingerTypeEnum
		{
			Chat,
			Marker
		}

		public static PingerTypeEnum PingerType => ConfigMgr.PingerType;

		public static float Ping
		{
			get
			{
				if (PingerType != 0)
				{
					return MarkerPinger.Ping;
				}
				return ChatPinger.Ping;
			}
		}

		public static float RawPing
		{
			get
			{
				if (PingerType != 0)
				{
					return MarkerPinger.RawPing;
				}
				return ChatPinger.RawPing;
			}
		}

		public static int PingMs => (int)(Ping * 1000f);

		public static int RawPingMs => (int)(RawPing * 1000f);

		public static float Jitter
		{
			get
			{
				if (PingerType != 0)
				{
					return MarkerPinger.Jitter;
				}
				return ChatPinger.Jitter;
			}
		}

		public static float RawJitter
		{
			get
			{
				if (PingerType != 0)
				{
					return MarkerPinger.RawJitter;
				}
				return ChatPinger.RawJitter;
			}
		}

		public static float JitterMs => (int)(Jitter * 1000f);

		public static float RawJitterMs => (int)(RawJitter * 1000f);

		public static bool IsPingerActive
		{
			get
			{
				if (PingerType != 0)
				{
					return MarkerPinger.IsMeasuring;
				}
				return true;
			}
		}

		public static bool IsDesynced
		{
			get
			{
				if (PingerType != 0)
				{
					return MarkerPinger.IsDesynced;
				}
				return ChatPinger.IsDesynced;
			}
		}

		public static ReadOnlySpan<ChannelStats> Channels => SteamP2P.Channels;

		public static uint BytesReceived => SteamP2P.BytesReceived;

		public static uint PacketsReceived => SteamP2P.PacketsReceived;

		public static uint BytesSent => SteamP2P.BytesSent;

		public static uint PacketsSent => SteamP2P.PacketsSent;

		public static int BytesQueuedForSend => SteamP2P.BytesQueuedForSend;

		public static int PacketsQueuedForSend => SteamP2P.PacketsQueuedForSend;

		public static TickStats GetTickStat(ulong steamId)
		{
			return TickTimer.GetTickStat(steamId);
		}
	}
	[BepInPlugin("food.randomuser.gtfo.Netstat", "Netstat", "1.0.7")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BasePlugin
	{
		public const string NAME = "Netstat";

		public const string GUID = "food.randomuser.gtfo.Netstat";

		public const string VERSION = "1.0.7";

		private GameObject _netstatObj;

		public event Action? OnManagersSetup;

		public override void Load()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Expected O, but got Unknown
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Expected O, but got Unknown
			//IL_00c9: Expected O, but got Unknown
			Logger.Setup();
			Logger.Info("Netstat [food.randomuser.gtfo.Netstat @ 1.0.7]");
			Harmony val = new Harmony("food.randomuser.gtfo.Netstat");
			ConfigMgr.Init();
			ClassInjector.RegisterTypeInIl2Cpp<UIManager>();
			ClassInjector.RegisterTypeInIl2Cpp<ChatPinger>();
			ClassInjector.RegisterTypeInIl2Cpp<MarkerPinger>();
			ClassInjector.RegisterTypeInIl2Cpp<SteamP2P>();
			ClassInjector.RegisterTypeInIl2Cpp<TickTimer>();
			ClassInjector.RegisterTypeInIl2Cpp<CuteBehaviour>();
			OnManagersSetup += Initialize;
			Global.OnAllManagersSetup += Action.op_Implicit(this.OnManagersSetup);
			Logger.Info("Patching...");
			RundownManager.OnExpeditionGameplayStarted += Action.op_Implicit((Action)MarkerPinger.Start);
			ApplyPatch<MarkerPinger>(val);
			ApplyPatch<ChatPinger>(val);
			ApplyPatch<SteamP2P>(val);
			RundownManager.OnExpeditionGameplayStarted += Action.op_Implicit((Action)TickTimer.Start);
			ApplyPatch<TickTimer>(val);
			Logger.Info("Finished Patching");
		}

		private static void ApplyPatch<T>(Harmony h)
		{
			h.PatchAll(typeof(T));
		}

		private void Initialize()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			_netstatObj = new GameObject("food.randomuser.gtfo.Netstat");
			Object.DontDestroyOnLoad((Object)(object)_netstatObj);
			_netstatObj.AddComponent<ChatPinger>();
			_netstatObj.AddComponent<MarkerPinger>();
			_netstatObj.AddComponent<SteamP2P>();
			_netstatObj.AddComponent<TickTimer>();
			_netstatObj.AddComponent<UIManager>();
			_netstatObj.AddComponent<CuteBehaviour>();
		}

		public override bool Unload()
		{
			return true;
		}
	}
	public static class Util
	{
		private static readonly string[] _siAbbrs = new string[7] { "", "K", "M", "G", "T", "P", "E" };

		public static Vector3 Extend(this Vector2 v, float z = 0f)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(v.x, v.y, z);
		}

		public static int TrueMod(int n, int m)
		{
			return (n % m + m) % m;
		}

		public static string Value2SIAbbrStr(float value, bool includeOneDecimalWhenValueLessThan10 = true)
		{
			bool flag = value < 1000f;
			int num = 0;
			while (value >= 1000f && num < _siAbbrs.Length - 1)
			{
				value /= 1000f;
				num++;
			}
			string text = ((!flag && includeOneDecimalWhenValueLessThan10 && value < 10f) ? "0.0" : "0");
			return value.ToString(text) + _siAbbrs[num];
		}
	}
}
namespace Netstat.UI
{
	[Flags]
	public enum eNetstatData
	{
		Ping = 1,
		Rx = 2,
		Tx = 4,
		CTT = 8,
		STT = 0x10
	}
	[Flags]
	public enum eNetstatGraph
	{
		Ping = 1,
		RxTx = 2,
		RxChan = 4,
		TxChan = 8,
		CSTT = 0x10
	}
	public class StatConfigLib
	{
		public static readonly StatGraphConfig Ping;

		public static readonly StatGraphConfig RxTx;

		public static readonly StatGraphConfig RxChannelsShort;

		public static readonly StatGraphConfig TxChannelsShort;

		public static readonly StatGraphConfig CSTT;

		public static eNetstatGraph Str2GraphType(string key)
		{
			return key switch
			{
				"ping" => eNetstatGraph.Ping, 
				"rxtx" => eNetstatGraph.RxTx, 
				"rxchan" => eNetstatGraph.RxChan, 
				"txchan" => eNetstatGraph.TxChan, 
				"cstt" => eNetstatGraph.CSTT, 
				_ => (eNetstatGraph)0, 
			};
		}

		public static bool TryGet(string key, out StatGraphConfig conf)
		{
			return TryGet(Str2GraphType(key), out conf);
		}

		public static bool TryGet(eNetstatGraph type, out StatGraphConfig conf)
		{
			//IL_0024: 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_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			switch (type)
			{
			case eNetstatGraph.Ping:
				conf = Ping;
				break;
			case eNetstatGraph.RxTx:
				conf = RxTx;
				break;
			case eNetstatGraph.RxChan:
				conf = RxChannelsShort;
				break;
			case eNetstatGraph.TxChan:
				conf = TxChannelsShort;
				break;
			case eNetstatGraph.CSTT:
				conf = CSTT;
				break;
			default:
				conf = default(StatGraphConfig);
				return false;
			}
			return true;
		}

		static StatConfigLib()
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			StatGraphConfig val = default(StatGraphConfig);
			((StatGraphConfig)(ref val))..ctor();
			val.Sources = StatSourceLib.WPing;
			val.Unit = "ms";
			val.PlotMin = 0f;
			val.PlotMax = 500f;
			val.PlotAutoScale = true;
			val.PlotAutoScaleIncrement = 50f;
			val.AbbreviateWithSIPrefix = false;
			val.SampleRate = 2f;
			val.Precision = 0u;
			Ping = val;
			((StatGraphConfig)(ref val))..ctor();
			val.Sources = StatSourceLib.WRxTx;
			val.Unit = "B/s";
			val.PlotMin = 0f;
			val.PlotMax = 1000f;
			val.PlotAutoScale = true;
			val.PlotAutoScaleIncrement = 500f;
			val.AbbreviateWithSIPrefix = true;
			val.SampleRate = 2f;
			val.Precision = 0u;
			RxTx = val;
			((StatGraphConfig)(ref val))..ctor();
			val.Sources = StatSourceLib.WRxChannelsShort;
			val.Unit = "B/s";
			val.PlotMin = 0f;
			val.PlotMax = 1000f;
			val.PlotAutoScale = true;
			val.PlotAutoScaleIncrement = 500f;
			val.AbbreviateWithSIPrefix = true;
			val.SampleRate = 2f;
			val.Precision = 0u;
			RxChannelsShort = val;
			((StatGraphConfig)(ref val))..ctor();
			val.Sources = StatSourceLib.WTxChannelsShort;
			val.Unit = "B/s";
			val.PlotMin = 0f;
			val.PlotMax = 1000f;
			val.PlotAutoScale = true;
			val.PlotAutoScaleIncrement = 500f;
			val.AbbreviateWithSIPrefix = true;
			val.SampleRate = 2f;
			val.Precision = 0u;
			TxChannelsShort = val;
			((StatGraphConfig)(ref val))..ctor();
			val.Sources = StatSourceLib.WCSTT;
			val.Unit = "ms";
			val.PlotMin = 0f;
			val.PlotMax = 200f;
			val.PlotAutoScale = true;
			val.PlotAutoScaleIncrement = 50f;
			val.AbbreviateWithSIPrefix = false;
			val.SampleRate = 2f;
			val.Precision = 0u;
			CSTT = val;
		}
	}
	public static class StatSourceLib
	{
		public static readonly DataSource Ping = new DataSource
		{
			Label = "Ping",
			ValueProvider = () => NetstatAPI.PingMs
		};

		public static readonly DataSource Rx = new DataSource
		{
			Label = "Rx",
			ValueProvider = () => NetstatAPI.BytesReceived
		};

		public static readonly DataSource Tx = new DataSource
		{
			Label = "Tx",
			ValueProvider = () => NetstatAPI.BytesSent
		};

		public static readonly DataSource CTT = new DataSource
		{
			Label = "CTT",
			ValueProvider = () => ((Object)(object)SNet.LocalPlayer != (Object)null) ? (NetstatAPI.GetTickStat(SNet.LocalPlayer.Lookup).TickTime * 1000f) : 0f
		};

		public static readonly DataSource STT = new DataSource
		{
			Label = "STT",
			ValueProvider = () => ((Object)(object)SNet.Master != (Object)null) ? (NetstatAPI.GetTickStat(SNet.Master.Lookup).TickTime * 1000f) : 0f
		};

		public static readonly DataSource[] WPing = (DataSource[])(object)new DataSource[1]
		{
			new DataSource
			{
				Label = "Ping",
				ValueProvider = () => NetstatAPI.PingMs
			}
		};

		public static readonly DataSource[] WRxTx = (DataSource[])(object)new DataSource[2]
		{
			new DataSource
			{
				Label = "Rx",
				ValueProvider = () => NetstatAPI.BytesReceived
			},
			new DataSource
			{
				Label = "Tx",
				ValueProvider = () => NetstatAPI.BytesSent
			}
		};

		public static readonly DataSource[] WRxChannels = Array.ConvertAll((SNet_ChannelType[])Enum.GetValues(typeof(SNet_ChannelType)), delegate(SNet_ChannelType value)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			DataSource result4 = default(DataSource);
			result4.Label = "Tx " + SteamP2P.SNetChannelType2Str(value);
			result4.ValueProvider = () => NetstatAPI.Channels[(int)value].BytesSent;
			return result4;
		});

		public static readonly DataSource[] WTxChannels = Array.ConvertAll((SNet_ChannelType[])Enum.GetValues(typeof(SNet_ChannelType)), delegate(SNet_ChannelType value)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			DataSource result3 = default(DataSource);
			result3.Label = "Rx " + SteamP2P.SNetChannelType2Str(value);
			result3.ValueProvider = () => NetstatAPI.Channels[(int)value].BytesReceived;
			return result3;
		});

		public static readonly DataSource[] WRxChannelsShort = Array.ConvertAll((SNet_ChannelType[])Enum.GetValues(typeof(SNet_ChannelType)), delegate(SNet_ChannelType value)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			DataSource result2 = default(DataSource);
			result2.Label = "Tx " + SteamP2P.SNetChannelType2StrShort(value);
			result2.ValueProvider = () => NetstatAPI.Channels[(int)value].BytesSent;
			return result2;
		});

		public static readonly DataSource[] WTxChannelsShort = Array.ConvertAll((SNet_ChannelType[])Enum.GetValues(typeof(SNet_ChannelType)), delegate(SNet_ChannelType value)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			DataSource result = default(DataSource);
			result.Label = "Rx " + SteamP2P.SNetChannelType2StrShort(value);
			result.ValueProvider = () => NetstatAPI.Channels[(int)value].BytesReceived;
			return result;
		});

		public static readonly DataSource[] WCSTT = (DataSource[])(object)new DataSource[2]
		{
			new DataSource
			{
				Label = "CTT",
				ValueProvider = () => ((Object)(object)SNet.LocalPlayer != (Object)null) ? (NetstatAPI.GetTickStat(SNet.LocalPlayer.Lookup).TickTime * 1000f) : 0f
			},
			new DataSource
			{
				Label = "STT",
				ValueProvider = () => ((Object)(object)SNet.Master != (Object)null) ? (NetstatAPI.GetTickStat(SNet.Master.Lookup).TickTime * 1000f) : 0f
			}
		};
	}
	public class UIManager : MonoBehaviour
	{
		private Canvas _canvas;

		private CanvasScaler _canvasScaler;

		private const float ElementSpacing = 4f;

		private static readonly Vector2 ReferenceResolution = new Vector2(2560f, 1440f);

		private static readonly Vector2 GraphSize = new Vector2(200f, 100f);

		public readonly Vector2 Pivot = new Vector2(0.5f, 0.5f);

		private bool _dirty;

		private GameObject? _uiRoot;

		private RectTransform? _graphLayerTrans;

		private readonly Dictionary<eNetstatGraph, StatGraph> _graphDict = new Dictionary<eNetstatGraph, StatGraph>();

		private List<StatGraph> _graphStack = new List<StatGraph>();

		private TextMeshProUGUI? _detailsText;

		private readonly Vector3 _detailsBarOffset = new Vector3(-340f, -12f, 0f);

		private TextMeshPro? _detailsBar;

		public static UIManager? Instance { get; private set; }

		public Vector2 Size { get; set; } = new Vector2(GraphSize.x, 100f);


		public Vector2 Anchor => ConfigMgr.UIAnchor;

		public Vector2 AnchorOffset => ConfigMgr.UIAnchorOffset;

		public bool Active => ConfigMgr.EnableGraphs;

		public void SetDirty()
		{
			_dirty = true;
		}

		private void Awake()
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Instance != (Object)null)
			{
				Object.Destroy((Object)(object)this);
				return;
			}
			Instance = this;
			_canvas = ((Component)this).gameObject.AddComponent<Canvas>();
			_canvas.renderMode = (RenderMode)0;
			_canvas.sortingOrder = 1000;
			_canvasScaler = ((Component)this).gameObject.AddComponent<CanvasScaler>();
			_canvasScaler.uiScaleMode = (ScaleMode)1;
			_canvasScaler.referenceResolution = ReferenceResolution;
			_canvasScaler.m_MatchWidthOrHeight = 1f;
			CreateUI();
		}

		private void Update()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Invalid comparison between Unknown and I4
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Invalid comparison between Unknown and I4
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Invalid comparison between Unknown and I4
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Invalid comparison between Unknown and I4
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			if ((int)FocusStateManager.Current.m_currentState != 5 && (int)FocusStateManager.Current.m_currentState != 6 && (int)FocusStateManager.Current.m_currentState != 8 && (int)FocusStateManager.Current.m_currentState != 14 && !PlayerChatManager.InChatMode && Input.GetKeyDown(ConfigMgr.GraphToggleKey))
			{
				ConfigMgr.EnableGraphs = !ConfigMgr.EnableGraphs;
			}
			if ((Object)(object)_graphLayerTrans != (Object)null && Active != ((Component)_graphLayerTrans).gameObject.activeSelf)
			{
				((Component)_graphLayerTrans).gameObject.SetActive(Active);
			}
			if ((Object)(object)_detailsBar != (Object)null && ((UIBehaviour)_detailsBar).IsActive() != ConfigMgr.DetailsBarEnabled)
			{
				TextMeshPro? detailsBar = _detailsBar;
				if (detailsBar != null)
				{
					((Component)detailsBar).gameObject.SetActive(ConfigMgr.DetailsBarEnabled);
				}
			}
			if (_dirty)
			{
				_dirty = false;
				UpdateConfigurableValues();
				RefreshGraphStack();
			}
			UpdateTextDisplays();
		}

		private void OnDestroy()
		{
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}

		private void UpdateConfigurableValues()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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_0066: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_graphLayerTrans == (Object)null)
			{
				return;
			}
			_graphLayerTrans.anchorMin = Anchor;
			_graphLayerTrans.anchorMax = Anchor;
			_graphLayerTrans.anchoredPosition3D = AnchorOffset.Extend();
			foreach (StatGraph value in _graphDict.Values)
			{
				value.PlotSize = ConfigMgr.GraphSize;
			}
		}

		private void CreateUI()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: 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_0120: 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_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: 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_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			_uiRoot = new GameObject("food.randomuser.gtfo.Netstat.UI");
			_graphLayerTrans = _uiRoot.AddComponent<RectTransform>();
			((Transform)_graphLayerTrans).SetParent(((Component)this).gameObject.transform);
			((Transform)_graphLayerTrans).localScale = Vector3.one;
			_graphLayerTrans.anchorMin = Anchor;
			_graphLayerTrans.anchorMax = Anchor;
			_graphLayerTrans.pivot = Pivot;
			_graphLayerTrans.anchoredPosition3D = AnchorOffset.Extend();
			_uiRoot.SetActive(true);
			GenerateGraphs();
			TextMeshPro val = default(TextMeshPro);
			if (TMPUtil.CreateTMP("food.randomuser.gtfo.Netstat.UI.DetailsBar", ((Component)GuiManager.PlayerLayer.m_playerStatus).transform, ref val))
			{
				((TMP_Text)val).alignment = (TextAlignmentOptions)513;
				((TMP_Text)val).enableAutoSizing = true;
				((TMP_Text)val).fontSize = 16f;
				((TMP_Text)val).fontSizeMin = 12f;
				((TMP_Text)val).fontSizeMax = 20f;
				RectTransform rectTransform = ((TMP_Text)val).rectTransform;
				rectTransform.anchorMax = new Vector2(0.5f, 0.5f);
				rectTransform.anchorMin = new Vector2(0.5f, 0.5f);
				rectTransform.pivot = new Vector2(0f, 1f);
				rectTransform.sizeDelta = new Vector2(400f, 16f);
				rectTransform.anchoredPosition3D = _detailsBarOffset;
			}
			_detailsBar = val;
			TextMeshProUGUI val2 = default(TextMeshProUGUI);
			if (TMPUtil.CreateTMPUGUI("food.randomuser.gtfo.Netstat.UI.Details", (Transform)(object)_graphLayerTrans, ref val2))
			{
				((TMP_Text)val2).alignment = (TextAlignmentOptions)257;
				RectTransform rectTransform2 = ((TMP_Text)val2).rectTransform;
				rectTransform2.anchorMax = new Vector2(0.5f, 0.5f);
				rectTransform2.anchorMin = new Vector2(0.5f, 0.5f);
				rectTransform2.pivot = new Vector2(1f, 1f);
				rectTransform2.sizeDelta = new Vector2(Size.x, 12f);
				rectTransform2.anchoredPosition3D = new Vector3(0f, -4f, 0f);
			}
			_detailsText = val2;
		}

		public void UpdateTextDisplays()
		{
			if ((Object)(object)_detailsText != (Object)null)
			{
				string text = "";
				text += (NetstatAPI.IsDesynced ? $"<#AF0000{(uint)((Mathf.Sin(Time.time * (float)Math.PI / 2f) + 1f) * 127f):X2}>DESYNCED</color>" : "\n");
				((TMP_Text)_detailsText).SetText(text.Trim(), true);
			}
			if (!((Object)(object)_detailsBar != (Object)null))
			{
				return;
			}
			List<string> list = new List<string>();
			if (ConfigMgr.DetailsBarData.HasFlag(eNetstatData.Ping))
			{
				list.Add($"Ping {NetstatAPI.PingMs}ms");
			}
			if (ConfigMgr.DetailsBarData.HasFlag(eNetstatData.Rx))
			{
				list.Add("Rx " + Util.Value2SIAbbrStr(NetstatAPI.BytesReceived) + "B/s");
			}
			if (ConfigMgr.DetailsBarData.HasFlag(eNetstatData.Tx))
			{
				list.Add("Tx " + Util.Value2SIAbbrStr(NetstatAPI.BytesSent) + "B/s");
			}
			if (ConfigMgr.DetailsBarData.HasFlag(eNetstatData.STT))
			{
				string text2 = "?";
				if ((Object)(object)SNet.Master != (Object)null)
				{
					text2 = ((int)(NetstatAPI.GetTickStat(SNet.Master.Lookup).TickTime * 1000f)).ToString();
				}
				list.Add("STT " + text2 + "ms");
			}
			if (ConfigMgr.DetailsBarData.HasFlag(eNetstatData.CTT))
			{
				string text3 = "?";
				if ((Object)(object)SNet.LocalPlayer != (Object)null)
				{
					text3 = ((int)(NetstatAPI.GetTickStat(SNet.LocalPlayer.Lookup).TickTime * 1000f)).ToString();
				}
				list.Add("CTT " + text3 + "ms");
			}
			string text4 = string.Join(" | ", list);
			TextMeshPro? detailsBar = _detailsBar;
			if (detailsBar != null)
			{
				((TMP_Text)detailsBar).SetText(text4, true);
			}
		}

		private void GenerateGraphs()
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_graphLayerTrans == (Object)null)
			{
				return;
			}
			foreach (StatGraph item in _graphStack)
			{
				Object.Destroy((Object)(object)((Component)item).gameObject);
			}
			eNetstatGraph[] values = Enum.GetValues<eNetstatGraph>();
			foreach (eNetstatGraph eNetstatGraph2 in values)
			{
				if (StatConfigLib.TryGet(eNetstatGraph2, out var conf))
				{
					_graphDict[eNetstatGraph2] = StatGraph.Create((Transform)(object)_graphLayerTrans, ConfigMgr.GraphSize, conf);
				}
			}
			RefreshGraphStack();
		}

		private void RefreshGraphStack()
		{
			_graphStack.Clear();
			foreach (eNetstatGraph item in ConfigMgr.GraphsInOrder)
			{
				if (_graphDict.TryGetValue(item, out StatGraph value))
				{
					if (ConfigMgr.EnabledGraphs.HasFlag(item))
					{
						((Component)value).gameObject.SetActive(true);
						_graphStack.Add(value);
					}
					else
					{
						((Component)value).gameObject.SetActive(false);
					}
				}
			}
			AlignGraphsVertical();
		}

		private void AlignGraphsVertical()
		{
			//IL_0021: 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)
			float num = 0f;
			for (int i = 0; i < _graphStack.Count; i++)
			{
				_graphStack[i].RT.anchoredPosition = new Vector2(0f, num);
				num += _graphStack[i].Size.y + 4f;
			}
		}
	}
}
namespace Netstat.Telemetry
{
	internal interface IPinger
	{
		static bool IsDesynced { get; }

		static float Ping { get; }
	}
	internal struct PingInfo
	{
		public float SendTime;

		public float RecvTime;

		public uint SeqNumber;

		public bool Ackd;
	}
	[HarmonyPatch]
	internal class ChatPinger : MonoBehaviour, IPinger
	{
		private const ulong MAGIC_NUMBER = 11474180236421424882uL;

		private static uint BUFFER_SIZE = 10u;

		private static PingInfo[] _buffer = new PingInfo[BUFFER_SIZE];

		private static uint _seqNumber = 0u;

		private static float _lastPingReceived = 0f;

		private static float _ping = 0f;

		private static float _rawPing = 0f;

		private static float _jitter = 0f;

		private static float _rawJitter = 0f;

		private static bool _running = false;

		private static float _nextPingSendTime;

		public static float Ping
		{
			get
			{
				if (!((Object)(object)SNet.Master == (Object)null) && !SNet.IsMaster)
				{
					return _ping;
				}
				return 0f;
			}
		}

		public static float RawPing
		{
			get
			{
				if (!((Object)(object)SNet.Master == (Object)null) && !SNet.IsMaster)
				{
					return _rawPing;
				}
				return 0f;
			}
		}

		public static float Jitter
		{
			get
			{
				if (!((Object)(object)SNet.Master == (Object)null) && !SNet.IsMaster)
				{
					return _jitter;
				}
				return 0f;
			}
		}

		public static float RawJitter
		{
			get
			{
				if (!((Object)(object)SNet.Master == (Object)null) && !SNet.IsMaster)
				{
					return _rawJitter;
				}
				return 0f;
			}
		}

		public static bool IsDesynced { get; private set; }

		public static void Start()
		{
			_seqNumber = 0u;
			ref PingInfo reference = ref _buffer[_seqNumber];
			reference.SeqNumber = _seqNumber;
			reference.Ackd = false;
			_running = true;
		}

		private static void Pause()
		{
			_running = false;
		}

		[HarmonyPatch(typeof(SNet_SessionHub), "OnJoinedLobby")]
		[HarmonyPrefix]
		private static void SNet_SessionHub_OnJoinedLobby()
		{
			Start();
		}

		[HarmonyPatch(typeof(SNet_SessionHub), "LeaveHub")]
		[HarmonyPrefix]
		private static void SNet_SessionHub_LeaveHub()
		{
			Pause();
		}

		private unsafe void Update()
		{
			PlayerChatManager current = PlayerChatManager.Current;
			if ((Object)(object)current == (Object)null)
			{
				return;
			}
			((SNet_SyncedAction<pChatMessage>)(object)current.m_sendChatMessage).m_channelType = (SNet_ChannelType)0;
			if (ConfigMgr.PingerType != 0 || !_running || SNet.IsMaster || (Object)(object)SNet.Master == (Object)null)
			{
				return;
			}
			PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent();
			if ((Object)(object)localPlayerAgent == (Object)null)
			{
				return;
			}
			_ = localPlayerAgent.Owner.Lookup;
			float now = SystemTime.Now;
			if (now > _nextPingSendTime)
			{
				_nextPingSendTime = now + 0.5f;
				if (now - _lastPingReceived > 1f)
				{
					IsDesynced = true;
				}
				ref PingInfo reference = ref _buffer[_seqNumber++ % BUFFER_SIZE];
				reference.SendTime = now;
				reference.Ackd = false;
				_buffer[_seqNumber % BUFFER_SIZE].SeqNumber = _seqNumber;
				string text;
				fixed (uint* value = &reference.SeqNumber)
				{
					text = new string((char*)value, 0, 2);
				}
				SNet_Player owner = localPlayerAgent.Owner;
				owner.Lookup ^= 0x9F3C7A21D8B4E6F2uL;
				PlayerChatManager.WantToSentTextMessage(localPlayerAgent, text, (PlayerAgent)null);
				SNet_Player owner2 = localPlayerAgent.Owner;
				owner2.Lookup ^= 0x9F3C7A21D8B4E6F2uL;
			}
		}

		[HarmonyPatch(typeof(PlayerChatManager), "DoSendChatMessage")]
		[HarmonyPrefix]
		private unsafe static bool OnPingReceive(PlayerChatManager __instance, pChatMessage data)
		{
			//IL_0066: 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)
			if (!_running || SNet.IsMaster || (Object)(object)SNet.Master == (Object)null || (Object)(object)SNet.LocalPlayer == (Object)null || (data.fromPlayer.lookup ^ 0x9F3C7A21D8B4E6F2uL) != SNet.LocalPlayer.Lookup)
			{
				SNet_Core_STEAM val = ((Il2CppObjectBase)SNet.Core).TryCast<SNet_Core_STEAM>();
				if ((Object)(object)val == (Object)null)
				{
					return true;
				}
				return val.m_playerLookup.ContainsKey(data.fromPlayer.lookup);
			}
			float now = SystemTime.Now;
			uint num;
			fixed (char* ptr = data.message.m_data)
			{
				num = *(uint*)ptr;
			}
			if (_buffer[_seqNumber % BUFFER_SIZE].SeqNumber - num >= BUFFER_SIZE)
			{
				return false;
			}
			PingInfo pingInfo = _buffer[num % BUFFER_SIZE];
			if (pingInfo.Ackd)
			{
				return false;
			}
			pingInfo.Ackd = true;
			pingInfo.RecvTime = now;
			float num2 = Mathf.Clamp(pingInfo.RecvTime - pingInfo.SendTime, 0f, 1f);
			_rawJitter = Mathf.Abs(num2 - _rawPing);
			_rawPing = num2;
			_jitter += (_rawJitter - _jitter) / 16f;
			_ping = 0.5f * _ping + 0.5f * _rawPing;
			_lastPingReceived = now;
			IsDesynced = false;
			return false;
		}
	}
	[HarmonyPatch]
	internal class MarkerPinger : MonoBehaviour, IPinger
	{
		private const uint MAGIC_NUMBER = 2882400175u;

		private static uint BUFFER_SIZE = 10u;

		private static PingInfo[] _buffer = new PingInfo[BUFFER_SIZE];

		private static uint _seqNumber = 0u;

		private static float _lastPingReceived = 0f;

		private static float _ping = 0f;

		private static float _rawPing = 0f;

		private static float _jitter = 0f;

		private static float _rawJitter = 0f;

		private static bool _running = false;

		private static int _localPlayerSlotIndex = -1;

		private static SyncedNavMarkerWrapper? _localPlayerNavMarker = null;

		private static pNavMarkerState _cachedNavMarkerState = default(pNavMarkerState);

		private static float _markerAutoHideTime = 0f;

		private static bool _shouldMarkerBeVisible = false;

		private static float _nextPingSendTime = 0f;

		public static float Ping
		{
			get
			{
				if (!((Object)(object)SNet.Master == (Object)null) && !SNet.IsMaster)
				{
					return _ping;
				}
				return 0f;
			}
		}

		public static float RawPing
		{
			get
			{
				if (!((Object)(object)SNet.Master == (Object)null) && !SNet.IsMaster)
				{
					return _rawPing;
				}
				return 0f;
			}
		}

		public static float Jitter
		{
			get
			{
				if (!((Object)(object)SNet.Master == (Object)null) && !SNet.IsMaster)
				{
					return _jitter;
				}
				return 0f;
			}
		}

		public static float RawJitter
		{
			get
			{
				if (!((Object)(object)SNet.Master == (Object)null) && !SNet.IsMaster)
				{
					return _rawJitter;
				}
				return 0f;
			}
		}

		public static bool IsMeasuring
		{
			get
			{
				if (_running)
				{
					return SystemTime.Now > _markerAutoHideTime;
				}
				return false;
			}
		}

		public static bool IsDesynced { get; private set; }

		public static void Start()
		{
			_seqNumber = 0u;
			ref PingInfo reference = ref _buffer[_seqNumber];
			reference.SeqNumber = _seqNumber;
			reference.Ackd = false;
			_markerAutoHideTime = 0f;
			_nextPingSendTime = 0f;
			_running = true;
		}

		private static void Pause()
		{
			_running = false;
			_localPlayerSlotIndex = -1;
			_localPlayerNavMarker = null;
		}

		[HarmonyPatch(typeof(RundownManager), "EndGameSession")]
		[HarmonyPrefix]
		private static void RundownManager_EndGameSession()
		{
			Pause();
		}

		[HarmonyPatch(typeof(SNet_SessionHub), "LeaveHub")]
		[HarmonyPrefix]
		private static void SNet_SessionHub_LeaveHub()
		{
			Pause();
		}

		[HarmonyPatch(typeof(GuiManager), "AttemptSetPlayerPingStatus")]
		[HarmonyPrefix]
		private static void GuiManager_AttemptSetPlayerPingStatus(PlayerAgent sourceAgent, bool visible, Vector3 worldPos, eNavMarkerStyle style)
		{
			if (!visible)
			{
				_markerAutoHideTime = 0f;
			}
			else
			{
				_shouldMarkerBeVisible = false;
			}
		}

		private void Update()
		{
			//IL_0102: 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_0140: 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_0150: Unknown result type (might be due to invalid IL or missing references)
			//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_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			if (ConfigMgr.PingerType != NetstatAPI.PingerTypeEnum.Marker || SNet.IsMaster || (Object)(object)SNet.Master == (Object)null || (Object)(object)SNet.LocalPlayer == (Object)null)
			{
				return;
			}
			_localPlayerSlotIndex = SNet.LocalPlayer.PlayerSlotIndex();
			GuiManager current = GuiManager.Current;
			_localPlayerNavMarker = ((current == null) ? null : ((Il2CppArrayBase<SyncedNavMarkerWrapper>)(object)current.m_playerPings)?[_localPlayerSlotIndex]);
			if ((Object)(object)_localPlayerNavMarker == (Object)null || !_running)
			{
				return;
			}
			float now = SystemTime.Now;
			if (now > _markerAutoHideTime)
			{
				if (now > _nextPingSendTime)
				{
					_nextPingSendTime = now + 0.5f;
					if (now - _lastPingReceived > 1f)
					{
						IsDesynced = true;
					}
					ref PingInfo reference = ref _buffer[_seqNumber++ % BUFFER_SIZE];
					reference.SendTime = now;
					reference.Ackd = false;
					_buffer[_seqNumber % BUFFER_SIZE].SeqNumber = _seqNumber;
					pNavMarkerInteraction val = default(pNavMarkerInteraction);
					val.type = (eNavMarkerInteractionType)1;
					val.worldPos.x = BitConverter.UInt32BitsToSingle(2882400175u);
					val.worldPos.y = Unsafe.As<uint, float>(ref reference.SeqNumber);
					pNavMarkerState val2 = default(pNavMarkerState);
					val2.status = (eNavMarkerStatus)1;
					val2.worldPos = val.worldPos;
					val2.terminalItemId = val.terminalItemId;
					SNet_StateReplicator<pNavMarkerState, pNavMarkerInteraction> stateReplicator = _localPlayerNavMarker.m_stateReplicator;
					stateReplicator.m_statePacket_Recall.Send(val2, stateReplicator.m_channelType, SNet.Master);
					stateReplicator.m_interactionPacket.Send(val, stateReplicator.m_channelType, SNet.Master);
				}
			}
			else
			{
				_lastPingReceived = now;
			}
		}

		[HarmonyPatch(typeof(SyncedNavMarkerWrapper), "OnStateChange")]
		[HarmonyPrefix]
		private static void OnRecievePingStatus(SyncedNavMarkerWrapper __instance, pNavMarkerState oldState, pNavMarkerState newState, bool isDropinState)
		{
			//IL_0045: 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)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Invalid comparison between Unknown and I4
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: 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_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			if (SNet.IsMaster || (Object)(object)SNet.Master == (Object)null || isDropinState || !_running || __instance.m_playerIndex != _localPlayerSlotIndex)
			{
				return;
			}
			float now = SystemTime.Now;
			if (!_shouldMarkerBeVisible && now > _markerAutoHideTime && (int)newState.status == 0)
			{
				_cachedNavMarkerState = newState;
				_markerAutoHideTime = now + __instance.AutoHideDelay;
				_shouldMarkerBeVisible = true;
			}
			else if (_shouldMarkerBeVisible && now <= _markerAutoHideTime && (int)newState.status == 1 && (int)_cachedNavMarkerState.status == 0)
			{
				pNavMarkerInteraction val = default(pNavMarkerInteraction);
				val.type = (eNavMarkerInteractionType)0;
				val.style = _cachedNavMarkerState.style;
				val.worldPos = _cachedNavMarkerState.worldPos;
				val.terminalItemId = _cachedNavMarkerState.terminalItemId;
				__instance.m_stateReplicator.AttemptInteract(val);
			}
			else
			{
				if (Unsafe.As<float, uint>(ref newState.worldPos.x) != 2882400175u)
				{
					return;
				}
				uint num = Unsafe.As<float, uint>(ref newState.worldPos.y);
				if (_buffer[_seqNumber % BUFFER_SIZE].SeqNumber - num < BUFFER_SIZE)
				{
					PingInfo pingInfo = _buffer[num % BUFFER_SIZE];
					if (!pingInfo.Ackd)
					{
						pingInfo.Ackd = true;
						pingInfo.RecvTime = now;
						float num2 = Mathf.Clamp(pingInfo.RecvTime - pingInfo.SendTime, 0f, 1f);
						_rawJitter = Mathf.Abs(num2 - _rawPing);
						_rawPing = num2;
						_jitter += (_rawJitter - _jitter) / 16f;
						_ping = 0.5f * _ping + 0.5f * _rawPing;
						_lastPingReceived = now;
						IsDesynced = false;
					}
				}
			}
		}
	}
	public struct ChannelStats
	{
		public uint _accumulatedBytesReceived;

		public uint BytesReceived;

		public uint _accumulatedPacketsReceived;

		public uint PacketsReceived;

		public uint _accumulatedBytesSent;

		public uint BytesSent;

		public uint _accumulatedPacketsSent;

		public uint PacketsSent;

		public ChannelStats()
		{
			_accumulatedBytesReceived = 0u;
			BytesReceived = 0u;
			_accumulatedPacketsReceived = 0u;
			PacketsReceived = 0u;
			_accumulatedBytesSent = 0u;
			BytesSent = 0u;
			_accumulatedPacketsSent = 0u;
			PacketsSent = 0u;
		}
	}
	[HarmonyPatch]
	internal class SteamP2P : MonoBehaviour
	{
		private static float _nextPollTimestamp = 0f;

		private static ChannelStats[] _channels = new ChannelStats[Enum.GetValues(typeof(SNet_ChannelType)).Length];

		public static ReadOnlySpan<ChannelStats> Channels => _channels;

		public static uint BytesReceived { get; private set; }

		public static uint PacketsReceived { get; private set; }

		public static uint BytesSent { get; private set; }

		public static uint PacketsSent { get; private set; }

		public static int BytesQueuedForSend { get; private set; }

		public static int PacketsQueuedForSend { get; private set; }

		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPrefix]
		private static void SteamNetworking_ReadP2PPacket(Il2CppStructArray<byte> pubDest, uint cubDest, uint pcubMsgSize, CSteamID psteamIDRemote, int nChannel)
		{
			if (nChannel >= 0 && nChannel < _channels.Length)
			{
				ref ChannelStats reference = ref _channels[nChannel];
				reference._accumulatedBytesReceived += pcubMsgSize;
				reference._accumulatedPacketsReceived++;
			}
		}

		[HarmonyPatch(typeof(SteamNetworking), "SendP2PPacket")]
		[HarmonyPrefix]
		private static void SteamNetworking_SendP2PPacket(CSteamID steamIDRemote, Il2CppStructArray<byte> pubData, uint cubData, EP2PSend eP2PSendType, int nChannel)
		{
			if (nChannel >= 0 && nChannel < _channels.Length)
			{
				ref ChannelStats reference = ref _channels[nChannel];
				reference._accumulatedBytesSent += cubData;
				reference._accumulatedPacketsSent++;
			}
		}

		private void Update()
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			BytesQueuedForSend = 0;
			PacketsQueuedForSend = 0;
			Enumerator<SNet_Player> enumerator = SNet.LobbyPlayers.GetEnumerator();
			P2PSessionState_t val = default(P2PSessionState_t);
			while (enumerator.MoveNext())
			{
				SNet_Player current = enumerator.Current;
				if (!current.IsLocal && !current.IsBot)
				{
					SteamNetworking.GetP2PSessionState(new CSteamID(current.Lookup), ref val);
					BytesQueuedForSend += val.m_nBytesQueuedForSend;
					PacketsQueuedForSend += val.m_nPacketsQueuedForSend;
				}
			}
			float now = SystemTime.Now;
			if (now > _nextPollTimestamp)
			{
				_nextPollTimestamp = now + 1f;
				BytesReceived = 0u;
				PacketsReceived = 0u;
				BytesSent = 0u;
				PacketsSent = 0u;
				for (int i = 0; i < _channels.Length; i++)
				{
					ref ChannelStats reference = ref _channels[i];
					reference.BytesReceived = (uint)((float)reference._accumulatedBytesReceived * 1f);
					reference._accumulatedBytesReceived = 0u;
					reference.PacketsReceived = (uint)((float)reference._accumulatedPacketsReceived * 1f);
					reference._accumulatedPacketsReceived = 0u;
					reference.BytesSent = (uint)((float)reference._accumulatedBytesSent * 1f);
					reference._accumulatedBytesSent = 0u;
					reference.PacketsSent = (uint)((float)reference._accumulatedPacketsSent * 1f);
					reference._accumulatedPacketsSent = 0u;
					BytesReceived += reference.BytesReceived;
					PacketsReceived += reference.PacketsReceived;
					BytesSent += reference.BytesSent;
					PacketsSent += reference.PacketsSent;
				}
			}
		}

		public static string SNetChannelType2Str(SNet_ChannelType t)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected I4, but got Unknown
			return (int)t switch
			{
				5 => "BotCmds", 
				4 => "NonCrit", 
				2 => "Crit", 
				3 => "RecvCrit", 
				1 => "SessMig", 
				0 => "SessCrit", 
				_ => "???", 
			};
		}

		public static string SNetChannelType2StrShort(SNet_ChannelType t)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected I4, but got Unknown
			return (int)t switch
			{
				5 => "BC", 
				4 => "NC", 
				2 => "CR", 
				3 => "RC", 
				1 => "SM", 
				0 => "SC", 
				_ => "???", 
			};
		}
	}
	internal class SystemTime
	{
		private static long _startTimestamp = _unixMs;

		private static long _unixMs => ((DateTimeOffset)DateTime.Now).ToUnixTimeMilliseconds();

		public static float Now => (float)(_unixMs - _startTimestamp) / 1000f;
	}
	public struct TickStats
	{
		public ulong SteamId;

		public float _lastTickTimestamp;

		public float TickTime;

		public float RawTickTime;

		public bool IsMeasuring;

		public TickStats(ulong steamId)
		{
			SteamId = 0uL;
			_lastTickTimestamp = 0f;
			TickTime = 0f;
			RawTickTime = 0f;
			IsMeasuring = false;
			SteamId = steamId;
		}
	}
	[HarmonyPatch]
	internal class TickTimer : MonoBehaviour
	{
		private static Dictionary<ulong, TickStats> _playerTicks = new Dictionary<ulong, TickStats>();

		private static void Measure(ref TickStats info)
		{
			float now = SystemTime.Now;
			if (info.IsMeasuring)
			{
				info.RawTickTime = now - info._lastTickTimestamp;
				info.TickTime = 0.5f * info.TickTime + 0.5f * info.RawTickTime;
			}
			info.IsMeasuring = true;
			info._lastTickTimestamp = now;
		}

		[HarmonyPatch(typeof(PlayerSync), "IncomingLocomotion")]
		[HarmonyPrefix]
		private static void PlayerSync_IncomingLocomotion(PlayerSync __instance, pPlayerLocomotion data)
		{
			SNet_Player owner = __instance.m_agent.Owner;
			if (!owner.IsBot && !owner.IsLocal)
			{
				ulong lookup = owner.Lookup;
				TickStats info = GetTickStat(lookup);
				float num = ((SFloat8)(ref data.VelRight)).Get(10f);
				float num2 = ((SFloat8)(ref data.VelFwd)).Get(10f);
				if (num * num + num2 * num2 < 1f)
				{
					info.IsMeasuring = false;
					_playerTicks[lookup] = info;
				}
				else
				{
					Measure(ref info);
					_playerTicks[lookup] = info;
				}
			}
		}

		[HarmonyPatch(typeof(PlayerSync), "SendLocomotion")]
		[HarmonyPrefix]
		private static void PlayerSync_SendLocomotion(PlayerSync __instance, PLOC_State state, Vector3 pos, Vector3 lookDir, float velFwd, float velRight)
		{
			SNet_Player owner = __instance.m_agent.Owner;
			if (!owner.IsBot && owner.IsLocal)
			{
				ulong lookup = owner.Lookup;
				TickStats info = GetTickStat(lookup);
				Measure(ref info);
				_playerTicks[lookup] = info;
			}
		}

		[HarmonyPatch(typeof(PLOC_ClimbLadder), "Exit")]
		[HarmonyPrefix]
		private static void PLOC_ClimbLadder_Exit(PLOC_ClimbLadder __instance)
		{
			CommonLadderExit(__instance);
		}

		[HarmonyPatch(typeof(PLOC_ClimbLadder), "SyncExit")]
		[HarmonyPrefix]
		private static void PLOC_ClimbLadder_SyncExit(PLOC_ClimbLadder __instance)
		{
			CommonLadderExit(__instance);
		}

		private static void CommonLadderExit(PLOC_ClimbLadder __instance)
		{
			SNet_Player owner = ((PLOC_Base)__instance).m_owner.Owner;
			if (!owner.IsBot && owner.IsLocal)
			{
				ulong lookup = owner.Lookup;
				TickStats tickStat = GetTickStat(lookup);
				tickStat.IsMeasuring = false;
				_playerTicks[lookup] = tickStat;
			}
		}

		public static TickStats GetTickStat(ulong steamId)
		{
			if (!_playerTicks.ContainsKey(steamId))
			{
				_playerTicks.Add(steamId, new TickStats(steamId));
			}
			return _playerTicks[steamId];
		}

		public static void Start()
		{
			_playerTicks.Clear();
		}

		private static void Pause()
		{
			_playerTicks.Clear();
		}

		[HarmonyPatch(typeof(RundownManager), "EndGameSession")]
		[HarmonyPrefix]
		private static void RundownManager_EndGameSession()
		{
			Pause();
		}

		[HarmonyPatch(typeof(SNet_SessionHub), "LeaveHub")]
		[HarmonyPrefix]
		private static void SNet_SessionHub_LeaveHub()
		{
			Pause();
		}
	}
}
namespace Netstat.Config
{
	public enum ConfigEntryRule
	{
		Min,
		Max
	}
	public class ConfigEntryExtended<T>
	{
		private Dictionary<ConfigEntryRule, T> _rules = new Dictionary<ConfigEntryRule, T>();

		private ConfigEntry<T> _entry;

		public T Value
		{
			get
			{
				return _entry.Value;
			}
			set
			{
				_entry.Value = Enforce(value);
			}
		}

		public object BoxedValue
		{
			get
			{
				return ((ConfigEntryBase)_entry).BoxedValue;
			}
			set
			{
				((ConfigEntryBase)_entry).BoxedValue = Enforce((T)value);
			}
		}

		public ConfigEntryExtended(ConfigEntry<T> entry)
		{
			_entry = entry;
		}

		public bool AddRule(ConfigEntryRule rule, T ruleValue)
		{
			if (_rules.TryAdd(rule, ruleValue))
			{
				Enforce(rule);
				return true;
			}
			return false;
		}

		private void Enforce()
		{
			T val = Enforce(_entry.Value);
			if (val != null && !val.Equals(_entry.Value))
			{
				_entry.Value = val;
			}
		}

		private T Enforce(T val)
		{
			foreach (var (configEntryRule2, val3) in _rules)
			{
				switch (configEntryRule2)
				{
				case ConfigEntryRule.Min:
					if (Comparer<T>.Default.Compare(val, val3) < 0)
					{
						val = val3;
					}
					break;
				case ConfigEntryRule.Max:
					if (Comparer<T>.Default.Compare(val, val3) > 0)
					{
						val = val3;
					}
					break;
				}
			}
			return val;
		}

		private void Enforce(ConfigEntryRule rule)
		{
			T value = _entry.Value;
			value = Enforce(value, rule);
			if (value != null && !value.Equals(_entry.Value))
			{
				_entry.Value = value;
			}
		}

		private T Enforce(T val, ConfigEntryRule rule)
		{
			if (!_rules.TryGetValue(rule, out var value))
			{
				return val;
			}
			switch (rule)
			{
			case ConfigEntryRule.Min:
				if (Comparer<T>.Default.Compare(val, value) < 0)
				{
					val = value;
				}
				break;
			case ConfigEntryRule.Max:
				if (Comparer<T>.Default.Compare(val, value) > 0)
				{
					val = value;
				}
				break;
			}
			return val;
		}

		public static implicit operator ConfigEntryExtended<T>(ConfigEntry<T> entry)
		{
			return new ConfigEntryExtended<T>(entry);
		}
	}
	internal static class ConfigMgr
	{
		private static readonly ConfigFile Conf;

		private static readonly FileSystemWatcher? ConfigWatcher;

		private static readonly ConfigEntryExtended<bool> DebugConf;

		private static readonly ConfigEntryExtended<NetstatAPI.PingerTypeEnum> PingerTypeConf;

		private static readonly ConfigEntryExtended<float> UIAnchorXConf;

		private static readonly ConfigEntryExtended<float> UIAnchorYConf;

		private static readonly ConfigEntryExtended<float> UIAnchorOffsetXConf;

		private static readonly ConfigEntryExtended<float> UIAnchorOffsetYConf;

		private static readonly ConfigEntryExtended<bool> GraphEnabledConf;

		private static readonly ConfigEntryExtended<KeyCode> GraphToggleKeyConf;

		private static readonly ConfigEntryExtended<float> GraphSizeXConf;

		private static readonly ConfigEntryExtended<float> GraphSizeYConf;

		private static readonly ConfigEntryExtended<eNetstatGraph> EnabledGraphsConf;

		private static readonly ConfigEntryExtended<string> GraphsOrderConf;

		private static readonly ConfigEntryExtended<bool> DetailsBarEnabledConf;

		private static readonly ConfigEntryExtended<eNetstatData> DetailsBarDataConf;

		public static bool Processed { get; private set; }

		public static bool Debug => DebugConf.Value;

		public static NetstatAPI.PingerTypeEnum PingerType => PingerTypeConf.Value;

		public static Vector2 UIAnchor => new Vector2(UIAnchorXConf.Value, UIAnchorYConf.Value);

		public static Vector2 UIAnchorOffset => new Vector2(UIAnchorOffsetXConf.Value, UIAnchorOffsetYConf.Value);

		public static bool EnableGraphs
		{
			get
			{
				return GraphEnabledConf.Value;
			}
			set
			{
				GraphEnabledConf.Value = value;
			}
		}

		public static KeyCode GraphToggleKey => GraphToggleKeyConf.Value;

		public static Vector2 GraphSize => new Vector2(GraphSizeXConf.Value, GraphSizeYConf.Value);

		public static eNetstatGraph EnabledGraphs => EnabledGraphsConf.Value;

		public static List<eNetstatGraph> GraphsInOrder { get; }

		public static bool DetailsBarEnabled => DetailsBarEnabledConf.Value;

		public static eNetstatData DetailsBarData => DetailsBarDataConf.Value;

		public static void Init()
		{
			Logger.Info($"debug={Debug}");
			Process();
		}

		public static void Process()
		{
			GraphsInOrder.Clear();
			eNetstatGraph[] array = GraphsOrderConf.Value.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries).Select(StatConfigLib.Str2GraphType).ToArray();
			foreach (eNetstatGraph eNetstatGraph in array)
			{
				if (!Enum.IsDefined(eNetstatGraph))
				{
					Logger.Warn($"Invalid graph type in Graphs Order config: {eNetstatGraph}");
				}
				else if (!GraphsInOrder.Contains(eNetstatGraph))
				{
					GraphsInOrder.Add(eNetstatGraph);
				}
			}
			array = Enum.GetValues<eNetstatGraph>();
			foreach (eNetstatGraph item in array)
			{
				if (!GraphsInOrder.Contains(item))
				{
					GraphsInOrder.Add(item);
				}
			}
			Processed = true;
			UIManager.Instance?.SetDirty();
		}

		static ConfigMgr()
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			Processed = false;
			GraphsInOrder = Enum.GetValues<eNetstatGraph>().ToList();
			string text = "Netstat.cfg";
			string text2 = Path.Combine(Paths.ConfigPath, text);
			Logger.Info("cfgPath = " + text2);
			Conf = new ConfigFile(text2, true);
			ConfigWatcher = new FileSystemWatcher(Paths.ConfigPath, text)
			{
				NotifyFilter = NotifyFilters.LastWrite,
				EnableRaisingEvents = true
			};
			ConfigWatcher.Changed += async delegate
			{
				ConfigWatcher.EnableRaisingEvents = false;
				await Task.Delay(500);
				Logger.Debug("Reloading config...");
				Conf.Reload();
				await Task.Delay(250);
				Process();
				ConfigWatcher.EnableRaisingEvents = true;
			};
			int section = 1;
			string sectionHeader = default(string);
			Header("Options");
			PingerTypeConf = Conf.Bind<NetstatAPI.PingerTypeEnum>(sectionHeader, "Pinger Type", NetstatAPI.PingerTypeEnum.Chat, "Change the algorithm used for calculating ping. 'Chat' uses player chat messages, this spams the host console with 'Chat Log Errors'. If this is undesirable then 'Marker' can be used. The 'Marker' algorithm doesn't work whilst in lobby or when the player nav marker is in use, but does not cause errors on host.");
			Header("UI");
			UIAnchorXConf = Conf.Bind<float>(sectionHeader, "UI Anchor (X, horizontal)", 1f, "Change the x-component of the anchor point for the UI. 0.0 is left most edge of the display, and 1.0 is right most edge of the display. This is proportional to the screen size, so 0.5 is always the horizontal center of the screen regardless of resolution.");
			UIAnchorXConf.AddRule(ConfigEntryRule.Max, 1f);
			UIAnchorXConf.AddRule(ConfigEntryRule.Min, 0f);
			UIAnchorYConf = Conf.Bind<float>(sectionHeader, "UI Anchor (Y, vertical)", 0.2f, "Change the y-component of the anchor point for the UI. 0.0 is the bottom edge of the display, and 1.0 is the top edge of the display. This is proportional to the screen size, so 0.5 is always the vertical center of the screen regardless of resolution.");
			UIAnchorYConf.AddRule(ConfigEntryRule.Max, 1f);
			UIAnchorYConf.AddRule(ConfigEntryRule.Min, 0f);
			UIAnchorOffsetXConf = Conf.Bind<float>(sectionHeader, "UI Anchor Offset (X, horizontal)", -40f, "Change the x-component of the offset for the anchor point of the UI. This is in pixels (reference resolution is 2560x1440). This is an absolute offset and is applied after the anchor point is calculated.");
			UIAnchorOffsetYConf = Conf.Bind<float>(sectionHeader, "UI Anchor Offset (Y, vertical)", 0f, "Change the y-component of the offset for the anchor point of the UI. This is in pixels (reference resolution is 2560x1440). This is an absolute offset and is applied after the anchor point is calculated.");
			Header("Graphs");
			GraphEnabledConf = Conf.Bind<bool>(sectionHeader, "Enable Graphs", false, "Whether to show the graphs or not.");
			GraphToggleKeyConf = Conf.Bind<KeyCode>(sectionHeader, "Graph Toggle Key", (KeyCode)110, "Change the key used to toggle the visibility of the graphs.");
			GraphSizeXConf = Conf.Bind<float>(sectionHeader, "Graph Size (X, horizontal)", 200f, "Change the x-component of the size of the graphs. This is in pixels (reference resolution is 2560x1440).");
			GraphSizeYConf = Conf.Bind<float>(sectionHeader, "Graph Size (Y, vertical)", 100f, "Change the y-component of the size of the graphs. This is in pixels (reference resolution is 2560x1440).");
			EnabledGraphsConf = Conf.Bind<eNetstatGraph>(sectionHeader, "Enabled Graphs", eNetstatGraph.Ping, "Change which graphs are enabled. Multiple graphs can be enabled at the same time. Check the readme for details on each graph type.");
			GraphsOrderConf = Conf.Bind<string>(sectionHeader, "Graph Ordering", "ping, rxtx, rxchan, txchan, cstt", "Change the order in which the graphs are displayed. Available graphs are 'ping', 'rxtx', 'rxchan', 'txchan', 'cstt'. This does not affect what graphs are enabled, graphs earlier in the list appear towards the bottom.");
			Header("Details Bar");
			DetailsBarEnabledConf = Conf.Bind<bool>(sectionHeader, "Enable Details Bar", true, "Toggle the details bar on or off. The details bar is shown below the player health bar and shows value-only details of current statistics.");
			DetailsBarDataConf = Conf.Bind<eNetstatData>(sectionHeader, "Details Bar Data", eNetstatData.Ping, "Change which data is shown in the details bar. Check graph types/details in the README for more information about each data type.");
			HeaderSp('Z', "Dev");
			DebugConf = Conf.Bind<bool>(sectionHeader, "Enable Debug Logs", false, "debug logging");
			void Header(string header)
			{
				sectionHeader = $"({section++}) {header}";
			}
			void HeaderSp(char prefix, string header)
			{
				sectionHeader = $"({prefix}) {header}";
			}
		}
	}
}