using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using TMPro; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.TextCore; using UnityEngine.TextCore.LowLevel; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("UU9.Muck.Translater")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("P R C")] [assembly: AssemblyProduct("UU9.Muck.Translater")] [assembly: AssemblyCopyright("Copyright © P R C 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("63b5c9fb-b128-4ef9-bbde-452c57595106")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace UU9.Muck.Translater; [BepInPlugin("UU9.Muck.Translater", "UU9 Muck Translater", "1.0.0")] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "UU9.Muck.Translater"; public const string PluginName = "UU9 Muck Translater"; public const string PluginVersion = "1.0.0"; private Harmony _harmony; private static Plugin _instance; private int _pendingTextRefreshFrames; private static ConfigEntry _fontFile; private static ConfigEntry _enableF5Reload; private static ConfigEntry _enableF6Toggle; public static ManualLogSource Log { get; private set; } public static string FontFile => _fontFile?.Value ?? "msyh.ttc"; public static bool IsF5ReloadEnabled => _enableF5Reload?.Value ?? true; public static bool IsF6ToggleEnabled => _enableF6Toggle?.Value ?? true; public static bool IsTranslationEnabled { get; private set; } = true; private void Awake() { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; _instance = this; try { InitializeSettings(); FontManager.Initialize(Log); TranslationManager.Initialize(Log); _harmony = new Harmony("UU9.Muck.Translater"); _harmony.PatchAll(Assembly.GetExecutingAssembly()); SceneManager.sceneLoaded += OnSceneLoaded; RefreshSceneTexts(); Log.LogInfo((object)"[UU9 Translater] UU9 Muck Translater v1.0.0 初始化成功!按下 F5 可热重载词典。"); } catch (Exception ex) { Log.LogError((object)("[UU9 Translater] 初始化阶段抛出异常: " + ex.Message)); } } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { Log.LogInfo((object)("[UU9 Translater] 检测到场景加载: " + ((Scene)(ref scene)).name + ",正在自动刷新 UI 汉化文本...")); RefreshSceneTexts(); } private static void InitializeSettings() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown string text = Path.Combine(Paths.ConfigPath, "UU9.Muck.Translater"); Directory.CreateDirectory(text); string text2 = Path.Combine(text, "UU9.Muck.Translater.cfg"); ConfigFile val = new ConfigFile(text2, true); _fontFile = val.Bind("General", "FontFile", "msyh.ttc", "Font filename to use. Searches C:\\Windows\\Fonts first, then BepInEx\\config\\UU9.Muck.Translater\\Font."); _enableF5Reload = val.Bind("Hotkeys", "EnableF5Reload", true, "Enable F5 dictionary reload."); _enableF6Toggle = val.Bind("Hotkeys", "EnableF6Toggle", true, "Enable F6 translation toggle."); } private void Update() { if (_pendingTextRefreshFrames > 0) { _pendingTextRefreshFrames--; if (_pendingTextRefreshFrames == 0 && IsTranslationEnabled) { RefreshSceneTexts(logCompletion: false); } } if (IsF5ReloadEnabled && Input.GetKeyDown((KeyCode)286)) { Log.LogInfo((object)"[UU9 Translater] 触发 F5 热重载,正在重新读取汉化词典并更新界面..."); TranslationManager.LoadTranslations(); if (IsTranslationEnabled) { RefreshSceneTexts(); } } if (IsF6ToggleEnabled && Input.GetKeyDown((KeyCode)287)) { IsTranslationEnabled = !IsTranslationEnabled; if (IsTranslationEnabled) { Log.LogInfo((object)"[UU9 Translater] 触发 F6:开启汉化,正在还原汉化文本..."); RefreshSceneTexts(); } else { Log.LogInfo((object)"[UU9 Translater] 触发 F6:暂时关闭汉化,正在还原为英文原文..."); RestoreOriginalSceneTexts(); } } } public static void RequestSceneTextRefresh() { if (!((Object)(object)_instance == (Object)null) && _instance._pendingTextRefreshFrames == 0) { _instance._pendingTextRefreshFrames = 2; } } private void RestoreOriginalSceneTexts() { try { int num = 0; TMP_Text[] array = Resources.FindObjectsOfTypeAll(); TMP_Text[] array2 = array; foreach (TMP_Text val in array2) { if (!((Object)(object)val == (Object)null) && ((Component)val).gameObject.activeInHierarchy && TranslationManager.TryGetOriginal(val.text, out var original) && val.text != original) { val.text = original; num++; } } Text[] array3 = Resources.FindObjectsOfTypeAll(); Text[] array4 = array3; foreach (Text val2 in array4) { if (!((Object)(object)val2 == (Object)null) && ((Component)val2).gameObject.activeInHierarchy && TranslationManager.TryGetOriginal(val2.text, out var original2) && val2.text != original2) { val2.text = original2; num++; } } FontManager.RestoreOriginalFonts(); Log.LogInfo((object)$"[UU9 Translater] F6 还原完成,成功将 {num} 处文本还原为英文原文。"); } catch (Exception ex) { Log.LogError((object)("[UU9 Translater] 还原英文原文 UI 出错: " + ex.Message)); } } private void RefreshSceneTexts(bool logCompletion = true) { try { int num = 0; TMP_Text[] array = Resources.FindObjectsOfTypeAll(); TMP_Text[] array2 = array; foreach (TMP_Text val in array2) { if (!((Object)(object)val == (Object)null) && ((Component)val).gameObject.activeInHierarchy) { FontManager.ApplyFont(val); if (TranslationManager.TryGetTranslation(val.text, out var translated) && val.text != translated) { FontManager.ApplyTranslatedFont(val, translated); val.text = translated; FontManager.RefreshLayout(val); num++; } } } Text[] array3 = Resources.FindObjectsOfTypeAll(); Text[] array4 = array3; foreach (Text val2 in array4) { if (!((Object)(object)val2 == (Object)null) && ((Component)val2).gameObject.activeInHierarchy) { FontManager.ApplyFont(val2); if (TranslationManager.TryGetTranslation(val2.text, out var translated2) && val2.text != translated2) { val2.text = translated2; num++; } } } if (logCompletion) { Log.LogInfo((object)$"[UU9 Translater] F5 刷新完成,成功更新 {num} 处文本。"); } } catch (Exception ex) { Log.LogError((object)("[UU9 Translater] 刷新场景 UI 文本出错: " + ex.Message)); } } private void OnDestroy() { SceneManager.sceneLoaded -= OnSceneLoaded; Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } if ((Object)(object)_instance == (Object)(object)this) { _instance = null; } } } public static class FontManager { private static Font _chineseOSFont; private static TMP_FontAsset _chineseTMPFont; private static ManualLogSource _logger; private static bool _initialized; private static readonly Dictionary OriginalTMPFonts = new Dictionary(); private static readonly Dictionary OriginalTMPMaterials = new Dictionary(); private static readonly Dictionary OriginalUIFonts = new Dictionary(); private static readonly Dictionary ChineseMaterialsBySource = new Dictionary(); public static void Initialize(ManualLogSource logger) { //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Expected O, but got Unknown //IL_02dc: Unknown result type (might be due to invalid IL or missing references) if (_initialized) { return; } _logger = logger; try { string text = Path.GetFileName(Plugin.FontFile); if (string.IsNullOrWhiteSpace(text)) { text = "msyh.ttc"; } string path = Path.Combine(Paths.ConfigPath, "UU9.Muck.Translater", "Font"); string[] array = new string[7] { Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Fonts), text), Path.Combine(path, text), "C:\\Windows\\Fonts\\msyh.ttc", "C:\\Windows\\Fonts\\msyh.ttf", "C:\\Windows\\Fonts\\simhei.ttf", "C:\\Windows\\Fonts\\simsun.ttc", "C:\\Windows\\Fonts\\arial.ttf" }; string[] array2 = array; foreach (string text2 in array2) { if (!File.Exists(text2)) { continue; } try { _chineseOSFont = new Font(text2); if ((Object)(object)_chineseOSFont != (Object)null) { Object.DontDestroyOnLoad((Object)(object)_chineseOSFont); ((Object)_chineseOSFont).hideFlags = (HideFlags)61; break; } } catch { } } if ((Object)(object)_chineseOSFont == (Object)null) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text); string[] array3 = new string[5] { fileNameWithoutExtension, "Microsoft YaHei UI", "Microsoft YaHei", "SimHei", "Arial" }; _chineseOSFont = Font.CreateDynamicFontFromOSFont(array3, 24); if ((Object)(object)_chineseOSFont != (Object)null) { Object.DontDestroyOnLoad((Object)(object)_chineseOSFont); ((Object)_chineseOSFont).hideFlags = (HideFlags)61; } } if ((Object)(object)_chineseOSFont == (Object)null) { _chineseOSFont = Resources.GetBuiltinResource("Arial.ttf"); } if ((Object)(object)_chineseOSFont != (Object)null) { try { _chineseTMPFont = TMP_FontAsset.CreateFontAsset(_chineseOSFont, 90, 5, (GlyphRenderMode)4165, 4096, 4096, (AtlasPopulationMode)1, false); } catch { } if ((Object)(object)_chineseTMPFont != (Object)null) { Object.DontDestroyOnLoad((Object)(object)_chineseTMPFont); ((Object)_chineseTMPFont).name = "UU9_Chinese_TMPFont"; ((Object)_chineseTMPFont).hideFlags = (HideFlags)61; _chineseTMPFont.atlasPopulationMode = (AtlasPopulationMode)1; _chineseTMPFont.isMultiAtlasTexturesEnabled = false; try { if ((Object)(object)TMP_Settings.defaultFontAsset != (Object)null) { FaceInfo faceInfo = TMP_Settings.defaultFontAsset.faceInfo; FaceInfo faceInfo2 = _chineseTMPFont.faceInfo; if (((FaceInfo)(ref faceInfo)).lineHeight > 0f && ((FaceInfo)(ref faceInfo2)).lineHeight > 0f) { float num = ((FaceInfo)(ref faceInfo)).lineHeight / ((FaceInfo)(ref faceInfo2)).lineHeight; ((FaceInfo)(ref faceInfo2)).lineHeight = ((FaceInfo)(ref faceInfo)).lineHeight; ((FaceInfo)(ref faceInfo2)).ascentLine = (int)(((FaceInfo)(ref faceInfo2)).ascentLine * num); ((FaceInfo)(ref faceInfo2)).descentLine = (int)(((FaceInfo)(ref faceInfo2)).descentLine * num); _chineseTMPFont.faceInfo = faceInfo2; } } } catch { } try { if (TMP_Settings.fallbackFontAssets != null && !TMP_Settings.fallbackFontAssets.Contains(_chineseTMPFont)) { TMP_Settings.fallbackFontAssets.Add(_chineseTMPFont); } if ((Object)(object)TMP_Settings.defaultFontAsset != (Object)null) { if (TMP_Settings.defaultFontAsset.fallbackFontAssetTable == null) { TMP_Settings.defaultFontAsset.fallbackFontAssetTable = new List(); } if (!TMP_Settings.defaultFontAsset.fallbackFontAssetTable.Contains(_chineseTMPFont)) { TMP_Settings.defaultFontAsset.fallbackFontAssetTable.Add(_chineseTMPFont); } } } catch { } } } _initialized = true; } catch (Exception ex) { ManualLogSource logger2 = _logger; if (logger2 != null) { logger2.LogError((object)("[UU9 Translater] FontManager 初始化异常: " + ex.Message)); } } } public static void AddCharactersToFont(string text) { if ((Object)(object)_chineseTMPFont == (Object)null || string.IsNullOrEmpty(text)) { return; } try { _chineseTMPFont.TryAddCharacters(text, false); } catch { } } public static void ApplyTranslatedFont(TMP_Text tmpText, string translated) { if ((Object)(object)tmpText == (Object)null || (Object)(object)_chineseTMPFont == (Object)null || string.IsNullOrEmpty(translated)) { return; } try { AddCharactersToFont(translated); if (ContainsNonAscii(translated) && (Object)(object)tmpText.font != (Object)(object)_chineseTMPFont) { RememberOriginalFont(tmpText); Material fontSharedMaterial = tmpText.fontSharedMaterial; tmpText.font = _chineseTMPFont; Material chineseMaterial = GetChineseMaterial(fontSharedMaterial); if ((Object)(object)chineseMaterial != (Object)null) { tmpText.fontSharedMaterial = chineseMaterial; } } } catch { } } public static void RefreshLayout(TMP_Text tmpText) { if ((Object)(object)tmpText == (Object)null) { return; } try { ((Graphic)tmpText).SetVerticesDirty(); ((Graphic)tmpText).SetLayoutDirty(); tmpText.ForceMeshUpdate(false, false); LayoutRebuilder.ForceRebuildLayoutImmediate(tmpText.rectTransform); Transform parent = ((Transform)tmpText.rectTransform).parent; RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null); if ((Object)(object)val != (Object)null) { LayoutRebuilder.MarkLayoutForRebuild(val); } } catch { } } private static bool ContainsNonAscii(string text) { foreach (char c in text) { if (c > '\u007f') { return true; } } return false; } public static void ApplyFont(TMP_Text tmpText) { if ((Object)(object)tmpText == (Object)null || (Object)(object)_chineseTMPFont == (Object)null) { return; } try { if ((Object)(object)tmpText.font != (Object)null) { if ((Object)(object)tmpText.font != (Object)(object)_chineseTMPFont) { if (tmpText.font.fallbackFontAssetTable == null) { tmpText.font.fallbackFontAssetTable = new List(); } if (!tmpText.font.fallbackFontAssetTable.Contains(_chineseTMPFont)) { tmpText.font.fallbackFontAssetTable.Add(_chineseTMPFont); } } } else { tmpText.font = _chineseTMPFont; } if (tmpText.text != null && tmpText.text.Contains("\n")) { tmpText.lineSpacingAdjustment = 0f; } } catch { } } public static void ApplyFont(Text uiText) { if ((Object)(object)uiText == (Object)null || (Object)(object)_chineseOSFont == (Object)null) { return; } try { RememberOriginalFont(uiText); uiText.font = _chineseOSFont; } catch { } } public static void RestoreOriginalFonts() { try { TMP_Text[] array = Resources.FindObjectsOfTypeAll(); TMP_Text[] array2 = array; foreach (TMP_Text val in array2) { if ((Object)(object)val == (Object)null) { continue; } int instanceID = ((Object)val).GetInstanceID(); if (OriginalTMPFonts.TryGetValue(instanceID, out var value)) { if ((Object)(object)value != (Object)null) { val.font = value; } if (OriginalTMPMaterials.TryGetValue(instanceID, out var value2) && (Object)(object)value2 != (Object)null) { val.fontSharedMaterial = value2; } OriginalTMPFonts.Remove(instanceID); OriginalTMPMaterials.Remove(instanceID); } } Text[] array3 = Resources.FindObjectsOfTypeAll(); Text[] array4 = array3; foreach (Text val2 in array4) { if ((Object)(object)val2 == (Object)null) { continue; } int instanceID2 = ((Object)val2).GetInstanceID(); if (OriginalUIFonts.TryGetValue(instanceID2, out var value3)) { if ((Object)(object)value3 != (Object)null) { val2.font = value3; } OriginalUIFonts.Remove(instanceID2); } } } catch (Exception ex) { ManualLogSource logger = _logger; if (logger != null) { logger.LogError((object)("[UU9 Translater] Restore original fonts failed: " + ex.Message)); } } } private static void RememberOriginalFont(TMP_Text tmpText) { int instanceID = ((Object)tmpText).GetInstanceID(); if (!OriginalTMPFonts.ContainsKey(instanceID)) { OriginalTMPFonts[instanceID] = tmpText.font; OriginalTMPMaterials[instanceID] = tmpText.fontSharedMaterial; } } private static Material GetChineseMaterial(Material sourceMaterial) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown if ((Object)(object)sourceMaterial == (Object)null || (Object)(object)_chineseTMPFont == (Object)null) { return null; } int instanceID = ((Object)sourceMaterial).GetInstanceID(); if (ChineseMaterialsBySource.TryGetValue(instanceID, out var value) && (Object)(object)value != (Object)null) { return value; } try { Material val = new Material(sourceMaterial); ((Object)val).name = "UU9_Chinese_" + ((Object)sourceMaterial).name; val.mainTexture = (Texture)(object)_chineseTMPFont.atlasTexture; ((Object)val).hideFlags = (HideFlags)61; ChineseMaterialsBySource[instanceID] = val; return val; } catch { return null; } } private static void RememberOriginalFont(Text uiText) { int instanceID = ((Object)uiText).GetInstanceID(); if (!OriginalUIFonts.ContainsKey(instanceID)) { OriginalUIFonts[instanceID] = uiText.font; } } } public static class TranslationManager { private static readonly Dictionary Translations = new Dictionary(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary ReverseTranslations = new Dictionary(StringComparer.OrdinalIgnoreCase); private static readonly Regex RichTextRegex = new Regex("<[^>]*>", RegexOptions.Compiled); private static string _translationDir; private static ManualLogSource _logger; private static List _cachedSortedKeys; public static void Initialize(ManualLogSource logger) { _logger = logger; _translationDir = Path.Combine(Paths.ConfigPath, "UU9.Muck.Translater", "Translation"); Directory.CreateDirectory(_translationDir); LoadTranslations(); } public static void LoadTranslations() { Translations.Clear(); ReverseTranslations.Clear(); _cachedSortedKeys = null; if (string.IsNullOrEmpty(_translationDir) || !Directory.Exists(_translationDir)) { return; } try { string[] files = Directory.GetFiles(_translationDir, "*.cfg", SearchOption.AllDirectories); int num = 0; StringBuilder stringBuilder = new StringBuilder(); string[] array = files; foreach (string path in array) { string[] array2 = File.ReadAllLines(path, Encoding.UTF8); foreach (string text in array2) { if (string.IsNullOrWhiteSpace(text) || text.StartsWith("#") || text.StartsWith("//")) { continue; } int num2 = text.IndexOf('='); if (num2 <= 0) { continue; } string text2 = text.Substring(0, num2).Trim().Replace("\\n", "\n") .Replace("\\r", "\r"); string text3 = text.Substring(num2 + 1).Trim().Replace("\\n", "\n") .Replace("\\r", "\r"); if (!string.IsNullOrEmpty(text2) && !Translations.ContainsKey(text2)) { Translations[text2] = text3; if (!string.IsNullOrEmpty(text3) && !ReverseTranslations.ContainsKey(text3)) { ReverseTranslations[text3] = text2; } stringBuilder.Append(text3); num++; } } } for (char c = ' '; c <= '~'; c = (char)(c + 1)) { stringBuilder.Append(c); } FontManager.AddCharactersToFont(stringBuilder.ToString()); ManualLogSource logger = _logger; if (logger != null) { logger.LogInfo((object)$"[UU9 Translater] 从 {files.Length} 个词典文件加载 {num} 条翻译文本:{_translationDir}"); } } catch (Exception ex) { ManualLogSource logger2 = _logger; if (logger2 != null) { logger2.LogError((object)("[UU9 Translater] 读取词典目录失败: " + ex.Message)); } } } public static bool TryGetOriginal(string translated, out string original) { original = null; if (string.IsNullOrWhiteSpace(translated)) { return false; } if (ReverseTranslations.TryGetValue(translated, out original)) { return true; } string key = translated.Trim(); if (ReverseTranslations.TryGetValue(key, out var value)) { original = PreserveOuterWhitespace(translated, value); return true; } return TryTranslateLines(translated, ReverseTranslations, out original); } public static bool TryGetTranslation(string original, out string translated) { translated = null; if (string.IsNullOrWhiteSpace(original)) { return false; } if (Translations.TryGetValue(original, out translated)) { return true; } string key = original.Trim(); if (Translations.TryGetValue(key, out var value)) { translated = PreserveOuterWhitespace(original, value); return true; } if (TryTranslateLines(original, Translations, out translated)) { return true; } string text = original; bool flag = false; foreach (string sortedTranslationKey in GetSortedTranslationKeys()) { if (!string.IsNullOrEmpty(sortedTranslationKey) && text.IndexOf(sortedTranslationKey, StringComparison.OrdinalIgnoreCase) >= 0) { text = ReplaceWordOrPhrase(text, sortedTranslationKey, Translations[sortedTranslationKey]); flag = true; } } if (!flag) { return false; } translated = text; return true; } private static bool TryTranslateLines(string input, Dictionary dictionary, out string translated) { translated = null; if (!input.Contains("\n")) { return false; } string[] array = input.Split(new char[1] { '\n' }); bool flag = false; for (int i = 0; i < array.Length; i++) { string text = array[i]; string text2 = text.Trim('\r', ' '); if (!dictionary.TryGetValue(text2, out var value)) { string text3 = RichTextRegex.Replace(text2, string.Empty); if (!dictionary.TryGetValue(text3, out value)) { continue; } array[i] = text.Replace(text3, value); } else { array[i] = text.Replace(text2, value); } flag = true; } if (!flag) { return false; } translated = string.Join("\n", array); return true; } private static string PreserveOuterWhitespace(string original, string replacement) { int length = original.Length - original.TrimStart(Array.Empty()).Length; int num = original.Length - original.TrimEnd(Array.Empty()).Length; return original.Substring(0, length) + replacement + original.Substring(original.Length - num); } private static List GetSortedTranslationKeys() { if (_cachedSortedKeys != null) { return _cachedSortedKeys; } _cachedSortedKeys = new List(Translations.Keys); _cachedSortedKeys.Sort((string a, string b) => b.Length.CompareTo(a.Length)); return _cachedSortedKeys; } private static string ReplaceWordOrPhrase(string input, string pattern, string replacement) { bool flag = true; foreach (char c in pattern) { if (!char.IsLetterOrDigit(c) && c != '_') { flag = false; break; } } string text = Regex.Escape(pattern); if (flag) { text = "\\b" + text + "\\b"; } return Regex.Replace(input, text, replacement, RegexOptions.IgnoreCase); } } [HarmonyPatch(typeof(TMP_Text))] internal static class TMP_Text_Patches { [HarmonyPrefix] [HarmonyPatch("SetTextInternal")] public static void SetTextInternal_Prefix(TMP_Text __instance, ref string __0) { TranslateAndUpdateFont(__instance, ref __0); } [HarmonyPrefix] [HarmonyPatch(/*Could not decode attribute arguments.*/)] public static void SetTextProperty_Prefix(TMP_Text __instance, ref string value) { TranslateAndUpdateFont(__instance, ref value); } [HarmonyPrefix] [HarmonyPatch("SetText", new Type[] { typeof(string), typeof(bool) })] public static void SetText_Prefix(TMP_Text __instance, ref string __0) { TranslateAndUpdateFont(__instance, ref __0); } [HarmonyPrefix] [HarmonyPatch("SetText", new Type[] { typeof(string), typeof(float) })] public static void SetText_OneValue_Prefix(TMP_Text __instance, ref string __0) { TranslateAndUpdateFont(__instance, ref __0); } [HarmonyPrefix] [HarmonyPatch("SetText", new Type[] { typeof(string), typeof(float), typeof(float) })] public static void SetText_TwoValues_Prefix(TMP_Text __instance, ref string __0) { TranslateAndUpdateFont(__instance, ref __0); } [HarmonyPrefix] [HarmonyPatch("SetText", new Type[] { typeof(string), typeof(float), typeof(float), typeof(float) })] public static void SetText_ThreeValues_Prefix(TMP_Text __instance, ref string __0) { TranslateAndUpdateFont(__instance, ref __0); } [HarmonyPrefix] [HarmonyPatch("SetText", new Type[] { typeof(StringBuilder) })] public static void SetText_StringBuilder_Prefix(TMP_Text __instance, ref StringBuilder __0) { try { if (__0 != null && !((Object)(object)__instance == (Object)null)) { string original = __0.ToString(); FontManager.ApplyFont(__instance); if (TranslationManager.TryGetTranslation(original, out var translated)) { FontManager.ApplyTranslatedFont(__instance, translated); __0 = new StringBuilder(translated); } } } catch { } } private static void TranslateAndUpdateFont(TMP_Text component, ref string text) { try { if (Plugin.IsTranslationEnabled && !((Object)(object)component == (Object)null) && !string.IsNullOrEmpty(text)) { FontManager.ApplyFont(component); if (TranslationManager.TryGetTranslation(text, out var translated)) { FontManager.ApplyTranslatedFont(component, translated); text = translated; } } } catch { } } } [HarmonyPatch] internal static class TMP_GetTextElement_Patch { [HarmonyTargetMethod] public static MethodBase TargetMethod() { MethodInfo methodInfo = AccessTools.Method(typeof(TMP_Text), "GetTextElement", new Type[1] { typeof(int) }, (Type[])null); if (methodInfo == null) { methodInfo = AccessTools.Method(typeof(TMP_Text), "GetTextElement", new Type[1] { typeof(uint) }, (Type[])null); } if (methodInfo == null) { methodInfo = AccessTools.Method(typeof(TMP_Text), "GetTextElement", new Type[1] { typeof(char) }, (Type[])null); } if (methodInfo == null) { methodInfo = AccessTools.FirstMethod(typeof(TMP_Text), (Func)((MethodInfo m) => m.Name == "GetTextElement")); } return methodInfo; } [HarmonyPostfix] public static void Postfix(object __0, ref TMP_TextElement __result) { if (__result != null || __0 == null) { return; } try { int num = Convert.ToInt32(__0); if (num > 0) { string text = char.ConvertFromUtf32(num); FontManager.AddCharactersToFont(text); } } catch { } } } [HarmonyPatch(typeof(Text))] internal static class UnityEngine_UI_Text_Patches { [HarmonyPrefix] [HarmonyPatch(/*Could not decode attribute arguments.*/)] public static void SetTextProperty_Prefix(Text __instance, ref string value) { TranslateAndUpdateFont(__instance, ref value); } private static void TranslateAndUpdateFont(Text component, ref string text) { try { if (Plugin.IsTranslationEnabled && !((Object)(object)component == (Object)null) && !string.IsNullOrEmpty(text)) { FontManager.ApplyFont(component); if (TranslationManager.TryGetTranslation(text, out var translated)) { text = translated; } } } catch { } } } [HarmonyPatch(typeof(TextMeshProUGUI))] internal static class TextMeshProUGUI_OnEnable_Patch { [HarmonyPostfix] [HarmonyPatch("OnEnable")] public static void Postfix(TextMeshProUGUI __instance) { try { if (!Plugin.IsTranslationEnabled || (Object)(object)__instance == (Object)null) { return; } string text = ((TMP_Text)__instance).text; if (!string.IsNullOrEmpty(text)) { FontManager.ApplyFont((TMP_Text)(object)__instance); if (TranslationManager.TryGetTranslation(text, out var translated) && text != translated) { FontManager.ApplyTranslatedFont((TMP_Text)(object)__instance, translated); ((TMP_Text)__instance).text = translated; FontManager.RefreshLayout((TMP_Text)(object)__instance); } } } catch { } } } [HarmonyPatch(typeof(TextMeshPro))] internal static class TextMeshPro_OnEnable_Patch { [HarmonyPostfix] [HarmonyPatch("OnEnable")] public static void Postfix(TextMeshPro __instance) { try { if (!Plugin.IsTranslationEnabled || (Object)(object)__instance == (Object)null) { return; } string text = ((TMP_Text)__instance).text; if (!string.IsNullOrEmpty(text)) { FontManager.ApplyFont((TMP_Text)(object)__instance); if (TranslationManager.TryGetTranslation(text, out var translated) && text != translated) { FontManager.ApplyTranslatedFont((TMP_Text)(object)__instance, translated); ((TMP_Text)__instance).text = translated; FontManager.RefreshLayout((TMP_Text)(object)__instance); } } } catch { } } } [HarmonyPatch(typeof(Text))] internal static class Text_OnEnable_Patch { [HarmonyPostfix] [HarmonyPatch("OnEnable")] public static void Postfix(Text __instance) { try { if (!Plugin.IsTranslationEnabled || (Object)(object)__instance == (Object)null) { return; } string text = __instance.text; if (!string.IsNullOrEmpty(text)) { FontManager.ApplyFont(__instance); if (TranslationManager.TryGetTranslation(text, out var translated) && text != translated) { __instance.text = translated; } } } catch { } } } [HarmonyPatch] internal static class CraftingUI_UpdateCraftables_Patch { [HarmonyTargetMethod] public static MethodBase TargetMethod() { Type type = AccessTools.TypeByName("CraftingUI"); return (type == null) ? null : AccessTools.Method(type, "UpdateCraftables", (Type[])null, (Type[])null); } [HarmonyPostfix] public static void Postfix() { Plugin.RequestSceneTextRefresh(); } } [HarmonyPatch] internal static class InventoryCell_OnPointerEnter_Patch { [HarmonyTargetMethod] public static MethodBase TargetMethod() { Type type = AccessTools.TypeByName("InventoryCell"); return (type == null) ? null : AccessTools.Method(type, "OnPointerEnter", (Type[])null, (Type[])null); } [HarmonyPostfix] public static void Postfix() { Plugin.RequestSceneTextRefresh(); } }