Decompiled source of Auto Translate v1.1.1
AutoTranslate.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using 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.InteropServices; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using ETGGUI; using HarmonyLib; using Mono.Cecil.Cil; using MonoMod.Cil; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using SGUI; using UnityEngine; using UnityEngine.Networking; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("AutoTranslate")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("AutoTranslate")] [assembly: AssemblyCopyright("Copyright © 2023")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("825bc8e2-2faf-496c-803c-3f3e31eba1a0")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace AutoTranslate; internal class AssetBundleLoader { public static AssetBundle LoadAssetBundle(string filePath) { AssetBundle result = null; if (File.Exists(filePath)) { try { result = AssetBundle.LoadFromFile(filePath); Debug.Log((object)"已成功加载AssetBundle!Successfully loaded AssetBundle!"); } catch (Exception ex) { Debug.LogError((object)"从文件加载AssetBundle失败。Failed loading AssetBundle from file."); Debug.LogError((object)ex.ToString()); } } else { Debug.LogError((object)"AssetBundle不存在!AssetBundle does not exist!"); } return result; } } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("kleirof.etg.autotranslate", "Auto Translate", "1.1.1")] public class AutoTranslateModule : BaseUnityPlugin { public enum FilterForFullTextNeedToTranslateType { Chinese, CustomRegex } public enum FilterForEachLineNeedToTranslateType { Chinese, CustomRegex } public enum FilterForIgnoredSubstringWithinTextType { Chinese, CustomRegex } public enum TranslationAPIType { Tencent, Baidu, Azure, Llm } public enum OverrideFontType { None, Chinese, English, Japanese, Korean, Russian, Polish, Custom } public enum OverrideDfTokenizerType { None, Chinese, CustomRegex } public enum OverrideItemTipsTokenizerType { Chinese, CustomRegex } public enum LlmQuotePreprocessType { None, Chinese } public enum LlmDataFormatType { Json, Split, Positioned, Parallel } public const string GUID = "kleirof.etg.autotranslate"; public const string NAME = "Auto Translate"; public const string VERSION = "1.1.1"; public const string TEXT_COLOR = "#AA3399"; internal static AutoTranslateModule instance; private ConfigEntry<bool> AcceptedModDeclaration; private ConfigEntry<TranslationAPIType> TranslationAPI; private ConfigEntry<KeyCode> ToggleTranslationKeyBinding; private ConfigEntry<FilterForFullTextNeedToTranslateType> FilterForFullTextNeedToTranslate; private ConfigEntry<string> RegexForFullTextNeedToTranslate; private ConfigEntry<FilterForEachLineNeedToTranslateType> FilterForEachLineNeedToTranslate; private ConfigEntry<string> RegexForEachLineNeedToTranslate; private ConfigEntry<FilterForIgnoredSubstringWithinTextType> FilterForIgnoredSubstringWithinText; private ConfigEntry<string> RegexForIgnoredSubstringWithinText; private ConfigEntry<int> MaxBatchCharacterCount; private ConfigEntry<int> MaxBatchTextCount; private ConfigEntry<int> MaxRetryCount; private ConfigEntry<float> RetryInterval; private ConfigEntry<int> TranslationCacheCapacity; private ConfigEntry<string> PresetTranslations; private ConfigEntry<string> CachedTranslations; private ConfigEntry<bool> AutoSaveCachedTranslationsUponQuit; private ConfigEntry<bool> LogRequestedTexts; private ConfigEntry<OverrideFontType> OverrideFont; private ConfigEntry<string> FontAssetBundleName; private ConfigEntry<string> CustomDfFontName; private ConfigEntry<string> CustomTk2dFontName; private ConfigEntry<string> RegexForDfTokenizer; private ConfigEntry<OverrideDfTokenizerType> OverrideDfTokenizer; private ConfigEntry<float> DfTextScaleExpandThreshold; private ConfigEntry<float> DfTextScaleExpandToValue; private ConfigEntry<bool> ShowRequestedCharacterCount; private ConfigEntry<int> RequestedCharacterCountAlertThreshold; private ConfigEntry<KeyCode> ToggleRequestedCharacterCountKeyBinding; private ConfigEntry<string> CountLabelAnchor; private ConfigEntry<string> CountLabelPivot; private ConfigEntry<bool> TranslateTextsOfItemTipsMod; private ConfigEntry<OverrideItemTipsTokenizerType> OverrideItemTipsTokenizer; private ConfigEntry<string> RegexForItemTipsModTokenizer; private ConfigEntry<float> ItemTipsFontScale; private ConfigEntry<float> ItemTipsBackgroundWidthScale; private ConfigEntry<float> ItemTipsLineHeightScale; private ConfigEntry<string> ItemTipsAnchor; private ConfigEntry<string> ItemTipsPivot; private ConfigEntry<int> ItemTipsSourceBitmapFontBaseLine; private ConfigEntry<string> TencentSecretId; private ConfigEntry<string> TencentSecretKey; private ConfigEntry<string> TencentSourceLanguage; private ConfigEntry<string> TencentTargetLanguage; private ConfigEntry<string> TencentRegion; private ConfigEntry<string> BaiduAppId; private ConfigEntry<string> BaiduSecretKey; private ConfigEntry<string> BaiduSourceLanguage; private ConfigEntry<string> BaiduTargetLanguage; private ConfigEntry<string> AzureSubscriptionKey; private ConfigEntry<string> AzureSourceLanguage; private ConfigEntry<string> AzureTargetLanguage; private ConfigEntry<string> AzureRegion; private ConfigEntry<string> LlmBaseUrl; private ConfigEntry<string> LlmApiKey; private ConfigEntry<string> LlmName; private ConfigEntry<string> LlmPrompt; private ConfigEntry<int> LlmMaxTokens; private ConfigEntry<float> LlmTemperature; private ConfigEntry<float> LlmTopP; private ConfigEntry<int> LlmTopK; private ConfigEntry<float> LlmFrequencyPenalty; private ConfigEntry<string> LlmExtraParametersJson; private ConfigEntry<LlmQuotePreprocessType> LlmQuotePreprocess; private ConfigEntry<LlmDataFormatType> LlmDataFormat; private ConfigEntry<string> LlmSplitText; private ConfigEntry<string> LlmPositionText; private ConfigEntry<string> LlmSegmentText; private Harmony harmony; private GameObject autoTranslateObject; internal TranslationManager translateManager; internal FontManager fontManager; internal AutoTranslateConfig config; internal StatusLabelController statusLabel; private readonly string errorColor = "#FF0000"; public void Start() { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown ETGModMainBehaviour.WaitForGameManagerStart((Action<GameManager>)GMStart); instance = this; config = InitializeConfigs(); if (!AcceptedModDeclaration.Value) { Debug.LogError((object)"AutoTranslate: 还未接受Mod声明!Mod declaration not accepted!"); return; } if (!config.isConfigValid) { Debug.LogError((object)"AutoTranslate: 翻译配置无效!Invalid Translate Config!"); } fontManager = new FontManager(); harmony = new Harmony("kleirof.etg.autotranslate"); harmony.PatchAll(); autoTranslateObject = new GameObject("Auto Translate Object"); Object.DontDestroyOnLoad((Object)(object)autoTranslateObject); translateManager = autoTranslateObject.AddComponent<TranslationManager>(); translateManager.Initialize(); DoOptionalPatches(); statusLabel = new StatusLabelController(); } internal static void Log(string text, string color = "FFFFFF") { ETGModConsole.Log((object)("<color=" + color + ">" + text + "</color>"), false); } internal void GMStart(GameManager g) { if (!AcceptedModDeclaration.Value) { Log("Auto Translate v1.1.1 started, but AcceptedModDeclaration not checked!", errorColor); Log("(Important!) Please read the declaration on mod website and then check the config in mod manager or manually edit it.", errorColor); return; } if (!config.isConfigValid) { Log("Auto Translate v1.1.1 started, but config is invalid!", errorColor); Log("Please check the config in mod manager or manually edit it.", errorColor); return; } Log("Auto Translate v1.1.1 started successfully.", "#AA3399"); fontManager?.InitializeFontAfterGameManager(OverrideFont.Value); statusLabel?.InitializeStatusLabel(); ETGModConsole.Commands.AddGroup("autotranslate", (Action<string[]>)LogHelp); ETGModConsole.Commands.GetGroup("autotranslate").AddUnit("help", (Action<string[]>)LogHelp); ETGModConsole.Commands.GetGroup("autotranslate").AddUnit("save_cache", (Action<string[]>)SaveCache); ETGModConsole.Commands.GetGroup("autotranslate").AddUnit("load_cache", (Action<string[]>)LoadCache); } private AutoTranslateConfig InitializeConfigs() { //IL_09ac: Unknown result type (might be due to invalid IL or missing references) //IL_09b1: Unknown result type (might be due to invalid IL or missing references) //IL_0b7f: Unknown result type (might be due to invalid IL or missing references) //IL_0b84: Unknown result type (might be due to invalid IL or missing references) AcceptedModDeclaration = ((BaseUnityPlugin)this).Config.Bind<bool>("1.General", "AcceptedModDeclaration", false, "作为Mod用户,我已阅读并同意网站上此mod的声明,清楚潜在费用的去向并信任此mod的行为,并对自己的选择负责任。As a mod user, I have read and accepted the declaration on this mod's website, understand the potential destination of the fees, trust the actions of this mod, and take responsibility for my choice."); TranslationAPI = ((BaseUnityPlugin)this).Config.Bind<TranslationAPIType>("1.General", "TranslationAPI", TranslationAPIType.Tencent, "选择使用的翻译API。Choose the translation API to use."); ToggleTranslationKeyBinding = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("1.General", "ToggleTranslationKeyBinding", (KeyCode)291, "启用或关闭翻译的按键。The key binding of toggling translation."); FilterForFullTextNeedToTranslate = ((BaseUnityPlugin)this).Config.Bind<FilterForFullTextNeedToTranslateType>("1.General", "FilterForFullTextNeedToTranslate", FilterForFullTextNeedToTranslateType.Chinese, "对整个文本生效。用来筛选待翻译的文本以节省翻译额度。Effective for the full text. Used to filter the text to be translated to save translation quotas."); RegexForFullTextNeedToTranslate = ((BaseUnityPlugin)this).Config.Bind<string>("1.General", "RegexForFullTextNeedToTranslate", "^(?!Enter the Gungeon).*$", "正则表达式,一个多行文本若匹配为真,则这个多行文本保留以待翻译。只在FilterForFullTextNeedToTranslate为CustomRegex时生效。Regular expression, if a multiple line text matches true, then this multiple line text is retained for translation. Only effective when FilterForFullTextNeedToTranslate is set to CustomRegex."); FilterForEachLineNeedToTranslate = ((BaseUnityPlugin)this).Config.Bind<FilterForEachLineNeedToTranslateType>("1.General", "FilterForEachLineNeedToTranslate", FilterForEachLineNeedToTranslateType.Chinese, "对文本的每一行生效。用来筛选待翻译的文本以节省翻译额度。Effective for each line of text. Used to filter the text to be translated to save translation quotas."); RegexForEachLineNeedToTranslate = ((BaseUnityPlugin)this).Config.Bind<string>("1.General", "RegexForEachLineNeedToTranslate", "^(?![@#])(?=\\S)(?!^[\\d\\p{P}]+$)(?!.*[\\u4e00-\\u9fa5\\u3000-\\u303F\\uFF00-\\uFFEF]).*$", "正则表达式,多行文本若存在一行匹配,整个多行文本保留以待翻译。只在FilterForEachLineNeedToTranslate为CustomRegex时生效。Regular expression, if there is a matching line in multiple lines of text, the entire multiple lines of text are retained for translation. Only effective when FilterForEachLineNeedToTranslate is set to CustomRegex."); FilterForIgnoredSubstringWithinText = ((BaseUnityPlugin)this).Config.Bind<FilterForIgnoredSubstringWithinTextType>("1.General", "FilterForIgnoredSubstringWithinText", FilterForIgnoredSubstringWithinTextType.Chinese, "用来过滤文本中需要忽略的子文本。这通常包括一些要特殊处理的贴图和转义符。Used to filter sub texts that need to be ignored in the text. This usually includes some textures and escape characters that require special handling."); RegexForIgnoredSubstringWithinText = ((BaseUnityPlugin)this).Config.Bind<string>("1.General", "RegexForIgnoredSubstringWithinText", "(?:\\[color\\s+[^\\]]+\\])|(?:\\[sprite\\s+[^\\]]+\\])|(?:\\[/color\\])|(?:\\{[^}]*\\})|(?:\\^[\\w\\d]{9})|(?:[\\u4e00-\\u9fa5\\u3000-\\u303F\\uFF00-\\uFFEF]+)|(?:<color=[^>]+>)|(?:</color>)|(?:^\\s*[\\d\\p{P}]+\\s*$)|(?:[<>\\[\\]])|(?:@[a-fA-F0-9]{6})", "正则表达式,匹配文本中需要忽略的子文本。请使用非捕获组。只在FilterForIgnoredSubstringWithinText为CustomRegex时生效。Regular expression, matching sub texts that need to be ignored in the text. Please use non capture groups. Only effective when FilterForIgnoredSubstringWithinText is set to CustomRegex."); MaxBatchCharacterCount = ((BaseUnityPlugin)this).Config.Bind<int>("1.General", "MaxBatchCharacterCount", 1024, "处理的批量数据最大字符数。若翻译api提示单次请求过长,请减小此值。The maximum count of batch data characters for processing. If the translation API prompts that a single request is too long, please reduce this value."); MaxBatchTextCount = ((BaseUnityPlugin)this).Config.Bind<int>("1.General", "MaxBatchTextCount", 0, "处理的批量数据最大项数。为0表示不限制。The maximum count of batch data texts for processing. A value of 0 indicates no restriction."); MaxRetryCount = ((BaseUnityPlugin)this).Config.Bind<int>("1.General", "MaxRetryCount", 3, "发生错误时的最大重试次数。The maximum number of retries when an error occurs."); RetryInterval = ((BaseUnityPlugin)this).Config.Bind<float>("1.General", "RetryInterval", 2f, "发生错误时的重试时间间隔。The interval of retries when an error occurs."); TranslationCacheCapacity = ((BaseUnityPlugin)this).Config.Bind<int>("1.General", "TranslationCacheCapacity", 1024, "最大翻译缓存容量。Maximum translation cache capacity."); PresetTranslations = ((BaseUnityPlugin)this).Config.Bind<string>("1.General", "PresetTranslations", "CachedTranslations.json;PresetTranslations.json", "预设翻译的文件名。使用预设翻译以减少加载时常见文本的翻译请求,留空表示不使用。预设翻译为位于dll同目录下的JSON文件。用“;”分割,文件会按顺序先后加载。The file name for preset translations. Use preset translation to reduce translation requests for common text during loading, leaving blank to indicate not using. The preset translation is a JSON file located in the same directory as the DLL. Separated by ';', files will be loaded sequentially."); CachedTranslations = ((BaseUnityPlugin)this).Config.Bind<string>("1.General", "CachedTranslations", "CachedTranslations.json", "缓存翻译的文件名。缓存翻译为位于dll同目录下的JSON文件。The file name cached translations. The preset translation is a JSON file located in the same directory as the DLL."); AutoSaveCachedTranslationsUponQuit = ((BaseUnityPlugin)this).Config.Bind<bool>("1.General", "AutoSaveCachedTranslationsUponQuit", false, "是否在退出时自动保存缓存翻译。强制退出时不会生效。Whether to automatically save cached translations upon quit. It will not take effect when quiting abnormally."); LogRequestedTexts = ((BaseUnityPlugin)this).Config.Bind<bool>("1.General", "LogRequestedTexts", false, "是否在日志中显示请求翻译的文本。Whether to log the text requested for translation."); OverrideFont = ((BaseUnityPlugin)this).Config.Bind<OverrideFontType>("2.Font", "OverrideFont", OverrideFontType.Custom, "用来覆盖游戏字体的字体。根据你需要的目标语言选择。Font used to override the font of the game. Choose according to the target language you need."); FontAssetBundleName = ((BaseUnityPlugin)this).Config.Bind<string>("2.Font", "FontAssetBundleName", "fusion_pixel_12px_zh_cn", "包含自定义字体的AssetBundle名称。位于dll同目录下。AssetBundle name containing custom fonts. Located in the same directory as DLL."); CustomDfFontName = ((BaseUnityPlugin)this).Config.Bind<string>("2.Font", "CustomDfFontName", "Fusion_Pixel_12px_Monospaced_dfDynamic", "要使用的自定义df字体。请把它包含于FontAssetBundle。The custom df font to be used. Please include it in FontAssetBundle."); CustomTk2dFontName = ((BaseUnityPlugin)this).Config.Bind<string>("2.Font", "CustomTk2dFontName", "Fusion_Pixel_12px_Monospaced_tk2d", "要使用的自定义tk2d字体。请把它包含于FontAssetBundle。The custom tk2d font to be used. Please include it in FontAssetBundle."); OverrideDfTokenizer = ((BaseUnityPlugin)this).Config.Bind<OverrideDfTokenizerType>("2.Font", "OverrideDfTokenizer", OverrideDfTokenizerType.Chinese, "覆盖的Df分词器。Token可以用于处理文本的自动换行位置。如每个字换行还是单词后换行。Override Df tokenizer. Token is used to handle the automatic line break position of text. Whether to wrap each word or to wrap after each word."); RegexForDfTokenizer = ((BaseUnityPlugin)this).Config.Bind<string>("2.Font", "RegexForDfTokenizer", FontManager.defaultRegexForTokenizer, "用于Df生成token的正则表达式。只在OverrideDfTokenizer为CustomRegex时生效。A regular expression used for generating tokens for Df. Only effective when OverrideDfTokenizer is set to CustomRegex."); DfTextScaleExpandThreshold = ((BaseUnityPlugin)this).Config.Bind<float>("2.Font", "DfTextScaleExpandThreshold", 1f, "低于这个值的Df TextScale会被扩大。为负表示不生效。Df TextScale below this value will be expanded. Negative indicates non effectiveness."); DfTextScaleExpandToValue = ((BaseUnityPlugin)this).Config.Bind<float>("2.Font", "DfTextScaleExpandToValue", 2f, "低于门槛的Df TextScale被扩大到多少。How much is the Df TextScale below the threshold expanded to."); ShowRequestedCharacterCount = ((BaseUnityPlugin)this).Config.Bind<bool>("3.RequestedCharacterCount", "ShowRequestedCharacterCount", true, "显示已翻译字符数。Show requested character count."); RequestedCharacterCountAlertThreshold = ((BaseUnityPlugin)this).Config.Bind<int>("3.RequestedCharacterCount", "RequestedCharacterCountAlertThreshold", 50000, "已请求翻译字符数警报阈值。当翻译请求即将超出时,会暂停翻译。为零表示不设阈值。The alert threshold of the count of characters requested for translation. When this count is about to exceed, translation will be paused. A value of zero indicates no threshold is set."); ToggleRequestedCharacterCountKeyBinding = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("3.RequestedCharacterCount", "ToggleRequestedCharacterCountKeyBinding", (KeyCode)287, "开启或关闭已翻译字符数的显示的按键。The key binding of toggling the display of requested character count."); CountLabelAnchor = ((BaseUnityPlugin)this).Config.Bind<string>("3.RequestedCharacterCount", "CountLabelAnchor", "0.5 0", "用空格或逗号分隔的一个二维向量,决定计数标签相对于父级的锚点位置。左上角为0 0,右下角是1 1。A two-dimensional vector separated by spaces or commas, which determines where the count label is anchored relative to its parent. The top left corner is 0 0, and the bottom right corner is 1 1."); CountLabelPivot = ((BaseUnityPlugin)this).Config.Bind<string>("3.RequestedCharacterCount", "CountLabelPivot", "0.5 0", "用空格或逗号分隔的一个二维向量,定义计数标签的定位基准点。左上角为0 0,右下角是1 1。A two-dimensional vector separated by spaces or commas, which defines the pivot point of the count label for positioning. The top left corner is 0 0, and the bottom right corner is 1 1."); TranslateTextsOfItemTipsMod = ((BaseUnityPlugin)this).Config.Bind<bool>("4.Compatibility", "TranslateTextsOfItemTipsMod", true, "翻译ItemTipsMod中的文本。Translate the text in ItemTipsMod."); OverrideItemTipsTokenizer = ((BaseUnityPlugin)this).Config.Bind<OverrideItemTipsTokenizerType>("4.Compatibility", "OverrideItemTipsTokenizer", OverrideItemTipsTokenizerType.Chinese, "覆盖的ItemTips分词器。Token可以用于处理文本的自动换行位置。如每个字换行还是单词后换行。Override ItemTips tokenizer. Token is used to handle the automatic line break position of text. Whether to wrap each word or to wrap after each word."); RegexForItemTipsModTokenizer = ((BaseUnityPlugin)this).Config.Bind<string>("4.Compatibility", "RegexForItemTipsModTokenizer", FontManager.defaultRegexForItemTipsModTokenizer, "用于ItemTips生成token的正则表达式。只在OverrideItemTipsTokenizer为CustomRegex时生效。A regular expression used for generating tokens for ItemTips. Only effective when OverrideItemTipsTokenizer is set to CustomRegex."); ItemTipsFontScale = ((BaseUnityPlugin)this).Config.Bind<float>("4.Compatibility", "ItemTipsFontScale", 1.5f, "ItemTips的字体缩放大小。The font scale of ItemTips."); ItemTipsBackgroundWidthScale = ((BaseUnityPlugin)this).Config.Bind<float>("4.Compatibility", "ItemTipsBackgroundWidthScale", 1f, "ItemTips的背景宽度缩放大小。The width scale of ItemTips background."); ItemTipsLineHeightScale = ((BaseUnityPlugin)this).Config.Bind<float>("4.Compatibility", "ItemTipsLineHeightScale", 1.4f, "ItemTips的行高缩放大小。The width scale of ItemTips line height."); ItemTipsAnchor = ((BaseUnityPlugin)this).Config.Bind<string>("4.Compatibility", "ItemTipsAnchor", "0.1 0.5", "用空格或逗号分隔的一个二维向量,决定ItemTips相对于父级的锚点位置。左上角为0 0,右下角是1 1。A two-dimensional vector separated by spaces or commas, which determines where ItemTips is anchored relative to its parent. The top left corner is 0 0, and the bottom right corner is 1 1."); ItemTipsPivot = ((BaseUnityPlugin)this).Config.Bind<string>("4.Compatibility", "ItemTipsPivot", "0 0.5", "用空格或逗号分隔的一个二维向量,定义ItemTips的定位基准点。左上角为0 0,右下角是1 1。A two-dimensional vector separated by spaces or commas, which defines the pivot point of ItemTips for positioning. The top left corner is 0 0, and the bottom right corner is 1 1."); ItemTipsSourceBitmapFontBaseLine = ((BaseUnityPlugin)this).Config.Bind<int>("4.Compatibility", "ItemTipsSourceBitmapFontBaseLine", 10, "ItemTips的字体如果由位图字体生成,可以在此控制位图字体的基准线。If the font used by ItemTips is generated from a bitmap font, you can adjust the baseline of the bitmap font here."); TencentSecretId = ((BaseUnityPlugin)this).Config.Bind<string>("5.TencentTranslation", "SecretId", "", "腾讯翻译的SecretId。The SecretId of Tencent Translate."); TencentSecretKey = ((BaseUnityPlugin)this).Config.Bind<string>("5.TencentTranslation", "SecretKey", "", "腾讯翻译的SecretKey。The SecretKey of Tencent Translate."); TencentSourceLanguage = ((BaseUnityPlugin)this).Config.Bind<string>("5.TencentTranslation", "SourceLanguage", "en", "腾讯翻译的源语言,如en。The source language of Tencent Translate, such as en."); TencentTargetLanguage = ((BaseUnityPlugin)this).Config.Bind<string>("5.TencentTranslation", "TargetLanguage", "zh", "腾讯翻译的目标语言,如zh。Tencent Translate's target language, such as zh."); TencentRegion = ((BaseUnityPlugin)this).Config.Bind<string>("5.TencentTranslation", "Region", "ap-beijing", "地域,用来标识希望连接哪个地域的服务器,如ap-beijing。Region, used to identify which region's server you want to connect to, such as ap-beijing."); BaiduAppId = ((BaseUnityPlugin)this).Config.Bind<string>("6.BaiduTranslate", "SecretId", "", "百度翻译的AppId。The AppId of Baidu Translate."); BaiduSecretKey = ((BaseUnityPlugin)this).Config.Bind<string>("6.BaiduTranslate", "SecretKey", "", "百度翻译的SecretKey。The SecretKey for Baidu Translate."); BaiduSourceLanguage = ((BaseUnityPlugin)this).Config.Bind<string>("6.BaiduTranslate", "SourceLanguage", "en", "百度翻译的源语言,如en。The source language of Baidu Translate, such as en."); BaiduTargetLanguage = ((BaseUnityPlugin)this).Config.Bind<string>("6.BaiduTranslate", "TargetLanguage", "zh", "百度翻译的目标语言,如zh。The target language for Baidu Translate, such as zh."); AzureSubscriptionKey = ((BaseUnityPlugin)this).Config.Bind<string>("7.AzureTranslate", "AzureSubscriptionKey", "", "Azure翻译的SubscriptionKey。Subscription Key for Azure Translation."); AzureSourceLanguage = ((BaseUnityPlugin)this).Config.Bind<string>("7.AzureTranslate", "SourceLanguage", "en", "Azure翻译的源语言,如en。The source language for Azure translation, such as en."); AzureTargetLanguage = ((BaseUnityPlugin)this).Config.Bind<string>("7.AzureTranslate", "TargetLanguage", "zh-Hans", "Azure翻译的目标语言,如zh-Hans。The target language for Azure translation, such as zh-Hans."); AzureRegion = ((BaseUnityPlugin)this).Config.Bind<string>("7.AzureTranslate", "AzureRegion", "global", "地域,用来标识希望连接哪个地域的服务器,如global。Region, used to identify which region's server you want to connect to, such as global."); LlmBaseUrl = ((BaseUnityPlugin)this).Config.Bind<string>("8.Llm", "LlmBaseUrl", "", "大模型API的基础URL,用来连接到目标大模型服务的接口地址。Base URL of the large model API, used to connect to the target large model service endpoint."); LlmApiKey = ((BaseUnityPlugin)this).Config.Bind<string>("8.Llm", "LlmApiKey", "", "大模型API的访问密钥,用来进行身份验证并访问API服务。API key for the large model, used for authentication and accessing the API service."); LlmName = ((BaseUnityPlugin)this).Config.Bind<string>("8.Llm", "LlmName", "", "大模型的名称,指定要使用的模型版本或名称。The name of the large model, specifying which model version or name to use."); LlmPrompt = ((BaseUnityPlugin)this).Config.Bind<string>("8.Llm", "LlmPrompt", "英文翻译为中文,仅返回JSON的内容。输出格式和输入一致。输入:[{\"id\":1,\"text\":\"Hello\"}, {\"id\":2,\"text\":\"World\"}] 输出:[{\"id\":1,\"text\":\"你好\"}, {\"id\":2,\"text\":\"世界\"}]", "Prompt是向语言模型提供指示或请求的输入文本,帮助模型理解任务并生成响应。A prompt is the input text given to a language model to guide it in understanding the task and generating a response."); LlmMaxTokens = ((BaseUnityPlugin)this).Config.Bind<int>("8.Llm", "LlmMaxTokens", 1024, "大模型API允许的最大token数,控制生成内容的最大长度。Maximum number of tokens allowed by the large model API, controlling the maximum length of generated content."); LlmTemperature = ((BaseUnityPlugin)this).Config.Bind<float>("8.Llm", "LlmTemperature", 1.3f, "控制大模型生成文本的创造性,值越高,生成的文本越随机,越低则越确定。Controls the creativity of the large model's text generation, with higher values leading to more random and lower values leading to more deterministic output."); LlmTopP = ((BaseUnityPlugin)this).Config.Bind<float>("8.Llm", "LlmTopP", 0.7f, "控制大模型生成文本时的采样范围,值越低,结果越集中。Controls the sampling range of the large model's text generation, with lower values leading to more focused results."); LlmTopK = ((BaseUnityPlugin)this).Config.Bind<int>("8.Llm", "LlmTopK", 30, "控制大模型生成文本时考虑的最高概率词的数量,值越高,结果越多样化。Controls the number of highest probability words considered by the large model during text generation, with higher values leading to more diverse results."); LlmFrequencyPenalty = ((BaseUnityPlugin)this).Config.Bind<float>("8.Llm", "LlmFrequencyPenalty", 0f, "控制生成文本中词汇重复的概率。值越高,生成内容越多样化;值越低,生成内容越集中和重复。Controls the likelihood of token repetition in generated text.Higher values promote diversity, while lower values result in more focused and repetitive outputs."); LlmExtraParametersJson = ((BaseUnityPlugin)this).Config.Bind<string>("8.Llm", "LlmExtraParametersJson", "{\"enable_thinking\": false}", "一个JSON,列举了大模型需要的额外参数。A JSON listing the additional parameters required by the large language model."); LlmQuotePreprocess = ((BaseUnityPlugin)this).Config.Bind<LlmQuotePreprocessType>("8.Llm", "LlmQuotePreprocess", LlmQuotePreprocessType.Chinese, "用于设置引号预处理的类型。Sets the quote preprocessing type."); LlmDataFormat = ((BaseUnityPlugin)this).Config.Bind<LlmDataFormatType>("8.Llm", "LlmDataFormat", LlmDataFormatType.Json, "用于设置收发数据的格式类型。Set the format type for sending and receiving data."); LlmSplitText = ((BaseUnityPlugin)this).Config.Bind<string>("8.Llm", "LlmSplitText", "<tspl>", "仅当LlmDataFormat为Split时生效。分割形式收发数据时的分隔符。Only takes effect when LlmDataFormat is set to Split. The split text for sending and receiving data in the format of splitted."); LlmPositionText = ((BaseUnityPlugin)this).Config.Bind<string>("8.Llm", "LlmPositionText", "<!pos!>", "仅当LlmDataFormat为PositionTagged时生效。位置编号的起始标记。Only takes effect when LlmDataFormat is set to PositionTagged. The starting tag of the position number."); LlmSegmentText = ((BaseUnityPlugin)this).Config.Bind<string>("8.Llm", "LlmSegmentText", "<!seg!>", "仅当LlmDataFormat为Positioned时生效。被定位的段的起始标记。Only takes effect when LlmDataFormat is set to Positioned. The starting tag of the positioned segment."); AutoTranslateConfig autoTranslateConfig = new AutoTranslateConfig { TranslationAPI = TranslationAPI.Value, ToggleTranslationKeyBinding = ToggleTranslationKeyBinding.Value, FilterForFullTextNeedToTranslate = FilterForFullTextNeedToTranslate.Value, RegexForFullTextNeedToTranslate = RegexForFullTextNeedToTranslate.Value, FilterForEachLineNeedToTranslate = FilterForEachLineNeedToTranslate.Value, RegexForEachLineNeedToTranslate = RegexForEachLineNeedToTranslate.Value, FilterForIgnoredSubstringWithinText = FilterForIgnoredSubstringWithinText.Value, RegexForIgnoredSubstringWithinText = RegexForIgnoredSubstringWithinText.Value, MaxBatchCharacterCount = MaxBatchCharacterCount.Value, MaxBatchTextCount = MaxBatchTextCount.Value, MaxRetryCount = MaxRetryCount.Value, RetryInterval = ((RetryInterval.Value > 0f) ? RetryInterval.Value : 2f), TranslationCacheCapacity = TranslationCacheCapacity.Value, PresetTranslations = PresetTranslations.Value, CachedTranslations = CachedTranslations.Value, AutoSaveCachedTranslationsUponQuit = AutoSaveCachedTranslationsUponQuit.Value, LogRequestedTexts = LogRequestedTexts.Value, OverrideFont = OverrideFont.Value, FontAssetBundleName = FontAssetBundleName.Value, CustomDfFontName = CustomDfFontName.Value, CustomTk2dFontName = CustomTk2dFontName.Value, OverrideDfTokenizer = OverrideDfTokenizer.Value, RegexForDfTokenizer = RegexForDfTokenizer.Value, DfTextScaleExpandThreshold = DfTextScaleExpandThreshold.Value, DfTextScaleExpandToValue = DfTextScaleExpandToValue.Value, ShowRequestedCharacterCount = ShowRequestedCharacterCount.Value, RequestedCharacterCountAlertThreshold = RequestedCharacterCountAlertThreshold.Value, ToggleRequestedCharacterCountKeyBinding = ToggleRequestedCharacterCountKeyBinding.Value, CountLabelAnchor = CountLabelAnchor.Value, CountLabelPivot = CountLabelPivot.Value, TranslateTextsOfItemTipsMod = TranslateTextsOfItemTipsMod.Value, OverrideItemTipsTokenizer = OverrideItemTipsTokenizer.Value, RegexForItemTipsModTokenizer = RegexForItemTipsModTokenizer.Value, ItemTipsFontScale = ((ItemTipsFontScale.Value > 0f) ? ItemTipsFontScale.Value : 1f), ItemTipsBackgroundWidthScale = ((ItemTipsBackgroundWidthScale.Value > 0f) ? ItemTipsBackgroundWidthScale.Value : 1f), ItemTipsLineHeightScale = ((ItemTipsLineHeightScale.Value > 0f) ? ItemTipsLineHeightScale.Value : 1f), ItemTipsAnchor = ItemTipsAnchor.Value, ItemTipsPivot = ItemTipsPivot.Value, ItemTipsSourceBitmapFontBaseLine = ItemTipsSourceBitmapFontBaseLine.Value, TencentSecretId = TencentSecretId.Value, TencentSecretKey = TencentSecretKey.Value, TencentSourceLanguage = TencentSourceLanguage.Value, TencentTargetLanguage = TencentTargetLanguage.Value, TencentRegion = TencentRegion.Value, BaiduAppId = BaiduAppId.Value, BaiduSecretKey = BaiduSecretKey.Value, BaiduSourceLanguage = BaiduSourceLanguage.Value, BaiduTargetLanguage = BaiduTargetLanguage.Value, AzureSubscriptionKey = AzureSubscriptionKey.Value, AzureSourceLanguage = AzureSourceLanguage.Value, AzureTargetLanguage = AzureTargetLanguage.Value, AzureRegion = AzureRegion.Value, LlmBaseUrl = LlmBaseUrl.Value, LlmApiKey = LlmApiKey.Value, LlmName = LlmName.Value, LlmPrompt = LlmPrompt.Value, LlmMaxTokens = LlmMaxTokens.Value, LlmTemperature = LlmTemperature.Value, LlmTopP = LlmTopP.Value, LlmTopK = LlmTopK.Value, LlmFrequencyPenalty = LlmFrequencyPenalty.Value, LlmExtraParametersJson = LlmExtraParametersJson.Value, LlmQuotePreprocess = LlmQuotePreprocess.Value, LlmDataFormat = LlmDataFormat.Value, LlmSplitText = LlmSplitText.Value, LlmPositionText = LlmPositionText.Value, LlmSegmentText = LlmSegmentText.Value }; autoTranslateConfig.CheckConfig(); return autoTranslateConfig; } private void DoOptionalPatches() { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected O, but got Unknown //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Expected O, but got Unknown //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Expected O, but got Unknown //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Expected O, but got Unknown //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Expected O, but got Unknown //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Expected O, but got Unknown //IL_029e: Unknown result type (might be due to invalid IL or missing references) //IL_02ac: Expected O, but got Unknown //IL_02e3: Unknown result type (might be due to invalid IL or missing references) //IL_02ed: Expected O, but got Unknown //IL_032c: Unknown result type (might be due to invalid IL or missing references) //IL_033a: Expected O, but got Unknown //IL_0371: Unknown result type (might be due to invalid IL or missing references) //IL_037b: Expected O, but got Unknown if (Chainloader.PluginInfos.ContainsKey("glorfindel.etg.itemtips")) { FontManager.instance.itemTipsModuleType = AccessTools.TypeByName("ItemTipsMod.ItemTipsModule"); MethodInfo methodInfo = AccessTools.Method(FontManager.instance.itemTipsModuleType, "GmStart", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(AutoTranslatePatches.GmStartPatchClass), "GmStartPostfix", (Type[])null, (Type[])null); harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); MethodInfo methodInfo3 = AccessTools.Method(FontManager.instance.itemTipsModuleType, "LoadFont", (Type[])null, (Type[])null); MethodInfo methodInfo4 = AccessTools.Method(typeof(AutoTranslatePatches.LoadFontPatchClass), "LoadFontPrefix", (Type[])null, (Type[])null); harmony.Patch((MethodBase)methodInfo3, new HarmonyMethod(methodInfo4), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); MethodInfo methodInfo5 = AccessTools.Method(FontManager.instance.itemTipsModuleType, "ConvertStringToFixedWidthLines", (Type[])null, (Type[])null); MethodInfo methodInfo6 = AccessTools.Method(typeof(AutoTranslatePatches.ConvertStringToFixedWidthLinesPatchClass), "ConvertStringToFixedWidthLinesPrefix", (Type[])null, (Type[])null); harmony.Patch((MethodBase)methodInfo5, new HarmonyMethod(methodInfo6), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); MethodInfo methodInfo7 = AccessTools.Method(FontManager.instance.itemTipsModuleType, "GenerateTextInfo", (Type[])null, (Type[])null); MethodInfo methodInfo8 = AccessTools.Method(typeof(AutoTranslatePatches.GenerateTextInfoPatchClass), "GenerateTextInfoPatch", (Type[])null, (Type[])null); harmony.Patch((MethodBase)methodInfo7, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(methodInfo8)); MethodInfo methodInfo9 = AccessTools.Method(FontManager.instance.itemTipsModuleType, "ShowTip", (Type[])null, (Type[])null); MethodInfo methodInfo10 = AccessTools.Method(typeof(AutoTranslatePatches.ShowTipPatchClass), "ShowTipPostfix", (Type[])null, (Type[])null); harmony.Patch((MethodBase)methodInfo9, (HarmonyMethod)null, new HarmonyMethod(methodInfo10), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Type type = AccessTools.TypeByName("ItemTipsMod.Label"); MethodInfo methodInfo11 = AccessTools.Method(type, "Reposition", (Type[])null, (Type[])null); MethodInfo methodInfo12 = AccessTools.Method(typeof(AutoTranslatePatches.RepositionPatchClass), "RepositionPostfix", (Type[])null, (Type[])null); harmony.Patch((MethodBase)methodInfo11, (HarmonyMethod)null, new HarmonyMethod(methodInfo12), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } if (Chainloader.PluginInfos.ContainsKey("lazymo3_and_NilT_PL.etg.NoBrain")) { MethodInfo methodInfo13 = AccessTools.Method(AccessTools.TypeByName("NBInteractableBehaviour"), "onNewShopItemController", (Type[])null, (Type[])null); MethodInfo methodInfo14 = AccessTools.Method(typeof(AutoTranslatePatches.NewShopItemControllerPatchClass), "NewShopItemControllerPrefix", (Type[])null, (Type[])null); harmony.Patch((MethodBase)methodInfo13, new HarmonyMethod(methodInfo14), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } if (RegexForDfTokenizer.Value != string.Empty) { Type typeFromHandle = typeof(DynamicFontRenderer); MethodInfo methodInfo15 = AccessTools.Method(typeFromHandle, "tokenize", (Type[])null, (Type[])null); MethodInfo methodInfo16 = AccessTools.Method(typeof(AutoTranslatePatches.DynamicFontRendererTokenizePatchClass), "TokenizePrefix", (Type[])null, (Type[])null); harmony.Patch((MethodBase)methodInfo15, new HarmonyMethod(methodInfo16), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); MethodInfo methodInfo17 = AccessTools.Method(typeFromHandle, "calculateLinebreaks", (Type[])null, (Type[])null); MethodInfo methodInfo18 = AccessTools.Method(typeof(AutoTranslatePatches.DynamicFontRendererCalculateLinebreaksPatchClass), "CalculateLinebreaksPatch", (Type[])null, (Type[])null); harmony.Patch((MethodBase)methodInfo17, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(methodInfo18)); Type typeFromHandle2 = typeof(BitmappedFontRenderer); MethodInfo methodInfo19 = AccessTools.Method(typeFromHandle2, "tokenize", (Type[])null, (Type[])null); MethodInfo methodInfo20 = AccessTools.Method(typeof(AutoTranslatePatches.BitmappedFontRendererTokenizePatchClass), "TokenizePrefix", (Type[])null, (Type[])null); harmony.Patch((MethodBase)methodInfo19, new HarmonyMethod(methodInfo20), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); MethodInfo methodInfo21 = AccessTools.Method(typeFromHandle2, "calculateLinebreaks", (Type[])null, (Type[])null); MethodInfo methodInfo22 = AccessTools.Method(typeof(AutoTranslatePatches.BitmappedFontRendererCalculateLinebreaksPatchClass), "CalculateLinebreaksPatch", (Type[])null, (Type[])null); harmony.Patch((MethodBase)methodInfo21, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(methodInfo22)); } } private void LogHelp(string[] args) { ETGModConsole.Log((object)"", false); ETGModConsole.Log((object)"Command list:", false); ETGModConsole.Log((object)" -- <color=#AA3399>autotranslate save_cache [cache_json_name]</color>", false); ETGModConsole.Log((object)" - Save the translation cache to [cache_json_name], which defaults to CachedTranslations.json.", false); ETGModConsole.Log((object)" -- <color=#AA3399>autotranslate load_cache [cache_json_name]</color>", false); ETGModConsole.Log((object)" - Load the translation cache from [cache_json_name], which defaults to CachedTranslations.json.", false); } private void SaveCache(string[] args) { string text = Path.Combine(path2: (args != null && args.Length != 0) ? args[0] : (string.IsNullOrEmpty(config.CachedTranslations) ? "CachedTranslations.json" : config.CachedTranslations), path1: ETGMod.FolderPath((BaseUnityPlugin)(object)instance)); translateManager.SaveTranslationCache(text, config.TranslationCacheCapacity); ETGModConsole.Log((object)("Translation cache saved successfully to " + text), false); } private void LoadCache(string[] args) { string text = Path.Combine(path2: (args != null && args.Length != 0) ? args[0] : (string.IsNullOrEmpty(config.CachedTranslations) ? "CachedTranslations.json" : config.CachedTranslations), path1: ETGMod.FolderPath((BaseUnityPlugin)(object)instance)); translateManager.ReadAndRestoreTranslationCache(text); ETGModConsole.Log((object)("Translation cache loaded successfully from " + text), false); } public void OnApplicationQuit() { if (config.AutoSaveCachedTranslationsUponQuit) { SaveCache(null); } } } public static class AutoTranslatePatches { [HarmonyPatch(/*Could not decode attribute arguments.*/)] public class DfLabelTextPatchClass { [HarmonyPostfix] public static void DfLabelTextPostfix(dfLabel __instance) { DfLabelTextAddCall(__instance); } } [HarmonyPatch(typeof(dfLabel), "OnLocalize")] public class DfLabelOnLocalizePatchClass { [HarmonyPostfix] public static void DfLabelOnLocalizePostfix(dfLabel __instance) { DfLabelTextAddCall(__instance); } } [HarmonyPatch(typeof(dfLabel), "ModifyLocalizedText")] public class DfLabelModifyLocalizedTextPatchClass { [HarmonyPostfix] public static void DfLabelModifyLocalizedTextPostfix(dfLabel __instance) { DfLabelTextAddCall(__instance); } } [HarmonyPatch(/*Could not decode attribute arguments.*/)] public class DfButtonTextPatchClass { [HarmonyPostfix] public static void DfButtonTextPostfix(dfButton __instance) { DfButtonTextAddCall(__instance); } } [HarmonyPatch(typeof(dfButton), "OnLocalize")] public class DfButtonOnLocalizePatchClass { [HarmonyPostfix] public static void DfButtonOnLocalizePostfix(dfButton __instance) { DfButtonTextAddCall(__instance); } } [HarmonyPatch(typeof(dfButton), "ModifyLocalizedText")] public class DfButtonModifyLocalizedTextPatchClass { [HarmonyPostfix] public static void DfButtonModifyLocalizedTextPostfix(dfButton __instance) { DfButtonTextAddCall(__instance); } } public class GmStartPatchClass { public static void GmStartPostfix(object __instance) { FontManager.instance.itemTipsModuleObject = __instance; FieldInfo field = FontManager.instance.itemTipsModuleType.GetField("_infoLabel", BindingFlags.Instance | BindingFlags.NonPublic); ref SLabel itemTipsModuleLabel = ref FontManager.instance.itemTipsModuleLabel; object? value = field.GetValue(__instance); itemTipsModuleLabel = (SLabel)((value is SLabel) ? value : null); } } public class ShowTipPatchClass { public static void ShowTipPostfix() { if (FontManager.instance.itemTipsModuleText != null && config.TranslateTextsOfItemTipsMod) { TranslationManager.instance.AddTranslationRequest(FontManager.instance.itemTipsModuleText, FontManager.instance.itemTipsModuleLabel); } } } public class LoadFontPatchClass { public static bool LoadFontPrefix(ref Font __result) { FieldInfo field = FontManager.instance.itemTipsModuleType.GetField("_gameFont", BindingFlags.Instance | BindingFlags.NonPublic); dfFontBase dfFontBase = FontManager.instance.dfFontBase; if ((Object)(object)dfFontBase != (Object)null) { dfDynamicFont val = (dfDynamicFont)(object)((dfFontBase is dfDynamicFont) ? dfFontBase : null); if (val != null) { FontManager.instance.potentialItemTipsDynamicBaseFont = val.baseFont; __result = val.baseFont; field.SetValue(FontManager.instance.itemTipsModuleObject, __result); FontManager.instance.itemTipsModuleFont = __result; return false; } } if ((Object)(object)dfFontBase != (Object)null) { dfFont val2 = (dfFont)(object)((dfFontBase is dfFont) ? dfFontBase : null); if (val2 != null) { FontManager.instance.originalLineHeight = ((dfFontBase)val2).LineHeight; __result = FontManager.GetFontFromdfFont(val2, 1.3f * config.ItemTipsFontScale, config.ItemTipsSourceBitmapFontBaseLine); field.SetValue(FontManager.instance.itemTipsModuleObject, __result); FontManager.instance.itemTipsModuleFont = __result; return false; } } dfFont gameFont = FontManager.GetGameFont(); if ((Object)(object)gameFont != (Object)null) { FontManager.instance.originalLineHeight = ((dfFontBase)gameFont).LineHeight; __result = FontManager.GetFontFromdfFont(gameFont, 1.3f * config.ItemTipsFontScale, config.ItemTipsSourceBitmapFontBaseLine); field.SetValue(FontManager.instance.itemTipsModuleObject, __result); FontManager.instance.itemTipsModuleFont = __result; return false; } return true; } } [HarmonyPatch(/*Could not decode attribute arguments.*/)] public class Tk2dTextMeshTextPatchClass { [HarmonyPostfix] public static void Tk2dTextMeshTextPostfix(tk2dTextMesh __instance) { tk2dFontData tk2dFont = FontManager.instance.tk2dFont; if ((Object)(object)tk2dFont != (Object)null && (Object)(object)__instance.font != (Object)(object)tk2dFont) { FontManager.SetTextMeshFont(__instance, tk2dFont); } if (__instance.data != null && __instance.data.text != null) { TranslationManager.instance.AddTranslationRequest(__instance.data.text, __instance); } } } [HarmonyPatch(/*Could not decode attribute arguments.*/)] public class Tk2dTextMeshFontPatchClass { [HarmonyPrefix] public static bool Tk2dTextMeshFontPrefix(tk2dTextMesh __instance) { tk2dFontData tk2dFont = FontManager.instance.tk2dFont; if ((Object)(object)tk2dFont != (Object)null && (Object)(object)__instance.font != (Object)(object)tk2dFont) { FontManager.SetTextMeshFont(__instance, tk2dFont); } return false; } } [HarmonyPatch(typeof(TextBoxManager), "SetText")] public class SetTextPatchClass { [HarmonyPrefix] public static void SetTextPrefix(ref bool instant) { instant = true; } } public class DynamicFontRendererTokenizePatchClass { public static bool TokenizePrefix(DynamicFontRenderer __instance, string text) { try { if (__instance.tokens != null) { if ((object)__instance.tokens[0].Source == text) { return false; } __instance.tokens.ReleaseItems(); __instance.tokens.Release(); } __instance.tokens = FontManager.instance?.Tokenize(text); for (int i = 0; i < __instance.tokens.Count; i++) { __instance.calculateTokenRenderSize(__instance.tokens[i]); } } finally { } return false; } } public class DynamicFontRendererCalculateLinebreaksPatchClass { [HarmonyILManipulator] public static void CalculateLinebreaksPatch(ILContext ctx) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) ILCursor crs = new ILCursor(ctx); if (TheNthTime(() => crs.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1] { (Instruction x) => ILPatternMatchingExt.MatchLdcI4(x, 0) }), 8)) { crs.Emit(OpCodes.Ldloca_S, (byte)3); crs.EmitCall<DynamicFontRendererCalculateLinebreaksPatchClass>("CalculateLinebreaksPatchCall_1"); ILCursor obj = crs; int index = obj.Index; obj.Index = index + 1; } if (crs.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1] { (Instruction x) => ILPatternMatchingExt.MatchLdcI4(x, 0) })) { crs.Emit(OpCodes.Ldloca_S, (byte)3); crs.EmitCall<DynamicFontRendererCalculateLinebreaksPatchClass>("CalculateLinebreaksPatchCall_1"); } if (crs.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1] { (Instruction x) => ILPatternMatchingExt.MatchLdcI4(x, 2) })) { crs.EmitCall<DynamicFontRendererCalculateLinebreaksPatchClass>("CalculateLinebreaksPatchCall_2"); } } private static void CalculateLinebreaksPatchCall_1(ref int orig) { orig--; } private static int CalculateLinebreaksPatchCall_2(int orig) { return 2; } } public class BitmappedFontRendererTokenizePatchClass { public static bool TokenizePrefix(BitmappedFontRenderer __instance, string text, ref dfList<dfMarkupToken> __result) { try { if (__instance.tokens != null) { if ((object)__instance.tokens[0].Source == text) { __result = __instance.tokens; return false; } __instance.tokens.ReleaseItems(); __instance.tokens.Release(); } __instance.tokens = FontManager.instance?.Tokenize(text); for (int i = 0; i < __instance.tokens.Count; i++) { __instance.calculateTokenRenderSize(__instance.tokens[i]); } __result = __instance.tokens; } finally { } return false; } } public class BitmappedFontRendererCalculateLinebreaksPatchClass { public static void CalculateLinebreaksPatch(ILContext ctx) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown ILCursor val = new ILCursor(ctx); if (val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1] { (Instruction x) => ILPatternMatchingExt.MatchLdcI4(x, 7) })) { val.EmitCall<BitmappedFontRendererCalculateLinebreaksPatchClass>("CalculateLinebreaksPatchCall_1"); } if (val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1] { (Instruction x) => ILPatternMatchingExt.MatchLdcI4(x, 2) })) { val.EmitCall<BitmappedFontRendererCalculateLinebreaksPatchClass>("CalculateLinebreaksPatchCall_2"); } } private static int CalculateLinebreaksPatchCall_1(int orig) { return 7; } private static int CalculateLinebreaksPatchCall_2(int orig) { return 2; } } [HarmonyPatch(typeof(tk2dTextMesh), "CheckFontsForLanguage")] public class Tk2dTextMeshCheckFontsForLanguagePatchClass { [HarmonyPrefix] public static bool CheckFontsForLanguagePrefix() { if ((Object)(object)FontManager.instance.tk2dFont != (Object)null) { return false; } return true; } } [HarmonyPatch(typeof(dfLabel), "CheckFontsForLanguage")] public class DfLabelCheckFontsForLanguagePatchClass { [HarmonyPrefix] public static bool CheckFontsForLanguagePrefix() { if ((Object)(object)FontManager.instance.dfFontBase != (Object)null) { return false; } return true; } } [HarmonyPatch(typeof(dfButton), "CheckFontsForLanguage")] public class DfButtonCheckFontsForLanguagePatchClass { [HarmonyPrefix] public static bool CheckFontsForLanguagePrefix() { if ((Object)(object)FontManager.instance.dfFontBase != (Object)null) { return false; } return true; } } [HarmonyPatch(typeof(DefaultLabelController), "Trigger", new Type[] { typeof(Transform), typeof(Vector3) })] public class DefaultLabelControllerTriggerPatchClass { [HarmonyPrefix] public static void TriggerPrefix(DefaultLabelController __instance) { __instance.label.AutoSize = true; } } [HarmonyPatch(typeof(SimpleStatLabel), "Start")] public class SimpleStatLabelStartPatchClass { [HarmonyPostfix] public static void StartPostfix(SimpleStatLabel __instance) { __instance.m_label.autoSize = true; } } [HarmonyPatch(typeof(GameUIRoot), "UpdatePlayerConsumables")] public class UpdatePlayerConsumablesPatchClass { [HarmonyPrefix] public static void UpdatePlayerConsumablesPrefix(GameUIRoot __instance) { __instance.p_playerKeyLabel.autoSize = true; __instance.p_playerCoinLabel.autoSize = true; } } [HarmonyPatch(typeof(DynamicFontRenderer), "renderText")] public class RenderTextPatchClass { [HarmonyILManipulator] public static void RenderTextPatch(ILContext ctx) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) ILCursor val = new ILCursor(ctx); if (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1] { (Instruction x) => ILPatternMatchingExt.MatchCall<CharacterInfo>(x, "get_maxX") })) { val.Emit(OpCodes.Ldloca_S, (byte)3); val.EmitCall<RenderTextPatchClass>("RenderTextPatchCall"); } } private static int RenderTextPatchCall(int orig, ref CharacterInfo characterInfo) { return ((CharacterInfo)(ref characterInfo)).advance; } } [HarmonyPatch(typeof(DynamicFontRenderer), "calculateTokenRenderSize")] public class CalculateTokenRenderSizePatchClass { [HarmonyILManipulator] public static void CalculateTokenRenderSizePatch(ILContext ctx) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) ILCursor val = new ILCursor(ctx); if (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1] { (Instruction x) => ILPatternMatchingExt.MatchCall<CharacterInfo>(x, "get_maxX") })) { val.Emit(OpCodes.Ldloca_S, (byte)3); val.EmitCall<CalculateTokenRenderSizePatchClass>("CalculateTokenRenderSizePatchCall"); } } private static int CalculateTokenRenderSizePatchCall(int orig, ref CharacterInfo characterInfo) { return ((CharacterInfo)(ref characterInfo)).advance; } } [HarmonyPatch] public class GetCharacterWidthsPatchClass { public static MethodBase TargetMethod() { return AccessTools.Method(typeof(DynamicFontRenderer), "GetCharacterWidths", new Type[4] { typeof(string), typeof(int), typeof(int), typeof(float).MakeByRefType() }, (Type[])null); } [HarmonyILManipulator] public static void GetCharacterWidthsPatch(ILContext ctx) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) ILCursor val = new ILCursor(ctx); if (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1] { (Instruction x) => ILPatternMatchingExt.MatchCall<CharacterInfo>(x, "get_maxX") })) { val.Emit(OpCodes.Ldloca_S, (byte)5); val.EmitCall<GetCharacterWidthsPatchClass>("GetCharacterWidthsPatchCall"); } } private static int GetCharacterWidthsPatchCall(int orig, ref CharacterInfo characterInfo) { return ((CharacterInfo)(ref characterInfo)).advance; } } public class ConvertStringToFixedWidthLinesPatchClass { public static bool ConvertStringToFixedWidthLinesPrefix(string text, ref List<string> __result) { __result = new List<string> { text }; return false; } } public class GenerateTextInfoPatchClass { public static void GenerateTextInfoPatch(ILContext ctx) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) ILCursor val = new ILCursor(ctx); if (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1] { (Instruction x) => ILPatternMatchingExt.MatchCall<string>(x, "Join") })) { val.Emit(OpCodes.Ldloca_S, (byte)4); val.EmitCall<GenerateTextInfoPatchClass>("GenerateTextInfoPatchCall"); } } private static string GenerateTextInfoPatchCall(string text, ref Vector2 size) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) FontManager.instance.itemTipsModuleText = text; Vector2 resultSize; string result = FontManager.instance.WrapText(text, out resultSize); size = resultSize; return result; } } [HarmonyPatch(/*Could not decode attribute arguments.*/)] public class Expand_CRPatchClass { [HarmonyILManipulator] public static void Expand_CRPatch(ILContext ctx) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) ILCursor val = new ILCursor(ctx); if (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1] { (Instruction x) => ILPatternMatchingExt.MatchLdfld(x, "DefaultLabelController+<Expand_CR>c__Iterator0", "<targetWidth>__0") })) { val.Emit(OpCodes.Ldarg_0); val.EmitCall<Expand_CRPatchClass>("Expand_CRPatchCall"); } } private static float Expand_CRPatchCall(float orig, object selfObject) { DefaultLabelController fieldValueInEnumerator = GetFieldValueInEnumerator<DefaultLabelController>(selfObject, "this"); return ((dfControl)fieldValueInEnumerator.label).Width + 1f; } } [HarmonyPatch(typeof(DefaultLabelController), "UpdateForLanguage")] public class DefaultLabelControllerUpdateForLanguagePatchClass { [HarmonyPrefix] public static bool UpdateForLanguagePrefix() { if (FontManager.instance.overrideFont == AutoTranslateModule.OverrideFontType.Custom && (Object)(object)FontManager.instance.dfFontBase != (Object)null) { return false; } return true; } [HarmonyILManipulator] public static void UpdateForLanguagePatch(ILContext ctx) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown ILCursor val = new ILCursor(ctx); if (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1] { (Instruction x) => ILPatternMatchingExt.MatchLdcI4(x, -6) })) { val.EmitCall<DefaultLabelControllerUpdateForLanguagePatchClass>("UpdateForLanguagePatchCall"); } } private static int UpdateForLanguagePatchCall(int orig) { return -2; } } public class NewShopItemControllerPatchClass { public static void NewShopItemControllerPrefix(DefaultLabelController labelController) { labelController.label.AutoSize = false; } } public class RepositionPatchClass { public static void RepositionPostfix(SLabel __instance) { FontManager.instance.ItemTipsReposition(__instance); } } [HarmonyPatch] public class MeasureTextPatchClass { public static MethodBase TargetMethod() { return AccessTools.Method(typeof(SGUIIMBackend), "MeasureText", new Type[3] { typeof(string).MakeByRefType(), typeof(Vector2?), typeof(object) }, (Type[])null); } [HarmonyILManipulator] public static void MeasureTextPatch(ILContext ctx) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) ILCursor val = new ILCursor(ctx); if (val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1] { (Instruction x) => ILPatternMatchingExt.MatchCallvirt<Font>(x, "RequestCharactersInTexture") })) { val.Emit(OpCodes.Ldloc_0); val.EmitCall<MeasureTextPatchClass>("MeasureTextPatchCall_1"); } if (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1] { (Instruction x) => ILPatternMatchingExt.MatchCallvirt<Font>(x, "GetCharacterInfo") })) { val.Emit(OpCodes.Ldloc_0); val.Emit(OpCodes.Ldloc_S, (byte)9); val.Emit(OpCodes.Ldloca_S, (byte)10); val.EmitCall<MeasureTextPatchClass>("MeasureTextPatchCall_2"); } } private static int MeasureTextPatchCall_1(int orig, Font font2) { if ((Object)(object)FontManager.instance.potentialItemTipsDynamicBaseFont != (Object)null && (Object)(object)font2 == (Object)(object)FontManager.instance.potentialItemTipsDynamicBaseFont) { return Mathf.RoundToInt((float)font2.fontSize * config.ItemTipsFontScale); } return orig; } private static bool MeasureTextPatchCall_2(bool orig, Font font2, char c, out CharacterInfo characterInfo2) { if ((Object)(object)FontManager.instance.potentialItemTipsDynamicBaseFont != (Object)null && (Object)(object)font2 == (Object)(object)FontManager.instance.potentialItemTipsDynamicBaseFont) { return font2.GetCharacterInfo(c, ref characterInfo2, Mathf.RoundToInt((float)font2.fontSize * config.ItemTipsFontScale)); } return font2.GetCharacterInfo(c, ref characterInfo2); } } [HarmonyPatch(typeof(SLabel), "Render")] public class SLabelRenderPatchClass { [HarmonyPrefix] public static void RenderPrefix(SLabel __instance) { object font = ((SElement)__instance).Font; Font val = (Font)((font is Font) ? font : null); if (val != null && (Object)(object)FontManager.instance.potentialItemTipsDynamicBaseFont != (Object)null && (Object)(object)val == (Object)(object)FontManager.instance.potentialItemTipsDynamicBaseFont) { ISGUIBackend backend = ((SElement)__instance).Backend; SGUIIMBackend val2 = (SGUIIMBackend)(object)((backend is SGUIIMBackend) ? backend : null); if (val2 != null) { val2.Skin.label.fontSize = Mathf.RoundToInt((float)val.fontSize * config.ItemTipsFontScale); } } } } [HarmonyPatch(/*Could not decode attribute arguments.*/)] public class GetLineHeightPatchClass { [HarmonyPostfix] public static void GetLineHeightPostfix(SGUIIMBackend __instance, ref float __result) { if ((Object)(object)__instance.Skin.font != (Object)null && (Object)(object)__instance.Skin.font == (Object)(object)FontManager.instance.potentialItemTipsDynamicBaseFont) { __result = (float)__instance.Skin.font.fontSize * config.ItemTipsFontScale * config.ItemTipsLineHeightScale; } else if ((Object)(object)__instance.Skin.font != (Object)null && (Object)(object)__instance.Skin.font == (Object)(object)FontManager.instance.itemTipsModuleFont) { __result = 1.1f * (float)FontManager.instance.originalLineHeight * config.ItemTipsFontScale * config.ItemTipsLineHeightScale; } } } private static AutoTranslateConfig config = AutoTranslateModule.instance.config; private static readonly Regex spritePattern = new Regex("(\\[sprite\\s+\"[^\"]*\")(?!\\])", RegexOptions.Compiled); public static void EmitCall<T>(this ILCursor iLCursor, string methodName, Type[] parameters = null, Type[] generics = null) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) MethodInfo methodInfo = AccessTools.Method(typeof(T), methodName, parameters, generics); iLCursor.Emit(OpCodes.Call, (MethodBase)methodInfo); } public static bool TheNthTime(this Func<bool> predict, int n = 1) { for (int i = 0; i < n; i++) { if (!predict()) { return false; } } return true; } public static T GetFieldValueInEnumerator<T>(object instance, string fieldNamePattern) { return (T)instance.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((FieldInfo f) => f.Name.Contains("$" + fieldNamePattern) || f.Name.Contains("<" + fieldNamePattern + ">") || f.Name == fieldNamePattern) .GetValue(instance); } private static string AddMissingBracket(string input) { return spritePattern.Replace(input, (Match match) => match.Groups[1].Value + "]"); } private static void DfLabelTextAddCall(dfLabel instance) { dfFontBase dfFontBase = FontManager.instance.dfFontBase; if ((Object)(object)dfFontBase != (Object)null && (Object)(object)instance.Font != (Object)(object)dfFontBase) { instance.Font = dfFontBase; dfFont val = (dfFont)(object)((dfFontBase is dfFont) ? dfFontBase : null); if (val != null) { instance.Atlas = val.Atlas; } if (config.DfTextScaleExpandThreshold >= 0f && instance.TextScale < config.DfTextScaleExpandThreshold) { instance.TextScale = config.DfTextScaleExpandToValue; } } TranslationManager.instance.AddTranslationRequest(instance.text, instance); } private static void DfButtonTextAddCall(dfButton instance) { dfFontBase dfFontBase = FontManager.instance.dfFontBase; if ((Object)(object)dfFontBase != (Object)null && (Object)(object)instance.Font != (Object)(object)dfFontBase) { instance.Font = dfFontBase; dfFont val = (dfFont)(object)((dfFontBase is dfFont) ? dfFontBase : null); if (val != null) { ((dfInteractiveBase)instance).Atlas = val.Atlas; } if (config.DfTextScaleExpandThreshold >= 0f && instance.TextScale < config.DfTextScaleExpandThreshold) { instance.TextScale = config.DfTextScaleExpandToValue; } } string text = AddMissingBracket(instance.text); if (text != instance.text) { instance.text = text; ((dfControl)instance).Invalidate(); } TranslationManager.instance.AddTranslationRequest(instance.text, instance); } } public class AzureTranslationService : ITranslationService { private AutoTranslateConfig config; private string endpoint = "https://api.cognitive.microsofttranslator.com"; private string action = "/translate"; private string version = "3.0"; public AzureTranslationService(AutoTranslateConfig config) { this.config = config; } private string[] ParseResponse(string responseJson) { //IL_000d: Expected O, but got Unknown JArray val; try { val = JArray.Parse(responseJson); } catch (JsonReaderException val2) { JsonReaderException innerException = val2; throw new InvalidOperationException("响应的JSON格式无效 The JSON format of the response is invalid: ", (Exception?)(object)innerException); } List<string> list = new List<string>(); foreach (JToken item in val) { JToken obj = item[(object)"translations"]; JArray val3 = (JArray)(object)((obj is JArray) ? obj : null); if (val3 == null) { continue; } foreach (JToken item2 in val3) { list.Add(((object)item2[(object)"text"]).ToString()); } } if (list.Count == 0) { throw new InvalidOperationException("翻译结果为空!The translation result is empty!"); } return list.ToArray(); } public static string[] PreprocessText(List<string> inputTexts) { return inputTexts.Select((string text) => text.Replace("\r", "")).ToArray(); } public IEnumerator StartTranslation(List<string> texts, Action<string[]> callback) { string[] preprocessedTexts = PreprocessText(texts); var payload = preprocessedTexts.Select((string text) => new { Text = text }).ToArray(); string payloadJson = JsonConvert.SerializeObject((object)payload); string subscriptionKey = config.AzureSubscriptionKey; string region = config.AzureRegion; string requestUrl = endpoint + action + "?api-version=" + version + "&to=" + config.AzureTargetLanguage; if (config.AzureSourceLanguage != string.Empty) { requestUrl = requestUrl + "&from=" + config.AzureSourceLanguage; } int retryCount = 0; bool needRetry = false; while (true) { if (needRetry) { if (retryCount >= config.MaxRetryCount) { break; } retryCount++; Debug.Log((object)$"正在重试。。。尝试第 {retryCount} 次。Retrying... Attempt time {retryCount}."); needRetry = false; yield return (object)new WaitForSecondsRealtime(config.RetryInterval); } UnityWebRequest request = new UnityWebRequest(requestUrl, "POST"); try { byte[] bodyRaw = Encoding.UTF8.GetBytes(payloadJson); request.uploadHandler = (UploadHandler)new UploadHandlerRaw(bodyRaw); request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); request.SetRequestHeader("Content-Type", "application/json"); request.SetRequestHeader("Ocp-Apim-Subscription-Key", subscriptionKey); request.SetRequestHeader("Ocp-Apim-Subscription-Region", region); yield return request.SendWebRequest(); if (request.isNetworkError || request.isHttpError) { Debug.LogError((object)("请求失败 Request failed: " + request.error)); needRetry = true; continue; } string responseJson = request.downloadHandler.text; string[] translatedTexts; try { translatedTexts = ParseResponse(responseJson); } catch (Exception ex2) { Exception ex = ex2; Debug.LogError((object)("解析翻译结果失败 Failed to parse translation result:" + ex.Message)); Debug.LogError((object)("响应JSON Response JSON:\n" + responseJson)); needRetry = true; goto end_IL_027d; } if (translatedTexts != null) { callback?.Invoke(translatedTexts); yield break; } Debug.LogError((object)"翻译失败,未获得翻译结果!Translation failed, no translation result obtained!"); needRetry = true; yield break; end_IL_027d:; } finally { ((IDisposable)request)?.Dispose(); } } Debug.LogError((object)$"多次尝试失败。已重试 {config.MaxRetryCount} 次。翻译中止!Multiple attempts failed. Retried {config.MaxRetryCount} times. translation aborted!"); callback?.Invoke(null); } } public class BaiduTranslationService : ITranslationService { private AutoTranslateConfig config; private string apiUrl = "https://fanyi-api.baidu.com/api/trans/vip/translate"; public BaiduTranslationService(AutoTranslateConfig config) { this.config = config; } private string[] ParseResponse(string responseJson) { //IL_000d: Expected O, but got Unknown JObject val; try { val = JObject.Parse(responseJson); } catch (JsonReaderException val2) { JsonReaderException innerException = val2; throw new InvalidOperationException("响应的JSON格式无效 The JSON format of the response is invalid: ", (Exception?)(object)innerException); } if (val["error_code"] != null) { string text = ((object)val["error_code"])?.ToString(); string text2 = ((object)val["error_msg"])?.ToString(); throw new InvalidOperationException("API请求失败 API request failed: " + text + " - " + text2); } JToken val3 = val["trans_result"]; if (val3 == null) { throw new InvalidOperationException("响应JSON中缺少trans_result字段!The 'trans_desult' field is missing in the response JSON!"); } if (!((IEnumerable<JToken>)val3).Any()) { throw new InvalidOperationException("翻译结果为空!The translation result is empty!"); } return ((IEnumerable<JToken>)val3).Select((JToken result) => ((object)result[(object)"dst"])?.ToString() ?? string.Empty).ToArray(); } public static string[] PreprocessText(List<string> inputTexts) { return inputTexts.Select((string text) => text.Replace("\n", "\\n").Replace("\r", "")).ToArray(); } public IEnumerator StartTranslation(List<string> texts, Action<string[]> callback) { string salt = Guid.NewGuid().ToString(); string[] preprocessedTexts = PreprocessText(texts); string sign = GenerateSign(config.BaiduAppId, string.Join("\n", preprocessedTexts), salt, config.BaiduSecretKey); string url = apiUrl + "?q=" + Uri.EscapeDataString(string.Join("\n", preprocessedTexts)) + "&from=" + config.BaiduSourceLanguage + "&to=" + config.BaiduTargetLanguage + "&appid=" + config.BaiduAppId + "&salt=" + salt + "&sign=" + sign; bool needRetry = false; int retryCount = 0; while (true) { if (needRetry) { if (retryCount >= config.MaxRetryCount) { break; } retryCount++; Debug.Log((object)$"正在重试。。。尝试第 {retryCount} 次。Retrying... Attempt time {retryCount}."); needRetry = false; yield return (object)new WaitForSecondsRealtime(config.RetryInterval); } UnityWebRequest request = UnityWebRequest.Get(url); try { yield return request.SendWebRequest(); if (request.isNetworkError || request.isHttpError) { Debug.LogError((object)("请求失败 Request failed: " + request.error)); needRetry = true; continue; } string responseJson = request.downloadHandler.text; string[] translatedTexts; try { translatedTexts = ParseResponse(responseJson); } catch (Exception ex2) { Exception ex = ex2; Debug.LogError((object)("解析翻译结果失败 Failed to parse translation result:" + ex.Message)); Debug.LogError((object)("响应JSON Response JSON:\n" + responseJson)); needRetry = true; goto end_IL_027b; } if (translatedTexts != null) { callback?.Invoke(translatedTexts); yield break; } Debug.LogError((object)"翻译失败,未获得翻译结果!Translation failed, no translation result obtained!"); needRetry = true; yield break; end_IL_027b:; } finally { ((IDisposable)request)?.Dispose(); } } Debug.LogError((object)$"多次尝试失败。已重试 {config.MaxRetryCount} 次。翻译中止!Multiple attempts failed. Retried {config.MaxRetryCount} times. translation aborted!"); callback?.Invoke(null); } private string GenerateSign(string appId, string query, string salt, string secretKey) { string s = appId + query + salt + secretKey; using MD5 mD = MD5.Create(); byte[] array = mD.ComputeHash(Encoding.UTF8.GetBytes(s)); StringBuilder stringBuilder = new StringBuilder(); byte[] array2 = array; foreach (byte b in array2) { stringBuilder.Append(b.ToString("x2")); } return stringBuilder.ToString(); } } public interface ITranslationService { IEnumerator StartTranslation(List<string> texts, Action<string[]> callback); } public class LlmTranslationService : ITranslationService { private AutoTranslateConfig config; private StringBuilder builder = new StringBuilder(); private StringBuilder jsonBuilder = new StringBuilder(); private StringBuilder positionedBuilder = new StringBuilder(); private readonly string[] cachedSplitPattern = new string[1]; private static Regex positionedResponseRegex; public LlmTranslationService(AutoTranslateConfig config) { this.config = config; cachedSplitPattern[0] = config.LlmSplitText; } private string[] ParseJsonResponse(string content) { //IL_0053: Expected O, but got Unknown List<string> list = new List<string>(); try { JArray val = JArray.Parse(content); foreach (JToken item in val) { list.Add(((object)item[(object)"text"]).ToString()); } } catch (JsonReaderException val2) { JsonReaderException val3 = val2; Debug.LogError((object)("解析 'content' 字段时失败: " + ((Exception)(object)val3).Message)); } return list.ToArray(); } private string[] ParseSplittedResponse(string response) { if (string.IsNullOrEmpty(response)) { return null; } string[] result = null; try { result = response.Split(cachedSplitPattern, StringSplitOptions.RemoveEmptyEntries); } catch (Exception arg) { Debug.LogError((object)$"分割字符串时发生意外错误。An unexpected error occurred while splitting the string.{arg}"); } return result; } private string[] ParsePositionedResponse(string response) { if (string.IsNullOrEmpty(response)) { return null; } if (string.IsNullOrEmpty(config.LlmPositionText) || string.IsNullOrEmpty(config.LlmSegmentText)) { throw new ArgumentException("标记不能为空。The tag cannot be empty."); } string llmPositionText = config.LlmPositionText; string llmSegmentText = config.LlmSegmentText; List<string> list = new List<string>(); int length = response.Length; int num = 0; int length2 = llmPositionText.Length; int length3 = llmSegmentText.Length; while (num < length) { int num2 = response.IndexOf(llmPositionText, num, StringComparison.OrdinalIgnoreCase); if (num2 == -1) { string text = response.Substring(num); if (!IsNullOrWhiteSpace(text)) { list.Add(text.Trim()); } break; } if (num2 > num) { string text2 = response.Substring(num, num2 - num); if (!IsNullOrWhiteSpace(text2)) { list.Add(text2.Trim()); } } int i; for (i = num2 + length2; i < length && response[i] >= '0' && response[i] <= '9'; i++) { } num = ((i + length3 > length || string.Compare(response, i, llmSegmentText, 0, length3, StringComparison.OrdinalIgnoreCase) != 0) ? i : (i + length3)); } return (list.Count > 0) ? list.ToArray() : null; } private static bool IsNullOrWhiteSpace(string value) { return string.IsNullOrEmpty(value) || value.Trim().Length == 0; } private string[] ParseFormattedResponse(string responseJson, List<string> texts) { string text = ParseResponse(responseJson); string[] array = null; if (!string.IsNullOrEmpty(text)) { switch (config.LlmDataFormat) { case AutoTranslateModule.LlmDataFormatType.Json: array = ParseJsonResponse(text); break; case AutoTranslateModule.LlmDataFormatType.Split: array = ParseSplittedResponse(text); break; case AutoTranslateModule.LlmDataFormatType.Positioned: array = ParsePositionedResponse(text); break; } } if (array == null || array.Length == 0) { throw new InvalidOperationException("翻译结果为空!The translation result is empty!"); } if (array.Length != texts.Count) { Debug.LogError((object)"翻译结果数量与请求数量不匹配!The number of translation results does not match the number of requests!"); Debug.LogError((object)"请求 Requests:"); foreach (string text3 in texts) { Debug.Log((object)(" " + text3)); } Debug.LogError((object)"结果 Results:"); string[] array2 = array; foreach (string text2 in array2) { Debug.Log((object)(" " + text2)); } throw new InvalidOperationException("翻译结果数量与请求数量不匹配!The number of translation results does not match the number of requests!"); } return array; } private string ParseResponse(string responseJson) { //IL_000d: Expected O, but got Unknown JObject val; try { val = JObject.Parse(responseJson); } catch (JsonReaderException val2) { JsonReaderException innerException = val2; throw new InvalidOperationException("响应的JSON格式无效 The JSON format of the response is invalid: ", (Exception?)(object)innerException); } string text = null; JToken obj = val["choices"]; JArray val3 = (JArray)(object)((obj is JArray) ? obj : null); if (val3 != null) { JToken obj2 = val3[0][(object)"message"]; string text2 = ((obj2 == null) ? null : ((object)obj2[(object)"content"])?.ToString()); if (!string.IsNullOrEmpty(text2)) { text = text2; } } if (text == null) { throw new InvalidOperationException("翻译结果为空!The translation result is empty!"); } return text; } private string ReplaceQuotesWithChinese(string source) { builder.Length = 0; bool flag = false; bool flag2 = false; foreach (char c in source) { switch (c) { case '"': builder.Append(flag ? '”' : '“'); flag = !flag; break; case '\'': builder.Append(flag2 ? '’' : '‘'); flag2 = !flag2; break; default: builder.Append(c); break; } } return builder.ToString(); } private string PreprocessQuotes(string source) { AutoTranslateModule.LlmQuotePreprocessType llmQuotePreprocess = config.LlmQuotePreprocess; AutoTranslateModule.LlmQuotePreprocessType llmQuotePreprocessType = llmQuotePreprocess; if (llmQuotePreprocessType != 0 && llmQuotePreprocessType == AutoTranslateModule.LlmQuotePreprocessType.Chinese) { return ReplaceQuotesWithChinese(source); } return source.Replace("\"", "\\\""); } private string ConvertListToJson(List<string> texts) { jsonBuilder.Length = 0; jsonBuilder.Append("["); for (int i = 0; i < texts.Count; i++) { if (i > 0) { jsonBuilder.Append(", "); } int value = i + 1; jsonBuilder.Append("{\"id\": ").Append(value).Append(", \"text\": \"") .Append(PreprocessQuotes(texts[i].Replace("\\\\", "\\").Replace("\r", ""))) .Append("\"}"); } jsonBuilder.Append("]"); return jsonBuilder.ToString(); } private string ConvertListToSplitted(List<string> texts) { if (texts == null || texts.Count == 0) { return string.Empty; } return string.Join(config.LlmSplitText, texts.ToArray()).Replace("\r", ""); } private string ConvertListToPositioned(List<string> texts) { if (texts == null || texts.Count == 0) { return string.Empty; } positionedBuilder.Length = 0; for (int i = 0; i < texts.Count; i++) { positionedBuilder.Append("<!pos!>").Append(i + 1).Append("<!seg!>") .Append(texts[i]); } return positionedBuilder.ToString().Replace("\r", ""); } private string ConvertListToFormatted(List<string> texts) { return config.LlmDataFormat switch { AutoTranslateModule.LlmDataFormatType.Json => ConvertListToJson(texts), AutoTranslateModule.LlmDataFormatType.Split => ConvertListToSplitted(texts), _ => ConvertListToPositioned(texts), }; } public IEnumerator StartSingleTranslation(List<string> texts, Action<string[]> callback) { JObject val = new JObject(); val.Add("model", JToken.op_Implicit(config.LlmName)); JArray val2 = new JArray(); JObject val3 = new JObject(); val3.Add("role", JToken.op_Implicit("system")); val3.Add("content", JToken.op_Implicit(config.LlmPrompt)); val2.Add((JToken)val3); JObject val4 = new JObject(); val4.Add("role", JToken.op_Implicit("user")); val4.Add("content", JToken.op_Implicit(ConvertListToFormatted(texts))); val2.Add((JToken)val4); val.Add("messages", (JToken)val2); val.Add("temperature", JToken.op_Implicit(config.LlmTemperature)); val.Add("max_tokens", JToken.op_Implicit(config.LlmMaxTokens)); val.Add("top_p", JToken.op_Implicit(config.LlmTopP)); val.Add("top_k", JToken.op_Implicit(config.LlmTopK)); val.Add("frequency_penalty", JToken.op_Implicit(config.LlmFrequencyPenalty)); val.Add("n", JToken.op_Implicit(1)); JObject jsonObject = val; if (!string.IsNullOrEmpty(config.LlmExtraParametersJson)) { JObject extraObj = JObject.Parse(config.LlmExtraParametersJson); foreach (JProperty property in extraObj.Properties()) { jsonObject[property.Name] = property.Value; } } string payloadJson = ((JToken)jsonObject).ToString((Formatting)0, (JsonConverter[])(object)new JsonConverter[0]); string requestUrl = config.LlmBaseUrl ?? ""; int retryCount = 0; bool needRetry = false; while (true) { if (needRetry) { if (retryCount >= config.MaxRetryCount) { break; } retryCount++; Debug.Log((object)$"正在重试。。。尝试第 {retryCount} 次。Retrying... Attempt time {retryCount}."); needRetry = false; yield return (object)new WaitForSecondsRealtime(config.RetryInterval); } UnityWebRequest request = new UnityWebRequest(requestUrl, "POST"); try { byte[] bodyRaw = Encoding.UTF8.GetBytes(payloadJson); request.uploadHandler = (UploadHandler)new UploadHandlerRaw(bodyRaw); request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); request.SetRequestHeader("Content-Type", "application/json"); request.SetRequestHeader("Authorization", "Bearer " + config.LlmApiKey); yield return request.SendWebRequest(); if (request.isNetworkError || request.isHttpError) { Debug.LogError((object)("请求失败 Request failed: " + request.error)); needRetry = true; continue; } string responseJson = request.downloadHandler.text; string[] translatedTexts; try { translatedTexts = ParseFormattedResponse(responseJson, texts); } catch (Exception ex2) { Exception ex = ex2; Debug.LogError((object)("解析翻译结果失败 Failed to parse translation result: " + ex.Message)); Debug.LogError((object)("响应JSON Response JSON:\n" + responseJson)); needRetry = true; goto end_IL_03cd; } if (translatedTexts != null && translatedTexts.Length != 0) { callback?.Invoke(translatedTexts); yield break; } Debug.LogError((object)"翻译失败,未获得翻译结果!Translation failed, no translation result obtained!"); needRetry = true; yield break; end_IL_03cd:; } finally { ((IDisposable)request)?.Dispose(); } } Debug.LogError((object)$"多次尝试失败。已重试 {config.MaxRetryCount} 次。翻译中止!Multiple attempts failed. Retried {config.MaxRetryCount} times. Translation aborted!"); callback?.Invoke(null); } public IEnumerator StartTranslation(List<string> texts, Action<string[]> callback) { if (config.LlmDataFormat == AutoTranslateModule.LlmDataFormatType.Parallel) { yield return ((MonoBehaviour)TranslationManager.instance).StartCoroutine(StartParallelBatchTranslation(texts, callback)); } else { yield return ((MonoBehaviour)TranslationManager.instance).StartCoroutine(StartSingleTranslation(texts, callback)); } } public IEnumerator StartParallelBatchTranslation(List<string> texts, Action<string[]> callback) { int totalBatches = texts.Count; int completedBatches = 0; bool anyFailed = false; string[] batchResults = new string[totalBatches]; for (int i = 0; i < totalBatches; i++) { int batchIndex = i; string singleText = texts[i]; ((MonoBehaviour)TranslationManager.instance).StartCoroutine(SendBatchRequest(singleText, batchIndex, delegate(bool success, string results) { int num = completedBatches; completedBatches = num + 1; if (success && results != null) { batchResults[batchIndex] = results; } else { anyFailed = true; } if (completedBatches == totalBatches) { if (anyFailed) { Debug.LogError((object)"并行批量模式存在失败批次。There are failed batches in parallel batch mode."); callback?.Invoke(null); } else { callback?.Invoke(batchResults); } } })); } while (completedBatches < totalBatches) { yield return null; } } private IEnumerator SendBatchRequest(string singleText, int batchIndex, Action<bool, string> batchCallback) { JObject val = new JObject(); val.Add("model", JToken.op_Implicit(config.LlmName)); JArray val2 = new JArray(); JObject val3 = new JObject(); val3.Add("role", JToken.op_Implicit("system")); val3.Add("content", JToken.op_Implicit(config.LlmPrompt)); val2.Add((JToken)val3); JObject val4 = new JObject(); val4.Add("role", JToken.op_Implicit("user")); val4.Add("content", JToken.op_Implicit(singleText.Replace("\r", ""))); val2.Add((JToken)val4); val.Add("messages", (JToken)val2); val.Add("temperature", JToken.op_Implicit(config.LlmTemperature)); val.Add("max_tokens", JToken.op_Implicit(config.LlmMaxTokens)); val.Add("top_p", JToken.op_Implicit(config.LlmTopP)); val.Add("top_k", JToken.op_Implicit(config.LlmTopK)); val.Add("frequency_penalty", JToken.op_Implicit(config.LlmFrequencyPenalty)); val.Add("n", JToken.op_Implicit(1)); JObject jsonObject = val; if (!string.IsNullOrEmpty(config.LlmExtraParametersJson)) { JObject extraObj = JObject.Parse(config.LlmExtraParametersJson); foreach (JProperty property in extraObj.Properties()) { jsonObject[property.Name] = property.Value; } } string payloadJson = ((JToken)jsonObject).ToString((Formatting)0, (JsonConverter[])(object)new JsonConverter[0]); string requestUrl = config.LlmBaseUrl ?? ""; int retryCount = 0; bool needRetry = false; while (true) { if (needRetry) { if (retryCount >= config.MaxRetryCount) { break; } retryCount++; Debug.Log((object)$"批次 {batchIndex} 正在重试... 尝试第 {retryCount} 次。Batch {batchIndex} is retrying... Attempt time {retryCount}."); needRetry = false; yield return (object)new WaitForSecondsRealtime(config.RetryInterval); } UnityWebRequest request = new UnityWebRequest(requestUrl, "POST"); try { byte[] bodyRaw = Encoding.UTF8.GetBytes(payloadJson); request.uploadHandler = (UploadHandler)new UploadHandlerRaw(bodyRaw); request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); request.SetRequestHeader("Content-Type", "application/json"); request.SetRequestHeader("Authorization", "Bearer " + config.LlmApiKey); yield return request.SendWebRequest(); if (request.isNetworkError || request.isHttpError) { Debug.LogError((object)$"批次 {batchIndex} 请求失败 Request failed in batch {batchIndex}: {request.error}"); needRetry = true; continue; } string responseJson = request.downloadHandler.text; string translatedText; try { translatedText = ParseResponse(responseJson); } catch (Exception ex2) { Exception ex = ex2; Debug.LogError((object)$"批次 {batchIndex} 解析翻译结果失败 Failed to parse translation result in batch {batchIndex}: {ex.Message}"); Debug.LogError((object)("响应JSON Response JSON:\n" + responseJson)); needRetry = true; goto end_IL_0425; } if (translatedText != null) { batchCallback?.Invoke(arg1: true, translatedText); yield break; } Debug.LogError((object)$"批次 {batchIndex} 无翻译结果。No translation results in batch {batchIndex}."); needRetry = true; yield break; end_IL_0425:; } finally { ((IDisposable)request)?.Dispose(); } } Debug.LogError((object)$"批次 {batchIndex} 多次尝试失败。已重试 {config.MaxRetryCount} 次。Multiple attempts failed in batch {batchIndex}. Retried {config.MaxRetryCount} times. Translation aborted!"); batchCallback?.Invoke(arg1: false, null); } } public class LRUCache<TKey, TValue> { public class CacheItem { public TKey Key; public TValue Value; public void Reset(TKey key, TValue value) { Key = key; Value = value; } } private readonly int _capacity; private readonly Dictionary<TKey, LinkedListNode<CacheItem>> _cache; private readonly LinkedList<CacheItem> _order; private readonly ObjectPool<LinkedListNode<CacheItem>> _nodePool; private readonly ObjectPool<CacheItem> _cacheItemPool; public LRUCache(int capacity) { if (capacity <= 0) { throw new ArgumentException("容量必须大于0。Capacity must be greater than zero."); } _capacity = capacity; _cache = new Dictionary<TKey, LinkedListNode<CacheItem>>(capacity); _order = new LinkedList<CacheItem>(); _nodePool = new ObjectPool<LinkedListNode<CacheItem>>(() => new LinkedListNode<CacheItem>(null), capacity, delegate(LinkedListNode<CacheItem> node) { node.Value = null; }); _cacheItemPool = new ObjectPool<CacheItem>(() => new CacheItem(), capacity, delegate(CacheItem item) { item.Reset(default(TKey), default(TValue)); }); } public TValue Get(TKey key) { if (_cache.TryGetValue(key, out var value)) { _order.Remove(value); _order.AddFirst(value); return value.Value.Value; } return default(TValue); } public bool TryGetValue(TKey key, out TValue value) { if (_cache.TryGetValue(key, out var value2)) { _order.Remove(value2); _order.AddFirst(value2); value = value2.Value.Value; return true; } value = default(TValue); return false; } public void Set(TKey key, TValue value) { if (_cache.TryGetValue(key, out var value2)) { if (!EqualityComparer<TValue>.Default.Equals(value2.Value.Value, value)) { value2.Value.Reset(key, value); } return; } if (_cache.Count >= _capacity) { LinkedListNode<CacheItem> last = _order.Last; _cache.Remove(last.Value.Key); _order.RemoveLast(); _cacheItemPool.Return(last.Value); _nodePool.Return(last); } CacheItem cacheItem = _cacheItemPool.Get(); cacheItem.Reset(key, value); value2 = _nodePool.Get(); value2.Value = cacheItem; _order.AddFirst(value2); _cache[key] = value2; } public bool ContainsKey(TKey key) { return _cache.ContainsKey(key); } public List<KeyValuePair<TKey, TValue>> GetOrderedKeyValuePairs() { List<KeyValuePair<TKey, TValue>> list = new List<KeyValuePair<TKey, TValue>>(_cache.Count); for (LinkedListNode<CacheItem> linkedListNode = _order.First; linkedListNode != null; linkedListNode = linkedListNode.Next) { if (linkedListNode.Value != null) { list.Add(new KeyValuePair<TKey, TValue>(linkedListNode.Value.Key, linkedListNode.Value.Value)); } } return list; } public int GetCapacity() { return _capacity; } public Dictionary<TKey, LinkedListNode<CacheItem>> GetCache() { return _cache; } public LinkedList<CacheItem> GetOrder() { return _order; } } public class ObjectPool<T> where T : class { private readonly Queue<T> _pool; private readonly int _maxSize; private readonly Func<T> _factory; private readonly Action<T> _resetAction; public ObjectPool(Func<T> factory, int maxSize = 16, Action<T> resetAction = null) { _factory = factory ?? throw new ArgumentNullException("factory"); _maxSize = maxSize; _pool = new Queue<T>(maxSize); _resetAction = resetAction; } public T Get() { if (_pool.Count > 0) { return _pool.Dequeue(); } return _factory(); } public void Return(T obj) { if (_resetAction != null) { _resetAction(obj); } if (_pool.Count < _maxSize) { _pool.Enqueue(obj); } } } public class StatusLabelController { internal class StatusLabelModifier : SModifier { private AutoTranslateConfig config; private StatusLabelController statusLabel; public StatusLabelModifier(AutoTranslateConfig autoTranslateConfig, StatusLabelController statusLabelController) { config = autoTranslateConfig; statusLabel = statusLabelController; } public override void Update() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) if (Input.GetKeyDown(config.ToggleRequestedCharacterCountKeyBinding)) { statusLabel.ToggleVisibility(); } } } internal SLabel label; private Font font; private readonly Color backgroundColor = new Color(0f, 0f, 0f, 0.5f); private readonly Color defaultColor = Color.white; private readonly Color highlightColor = Color.red; private StatusLabelModifier modifier; private bool highlight = false; private AutoTranslateConfig config; private readonly Vector2 defaultAnchor = new Vector2(0.5f, 0f); private readonly Vector2 defaultPivot = new Vector2(0.5f, 0f); private Vector2 anchor; private Vector2 pivot; public static StatusLabelController instance; internal void InitializeStatusLabel() { //IL_004b: 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_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) instance = this; config = AutoTranslateModule.instance.config; try { anchor = ParseVector2(config.CountLabelAnchor); pivot = ParseVector2(config.CountLabelPivot); } catch { anchor = defaultAnchor; pivot = defaultPivot; } label = new SLabel(); ((SElement)label).Background = backgroundColor; ((SElement)label).Foreground = defaultColor; modifier = new StatusLabelModifier(config, this); ((SElement)label).With.Add((SModifier)(object)modifier); ((SElement)label).OnUpdateStyle = delegate(SElement element) { element.Font = LoadFont(); Reposition(); }; ((SElement)label).Visible = config.ShowRequestedCharacterCount; SGUIRoot.Main.Children.Add((SElement)(object)label); } private Font LoadFont() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown if ((Object)(object)font == (Object)null) { dfFont val = (dfFont)GameUIRoot.Instance.Manager.DefaultFont; font = FontConverter.GetFontFromdfFont(val, 2); } return font; } internal void SetText(string text) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) label.Text = text; ((SElement)label).Size = ((SElement)label).Backend.MeasureText(text, (Vector2?)null, (object)font); Reposition(); } private void Reposition() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) if (((SElement)label).Root != null) { ((SElement)label).Position.x = ((SElement)label).Root.Size.x * anchor.x - ((SElement)label).Size.x * pivot.x; ((SElement)label).Position.y = ((SElement)label).Root.Size.y * anchor.y - ((SElement)label).Size.y * pivot.y; } } internal void SetHighlight() { if (!highlight) { highlight = true; ForceSetVisibility(value: true); ((MonoBehaviour)TranslationManager.instance).StartCoroutine(AlternateColor()); } } private IEnumerator AlternateColor() { while (true) { ((SElement)label).Foreground = highlightColor; yield return (object)new WaitForSecondsRealtime(0.5f); ((SElement)label).Foreground = defaultColor; yield return (object)new WaitForSecondsRealtime(0.5f); } } internal void ForceSetVisibility(bool value) { ((SElement)label).Visible = value; Debug.Log((object)("请求字符计数强制设置为" + (value ? "ON" : "OFF") + "。RequestedCharacterCount forcefully set to " + (value ? "ON" : "OFF") + ".")); } internal void ToggleVisibility() { ((SElement)label).Visible = !((SElement)label).Visible; Debug.Log((object)("请求字符计数切换为" + (((SElement)label).Visible ? "ON" : "OFF") + "。RequestedCharacterCount toggled set to " + (((SElement)label).Visible ? "ON" : "OFF") + ".")); } public static Vector2 ParseVector2(string input) { //IL_02c2: Unknown result type (might be due to invalid IL or missing references) //IL_02c7: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Unknown result type (might be due to invalid IL or missing references) if (input == null) { throw new ArgumentException("输入不能为空。Input cannot be empty."); } int length = input.Length; int i; for (i = 0; i < length && char.IsWhiteSpace(input[i]); i++) { } if (i >= length) { throw new FormatException("输入不能为空。Input cannot be empty."); } int num = i; if (input[i] == '-' || input[i] == '+') { i++; } bool flag = false; while (i < length) { char c = input[i]; if (char.IsDigit(c)) { i++; continue; } if (c == '.' && !flag) { flag = true; i++; continue; } break; } if (i == num || (i == num + 1 && (input[num] == '-' || input[num] == '+'))) { throw new FormatException("第一个数字不能为空。First number cannot be empty."); } if (!float.TryParse(input.Substring(num, i - num), out