using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; [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: AssemblyCompany("BepInExLogFilter")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("BepInExLogFilter")] [assembly: AssemblyTitle("BepInExLogFilter")] [assembly: AssemblyVersion("1.0.0.0")] [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 BepInExLogFilter { [BepInPlugin("com.nadre.bepinexlogfilter", "BepInExLogFilter", "1.4.0")] public class Plugin : BaseUnityPlugin { public const string ModGUID = "com.nadre.bepinexlogfilter"; public const string ModName = "BepInExLogFilter"; public const string ModVersion = "1.4.0"; private readonly Harmony harmony = new Harmony("com.nadre.bepinexlogfilter"); internal static ManualLogSource LoggerInstance = null; private static ConfigEntry configEnabled = null; private static ConfigEntry configBlockedKeywords = null; private static ConfigEntry configBlockedSources = null; internal static HashSet BlockedSourcesSet = new HashSet(StringComparer.OrdinalIgnoreCase); internal static List BlockedKeywords = new List(); internal static readonly Dictionary<(string source, string message), (DateTime lastTime, int suppressCount)> MessageCache = new Dictionary<(string, string), (DateTime, int)>(200); internal const double SuppressionWindowSeconds = 2.0; internal const int MaxCacheSize = 200; private void Awake() { LoggerInstance = ((BaseUnityPlugin)this).Logger; configEnabled = ((BaseUnityPlugin)this).Config.Bind("General", "EnableFiltering", true, "Activer ou desactiver le filtrage global des logs."); string text = "Player has a camera,Player does not have a camera,Exposed name does not exist,PlayOneShot was called with a null AudioClip,smart pathfinding data while it was not present,DropAllHeldItems called on player,Item slot #,placedPosition:,item awake:,Item sales percentages,Unable to add the requested character to font asset,DontDestroyOnLoad only works for root GameObjects,NetworkVariable is written to,but doesn't know its NetworkBehaviour yet,damageTrigger is disabled! Netcode for GameObjects,The referenced script,missing!,CustomMessagingManager indisponible,does not allow read access,does not support negative scale or size,Failed to Unpatch,not a valid .NET assembly"; configBlockedKeywords = ((BaseUnityPlugin)this).Config.Bind("Filters", "BlockedKeywords", text, "Mots-cles a filtrer dans les messages (separes par des virgules)."); configBlockedSources = ((BaseUnityPlugin)this).Config.Bind("Filters", "BlockedSources", "HDLCPatch,PathfindingLib,SuperAdminMenu", "Sources de logs de mods a filtrer entierement (separees par des virgules)."); LoggerInstance.LogInfo((object)"BepInExLogFilter v1.4.0 charge."); if (configEnabled.Value) { ParseConfigs(); try { harmony.PatchAll(typeof(Plugin).Assembly); LoggerInstance.LogInfo((object)"Filtre Harmony applique avec succes sur BepInEx.Logging.Logger.InternalLogEvent. Securite anti-conflit universelle activee."); } catch (Exception ex) { LoggerInstance.LogError((object)("Erreur lors de l'application du patch Harmony : " + ex.Message)); } } } private void ParseConfigs() { BlockedKeywords.Clear(); if (!string.IsNullOrEmpty(configBlockedKeywords.Value)) { string[] array = configBlockedKeywords.Value.Split(','); foreach (string text in array) { string text2 = text.Trim(); if (!string.IsNullOrEmpty(text2)) { BlockedKeywords.Add(text2); } } } List list = new List(); if (!string.IsNullOrEmpty(configBlockedSources.Value)) { string[] array2 = configBlockedSources.Value.Split(','); foreach (string text3 in array2) { string text4 = text3.Trim(); if (!string.IsNullOrEmpty(text4)) { list.Add(text4); } } } BlockedSourcesSet = new HashSet(list, StringComparer.OrdinalIgnoreCase); } } [HarmonyPatch(typeof(Logger), "InternalLogEvent")] public static class LoggerLogEventPatch { private static string MaskNumbers(string text) { if (string.IsNullOrEmpty(text)) { return text; } bool flag = false; for (int i = 0; i < text.Length; i++) { if (char.IsDigit(text[i])) { flag = true; break; } } if (!flag) { return text; } StringBuilder stringBuilder = new StringBuilder(text.Length); bool flag2 = false; for (int j = 0; j < text.Length; j++) { char c = text[j]; if (char.IsDigit(c) || c == '.' || c == ',' || c == '-') { if (c == '.' || c == ',' || c == '-') { if (j + 1 < text.Length && char.IsDigit(text[j + 1])) { if (!flag2) { stringBuilder.Append('#'); flag2 = true; } } else { stringBuilder.Append(c); flag2 = false; } } else if (!flag2) { stringBuilder.Append('#'); flag2 = true; } } else { stringBuilder.Append(c); flag2 = false; } } return stringBuilder.ToString(); } [HarmonyPrefix] public static bool Prefix(object sender, LogEventArgs eventArgs) { if (eventArgs == null) { return true; } ILogSource source = eventArgs.Source; string text = ((source != null) ? source.SourceName : null) ?? ""; if (text == "com.nadre.bepinexlogfilter" || text == "BepInExLogFilter") { return true; } if (Plugin.BlockedSourcesSet.Contains(text)) { return false; } string text2 = eventArgs.Data?.ToString() ?? ""; foreach (string blockedKeyword in Plugin.BlockedKeywords) { if (text2.Contains(blockedKeyword, StringComparison.OrdinalIgnoreCase)) { return false; } } string item = MaskNumbers(text2); (string, string) key = (text, item); DateTime utcNow = DateTime.UtcNow; int num = 0; lock (Plugin.MessageCache) { if (Plugin.MessageCache.TryGetValue(key, out (DateTime, int) value)) { double totalSeconds = (utcNow - value.Item1).TotalSeconds; if (totalSeconds < 2.0) { Plugin.MessageCache[key] = (value.Item1, value.Item2 + 1); return false; } num = value.Item2; } if (Plugin.MessageCache.Count >= 200) { List<(string, string)> list = new List<(string, string)>(); foreach (KeyValuePair<(string, string), (DateTime, int)> item2 in Plugin.MessageCache) { double totalSeconds2 = (utcNow - item2.Value.Item1).TotalSeconds; if (totalSeconds2 >= 2.0) { list.Add(item2.Key); if (item2.Value.Item2 > 0 && num == 0) { num = item2.Value.Item2; } } } foreach (var item3 in list) { Plugin.MessageCache.Remove(item3); } if (Plugin.MessageCache.Count >= 200) { Plugin.MessageCache.Clear(); } } Plugin.MessageCache[key] = (utcNow, 0); } if (num > 0) { string text3 = $"[BepInExLogFilter] Supprime {num} logs repetitifs (dynamiques groupes) provenant de {text}"; Plugin.LoggerInstance.LogInfo((object)text3); } return true; } } }