From a2cf66476c40b9ade0d38bb428cf945a36c0cde5 Mon Sep 17 00:00:00 2001 From: ivan tkachenko Date: Sun, 18 Jan 2026 16:22:05 +0200 Subject: [PATCH] Deduplicate logs to avoid spamming console with errors each frame --- MuzikaGromche/DedupManualLogSource.cs | 70 +++++++++++++++++++++++++++ MuzikaGromche/Plugin.cs | 18 +++++-- 2 files changed, 83 insertions(+), 5 deletions(-) create mode 100644 MuzikaGromche/DedupManualLogSource.cs diff --git a/MuzikaGromche/DedupManualLogSource.cs b/MuzikaGromche/DedupManualLogSource.cs new file mode 100644 index 0000000..9440e57 --- /dev/null +++ b/MuzikaGromche/DedupManualLogSource.cs @@ -0,0 +1,70 @@ +using BepInEx.Logging; + +namespace MuzikaGromche; + +#if DEBUG + +// A logger with an API similar to ManualLogSource. +// This logger caches last posted messagee and uses it to deduplicate subsequent messages. +// Use Clear() to forget deduplicated message. +internal class DedupManualLogSource +{ + public ManualLogSource Source; + + object? lastData = null; + + public DedupManualLogSource(ManualLogSource source) + { + Source = source; + } + + public void Log(LogLevel level, object data) + { + if (lastData != data) + { + lastData = data; + Source.Log(level, data); + } + } + + public void LogFatal(object data) + { + Log(LogLevel.Fatal, data); + } + + public void LogError(object data) + { + Log(LogLevel.Error, data); + } + + public void LogWarning(object data) + { + Log(LogLevel.Warning, data); + } + + public void LogMessage(object data) + { + Log(LogLevel.Message, data); + } + + public void LogInfo(object data) + { + Log(LogLevel.Info, data); + } + + public void LogDebug(object data) + { + Log(LogLevel.Debug, data); + } + + public void Clear() + { + lastData = null; + } + + public void Dispose() + { + } +} + +#endif diff --git a/MuzikaGromche/Plugin.cs b/MuzikaGromche/Plugin.cs index 559e266..01d2d06 100644 --- a/MuzikaGromche/Plugin.cs +++ b/MuzikaGromche/Plugin.cs @@ -1178,6 +1178,7 @@ namespace MuzikaGromche Array.Sort(Tracks.Select(track => track.Name).ToArray(), Tracks); #if DEBUG + JesterPatch.DedupLog = new DedupManualLogSource(Logger); GlobalBehaviour.Instance.StartCoroutine(PreloadDebugAndExport(Tracks)); #endif Config = new Config(base.Config); @@ -3319,6 +3320,11 @@ namespace MuzikaGromche }; } +#if DEBUG + // avoid spamming console with errors each frame + public static DedupManualLogSource DedupLog = null!; +#endif + [HarmonyPatch(nameof(JesterAI.Update))] [HarmonyPostfix] static void JesterUpdatePostfix(JesterAI __instance, State __state) @@ -3331,21 +3337,23 @@ namespace MuzikaGromche { #if DEBUG if (behaviour.CurrentTrack == null) - { - Plugin.Log.LogError("CurrentTrack is not set!"); + { + DedupLog.LogWarning("CurrentTrack is not set!"); } else if (AudioClipsCacheManager.AllDone) { - Plugin.Log.LogError("Failed to load audio clips, no in-flight requests running"); + DedupLog.LogWarning("Failed to load audio clips, no in-flight requests running"); } else { - Plugin.Log.LogDebug($"Waiting for audio clips to load"); + DedupLog.LogWarning("Waiting for audio clips to load"); } #endif return; } - +#if DEBUG + DedupLog.Clear(); +#endif var vanillaCompatMode = behaviour.VanillaCompatMode; // If greater than zero, delay the intro to start playing later. // If less than zero, start playing before the beginCrankingTimer runs out.