Merge branch 'cassidy'
This commit is contained in:
commit
c5720a02ca
9 changed files with 486 additions and 158 deletions
|
|
@ -14,6 +14,10 @@ namespace PvZ_Fusion_Translator.AssetStore
|
||||||
|
|
||||||
public static Dictionary<string, string> translationString = new();
|
public static Dictionary<string, string> translationString = new();
|
||||||
|
|
||||||
|
public static Dictionary<string, string> customLevelStringRegex = new();
|
||||||
|
|
||||||
|
public static Dictionary<string, string> customLevelString = new();
|
||||||
|
|
||||||
public static Dictionary<string, string> izLevelTipDictionary = new();
|
public static Dictionary<string, string> izLevelTipDictionary = new();
|
||||||
|
|
||||||
public static Dictionary<string, string> izTipCollectionString = new();
|
public static Dictionary<string, string> izTipCollectionString = new();
|
||||||
|
|
@ -80,6 +84,8 @@ namespace PvZ_Fusion_Translator.AssetStore
|
||||||
{
|
{
|
||||||
translationString.Clear();
|
translationString.Clear();
|
||||||
translationStringRegex.Clear();
|
translationStringRegex.Clear();
|
||||||
|
customLevelString.Clear();
|
||||||
|
customLevelStringRegex.Clear();
|
||||||
izLevelTipDictionary.Clear();
|
izLevelTipDictionary.Clear();
|
||||||
izTipCollectionString.Clear();
|
izTipCollectionString.Clear();
|
||||||
fsLevelTipDictionary.Clear();
|
fsLevelTipDictionary.Clear();
|
||||||
|
|
@ -158,37 +164,70 @@ namespace PvZ_Fusion_Translator.AssetStore
|
||||||
|
|
||||||
public static string TranslateText(string originalText, string pattern, bool isLog = false)
|
public static string TranslateText(string originalText, string pattern, bool isLog = false)
|
||||||
{
|
{
|
||||||
if (TestRegex(originalText, pattern) && translationStringRegex.ContainsKey(pattern))
|
if (TestRegex(originalText, pattern))
|
||||||
{
|
{
|
||||||
// Extract dynamic parts from the original text
|
if(translationStringRegex.ContainsKey(pattern))
|
||||||
var regex = new Regex(pattern);
|
{
|
||||||
var match = regex.Match(originalText);
|
// Extract dynamic parts from the original text
|
||||||
int groupCount = match.Groups.Count;
|
var regex = new Regex(pattern);
|
||||||
|
var match = regex.Match(originalText);
|
||||||
|
int groupCount = match.Groups.Count;
|
||||||
|
|
||||||
if (isLog)
|
if (isLog)
|
||||||
Log.LogDebug("Text found in translationStringRegex {0}: {1}", match, groupCount);
|
Log.LogDebug("Text found in translationStringRegex {0}: {1}", match, groupCount);
|
||||||
|
|
||||||
// List to hold formatted dynamic parts
|
// List to hold formatted dynamic parts
|
||||||
List<string> dynamicParts = [];
|
List<string> dynamicParts = [];
|
||||||
|
|
||||||
// Loop through each group and determine its translation
|
// Loop through each group and determine its translation
|
||||||
for (int i = 1; i < groupCount; i++)
|
for (int i = 1; i < groupCount; i++)
|
||||||
{
|
{
|
||||||
string groupValue = match.Groups[i].Value;
|
string groupValue = match.Groups[i].Value;
|
||||||
string translatedValue = translationString.ContainsKey(groupValue)
|
string translatedValue = translationString.ContainsKey(groupValue)
|
||||||
? translationString[groupValue]
|
? translationString[groupValue]
|
||||||
: groupValue;
|
: groupValue;
|
||||||
dynamicParts.Add(translatedValue);
|
dynamicParts.Add(translatedValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format the output string with dynamic parts
|
// Format the output string with dynamic parts
|
||||||
return string.Format(translationStringRegex[pattern], [.. dynamicParts]);
|
return string.Format(translationStringRegex[pattern], [.. dynamicParts]);
|
||||||
}
|
}
|
||||||
|
else if(customLevelStringRegex.ContainsKey(pattern))
|
||||||
|
{
|
||||||
|
// Extract dynamic parts from the original text
|
||||||
|
var regex = new Regex(pattern);
|
||||||
|
var match = regex.Match(originalText);
|
||||||
|
int groupCount = match.Groups.Count;
|
||||||
|
|
||||||
|
if (isLog)
|
||||||
|
Log.LogDebug("Text found in customLevelStringRegex {0}: {1}", match, groupCount);
|
||||||
|
|
||||||
|
// List to hold formatted dynamic parts
|
||||||
|
List<string> dynamicParts = [];
|
||||||
|
|
||||||
|
// Loop through each group and determine its translation
|
||||||
|
for (int i = 1; i < groupCount; i++)
|
||||||
|
{
|
||||||
|
string groupValue = match.Groups[i].Value;
|
||||||
|
string translatedValue = customLevelString.ContainsKey(groupValue)
|
||||||
|
? customLevelString[groupValue]
|
||||||
|
: groupValue;
|
||||||
|
dynamicParts.Add(translatedValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format the output string with dynamic parts
|
||||||
|
return string.Format(customLevelStringRegex[pattern], [.. dynamicParts]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return originalText;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (isLog)
|
if (isLog)
|
||||||
Log.LogDebug($"Text '{originalText}' not translated");
|
Log.LogDebug($"Text '{originalText}' not translated");
|
||||||
FileLoader.DumpUntranslatedStrings(originalText);
|
FileLoader.DumpUntranslatedStrings(originalText);
|
||||||
return originalText;
|
return originalText;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -228,6 +267,15 @@ namespace PvZ_Fusion_Translator.AssetStore
|
||||||
return fsTipCollectionString[originalText];
|
return fsTipCollectionString[originalText];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(customLevelString.ContainsKey(originalText))
|
||||||
|
{
|
||||||
|
if(isLog)
|
||||||
|
{
|
||||||
|
Log.LogDebug($"Text '{originalText}' found in customLevelString");
|
||||||
|
}
|
||||||
|
return customLevelString[originalText];
|
||||||
|
}
|
||||||
|
|
||||||
// Regex-based dynamic translation
|
// Regex-based dynamic translation
|
||||||
foreach (var entry in translationStringRegex)
|
foreach (var entry in translationStringRegex)
|
||||||
{
|
{
|
||||||
|
|
@ -259,6 +307,36 @@ namespace PvZ_Fusion_Translator.AssetStore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (var entry in customLevelStringRegex)
|
||||||
|
{
|
||||||
|
if (TestRegex(originalText, entry.Key))
|
||||||
|
{
|
||||||
|
// Extract dynamic parts from the original text
|
||||||
|
var regex = new Regex(entry.Key);
|
||||||
|
var match = regex.Match(originalText);
|
||||||
|
int groupCount = match.Groups.Count;
|
||||||
|
|
||||||
|
if (isLog)
|
||||||
|
Log.LogDebug("Text found in customLevelRegex {0}: {1}", match, groupCount);
|
||||||
|
|
||||||
|
// List to hold formatted dynamic parts
|
||||||
|
List<string> dynamicParts = [];
|
||||||
|
|
||||||
|
// Loop through each group and determine its translation
|
||||||
|
for (int i = 1; i < groupCount; i++)
|
||||||
|
{
|
||||||
|
string groupValue = match.Groups[i].Value;
|
||||||
|
string translatedValue = customLevelString.ContainsKey(groupValue)
|
||||||
|
? customLevelString[groupValue]
|
||||||
|
: groupValue;
|
||||||
|
dynamicParts.Add(translatedValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format the output string with dynamic parts
|
||||||
|
return string.Format(entry.Value, [.. dynamicParts]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (isLog)
|
if (isLog)
|
||||||
Log.LogDebug($"Text '{originalText}' not translated");
|
Log.LogDebug($"Text '{originalText}' not translated");
|
||||||
if(Utils.CheckForUntranslatedText(originalText))
|
if(Utils.CheckForUntranslatedText(originalText))
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,37 @@ namespace PvZ_Fusion_Translator
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string customLevelStringsContent = Utils.GetDataFromWeb($"https://raw.githubusercontent.com/Teyliu/PVZF-Translation/refs/heads/main/PvZ_Fusion_Translator/Localization/{Utils.Language.ToString()}/Strings/customlevel_strings.json").Result;
|
||||||
|
|
||||||
|
if(customLevelStringsContent != null)
|
||||||
|
{
|
||||||
|
LoadCustomLevelStrings(customLevelStringsContent);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string customLevelStringsPath = Path.Combine(GetAssetDir(AssetType.Strings, Utils.Language), "customlevel_strings.json");
|
||||||
|
if(File.Exists(customLevelStringsPath))
|
||||||
|
{
|
||||||
|
LoadCustomLevelStrings(File.ReadAllText(customLevelStringsPath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// load translationRegexs
|
||||||
|
string customLevelRegexsContent = Utils.GetDataFromWeb($"https://raw.githubusercontent.com/Teyliu/PVZF-Translation/refs/heads/main/PvZ_Fusion_Translator/Localization/{Utils.Language.ToString()}/Strings/customlevel_regexs.json").Result;
|
||||||
|
|
||||||
|
if(customLevelRegexsContent != null)
|
||||||
|
{
|
||||||
|
LoadCustomLevelRegexs(customLevelRegexsContent);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string customLevelRegexsPath = Path.Combine(GetAssetDir(AssetType.Strings, Utils.Language), "customlevel_regexs.json");
|
||||||
|
if(File.Exists(customLevelRegexsPath))
|
||||||
|
{
|
||||||
|
LoadCustomLevelRegexs(File.ReadAllText(customLevelRegexsPath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// load changelog
|
// load changelog
|
||||||
|
|
||||||
LoadChangelogText();
|
LoadChangelogText();
|
||||||
|
|
@ -200,14 +231,22 @@ namespace PvZ_Fusion_Translator
|
||||||
Log.LogInfo("Loading File : " + filepath);
|
Log.LogInfo("Loading File : " + filepath);
|
||||||
#endif
|
#endif
|
||||||
string jsonString = File.ReadAllText(filepath);
|
string jsonString = File.ReadAllText(filepath);
|
||||||
if (fileName.EndsWith("_strings"))
|
if (fileName.EndsWith("translation_strings"))
|
||||||
{
|
{
|
||||||
LoadTranslationStrings(jsonString);
|
LoadTranslationStrings(jsonString);
|
||||||
}
|
}
|
||||||
else if (fileName.EndsWith("_regexs"))
|
else if (fileName.EndsWith("translation_regexs"))
|
||||||
{
|
{
|
||||||
LoadTranslationRegexs(jsonString);
|
LoadTranslationRegexs(jsonString);
|
||||||
}
|
}
|
||||||
|
else if (fileName.EndsWith("customlevel_strings"))
|
||||||
|
{
|
||||||
|
LoadCustomLevelStrings(jsonString);
|
||||||
|
}
|
||||||
|
else if (fileName.EndsWith("customlevel_regexs"))
|
||||||
|
{
|
||||||
|
LoadCustomLevelRegexs(jsonString);
|
||||||
|
}
|
||||||
else if(fileName.EndsWith("tips_iz"))
|
else if(fileName.EndsWith("tips_iz"))
|
||||||
{
|
{
|
||||||
LoadIZStrings(jsonString);
|
LoadIZStrings(jsonString);
|
||||||
|
|
@ -280,6 +319,24 @@ namespace PvZ_Fusion_Translator
|
||||||
Zombie_Patch.LoadHPStrings();
|
Zombie_Patch.LoadHPStrings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static void LoadCustomLevelStrings(string content)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> dictionary = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, string>>(content);
|
||||||
|
foreach (var (key, value) in dictionary)
|
||||||
|
{
|
||||||
|
StringStore.customLevelString[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void LoadCustomLevelRegexs(string content)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> dictionary = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, string>>(content);
|
||||||
|
foreach (var (key, value) in dictionary)
|
||||||
|
{
|
||||||
|
StringStore.customLevelStringRegex[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal static void LoadIZStrings(string content)
|
internal static void LoadIZStrings(string content)
|
||||||
{
|
{
|
||||||
var izDump = DumpIZStrings();
|
var izDump = DumpIZStrings();
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
//#if DEBUG
|
//#if DEBUG
|
||||||
|
using Il2Cpp;
|
||||||
|
using Il2CppGameLevel;
|
||||||
using PvZ_Fusion_Translator.AssetStore;
|
using PvZ_Fusion_Translator.AssetStore;
|
||||||
using PvZ_Fusion_Translator.Patches.Modes.Super_Editor;
|
using PvZ_Fusion_Translator.Patches.Modes.Super_Editor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
@ -10,7 +12,8 @@ namespace PvZ_Fusion_Translator
|
||||||
public enum ModType
|
public enum ModType
|
||||||
{
|
{
|
||||||
ReloadStrings,
|
ReloadStrings,
|
||||||
ReloadTextures
|
ReloadTextures,
|
||||||
|
ExportLevelStrings
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ModFeature
|
private class ModFeature
|
||||||
|
|
@ -43,13 +46,26 @@ namespace PvZ_Fusion_Translator
|
||||||
Core.ShowToast("Textures Reloaded!");
|
Core.ShowToast("Textures Reloaded!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.ModType == ModType.ExportLevelStrings)
|
||||||
|
{
|
||||||
|
CustomMenu customMenu = UnityEngine.Object.FindObjectOfType<CustomMenu>();
|
||||||
|
if (!customMenu) return;
|
||||||
|
if(customMenu.isActiveAndEnabled)
|
||||||
|
{
|
||||||
|
Patches.Modes.Super_Editor.GameLevel.LevelManager_Patch.ExportLevelStrings(customMenu.LevelData);
|
||||||
|
Core.ShowToast("Dumped level strings!");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Dictionary<ModType, ModFeature> featureLists = new()
|
private static Dictionary<ModType, ModFeature> featureLists = new()
|
||||||
{
|
{
|
||||||
{ModType.ReloadStrings,new ModFeature("Reload Strings",ModType.ReloadStrings,KeyCode.Home, true)},
|
{ModType.ReloadStrings,new ModFeature("Reload Strings",ModType.ReloadStrings,KeyCode.Home, true)},
|
||||||
{ModType.ReloadTextures,new ModFeature("Reload Textures",ModType.ReloadTextures,KeyCode.End, true)}
|
{ModType.ReloadTextures,new ModFeature("Reload Textures",ModType.ReloadTextures,KeyCode.End, true)},
|
||||||
|
{ModType.ExportLevelStrings,new ModFeature("Export Level Strings",ModType.ExportLevelStrings,KeyCode.N, true)}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,7 @@ namespace PvZ_Fusion_Translator.Patches.BaseTextObjects
|
||||||
int godsGachaCheck = CheckGodsGachaPopup(originalText);
|
int godsGachaCheck = CheckGodsGachaPopup(originalText);
|
||||||
string godsGachaMatch = "";
|
string godsGachaMatch = "";
|
||||||
string superEditorPlantMatch = CheckSuperEditorPopup(originalText);
|
string superEditorPlantMatch = CheckSuperEditorPopup(originalText);
|
||||||
|
string customLevelRegexMatch = CheckCustomLevelRegex(originalText);
|
||||||
|
|
||||||
switch(godsGachaCheck)
|
switch(godsGachaCheck)
|
||||||
{
|
{
|
||||||
|
|
@ -119,7 +120,15 @@ namespace PvZ_Fusion_Translator.Patches.BaseTextObjects
|
||||||
{
|
{
|
||||||
txt.text = lockedPlantMatch;
|
txt.text = lockedPlantMatch;
|
||||||
}
|
}
|
||||||
else if((Regex.Match(txt.text, @"(<color[^>]*>.*?</color>)", RegexOptions.Singleline).Success) && (!StringStore.translationString.ContainsKey(txt.text) && !StringStore.fsTipCollectionString.ContainsKey(txt.text) && !StringStore.izTipCollectionString.ContainsKey(txt.text)))
|
else if(customLevelRegexMatch != "")
|
||||||
|
{
|
||||||
|
txt.text = customLevelRegexMatch;
|
||||||
|
}
|
||||||
|
else if((Regex.Match(txt.text, @"(<color[^>]*>.*?</color>)", RegexOptions.Singleline).Success) &&
|
||||||
|
!StringStore.translationString.ContainsKey(txt.text) &&
|
||||||
|
!StringStore.fsTipCollectionString.ContainsKey(txt.text) &&
|
||||||
|
!StringStore.izTipCollectionString.ContainsKey(txt.text) &&
|
||||||
|
!StringStore.customLevelString.ContainsKey(txt.text))
|
||||||
{
|
{
|
||||||
txt.text = StringStore.TranslateColorText(txt.text, true);
|
txt.text = StringStore.TranslateColorText(txt.text, true);
|
||||||
if (txt.gameObject.name.Contains("main"))
|
if (txt.gameObject.name.Contains("main"))
|
||||||
|
|
@ -348,5 +357,19 @@ namespace PvZ_Fusion_Translator.Patches.BaseTextObjects
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string CheckCustomLevelRegex(string originalText)
|
||||||
|
{
|
||||||
|
string res = "";
|
||||||
|
|
||||||
|
foreach(var pair in StringStore.customLevelStringRegex)
|
||||||
|
{
|
||||||
|
if(StringStore.TestRegex(originalText, pair.Key))
|
||||||
|
{
|
||||||
|
res = StringStore.TranslateText(originalText, pair.Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -27,7 +27,14 @@ namespace PvZ_Fusion_Translator.Patches.Modes.Odyssey
|
||||||
foreach(TextMeshProUGUI txt in window.GetComponentsInChildren<TextMeshProUGUI>())
|
foreach(TextMeshProUGUI txt in window.GetComponentsInChildren<TextMeshProUGUI>())
|
||||||
{
|
{
|
||||||
txt.font = fontAsset;
|
txt.font = fontAsset;
|
||||||
txt.text = StringStore.translationString.ContainsKey(txt.text + "_MC") ? StringStore.TranslateText(txt.text + "_MC") : StringStore.TranslateText(txt.text);
|
if(StringStore.customLevelString.ContainsKey(txt.text))
|
||||||
|
{
|
||||||
|
txt.text = StringStore.customLevelString[txt.text];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
txt.text = StringStore.translationString.ContainsKey(txt.text + "_MC") ? StringStore.TranslateText(txt.text + "_MC") : StringStore.TranslateText(txt.text);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,15 @@ namespace PvZ_Fusion_Translator.Patches.Modes.Super_Editor
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TranslatedLevelData dumpedLevelData = new TranslatedLevelData(level.onlineLevelInfo.levelName, serializedLevel.boardConfig.startTip);
|
TranslatedLevelData dumpedLevelData = new TranslatedLevelData(level.onlineLevelInfo.levelName, serializedLevel.boardConfig.startTip);
|
||||||
dumpData.Add(levelId, dumpedLevelData);
|
|
||||||
|
if (dumpData.ContainsKey(levelId))
|
||||||
|
{
|
||||||
|
dumpData[levelId] = dumpedLevelData;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dumpData.Add(levelId, dumpedLevelData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*level.levelData.SerializedLevelData
|
/*level.levelData.SerializedLevelData
|
||||||
|
|
@ -93,123 +101,4 @@ namespace PvZ_Fusion_Translator.Patches.Modes.Super_Editor
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*[HarmonyPatch(typeof(LevelManager))]
|
|
||||||
public static class Test
|
|
||||||
{
|
|
||||||
[HarmonyPatch(nameof(LevelManager.SaveLevelData))]
|
|
||||||
[HarmonyPostfix]
|
|
||||||
public static void SaveLevelData(LevelManager __instance, ref SerializedLevelData serializedLevelData)
|
|
||||||
{
|
|
||||||
Log.LogDebug("hi 2");
|
|
||||||
string json = JsonUtility.ToJson(serializedLevelData);
|
|
||||||
ReferenceLevelData references = Newtonsoft.Json.JsonConvert.DeserializeObject<ReferenceLevelData>(json);
|
|
||||||
foreach(var reference in references.references.RefIds)
|
|
||||||
{
|
|
||||||
ReferenceLevelData.Data nodeData = reference.data;
|
|
||||||
string nodeType = nodeData.nodeType;
|
|
||||||
|
|
||||||
if(nodeType == "StringConcatNode")
|
|
||||||
{
|
|
||||||
Log.LogDebug(nodeData.value.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
if(nodeType == "StringValueNode")
|
|
||||||
{
|
|
||||||
Log.LogDebug(nodeData.value.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public class ReferenceLevelData
|
|
||||||
{
|
|
||||||
public class Data
|
|
||||||
{
|
|
||||||
public string nodeId { get; set; }
|
|
||||||
public string nodeType { get; set; }
|
|
||||||
public Position position { get; set; }
|
|
||||||
public string nodeName { get; set; }
|
|
||||||
public string plant_PortName { get; set; }
|
|
||||||
public string column_PortName { get; set; }
|
|
||||||
public string row_PortName { get; set; }
|
|
||||||
public string plantType_PortName { get; set; }
|
|
||||||
public object value { get; set; }
|
|
||||||
public string value_PortName { get; set; }
|
|
||||||
public string plantTypeA_PortName { get; set; }
|
|
||||||
public string plantTypeB_PortName { get; set; }
|
|
||||||
public string equal_PortName { get; set; }
|
|
||||||
public string trigger_PortName { get; set; }
|
|
||||||
public string count_PortName { get; set; }
|
|
||||||
public string output_PortName { get; set; }
|
|
||||||
public string index_PortName { get; set; }
|
|
||||||
public string plants_PortName { get; set; }
|
|
||||||
public string plantList_PortName { get; set; }
|
|
||||||
public string loopBody_PortName { get; set; }
|
|
||||||
public string currentPlant_PortName { get; set; }
|
|
||||||
public string currentIndex_PortName { get; set; }
|
|
||||||
public string onCompleted_PortName { get; set; }
|
|
||||||
public string condition_PortName { get; set; }
|
|
||||||
public string then_PortName { get; set; }
|
|
||||||
public string else_PortName { get; set; }
|
|
||||||
public string a_PortName { get; set; }
|
|
||||||
public string b_PortName { get; set; }
|
|
||||||
public string result_PortName { get; set; }
|
|
||||||
public string shouldReset_PortName { get; set; }
|
|
||||||
public string onCount_PortName { get; set; }
|
|
||||||
public int? startValue { get; set; }
|
|
||||||
public string valueA_PortName { get; set; }
|
|
||||||
public string valueB_PortName { get; set; }
|
|
||||||
public string greater_PortName { get; set; }
|
|
||||||
public string less_PortName { get; set; }
|
|
||||||
public string displayText { get; set; }
|
|
||||||
public double? duration { get; set; }
|
|
||||||
public string text_PortName { get; set; }
|
|
||||||
public string duration_PortName { get; set; }
|
|
||||||
public string int_PortName { get; set; }
|
|
||||||
public string float_PortName { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class GodShootingConfig
|
|
||||||
{
|
|
||||||
public List<object> plants { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Position
|
|
||||||
{
|
|
||||||
public double x { get; set; }
|
|
||||||
public double y { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class References
|
|
||||||
{
|
|
||||||
public int version { get; set; }
|
|
||||||
public List<RefId> RefIds { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class RefId
|
|
||||||
{
|
|
||||||
public int rid { get; set; }
|
|
||||||
public Type type { get; set; }
|
|
||||||
public Data data { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Type
|
|
||||||
{
|
|
||||||
public string @class { get; set; }
|
|
||||||
public string ns { get; set; }
|
|
||||||
public string asm { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ZombiesWithRow
|
|
||||||
{
|
|
||||||
public int zombieType { get; set; }
|
|
||||||
public int row { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public EventNodeGraph eventNodeGraph { get; set; }
|
|
||||||
public References references { get; set; }
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
@ -26,6 +26,8 @@ namespace PvZ_Fusion_Translator.Patches.Modes.Super_Editor.GameLevel.EventNodes
|
||||||
[HarmonyPostfix]
|
[HarmonyPostfix]
|
||||||
public static void Awake(RuntimeNodeUI __instance)
|
public static void Awake(RuntimeNodeUI __instance)
|
||||||
{
|
{
|
||||||
|
if (!__instance.isActiveAndEnabled) return;
|
||||||
|
|
||||||
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
|
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
|
||||||
|
|
||||||
if(__instance.dropdownPrefab)
|
if(__instance.dropdownPrefab)
|
||||||
|
|
@ -56,6 +58,8 @@ namespace PvZ_Fusion_Translator.Patches.Modes.Super_Editor.GameLevel.EventNodes
|
||||||
[HarmonyPostfix]
|
[HarmonyPostfix]
|
||||||
public static void UpdateDisplay(RuntimeNodeUI __instance)
|
public static void UpdateDisplay(RuntimeNodeUI __instance)
|
||||||
{
|
{
|
||||||
|
if (!__instance.isActiveAndEnabled) return;
|
||||||
|
|
||||||
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
|
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
|
||||||
|
|
||||||
if(__instance.Node.nodeType == "PlantTypeValueNode")
|
if(__instance.Node.nodeType == "PlantTypeValueNode")
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,16 @@
|
||||||
using System;
|
using HarmonyLib;
|
||||||
|
using Il2Cpp;
|
||||||
|
using Il2CppGameLevel;
|
||||||
|
using Il2CppGameLevel.EventNodes;
|
||||||
|
using MelonLoader;
|
||||||
|
using PvZ_Fusion_Translator.AssetStore;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Text.Encodings.Web;
|
||||||
|
using System.Text.Json;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using HarmonyLib;
|
|
||||||
using Il2Cpp;
|
|
||||||
using Il2CppGameLevel;
|
|
||||||
using PvZ_Fusion_Translator.AssetStore;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace PvZ_Fusion_Translator.Patches.Modes.Super_Editor.GameLevel
|
namespace PvZ_Fusion_Translator.Patches.Modes.Super_Editor.GameLevel
|
||||||
|
|
@ -18,10 +22,259 @@ namespace PvZ_Fusion_Translator.Patches.Modes.Super_Editor.GameLevel
|
||||||
[HarmonyPrefix]
|
[HarmonyPrefix]
|
||||||
public static void Pre_SaveLevelData(LevelManager __instance, ref SerializedLevelData serializedLevelData)
|
public static void Pre_SaveLevelData(LevelManager __instance, ref SerializedLevelData serializedLevelData)
|
||||||
{
|
{
|
||||||
if(serializedLevelData.name == "未命名关卡")
|
if (serializedLevelData.name == "未命名关卡")
|
||||||
{
|
{
|
||||||
serializedLevelData.name = StringStore.translationString.ContainsKey("LEVEL_UNNAMED") ? StringStore.TranslateText("LEVEL_UNNAMED") : "Unnamed";
|
serializedLevelData.name = StringStore.translationString.ContainsKey("LEVEL_UNNAMED") ? StringStore.TranslateText("LEVEL_UNNAMED") : "Unnamed";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void ExportLevelStrings(SerializedLevelData serializedLevelData)
|
||||||
|
{
|
||||||
|
string levelDataString = JsonUtility.ToJson(serializedLevelData);
|
||||||
|
ReferenceLevelData referenceLevelData = Newtonsoft.Json.JsonConvert.DeserializeObject<ReferenceLevelData>(levelDataString);
|
||||||
|
EventNodeGraph eventNodeGraph = serializedLevelData.eventNodeGraph;
|
||||||
|
eventNodeGraph.BuildCache();
|
||||||
|
|
||||||
|
List<string> stringValueNodeIds = new List<string>();
|
||||||
|
List<string> stringConcatNodeIds = new List<string>();
|
||||||
|
List<string> showTextNodeIds = new List<string>();
|
||||||
|
List<string> addOptionNodeIds = new List<string>();
|
||||||
|
|
||||||
|
foreach (var reference in referenceLevelData.references.RefIds)
|
||||||
|
{
|
||||||
|
string nodeType = reference.data.nodeType;
|
||||||
|
string nodeId = reference.data.nodeId;
|
||||||
|
|
||||||
|
if (nodeType == "ShowTextNode")
|
||||||
|
{
|
||||||
|
if(!showTextNodeIds.Contains(nodeId))
|
||||||
|
{
|
||||||
|
showTextNodeIds.Add(nodeId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (nodeType == "AddMultipleChoiceOptionNode")
|
||||||
|
{
|
||||||
|
if(!addOptionNodeIds.Contains(nodeId))
|
||||||
|
{
|
||||||
|
addOptionNodeIds.Add(nodeId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var reference in referenceLevelData.references.RefIds)
|
||||||
|
{
|
||||||
|
string nodeType = reference.data.nodeType;
|
||||||
|
string nodeId = reference.data.nodeId;
|
||||||
|
|
||||||
|
switch(nodeType)
|
||||||
|
{
|
||||||
|
case "StringValueNode":
|
||||||
|
case "FloatToStringNode":
|
||||||
|
case "StringConcatNode":
|
||||||
|
stringValueNodeIds.Add(nodeId);
|
||||||
|
if(nodeType == "StringConcatNode")
|
||||||
|
{
|
||||||
|
stringConcatNodeIds.Add(nodeId);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary<string, ValueTuple<string, string>> stringConcatNodePairs = new();
|
||||||
|
|
||||||
|
foreach(var connection in eventNodeGraph.connections)
|
||||||
|
{
|
||||||
|
string sourceNodeId = connection.sourceNodeId;
|
||||||
|
string sourcePortName = connection.sourcePortName;
|
||||||
|
string targetNodeId = connection.targetNodeId;
|
||||||
|
string targetPortName = connection.targetPortName;
|
||||||
|
|
||||||
|
if(stringValueNodeIds.Contains(sourceNodeId))
|
||||||
|
{
|
||||||
|
if(stringConcatNodeIds.Contains(targetNodeId))
|
||||||
|
{
|
||||||
|
if(stringConcatNodePairs.ContainsKey(targetNodeId))
|
||||||
|
{
|
||||||
|
ValueTuple<string, string> temp = stringConcatNodePairs[targetNodeId];
|
||||||
|
switch(targetPortName)
|
||||||
|
{
|
||||||
|
case "A":
|
||||||
|
temp.Item1 = sourceNodeId;
|
||||||
|
stringConcatNodePairs[targetNodeId] = temp;
|
||||||
|
break;
|
||||||
|
case "B":
|
||||||
|
temp.Item2 = sourceNodeId;
|
||||||
|
stringConcatNodePairs[targetNodeId] = temp;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stringConcatNodePairs.Add(targetNodeId, new ValueTuple<string, string>());
|
||||||
|
ValueTuple<string, string> temp = stringConcatNodePairs[targetNodeId];
|
||||||
|
switch(targetPortName)
|
||||||
|
{
|
||||||
|
case "A":
|
||||||
|
temp.Item1 = sourceNodeId;
|
||||||
|
stringConcatNodePairs[targetNodeId] = temp;
|
||||||
|
break;
|
||||||
|
case "B":
|
||||||
|
temp.Item2 = sourceNodeId;
|
||||||
|
stringConcatNodePairs[targetNodeId] = temp;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string GetStringNodeValue(EventNodeBase eventNodeBase)
|
||||||
|
{
|
||||||
|
string stringValue = "";
|
||||||
|
|
||||||
|
switch(eventNodeBase.nodeType)
|
||||||
|
{
|
||||||
|
case "StringValueNode":
|
||||||
|
StringValueNode stringNode = eventNodeBase.TryCast<StringValueNode>();
|
||||||
|
stringValue = stringNode.value;
|
||||||
|
break;
|
||||||
|
case "FloatToStringNode":
|
||||||
|
stringValue = "([^\\s]+)";
|
||||||
|
break;
|
||||||
|
case "StringConcatNode":
|
||||||
|
StringConcatNode stringConcatNode = eventNodeBase.TryCast<StringConcatNode>();
|
||||||
|
stringConcatNode.InitializeConnections(eventNodeGraph);
|
||||||
|
stringValue = GetStringNodeValue(stringConcatNode.aSourceNode) + GetStringNodeValue(stringConcatNode.bSourceNode);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stringValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
string baseDumpDir = FileLoader.GetAssetDir(FileLoader.AssetType.Dumps);
|
||||||
|
string levelDumpDir = Path.Combine(baseDumpDir, "CustomLevels.json");
|
||||||
|
if (!File.Exists(levelDumpDir)) File.WriteAllText(levelDumpDir, "{}");
|
||||||
|
Dictionary<string, string> dump = JsonSerializer.Deserialize<Dictionary<string, string>>(File.ReadAllText(levelDumpDir));
|
||||||
|
|
||||||
|
foreach(string showTextNodeId in showTextNodeIds)
|
||||||
|
{
|
||||||
|
ShowTextNode showTextNode = eventNodeGraph.GetNodeById(showTextNodeId).TryCast<ShowTextNode>();
|
||||||
|
showTextNode.InitializeConnections(eventNodeGraph);
|
||||||
|
string value = GetStringNodeValue(showTextNode.textSourceNode);
|
||||||
|
if (!dump.ContainsKey(value))
|
||||||
|
{
|
||||||
|
dump.Add(value, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(string addOptionId in addOptionNodeIds)
|
||||||
|
{
|
||||||
|
AddMultipleChoiceOptionNode addOptionNode = eventNodeGraph.GetNodeById(addOptionId).TryCast<AddMultipleChoiceOptionNode>();
|
||||||
|
addOptionNode.InitializeConnections(eventNodeGraph);
|
||||||
|
string titleValue = GetStringNodeValue(addOptionNode.titleSourceNode);
|
||||||
|
if (!dump.ContainsKey(titleValue))
|
||||||
|
{
|
||||||
|
dump.Add(titleValue, titleValue);
|
||||||
|
}
|
||||||
|
string descriptionValue = GetStringNodeValue(addOptionNode.descriptionSourceNode);
|
||||||
|
if (!dump.ContainsKey(descriptionValue))
|
||||||
|
{
|
||||||
|
dump.Add(descriptionValue, descriptionValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
File.WriteAllText(levelDumpDir, JsonSerializer.Serialize(dump, new JsonSerializerOptions
|
||||||
|
{
|
||||||
|
WriteIndented = true,
|
||||||
|
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
// reference level data classes
|
||||||
|
|
||||||
|
public class ReferenceLevelData
|
||||||
|
{
|
||||||
|
public References references { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Data
|
||||||
|
{
|
||||||
|
public string nodeId { get; set; }
|
||||||
|
public string nodeType { get; set; }
|
||||||
|
public Position position { get; set; }
|
||||||
|
public string nodeName { get; set; }
|
||||||
|
public string plant_PortName { get; set; }
|
||||||
|
public string column_PortName { get; set; }
|
||||||
|
public string row_PortName { get; set; }
|
||||||
|
public string plantType_PortName { get; set; }
|
||||||
|
public object value { get; set; }
|
||||||
|
public string value_PortName { get; set; }
|
||||||
|
public string plantTypeA_PortName { get; set; }
|
||||||
|
public string plantTypeB_PortName { get; set; }
|
||||||
|
public string equal_PortName { get; set; }
|
||||||
|
public string trigger_PortName { get; set; }
|
||||||
|
public string count_PortName { get; set; }
|
||||||
|
public string output_PortName { get; set; }
|
||||||
|
public string index_PortName { get; set; }
|
||||||
|
public string plants_PortName { get; set; }
|
||||||
|
public string plantList_PortName { get; set; }
|
||||||
|
public string loopBody_PortName { get; set; }
|
||||||
|
public string currentPlant_PortName { get; set; }
|
||||||
|
public string currentIndex_PortName { get; set; }
|
||||||
|
public string onCompleted_PortName { get; set; }
|
||||||
|
public string condition_PortName { get; set; }
|
||||||
|
public string then_PortName { get; set; }
|
||||||
|
public string else_PortName { get; set; }
|
||||||
|
public string a_PortName { get; set; }
|
||||||
|
public string b_PortName { get; set; }
|
||||||
|
public string result_PortName { get; set; }
|
||||||
|
public string shouldReset_PortName { get; set; }
|
||||||
|
public string onCount_PortName { get; set; }
|
||||||
|
public int? startValue { get; set; }
|
||||||
|
public string valueA_PortName { get; set; }
|
||||||
|
public string valueB_PortName { get; set; }
|
||||||
|
public string greater_PortName { get; set; }
|
||||||
|
public string less_PortName { get; set; }
|
||||||
|
public string displayText { get; set; }
|
||||||
|
public double? duration { get; set; }
|
||||||
|
public string text_PortName { get; set; }
|
||||||
|
public string duration_PortName { get; set; }
|
||||||
|
public string int_PortName { get; set; }
|
||||||
|
public string float_PortName { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Position
|
||||||
|
{
|
||||||
|
public double x { get; set; }
|
||||||
|
public double y { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class References
|
||||||
|
{
|
||||||
|
public int version { get; set; }
|
||||||
|
public List<RefId> RefIds { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RefId
|
||||||
|
{
|
||||||
|
public int rid { get; set; }
|
||||||
|
public Type type { get; set; }
|
||||||
|
public Data data { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Type
|
||||||
|
{
|
||||||
|
public string @class { get; set; }
|
||||||
|
public string ns { get; set; }
|
||||||
|
public string asm { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -549,7 +549,7 @@ namespace PvZ_Fusion_Translator
|
||||||
//Javanese,
|
//Javanese,
|
||||||
//Filipino,
|
//Filipino,
|
||||||
Vietnamese,
|
Vietnamese,
|
||||||
//Indonesian,
|
Indonesian,
|
||||||
//Russian, //NOTE: legacy language
|
//Russian, //NOTE: legacy language
|
||||||
Japanese,
|
Japanese,
|
||||||
|
|
||||||
|
|
@ -574,6 +574,7 @@ namespace PvZ_Fusion_Translator
|
||||||
{ LanguageEnum.German, "Deutsch"},
|
{ LanguageEnum.German, "Deutsch"},
|
||||||
{ LanguageEnum.Spanish, "Español"},
|
{ LanguageEnum.Spanish, "Español"},
|
||||||
{ LanguageEnum.Vietnamese, "Tiếng Việt"},
|
{ LanguageEnum.Vietnamese, "Tiếng Việt"},
|
||||||
|
{ LanguageEnum.Indonesian, "Bahasa Indonesia"},
|
||||||
{ LanguageEnum.Japanese, "日本語"},
|
{ LanguageEnum.Japanese, "日本語"},
|
||||||
{ LanguageEnum.Korean, "한국어"},
|
{ LanguageEnum.Korean, "한국어"},
|
||||||
{ LanguageEnum.Ukrainian, "українська"},
|
{ LanguageEnum.Ukrainian, "українська"},
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue