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.");
}
}
}
}