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 Valheim Viet Hoa v0.2.11
plugins/ValheimVietHoa/ValheimVietnameseFont.dll
Decompiled a day agousing System; using System.Collections; 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 BepInEx; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.TextCore.LowLevel; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("ValheimVietnameseFont")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+9ace735278ffd89e89db0466074df1844798748e")] [assembly: AssemblyProduct("ValheimVietnameseFont")] [assembly: AssemblyTitle("ValheimVietnameseFont")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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 ValheimVietnameseFont { [BepInPlugin("dev.valheim-vn.font-fallback", "Valheim Vietnamese Font Fallback", "0.2.11")] public sealed class VietnameseFontPlugin : BaseUnityPlugin { public const string PluginId = "dev.valheim-vn.font-fallback"; public const string PluginName = "Valheim Vietnamese Font Fallback"; public const string PluginVersion = "0.2.11"; private const string VietnameseCharacters = "ÀÁẠẢÃÂẦẤẬẨẪĂẰẮẶẲẴÈÉẸẺẼÊỀẾỆỂỄÌÍỊỈĨÒÓỌỎÕÔỒỐỘỔỖƠỜỚỢỞỠÙÚỤỦŨƯỪỨỰỬỮỲÝỴỶỸĐàáạảãâầấậẩẫăằắặẳẵèéẹẻẽêềếệểễìíịỉĩòóọỏõôồốộổỗơờớợởỡùúụủũưừứựửữỳýỵỷỹđ"; private TMP_FontAsset _customRegular; private TMP_FontAsset _customBold; private string _averiaSansPath; private string _averiaSerifPath; private TMP_FontAsset _sansFallback; private TMP_FontAsset _serifFallback; private readonly HashSet<int> _patchedAveriaAssets = new HashSet<int>(); private readonly Dictionary<Material, Material> _regularMaterials = new Dictionary<Material, Material>(); private readonly Dictionary<Material, Material> _boldMaterials = new Dictionary<Material, Material>(); private bool _installed; private void Awake() { ((MonoBehaviour)this).StartCoroutine(InstallWhenResourcesAreReady()); } private IEnumerator InstallWhenResourcesAreReady() { for (int attempt = 1; attempt <= 120; attempt++) { if (TryInstall()) { yield break; } yield return null; } ((BaseUnityPlugin)this).Logger.LogError((object)"Could not find Valheim's embedded Noto fonts after 120 frames."); } private bool TryInstall() { if (_installed) { return true; } Font[] source = Resources.FindObjectsOfTypeAll<Font>(); Font val = ((IEnumerable<Font>)source).FirstOrDefault((Func<Font, bool>)((Font font) => ((Object)font).name == "NotoSans-Regular")); Font val2 = ((IEnumerable<Font>)source).FirstOrDefault((Func<Font, bool>)((Font font) => ((Object)font).name == "NotoSerif-Regular")); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { return false; } string directoryName = Path.GetDirectoryName(typeof(VietnameseFontPlugin).Assembly.Location); _averiaSansPath = Path.Combine(directoryName, "ValheimVN-Sans-Regular.ttf"); _averiaSerifPath = Path.Combine(directoryName, "ValheimVN-Serif-Regular.ttf"); if (!File.Exists(_averiaSansPath) || !File.Exists(_averiaSerifPath)) { ((BaseUnityPlugin)this).Logger.LogError((object)"The bundled Vietnamese-complete Averia source files are missing; the original font assets cannot be populated safely."); return true; } _sansFallback = CreateFallback(val, "ValheimVN-NotoSans-Fallback"); _serifFallback = CreateFallback(val2, "ValheimVN-NotoSerif-Fallback"); if ((Object)(object)_sansFallback == (Object)null || (Object)(object)_serifFallback == (Object)null) { ((BaseUnityPlugin)this).Logger.LogError((object)"TextMeshPro could not create the embedded Noto safety fallback assets."); return true; } string text = Path.Combine(directoryName, "SVN-Norse Regular.otf"); string text2 = Path.Combine(directoryName, "SVN-Norse Bold.otf"); if (File.Exists(text) && File.Exists(text2)) { _customRegular = CreateFallback(text, "ValheimVN-SVN-Norse-Regular"); _customBold = CreateFallback(text2, "ValheimVN-SVN-Norse-Bold"); if ((Object)(object)_customRegular == (Object)null || (Object)(object)_customBold == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"SVN-Norse was found but TextMeshPro could not load it; using bundled Noto fonts."); _customRegular = null; _customBold = null; } } else { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Optional SVN-Norse fonts were not found; using Valheim's bundled Noto fonts."); } EnableFallbackMaterialPresetMatching(); AddGlobalFallback(_sansFallback); if ((Object)(object)_customRegular != (Object)null) { AddAssetFallback(_customRegular, _sansFallback); AddAssetFallback(_customBold, _sansFallback); } int num = PatchLoadedFontAssets(); int num2 = ReplaceLoadedFonts(); ((MonoBehaviour)this).StartCoroutine(PatchFontsAsTheyLoad()); string text3 = "Norse=" + (((Object)(object)_customRegular == (Object)null) ? "original" : "SVN-Norse Regular/Bold") + ", AveriaSans=original asset populated from patched bundled source, AveriaSerif=original asset populated from patched bundled source, Noto safety fallback"; ((BaseUnityPlugin)this).Logger.LogInfo((object)("Vietnamese font fallback ready with " + text3 + "; preloaded " + string.Format("{0} characters, patched {1} fallback tables, ", "ÀÁẠẢÃÂẦẤẬẨẪĂẰẮẶẲẴÈÉẸẺẼÊỀẾỆỂỄÌÍỊỈĨÒÓỌỎÕÔỒỐỘỔỖƠỜỚỢỞỠÙÚỤỦŨƯỪỨỰỬỮỲÝỴỶỸĐàáạảãâầấậẩẫăằắặẳẵèéẹẻẽêềếệểễìíịỉĩòóọỏõôồốộổỗơờớợởỡùúụủũưừứựửữỳýỵỷỹđ".Length, num) + $"and replaced {num2} loaded text components.")); _installed = true; return true; } private TMP_FontAsset CreateFallback(string fontPath, string assetName) { TMP_FontAsset asset = TMP_FontAsset.CreateFontAsset(fontPath, 0, 64, 8, (GlyphRenderMode)4165, 2048, 2048); return PrepareFallback(asset, assetName); } private TMP_FontAsset CreateFallback(Font source, string assetName) { TMP_FontAsset asset = TMP_FontAsset.CreateFontAsset(source, 64, 8, (GlyphRenderMode)4165, 2048, 2048, (AtlasPopulationMode)1, true); return PrepareFallback(asset, assetName); } private TMP_FontAsset PrepareFallback(TMP_FontAsset asset, string assetName) { if ((Object)(object)asset == (Object)null) { return null; } ((Object)asset).name = assetName; ((Object)asset).hideFlags = (HideFlags)61; string text = default(string); if (!asset.TryAddCharacters("ÀÁẠẢÃÂẦẤẬẨẪĂẰẮẶẲẴÈÉẸẺẼÊỀẾỆỂỄÌÍỊỈĨÒÓỌỎÕÔỒỐỘỔỖƠỜỚỢỞỠÙÚỤỦŨƯỪỨỰỬỮỲÝỴỶỸĐàáạảãâầấậẩẫăằắặẳẵèéẹẻẽêềếệểễìíịỉĩòóọỏõôồốộổỗơờớợởỡùúụủũưừứựửữỳýỵỷỹđ", ref text, true)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)(assetName + " could not preload: " + text)); } return asset; } private void EnableFallbackMaterialPresetMatching() { if (TMP_Settings.matchMaterialPreset) { return; } FieldInfo field = typeof(TMP_Settings).GetField("m_matchMaterialPreset", BindingFlags.Instance | BindingFlags.NonPublic); if (field == null || (Object)(object)TMP_Settings.instance == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Could not enable TextMeshPro fallback material matching; fallback glyph outlines may differ."); return; } try { field.SetValue(TMP_Settings.instance, true); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not enable TextMeshPro fallback material matching: " + ex.Message)); return; } TMP_Text[] array = Resources.FindObjectsOfTypeAll<TMP_Text>(); foreach (TMP_Text val in array) { if ((Object)(object)val != (Object)null) { ((Graphic)val).SetAllDirty(); } } ((BaseUnityPlugin)this).Logger.LogInfo((object)"TextMeshPro fallback material preset matching enabled."); } private IEnumerator PatchFontsAsTheyLoad() { WaitForSecondsRealtime wait = new WaitForSecondsRealtime(1f); while (true) { PatchLoadedFontAssets(); ReplaceLoadedFonts(); yield return wait; } } private int PatchLoadedFontAssets() { int num = 0; TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>(); foreach (TMP_FontAsset val in array) { if ((Object)(object)val == (Object)null || (Object)(object)val == (Object)(object)_customRegular || (Object)(object)val == (Object)(object)_customBold || (Object)(object)val == (Object)(object)_sansFallback || (Object)(object)val == (Object)(object)_serifFallback) { continue; } if (IsValheimAveriaSans(val)) { if (PopulateAveriaAsset(val, _averiaSansPath, _sansFallback)) { num++; } continue; } if (IsValheimAveriaSerif(val)) { if (PopulateAveriaAsset(val, _averiaSerifPath, _serifFallback)) { num++; } continue; } TMP_FontAsset fallback = ((((Object)val).name.IndexOf("Serif", StringComparison.OrdinalIgnoreCase) >= 0) ? _serifFallback : _sansFallback); if (AddAssetFallback(val, fallback)) { num++; } } return num; } private bool PopulateAveriaAsset(TMP_FontAsset asset, string sourcePath, TMP_FontAsset safetyFallback) { if (!_patchedAveriaAssets.Add(((Object)asset).GetInstanceID())) { return false; } FieldInfo field = typeof(TMP_FontAsset).GetField("m_SourceFontFile", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo field2 = typeof(TMP_FontAsset).GetField("m_SourceFontFilePath", BindingFlags.Instance | BindingFlags.NonPublic); if (field == null || field2 == null) { ((BaseUnityPlugin)this).Logger.LogError((object)("Could not attach the bundled source font to " + ((Object)asset).name + ".")); AddAssetFallback(asset, safetyFallback); return true; } try { field.SetValue(asset, null); field2.SetValue(asset, sourcePath); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Could not attach the source font to " + ((Object)asset).name + ": " + ex.Message)); AddAssetFallback(asset, safetyFallback); return true; } asset.atlasPopulationMode = (AtlasPopulationMode)1; asset.isMultiAtlasTexturesEnabled = true; string text = new string("ÀÁẠẢÃÂẦẤẬẨẪĂẰẮẶẲẴÈÉẸẺẼÊỀẾỆỂỄÌÍỊỈĨÒÓỌỎÕÔỒỐỘỔỖƠỜỚỢỞỠÙÚỤỦŨƯỪỨỰỬỮỲÝỴỶỸĐàáạảãâầấậẩẫăằắặẳẵèéẹẻẽêềếệểễìíịỉĩòóọỏõôồốộổỗơờớợởỡùúụủũưừứựửữỳýỵỷỹđ".Where((char character) => !asset.HasCharacter(character, false, false)).ToArray()); if (text.Length > 0) { string text2 = default(string); asset.TryAddCharacters(text, ref text2, true); } string text3 = new string("ÀÁẠẢÃÂẦẤẬẨẪĂẰẮẶẲẴÈÉẸẺẼÊỀẾỆỂỄÌÍỊỈĨÒÓỌỎÕÔỒỐỘỔỖƠỜỚỢỞỠÙÚỤỦŨƯỪỨỰỬỮỲÝỴỶỸĐàáạảãâầấậẩẫăằắặẳẵèéẹẻẽêềếệểễìíịỉĩòóọỏõôồốộổỗơờớợởỡùúụủũưừứựửữỳýỵỷỹđ".Where((char character) => !asset.HasCharacter(character, false, false)).ToArray()); if (text3.Length > 0) { ((BaseUnityPlugin)this).Logger.LogWarning((object)(((Object)asset).name + " could not add Vietnamese glyphs in place: " + text3)); AddAssetFallback(asset, safetyFallback); } else { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Populated " + ((Object)asset).name + " in place with its original material and " + $"{asset.atlasTextureCount} atlas texture(s).")); } TMP_Text[] array = Resources.FindObjectsOfTypeAll<TMP_Text>(); foreach (TMP_Text val in array) { if ((Object)(object)val != (Object)null && (Object)(object)val.font == (Object)(object)asset) { ((Graphic)val).SetAllDirty(); } } return true; } private int ReplaceLoadedFonts() { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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_005e: Invalid comparison between Unknown and I4 int num = 0; TMP_Text[] array = Resources.FindObjectsOfTypeAll<TMP_Text>(); foreach (TMP_Text val in array) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val.font == (Object)null)) { bool flag = ((Object)val.font).name.IndexOf("bold", StringComparison.OrdinalIgnoreCase) >= 0 || (val.fontStyle & 1) != 0 || (int)val.fontWeight >= 700; TMP_FontAsset val2 = null; if (IsValheimNorse(val.font) && (Object)(object)_customRegular != (Object)null && (Object)(object)_customBold != (Object)null) { val2 = (flag ? _customBold : _customRegular); } if (!((Object)(object)val2 == (Object)null)) { Material fontSharedMaterial = val.fontSharedMaterial; val.font = val2; val.fontSharedMaterial = GetReplacementMaterial(fontSharedMaterial, val2, flag); num++; } } } return num; } private bool IsValheimNorse(TMP_FontAsset asset) { if ((Object)(object)asset != (Object)null && (Object)(object)asset != (Object)(object)_customRegular && (Object)(object)asset != (Object)(object)_customBold) { return ((Object)asset).name.StartsWith("Valheim-Norse", StringComparison.OrdinalIgnoreCase); } return false; } private bool IsValheimAveriaSans(TMP_FontAsset asset) { if ((Object)(object)asset != (Object)null) { return ((Object)asset).name.StartsWith("Valheim-AveriaSansLibre", StringComparison.OrdinalIgnoreCase); } return false; } private bool IsValheimAveriaSerif(TMP_FontAsset asset) { if ((Object)(object)asset != (Object)null) { return ((Object)asset).name.StartsWith("Valheim-AveriaSerifLibre", StringComparison.OrdinalIgnoreCase); } return false; } private Material GetReplacementMaterial(Material source, TMP_FontAsset replacement, bool bold) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown if ((Object)(object)source == (Object)null) { return ((TMP_Asset)replacement).material; } Dictionary<Material, Material> dictionary = (bold ? _boldMaterials : _regularMaterials); if (dictionary.TryGetValue(source, out var value) && (Object)(object)value != (Object)null) { return value; } Material val = new Material(((TMP_Asset)replacement).material); TMP_MaterialManager.CopyMaterialPresetProperties(source, val); ((Object)val).name = ((Object)source).name + " (" + ((Object)replacement).name + ")"; ((Object)val).hideFlags = (HideFlags)61; dictionary[source] = val; return val; } private static bool AddAssetFallback(TMP_FontAsset asset, TMP_FontAsset fallback) { if ((Object)(object)asset == (Object)null || (Object)(object)fallback == (Object)null) { return false; } if (asset.fallbackFontAssetTable == null) { asset.fallbackFontAssetTable = new List<TMP_FontAsset>(); } if (asset.fallbackFontAssetTable.Contains(fallback)) { return false; } asset.fallbackFontAssetTable.Insert(0, fallback); return true; } private static void AddGlobalFallback(TMP_FontAsset fallback) { if (TMP_Settings.fallbackFontAssets == null) { TMP_Settings.fallbackFontAssets = new List<TMP_FontAsset>(); } if (!TMP_Settings.fallbackFontAssets.Contains(fallback)) { TMP_Settings.fallbackFontAssets.Insert(0, fallback); } } } }