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.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ComputerysModdingUtilities; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.TextCore; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: StraftatMod(true)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("KillfeedIcons")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyDescription("Replaces text in the killfeed with icons")] [assembly: AssemblyFileVersion("1.0.3.0")] [assembly: AssemblyInformationalVersion("1.0.3")] [assembly: AssemblyProduct("Killfeed Icons")] [assembly: AssemblyTitle("KillfeedIcons")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.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 KillfeedIcons { public static class IconLoader { private static bool _attempted; public static TMP_SpriteAsset SpriteAsset { get; private set; } public static void EnsureLoaded() { //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Expected O, but got Unknown //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Expected O, but got Unknown //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Expected O, but got Unknown //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_028a: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Expected O, but got Unknown //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02a9: Unknown result type (might be due to invalid IL or missing references) //IL_02ae: Unknown result type (might be due to invalid IL or missing references) //IL_02bf: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_02d6: Unknown result type (might be due to invalid IL or missing references) //IL_02db: Unknown result type (might be due to invalid IL or missing references) //IL_02e5: Unknown result type (might be due to invalid IL or missing references) //IL_0306: Unknown result type (might be due to invalid IL or missing references) //IL_030b: Unknown result type (might be due to invalid IL or missing references) //IL_031a: Unknown result type (might be due to invalid IL or missing references) //IL_0323: Unknown result type (might be due to invalid IL or missing references) //IL_0332: Unknown result type (might be due to invalid IL or missing references) //IL_033e: Unknown result type (might be due to invalid IL or missing references) //IL_034c: Expected O, but got Unknown if (_attempted) { return; } _attempted = true; string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "icons"); if (!Directory.Exists(text)) { Directory.CreateDirectory(text); Plugin.Logger.LogWarning((object)("[KillfeedIcons] Created icons folder at " + text)); return; } string[] files = Directory.GetFiles(text, "*.png"); if (files.Length == 0) { Plugin.Logger.LogWarning((object)"[KillfeedIcons] No icons found in icons folder"); return; } List list = new List(); List list2 = new List(); string[] array = files; foreach (string text2 in array) { byte[] array2 = File.ReadAllBytes(text2); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); ((Texture)val).filterMode = (FilterMode)1; if (!ImageConversion.LoadImage(val, array2)) { Plugin.Logger.LogWarning((object)("[KillfeedIcons] Failed to load " + text2)); continue; } list.Add(val); list2.Add(Path.GetFileNameWithoutExtension(text2)); } if (list.Count == 0) { return; } Texture2D val2 = new Texture2D(512, 512, (TextureFormat)4, false); ((Texture)val2).filterMode = (FilterMode)1; Rect[] array3 = val2.PackTextures(list.ToArray(), 2, 4096); val2.Apply(); Shader val3 = Shader.Find("TextMeshPro/Sprite"); if ((Object)(object)val3 == (Object)null) { Plugin.Logger.LogError((object)"[KillfeedIcons] TextMeshPro/Sprite shader not found."); return; } Material val4 = new Material(val3); val4.mainTexture = (Texture)(object)val2; TMP_SpriteAsset val5 = ScriptableObject.CreateInstance(); ((Object)val5).name = "KillfeedIconsAsset"; typeof(TMP_SpriteAsset).GetField("m_Version", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(val5, "1.1.0"); ((TMP_Asset)val5).material = val4; val5.spriteSheet = (Texture)(object)val2; for (int j = 0; j < list.Count; j++) { TMP_SpriteGlyph val6 = new TMP_SpriteGlyph { index = (uint)j, glyphRect = new GlyphRect((int)(((Rect)(ref array3[j])).x * (float)((Texture)val2).width), (int)(((Rect)(ref array3[j])).y * (float)((Texture)val2).height), (int)(((Rect)(ref array3[j])).width * (float)((Texture)val2).width), (int)(((Rect)(ref array3[j])).height * (float)((Texture)val2).height)), scale = 1f, atlasIndex = 0 }; GlyphRect glyphRect = ((Glyph)val6).glyphRect; float num = ((GlyphRect)(ref glyphRect)).width; glyphRect = ((Glyph)val6).glyphRect; float num2 = ((GlyphRect)(ref glyphRect)).height; glyphRect = ((Glyph)val6).glyphRect; float num3 = (float)((GlyphRect)(ref glyphRect)).height * 0.75f; glyphRect = ((Glyph)val6).glyphRect; ((Glyph)val6).metrics = new GlyphMetrics(num, num2, 0f, num3, (float)((GlyphRect)(ref glyphRect)).width); val5.spriteGlyphTable.Add(val6); val5.spriteCharacterTable.Add(new TMP_SpriteCharacter { name = list2[j], glyphIndex = (uint)j, unicode = (uint)(57344 + j), scale = 1f, glyph = (Glyph)(object)val6 }); } val5.UpdateLookupTables(); SpriteAsset = val5; Plugin.Logger.LogInfo((object)$"[KillfeedIcons] Loaded {list.Count} icons."); } } [HarmonyPatch(typeof(MatchLogsOffline), "WriteLog")] public class KillfeedOfflinePatch { private static void Prefix(ref string line) { IconLoader.EnsureLoaded(); line = KillfeedHelper.ModifyKillfeedText(line); } private static void Postfix(MatchLogsOffline __instance) { KillfeedHelper.InjectSpriteAsset(__instance.parentForChatLines); } } [HarmonyPatch(typeof(MatchLogs), "RpcLogic___RpcSendChatLineToAllObservers_3615296227")] public class KillfeedOnlineRpcPatch { private static void Prefix(ref string line) { IconLoader.EnsureLoaded(); line = KillfeedHelper.ModifyKillfeedText(line); } private static void Postfix(MatchLogs __instance) { KillfeedHelper.InjectSpriteAsset(__instance.parentForChatLines); } } [HarmonyPatch(typeof(MatchLogs), "WriteLocalLog")] public class KillfeedOnlineLocalPatch { private static void Prefix(ref string line) { IconLoader.EnsureLoaded(); line = KillfeedHelper.ModifyKillfeedText(line); } private static void Postfix(MatchLogs __instance) { KillfeedHelper.InjectSpriteAsset(__instance.parentForChatLines); } } public static class KillfeedHelper { public static bool needsSpriteInjection; private const string KillerColor = "A8BAFF"; private const string VictimColor = "FF9376"; private const string SpriteReset = ""; private static readonly Regex KillPattern = new Regex("((?:\\{PLAYER_NAME\\}:\\{\\d+\\}|.+?)) was (killed|headshot|slain|beheaded) with an?\\s+(?:)?(.+?)(?:)? by ((?:\\{PLAYER_NAME\\}:\\{\\d+\\}|.+?))", RegexOptions.Compiled); private static readonly Regex BubleePattern = new Regex("((?:\\{PLAYER_NAME\\}:\\{\\d+\\}|.+?)) was killed with the Bublee by ((?:\\{PLAYER_NAME\\}:\\{\\d+\\}|.+?))", RegexOptions.Compiled); private static readonly Regex ColorTagPattern = new Regex("", RegexOptions.Compiled); private static string FormatName(string nameTag, string hexColor) { return ColorTagPattern.Replace(nameTag.Replace("", "").Replace("", ""), ""); } private static string BuildResult(string killer, string victim, string spriteName, bool headshot = false) { string text = (headshot ? " " : ""); return FormatName(killer, "A8BAFF") + " " + text + " " + FormatName(victim, "FF9376"); } public static void InjectSpriteAsset(Transform parent) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)IconLoader.SpriteAsset == (Object)null) && needsSpriteInjection && !((Object)(object)parent == (Object)null) && parent.childCount != 0) { Transform child = parent.GetChild(parent.childCount - 1); TMP_Text val = ((child != null) ? ((Component)child).GetComponentInChildren() : null); if (!((Object)(object)val == (Object)null)) { ((TMP_Asset)IconLoader.SpriteAsset).material.color = Plugin.IconColor.Value; val.spriteAsset = IconLoader.SpriteAsset; val.text = val.text.Replace("", ""); val.ForceMeshUpdate(false, false); needsSpriteInjection = false; } } } public static string ModifyKillfeedText(string text) { Match match = KillPattern.Match(text); if (match.Success) { string value = match.Groups[2].Value; bool flag = ((value == "headshot" || value == "beheaded") ? true : false); bool headshot = flag; string result = BuildResult(match.Groups[4].Value, match.Groups[1].Value, match.Groups[3].Value, headshot); needsSpriteInjection = true; return result; } Match match2 = BubleePattern.Match(text); if (match2.Success) { needsSpriteInjection = true; return BuildResult(match2.Groups[2].Value, match2.Groups[1].Value, "bubblee"); } if (text.Contains("commited suicide")) { string nameTag = text.Substring(0, text.IndexOf(" commited suicide")); needsSpriteInjection = true; return FormatName(nameTag, "FF9376") + " "; } needsSpriteInjection = false; return text; } } [BepInPlugin("KillfeedIcons", "Killfeed Icons", "1.0.3")] public class Plugin : BaseUnityPlugin { internal static ManualLogSource Logger; internal static ConfigEntry IconColor; private void Awake() { //IL_001c: 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) Logger = ((BaseUnityPlugin)this).Logger; IconColor = ((BaseUnityPlugin)this).Config.Bind("General", "IconColor", Color.white, "Default: #FFFFFF. Requires game restart."); new Harmony("KillfeedIcons").PatchAll(); Logger.LogInfo((object)"Killfeed Icons Loaded :D"); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "KillfeedIcons"; public const string PLUGIN_NAME = "Killfeed Icons"; public const string PLUGIN_VERSION = "1.0.3"; } }