Decompiled source of AdditionalUI v1.0.1

AdditionalUI.dll

Decompiled 3 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("AdditionalUI")]
[assembly: AssemblyDescription("J7 Additional UI Mod - HP, STAMINA, MOVEMENT SPEED, PING")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AdditionalUI")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("5ef15715-6195-4c0f-9662-8fcb6d19a38e")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace AdditionalUI;

public class SettingsMenu : MonoBehaviour
{
	private class DragMove : MonoBehaviour, IBeginDragHandler, IEventSystemHandler, IDragHandler
	{
		private RectTransform _target;

		private Vector2 _startMouse;

		private Vector2 _startPos;

		public void Init(RectTransform target)
		{
			_target = target;
		}

		public void OnBeginDrag(PointerEventData e)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//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)
			Vector2 startMouse = default(Vector2);
			if (!((Object)(object)_target == (Object)null) && RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)/*isinst with value type is only supported in some contexts*/, e.position, (Camera)null, ref startMouse))
			{
				_startMouse = startMouse;
				_startPos = _target.anchoredPosition;
			}
		}

		public void OnDrag(PointerEventData e)
		{
			//IL_0020: 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_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_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = default(Vector2);
			if (!((Object)(object)_target == (Object)null) && RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)/*isinst with value type is only supported in some contexts*/, e.position, (Camera)null, ref val))
			{
				Vector2 val2 = val - _startMouse;
				_target.anchoredPosition = _startPos + val2;
			}
		}
	}

	private static SettingsMenu _instance;

	private const KeyCode TOGGLE_KEY = 291;

	private GameObject _root;

	private Canvas _canvas;

	private CanvasGroup _cg;

	private RectTransform _window;

	private bool _open;

	private CursorLockMode _prevLock;

	private bool _prevCursorVisible;

	private bool _prevSendNav;

	private readonly List<Selectable> _selectables = new List<Selectable>();

	private Toggle _tShowHPST;

	private Toggle _tShowSpeed;

	private Toggle _tShowPing;

	private Slider _spdX;

	private Slider _spdY;

	private Text _spdXVal;

	private Text _spdYVal;

	private Slider _pngX;

	private Slider _pngY;

	private Text _pngXVal;

	private Text _pngYVal;

	private Button _btnClose;

	private Button _btnReload;

	public static SettingsMenu CreateOrGet()
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Expected O, but got Unknown
		if ((Object)(object)_instance != (Object)null)
		{
			return _instance;
		}
		GameObject val = new GameObject("SettingsMenuHost");
		Object.DontDestroyOnLoad((Object)val);
		_instance = val.AddComponent<SettingsMenu>();
		return _instance;
	}

	private void Awake()
	{
		EnsureEventSystem();
		BuildCanvas();
		BuildWindow();
		PopulateFromConfig();
		SetVisible(v: false);
	}

	private void Update()
	{
		if (Input.GetKeyDown((KeyCode)291))
		{
			SetVisible(!_open);
		}
		if (!_open && (Object)(object)EventSystem.current != (Object)null)
		{
			GameObject currentSelectedGameObject = EventSystem.current.currentSelectedGameObject;
			if ((Object)(object)currentSelectedGameObject != (Object)null && (Object)(object)_root != (Object)null && currentSelectedGameObject.transform.IsChildOf(_root.transform))
			{
				EventSystem.current.SetSelectedGameObject((GameObject)null);
			}
		}
	}

	private void BuildCanvas()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Expected O, but got Unknown
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		_root = new GameObject("SettingsMenuCanvas");
		_root.layer = LayerMask.NameToLayer("UI");
		Object.DontDestroyOnLoad((Object)(object)_root);
		_canvas = _root.AddComponent<Canvas>();
		_canvas.renderMode = (RenderMode)0;
		_canvas.sortingOrder = 9999;
		CanvasScaler obj = _root.AddComponent<CanvasScaler>();
		obj.uiScaleMode = (ScaleMode)1;
		obj.referenceResolution = new Vector2(1920f, 1080f);
		obj.matchWidthOrHeight = 1f;
		_root.AddComponent<GraphicRaycaster>();
		_cg = _root.AddComponent<CanvasGroup>();
		_cg.alpha = 1f;
		_cg.interactable = true;
		_cg.blocksRaycasts = true;
	}

	private void BuildWindow()
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Expected O, but got Unknown
		//IL_003e: 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_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0116: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		//IL_0158: Unknown result type (might be due to invalid IL or missing references)
		//IL_0187: 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_01df: Unknown result type (might be due to invalid IL or missing references)
		//IL_0200: Unknown result type (might be due to invalid IL or missing references)
		//IL_023a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0261: Unknown result type (might be due to invalid IL or missing references)
		//IL_0288: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b9: 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_0314: Unknown result type (might be due to invalid IL or missing references)
		//IL_0361: Unknown result type (might be due to invalid IL or missing references)
		//IL_0384: Unknown result type (might be due to invalid IL or missing references)
		//IL_038e: Expected O, but got Unknown
		//IL_03a3: 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_03d0: Expected O, but got Unknown
		GameObject val = new GameObject("SettingsWindow");
		val.transform.SetParent(((Component)_canvas).transform, false);
		_window = val.AddComponent<RectTransform>();
		_window.sizeDelta = new Vector2(600f, 440f);
		RectTransform window = _window;
		RectTransform window2 = _window;
		Vector2 val2 = default(Vector2);
		((Vector2)(ref val2))..ctor(1f, 1f);
		window2.anchorMax = val2;
		window.anchorMin = val2;
		_window.pivot = new Vector2(1f, 1f);
		_window.anchoredPosition = new Vector2(-40f, -40f);
		((Graphic)val.AddComponent<Image>()).color = new Color(0f, 0f, 0f, 0.72f);
		val.AddComponent<DragMove>().Init(_window);
		float num = -16f;
		MakeLabel(val.transform, "Settings", 22, new Vector2(16f, num), (TextAnchor)0);
		num -= 48f;
		_tShowHPST = MakeToggle(val.transform, new Vector2(16f, num), "Health & Stamina");
		_tShowSpeed = MakeToggle(val.transform, new Vector2(201f, num), "Speed");
		_tShowPing = MakeToggle(val.transform, new Vector2(356f, num), "Ping");
		num -= 48f;
		MakeLabel(val.transform, "Speed Offset", 16, new Vector2(16f, num), (TextAnchor)0);
		num -= 28f;
		float num2 = 275f;
		CreateSliderWithCenteredValue(val.transform, new Vector2(16f, num), num2, out _spdX, out _spdXVal);
		MakeLabel(val.transform, "X", 13, new Vector2(16f, num + 20f), (TextAnchor)0);
		CreateSliderWithCenteredValue(val.transform, new Vector2(16f + num2 + 18f, num), num2, out _spdY, out _spdYVal);
		MakeLabel(val.transform, "Y", 13, new Vector2(16f + num2 + 18f, num + 20f), (TextAnchor)0);
		num -= 76f;
		MakeLabel(val.transform, "Ping Offset", 16, new Vector2(16f, num), (TextAnchor)0);
		num -= 28f;
		float num3 = 275f;
		CreateSliderWithCenteredValue(val.transform, new Vector2(16f, num), num3, out _pngX, out _pngXVal);
		MakeLabel(val.transform, "X", 13, new Vector2(16f, num + 20f), (TextAnchor)0);
		CreateSliderWithCenteredValue(val.transform, new Vector2(16f + num3 + 18f, num), num3, out _pngY, out _pngYVal);
		MakeLabel(val.transform, "Y", 13, new Vector2(16f + num3 + 18f, num + 20f), (TextAnchor)0);
		num -= 76f;
		float num4 = 130f;
		float num5 = 30f;
		float num6 = 0f - (440f - num5 - 16f);
		_btnReload = MakeButton(val.transform, "Reload Mod", new Vector2(584f - num4 - num4 - 12f, num6), num4, num5);
		((UnityEvent)_btnReload.onClick).AddListener(new UnityAction(ReloadModSafe));
		_btnClose = MakeButton(val.transform, "Close", new Vector2(584f - num4, num6), num4, num5);
		((UnityEvent)_btnClose.onClick).AddListener((UnityAction)delegate
		{
			SetVisible(v: false);
		});
		_selectables.Clear();
		Selectable[] componentsInChildren = _root.GetComponentsInChildren<Selectable>(true);
		foreach (Selectable val3 in componentsInChildren)
		{
			DisableKeyboardNavigation(val3);
			_selectables.Add(val3);
		}
	}

	private void PopulateFromConfig()
	{
		ConfigFile configRef = PluginMain.ConfigRef;
		_tShowHPST.isOn = configRef.Bind<bool>("StatsOverlay", "ShowHealthStamina", true, "").Value;
		_tShowSpeed.isOn = configRef.Bind<bool>("StatsOverlay", "ShowSpeed", true, "").Value;
		_tShowPing.isOn = configRef.Bind<bool>("StatsOverlay", "ShowPing", true, "").Value;
		((UnityEvent<bool>)(object)_tShowHPST.onValueChanged).AddListener((UnityAction<bool>)delegate(bool v)
		{
			SetCfg("StatsOverlay", "ShowHealthStamina", v);
			ApplyAndPush();
		});
		((UnityEvent<bool>)(object)_tShowSpeed.onValueChanged).AddListener((UnityAction<bool>)delegate(bool v)
		{
			SetCfg("StatsOverlay", "ShowSpeed", v);
			ApplyAndPush();
		});
		((UnityEvent<bool>)(object)_tShowPing.onValueChanged).AddListener((UnityAction<bool>)delegate(bool v)
		{
			SetCfg("StatsOverlay", "ShowPing", v);
			ApplyAndPush();
		});
		SetupSlider(_spdX, -1f, 1f, configRef.Bind<float>("StatsOverlay.SpeedOffset", "X", 0.53f, "").Value, _spdXVal);
		SetupSlider(_spdY, -1f, 1f, configRef.Bind<float>("StatsOverlay.SpeedOffset", "Y", -0.017f, "").Value, _spdYVal);
		SetupSlider(_pngX, -1f, 1f, configRef.Bind<float>("StatsOverlay.PingOffset", "X", -0.101f, "").Value, _pngXVal);
		SetupSlider(_pngY, -1f, 1f, configRef.Bind<float>("StatsOverlay.PingOffset", "Y", 1f, "").Value, _pngYVal);
		((UnityEvent<float>)(object)_spdX.onValueChanged).AddListener((UnityAction<float>)delegate(float v)
		{
			if ((Object)(object)_spdXVal != (Object)null)
			{
				_spdXVal.text = v.ToString("0.000");
			}
			SetCfg("StatsOverlay.SpeedOffset", "X", v);
			ApplyAndPush();
		});
		((UnityEvent<float>)(object)_spdY.onValueChanged).AddListener((UnityAction<float>)delegate(float v)
		{
			if ((Object)(object)_spdYVal != (Object)null)
			{
				_spdYVal.text = v.ToString("0.000");
			}
			SetCfg("StatsOverlay.SpeedOffset", "Y", v);
			ApplyAndPush();
		});
		((UnityEvent<float>)(object)_pngX.onValueChanged).AddListener((UnityAction<float>)delegate(float v)
		{
			if ((Object)(object)_pngXVal != (Object)null)
			{
				_pngXVal.text = v.ToString("0.000");
			}
			SetCfg("StatsOverlay.PingOffset", "X", v);
			ApplyAndPush();
		});
		((UnityEvent<float>)(object)_pngY.onValueChanged).AddListener((UnityAction<float>)delegate(float v)
		{
			if ((Object)(object)_pngYVal != (Object)null)
			{
				_pngYVal.text = v.ToString("0.000");
			}
			SetCfg("StatsOverlay.PingOffset", "Y", v);
			ApplyAndPush();
		});
		PushOverlay();
	}

	private void SetVisible(bool v)
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0191: Unknown result type (might be due to invalid IL or missing references)
		_open = v;
		if (v)
		{
			EnsureEventSystem();
			_prevLock = Cursor.lockState;
			_prevCursorVisible = Cursor.visible;
			if ((Object)(object)EventSystem.current != (Object)null)
			{
				_prevSendNav = EventSystem.current.sendNavigationEvents;
				EventSystem.current.sendNavigationEvents = false;
				EventSystem.current.SetSelectedGameObject((GameObject)null);
			}
			_cg.interactable = true;
			_cg.blocksRaycasts = true;
			_root.SetActive(true);
			Cursor.lockState = (CursorLockMode)0;
			Cursor.visible = true;
			{
				foreach (Selectable selectable in _selectables)
				{
					if (Object.op_Implicit((Object)(object)selectable))
					{
						selectable.interactable = true;
					}
				}
				return;
			}
		}
		_cg.interactable = false;
		_cg.blocksRaycasts = false;
		foreach (Selectable selectable2 in _selectables)
		{
			if (Object.op_Implicit((Object)(object)selectable2))
			{
				selectable2.interactable = false;
			}
		}
		if ((Object)(object)EventSystem.current != (Object)null)
		{
			GameObject currentSelectedGameObject = EventSystem.current.currentSelectedGameObject;
			if ((Object)(object)currentSelectedGameObject != (Object)null && (Object)(object)_root != (Object)null && currentSelectedGameObject.transform.IsChildOf(_root.transform))
			{
				EventSystem.current.SetSelectedGameObject((GameObject)null);
			}
			EventSystem.current.sendNavigationEvents = _prevSendNav;
		}
		_root.SetActive(false);
		Cursor.lockState = _prevLock;
		Cursor.visible = _prevCursorVisible;
	}

	private static void EnsureEventSystem()
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Expected O, but got Unknown
		if (!((Object)(object)EventSystem.current != (Object)null))
		{
			GameObject val = new GameObject("EventSystem");
			val.AddComponent<EventSystem>();
			val.AddComponent<StandaloneInputModule>();
			Object.DontDestroyOnLoad((Object)val);
		}
	}

	private void ApplyAndPush()
	{
		PluginMain.ConfigRef.Save();
		PushOverlay();
	}

	private void PushOverlay()
	{
		StatsOverlay statsOverlay = Object.FindObjectOfType<StatsOverlay>(true);
		if ((Object)(object)statsOverlay != (Object)null)
		{
			statsOverlay.ApplyConfigFromMenu();
		}
	}

	private static Text MakeLabel(Transform parent, string text, int fontSize, Vector2 pos, TextAnchor anchor)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: 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_0045: 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_005c: 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)
		//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)
		GameObject val = new GameObject("Label");
		val.transform.SetParent(parent, false);
		RectTransform obj = val.AddComponent<RectTransform>();
		obj.sizeDelta = new Vector2(540f, 24f);
		Vector2 val2 = default(Vector2);
		((Vector2)(ref val2))..ctor(0f, 1f);
		obj.anchorMax = val2;
		obj.anchorMin = val2;
		obj.pivot = new Vector2(0f, 1f);
		obj.anchoredPosition = pos;
		Text obj2 = val.AddComponent<Text>();
		obj2.text = text;
		obj2.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
		obj2.fontSize = fontSize;
		obj2.alignment = anchor;
		((Graphic)obj2).color = Color.white;
		return obj2;
	}

	private static Button MakeButton(Transform parent, string text, Vector2 pos, float w, float h)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Expected O, but got Unknown
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: 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_0097: 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_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_011e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: 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_014e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0178: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("Button");
		val.transform.SetParent(parent, false);
		RectTransform obj = val.AddComponent<RectTransform>();
		Vector2 val2 = default(Vector2);
		((Vector2)(ref val2))..ctor(0f, 1f);
		obj.anchorMax = val2;
		obj.anchorMin = val2;
		obj.pivot = new Vector2(0f, 1f);
		obj.anchoredPosition = pos;
		obj.sizeDelta = new Vector2(w, h);
		((Graphic)val.AddComponent<Image>()).color = new Color(1f, 1f, 1f, 0.14f);
		Button obj2 = val.AddComponent<Button>();
		DisableKeyboardNavigation((Selectable)(object)obj2);
		ColorBlock colors = ((Selectable)obj2).colors;
		((ColorBlock)(ref colors)).highlightedColor = new Color(1f, 1f, 1f, 0.2f);
		((ColorBlock)(ref colors)).pressedColor = new Color(1f, 1f, 1f, 0.26f);
		((Selectable)obj2).colors = colors;
		Text obj3 = new GameObject("Text").AddComponent<Text>();
		((Component)obj3).transform.SetParent(val.transform, false);
		RectTransform component = ((Component)obj3).GetComponent<RectTransform>();
		((Vector2)(ref val2))..ctor(0.5f, 0.5f);
		component.anchorMax = val2;
		component.anchorMin = val2;
		component.pivot = new Vector2(0.5f, 0.5f);
		component.sizeDelta = new Vector2(w - 10f, h - 6f);
		obj3.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
		obj3.text = text;
		obj3.fontSize = 14;
		((Graphic)obj3).color = Color.white;
		obj3.alignment = (TextAnchor)4;
		return obj2;
	}

	private static Slider MakeSlider(Transform parent, Vector2 pos, float width)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Expected O, but got Unknown
		//IL_0031: 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_004a: 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_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Expected O, but got Unknown
		//IL_00c0: 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_00ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0122: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: 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_015b: Unknown result type (might be due to invalid IL or missing references)
		//IL_016d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0182: Unknown result type (might be due to invalid IL or missing references)
		//IL_0197: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01da: Expected O, but got Unknown
		//IL_020b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0212: Unknown result type (might be due to invalid IL or missing references)
		//IL_0225: Unknown result type (might be due to invalid IL or missing references)
		//IL_023b: Unknown result type (might be due to invalid IL or missing references)
		//IL_024c: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("Slider");
		val.transform.SetParent(parent, false);
		RectTransform obj = val.AddComponent<RectTransform>();
		Vector2 val2 = default(Vector2);
		((Vector2)(ref val2))..ctor(0f, 1f);
		obj.anchorMax = val2;
		obj.anchorMin = val2;
		obj.pivot = new Vector2(0f, 1f);
		obj.anchoredPosition = pos;
		obj.sizeDelta = new Vector2(width, 30f);
		Slider val3 = val.AddComponent<Slider>();
		val3.direction = (Direction)0;
		DisableKeyboardNavigation((Selectable)(object)val3);
		GameObject val4 = new GameObject("Track", new Type[1] { typeof(Image) });
		val4.transform.SetParent(val.transform, false);
		RectTransform component = val4.GetComponent<RectTransform>();
		component.anchorMin = new Vector2(0f, 0.5f);
		component.anchorMax = new Vector2(1f, 0.5f);
		component.pivot = new Vector2(0.5f, 0.5f);
		component.sizeDelta = new Vector2(0f, 8f);
		((Graphic)val4.GetComponent<Image>()).color = new Color(1f, 1f, 1f, 0.1f);
		GameObject val5 = new GameObject("Fill", new Type[1] { typeof(Image) });
		val5.transform.SetParent(val4.transform, false);
		RectTransform component2 = val5.GetComponent<RectTransform>();
		component2.anchorMin = new Vector2(0f, 0f);
		component2.anchorMax = new Vector2(1f, 1f);
		component2.pivot = new Vector2(0.5f, 0.5f);
		component2.sizeDelta = Vector2.zero;
		((Graphic)val5.GetComponent<Image>()).color = Color.white;
		GameObject val6 = new GameObject("Handle", new Type[1] { typeof(Image) });
		val6.transform.SetParent(val.transform, false);
		RectTransform component3 = val6.GetComponent<RectTransform>();
		((Vector2)(ref val2))..ctor(0.5f, 0.5f);
		component3.anchorMax = val2;
		component3.anchorMin = val2;
		component3.pivot = new Vector2(0.5f, 0.5f);
		component3.sizeDelta = new Vector2(10f, 18f);
		((Graphic)val6.GetComponent<Image>()).color = Color.white;
		val3.fillRect = component2;
		val3.handleRect = component3;
		((Selectable)val3).targetGraphic = (Graphic)(object)val6.GetComponent<Image>();
		val3.wholeNumbers = false;
		return val3;
	}

	private static void CreateSliderWithCenteredValue(Transform parent, Vector2 pos, float width, out Slider slider, out Text valueLabel)
	{
		//IL_0002: 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_0040: 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_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: 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)
		slider = MakeSlider(parent, pos, width);
		Text val = new GameObject("Value").AddComponent<Text>();
		((Component)val).transform.SetParent(parent, false);
		RectTransform component = ((Component)val).GetComponent<RectTransform>();
		Vector2 val2 = default(Vector2);
		((Vector2)(ref val2))..ctor(0f, 1f);
		component.anchorMax = val2;
		component.anchorMin = val2;
		component.pivot = new Vector2(0f, 1f);
		component.anchoredPosition = new Vector2(pos.x, pos.y - 40f);
		component.sizeDelta = new Vector2(width, 18f);
		val.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
		val.fontSize = 12;
		((Graphic)val).color = Color.white;
		val.alignment = (TextAnchor)1;
		val.text = "0.000";
		valueLabel = val;
	}

	private static void SetupSlider(Slider s, float min, float max, float start, Text label)
	{
		s.minValue = min;
		s.maxValue = max;
		s.value = Mathf.Clamp(start, min, max);
		if ((Object)(object)label != (Object)null)
		{
			label.text = s.value.ToString("0.000");
		}
	}

	private static Toggle MakeToggle(Transform parent, Vector2 pos, string label)
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Expected O, but got Unknown
		//IL_0044: 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_005d: 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_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Expected O, but got Unknown
		//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_0104: Unknown result type (might be due to invalid IL or missing references)
		//IL_010e: 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_0164: Unknown result type (might be due to invalid IL or missing references)
		//IL_0169: 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_0194: Unknown result type (might be due to invalid IL or missing references)
		//IL_019b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0221: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("toggleRow", new Type[1] { typeof(RectTransform) });
		val.transform.SetParent(parent, false);
		RectTransform component = val.GetComponent<RectTransform>();
		Vector2 val2 = default(Vector2);
		((Vector2)(ref val2))..ctor(0f, 1f);
		component.anchorMax = val2;
		component.anchorMin = val2;
		component.pivot = new Vector2(0f, 1f);
		component.anchoredPosition = pos;
		component.sizeDelta = new Vector2(200f, 24f);
		Sprite builtinResource = Resources.GetBuiltinResource<Sprite>("UI/Skin/UISprite.psd");
		GameObject val3 = new GameObject("Background", new Type[1] { typeof(Image) });
		val3.transform.SetParent(val.transform, false);
		RectTransform component2 = val3.GetComponent<RectTransform>();
		((Vector2)(ref val2))..ctor(0f, 1f);
		component2.anchorMax = val2;
		component2.anchorMin = val2;
		component2.pivot = new Vector2(0f, 1f);
		component2.sizeDelta = new Vector2(20f, 20f);
		component2.anchoredPosition = Vector2.zero;
		Image component3 = val3.GetComponent<Image>();
		component3.sprite = builtinResource;
		component3.type = (Type)1;
		((Graphic)component3).color = new Color(1f, 1f, 1f, 0.18f);
		GameObject val4 = new GameObject("Checkmark", new Type[1] { typeof(Image) });
		val4.transform.SetParent(val3.transform, false);
		RectTransform component4 = val4.GetComponent<RectTransform>();
		((Vector2)(ref val2))..ctor(0.5f, 0.5f);
		component4.anchorMax = val2;
		component4.anchorMin = val2;
		component4.pivot = new Vector2(0.5f, 0.5f);
		component4.sizeDelta = new Vector2(12f, 12f);
		Image component5 = val4.GetComponent<Image>();
		component5.sprite = builtinResource;
		component5.type = (Type)1;
		((Graphic)component5).color = Color.white;
		Toggle obj = val.gameObject.AddComponent<Toggle>();
		((Selectable)obj).targetGraphic = (Graphic)(object)component3;
		obj.graphic = (Graphic)(object)component5;
		DisableKeyboardNavigation((Selectable)(object)obj);
		MakeLabel(val.transform, label, 14, new Vector2(26f, 0f), (TextAnchor)0);
		return obj;
	}

	private static void DisableKeyboardNavigation(Selectable s)
	{
		//IL_000b: 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_001a: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)s == (Object)null))
		{
			Navigation navigation = s.navigation;
			((Navigation)(ref navigation)).mode = (Mode)0;
			s.navigation = navigation;
		}
	}

	private static void SetCfg(string section, string key, bool v)
	{
		PluginMain.ConfigRef.Bind<bool>(section, key, v, "").Value = v;
	}

	private static void SetCfg(string section, string key, float v)
	{
		PluginMain.ConfigRef.Bind<float>(section, key, v, "").Value = v;
	}

	private void ReloadModSafe()
	{
		try
		{
			PluginMain.ConfigRef.Reload();
			StatsOverlay statsOverlay = Object.FindObjectOfType<StatsOverlay>(true);
			if ((Object)(object)statsOverlay != (Object)null)
			{
				statsOverlay.ExternalReload();
			}
			if ((Object)(object)_spdXVal != (Object)null)
			{
				_spdXVal.text = _spdX.value.ToString("0.000");
			}
			if ((Object)(object)_spdYVal != (Object)null)
			{
				_spdYVal.text = _spdY.value.ToString("0.000");
			}
			if ((Object)(object)_pngXVal != (Object)null)
			{
				_pngXVal.text = _pngX.value.ToString("0.000");
			}
			if ((Object)(object)_pngYVal != (Object)null)
			{
				_pngYVal.text = _pngY.value.ToString("0.000");
			}
		}
		catch (Exception ex)
		{
			Debug.LogError((object)("[SettingsMenu] Reload failed: " + ex));
		}
	}
}
public class StatsOverlay : MonoBehaviour
{
	private static readonly Vector3 HP_OFFSET = new Vector3(0.015f, -0.078f, -0.013f);

	private static readonly Vector3 ST_OFFSET = new Vector3(0.032f, -0.0775f, -0.013f);

	private static readonly Vector3 SPEED_OFFSET = new Vector3(0.009f, 0.0103f, -0.013f);

	private Vector3 _speedOffset = new Vector3(0.502f, 0.04f, -0.013f);

	private Vector3 _pingOffset = new Vector3(0f, 0.825f, -0.06f);

	private const float TEXT_SCALE = 0.0012f;

	private const float HP_Z_DEG = 90f;

	private const float ST_Z_DEG = 90f;

	private const float SPD_Z_DEG = 90f;

	private const float PING_Z_DEG = 90f;

	private static readonly Vector3 PING_OFFSET = new Vector3(0f, 0.84f, -0.06f);

	private TextMeshProUGUI _pingText;

	private float _nextPingAt;

	private const float PING_UPDATE_INTERVAL = 0.15f;

	private int _lastPingMs = int.MinValue;

	private float _nextForcePingAt;

	private const string RELATIVE_BONE_PATH = "Main Camera/ui/ionknow/Armature/Bone.014";

	private const string FALLBACK_ANCHOR = "Bone.014";

	private BaseUnityPlugin _plugin;

	private ConfigFile _cfg;

	private ConfigEntry<bool> _logEnabled;

	private readonly KeyboardShortcut _reloadKey = new KeyboardShortcut((KeyCode)290, Array.Empty<KeyCode>());

	private Canvas _worldCanvas;

	private Transform _worldRoot;

	private TextMeshProUGUI _hpText;

	private TextMeshProUGUI _stText;

	private TextMeshProUGUI _spdText;

	private GameObject _localPlayer;

	private Camera _playerCamera;

	private Transform _anchor;

	private float _nextProbeAt;

	private const float PROBE_INTERVAL = 0.25f;

	private bool _loggedProbeStart;

	private FieldInfo _fServerHealth;

	private FieldInfo _fPlayerHealth;

	private FieldInfo _fStamina;

	private Vector3 _prevPos;

	public Vector2 GetSpeedOffsetXY()
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		return new Vector2(_speedOffset.x, _speedOffset.y);
	}

	public Vector2 GetPingOffsetXY()
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		return new Vector2(_pingOffset.x, _pingOffset.y);
	}

	private void Awake()
	{
		_plugin = Object.FindObjectOfType<BaseUnityPlugin>();
		_cfg = (((Object)(object)_plugin != (Object)null) ? _plugin.Config : null);
		_logEnabled = _cfg.Bind<bool>("Logging", "Enabled", false, "Enable simple state-change logs.");
		Log("[StatsOverlay] Awake()");
		CacheReflection();
		BuildWorldCanvasAndTexts();
		BuildPingLabel();
		SetWorldVisible(on: false);
		SceneManager.activeSceneChanged += OnSceneChanged;
		_nextProbeAt = 0f;
	}

	private void OnDestroy()
	{
		SceneManager.activeSceneChanged -= OnSceneChanged;
		CleanupUI();
	}

	private void OnSceneChanged(Scene from, Scene to)
	{
		Log("[StatsOverlay] Scene change: " + ((Scene)(ref from)).name + " → " + ((Scene)(ref to)).name + " (reset)");
		_localPlayer = null;
		_playerCamera = null;
		_anchor = null;
		SetWorldVisible(on: false);
		_loggedProbeStart = false;
		_nextProbeAt = 0f;
	}

	private void Update()
	{
		if ((Object)(object)_pingText != (Object)null && Time.unscaledTime >= _nextPingAt)
		{
			if (PingReader.TryGetPingMilliseconds(out var pingMs))
			{
				((TMP_Text)_pingText).text = "PING: " + pingMs + " ms";
			}
			else
			{
				((TMP_Text)_pingText).text = "PING: --";
			}
			_nextPingAt = Time.unscaledTime + 0.15f;
		}
		if (Time.unscaledTime >= _nextProbeAt)
		{
			if (!_loggedProbeStart)
			{
				Log("[StatsOverlay] Starting probe loop…");
				_loggedProbeStart = true;
			}
			ProbePlayerCameraAndAnchor();
			_nextProbeAt = Time.unscaledTime + 0.25f;
		}
		if ((Object)(object)_localPlayer != (Object)null)
		{
			UpdateNumbers();
		}
	}

	public void ApplyConfigFromMenu()
	{
		//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_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		ConfigFile configRef = PluginMain.ConfigRef;
		float value = configRef.Bind<float>("StatsOverlay.SpeedOffset", "X", 0.53f, "").Value;
		float value2 = configRef.Bind<float>("StatsOverlay.SpeedOffset", "Y", -0.017f, "").Value;
		_speedOffset = new Vector3(value, value2, 0.047f);
		float value3 = configRef.Bind<float>("StatsOverlay.PingOffset", "X", -0.101f, "").Value;
		float value4 = configRef.Bind<float>("StatsOverlay.PingOffset", "Y", 0.74f, "").Value;
		_pingOffset = new Vector3(value3, value4, 0.102f);
		bool value5 = configRef.Bind<bool>("StatsOverlay", "ShowHealthStamina", true, "").Value;
		bool value6 = configRef.Bind<bool>("StatsOverlay", "ShowSpeed", true, "").Value;
		bool value7 = configRef.Bind<bool>("StatsOverlay", "ShowPing", true, "").Value;
		if (Object.op_Implicit((Object)(object)_hpText))
		{
			((Component)_hpText).gameObject.SetActive(value5);
		}
		if (Object.op_Implicit((Object)(object)_stText))
		{
			((Component)_stText).gameObject.SetActive(value5);
		}
		if (Object.op_Implicit((Object)(object)_spdText))
		{
			((Component)_spdText).gameObject.SetActive(value6);
		}
		if (Object.op_Implicit((Object)(object)_pingText))
		{
			((Component)_pingText).gameObject.SetActive(value7);
		}
		if (Object.op_Implicit((Object)(object)_worldRoot))
		{
			PositionWorldLabels();
		}
	}

	private void PositionWorldLabels()
	{
		//IL_0019: 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_006a: 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)
		if (Object.op_Implicit((Object)(object)_hpText))
		{
			ApplyWorldLabel(((TMP_Text)_hpText).rectTransform, HP_OFFSET, 90f);
		}
		if (Object.op_Implicit((Object)(object)_stText))
		{
			ApplyWorldLabel(((TMP_Text)_stText).rectTransform, ST_OFFSET, 90f);
		}
		if (Object.op_Implicit((Object)(object)_spdText))
		{
			ApplyWorldLabel(((TMP_Text)_spdText).rectTransform, _speedOffset, 90f);
		}
		if (Object.op_Implicit((Object)(object)_pingText))
		{
			ApplyWorldLabel(((TMP_Text)_pingText).rectTransform, _pingOffset, 90f);
		}
	}

	public void ExternalReload()
	{
		_cfg.Reload();
		BuildPingLabel();
		EnsureUI();
		Log("[StatsOverlay] Reloaded config.");
		_localPlayer = null;
		_playerCamera = null;
		_anchor = null;
		SetWorldVisible(on: false);
		_nextProbeAt = 0f;
		_loggedProbeStart = false;
	}

	private void Log(string msg)
	{
		if (_logEnabled.Value)
		{
			if (PluginMain.Log != null)
			{
				PluginMain.Log.LogInfo((object)msg);
			}
			else
			{
				Debug.Log((object)msg);
			}
		}
	}

	private void ProbePlayerCameraAndAnchor()
	{
		//IL_006b: 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)
		EnsureUI();
		if ((Object)(object)_localPlayer == (Object)null)
		{
			GameObject[] array = Object.FindObjectsOfType<GameObject>();
			foreach (GameObject val in array)
			{
				if ((Object)(object)val != (Object)null && ((Object)val).name == "Player(Clone)" && (Object)(object)val.transform.Find("armz") != (Object)null)
				{
					_localPlayer = val;
					_prevPos = _localPlayer.transform.position;
					Log("[StatsOverlay] Local player found.");
					break;
				}
			}
			if ((Object)(object)_localPlayer == (Object)null)
			{
				return;
			}
		}
		if ((Object)(object)_playerCamera == (Object)null)
		{
			_playerCamera = FindPlayerCamera(_localPlayer.transform);
			if (!((Object)(object)_playerCamera != (Object)null))
			{
				return;
			}
			_worldCanvas.worldCamera = _playerCamera;
			Log("[StatsOverlay] Player camera bound.");
		}
		if ((Object)(object)_anchor == (Object)null)
		{
			_anchor = FindRelativeUnder(_localPlayer.transform, "Main Camera/ui/ionknow/Armature/Bone.014");
			if ((Object)(object)_anchor == (Object)null)
			{
				_anchor = FindByNameUnder(_localPlayer.transform, "Bone.014");
			}
			if ((Object)(object)_anchor != (Object)null)
			{
				AttachWorldToAnchor(_anchor);
				SetWorldVisible(on: true);
				Log("[StatsOverlay] Anchored to player's HUD bone.");
			}
		}
	}

	private Camera FindPlayerCamera(Transform playerRoot)
	{
		if ((Object)(object)playerRoot == (Object)null)
		{
			return null;
		}
		Camera[] componentsInChildren = ((Component)playerRoot).GetComponentsInChildren<Camera>(true);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			if ((Object)(object)componentsInChildren[i] != (Object)null && ((Object)componentsInChildren[i]).name == "Main Camera")
			{
				return componentsInChildren[i];
			}
		}
		if (componentsInChildren.Length == 0)
		{
			return null;
		}
		return componentsInChildren[0];
	}

	private Transform FindRelativeUnder(Transform root, string relativePath)
	{
		if ((Object)(object)root == (Object)null || string.IsNullOrEmpty(relativePath))
		{
			return null;
		}
		string[] array = relativePath.Split(new char[1] { '/' });
		Transform val = FindByNameUnder(root, array[0]);
		if ((Object)(object)val == (Object)null)
		{
			return null;
		}
		Transform val2 = val;
		for (int i = 1; i < array.Length; i++)
		{
			val2 = val2.Find(array[i]);
			if ((Object)(object)val2 == (Object)null)
			{
				return null;
			}
		}
		return val2;
	}

	private Transform FindByNameUnder(Transform root, string name)
	{
		if ((Object)(object)root == (Object)null || string.IsNullOrEmpty(name))
		{
			return null;
		}
		Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true);
		foreach (Transform val in componentsInChildren)
		{
			if ((Object)(object)val != (Object)null && ((Object)val).name == name)
			{
				return val;
			}
		}
		return null;
	}

	private void BuildWorldCanvasAndTexts()
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Expected O, but got Unknown
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0119: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("MA_WorldCanvas");
		Object.DontDestroyOnLoad((Object)(object)val);
		_worldCanvas = val.AddComponent<Canvas>();
		_worldCanvas.renderMode = (RenderMode)2;
		_worldCanvas.worldCamera = Camera.main;
		_worldCanvas.planeDistance = 1f;
		_worldCanvas.overrideSorting = true;
		_worldCanvas.sortingOrder = 32767;
		val.AddComponent<CanvasScaler>();
		val.AddComponent<GraphicRaycaster>();
		_worldRoot = val.transform;
		((RectTransform)_worldRoot).sizeDelta = new Vector2(1f, 1f);
		_hpText = MakeTMP(_worldRoot, "HealthText", 16f);
		_stText = MakeTMP(_worldRoot, "StaminaText", 16f);
		_spdText = MakeTMP(_worldRoot, "SpeedText", 16f);
		ApplyWorldLabel(((TMP_Text)_hpText).rectTransform, HP_OFFSET, 90f);
		ApplyWorldLabel(((TMP_Text)_stText).rectTransform, ST_OFFSET, 90f);
		ApplyWorldLabel(((TMP_Text)_spdText).rectTransform, _speedOffset, 90f);
		((TMP_Text)_hpText).text = "HP: --";
		((TMP_Text)_stText).text = "ST: --";
		((TMP_Text)_spdText).text = "0.00 m/s";
	}

	private void EnsureUI()
	{
		if ((Object)(object)_worldCanvas == (Object)null || (Object)(object)_worldRoot == (Object)null || (Object)(object)_hpText == (Object)null || (Object)(object)_stText == (Object)null || (Object)(object)_spdText == (Object)null)
		{
			BuildWorldCanvasAndTexts();
			SetWorldVisible(on: false);
			if ((Object)(object)_playerCamera != (Object)null)
			{
				_worldCanvas.worldCamera = _playerCamera;
			}
			Log("[StatsOverlay] UI rebuilt (EnsureUI).");
		}
	}

	private TextMeshProUGUI MakeTMP(Transform parent, string name, float fontSize)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Expected O, but got Unknown
		//IL_002f: 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_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject(name);
		val.transform.SetParent(parent, false);
		TextMeshProUGUI obj = val.AddComponent<TextMeshProUGUI>();
		((Graphic)obj).color = new Color(1f, 1f, 1f, 0.85f);
		((TMP_Text)obj).alignment = (TextAlignmentOptions)513;
		((TMP_Text)obj).fontSize = fontSize;
		((TMP_Text)obj).enableWordWrapping = false;
		((Graphic)obj).raycastTarget = false;
		((TMP_Text)obj).enableKerning = false;
		Shadow obj2 = val.AddComponent<Shadow>();
		obj2.effectColor = new Color(0f, 0f, 0f, 0.6f);
		obj2.effectDistance = new Vector2(1f, -1f);
		((RectTransform)((TMP_Text)obj).transform).sizeDelta = new Vector2(0.35f, 0.1f);
		return obj;
	}

	private void ApplyWorldLabel(RectTransform rt, Vector3 localPos, float zDeg)
	{
		//IL_0001: 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_001e: 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)
		((Transform)rt).localPosition = localPos;
		((Transform)rt).localRotation = Quaternion.Euler(0f, 0f, zDeg);
		((Transform)rt).localScale = Vector3.one * 0.0012f;
	}

	private void AttachWorldToAnchor(Transform anchor)
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: 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_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: 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)
		_worldRoot.SetParent(anchor, false);
		_worldRoot.localPosition = Vector3.zero;
		_worldRoot.localRotation = Quaternion.Euler(0f, 270f, 0f);
		ApplyWorldLabel(((TMP_Text)_hpText).rectTransform, HP_OFFSET, 90f);
		ApplyWorldLabel(((TMP_Text)_stText).rectTransform, ST_OFFSET, 90f);
		ApplyWorldLabel(((TMP_Text)_spdText).rectTransform, SPEED_OFFSET, 90f);
		if ((Object)(object)_pingText != (Object)null)
		{
			ApplyWorldLabel(((TMP_Text)_pingText).rectTransform, PING_OFFSET, 90f);
		}
		PositionWorldLabels();
	}

	private void SetWorldVisible(bool on)
	{
		if ((Object)(object)_worldRoot != (Object)null && ((Component)_worldRoot).gameObject.activeSelf != on)
		{
			((Component)_worldRoot).gameObject.SetActive(on);
		}
	}

	private void CacheReflection()
	{
		Type typeFromHandle = typeof(PlayerMovement);
		BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
		_fServerHealth = typeFromHandle.GetField("ServerHealth", bindingAttr);
		_fPlayerHealth = typeFromHandle.GetField("playerHealth", bindingAttr);
		_fStamina = typeFromHandle.GetField("stamina", bindingAttr);
		Log("[StatsOverlay] Reflection cached.");
	}

	private void UpdateNumbers()
	{
		//IL_0130: 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_0137: Unknown result type (might be due to invalid IL or missing references)
		//IL_013a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0145: Unknown result type (might be due to invalid IL or missing references)
		//IL_0147: Unknown result type (might be due to invalid IL or missing references)
		PlayerMovement val = (((Object)(object)_localPlayer != (Object)null) ? _localPlayer.GetComponent<PlayerMovement>() : null);
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		float num = ReadFloat(val, _fPlayerHealth);
		if (!(num >= 0f))
		{
			num = ReadFloat(val, _fServerHealth);
		}
		if ((Object)(object)_hpText != (Object)null)
		{
			((TMP_Text)_hpText).text = ((num >= 0f) ? ("HP: " + Mathf.RoundToInt(num)) : "HP: --");
		}
		if ((Object)(object)_stText != (Object)null)
		{
			float num2 = ReadFloat(val, _fStamina);
			if (num2 >= 0f)
			{
				((TMP_Text)_stText).text = "ST: " + Mathf.RoundToInt(Mathf.Clamp(num2 * 10f, 0f, 100f));
			}
			else
			{
				((TMP_Text)_stText).text = "ST: --";
			}
		}
		if ((Object)(object)_spdText != (Object)null)
		{
			float deltaTime = Time.deltaTime;
			if (deltaTime <= 0f)
			{
				((TMP_Text)_spdText).text = "0.00 m/s";
				return;
			}
			Vector3 position = _localPlayer.transform.position;
			float num3 = Vector3.Distance(position, _prevPos);
			_prevPos = position;
			float num4 = num3 / deltaTime;
			((TMP_Text)_spdText).text = num4.ToString("0.00") + " m/s";
		}
		if (!((Object)(object)_pingText != (Object)null) || !(Time.unscaledTime >= _nextPingAt))
		{
			return;
		}
		if (PingReader.TryGetPingMilliseconds(out var pingMs))
		{
			bool num5 = _lastPingMs == int.MinValue || Mathf.Abs(pingMs - _lastPingMs) >= 2;
			bool flag = Time.unscaledTime >= _nextForcePingAt;
			if (num5 || flag)
			{
				((TMP_Text)_pingText).text = "PING: " + pingMs + " ms";
				_lastPingMs = pingMs;
				_nextForcePingAt = Time.unscaledTime + 1f;
			}
		}
		else if (_lastPingMs != int.MinValue)
		{
			((TMP_Text)_pingText).text = "PING: --";
			_lastPingMs = int.MinValue;
		}
		_nextPingAt = Time.unscaledTime + 0.15f;
	}

	private static float ReadFloat(object target, FieldInfo f)
	{
		try
		{
			if (target == null || f == null)
			{
				return -1f;
			}
			return Convert.ToSingle(f.GetValue(target));
		}
		catch
		{
			return -1f;
		}
	}

	private void CleanupUI()
	{
		if ((Object)(object)_hpText != (Object)null)
		{
			Object.Destroy((Object)(object)((Component)_hpText).gameObject);
		}
		if ((Object)(object)_stText != (Object)null)
		{
			Object.Destroy((Object)(object)((Component)_stText).gameObject);
		}
		if ((Object)(object)_spdText != (Object)null)
		{
			Object.Destroy((Object)(object)((Component)_spdText).gameObject);
		}
		_hpText = (_stText = (_spdText = null));
		if ((Object)(object)_pingText != (Object)null)
		{
			Object.Destroy((Object)(object)((Component)_pingText).gameObject);
		}
		_pingText = null;
		if ((Object)(object)_worldCanvas != (Object)null)
		{
			Object.Destroy((Object)(object)((Component)_worldCanvas).gameObject);
		}
		_worldCanvas = null;
		_worldRoot = null;
		_anchor = null;
		_playerCamera = null;
	}

	private void BuildPingLabel()
	{
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)_worldRoot == (Object)null))
		{
			if ((Object)(object)_pingText == (Object)null)
			{
				_pingText = MakeTMP(_worldRoot, "PingText", 16f);
			}
			ApplyWorldLabel(((TMP_Text)_pingText).rectTransform, _pingOffset, 90f);
			((TMP_Text)_pingText).text = "PING: --";
		}
	}
}
internal static class PingReader
{
	private static readonly BindingFlags F = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

	private static object _target;

	private static FieldInfo _f;

	private static PropertyInfo _p;

	private static bool _initialized;

	private static bool _failed;

	public static bool TryGetPingMilliseconds(out int pingMs)
	{
		if (!_initialized && !_failed)
		{
			Init();
		}
		if (_target != null)
		{
			double raw = -1.0;
			try
			{
				if (_f != null)
				{
					raw = ToDouble(_f.GetValue(_target));
				}
				else if (_p != null)
				{
					raw = ToDouble(_p.GetValue(_target, null));
				}
			}
			catch
			{
				raw = -1.0;
			}
			pingMs = NormalizeToMs(raw);
			return pingMs >= 0;
		}
		pingMs = -1;
		return false;
	}

	private static void Init()
	{
		_initialized = true;
		if (!FindFishNetProvider() && !FindDissonanceProvider())
		{
			_failed = true;
		}
	}

	private static bool FindFishNetProvider()
	{
		Type type = Type.GetType("FishNet.Managing.NetworkManager, FishNet.Runtime");
		if (type == null)
		{
			return false;
		}
		Object[] array = Object.FindObjectsOfType(type, true);
		if (array == null || array.Length == 0)
		{
			return false;
		}
		Object[] array2 = array;
		foreach (Object val in array2)
		{
			object[] array3 = new object[5]
			{
				val,
				GetMember(val, "TimeManager"),
				GetMember(val, "ClientManager"),
				GetMember(val, "TransportManager"),
				GetMember(GetMember(val, "TransportManager"), "Transport")
			};
			for (int j = 0; j < array3.Length; j++)
			{
				if (TryBindPingMember(array3[j]))
				{
					return true;
				}
			}
		}
		return false;
	}

	private static bool FindDissonanceProvider()
	{
		Type type = Type.GetType("Dissonance.DissonanceComms, Dissonance");
		if (type == null)
		{
			return false;
		}
		Object val = Object.FindObjectOfType(type, true);
		if (val == (Object)null)
		{
			return false;
		}
		object[] array = new object[4]
		{
			val,
			GetMember(val, "Network"),
			GetMember(val, "Diagnostics"),
			GetMember(val, "CommsNetwork")
		};
		for (int i = 0; i < array.Length; i++)
		{
			if (TryBindPingMember(array[i]))
			{
				return true;
			}
		}
		return false;
	}

	private static object GetMember(object target, string name)
	{
		if (target == null)
		{
			return null;
		}
		Type type = target.GetType();
		FieldInfo field = type.GetField(name, F);
		if (field != null)
		{
			try
			{
				return field.GetValue(target);
			}
			catch
			{
			}
		}
		PropertyInfo property = type.GetProperty(name, F);
		if (property != null && property.CanRead)
		{
			try
			{
				return property.GetValue(target, null);
			}
			catch
			{
			}
		}
		return null;
	}

	private static bool TryBindPingMember(object target)
	{
		if (target == null)
		{
			return false;
		}
		Type type = target.GetType();
		FieldInfo[] fields = type.GetFields(F);
		foreach (FieldInfo fieldInfo in fields)
		{
			if (LooksLikePingKey(fieldInfo.Name) && IsNumeric(fieldInfo.FieldType))
			{
				_target = target;
				_f = fieldInfo;
				_p = null;
				return true;
			}
		}
		PropertyInfo[] properties = type.GetProperties(F);
		foreach (PropertyInfo propertyInfo in properties)
		{
			if (propertyInfo.CanRead && LooksLikePingKey(propertyInfo.Name) && IsNumeric(propertyInfo.PropertyType))
			{
				_target = target;
				_p = propertyInfo;
				_f = null;
				return true;
			}
		}
		return false;
	}

	private static bool LooksLikePingKey(string name)
	{
		string text = name.ToLowerInvariant();
		if (!text.Contains("ping") && !text.Contains("rtt") && !text.Contains("roundtrip"))
		{
			return text.Contains("latency");
		}
		return true;
	}

	private static bool IsNumeric(Type t)
	{
		if (!(t == typeof(int)) && !(t == typeof(long)) && !(t == typeof(float)))
		{
			return t == typeof(double);
		}
		return true;
	}

	private static double ToDouble(object o)
	{
		if (o == null)
		{
			return -1.0;
		}
		try
		{
			return Convert.ToDouble(o);
		}
		catch
		{
			return -1.0;
		}
	}

	private static int NormalizeToMs(double raw)
	{
		if (raw < 0.0)
		{
			return -1;
		}
		if (raw < 1.5)
		{
			raw *= 1000.0;
		}
		if (raw > 100000.0 || double.IsNaN(raw))
		{
			return -1;
		}
		return (int)Math.Round(raw);
	}
}
[BepInPlugin("com.j7.additional.ui", "AdditionalUI", "1.0.0")]
public class PluginMain : BaseUnityPlugin
{
	private Harmony _harmony;

	internal static ConfigFile ConfigRef;

	public static ManualLogSource Log { get; private set; }

	private void Awake()
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		ConfigRef = ((BaseUnityPlugin)this).Config;
		_harmony = new Harmony("com.j7.additional.ui");
		StatsOverlayBootstrap.Ensure();
		SettingsMenu.CreateOrGet();
		Log.LogInfo((object)"AdditionalUI loaded.");
	}

	private void OnDestroy()
	{
		Harmony harmony = _harmony;
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
	}
}
internal static class StatsOverlayBootstrap
{
	private static GameObject _root;

	public static StatsOverlay Instance { get; private set; }

	public static void Ensure()
	{
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Expected O, but got Unknown
		if ((Object)(object)Instance != (Object)null)
		{
			return;
		}
		if ((Object)(object)_root == (Object)null)
		{
			_root = GameObject.Find("AdditionalUI.Root");
			if ((Object)(object)_root == (Object)null)
			{
				_root = new GameObject("AdditionalUI.Root");
				Object.DontDestroyOnLoad((Object)(object)_root);
			}
		}
		Instance = _root.GetComponent<StatsOverlay>();
		if ((Object)(object)Instance == (Object)null)
		{
			Instance = _root.AddComponent<StatsOverlay>();
			ManualLogSource log = PluginMain.Log;
			if (log != null)
			{
				log.LogInfo((object)"[StatsOverlayBootstrap] StatsOverlay component added.");
			}
		}
	}
}