Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of FPSCounter v1.0.5
FPSCounter.dll
Decompiled 2 weeks agousing System; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using MelonLoader; using MelonLoader.Preferences; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: MelonInfo(typeof(FPSCounter), "FPS Counter", "1.0.5", "DiumStream", null)] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: AssemblyMetadata("NexusModID", "737")] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyVersion("0.0.0.0")] 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; } } } public class FPSCounter : MelonMod { private GameObject? _uiRoot; private Text? _fpsText; private RectTransform? _bgRect; private float _smoothedFps; private float _currentFps; public override void OnInitializeMelon() { try { Application.targetFrameRate = -1; Config.Load(); InitializeUI(); MelonLogger.Msg("FPS Counter initialisé !"); } catch (Exception value) { MelonLogger.Error($"Erreur initialisation: {value}"); } } private void InitializeUI() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0051: 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_0067: Expected O, but got Unknown //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Expected O, but got Unknown //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0181: 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_018a: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) try { _uiRoot = new GameObject("FPS_Canvas"); Canvas val = _uiRoot.AddComponent<Canvas>(); val.renderMode = (RenderMode)0; val.sortingOrder = 9999; CanvasScaler val2 = _uiRoot.AddComponent<CanvasScaler>(); val2.uiScaleMode = (ScaleMode)1; val2.referenceResolution = new Vector2(1920f, 1080f); GameObject val3 = new GameObject("Background"); val3.transform.SetParent(_uiRoot.transform); _bgRect = val3.AddComponent<RectTransform>(); _bgRect.anchoredPosition = new Vector2(Config.FpsPosX.Value + 100f, Config.FpsPosY.Value); RectTransform? bgRect = _bgRect; Vector2 anchorMin = (_bgRect.anchorMax = new Vector2(0f, 1f)); bgRect.anchorMin = anchorMin; _bgRect.pivot = new Vector2(0.5f, 0.5f); _bgRect.sizeDelta = new Vector2(120f, 40f); ((Graphic)val3.AddComponent<Image>()).color = new Color(0f, 0f, 0f, 0.5f); GameObject val5 = new GameObject("FPS_Text"); val5.transform.SetParent(val3.transform); RectTransform val6 = val5.AddComponent<RectTransform>(); val6.anchoredPosition = Vector2.zero; anchorMin = (val6.anchorMax = new Vector2(0.5f, 0.5f)); val6.anchorMin = anchorMin; val6.pivot = new Vector2(0.5f, 0.5f); val6.sizeDelta = new Vector2(200f, 50f); _fpsText = val5.AddComponent<Text>(); _fpsText.font = Resources.GetBuiltinResource<Font>("Arial.ttf"); _fpsText.fontSize = Config.FontSize.Value; ((Graphic)_fpsText).color = Config.ColorValue.Value; _fpsText.alignment = (TextAnchor)4; ((Graphic)_fpsText).raycastTarget = false; Object.DontDestroyOnLoad((Object)(object)_uiRoot); } catch (Exception ex) { MelonLogger.Error($"Erreur création UI: {ex}\n{ex.StackTrace}"); } } private void UpdateUI() { //IL_0045: 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) if (!((Object)(object)_fpsText == (Object)null) && !((Object)(object)_bgRect == (Object)null)) { _fpsText.fontSize = Config.FontSize.Value; ((Graphic)_fpsText).color = Config.ColorValue.Value; _bgRect.sizeDelta = new Vector2(Mathf.Clamp(_fpsText.preferredWidth + 20f, 100f, 300f), 40f); } } private void UpdatePosition() { //IL_003d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_bgRect == (Object)null)) { _bgRect.anchoredPosition = new Vector2(Mathf.Round(Config.FpsPosX.Value) + 100f, Mathf.Round(Config.FpsPosY.Value)); } } public override void OnUpdate() { Application.targetFrameRate = -1; Config.CheckForChanges(); UpdateUI(); UpdatePosition(); if ((Object)(object)_uiRoot != (Object)null) { _uiRoot.SetActive(Config.Enabled.Value); if (Config.Enabled.Value && (Object)(object)_fpsText != (Object)null) { _currentFps = 1f / Time.unscaledDeltaTime; _smoothedFps = Mathf.Lerp(_smoothedFps, _currentFps, Config.SmoothingFactor.Value); _fpsText.text = $"FPS: {Mathf.RoundToInt(Mathf.Min(_smoothedFps, 999f))}"; } } } public override void OnSceneWasInitialized(int buildIndex, string sceneName) { if ((Object)(object)_uiRoot == (Object)null) { InitializeUI(); } } } public static class Config { private static FileSystemWatcher? _watcher; private static bool _needsReload; private static string _filePath; public static MelonPreferences_Category Category { get; private set; } public static MelonPreferences_Entry<Color> ColorValue { get; private set; } public static MelonPreferences_Entry<int> FontSize { get; private set; } public static MelonPreferences_Entry<bool> Enabled { get; private set; } public static MelonPreferences_Entry<float> SmoothingFactor { get; private set; } public static MelonPreferences_Entry<float> FpsPosX { get; private set; } public static MelonPreferences_Entry<float> FpsPosY { get; private set; } public static void Load() { try { InitializeCategory(); ConvertLegacyConfig(); SetupFileWatcher(); Category.SaveToFile(true); MelonLogger.Msg("Configuration chargée avec succès !"); } catch (Exception value) { MelonLogger.Error($"Erreur lors du chargement de la config: {value}"); } } private static void InitializeCategory() { //IL_0044: Unknown result type (might be due to invalid IL or missing references) Category = MelonPreferences.CreateCategory("FPSCounter_Visuals", "Paramètres visuels"); _filePath = Path.Combine(GetUserDataDirectory(), "FPSCounter.cfg"); Category.SetFilePath(_filePath); ColorValue = Category.CreateEntry<Color>("ColorValue", Color.white, "Couleur du texte", "Contrôle la couleur RGBA du compteur", false, false, (ValueValidator)null, (string)null); FontSize = Category.CreateEntry<int>("FontSize", 24, "Taille de police", "Taille en pixels du texte", false, false, (ValueValidator)null, (string)null); Enabled = Category.CreateEntry<bool>("Enabled", true, "Activé", "Activer/désactiver le compteur", false, false, (ValueValidator)null, (string)null); SmoothingFactor = Category.CreateEntry<float>("SmoothingFactor", 0.1f, "Lissage", "Fluidité de l'affichage (0.1-1.0)", false, false, (ValueValidator)null, (string)null); FpsPosX = Category.CreateEntry<float>("FpsPosX", -40f, "Position X", "Décalage horizontal", false, false, (ValueValidator)null, (string)null); FpsPosY = Category.CreateEntry<float>("FpsPosY", -20f, "Position Y", "Décalage vertical", false, false, (ValueValidator)null, (string)null); } private static void ConvertLegacyConfig() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) try { MelonPreferences_Entry<string> entry = MelonPreferences.GetEntry<string>("FPSCounter", "TextColorHex"); Color value = default(Color); if (entry != null && ColorUtility.TryParseHtmlString(entry.Value, ref value)) { ColorValue.Value = value; ((MelonPreferences_Entry)entry).IsHidden = true; } MelonPreferences_Entry<string> entry2 = MelonPreferences.GetEntry<string>("FPSCounter", "ColorValue"); if (entry2 != null) { float result; float[] array = (from s in entry2.Value.Trim('[', ']').Split(',') select float.TryParse(s.Trim(), out result) ? result : 255f).ToArray(); if (array.Length >= 4) { ColorValue.Value = new Color(Mathf.Clamp01(array[0] / 255f), Mathf.Clamp01(array[1] / 255f), Mathf.Clamp01(array[2] / 255f), Mathf.Clamp01(array[3] / 255f)); } ((MelonPreferences_Entry)entry2).IsHidden = true; } } catch (Exception ex) { MelonLogger.Warning("Échec de la conversion des anciens paramètres: " + ex.Message); } } private static string GetUserDataDirectory() { return Path.Combine(Directory.GetCurrentDirectory(), "UserData"); } private static void SetupFileWatcher() { try { _watcher = new FileSystemWatcher { Path = Path.GetDirectoryName(_filePath), Filter = Path.GetFileName(_filePath), NotifyFilter = NotifyFilters.LastWrite, InternalBufferSize = 65536 }; _watcher.Changed += delegate { _needsReload = true; }; _watcher.Error += delegate(object _, ErrorEventArgs e) { MelonLogger.Error("FileWatcher error: " + e.GetException().Message); }; _watcher.EnableRaisingEvents = true; } catch (Exception ex) { MelonLogger.Error("Impossible de démarrer le FileWatcher: " + ex.Message); } } public static void CheckForChanges() { if (!_needsReload) { return; } try { if (File.Exists(_filePath)) { Category.LoadFromFile(true); ValidateSettings(); MelonLogger.Msg("Configuration rechargée !"); } else { Category.SaveToFile(true); } _needsReload = false; } catch (Exception ex) { MelonLogger.Error("Erreur de rechargement: " + ex.Message); } } private static void ValidateSettings() { if (SmoothingFactor.Value < 0.1f || SmoothingFactor.Value > 1f) { SmoothingFactor.Value = Mathf.Clamp(SmoothingFactor.Value, 0.1f, 1f); Category.SaveToFile(true); } FpsPosX.Value = Mathf.Clamp(FpsPosX.Value, -1920f, 1920f); FpsPosY.Value = Mathf.Clamp(FpsPosY.Value, -1080f, 1080f); } } public static class PluginInfo { public const string PLUGIN_AUTHOR = "DiumStream"; public const string PLUGIN_NAME = "FPS Counter"; public const string PLUGIN_VERSION = "1.0.5"; }