The current BepInExPack is broken due to the Oakveil update, and mods installed through a mod manager may not work. Join the modding Discord for more information.
Decompiled source of CrimsonChatFilter v1.1.3
CrimsonChatFilter.dll
Decompiled a week agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text.Json; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Core.Logging.Interpolation; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using CrimsonChatFilter.Structs; using CrimsonChatFilter.Utils; using HarmonyLib; using Microsoft.CodeAnalysis; using ProjectM; using ProjectM.Network; using Unity.Collections; using Unity.Entities; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("CrimsonChatFilter")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Filter server chat!")] [assembly: AssemblyFileVersion("1.1.3.0")] [assembly: AssemblyInformationalVersion("1.1.3+1.Branch.master.Sha.0bf85cee523e58d1dc8041d4c261b282b442b8a9.0bf85cee523e58d1dc8041d4c261b282b442b8a9")] [assembly: AssemblyProduct("CrimsonChatFilter")] [assembly: AssemblyTitle("CrimsonChatFilter")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.3.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.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace CrimsonChatFilter { [BepInPlugin("CrimsonChatFilter", "CrimsonChatFilter", "1.1.3")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BasePlugin { private Harmony _harmony; public static readonly string ConfigFiles = Path.Combine(Paths.ConfigPath, "CrimsonChatFilter"); public static bool LogLoaded = false; public static bool BanLoaded = false; public static Plugin Instance { get; private set; } public static Harmony Harmony => Instance._harmony; public static Settings Settings { get; private set; } public static ManualLogSource LogInstance => ((BasePlugin)Instance).Log; public static Database Database { get; private set; } public override void Load() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Expected O, but got Unknown Instance = this; Settings = default(Settings); Settings.InitConfig(); Database = new Database(); _harmony = new Harmony("CrimsonChatFilter"); _harmony.PatchAll(Assembly.GetExecutingAssembly()); foreach (KeyValuePair<string, PluginInfo> plugin in ((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins) { BepInPlugin metadata = plugin.Value.Metadata; if (metadata.GUID.Equals("CrimsonLog")) { LogLoaded = true; } else if (metadata.GUID.Equals("CrimsonBanned")) { BanLoaded = true; } } ManualLogSource log = ((BasePlugin)this).Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(27, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Plugin "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("CrimsonChatFilter"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" version "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("1.1.3"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" is loaded!"); } log.LogInfo(val); } public static void AddLog(string message, bool console = false) { if (LogLoaded && !console) { Type type = Type.GetType("CrimsonLog.Systems.Logger, CrimsonLog"); if (type != null) { type.GetMethod("Record").Invoke(null, new object[3] { "Chat/Filter", "filter", message + "\n" }); return; } } LogInstance.LogInfo((object)message); } public override bool Unload() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } return true; } } public static class MyPluginInfo { public const string PLUGIN_GUID = "CrimsonChatFilter"; public const string PLUGIN_NAME = "CrimsonChatFilter"; public const string PLUGIN_VERSION = "1.1.3"; } } namespace CrimsonChatFilter.Utils { internal static class FilterString { private static string addressFilter = ".[0-9]+[0-9][0-9].[0-9]+[0-9][0-9].[0-9]+[0-9][0-9].[0-9]+[0-9][0-9]*"; private static string domainFilter = "\\bhttp:\\/\\/([^\\/]*)\\/([^\\s]*)"; public static string Filter(this string input) { if (Settings.FILTER_URLS.Value) { input = Regex.Replace(input, addressFilter, "****", RegexOptions.IgnoreCase); input = Regex.Replace(input, domainFilter, "****", RegexOptions.IgnoreCase); } foreach (string item in Database.Filtered) { string pattern = CreateRegexPattern(item); input = Regex.Replace(input, pattern, "****", RegexOptions.IgnoreCase); } return input; } public static bool ContainsFiltered(this string input) { if (Settings.FILTER_URLS.Value) { if (Regex.IsMatch(input, addressFilter)) { return true; } if (Regex.IsMatch(input, domainFilter)) { return true; } } foreach (string item in Database.Filtered) { string pattern = CreateRegexPattern(item); if (Regex.IsMatch(input, pattern, RegexOptions.IgnoreCase)) { return true; } } return false; } private static string CreateRegexPattern(string word) { string text = Regex.Escape(word).Replace("\\*", ".*"); return "\\b" + text + "\\b"; } } } namespace CrimsonChatFilter.Structs { public class Database { public static string FilteredFile = Path.Combine(Plugin.ConfigFiles, "filtered_words.json"); public static List<string> Filtered; public Database() { Load(); } private void Load() { if (!Directory.Exists(Plugin.ConfigFiles)) { Directory.CreateDirectory(Plugin.ConfigFiles); } if (!File.Exists(FilteredFile)) { Filtered = new List<string> { "coon", "jim crow", "nigger", "gook", "chink", "towelhead", "honky", "beaner", "spic" }; string contents = JsonSerializer.Serialize(Filtered, new JsonSerializerOptions { WriteIndented = true }); File.WriteAllText(FilteredFile, contents); } else { Filtered = JsonSerializer.Deserialize<List<string>>(File.ReadAllText(FilteredFile)); } } } [StructLayout(LayoutKind.Sequential, Size = 1)] public readonly struct Settings { public static readonly string CONFIG_PATH = Path.Combine(Paths.ConfigPath, "CrimsonChatFilter"); private static readonly List<string> OrderedSections = new List<string> { "Config", "AutoMod" }; public static ConfigEntry<bool> ENABLE_MOD { get; private set; } public static ConfigEntry<bool> FULL_REMOVE { get; private set; } public static ConfigEntry<bool> FILTER_URLS { get; private set; } public static void InitConfig() { ENABLE_MOD = InitConfigEntry(OrderedSections[0], "EnableMod", defaultValue: true, "Enable or disable chat filtering"); FULL_REMOVE = InitConfigEntry(OrderedSections[0], "FullRemove", defaultValue: false, "If enabled, others won't see the message, otherwise replaces filtered words with ****"); FILTER_URLS = InitConfigEntry(OrderedSections[0], "FilterURLs", defaultValue: true, "Includes .com and server addresses in filter list"); ReorderConfigSections(); } private static ConfigEntry<T> InitConfigEntry<T>(string section, string key, T defaultValue, string description) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) ConfigEntry<T> val = ((BasePlugin)Plugin.Instance).Config.Bind<T>(section, key, defaultValue, description); string text = Path.Combine(Paths.ConfigPath, "CrimsonChatFilter.cfg"); ConfigEntry<T> val2 = default(ConfigEntry<T>); if (File.Exists(text) && new ConfigFile(text, true).TryGetEntry<T>(section, key, ref val2)) { val.Value = val2.Value; } return val; } private static void ReorderConfigSections() { string path = Path.Combine(Paths.ConfigPath, "CrimsonChatFilter.cfg"); if (!File.Exists(path)) { return; } List<string> list = File.ReadAllLines(path).ToList(); Dictionary<string, List<string>> dictionary = new Dictionary<string, List<string>>(); string text = ""; foreach (string item in list) { if (item.StartsWith("[")) { text = item.Trim('[', ']'); dictionary[text] = new List<string> { item }; } else if (!string.IsNullOrWhiteSpace(text)) { dictionary[text].Add(item); } } using StreamWriter streamWriter = new StreamWriter(path, append: false); foreach (string orderedSection in OrderedSections) { if (!dictionary.ContainsKey(orderedSection)) { continue; } foreach (string item2 in dictionary[orderedSection]) { streamWriter.WriteLine(item2); } streamWriter.WriteLine(); } } } } namespace CrimsonChatFilter.Hooks { [HarmonyPatch] public static class ChatMessageSystem_Patch { [HarmonyPatch(typeof(ChatMessageSystem), "OnUpdate")] [HarmonyPrefix] public static bool OnUpdate(ChatMessageSystem __instance) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Invalid comparison between Unknown and I4 //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0177: 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_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_0107: 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_0110: Unknown result type (might be due to invalid IL or missing references) if (!Settings.ENABLE_MOD.Value) { return true; } _ = __instance.__query_661171423_0; EntityQuery _query_661171423_ = __instance.__query_661171423_0; NativeArray<Entity> val = ((EntityQuery)(ref _query_661171423_)).ToEntityArray(AllocatorHandle.op_Implicit((Allocator)2)); Enumerator<Entity> enumerator = val.GetEnumerator(); while (enumerator.MoveNext()) { Entity current = enumerator.Current; EntityManager entityManager = ((ComponentSystemBase)__instance).EntityManager; FromCharacter componentData = ((EntityManager)(ref entityManager)).GetComponentData<FromCharacter>(current); entityManager = ((ComponentSystemBase)__instance).EntityManager; User componentData2 = ((EntityManager)(ref entityManager)).GetComponentData<User>(componentData.User); entityManager = ((ComponentSystemBase)__instance).EntityManager; ChatMessageEvent componentData3 = ((EntityManager)(ref entityManager)).GetComponentData<ChatMessageEvent>(current); string text = ((object)(FixedString512Bytes)(ref componentData3.MessageText)).ToString(); if ((int)componentData3.MessageType != 5 && text.ContainsFiltered()) { if (Settings.FULL_REMOVE.Value) { Plugin.AddLog($"REMOVED from {componentData2.CharacterName}: \"{text}\""); entityManager = ((ComponentSystemBase)__instance).EntityManager; ((EntityManager)(ref entityManager)).DestroyEntity(current); } else { Plugin.AddLog($"CENSORED from {componentData2.CharacterName}: \"{text}\""); text = text.Filter(); componentData3.MessageText = FixedString512Bytes.op_Implicit(text); entityManager = ((ComponentSystemBase)__instance).EntityManager; ((EntityManager)(ref entityManager)).SetComponentData<ChatMessageEvent>(current, componentData3); } } } val.Dispose(); return true; } } }