using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using Fontifier; using HarmonyLib; using Il2CppTMPro; using MelonLoader; using RumbleModUI; using RumbleModUIPlus; using RumbleModdingAPI.RMAPI; using Semver; using SixLabors.Fonts; using UnityEngine; using UnityEngine.TextCore.LowLevel; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(global::Fontifier.Fontifier), "Fontifier", "1.1.5", "ninjaguardian", "https://thunderstore.io/c/rumble/p/ninjaguardian/Fontifier")] [assembly: MelonGame("Buckethead Entertainment", "RUMBLE")] [assembly: MelonColor(255, 0, 160, 230)] [assembly: MelonAuthorColor(255, 0, 160, 230)] [assembly: MelonPlatformDomain(/*Could not decode attribute arguments.*/)] [assembly: VerifyLoaderVersion("0.7.1", true)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")] [assembly: AssemblyCompany("ninjaguardian (github)")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright © 2025 ninjaguardian (github), This work is dedicated to the public domain under CC0 1.0.")] [assembly: AssemblyDescription("Lets you change the font for other mods")] [assembly: AssemblyFileVersion("1.1.5.0")] [assembly: AssemblyInformationalVersion("1.1.5")] [assembly: AssemblyProduct("Fontifier")] [assembly: AssemblyTitle("Fontifier")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/ninjaguardian/Fontifier")] [assembly: AssemblyVersion("1.1.5.0")] namespace Fontifier; public static class FontifierModInfo { public const string ModName = "Fontifier"; public const string ModVersion = "1.1.5"; public const string ModSchemaVer = "1.0.0"; public const string MLVersion = "0.7.1"; public const string Author = "ninjaguardian"; public const string DownloadLink = "https://thunderstore.io/c/rumble/p/ninjaguardian/Fontifier"; } public class FontNameValidator : ValidationParameters { public override bool DoValidation(string Input) { if (string.IsNullOrWhiteSpace(Input)) { return true; } foreach (TMP_FontAsset font in Fontifier.fonts) { if (((Object)font).name.Equals(Input, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } } public class Fontifier : MelonMod { private static class TournamentScoringPatch { public static HarmonyMethod GetPostfix => new HarmonyMethod(typeof(TournamentScoringPatch).GetMethod("Postfix")); public static MethodBase TargetMethod(MelonMod mod) { return ((object)mod).GetType().GetMethod("SpawnScoreboard", BindingFlags.Instance | BindingFlags.NonPublic); } public static void Postfix() { TextMeshPro val = TournamentScoreboardText(); if ((Object)(object)val != (Object)null) { ((TMP_Text)val).font = TournamentScoringFont(arg: true); } } } private static class MatchInfoPatch { public static HarmonyMethod GetPostfix => new HarmonyMethod(typeof(MatchInfoPatch).GetMethod("Postfix")); public static MethodBase TargetMethod(MelonMod mod) { return ((object)mod).GetType().GetMethod("RunInit", BindingFlags.Instance | BindingFlags.NonPublic); } public static void Postfix(MelonMod __instance) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Expected O, but got Unknown Type type = ((object)__instance).GetType(); TMP_FontAsset font = MatchInfoFont(arg: true); MatchInfoGameObject = (GameObject)(type.GetField("matchInfoGameObject", BindingFlags.Static | BindingFlags.Public)?.GetValue(null)); if ((Object)(object)MatchInfoGameObject == (Object)null) { Logger.Warning("MatchInfo's matchInfoGameObject is null"); } else { foreach (TextMeshPro componentsInChild in MatchInfoGameObject.GetComponentsInChildren(true)) { ((TMP_Text)componentsInChild).font = font; } } MatchInfoGymGameObject = (GameObject)(type.GetField("gymMatchInfoGameObject", BindingFlags.Static | BindingFlags.Public)?.GetValue(null)); if ((Object)(object)MatchInfoGymGameObject == (Object)null) { Logger.Warning("MatchInfo's gymMatchInfoGameObject is null"); return; } ((TMP_Text)MatchInfoGymGameObject.GetComponent()).font = font; foreach (TextMeshPro componentsInChild2 in MatchInfoGymGameObject.GetComponentsInChildren(true)) { ((TMP_Text)componentsInChild2).font = font; } } } private const string ModDesc = "Enter a font from the Font List or leave it empty to use the default font.\n\nMake sure to hit enter!"; private static Instance _logger; public static readonly List fonts = new List(); private static readonly Mod ModUI = new Mod(); private static readonly Tags tags = new Tags(); private static readonly FontNameValidator validator = new FontNameValidator(); private static TMP_FontAsset DefaultFont; private static readonly Dictionary> modFontCache = new Dictionary>(); private static Func TournamentScoringFont; private static Func TournamentScoreboardText; private static Func MatchInfoFont; private static GameObject MatchInfoGameObject; private static GameObject MatchInfoGymGameObject; public static Instance Logger { get { //IL_0034: 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_0045: Expected O, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown //IL_0402: Unknown result type (might be due to invalid IL or missing references) //IL_0407: Unknown result type (might be due to invalid IL or missing references) //IL_0413: Expected O, but got Unknown //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Expected O, but got Unknown if (_logger != null) { return _logger; } Type type = Type.GetType("MelonLoader.Properties.BuildInfo, MelonLoader") ?? Type.GetType("MelonLoader.BuildInfo, MelonLoader"); if (type == null) { Instance val = new Instance("Fontifier"); val.Error("Could not find MelonLoader.BuildInfo or MelonLoader.Properties.BuildInfo."); return val; } object obj = type.GetProperty("VersionNumber", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); if (obj == null) { Instance val2 = new Instance("Fontifier"); val2.Error("Could not get MelonLoader version."); return val2; } if (((object)SemVersion.Parse("0.7.0", false)).Equals(obj)) { dynamic val3 = Type.GetType("System.Drawing.Color, System.Drawing.Common")?.GetMethod("FromArgb", BindingFlags.Static | BindingFlags.Public, null, new Type[4] { typeof(int), typeof(int), typeof(int), typeof(int) }, null)?.Invoke(null, new object[4] { 255, 0, 160, 230 }); if (val3 != null) { _logger = new Instance("Fontifier", val3); return _logger; } Instance val4 = new Instance("Fontifier"); val4.Error("Detected MelonLoader 0.7.0 but couldn't use System.Drawing.Common"); return val4; } dynamic val5 = Type.GetType("MelonLoader.Logging.ColorARGB, MelonLoader").GetMethod("FromArgb", BindingFlags.Static | BindingFlags.Public, null, new Type[4] { typeof(byte), typeof(byte), typeof(byte), typeof(byte) }, null)?.Invoke(null, new object[4] { byte.MaxValue, (byte)0, (byte)160, (byte)230 }); if (val5 != null) { _logger = new Instance("Fontifier", val5); return _logger; } Instance val6 = new Instance("Fontifier"); val6.Error("Detected MelonLoader 0.7.1+ but couldn't use MelonLoader.Logging.ColorARGB"); return val6; } } [Obsolete("Can caused unintended side effects. Use FontFromNameCopy if possible.")] public static TMP_FontAsset FontFromName(string fontName) { if (string.IsNullOrWhiteSpace(fontName)) { return DefaultFont; } TMP_FontAsset val = ((IEnumerable)fonts).FirstOrDefault((Func)((TMP_FontAsset f) => string.Equals(((Object)f).name, fontName, StringComparison.OrdinalIgnoreCase))); if ((Object)(object)val == (Object)null) { Logger.Warning("Font with name " + fontName + " is not loaded"); return DefaultFont; } return val; } public static TMP_FontAsset FontFromNameCopy(string modName, string fontName, bool cache) { if (cache && modFontCache.TryGetValue(modName, out var value) && value.TryGetValue(fontName, out var value2)) { return value2; } TMP_FontAsset obj = FontFromName(fontName); string name = ((Object)obj).name; TMP_FontAsset val = DuplicateFont(obj); if ((Object)(object)val == (Object)null) { val = DuplicateFont(DefaultFont); if ((Object)(object)val == (Object)null) { return null; } name = ((Object)DefaultFont).name; } ((Object)val).name = "[" + modName + "] " + name; if (cache) { if (!modFontCache.ContainsKey(modName)) { modFontCache[modName] = new Dictionary(); } modFontCache[modName][fontName] = val; } return val; } public static TMP_FontAsset DuplicateFont(TMP_FontAsset currentFont) { //IL_0078: 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_0035: 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_00c0: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)currentFont == (Object)null) { return null; } TMP_FontAsset val; if (!string.IsNullOrWhiteSpace(currentFont.m_SourceFontFilePath) && File.Exists(currentFont.m_SourceFontFilePath)) { val = TMP_FontAsset.CreateFontAsset(currentFont.m_SourceFontFilePath, 0, 90, currentFont.atlasPadding, currentFont.atlasRenderMode, currentFont.atlasWidth, currentFont.atlasHeight, currentFont.atlasPopulationMode, currentFont.isMultiAtlasTexturesEnabled); } else { if (!((Object)(object)currentFont.m_SourceFontFile != (Object)null)) { Logger.BigError("Font named " + ((Object)currentFont).name + " does not have a source."); return null; } val = TMP_FontAsset.CreateFontAsset(currentFont.m_SourceFontFile, 0, 90, currentFont.atlasPadding, currentFont.atlasRenderMode, currentFont.atlasWidth, currentFont.atlasHeight, currentFont.atlasPopulationMode, currentFont.isMultiAtlasTexturesEnabled); } ((Object)val).hideFlags = ((Object)currentFont).hideFlags; ((Object)val).name = ((Object)currentFont).name + " (duplicated)"; return val; } public override void OnInitializeMelon() { DefaultFont = TMP_FontAsset.CreateFontAsset(AssetBundles.LoadAssetFromStream((MelonMod)(object)this, "Fontifier.gooddogfont", "GOODDP__"), 0, 90, 5, (GlyphRenderMode)4165, 1024, 1024, (AtlasPopulationMode)1, true); ((Object)DefaultFont).hideFlags = (HideFlags)61; ((Object)DefaultFont).name = "Default - GOODDP__"; } public override void OnLateInitializeMelon() { UI.instance.UI_Initialized += OnUIInitialized; } private void OnUIInitialized() { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Expected O, but got Unknown ((Mod)ModUI).ModName = "Fontifier"; ((Mod)ModUI).ModVersion = "1.1.5"; ModUI.ModFormatVersion = "1.0.0"; ((Mod)ModUI).SetFolder("Fontifier"); ModUI.AddDescriptionAtStart("Description", "", "Lets you change the font for other mods.", new Tags { IsSummary = true }); HashSet hashSet = new HashSet(StringComparer.OrdinalIgnoreCase); foreach (string item in from f in Directory.EnumerateFiles("UserData\\Fontifier\\fonts", "*.*", SearchOption.TopDirectoryOnly) where f.EndsWith(".ttf", StringComparison.OrdinalIgnoreCase) || f.EndsWith(".otf", StringComparison.OrdinalIgnoreCase) select f) { try { TMP_FontAsset val = TMP_FontAsset.CreateFontAsset(item, 0, 90, 5, (GlyphRenderMode)4165, 1024, 1024); ((Object)val).hideFlags = (HideFlags)61; string text; try { FontFamily val2 = new FontCollection().Add(item); text = ((FontFamily)(ref val2)).Name; if (string.IsNullOrWhiteSpace(text)) { throw new Exception("Font has no internal family name"); } } catch (Exception ex) { Logger.Error("Could not read internal font name for " + item + ", using filename instead.", ex); text = Path.GetFileNameWithoutExtension(item); } if (string.IsNullOrWhiteSpace(text)) { throw new Exception("Font has an invalid name/filename"); } string text2 = text; int num = 0; while (hashSet.Contains(text2)) { num++; text2 = $"{text} ({num})"; } ((Object)val).name = text2; hashSet.Add(((Object)val).name); fonts.Add(val); } catch (Exception ex2) { Logger.Error("Failed to load font from " + item, ex2); } } ModUI.AddDescriptionAtIndex("Fonts List", "", "The following fonts are loaded:\n" + string.Join("\n", fonts.Select((TMP_FontAsset f) => ((Object)f).name)), new Tags { IsEmpty = true }, 1); foreach (MelonMod mod in MelonTypeBase.RegisteredMelons) { if (((MelonBase)mod).Info.Name.Equals("RUMBLE Tournament Scoring", StringComparison.OrdinalIgnoreCase)) { FieldInfo scoreboardText = ((object)mod).GetType().GetField("scoreboardText", BindingFlags.Instance | BindingFlags.NonPublic); if (scoreboardText == null) { Logger.Warning("RUMBLE Tournament Scoring's scoreboardText FieldInfo is null"); continue; } TournamentScoreboardText = () => (TextMeshPro)scoreboardText.GetValue(mod); TournamentScoringFont = RegisterModWithReferenceCopy("RUMBLE Tournament Scoring", TournamentScoringChanged); ((MelonBase)this).HarmonyInstance.Patch(TournamentScoringPatch.TargetMethod(mod), (HarmonyMethod)null, TournamentScoringPatch.GetPostfix, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } else if (((MelonBase)mod).Info.Name.Equals("MatchInfo", StringComparison.OrdinalIgnoreCase)) { MatchInfoFont = RegisterModWithReferenceCopy("MatchInfo", MatchInfoChanged); ((MelonBase)this).HarmonyInstance.Patch(MatchInfoPatch.TargetMethod(mod), (HarmonyMethod)null, MatchInfoPatch.GetPostfix, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } ((Mod)ModUI).GetFromFile(); UI.instance.AddMod((Mod)(object)ModUI); } private static void TournamentScoringChanged(object sender, EventArgs args) { TextMeshPro val = TournamentScoreboardText(); if ((Object)(object)val != (Object)null) { ((TMP_Text)val).font = FontFromNameCopy("RUMBLE Tournament Scoring", ((ValueChange)(object)args)?.Value, cache: true); } } private static void MatchInfoChanged(object sender, EventArgs args) { TMP_FontAsset font = FontFromNameCopy("MatchInfo", ((ValueChange)(object)args)?.Value, cache: true); if ((Object)(object)MatchInfoGameObject != (Object)null) { foreach (TextMeshPro componentsInChild in MatchInfoGameObject.GetComponentsInChildren(true)) { ((TMP_Text)componentsInChild).font = font; } } if (!((Object)(object)MatchInfoGymGameObject != (Object)null)) { return; } ((TMP_Text)MatchInfoGymGameObject.GetComponent()).font = font; foreach (TextMeshPro componentsInChild2 in MatchInfoGymGameObject.GetComponentsInChildren(true)) { ((TMP_Text)componentsInChild2).font = font; } } private static ModSetting RegisterModBase(string modName, EventHandler valueChanged) { ModSetting obj = ((Mod)ModUI).AddToList(modName, "", "Enter a font from the Font List or leave it empty to use the default font.\n\nMake sure to hit enter!", tags); ((Mod)ModUI).AddValidation(modName, (ValidationParameters)(object)validator); ((ModSetting)obj).CurrentValueChanged += valueChanged; return obj; } [Obsolete("Can caused unintended side effects. Use RegisterModCopy if possible.")] public static (Func, Func) RegisterMod(string modName, EventHandler valueChanged) { ModSetting setting = RegisterModBase(modName, valueChanged); return (() => FontFromName((string)((ModSetting)setting).Value), FontFromName); } public static (Func, Func) RegisterModCopy(string modName, EventHandler valueChanged) { ModSetting setting = RegisterModBase(modName, valueChanged); return ((bool cache) => FontFromNameCopy(modName, (string)((ModSetting)setting).Value, cache), (string fontName, bool cache) => FontFromNameCopy(modName, fontName, cache)); } private static ModSetting RegisterModWithReferenceBase(string modName, EventHandler valueChanged) { ModSetting obj = ((Mod)ModUI).AddToList(modName, "", "Enter a font from the Font List or leave it empty to use the default font.\n\nMake sure to hit enter!", tags); ((Mod)ModUI).AddValidation(modName, (ValidationParameters)(object)validator); ((ModSetting)obj).CurrentValueChanged += valueChanged; return obj; } [Obsolete("Can caused unintended side effects. Use RegisterModWithReferenceCopy if possible.")] public static Func RegisterModWithReference(string modName, EventHandler valueChanged) { ModSetting setting = RegisterModWithReferenceBase(modName, valueChanged); return () => FontFromName((string)((ModSetting)setting).Value); } public static Func RegisterModWithReferenceCopy(string modName, EventHandler valueChanged) { ModSetting setting = RegisterModWithReferenceBase(modName, valueChanged); return (bool cache) => FontFromNameCopy(modName, (string)((ModSetting)setting).Value, cache); } }