using System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("denism")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0+10ad34c91fdf1785044db95fcc62ef0ea66f33d8")] [assembly: AssemblyProduct("DenisUIFpsCounter")] [assembly: AssemblyTitle("DenisUIFpsCounter")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace DenisUIFpsCounter { [BepInPlugin("denis.repo.denisuifpscounter", "Denis UI FPSCounter", "0.1.1")] public class FpsCounterPlugin : BaseUnityPlugin { private enum CounterPosition { Left, Right } private enum CounterColor { Yellow, Neutral } private const string PluginGuid = "denis.repo.denisuifpscounter"; private const string PluginName = "Denis UI FPSCounter"; private const string PluginVersion = "0.1.1"; private const float Margin = 18f; private const float Smoothing = 0.04f; private const float MainFpsSmoothing = 0.18f; private const float StatusHoldDuration = 2.25f; private static FpsCounterPlugin? _instance; private ConfigEntry _enabled = null; private ConfigEntry _position = null; private ConfigEntry _textSize = null; private ConfigEntry _textColor = null; private ConfigEntry _showMsAndAvg = null; private ConfigEntry _showStatus = null; private GUIStyle _basicValueStyle = null; private GUIStyle _telemetryValueStyle = null; private GUIStyle _telemetryMetaStyle = null; private GUIStyle _telemetryStatusStyle = null; private Rect _rect; private float _smoothedDeltaTime; private float _currentDeltaTime; private float _worstFrameMs; private float _windowElapsed; private float _statusHoldTimer; private float _displayFps; private string _telemetryValueText = string.Empty; private string _maxText = string.Empty; private string _avgText = string.Empty; private string _statusText = string.Empty; private string _latchedStatusText = string.Empty; private int _screenWidth; private int _screenHeight; private CounterPosition _lastPosition; private float _lastTextSize; private bool _lastShowMsAndAvg; private bool _lastShowStatus; private void Awake() { //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Expected O, but got Unknown if ((Object)(object)_instance != (Object)null && (Object)(object)_instance != (Object)(object)this) { Object.Destroy((Object)(object)this); return; } _instance = this; ((Component)this).gameObject.transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); _enabled = ((BaseUnityPlugin)this).Config.Bind("General", "FPS Counter", true, "Turn the FPS counter on or off."); _position = ((BaseUnityPlugin)this).Config.Bind("General", "Position", CounterPosition.Right, "Choose Left or Right."); _textSize = ((BaseUnityPlugin)this).Config.Bind("General", "Text Size", 1f, new ConfigDescription("Scale the text size. 1.0 is the default maximum size.", (AcceptableValueBase)(object)new AcceptableValueRange(0.35f, 1f), Array.Empty())); _textColor = ((BaseUnityPlugin)this).Config.Bind("General", "Text Color", CounterColor.Yellow, "Choose Yellow or Neutral."); _showMsAndAvg = ((BaseUnityPlugin)this).Config.Bind("Telemetry", "Show MS & AVG FPS", false, "Show frame time and average FPS details."); _showStatus = ((BaseUnityPlugin)this).Config.Bind("Telemetry", "Show Status", false, "Show human-readable performance warnings."); _smoothedDeltaTime = Time.unscaledDeltaTime; _currentDeltaTime = Time.unscaledDeltaTime; _worstFrameMs = _currentDeltaTime * 1000f; _displayFps = ((_currentDeltaTime > 0f) ? (1f / _currentDeltaTime) : 0f); _lastPosition = _position.Value; _lastTextSize = _textSize.Value; _lastShowMsAndAvg = _showMsAndAvg.Value; _lastShowStatus = _showStatus.Value; RecalculateRect(); } private void Update() { if (!_enabled.Value) { return; } _currentDeltaTime = Time.unscaledDeltaTime; float num = _currentDeltaTime * 1000f; _windowElapsed += _currentDeltaTime; _worstFrameMs = Mathf.Max(_worstFrameMs, num); if (_windowElapsed >= 0.35f) { _windowElapsed = 0f; _worstFrameMs = num; } _smoothedDeltaTime += (_currentDeltaTime - _smoothedDeltaTime) * 0.04f; float num2 = ((_currentDeltaTime > 0f) ? (1f / _currentDeltaTime) : 0f); _displayFps += (num2 - _displayFps) * 0.18f; float num3 = ((_smoothedDeltaTime > 0f) ? (1f / _smoothedDeltaTime) : 0f); _statusText = ResolveStatusText(num, _worstFrameMs); if (!string.IsNullOrWhiteSpace(_statusText)) { _latchedStatusText = _statusText; _statusHoldTimer = 2.25f; } else if (_statusHoldTimer > 0f) { _statusHoldTimer -= _currentDeltaTime; if (_statusHoldTimer <= 0f) { _statusHoldTimer = 0f; _latchedStatusText = string.Empty; } } _telemetryValueText = Mathf.RoundToInt(_displayFps).ToString(); _maxText = $"Max: {_worstFrameMs:0.0} ms"; _avgText = $"AVG: {Mathf.RoundToInt(num3)} FPS"; if (_screenWidth != Screen.width || _screenHeight != Screen.height || _lastPosition != _position.Value || !Mathf.Approximately(_lastTextSize, _textSize.Value) || _lastShowMsAndAvg != _showMsAndAvg.Value || _lastShowStatus != _showStatus.Value) { _lastPosition = _position.Value; _lastTextSize = _textSize.Value; _lastShowMsAndAvg = _showMsAndAvg.Value; _lastShowStatus = _showStatus.Value; RecalculateRect(); } } private void OnGUI() { //IL_0031: Unknown result type (might be due to invalid IL or missing references) if (_enabled.Value) { if (!_showMsAndAvg.Value) { BuildBasicStyleIfNeeded(); GUI.Label(_rect, _telemetryValueText, _basicValueStyle); } else { BuildTelemetryStylesIfNeeded(); DrawTelemetryHud(); } } } private void BuildBasicStyleIfNeeded() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Clamp(_textSize.Value, 0.35f, 1f); TextAnchor alignment = (TextAnchor)((_position.Value != 0) ? 2 : 0); int fontSize = Mathf.RoundToInt(34f * num); _basicValueStyle = BuildStyle(_basicValueStyle, fontSize, alignment, ResolveMainColor()); } private void BuildTelemetryStylesIfNeeded() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Clamp(_textSize.Value, 0.35f, 1f); TextAnchor alignment = (TextAnchor)((_position.Value != 0) ? 2 : 0); _telemetryValueStyle = BuildStyle(_telemetryValueStyle, Mathf.RoundToInt(34f * num), alignment, ResolveMainColor()); _telemetryMetaStyle = BuildStyle(_telemetryMetaStyle, Mathf.RoundToInt(18f * num), alignment, ResolveMetaColor()); _telemetryStatusStyle = BuildStyle(_telemetryStatusStyle, Mathf.RoundToInt(18f * num), alignment, ResolveStatusColor()); } private GUIStyle BuildStyle(GUIStyle existing, int fontSize, TextAnchor alignment, Color color) { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: 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_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0064: 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) if (existing != null) { Color textColor = existing.normal.textColor; if (existing.fontSize == fontSize && existing.alignment == alignment && Mathf.Approximately(textColor.r, color.r) && Mathf.Approximately(textColor.g, color.g) && Mathf.Approximately(textColor.b, color.b) && Mathf.Approximately(textColor.a, color.a)) { return existing; } } GUIStyle val = new GUIStyle(GUI.skin.label) { alignment = alignment, fontSize = fontSize, fontStyle = (FontStyle)1, richText = true, wordWrap = false, clipping = (TextClipping)0 }; val.normal.textColor = color; val.hover.textColor = color; val.active.textColor = color; val.focused.textColor = color; return val; } private void DrawTelemetryHud() { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Clamp(_textSize.Value, 0.35f, 1f); float num2 = 40f * num; float num3 = 24f * num; float num4 = 24f * num; float num5 = 2f * num; Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref _rect)).x, ((Rect)(ref _rect)).y, ((Rect)(ref _rect)).width, num2); GUI.Label(val, _telemetryValueText, _telemetryValueStyle); if (_showMsAndAvg.Value) { Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(((Rect)(ref _rect)).x, ((Rect)(ref _rect)).y + num2 + num5, ((Rect)(ref _rect)).width, num3); GUI.Label(val2, BuildMetaRichText(), _telemetryMetaStyle); if (_showStatus.Value && !string.IsNullOrWhiteSpace(_latchedStatusText)) { Rect val3 = default(Rect); ((Rect)(ref val3))..ctor(((Rect)(ref _rect)).x, ((Rect)(ref _rect)).y + num2 + num3 + num5 * 2f, ((Rect)(ref _rect)).width, num4); GUI.Label(val3, _latchedStatusText, _telemetryStatusStyle); } } } private string BuildMetaRichText() { //IL_0032: 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_004a: Unknown result type (might be due to invalid IL or missing references) if (_textColor.Value == CounterColor.Neutral) { return _maxText + " | " + _avgText; } string text = ColorUtility.ToHtmlStringRGBA(ResolveMaxColor()); string text2 = ColorUtility.ToHtmlStringRGBA(ResolveAvgColor()); string text3 = ColorUtility.ToHtmlStringRGBA(ResolveMetaColor()); return "" + _maxText + " | " + _avgText + ""; } private void RecalculateRect() { //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) _screenWidth = Screen.width; _screenHeight = Screen.height; float num = Mathf.Clamp(_textSize.Value, 0.35f, 1f); bool value = _showMsAndAvg.Value; bool flag = _showStatus.Value && !string.IsNullOrWhiteSpace(_latchedStatusText); float num2 = (value ? 430f : 180f) * num; float num3 = (value ? ((flag ? 112f : 84f) * num) : (48f * num)); float num4 = ((_position.Value == CounterPosition.Left) ? 18f : ((float)_screenWidth - num2 - 18f)); float num5 = 18f; _rect = new Rect(num4, num5, num2, num3); } private Color ResolveMainColor() { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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) if (_textColor.Value == CounterColor.Neutral) { return new Color(1f, 1f, 1f, 0.4f); } return new Color(1f, 0.88f, 0.14f, 1f); } private Color ResolveMetaColor() { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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) if (_textColor.Value == CounterColor.Neutral) { return new Color(1f, 1f, 1f, 0.4f); } return new Color(1f, 0.88f, 0.14f, 0.92f); } private Color ResolveMaxColor() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_008a: 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) if (_textColor.Value == CounterColor.Neutral) { return new Color(1f, 1f, 1f, 0.4f); } if (_worstFrameMs >= 33f) { return new Color(1f, 0.35f, 0.32f, 1f); } if (_worstFrameMs >= 25f) { return new Color(1f, 0.72f, 0.28f, 1f); } return new Color(1f, 0.88f, 0.14f, 1f); } private Color ResolveAvgColor() { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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) if (_textColor.Value == CounterColor.Neutral) { return new Color(1f, 1f, 1f, 0.4f); } return new Color(1f, 0.88f, 0.14f, 1f); } private Color ResolveStatusColor() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) if (_textColor.Value == CounterColor.Neutral) { return new Color(1f, 1f, 1f, 0.4f); } if (_worstFrameMs >= 33f) { return new Color(1f, 0.35f, 0.32f, 1f); } return new Color(1f, 0.72f, 0.28f, 1f); } private string ResolveStatusText(float currentMs, float worstMs) { if (worstMs >= 33f) { return $"Slow frame pacing: {worstMs:0.0} ms"; } if (worstMs >= 25f) { return $"Heavy frame spike: {worstMs:0.0} ms"; } return string.Empty; } } }