using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.Json;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using Bloodstone.API;
using Bloodstone.Hooks;
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 = "")]
[assembly: AssemblyCompany("CrimsonChatFilter")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Filter server chat!")]
[assembly: AssemblyFileVersion("0.1.3.0")]
[assembly: AssemblyInformationalVersion("0.1.3+1.Branch.master.Sha.241c5e7247e0bd24119642a65e43995f97696fcc")]
[assembly: AssemblyProduct("CrimsonChatFilter")]
[assembly: AssemblyTitle("CrimsonChatFilter")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.3.0")]
[module: UnverifiableCode]
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;
}
}
}
namespace CrimsonChatFilter
{
[BepInPlugin("CrimsonChatFilter", "CrimsonChatFilter", "0.1.3")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[Reloadable]
public class Plugin : BasePlugin
{
[Serializable]
[CompilerGenerated]
private sealed class <>c
{
public static readonly <>c <>9 = new <>c();
public static ChatEventHandler <>9__9_0;
internal void <Load>b__9_0(VChatEvent x)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Invalid comparison between Unknown and I4
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Expected O, but got Unknown
if ((int)x.Type != 5 && Settings.GetActiveOption(Settings.Options.Enable) && Settings.GetActiveOption(Settings.Options.FullRemove) && x.Message.ContainsFiltered())
{
ManualLogSource logger = Logger;
bool flag = default(bool);
BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(10, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("FILTERED: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(x.Message);
}
logger.LogWarning(val);
x.Cancel();
}
}
}
private Harmony _harmony;
public static Settings Settings { get; private set; }
public static ManualLogSource Logger { get; private set; }
public override void Load()
{
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Expected O, but got Unknown
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
//IL_0093: Expected O, but got Unknown
//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
//IL_00c2: Expected O, but got Unknown
Logger = ((BasePlugin)this).Log;
Settings = new Settings(((BasePlugin)this).Config);
Settings.InitConfig();
Database.InitFiltered("filtered_words");
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>("0.1.3");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" is loaded!");
}
log.LogInfo(val);
_harmony = new Harmony("CrimsonChatFilter");
_harmony.PatchAll(Assembly.GetExecutingAssembly());
object obj = <>c.<>9__9_0;
if (obj == null)
{
ChatEventHandler val2 = delegate(VChatEvent x)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Invalid comparison between Unknown and I4
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Expected O, but got Unknown
if ((int)x.Type != 5 && Settings.GetActiveOption(Settings.Options.Enable) && Settings.GetActiveOption(Settings.Options.FullRemove) && x.Message.ContainsFiltered())
{
ManualLogSource logger = Logger;
bool flag2 = default(bool);
BepInExWarningLogInterpolatedStringHandler val3 = new BepInExWarningLogInterpolatedStringHandler(10, 1, ref flag2);
if (flag2)
{
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("FILTERED: ");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(x.Message);
}
logger.LogWarning(val3);
x.Cancel();
}
};
<>c.<>9__9_0 = val2;
obj = (object)val2;
}
Chat.OnChatMessage += (ChatEventHandler)obj;
}
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 = "0.1.3";
}
}
namespace CrimsonChatFilter.Utils
{
internal static class FilterString
{
public static List<string> FilteredWords;
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 (Plugin.Settings.GetActiveOption(Settings.Options.FilterUrl))
{
input = Regex.Replace(input, addressFilter, "****", RegexOptions.IgnoreCase);
input = Regex.Replace(input, domainFilter, "****", RegexOptions.IgnoreCase);
}
foreach (string filteredWord in FilteredWords)
{
string pattern = CreateRegexPattern(filteredWord);
input = Regex.Replace(input, pattern, "****", RegexOptions.IgnoreCase);
}
return input;
}
public static bool ContainsFiltered(this string input)
{
if (Plugin.Settings.GetActiveOption(Settings.Options.FilterUrl))
{
if (Regex.IsMatch(input, addressFilter))
{
return true;
}
if (Regex.IsMatch(input, domainFilter))
{
return true;
}
}
foreach (string filteredWord in FilteredWords)
{
string pattern = CreateRegexPattern(filteredWord);
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
{
private static Database INSTANCE;
public string FilteredPath { get; set; }
public Database(string _path, string _db)
{
FilteredPath = Path.Combine(_path, _db + ".json");
}
public static void InitFiltered(string db)
{
INSTANCE = new Database(Path.Combine(Paths.ConfigPath, "CrimsonChatFilter"), db);
if (File.Exists(INSTANCE.FilteredPath))
{
FilterString.FilteredWords = JsonSerializer.Deserialize<List<string>>(File.ReadAllText(INSTANCE.FilteredPath));
}
}
}
public readonly struct Settings
{
public enum Options
{
Enable,
FullRemove,
FilterUrl
}
private readonly ConfigFile CONFIG;
private readonly ConfigEntry<bool> ENABLE_MOD;
private readonly ConfigEntry<bool> FULL_REMOVE;
private readonly ConfigEntry<bool> FILTER_URLS;
public static readonly string CONFIG_PATH = Path.Combine(Paths.ConfigPath, "CrimsonChatFilter");
public Settings(ConfigFile config)
{
CONFIG = config;
ENABLE_MOD = CONFIG.Bind<bool>("Config", "EnableMod", true, "Enable or disable chat filtering");
FULL_REMOVE = CONFIG.Bind<bool>("Config", "FullRemove", false, "If enabled, others won't see the message, otherwise replaces filtered words with ****");
FILTER_URLS = CONFIG.Bind<bool>("Config", "FilterURLs", true, "Includes .com and server addresses in filter list");
}
public void InitConfig()
{
WriteConfig();
}
public void WriteConfig()
{
if (!Directory.Exists(CONFIG_PATH))
{
Directory.CreateDirectory(CONFIG_PATH);
}
if (!File.Exists(Path.Combine(CONFIG_PATH, "filtered_words.json")))
{
string contents = JsonSerializer.Serialize(GenerateTemplate(), new JsonSerializerOptions
{
WriteIndented = true
});
File.WriteAllText(Path.Combine(CONFIG_PATH, "filtered_words.json"), contents);
}
}
private List<string> GenerateTemplate()
{
return new List<string> { "coon", "jim crow", "nigger", "gook", "chink", "towelhead", "honky", "beaner", "spic" };
}
public bool GetActiveOption(Options option)
{
return option switch
{
Options.Enable => ENABLE_MOD.Value,
Options.FullRemove => FULL_REMOVE.Value,
Options.FilterUrl => FILTER_URLS.Value,
_ => false,
};
}
}
}
namespace CrimsonChatFilter.Hooks
{
[HarmonyPatch]
public static class ChatMessageSystem_Patch
{
[HarmonyPatch(typeof(ChatMessageSystem), "OnUpdate")]
[HarmonyPrefix]
public static bool OnUpdate(ChatMessageSystem __instance)
{
//IL_0025: 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_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: 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_0047: 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_0054: 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_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: 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_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_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: 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_008c: 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_00a7: Unknown result type (might be due to invalid IL or missing references)
//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
//IL_00af: Invalid comparison between Unknown and I4
//IL_00be: Unknown result type (might be due to invalid IL or missing references)
//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
//IL_00c9: 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_00d2: Unknown result type (might be due to invalid IL or missing references)
//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
if (!Plugin.Settings.GetActiveOption(Settings.Options.Enable))
{
return true;
}
if (Plugin.Settings.GetActiveOption(Settings.Options.FullRemove))
{
return true;
}
_ = __instance.__query_661171423_0;
EntityQuery _query_661171423_ = __instance.__query_661171423_0;
Enumerator<Entity> enumerator = ((EntityQuery)(ref _query_661171423_)).ToEntityArray(AllocatorHandle.op_Implicit((Allocator)2)).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;
((EntityManager)(ref entityManager)).GetComponentData<User>(componentData.User);
entityManager = ((ComponentSystemBase)__instance).EntityManager;
ChatMessageEvent componentData2 = ((EntityManager)(ref entityManager)).GetComponentData<ChatMessageEvent>(current);
string input = ((object)(FixedString512Bytes)(ref componentData2.MessageText)).ToString();
if ((int)componentData2.MessageType != 5)
{
input = input.Filter();
componentData2.MessageText = FixedString512Bytes.op_Implicit(input);
entityManager = ((ComponentSystemBase)__instance).EntityManager;
((EntityManager)(ref entityManager)).SetComponentData<ChatMessageEvent>(current, componentData2);
}
}
return true;
}
}
}