Decompiled source of PEAK Breton Translation v1.0.0
BepInEx_Fix_Version/BepInEx_Fix_Version/BepInEx/plugins/com.voc.PeakTxtUpdater.dll
Decompiled 12 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Net.Http; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using System.Threading.Tasks; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Microsoft.CodeAnalysis; using Newtonsoft.Json; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("com.voc.PeakTxtUpdater")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+c9a16d2e7649da07991b4d6b81adac55a9956bf8")] [assembly: AssemblyProduct("com.voc.PeakTxtUpdater")] [assembly: AssemblyTitle("com.voc.PeakTxtUpdater")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace BepInEx { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class BepInAutoPluginAttribute : Attribute { public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace BepInEx.Preloader.Core.Patching { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class PatcherAutoPluginAttribute : Attribute { public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace PeakTxtUpdater { [BepInPlugin("com.voc.PeakTxtUpdater", "com.voc.PeakTxtUpdater", "1.0.0")] public class Plugin : BaseUnityPlugin { public class Manifest { public string generated_at { get; set; } public string @ref { get; set; } public string commit { get; set; } public string base_raw_url { get; set; } public List<ManifestFile> files { get; set; } } public class ManifestFile { public string name { get; set; } public string path { get; set; } public string sha256 { get; set; } } private const string DefaultManifestUrl = "https://raw.githubusercontent.com/Vocaloid2048/PEAK-zh-tw-Translation/main/BepInEx/config/zh-tw-voc/Text/manifest.json"; private const string TestMainifestUrl = "https://raw.githubusercontent.com/Vocaloid2048/PEAK-zh-tw-Translation/test-text-updater/BepInEx/config/zh-tw-voc/Text/manifest.json"; private static ConfigEntry<bool> configIsEnablePlugin; private static string[] updateFilesNameList = new string[12] { "Achievement.txt", "Book.txt", "Challenge.txt", "Item.txt", "LoadingAndRepeat.txt", "NeedTPMText.txt", "Settings.txt", "UI.txt", "Mod_Glizzy.txt", "Mod_MoreAscents.txt", "Mod_PEAK_Invitation_Mod.txt", "Mod_PEAK_Save_Manager.txt" }; internal static ManualLogSource Log; public const string Id = "com.voc.PeakTxtUpdater"; public static string Name => "com.voc.PeakTxtUpdater"; public static string Version => "1.0.0"; private void Awake() { Log = ((BaseUnityPlugin)this).Logger; Log.LogInfo((object)"PeakTxtUpdater init - reading config."); configIsEnablePlugin = ((BaseUnityPlugin)this).Config.Bind<bool>("PeakTxtUpdater", "Is Enable PeakTxtUpdater", true, "若啟用,則允許插件在啟動遊戲時自動更新繁體中文翻譯。"); if (!configIsEnablePlugin.Value) { Log.LogInfo((object)"PeakTxtUpdater is DISABLED in config."); return; } string text = Path.Combine(Paths.ConfigPath, "zh-tw-voc", "Text"); Directory.CreateDirectory(text); string path = Path.Combine(text, "Version.txt"); if (File.Exists(path)) { File.WriteAllText(path, "sr:\"^v.(\\d+).(\\d+).(.+)$\"=v.$1.$2.$3 (夜芷冰繁中翻譯)\nsr:\"^beta.(\\d+).(\\d+).(.+)$\"=beta.$1.$2.$3 (夜芷冰繁中翻譯)\nsr:\"^v(\\d+).(\\d+).(.+)$\"=v$1.$2.$3 (夜芷冰繁中翻譯)\nsr:\"^beta(\\d+).(\\d+).(.+)$\"=beta$1.$2.$3 (夜芷冰繁中翻譯)\n", Encoding.UTF8); } Task task = RunUpdaterAsync("https://raw.githubusercontent.com/Vocaloid2048/PEAK-zh-tw-Translation/main/BepInEx/config/zh-tw-voc/Text/manifest.json"); task.ContinueWith(delegate(Task t) { if (t.IsFaulted) { Log.LogError((object)$"RunUpdaterAsync failed: {t.Exception}"); } }, TaskScheduler.Default); } private async Task RunUpdaterAsync(string manifestUrl) { Log.LogInfo((object)"RunUpdaterAsync Task Started"); if (Log == null) { Log = ((BaseUnityPlugin)this).Logger; } try { Log.LogInfo((object)("Fetching manifest from " + manifestUrl)); using HttpClient http = new HttpClient(); string text = await http.GetStringAsync(manifestUrl); if (string.IsNullOrEmpty(text)) { Log.LogWarning((object)"Manifest JSON is empty."); return; } Manifest manifest; try { JsonSerializerSettings val = new JsonSerializerSettings { MissingMemberHandling = (MissingMemberHandling)0, NullValueHandling = (NullValueHandling)1, DateParseHandling = (DateParseHandling)0 }; manifest = JsonConvert.DeserializeObject<Manifest>(text, val); Log.LogInfo((object)"Manifest deserialized"); } catch (JsonException val2) { JsonException arg = val2; Log.LogError((object)$"Failed to deserialize manifest: {arg}"); if (!string.IsNullOrEmpty(text)) { string text2 = ((text.Length > 1000) ? (text.Substring(0, 1000) + "...") : text); Log.LogError((object)("Manifest snippet: " + text2)); } return; } if (manifest == null) { Log.LogWarning((object)"Manifest was empty or could not be deserialized."); return; } string localTextDir = Path.Combine(Paths.ConfigPath, "zh-tw-voc", "Text"); Directory.CreateDirectory(localTextDir); foreach (ManifestFile file in manifest.files ?? new List<ManifestFile>()) { if (Array.IndexOf(updateFilesNameList, file.name) == -1) { continue; } try { string localPath = Path.Combine(localTextDir, file.name); bool flag = true; if (!File.Exists(localPath)) { goto IL_0301; } if (string.Equals(file.name, "Version.txt", StringComparison.OrdinalIgnoreCase)) { continue; } string text3 = ComputeFileSha256(localPath); if (string.Equals(text3, file.sha256, StringComparison.OrdinalIgnoreCase)) { flag = false; } else { Log.LogInfo((object)("Outdated: " + file.name + " (local " + text3 + " vs remote " + file.sha256 + ")")); } goto IL_0301; IL_0301: if (flag) { string text4 = manifest.base_raw_url?.TrimEnd('/') + "/" + file.path; Log.LogInfo((object)("Downloading " + file.name + " from " + text4)); byte[] array = await http.GetByteArrayAsync(text4); string text5 = ComputeSha256(array); if (!string.Equals(text5, file.sha256, StringComparison.OrdinalIgnoreCase)) { Log.LogWarning((object)("SHA mismatch for " + file.name + ": expected " + file.sha256 + " got " + text5 + ". Skipping write.")); } else { string text6 = localPath + ".tmp"; File.WriteAllBytes(text6, array); File.Copy(text6, localPath, overwrite: true); File.Delete(text6); Log.LogInfo((object)("Wrote " + localPath)); } } } catch (Exception arg2) { Log.LogError((object)$"Failed to update {file.name}: {arg2}"); } } try { string text7 = Path.Combine(localTextDir, "Version.txt"); if (File.Exists(text7)) { File.Delete(text7); } string contents = "##Ref: " + manifest.@ref + "##\n##Commit: " + manifest.commit + "##\n##Generated at: " + manifest.generated_at + "##\n\nsr:\"^v.(\\d+).(\\d+).(.+)$\"=v.$1.$2.$3 (夜芷冰繁中翻譯 - #" + manifest.commit.Substring(0, 6) + ")\nsr:\"^beta.(\\d+).(\\d+).(.+)$\"=beta.$1.$2.$3 (夜芷冰繁中翻譯 - #" + manifest.commit.Substring(0, 6) + ")\nsr:\"^v(\\d+).(\\d+).(.+)$\"=v$1.$2.$3 (夜芷冰繁中翻譯 - #" + manifest.commit.Substring(0, 6) + ")\nsr:\"^beta(\\d+).(\\d+).(.+)$\"=beta$1.$2.$3 (夜芷冰繁中翻譯 - #" + manifest.commit.Substring(0, 6) + ")\n"; File.WriteAllText(text7, contents, Encoding.UTF8); Log.LogInfo((object)("Wrote version info to " + text7)); } catch (Exception arg3) { Log.LogError((object)$"Failed to write Version.txt: {arg3}"); } } catch (Exception arg4) { Log.LogError((object)$"TxtUpdater failed: {arg4}"); } } private static string ComputeFileSha256(string path) { using FileStream inputStream = File.OpenRead(path); using SHA256 sHA = SHA256.Create(); byte[] array = sHA.ComputeHash(inputStream); return BitConverter.ToString(array).Replace("-", "").ToLowerInvariant(); } private static string ComputeSha256(byte[] data) { using SHA256 sHA = SHA256.Create(); byte[] array = sHA.ComputeHash(data); return BitConverter.ToString(array).Replace("-", "").ToLowerInvariant(); } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }
BepInEx_Fix_Version/BepInEx_Fix_Version/BepInEx/plugins/UniversalFontPatcher.dll
Decompiled 12 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("XoFKon")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyDescription("Replace in-game font with other things")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+d5fa67705b60c049a3e31d66d30cc939edaa91fb")] [assembly: AssemblyProduct("UniversalFontPatcher")] [assembly: AssemblyTitle("UniversalFontPatcher")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace UniversalFontPatcher { public static class MyPluginInfo { public const string PLUGIN_GUID = "UniversalFontPatcher"; public const string PLUGIN_NAME = "UniversalFontPatcher"; public const string PLUGIN_VERSION = "1.0.0"; } } namespace FontPatcher { [HarmonyPatch] public static class FontLoader { internal class FontBundle { public string BundleName; public TMP_FontAsset Normal; public TMP_FontAsset Transmit; } internal static List<FontBundle> fontBundles = new List<FontBundle>(); internal static Regex normalRegex; internal static Regex transmitRegex; public static void RepatchAllFontsInScene() { TMP_Text[] array = Object.FindObjectsOfType<TMP_Text>(true); foreach (TMP_Text val in array) { if ((Object)(object)val != (Object)null && (Object)(object)val.font != (Object)null) { Plugin.LogInfo("[Repatch] " + ((Object)val).name + " using font " + ((Object)val.font).name); PatchFontAwake(val.font); } } } public static void Load() { try { string path = Path.Combine(Paths.ConfigPath); string text = Path.Combine(path, Plugin.configFontAssetPath.Value); Plugin.LogInfo("Font path: " + text); if (!Directory.Exists(text)) { Plugin.LogError("Font assets directory does not exist: " + text); return; } int num = 0; int num2 = 0; FileInfo[] files = new DirectoryInfo(text).GetFiles("*"); foreach (FileInfo fileInfo in files) { try { AssetBundle val = AssetBundle.LoadFromFile(fileInfo.FullName); Plugin.LogInfo("[" + fileInfo.Name + "] loaded"); FontBundle fontBundle = new FontBundle { Normal = val.LoadAsset<TMP_FontAsset>("Normal"), Transmit = val.LoadAsset<TMP_FontAsset>("Transmit") }; if ((Object)(object)fontBundle.Normal != (Object)null || (Object)(object)fontBundle.Transmit != (Object)null) { fontBundle.BundleName = fileInfo.Name; if ((Object)(object)fontBundle.Normal != (Object)null) { ((Object)fontBundle.Normal).name = fileInfo.Name + "(Normal)"; Plugin.LogInfo("Normal font found (" + ((Object)fontBundle.Normal).name + ")"); } if ((Object)(object)fontBundle.Transmit != (Object)null) { ((Object)fontBundle.Transmit).name = fileInfo.Name + "(Transmit)"; Plugin.LogInfo("Transmit font found (" + ((Object)fontBundle.Transmit).name + ")"); } fontBundles.Add(fontBundle); num++; continue; } throw new Exception("No recognizable TMP_FontAsset found in bundle"); } catch (Exception ex) { Plugin.LogError("[" + fileInfo.Name + "] load failed: " + ex.Message); num2++; } } normalRegex = new Regex(Plugin.configNormalRegexPattern.Value); transmitRegex = new Regex(Plugin.configTransmitRegexPattern.Value); Plugin.LogInfo($"{num} fonts loaded, {num2} failed"); RepatchAllFontsInScene(); } catch (Exception ex2) { Plugin.LogError(ex2.ToString()); } } public static void PatchFontAwake(TMP_FontAsset fontAsset) { //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Expected O, but got Unknown if ((Object)(object)fontAsset == (Object)null) { Plugin.LogError("[PatchFontAwake] fontAsset is NULL — skipping."); return; } if ((Object)(object)fontAsset.atlasTexture == (Object)null) { Plugin.LogError("[Fatal] Font '" + ((Object)fontAsset).name + "' has null atlasTexture — aborting patch to prevent crash."); return; } Plugin.LogInfo($"[FontCheck] {((Object)fontAsset).name}: material={(Object)(object)((TMP_Asset)fontAsset).material != (Object)null}, atlas={(Object)(object)fontAsset.atlasTexture != (Object)null}"); if ((Object)(object)((TMP_Asset)fontAsset).material == (Object)null) { Shader val = Shader.Find("TextMeshPro/Distance Field"); if (!((Object)(object)val != (Object)null)) { Plugin.LogError("[MaterialFix] TMP Shader not found — cannot assign material"); return; } ((TMP_Asset)fontAsset).material = new Material(val) { name = ((Object)fontAsset).name + "_Material" }; ((TMP_Asset)fontAsset).material.SetTexture("_MainTex", (Texture)(object)fontAsset.atlasTexture); ((TMP_Asset)fontAsset).material.mainTexture = (Texture)(object)fontAsset.atlasTexture; Plugin.LogInfo("[MaterialFix] Created material for " + ((Object)fontAsset).name); } Material material = ((TMP_Asset)fontAsset).material; if ((Object)(object)material != (Object)null) { if (!material.HasProperty("_MainTex")) { Plugin.LogWarning("[MaterialCheck] " + ((Object)fontAsset).name + " 材質無 _MainTex"); } if ((Object)(object)material.mainTexture == (Object)null && (Object)(object)fontAsset.atlasTexture != (Object)null) { material.SetTexture("_MainTex", (Texture)(object)fontAsset.atlasTexture); material.mainTexture = (Texture)(object)fontAsset.atlasTexture; Plugin.LogInfo("[MainTexFix] Assigned _MainTex from atlas for " + ((Object)fontAsset).name); } if (material.shaderKeywords == null) { material.shaderKeywords = Array.Empty<string>(); } if (material.renderQueue < 1000) { material.renderQueue = 3000; Plugin.LogInfo("[RenderQueueFix] Set to 3000 for " + ((Object)fontAsset).name); } material.SetFloat("_UnderlayDilate", 1f); material.SetFloat("_UnderlayOffsetX", 0.1f); } string name = ((Object)fontAsset).name; if (normalRegex.IsMatch(name)) { if (!Plugin.configNormalIngameFont.Value) { DisableFont(fontAsset); } AddFallbackFonts(fontAsset, isNormal: true); } else if (transmitRegex.IsMatch(name)) { if (!Plugin.configTransmitIngameFont.Value) { DisableFont(fontAsset); } AddFallbackFonts(fontAsset, isNormal: false); } else if (fontAsset.characterLookupTable == null || fontAsset.characterLookupTable.Count == 0) { Plugin.LogWarning("[Disable] Font " + ((Object)fontAsset).name + " has empty lookup table — disabling."); DisableFont(fontAsset); } else { Plugin.LogWarning("[" + name + "] not matched any regex pattern"); } } private static void FixFontAssetMaterial(TMP_FontAsset fontAsset) { //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_006c: Expected O, but got Unknown if ((Object)(object)fontAsset == (Object)null) { return; } Shader val = Shader.Find("TextMeshPro/Distance Field"); if ((Object)(object)val == (Object)null) { Plugin.LogError("[FixMaterial] TMP shader not found!"); return; } if ((Object)(object)((TMP_Asset)fontAsset).material == (Object)null) { ((TMP_Asset)fontAsset).material = new Material(val) { name = ((Object)fontAsset).name + "_Material" }; Plugin.LogInfo("[FixMaterial] Created new material for " + ((Object)fontAsset).name); } else { ((TMP_Asset)fontAsset).material.shader = val; Plugin.LogInfo("[FixMaterial] Reassigned shader for " + ((Object)fontAsset).name); } if ((Object)(object)fontAsset.atlasTexture != (Object)null) { ((TMP_Asset)fontAsset).material.SetTexture("_MainTex", (Texture)(object)fontAsset.atlasTexture); ((TMP_Asset)fontAsset).material.mainTexture = (Texture)(object)fontAsset.atlasTexture; } } private static void AddFallbackFonts(TMP_FontAsset target, bool isNormal) { int num = 0; foreach (FontBundle fontBundle in fontBundles) { TMP_FontAsset val = (isNormal ? fontBundle.Normal : fontBundle.Transmit); if (!((Object)(object)val == (Object)null)) { FixFontAssetMaterial(val); if ((Object)(object)((TMP_Asset)val).material == (Object)null || (Object)(object)val.atlasTexture == (Object)null || (Object)(object)((TMP_Asset)val).material.mainTexture == (Object)null || !((TMP_Asset)val).material.HasProperty("_MainTex")) { Plugin.LogWarning("[SkipFallback] " + ((Object)val).name + " is missing required material/texture/_MainTex"); } else if (!target.fallbackFontAssetTable.Contains(val)) { target.fallbackFontAssetTable.Add(val); num++; } } } if (num > 0) { Plugin.LogInfo(string.Format("[{0}] font patched ({1}) +{2}", ((Object)target).name, isNormal ? "Normal" : "Transmit", num)); } } [HarmonyPostfix] [HarmonyPatch(typeof(TextMeshPro), "Awake")] public static void PatchTMPAwake(TextMeshPro __instance) { if ((Object)(object)((TMP_Text)__instance).font != (Object)null) { PatchFontAwake(((TMP_Text)__instance).font); } } [HarmonyPostfix] [HarmonyPatch(typeof(TextMeshProUGUI), "Awake")] public static void PatchTMPUGUIAwake(TextMeshProUGUI __instance) { if ((Object)(object)((TMP_Text)__instance).font != (Object)null) { TMP_FontAsset font = ((TMP_Text)__instance).font; object[] obj = new object[4] { ((Object)font).name, (Object)(object)((TMP_Asset)font).material != (Object)null, (Object)(object)font.atlasTexture != (Object)null, null }; Material material = ((TMP_Asset)font).material; obj[3] = (Object)(object)((material != null) ? material.mainTexture : null) != (Object)null; Plugin.LogInfo(string.Format("[TMP Awake] {0} / material={1} / atlas={2} / mainTex={3}", obj)); PatchFontAwake(font); } else { Plugin.LogError("[TMP Awake] font is NULL!"); } } private static void DisableFont(TMP_FontAsset font) { font.characterLookupTable?.Clear(); font.atlasPopulationMode = (AtlasPopulationMode)0; } } internal static class PluginInfo { public const string GUID = "universal.fontpatcher"; public const string Name = "Universal TMP Replacer"; public const string Version = "1.0.0"; } [BepInPlugin("universal.fontpatcher", "Universal TMP Replacer", "1.0.0")] public class Plugin : BaseUnityPlugin { public static ConfigEntry<bool> configNormalIngameFont; public static ConfigEntry<bool> configTransmitIngameFont; public static ConfigEntry<string> configNormalRegexPattern; public static ConfigEntry<string> configTransmitRegexPattern; public static ConfigEntry<string> configFontAssetPath; public static ConfigEntry<bool> configDebugLog; public static Plugin Instance; private void Awake() { if ((Object)(object)Instance == (Object)null) { Instance = this; } configNormalIngameFont = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "UsingNormalIngameFont", true, "是否啟用遊戲內建的 Normal 字體"); configTransmitIngameFont = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "UsingTransmitIngameFont", true, "是否啟用遊戲內建的 Transmit 字體"); configNormalRegexPattern = ((BaseUnityPlugin)this).Config.Bind<string>("Regex", "NormalFontNameRegex", ".*", "匹配 Normal 字體名稱的正則表達式"); configTransmitRegexPattern = ((BaseUnityPlugin)this).Config.Bind<string>("Regex", "TransmitFontNameRegex", ".*", "匹配 Transmit 字體名稱的正則表達式"); configFontAssetPath = ((BaseUnityPlugin)this).Config.Bind<string>("Path", "FontAssetsPath", "FontPatcher", "字體資源所在的資料夾,位於 <遊戲資料夾>/FontPatcher/<此設定>"); configDebugLog = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "Log", false, "是否啟用除錯日誌"); FontLoader.Load(); Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null); } public static void LogInfo(string msg) { if (configDebugLog.Value) { ((BaseUnityPlugin)Instance).Logger.LogInfo((object)msg); } } public static void LogWarning(string msg) { if (configDebugLog.Value) { ((BaseUnityPlugin)Instance).Logger.LogWarning((object)msg); } } public static void LogError(string msg) { ((BaseUnityPlugin)Instance).Logger.LogError((object)msg); } } internal static class ResourcePath { public const string NormalFont = "Normal"; public const string TransmitFont = "Transmit"; } }