diff --git a/MelonLoader/AssetStore/DllStore.cs b/MelonLoader/AssetStore/DllStore.cs new file mode 100644 index 0000000..54eea26 --- /dev/null +++ b/MelonLoader/AssetStore/DllStore.cs @@ -0,0 +1,111 @@ +using MelonLoader; +using MelonLoader.Utils; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PvZ_Fusion_Translator.AssetStore +{ + public static class DllStore + { + public static Dictionary dllData = new Dictionary() + { + { "Blooms_QOL.dll", null }, + { "HideMetalObjects.dll", null }, + { "PvZ_Fusion_Translator.dll", null } + }; + public static bool updateOnClose = false; + + public static void Init(string gameVersion) => TryGetNewDll(gameVersion); + + public static void TryGetNewDll(string gameVersion) + { + bool ableToUpdate = true; + string unableReason = ""; + string getGameVersionRequest = Utils.GetDataFromWeb("https://raw.githubusercontent.com/SillyStar-Github/PvZF-Translation-DLLs/refs/heads/main/CURRENT_GAME_VER").Result; + if(getGameVersionRequest != null) + { + Log.LogDebug($"Requst game version: {getGameVersionRequest} -> {Utils.CalculateGameVersion(getGameVersionRequest)}"); + Log.LogDebug($"This game version: {gameVersion} -> {Utils.CalculateGameVersion(gameVersion)}"); + if (Utils.CalculateGameVersion(getGameVersionRequest) != Utils.CalculateGameVersion(gameVersion)) + { + ableToUpdate = false; + unableReason = "Incorrect game version..."; + } + } + else + { + ableToUpdate = false; + unableReason = "Couldn't get latest game version info..."; + } + + if (ableToUpdate) + { + foreach(var key in dllData.Keys) + { + byte[] newDllRequest = Utils.GetByteDataFromWeb($"https://raw.githubusercontent.com/SillyStar-Github/PvZF-Translation-DLLs/refs/heads/main/{key}").Result; + if(newDllRequest != null) + { + dllData[key] = newDllRequest; + SaveNewDll(key); + } + else + { + Log.LogError($"Couldn't get latest {key} data!"); + } + } + } + else + { + Log.LogError($"Unable to update! {unableReason}"); + } + } + + public static void SaveNewDll(string name) + { + byte[] newDllData = dllData[name]; + if(newDllData != null) + { + string basePath = MelonEnvironment.ModsDirectory; + string toSavePath = Path.Combine(basePath, name + ".update"); + File.WriteAllBytes(toSavePath, newDllData); + } + } + + public static void UpdateNewDll() + { + foreach(var pair in dllData) + { + if(pair.Value != null) + { + updateOnClose = true; + } + } + + if(updateOnClose) + { + int processId = (Process.GetCurrentProcess().Id); + + var assembly = Core.Instance.MelonAssembly.Assembly; + string programName = "PvZ_Fusion_Translator.Resources.ModUpdateUtil.exe"; + + using var exeResourceStream = assembly.GetManifestResourceStream(programName); + string tempPath = Path.Combine(Path.GetTempPath(), "ModUpdateUtil.exe"); + using (var fileStream = File.Create(tempPath)) + { + exeResourceStream.CopyTo(fileStream); + } + + Process.Start(new ProcessStartInfo + { + FileName = tempPath, + Arguments = $"{processId.ToString()} {string.Join(",", dllData.Keys)} {MelonEnvironment.ModsDirectory}", + UseShellExecute = true + }); + } + } + } +} diff --git a/MelonLoader/Core.cs b/MelonLoader/Core.cs index 91c491d..984ea2c 100644 --- a/MelonLoader/Core.cs +++ b/MelonLoader/Core.cs @@ -31,6 +31,9 @@ namespace PvZ_Fusion_Translator { base.OnInitializeMelon(); Instance = this; + + DllStore.Init(MelonLoader.InternalUtils.UnityInformationHandler.GameVersion); + Config(); #if MULTI_LANGUAGE FileLoader.LoadLanguage(); @@ -40,6 +43,7 @@ namespace PvZ_Fusion_Translator AudioStore.Init(); FontStore.Init(); Utils.RegisterPlantIndices(); + //Utils.RegisterRecipeLinks(); } @@ -56,6 +60,7 @@ namespace PvZ_Fusion_Translator #if MULTI_LANGUAGE FileLoader.SaveLanguage(); #endif + DllStore.UpdateNewDll(); #if OBFUSCATE && !RELEASE CheckSumStore.ConvertMD5Json(); #endif @@ -80,7 +85,7 @@ namespace PvZ_Fusion_Translator if (Input.GetKeyDown(KeyCode.Delete)) { - Utils.OpenTrello(); + Utils.OpenOnlineAlmanac(); } TowerManager_Patch.UpdateText(); diff --git a/MelonLoader/FileLoader.cs b/MelonLoader/FileLoader.cs index 0660f12..bb3c471 100644 --- a/MelonLoader/FileLoader.cs +++ b/MelonLoader/FileLoader.cs @@ -41,6 +41,10 @@ namespace PvZ_Fusion_Translator internal static void LoadStrings(Utils.LanguageEnum language) { string stringDir = GetAssetDir(AssetType.Strings, Utils.Language); + if (!Directory.Exists(stringDir)) + { + Directory.CreateDirectory(stringDir); + } if(!Utils.useLocal) { @@ -128,6 +132,14 @@ namespace PvZ_Fusion_Translator } // load almanacs + + string almanacDir = GetAssetDir(AssetType.Almanac, Utils.Language); + + if(!Directory.Exists(almanacDir)) + { + Directory.CreateDirectory(almanacDir); + } + string plantAlmanacContent = Utils.GetDataFromWeb($"https://raw.githubusercontent.com/Teyliu/PVZF-Translation/refs/heads/main/PvZ_Fusion_Translator/Localization/{Utils.Language.ToString()}/Almanac/LawnStringsTranslate.json").Result; if(plantAlmanacContent != null) @@ -136,7 +148,6 @@ namespace PvZ_Fusion_Translator } else { - string almanacDir = GetAssetDir(AssetType.Almanac, Utils.Language); string path = Path.Combine(almanacDir, "LawnStringsTranslate.json"); if(File.Exists(path)) { @@ -152,7 +163,6 @@ namespace PvZ_Fusion_Translator } else { - string almanacDir = GetAssetDir(AssetType.Almanac, Utils.Language); string path = Path.Combine(almanacDir, "ZombieStringsTranslate.json"); if(File.Exists(path)) { @@ -219,7 +229,14 @@ namespace PvZ_Fusion_Translator } string almanacDir = GetAssetDir(AssetType.Almanac, Utils.Language); + + if(!Directory.Exists(almanacDir)) + { + Directory.CreateDirectory(almanacDir); + } + string plantAlmanacPath = Path.Combine(almanacDir, "LawnStringsTranslate.json"); + if(File.Exists(plantAlmanacPath)) { AlmanacPlantMenu_Patch.almanacJson = File.ReadAllText(plantAlmanacPath); @@ -422,12 +439,16 @@ namespace PvZ_Fusion_Translator string baseUrl = $"https://raw.githubusercontent.com/Teyliu/PVZF-Translation/refs/heads/main/PvZ_Fusion_Translator/"; string url = baseUrl + path; - byte[] imageData = Utils.GetImageDataFromWeb(url).Result; + byte[] imageData = Utils.GetByteDataFromWeb(url).Result; if(imageData != null) { string fileName = Path.GetFileName(downloadPath); Texture2D texture2D = Utils.LoadImage(imageData); TextureStore.textureDict[fileName] = imageData; + if(!Directory.Exists(Path.GetDirectoryName(downloadPath))) + { + Directory.CreateDirectory(Path.GetDirectoryName(downloadPath)); + } File.WriteAllBytes(downloadPath, imageData); } } @@ -531,12 +552,16 @@ namespace PvZ_Fusion_Translator string baseUrl = $"https://raw.githubusercontent.com/Teyliu/PVZF-Translation/refs/heads/main/PvZ_Fusion_Translator/"; string url = baseUrl + path; - byte[] imageData = Utils.GetImageDataFromWeb(url).Result; + byte[] imageData = Utils.GetByteDataFromWeb(url).Result; if(imageData != null) { string fileName = Path.GetFileName(downloadPath); Texture2D texture2D = Utils.LoadImage(imageData); TextureStore.spriteDict[fileName] = imageData; + if(!Directory.Exists(Path.GetDirectoryName(downloadPath))) + { + Directory.CreateDirectory(Path.GetDirectoryName(downloadPath)); + } File.WriteAllBytes(downloadPath, imageData); } } @@ -641,12 +666,16 @@ namespace PvZ_Fusion_Translator string baseUrl = $"https://raw.githubusercontent.com/Teyliu/PVZF-Translation/refs/heads/main/PvZ_Fusion_Translator/"; string url = baseUrl + path; - byte[] imageData = Utils.GetImageDataFromWeb(url).Result; + byte[] imageData = Utils.GetByteDataFromWeb(url).Result; if (imageData != null) { string fileName = Path.GetFileName(downloadPath); Texture2D texture2D = Utils.LoadImage(imageData); TextureStore.textureDict[fileName] = imageData; + if(!Directory.Exists(Path.GetDirectoryName(downloadPath))) + { + Directory.CreateDirectory(Path.GetDirectoryName(downloadPath)); + } File.WriteAllBytes(downloadPath, imageData); } } @@ -743,12 +772,16 @@ namespace PvZ_Fusion_Translator string baseUrl = $"https://raw.githubusercontent.com/Teyliu/PVZF-Translation/refs/heads/main/PvZ_Fusion_Translator/"; string url = baseUrl + path; - byte[] imageData = Utils.GetImageDataFromWeb(url).Result; + byte[] imageData = Utils.GetByteDataFromWeb(url).Result; if (imageData != null) { string fileName = Path.GetFileName(downloadPath); Texture2D texture2D = Utils.LoadImage(imageData); TextureStore.textureDict[fileName] = imageData; + if(!Directory.Exists(Path.GetDirectoryName(downloadPath))) + { + Directory.CreateDirectory(Path.GetDirectoryName(downloadPath)); + } File.WriteAllBytes(downloadPath, imageData); } } diff --git a/MelonLoader/Patches/BaseTextObjects/InGameText_Patch.cs b/MelonLoader/Patches/BaseTextObjects/InGameText_Patch.cs index 171ec7d..936ac63 100644 --- a/MelonLoader/Patches/BaseTextObjects/InGameText_Patch.cs +++ b/MelonLoader/Patches/BaseTextObjects/InGameText_Patch.cs @@ -107,7 +107,7 @@ namespace PvZ_Fusion_Translator.Patches.BaseTextObjects { txt.text = superEditorPlantMatch; } - else if((Regex.Match(txt.text, @"(]*>.*?)", RegexOptions.Singleline).Success) && !StringStore.translationString.ContainsKey(txt.text)) + else if((Regex.Match(txt.text, @"(]*>.*?)", RegexOptions.Singleline).Success) && (!StringStore.translationString.ContainsKey(txt.text) && !StringStore.fsTipCollectionString.ContainsKey(txt.text) && !StringStore.izTipCollectionString.ContainsKey(txt.text))) { txt.text = StringStore.TranslateColorText(txt.text, true); if (txt.gameObject.name.Contains("main")) diff --git a/MelonLoader/Patches/BaseTextObjects/TextMeshProUGUI_Patch.cs b/MelonLoader/Patches/BaseTextObjects/TextMeshProUGUI_Patch.cs index d9e6730..d5d9d1c 100644 --- a/MelonLoader/Patches/BaseTextObjects/TextMeshProUGUI_Patch.cs +++ b/MelonLoader/Patches/BaseTextObjects/TextMeshProUGUI_Patch.cs @@ -32,7 +32,7 @@ namespace PvZ_Fusion_Translator.Patches.BaseTextObjects { __instance.text = __instance.text.Replace("\n", " "); - if (__instance.name == "LevelName2" || __instance.name == "LevelName3") + if ((__instance.name == "LevelName2" || __instance.name == "LevelName3") && !(__instance.gameObject.transform.parent.name.Contains("Difficulty") || __instance.gameObject.name.Contains("Difficulty"))) { TowerManager_Patch.updatedText.Add(__instance.transform); } diff --git a/MelonLoader/Patches/GameObjects/ButtonObjects/InGameBtn_Patch.cs b/MelonLoader/Patches/GameObjects/ButtonObjects/InGameBtn_Patch.cs index dda9ac9..f223c6d 100644 --- a/MelonLoader/Patches/GameObjects/ButtonObjects/InGameBtn_Patch.cs +++ b/MelonLoader/Patches/GameObjects/ButtonObjects/InGameBtn_Patch.cs @@ -9,9 +9,38 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects.ButtonObjects [HarmonyPatch(typeof(InGameBtn))] public static class InGameBtn_Patch { - [HarmonyPatch(nameof(InGameBtn.Update))] + [HarmonyPatch(nameof(InGameBtn.Start))] [HarmonyPostfix] - private static void Update(InGameBtn __instance) + private static void Start(InGameBtn __instance) + { + Transform sceneText = __instance.transform.FindChild("SceneText"); + if(sceneText != null) + { + TextMeshProUGUI sceneTextTMP = sceneText.transform.GetComponent(); + if(sceneTextTMP != null) + { + sceneTextTMP = AssetStore.StringStore.TranslateText(sceneTextTMP); + } + Transform sceneTextShadow = sceneText.transform.FindChild("SceneText"); + if(sceneTextShadow != null) + { + TextMeshProUGUI sceneTextShadowTMP = sceneTextShadow.transform.GetComponent(); + if (sceneTextShadowTMP != null) + { + sceneTextShadowTMP = AssetStore.StringStore.TranslateText(sceneTextShadowTMP); + } + } + } + + foreach(TextMeshProUGUI text in __instance.transform.GetComponentsInChildren()) + { + text.text = StringStore.TranslateText(text.text); + } + } + + [HarmonyPatch(nameof(InGameBtn.ChangeStrings))] + [HarmonyPostfix] + private static void ChangeStrings(InGameBtn __instance) { Transform sceneText = __instance.transform.FindChild("SceneText"); if(sceneText != null) diff --git a/MelonLoader/Patches/GameObjects/MinorObjects/Money_Patch.cs b/MelonLoader/Patches/GameObjects/MinorObjects/Money_Patch.cs index 12ede0d..3caa1d1 100644 --- a/MelonLoader/Patches/GameObjects/MinorObjects/Money_Patch.cs +++ b/MelonLoader/Patches/GameObjects/MinorObjects/Money_Patch.cs @@ -11,6 +11,7 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects.MinorObjects [HarmonyPatch(nameof(Money.Update))] private static void Update(Money __instance) { + if (!Utils.CheckForUntranslatedText(__instance.beanCount.text)) return; __instance.beanCount.text = StringStore.TranslateText(__instance.beanCount.text); __instance.beanCount2.text = StringStore.TranslateText(__instance.beanCount2.text); } diff --git a/MelonLoader/Patches/GameObjects/UIDifficulty_Patch.cs b/MelonLoader/Patches/GameObjects/UIDifficulty_Patch.cs index b914913..c7b6c5b 100644 --- a/MelonLoader/Patches/GameObjects/UIDifficulty_Patch.cs +++ b/MelonLoader/Patches/GameObjects/UIDifficulty_Patch.cs @@ -14,11 +14,8 @@ namespace PvZ_Fusion_Translator.Patches.GameObjects [HarmonyPostfix] private static void Update(UIDifficulty __instance) { + if (!Utils.CheckForUntranslatedText(__instance.t.text)) return; __instance.t.text = StringStore.TranslateText(__instance.t.text); - foreach(TextMeshProUGUI text in __instance.GetComponentsInChildren()) - { - text.text = StringStore.TranslateText(text.text); - } } } } \ No newline at end of file diff --git a/MelonLoader/Patches/Managers/InGameUI_Patch.cs b/MelonLoader/Patches/Managers/InGameUI_Patch.cs index 670187b..fac7ed0 100644 --- a/MelonLoader/Patches/Managers/InGameUI_Patch.cs +++ b/MelonLoader/Patches/Managers/InGameUI_Patch.cs @@ -15,10 +15,10 @@ namespace PvZ_Fusion_Translator.Patches.Managers [HarmonyPostfix] private static void Start(InGameUI __instance) { - foreach(TextMeshProUGUI text in __instance.T) + foreach (TextMeshProUGUI text in __instance.T) { if (text.text == null) continue; - + string originalText = text.text; text.text = text.text.Replace("\n", " "); Regex checkFusionChallenge = new Regex("^超级([^\\s:]+)(:?挑战1?)"); @@ -47,10 +47,10 @@ namespace PvZ_Fusion_Translator.Patches.Managers [HarmonyPostfix] private static void SetUniqueText(InGameUI __instance) { - foreach(TextMeshProUGUI text in __instance.T) + foreach (TextMeshProUGUI text in __instance.T) { if (text.text == null) continue; - + string originalText = text.text; text.text = text.text.Replace("\n", " "); Regex checkFusionChallenge = new Regex("^超级([^\\s:]+)(:?挑战1?)"); @@ -79,10 +79,10 @@ namespace PvZ_Fusion_Translator.Patches.Managers [HarmonyPostfix] private static void SetLevelName(InGameUI __instance) { - foreach(TextMeshProUGUI text in __instance.T) + foreach (TextMeshProUGUI text in __instance.T) { if (text.text == null) continue; - + string originalText = text.text; text.text = text.text.Replace("\n", " "); Regex checkFusionChallenge = new Regex("^超级([^\\s:]+)(:?挑战1?)"); diff --git a/MelonLoader/Patches/Managers/TowerManager_Patch.cs b/MelonLoader/Patches/Managers/TowerManager_Patch.cs index 221b6e5..3088e45 100644 --- a/MelonLoader/Patches/Managers/TowerManager_Patch.cs +++ b/MelonLoader/Patches/Managers/TowerManager_Patch.cs @@ -17,7 +17,10 @@ namespace PvZ_Fusion_Translator.Patches.Managers { if (transform != null) { - transform.GetComponent().text = StringStore.TranslateText(transform.GetComponent().text); + if(transform.gameObject.active) + { + transform.GetComponent().text = StringStore.TranslateText(transform.GetComponent().text); + } } } } diff --git a/MelonLoader/PvZ Fusion Translator [MelonLoader].csproj b/MelonLoader/PvZ Fusion Translator [MelonLoader].csproj index e6ea827..18fcea9 100644 --- a/MelonLoader/PvZ Fusion Translator [MelonLoader].csproj +++ b/MelonLoader/PvZ Fusion Translator [MelonLoader].csproj @@ -31,6 +31,7 @@ + @@ -390,6 +391,7 @@ + @@ -550,6 +552,10 @@ + + + + @@ -558,5 +564,6 @@ + \ No newline at end of file diff --git a/MelonLoader/Resources/ModUpdateUtil.exe b/MelonLoader/Resources/ModUpdateUtil.exe new file mode 100644 index 0000000..1514752 Binary files /dev/null and b/MelonLoader/Resources/ModUpdateUtil.exe differ diff --git a/MelonLoader/Utils.cs b/MelonLoader/Utils.cs index cb0a263..d8ce77b 100644 --- a/MelonLoader/Utils.cs +++ b/MelonLoader/Utils.cs @@ -93,9 +93,9 @@ namespace PvZ_Fusion_Translator Process.Start("explorer.exe", saveDirectory); } - public static void OpenTrello() + public static void OpenOnlineAlmanac() { - string website = "https://trello.com/b/DcdT1kUp"; + string website = "https://carroti4ch.itch.io/almanac"; Process.Start(new ProcessStartInfo(website) { UseShellExecute = true }); } @@ -420,7 +420,7 @@ namespace PvZ_Fusion_Translator } } - public static async Task GetImageDataFromWeb(string url, bool isLog = true) + public static async Task GetByteDataFromWeb(string url, bool isLog = true) { if (isLog) { @@ -501,6 +501,26 @@ namespace PvZ_Fusion_Translator } } + public static int CalculateGameVersion(string gameVersion) + { + int res = 0; + string[] gameVersionParts = gameVersion.Split('.'); + + int startingPower = (int)Math.Max(gameVersionParts.Length, 3); + for (int i = 0; i < startingPower; i++) + { + int factor = 0; + if (i < gameVersionParts.Length) + { + factor = int.Parse(gameVersionParts[i]); + } + int power = startingPower - i; + res += factor * (int)Math.Pow(10, power - 1); + } + + return res; + } + #if MULTI_LANGUAGE internal static void ChangeLanguage(string language) {