From c7ea71ca70e927d06717fcebae29cd8d252431c9 Mon Sep 17 00:00:00 2001 From: Clansty Date: Fri, 7 Nov 2025 15:14:31 +0800 Subject: [PATCH] =?UTF-8?q?[O]=20=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E8=AF=BB=E5=86=99=E7=9B=B8=E5=85=B3=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit close #87 --- AquaMai.Core/ConfigLoader.cs | 10 +++-- AquaMai.Core/Helpers/InvalidConfigAlert.cs | 52 ++++++++++++++++++++++ AquaMai.Core/Resources/Locale.Designer.cs | 31 +++++++++---- AquaMai.Core/Resources/Locale.resx | 7 +++ AquaMai.Core/Resources/Locale.zh.resx | 6 +++ AquaMai.Core/Startup.cs | 43 ++++++++++++++---- 6 files changed, 128 insertions(+), 21 deletions(-) create mode 100644 AquaMai.Core/Helpers/InvalidConfigAlert.cs diff --git a/AquaMai.Core/ConfigLoader.cs b/AquaMai.Core/ConfigLoader.cs index e87088fc..f635e5c4 100644 --- a/AquaMai.Core/ConfigLoader.cs +++ b/AquaMai.Core/ConfigLoader.cs @@ -18,6 +18,8 @@ public static class ConfigLoader public static Config.Config Config => config; + private static string configText; + public static bool LoadConfig(Assembly modsAssembly) { Utility.LogFunction = MelonLogger.Msg; @@ -43,7 +45,7 @@ public static class ConfigLoader return false; } - var configText = File.ReadAllText(ConfigFile); + configText = File.ReadAllText(ConfigFile); var configView = new ConfigView(configText); var configVersion = ConfigMigrationManager.Instance.GetVersion(configView); if (configVersion != ConfigMigrationManager.Instance.LatestVersion) @@ -60,6 +62,8 @@ public static class ConfigLoader public static void SaveConfig(string lang) { + var newText = SerailizeCurrentConfig(lang); + if (newText == configText) return; File.WriteAllText(ConfigFile, SerailizeCurrentConfig(lang)); } @@ -74,10 +78,10 @@ public static class ConfigLoader private static IDictionary GenerateExamples() { var examples = new Dictionary(); - foreach (var lang in (string[]) ["en", "zh"]) + foreach (var lang in (string[])["en", "zh"]) { examples[lang] = SerailizeCurrentConfig(lang); } return examples; } -} +} \ No newline at end of file diff --git a/AquaMai.Core/Helpers/InvalidConfigAlert.cs b/AquaMai.Core/Helpers/InvalidConfigAlert.cs new file mode 100644 index 00000000..702dd1b3 --- /dev/null +++ b/AquaMai.Core/Helpers/InvalidConfigAlert.cs @@ -0,0 +1,52 @@ +using HarmonyLib; +using Main; +using UnityEngine; + +namespace AquaMai.Core.Helpers; + +public class InvalidConfigAlert : MonoBehaviour +{ + [HarmonyPostfix] + [HarmonyPatch(typeof(GameMainObject), "Awake")] + public static void OnGameMainObjectAwake(GameMainObject __instance) + { + Destroy(__instance); + var go = new GameObject("配置错误提示组件"); + go.AddComponent(); + } + + public const string ConfigNotFoundMessage = """ + 找不到 AquaMai 配置文件! + 已生成示例配置文件并保存到 AquaMai.zh.toml,请将其重命名为 AquaMai.toml 并做需要的更改 + 你可以使用 MaiChartManager 来图形化修改配置文件 + 现在请退出游戏 + + AquaMai Configuration Not Found! + Example configuration files have been generated and saved to AquaMai.en.toml + Please rename them to AquaMai.toml and make the necessary changes + Now please exit the game + """; + + public const string ConfigCorruptedMessage = """ + AquaMai 配置文件损坏!读取配置文件时遇到问题 + 请退出游戏并检查配置文件是否有格式错误 + + AquaMai Configuration Corrupted! An error occurred while reading the configuration file + Please exit the game and check if the configuration file has any format errors + Now please exit the game + """; + + public static string message = ""; + + private void OnGUI() + { + GUIStyle style = new GUIStyle(GUI.skin.label) + { + fontSize = 25, + alignment = TextAnchor.UpperLeft, + wordWrap = true, + }; + + GUI.Label(new Rect(50, 50, Screen.width / 2f, Screen.height / 1920f * 450f), message, style); + } +} \ No newline at end of file diff --git a/AquaMai.Core/Resources/Locale.Designer.cs b/AquaMai.Core/Resources/Locale.Designer.cs index c0cb5081..97795c2f 100644 --- a/AquaMai.Core/Resources/Locale.Designer.cs +++ b/AquaMai.Core/Resources/Locale.Designer.cs @@ -280,15 +280,6 @@ namespace AquaMai.Core.Resources { } } - /// - /// Looks up a localized string similar to SSS+ => DXRating += {0}. - /// - public static string RatingUpWhenSSSp { - get { - return ResourceManager.GetString("RatingUpWhenSSSp", resourceCulture); - } - } - /// /// Looks up a localized string similar to AP => DXRating += {0}. /// @@ -298,6 +289,15 @@ namespace AquaMai.Core.Resources { } } + /// + /// Looks up a localized string similar to SSS+ => DXRating += {0}. + /// + public static string RatingUpWhenSSSp { + get { + return ResourceManager.GetString("RatingUpWhenSSSp", resourceCulture); + } + } + /// /// Looks up a localized string similar to Repeat end time cannot be less than repeat start time. /// @@ -473,6 +473,19 @@ namespace AquaMai.Core.Resources { } } + /// + /// Looks up a localized string similar to ==================================================================!!! + ///Unable to save configuration file. + ///Maybe the configuration file directory is read-only or other problems + ///The local configuration file may not reflect the latest added options + ///=====================================================================. + /// + public static string UnableSaveConfig { + get { + return ResourceManager.GetString("UnableSaveConfig", resourceCulture); + } + } + /// /// Looks up a localized string similar to Unable to establish TLS connection to title server, will use plain HTTP instead.. /// diff --git a/AquaMai.Core/Resources/Locale.resx b/AquaMai.Core/Resources/Locale.resx index 472ef3b3..bbc60ebe 100644 --- a/AquaMai.Core/Resources/Locale.resx +++ b/AquaMai.Core/Resources/Locale.resx @@ -172,4 +172,11 @@ Press {2} to switch block or exit adjustment mode Autoplay was used, score will not be saved. + + ==================================================================!!! +Unable to save configuration file. +Maybe the configuration file directory is read-only or other problems +The local configuration file may not reflect the latest added options +===================================================================== + diff --git a/AquaMai.Core/Resources/Locale.zh.resx b/AquaMai.Core/Resources/Locale.zh.resx index 20e674b6..93996943 100644 --- a/AquaMai.Core/Resources/Locale.zh.resx +++ b/AquaMai.Core/Resources/Locale.zh.resx @@ -165,4 +165,10 @@ Autoplay曾开启过,本曲成绩不会被上传。 + + =============================================!!! +无法保存配置文件。或许是配置文件目录只读或者其他问题 +本地的配置文件可能无法反应最新添加的选项 +================================================ + diff --git a/AquaMai.Core/Startup.cs b/AquaMai.Core/Startup.cs index 28ba0b42..89667d4a 100644 --- a/AquaMai.Core/Startup.cs +++ b/AquaMai.Core/Startup.cs @@ -136,21 +136,46 @@ public class Startup public static void Initialize(Assembly modsAssembly, HarmonyLib.Harmony harmony) { MelonLogger.Msg("Loading mod settings..."); - - var configLoaded = ConfigLoader.LoadConfig(modsAssembly); - var lang = ResolveLocale(); - if (configLoaded) - { - ConfigLoader.SaveConfig(lang); // Re-save the config as soon as possible - } - _harmony = harmony; + bool configLoaded; + try + { + configLoaded = ConfigLoader.LoadConfig(modsAssembly); + } + catch (Exception ex) + { + MelonLogger.Error($"Failed to load config file: {ex}"); + InvalidConfigAlert.message = InvalidConfigAlert.ConfigCorruptedMessage; + ApplyPatch(typeof(InvalidConfigAlert)); + return; + } + + var lang = ResolveLocale(); // Init locale with patching C# runtime // https://stackoverflow.com/questions/1952638/single-assembly-multi-language-windows-forms-deployment-ilmerge-and-satellite-a ApplyPatch(typeof(I18nSingleAssemblyHook)); Locale.Culture = CultureInfo.GetCultureInfo(lang); // Must be called after I18nSingleAssemblyHook patched + if (configLoaded) + { + try + { + ConfigLoader.SaveConfig(lang); // Re-save the config as soon as possible + } + catch (Exception ex) + { + MelonLogger.Warning(ex); + MelonLogger.Warning("\n" + Locale.UnableSaveConfig); + } + } + else + { + InvalidConfigAlert.message = InvalidConfigAlert.ConfigNotFoundMessage; + ApplyPatch(typeof(InvalidConfigAlert)); + return; + } + // The patch list is ordered List wantedPatches = []; @@ -213,4 +238,4 @@ public class Startup GuiSizes.SetupStyles(); } } -} +} \ No newline at end of file