using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using Character;
using DisputeLib;
using HarmonyLib;
using Player;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("AGDDebugHUD")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+d64b7691c3c7461419fce52522e421ee733440f6")]
[assembly: AssemblyProduct("AGDDebugHUD")]
[assembly: AssemblyTitle("AGDDebugHUD")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace AGDDebugHUD;
[HarmonyPatch]
public static class DebugHUDInjector
{
[HarmonyPatch(typeof(GameSingleton), "Awake")]
[HarmonyPostfix]
private static void InjectDebugHUD()
{
//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)GameObject.Find("AGD_DebugHUD") != (Object)null))
{
GameObject val = new GameObject("AGD_DebugHUD");
Object.DontDestroyOnLoad((Object)val);
val.AddComponent<DebugHUDBehaviour>();
Debug.Log((object)"[[AGDDebugHUD]] Debug HUD injected successfully.");
}
}
}
public class DebugHUDBehaviour : MonoBehaviour
{
private Canvas _canvas;
private GameObject _panel;
private PlayerController _localPlayer;
private CoreCharacterController _characterController;
private CharacterMovementController _characterMovementController;
private RagdollController _characterRagdollController;
private Stopwatch HUDTimeStopwatch = new Stopwatch();
public double HUDTimeMs;
private void Awake()
{
if (!Plugin.EnabledConfig.Value)
{
((Behaviour)this).enabled = false;
return;
}
RegisterDefaultLines();
CreateUI();
}
private void EnsureControllers()
{
if (((Object)(object)_localPlayer != (Object)null && (Object)(object)_characterController != (Object)null && (Object)(object)_characterMovementController != (Object)null && (Object)(object)_characterRagdollController != (Object)null) || (Object)(object)SessionManager.Instance == (Object)null)
{
return;
}
_localPlayer = SessionManager.Instance.LocalPlayer;
if (!((Object)(object)_localPlayer == (Object)null))
{
_characterController = _localPlayer.serverSpawnedCharacter;
if ((Object)(object)_characterController != (Object)null)
{
_characterMovementController = ((Component)_characterController).GetComponent<CharacterMovementController>();
_characterRagdollController = _characterController.Model.RagdollController;
}
}
}
private void RegisterDefaultLines()
{
if (Plugin.EnableGameSectionConfig.Value)
{
DebugHUDAPI.Header header = DebugHUDAPI.RegisterHeader("--- Game ---");
if (Plugin.EnableFPSConfig.Value)
{
DebugHUDAPI.RegisterCustomLine("FPS", () => $"Frame time: {Time.deltaTime * 1000f:F1}ms FPS: {1f / Time.deltaTime:F2}", header);
}
if (Plugin.EnableHUDFPSConfig.Value)
{
DebugHUDAPI.RegisterCustomLine("HUD Time", () => $"HUD time: {HUDTimeMs:F3}ms FPS impact: {1.0 / ((double)Time.deltaTime - HUDTimeMs / 1000.0) - (double)(1f / Time.deltaTime):F2}", header);
}
}
if (Plugin.EnableNetworkSectionConfig.Value)
{
DebugHUDAPI.Header header2 = DebugHUDAPI.RegisterHeader("--- Network ---");
if (Plugin.EnablePingConfig.Value)
{
DebugHUDAPI.RegisterCustomLine("Ping", delegate
{
EnsureControllers();
return ((Object)(object)_localPlayer == (Object)null) ? null : $"Ping: {_localPlayer.CurrentPing.Value}";
}, header2);
}
}
if (Plugin.EnableMovementSectionConfig.Value)
{
DebugHUDAPI.Header header3 = DebugHUDAPI.RegisterHeader("--- Movement ---");
if (Plugin.EnableVelocityConfig.Value)
{
DebugHUDAPI.RegisterCustomLine("Velocity", delegate
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
EnsureControllers();
if ((Object)(object)_characterMovementController == (Object)null)
{
return (string)null;
}
Vector3 velocity = _characterMovementController.Velocity;
return $"Velocity: {((Vector3)(ref velocity)).magnitude:F2} m/s (X:{velocity.x:F2} Y:{velocity.y:F2} Z:{velocity.z:F2})";
}, header3);
}
if (Plugin.EnablePositionConfig.Value)
{
DebugHUDAPI.RegisterCustomLine("Position", delegate
{
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: 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_0042: Unknown result type (might be due to invalid IL or missing references)
EnsureControllers();
if ((Object)(object)_characterMovementController == (Object)null)
{
return (string)null;
}
Vector3 position = ((Component)_characterMovementController).transform.position;
return $"Position: ({position.x:F2}, {position.y:F2}, {position.z:F2})";
}, header3);
}
}
if (Plugin.EnablePhysicsSectionConfig.Value)
{
DebugHUDAPI.Header header4 = DebugHUDAPI.RegisterHeader("--- Physics ---");
if (Plugin.EnableRagdollStateConfig.Value)
{
DebugHUDAPI.RegisterCustomLine("Ragdoll State", delegate
{
EnsureControllers();
return ((Object)(object)_characterRagdollController == (Object)null) ? null : $"IsRagdoll: {_characterRagdollController.IsRagdollNetworked.Value} TimeInRagdollState: {_characterRagdollController.TimeInRagdollState.Elapsed}";
}, header4);
}
}
if (!Plugin.EnableStatusSectionConfig.Value)
{
return;
}
DebugHUDAPI.Header header5 = DebugHUDAPI.RegisterHeader("--- Status ---");
if (Plugin.EnableStateConfig.Value)
{
DebugHUDAPI.RegisterCustomLine("State", delegate
{
EnsureControllers();
return ((Object)(object)_characterController == (Object)null) ? null : string.Format("Grounded: {0} Aiming: {1} Alive: {2} NoClip: {3}", ((Object)(object)_characterMovementController != (Object)null) ? _characterMovementController.IsGroundedNetworked.Value.ToString() : "?", _characterController.IsAiming, _characterController.IsAlive, _localPlayer.NoClip);
}, header5);
}
if (!Plugin.EnableStatusEffectsConfig.Value)
{
return;
}
DebugHUDAPI.RegisterCustomLine("Status Effects", delegate
{
EnsureControllers();
if ((Object)(object)_characterController == (Object)null)
{
return (string)null;
}
StatusEffectController statusEffectController = _characterController.statusEffectController;
if ((Object)(object)statusEffectController != (Object)null && statusEffectController.StatusEffects != null)
{
string[] array = (from e in (IEnumerable<StatusEffectData>)statusEffectController.StatusEffects
where e != null
select ((object)Unsafe.As<StatusEffect, StatusEffect>(ref e.Effect)/*cast due to .constrained prefix*/).ToString()).ToArray();
return string.Format("Status Effects ({0}): {1}", array.Length, (array.Length != 0) ? string.Join(", ", array) : "none");
}
return "Status Effects (0): none";
}, header5);
}
private void CreateUI()
{
//IL_0049: 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_00a9: Expected O, but got Unknown
//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
//IL_0100: Unknown result type (might be due to invalid IL or missing references)
//IL_0114: Unknown result type (might be due to invalid IL or missing references)
//IL_013d: Unknown result type (might be due to invalid IL or missing references)
//IL_0159: Unknown result type (might be due to invalid IL or missing references)
//IL_0163: Expected O, but got Unknown
_canvas = ((Component)this).gameObject.AddComponent<Canvas>();
_canvas.renderMode = (RenderMode)0;
_canvas.sortingOrder = 32767;
CanvasScaler obj = ((Component)this).gameObject.AddComponent<CanvasScaler>();
obj.uiScaleMode = (ScaleMode)1;
obj.referenceResolution = new Vector2(1920f, 1080f);
((Component)this).gameObject.AddComponent<GraphicRaycaster>();
_panel = new GameObject("Panel", new Type[4]
{
typeof(RectTransform),
typeof(Image),
typeof(VerticalLayoutGroup),
typeof(ContentSizeFitter)
});
_panel.transform.SetParent(((Component)this).transform, false);
RectTransform component = _panel.GetComponent<RectTransform>();
component.anchorMin = new Vector2(0f, 1f);
component.anchorMax = new Vector2(0f, 1f);
component.pivot = new Vector2(0f, 1f);
component.anchoredPosition = new Vector2(10f, -10f);
((Graphic)_panel.GetComponent<Image>()).color = new Color(0f, 0f, 0f, 0.6f);
VerticalLayoutGroup component2 = _panel.GetComponent<VerticalLayoutGroup>();
((LayoutGroup)component2).padding = new RectOffset(10, 10, 6, 6);
((HorizontalOrVerticalLayoutGroup)component2).spacing = 2f;
((LayoutGroup)component2).childAlignment = (TextAnchor)0;
((HorizontalOrVerticalLayoutGroup)component2).childControlWidth = true;
((HorizontalOrVerticalLayoutGroup)component2).childControlHeight = true;
ContentSizeFitter component3 = _panel.GetComponent<ContentSizeFitter>();
component3.horizontalFit = (FitMode)2;
component3.verticalFit = (FitMode)2;
DebugHUDAPI.Initialize(_panel, 14f);
}
private void Update()
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
if (Input.GetKeyDown(Plugin.ToggleKeyConfig.Value))
{
_panel.SetActive(!_panel.activeSelf);
}
if (_panel.activeSelf)
{
HUDTimeStopwatch.Restart();
DebugHUDAPI.RefreshAll();
HUDTimeStopwatch.Stop();
HUDTimeMs = HUDTimeStopwatch.Elapsed.TotalMilliseconds;
}
}
}
public static class DebugHUDAPI
{
public class CustomLineEntry
{
public enum State
{
Enabled,
Frozen,
Disabled
}
public string Label;
public TextMeshProUGUI Tmp;
public Func<string> Getter;
public State CurrentState;
}
public class Header
{
public string Label;
internal TextMeshProUGUI Tmp;
}
private static readonly Header _defaultHeader = new Header();
private static readonly Dictionary<Header, List<CustomLineEntry>> _lines = new Dictionary<Header, List<CustomLineEntry>>();
private static readonly Dictionary<string, Header> _headerByLabel = new Dictionary<string, Header>();
private static readonly Dictionary<string, CustomLineEntry> _entryByLabel = new Dictionary<string, CustomLineEntry>();
private static GameObject _panel;
private static float _fontSize;
private static bool _initialized;
public static void RegisterCustomLine(string label, Func<string> getter, Header header = null)
{
if (header == null)
{
header = _defaultHeader;
}
Header header2 = null;
if (_entryByLabel.TryGetValue(label, out var value))
{
value.Getter = getter;
foreach (KeyValuePair<Header, List<CustomLineEntry>> line in _lines)
{
if (line.Value.Remove(value))
{
header2 = line.Key;
break;
}
}
}
else
{
value = new CustomLineEntry
{
Label = label,
Getter = getter
};
_entryByLabel[label] = value;
}
if (!_lines.ContainsKey(header))
{
_lines[header] = new List<CustomLineEntry>();
}
_lines[header].Add(value);
if (_initialized && (Object)(object)_panel != (Object)null)
{
if ((Object)(object)value.Tmp == (Object)null)
{
value.Tmp = CreateLineInternal(_panel, label, _fontSize, isHeader: false);
}
else if (header2 != null && header2 != header)
{
Object.Destroy((Object)(object)((Component)value.Tmp).gameObject);
value.Tmp = CreateLineInternal(_panel, label, _fontSize, isHeader: false);
}
}
}
public static Header RegisterHeader(string label)
{
if (_headerByLabel.TryGetValue(label, out var value))
{
return value;
}
value = new Header
{
Label = label
};
_headerByLabel[label] = value;
_lines[value] = new List<CustomLineEntry>();
if (_initialized && (Object)(object)_panel != (Object)null)
{
value.Tmp = CreateLineInternal(_panel, label, _fontSize, isHeader: true);
}
return value;
}
public static void EnableLine(string label)
{
SetLineState(label, CustomLineEntry.State.Enabled);
}
public static void DisableLine(string label)
{
SetLineState(label, CustomLineEntry.State.Disabled);
}
public static void FreezeLine(string label)
{
SetLineState(label, CustomLineEntry.State.Frozen);
}
public static void SetLineState(string label, CustomLineEntry.State state)
{
if (_entryByLabel.TryGetValue(label, out var value))
{
value.CurrentState = state;
}
}
public static void Initialize(GameObject panel, float fontSize)
{
_panel = panel;
_fontSize = fontSize;
_initialized = true;
foreach (KeyValuePair<Header, List<CustomLineEntry>> line in _lines)
{
Header key = line.Key;
if (key != _defaultHeader && (Object)(object)key.Tmp == (Object)null)
{
key.Tmp = CreateLineInternal(panel, key.Label, fontSize, isHeader: true);
}
foreach (CustomLineEntry item in line.Value)
{
if ((Object)(object)item.Tmp == (Object)null)
{
item.Tmp = CreateLineInternal(panel, item.Label, fontSize, isHeader: false);
}
}
}
}
public static void RefreshAll()
{
foreach (KeyValuePair<Header, List<CustomLineEntry>> line in _lines)
{
Header key = line.Key;
if (key != _defaultHeader && (Object)(object)key.Tmp != (Object)null)
{
((TMP_Text)key.Tmp).text = key.Label;
}
foreach (CustomLineEntry item in line.Value)
{
if ((Object)(object)item.Tmp == (Object)null)
{
continue;
}
switch (item.CurrentState)
{
case CustomLineEntry.State.Disabled:
((Component)item.Tmp).gameObject.SetActive(false);
continue;
case CustomLineEntry.State.Frozen:
continue;
}
string text = item.Getter?.Invoke();
bool flag = text != null;
if (flag)
{
((TMP_Text)item.Tmp).text = text;
}
((Component)item.Tmp).gameObject.SetActive(flag);
}
}
}
private static TextMeshProUGUI CreateLineInternal(GameObject parent, string name, float fontSize, bool isHeader)
{
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Expected O, but got Unknown
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
GameObject val = new GameObject(name, new Type[2]
{
typeof(RectTransform),
typeof(TextMeshProUGUI)
});
val.transform.SetParent(parent.transform, false);
TextMeshProUGUI component = val.GetComponent<TextMeshProUGUI>();
((TMP_Text)component).text = name;
((TMP_Text)component).fontSize = fontSize;
((TMP_Text)component).fontStyle = (FontStyles)(isHeader ? 1 : 0);
((Graphic)component).color = (Color)(isHeader ? new Color(1f, 0.85f, 0.3f) : Color.white);
((Graphic)component).raycastTarget = false;
val.AddComponent<LayoutElement>().minHeight = fontSize + 4f;
return component;
}
}
[BepInPlugin("com.unii.debugHud", "Debug HUD", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
public static ConfigEntry<bool> EnabledConfig;
public static ConfigEntry<KeyCode> ToggleKeyConfig;
public static ConfigEntry<bool> EnableGameSectionConfig;
public static ConfigEntry<bool> EnableFPSConfig;
public static ConfigEntry<bool> EnableHUDFPSConfig;
public static ConfigEntry<bool> EnableNetworkSectionConfig;
public static ConfigEntry<bool> EnablePingConfig;
public static ConfigEntry<bool> EnableMovementSectionConfig;
public static ConfigEntry<bool> EnableVelocityConfig;
public static ConfigEntry<bool> EnablePositionConfig;
public static ConfigEntry<bool> EnablePhysicsSectionConfig;
public static ConfigEntry<bool> EnableRagdollStateConfig;
public static ConfigEntry<bool> EnableStatusSectionConfig;
public static ConfigEntry<bool> EnableStateConfig;
public static ConfigEntry<bool> EnableStatusEffectsConfig;
private void Awake()
{
//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
EnabledConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable or disable the Debug HUD overlay.");
ToggleKeyConfig = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "ToggleKey", (KeyCode)284, "Key to toggle the debug HUD on/off.");
EnableGameSectionConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("DefaultLines", "EnableGameSection", true, "Enable the values under the Game header. Overrides EnableFPS and EnableHUDFPS.");
EnableFPSConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("DefaultLines", "EnableFPS", true, "Enable showing FPS and frame time under the Game header.");
EnableHUDFPSConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("DefaultLines", "EnableHUDFPS", true, "Enable showing HUD specific frame time and FPS impact under the Game header.");
EnableNetworkSectionConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("DefaultLines", "EnableNetworkSection", true, "Enable the values under the Network header. Overrides EnablePing.");
EnablePingConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("DefaultLines", "EnablePing", true, "Enable showing Ping under the Network header.");
EnableMovementSectionConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("DefaultLines", "EnableMovementSection", true, "Enable the values under the Movement header. Overrides EnableVelocity and EnablePosition.");
EnableVelocityConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("DefaultLines", "EnableVelocity", true, "Enable showing player velocity under the Movement header.");
EnablePositionConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("DefaultLines", "EnablePosition", true, "Enable showing player coordinates under the Movement header.");
EnablePhysicsSectionConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("DefaultLines", "EnablePhysicsSection", true, "Enable the values under the Physics header. Overrides EnableRagdollState.");
EnableRagdollStateConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("DefaultLines", "EnableRagdollState", true, "Enable showing the player's ragdoll state under the Physics header.");
EnableStatusSectionConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("DefaultLines", "EnableStatusSection", true, "Enable the values under the Status header. Overrides EnableState and EnableStatusEffects.");
EnableStateConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("DefaultLines", "EnableState", true, "Enable showing the player's current state under the Status header.");
EnableStatusEffectsConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("DefaultLines", "EnableStatusEffects", true, "Enable showing active status effects under the Status header.");
((BaseUnityPlugin)this).Logger.LogInfo((object)"Debug HUD plugin loaded successfully!");
new Harmony("com.unii.debugHud").PatchAll();
}
}