Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of RichEmoji v0.3.1
BepInEx\plugins\RichEmoji.dll
Decompiled 2 days agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using BepInEx; using BepInEx.Logging; using GUIFramework; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.TextCore; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("gui_framework")] [assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("Ron4242")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright © Ron4242 2026")] [assembly: AssemblyDescription("Enhances emojis all across Valheim, adds new ones, and even lets you add your own!")] [assembly: AssemblyFileVersion("0.3.1.0")] [assembly: AssemblyInformationalVersion("0.3.1+fff5df7fb70a928f13c313b76f379e4502759588")] [assembly: AssemblyProduct("RichEmoji")] [assembly: AssemblyTitle("RichEmoji")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.3.1.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 RichEmoji { public static class EmojiConverter { public class EmojiTextPreprocessor : ITextPreprocessor { public static readonly EmojiTextPreprocessor Instance = new EmojiTextPreprocessor(); public string PreprocessText(string text) { return ToFakeUnicode(text); } } private const string BaseEmoji = "(?:(?:\\uD83C[\\uDDE6-\\uDDFF]){2}|[\\uD83C-\\uD83F][\\uDC00-\\uDFFF]|[\\u2000-\\u3299]|[\\u00A9\\u00AE]|[0-9#*]\\uFE0F?\\u20E3)(?:\\uD83C[\\uDFFB-\\uDFFF])?\\uFE0F?"; public static readonly Regex EmojiNamePattern = new Regex(":([a-zA-Z0-9-_]+):", RegexOptions.Compiled); public static readonly Regex EmojiUnicodePattern = new Regex("(?:(?:\\uD83C[\\uDDE6-\\uDDFF]){2}|[\\uD83C-\\uD83F][\\uDC00-\\uDFFF]|[\\u2000-\\u3299]|[\\u00A9\\u00AE]|[0-9#*]\\uFE0F?\\u20E3)(?:\\uD83C[\\uDFFB-\\uDFFF])?\\uFE0F?(?:\\u200D(?:(?:\\uD83C[\\uDDE6-\\uDDFF]){2}|[\\uD83C-\\uD83F][\\uDC00-\\uDFFF]|[\\u2000-\\u3299]|[\\u00A9\\u00AE]|[0-9#*]\\uFE0F?\\u20E3)(?:\\uD83C[\\uDFFB-\\uDFFF])?\\uFE0F?)*", RegexOptions.Compiled); public static string ToFakeUnicode(string text) { if (string.IsNullOrEmpty(text)) { return text; } string text2 = text; if (text2.Contains(":")) { text2 = EmojiNamePattern.Replace(text2, (Match match) => (!RichEmoji.EmojiNameLookup.TryGetValue(match.Groups[1].Value, out var value2)) ? match.Value : value2); } string value; return EmojiUnicodePattern.Replace(text2, (Match match) => (!RichEmoji.EmojiUnicodeLookup.TryGetValue(match.Value, out value)) ? match.Value : value); } public static string ToShortcodes(string text) { if (string.IsNullOrEmpty(text)) { return text; } StringBuilder stringBuilder = new StringBuilder(); foreach (char c in text) { if (RichEmoji.EmojiFakeUnicodeLookup.TryGetValue(c, out var value)) { stringBuilder.Append(value); } else { stringBuilder.Append(c); } } return stringBuilder.ToString(); } } public static class Patches { [HarmonyPatch(typeof(GuiInputField), "ActivateInputField")] public static class GuiInputFieldActivatePatch { private static void Postfix(GuiInputField __instance) { if (!string.IsNullOrEmpty(((TMP_InputField)__instance).text)) { string text = EmojiConverter.ToFakeUnicode(((TMP_InputField)__instance).text); if (!(text == ((TMP_InputField)__instance).text)) { ((TMP_InputField)__instance).SetTextWithoutNotify(text); ((TMP_InputField)__instance).m_OriginalText = text; ((TMP_InputField)__instance).caretPosition = ((TMP_InputField)__instance).text.Length; } } } } [HarmonyPatch(typeof(GuiInputField), "Awake")] public static class GuiInputFieldAwakePatch { [CompilerGenerated] private sealed class <>c__DisplayClass0_0 { public Coroutine pending; public GuiInputField __instance; internal void <Postfix>b__0(string text) { <>c__DisplayClass0_1 CS$<>8__locals0 = new <>c__DisplayClass0_1 { CS$<>8__locals1 = this }; if (pending != null) { ((MonoBehaviour)__instance).StopCoroutine(pending); } CS$<>8__locals0.captured = text; pending = ((MonoBehaviour)__instance).StartCoroutine(Routine()); [IteratorStateMachine(typeof(<>c__DisplayClass0_1.<<Postfix>g__Routine|1>d))] IEnumerator Routine() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <>c__DisplayClass0_1.<<Postfix>g__Routine|1>d(0) { <>4__this = CS$<>8__locals0 }; } } } [CompilerGenerated] private sealed class <>c__DisplayClass0_1 { public string captured; public <>c__DisplayClass0_0 CS$<>8__locals1; } private static void Postfix(GuiInputField __instance) { Coroutine pending = null; <>c__DisplayClass0_0 CS$<>8__locals0; ((UnityEvent<string>)(object)((TMP_InputField)__instance).onValueChanged).AddListener((UnityAction<string>)delegate(string text) { <>c__DisplayClass0_1 CS$<>8__locals1 = new <>c__DisplayClass0_1(); CS$<>8__locals1.CS$<>8__locals1 = CS$<>8__locals0; if (pending != null) { ((MonoBehaviour)__instance).StopCoroutine(pending); } CS$<>8__locals1.captured = text; pending = ((MonoBehaviour)__instance).StartCoroutine(Routine()); [IteratorStateMachine(typeof(<>c__DisplayClass0_1.<<Postfix>g__Routine|1>d))] IEnumerator Routine() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <>c__DisplayClass0_1.<<Postfix>g__Routine|1>d(0) { <>4__this = CS$<>8__locals1 }; } }); } } [HarmonyPatch(typeof(GuiInputField), "onInputSubmit")] public static class GuiInputFieldSubmitPatch { private static void Prefix(GuiInputField __instance, ref string text) { string text2 = EmojiConverter.ToShortcodes(text); if (!(text2 == text)) { ((TMP_InputField)__instance).SetTextWithoutNotify(text2); text = text2; } } } [HarmonyPatch(typeof(TextMeshProUGUI), "Awake")] public static class TMPTextAwakePatch { private static void Postfix(TextMeshProUGUI __instance) { if (((TMP_Text)__instance).textPreprocessor == null) { ITextPreprocessor val = (((TMP_Text)__instance).textPreprocessor = (ITextPreprocessor)(object)EmojiConverter.EmojiTextPreprocessor.Instance); } } } } [BepInPlugin("Ron4242.github.RichEmoji", "RichEmoji", "0.3.1")] public sealed class RichEmoji : BaseUnityPlugin { public const int MaxEmojis = 6400; public static readonly ManualLogSource Log = Logger.CreateLogSource("RichEmoji"); public static TMP_SpriteAsset CustomEmojiAsset; public static readonly Dictionary<string, string> EmojiNameLookup = new Dictionary<string, string>(); public static readonly Dictionary<char, string> EmojiFakeUnicodeLookup = new Dictionary<char, string>(); public static readonly Dictionary<string, string> EmojiUnicodeLookup = new Dictionary<string, string>(); private static MethodInfo LoadImageMethod { get; } = AccessTools.Method(typeof(ImageConversion), "LoadImage", new Type[2] { typeof(Texture2D), typeof(byte[]) }, (Type[])null); private void Awake() { Harmony.CreateAndPatchAll(typeof(RichEmoji).Assembly, (string)null); LoadEmojis(); } private void LoadEmojis() { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Expected O, but got Unknown //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Expected O, but got Unknown //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Expected O, but got Unknown //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_028e: Unknown result type (might be due to invalid IL or missing references) //IL_0296: Unknown result type (might be due to invalid IL or missing references) //IL_02a4: 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_02bb: Unknown result type (might be due to invalid IL or missing references) //IL_02c5: Unknown result type (might be due to invalid IL or missing references) //IL_02d2: Expected O, but got Unknown //IL_0397: Unknown result type (might be due to invalid IL or missing references) //IL_039c: Unknown result type (might be due to invalid IL or missing references) //IL_03a6: Expected O, but got Unknown string text = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "emojis"); if (!Directory.Exists(text)) { Log.LogWarning((object)("Emojis folder not found at " + text)); return; } string[] files = Directory.GetFiles(text, "*.png", SearchOption.AllDirectories); int num = files.Length; if (files.Length == 0) { return; } byte[][] bytes = new byte[num][]; Parallel.For(0, num, delegate(int i) { bytes[i] = File.ReadAllBytes(files[i]); }); List<Texture2D> list = new List<Texture2D>(num); List<string> list2 = new List<string>(num); for (int j = 0; j < num; j++) { Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); LoadImageMethod.Invoke(null, new object[2] { val, bytes[j] }); bytes[j] = null; Texture2D val2 = ResizeTexture(val, 96, 96); list.Add(val2); list2.Add(Path.GetFileNameWithoutExtension(files[j])); if ((Object)(object)val2 != (Object)(object)val) { Object.Destroy((Object)(object)val); } } Texture2D val3 = new Texture2D(2, 2, (TextureFormat)4, false); Rect[] array = val3.PackTextures(list.ToArray(), 2, 8192); foreach (Texture2D item2 in list) { Object.Destroy((Object)(object)item2); } list.Clear(); CustomEmojiAsset = ScriptableObject.CreateInstance<TMP_SpriteAsset>(); ((Object)CustomEmojiAsset).name = "RichEmojiAtlas"; CustomEmojiAsset.spriteSheet = (Texture)(object)val3; ((TMP_Asset)CustomEmojiAsset).m_Version = "1.1.0"; TMP_SpriteAsset defaultSpriteAsset = TMP_Settings.defaultSpriteAsset; ((TMP_Asset)CustomEmojiAsset).material = new Material(((TMP_Asset)defaultSpriteAsset).material) { mainTexture = (Texture)(object)val3 }; CustomEmojiAsset.spriteCharacterTable = new List<TMP_SpriteCharacter>(); CustomEmojiAsset.spriteGlyphTable = new List<TMP_SpriteGlyph>(); int num2 = Math.Min(array.Length, 6400); if (array.Length > 6400) { Log.LogWarning((object)$"Emoji limit exceeded! Found {array.Length}, but only up to {6400} emojis are supported. Not all emojis will be loaded."); } for (int k = 0; k < num2; k++) { Rect val4 = array[k]; string text2 = list2[k]; float num3 = ((Rect)(ref val4)).x * (float)((Texture)val3).width; float num4 = ((Rect)(ref val4)).y * (float)((Texture)val3).height; float num5 = ((Rect)(ref val4)).width * (float)((Texture)val3).width; float num6 = ((Rect)(ref val4)).height * (float)((Texture)val3).height; TMP_SpriteGlyph val5 = new TMP_SpriteGlyph { index = (uint)k, metrics = new GlyphMetrics(num5, num6, 0f, num6, num5), glyphRect = new GlyphRect((int)num3, (int)num4, (int)num5, (int)num6), scale = 1f }; CustomEmojiAsset.spriteGlyphTable.Add(val5); string[] array2 = text2.Split(new string[1] { "__" }, StringSplitOptions.None); string text3 = array2[0]; StringBuilder stringBuilder = new StringBuilder(); uint num7 = (uint)(57344 + k); if (array2.Length > 1) { string[] array3 = array2[1].Split(new char[1] { '-' }); bool flag = true; string[] array4 = array3; for (int l = 0; l < array4.Length; l++) { if (uint.TryParse(array4[l], NumberStyles.HexNumber, null, out var result)) { stringBuilder.Append(char.ConvertFromUtf32((int)result)); continue; } flag = false; break; } if (flag && stringBuilder.Length > 0) { EmojiUnicodeLookup[stringBuilder.ToString()] = char.ConvertFromUtf32((int)num7); } } TMP_SpriteCharacter item = new TMP_SpriteCharacter(num7, val5) { name = text3 }; CustomEmojiAsset.spriteCharacterTable.Add(item); EmojiNameLookup[text3] = char.ConvertFromUtf32((int)num7); EmojiFakeUnicodeLookup[char.ConvertFromUtf32((int)num7)[0]] = ":" + text3 + ":"; } CustomEmojiAsset.UpdateLookupTables(); TMP_SpriteAsset val6 = defaultSpriteAsset; if (val6.fallbackSpriteAssets == null) { val6.fallbackSpriteAssets = new List<TMP_SpriteAsset>(); } defaultSpriteAsset.fallbackSpriteAssets.Add(CustomEmojiAsset); Log.LogInfo((object)$"Loaded {files.Length} emojis!"); } private static Texture2D ResizeTexture(Texture2D source, int maxWidth, int maxHeight) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006e: 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_008d: Expected O, but got Unknown int width = ((Texture)source).width; int height = ((Texture)source).height; if (width > maxWidth || height > maxHeight) { float num = (float)width / (float)height; if (width > height) { width = maxWidth; height = Mathf.RoundToInt((float)width / num); } else { height = maxHeight; width = Mathf.RoundToInt((float)height * num); } RenderTexture val = (RenderTexture.active = RenderTexture.GetTemporary(width, height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)0)); Graphics.Blit((Texture)(object)source, val); Texture2D val2 = new Texture2D(width, height, (TextureFormat)4, false); val2.ReadPixels(new Rect(0f, 0f, (float)width, (float)height), 0, 0); val2.Apply(); RenderTexture.active = null; RenderTexture.ReleaseTemporary(val); return val2; } return source; } } internal static class ThisPluginInfo { public const string PLUGIN_GUID = "Ron4242.github.RichEmoji"; public const string PLUGIN_NAME = "RichEmoji"; public const string PLUGIN_VERSION = "0.3.1"; } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }