3.6.1 release code
This commit is contained in:
parent
92f03fdcb7
commit
5a923186f2
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> customLevelStringRegex = new();
|
||||
|
||||
public static Dictionary<string, string> customLevelString = new();
|
||||
|
||||
public static Dictionary<string, string> izLevelTipDictionary = new();
|
||||
|
||||
public static Dictionary<string, string> izTipCollectionString = new();
|
||||
|
|
@ -80,6 +84,8 @@ namespace PvZ_Fusion_Translator.AssetStore
|
|||
{
|
||||
translationString.Clear();
|
||||
translationStringRegex.Clear();
|
||||
customLevelString.Clear();
|
||||
customLevelStringRegex.Clear();
|
||||
izLevelTipDictionary.Clear();
|
||||
izTipCollectionString.Clear();
|
||||
fsLevelTipDictionary.Clear();
|
||||
|
|
@ -158,37 +164,70 @@ namespace PvZ_Fusion_Translator.AssetStore
|
|||
|
||||
public static string TranslateText(string originalText, string pattern, bool isLog = false)
|
||||
{
|
||||
if (TestRegex(originalText, pattern) && translationStringRegex.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 (TestRegex(originalText, pattern))
|
||||
{
|
||||
if(translationStringRegex.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 translationStringRegex {0}: {1}", match, groupCount);
|
||||
if (isLog)
|
||||
Log.LogDebug("Text found in translationStringRegex {0}: {1}", match, groupCount);
|
||||
|
||||
// List to hold formatted dynamic parts
|
||||
List<string> dynamicParts = [];
|
||||
// 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 = translationString.ContainsKey(groupValue)
|
||||
? translationString[groupValue]
|
||||
: groupValue;
|
||||
dynamicParts.Add(translatedValue);
|
||||
}
|
||||
// Loop through each group and determine its translation
|
||||
for (int i = 1; i < groupCount; i++)
|
||||
{
|
||||
string groupValue = match.Groups[i].Value;
|
||||
string translatedValue = translationString.ContainsKey(groupValue)
|
||||
? translationString[groupValue]
|
||||
: groupValue;
|
||||
dynamicParts.Add(translatedValue);
|
||||
}
|
||||
|
||||
// Format the output string with dynamic parts
|
||||
return string.Format(translationStringRegex[pattern], [.. dynamicParts]);
|
||||
}
|
||||
// Format the output string with dynamic parts
|
||||
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
|
||||
{
|
||||
if (isLog)
|
||||
Log.LogDebug($"Text '{originalText}' not translated");
|
||||
FileLoader.DumpUntranslatedStrings(originalText);
|
||||
if (isLog)
|
||||
Log.LogDebug($"Text '{originalText}' not translated");
|
||||
FileLoader.DumpUntranslatedStrings(originalText);
|
||||
return originalText;
|
||||
}
|
||||
}
|
||||
|
|
@ -228,6 +267,15 @@ namespace PvZ_Fusion_Translator.AssetStore
|
|||
return fsTipCollectionString[originalText];
|
||||
}
|
||||
|
||||
if(customLevelString.ContainsKey(originalText))
|
||||
{
|
||||
if(isLog)
|
||||
{
|
||||
Log.LogDebug($"Text '{originalText}' found in customLevelString");
|
||||
}
|
||||
return customLevelString[originalText];
|
||||
}
|
||||
|
||||
// Regex-based dynamic translation
|
||||
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)
|
||||
Log.LogDebug($"Text '{originalText}' not translated");
|
||||
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
|
||||
|
||||
LoadChangelogText();
|
||||
|
|
@ -200,14 +231,22 @@ namespace PvZ_Fusion_Translator
|
|||
Log.LogInfo("Loading File : " + filepath);
|
||||
#endif
|
||||
string jsonString = File.ReadAllText(filepath);
|
||||
if (fileName.EndsWith("_strings"))
|
||||
if (fileName.EndsWith("translation_strings"))
|
||||
{
|
||||
LoadTranslationStrings(jsonString);
|
||||
}
|
||||
else if (fileName.EndsWith("_regexs"))
|
||||
else if (fileName.EndsWith("translation_regexs"))
|
||||
{
|
||||
LoadTranslationRegexs(jsonString);
|
||||
}
|
||||
else if (fileName.EndsWith("customlevel_strings"))
|
||||
{
|
||||
LoadCustomLevelStrings(jsonString);
|
||||
}
|
||||
else if (fileName.EndsWith("customlevel_regexs"))
|
||||
{
|
||||
LoadCustomLevelRegexs(jsonString);
|
||||
}
|
||||
else if(fileName.EndsWith("tips_iz"))
|
||||
{
|
||||
LoadIZStrings(jsonString);
|
||||
|
|
@ -280,6 +319,24 @@ namespace PvZ_Fusion_Translator
|
|||
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)
|
||||
{
|
||||
var izDump = DumpIZStrings();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
//#if DEBUG
|
||||
using Il2Cpp;
|
||||
using Il2CppGameLevel;
|
||||
using PvZ_Fusion_Translator.AssetStore;
|
||||
using PvZ_Fusion_Translator.Patches.Modes.Super_Editor;
|
||||
using UnityEngine;
|
||||
|
|
@ -10,7 +12,8 @@ namespace PvZ_Fusion_Translator
|
|||
public enum ModType
|
||||
{
|
||||
ReloadStrings,
|
||||
ReloadTextures
|
||||
ReloadTextures,
|
||||
ExportLevelStrings
|
||||
}
|
||||
|
||||
private class ModFeature
|
||||
|
|
@ -43,13 +46,26 @@ namespace PvZ_Fusion_Translator
|
|||
Core.ShowToast("Textures Reloaded!");
|
||||
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()
|
||||
{
|
||||
{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);
|
||||
string godsGachaMatch = "";
|
||||
string superEditorPlantMatch = CheckSuperEditorPopup(originalText);
|
||||
string customLevelRegexMatch = CheckCustomLevelRegex(originalText);
|
||||
|
||||
switch(godsGachaCheck)
|
||||
{
|
||||
|
|
@ -119,7 +120,15 @@ namespace PvZ_Fusion_Translator.Patches.BaseTextObjects
|
|||
{
|
||||
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);
|
||||
if (txt.gameObject.name.Contains("main"))
|
||||
|
|
@ -348,5 +357,19 @@ namespace PvZ_Fusion_Translator.Patches.BaseTextObjects
|
|||
|
||||
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>())
|
||||
{
|
||||
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
|
||||
{
|
||||
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
|
||||
|
|
@ -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]
|
||||
public static void Awake(RuntimeNodeUI __instance)
|
||||
{
|
||||
if (!__instance.isActiveAndEnabled) return;
|
||||
|
||||
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
|
||||
|
||||
if(__instance.dropdownPrefab)
|
||||
|
|
@ -56,6 +58,8 @@ namespace PvZ_Fusion_Translator.Patches.Modes.Super_Editor.GameLevel.EventNodes
|
|||
[HarmonyPostfix]
|
||||
public static void UpdateDisplay(RuntimeNodeUI __instance)
|
||||
{
|
||||
if (!__instance.isActiveAndEnabled) return;
|
||||
|
||||
TMP_FontAsset fontAsset = FontStore.LoadTMPFont(Utils.Language.ToString());
|
||||
|
||||
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.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using HarmonyLib;
|
||||
using Il2Cpp;
|
||||
using Il2CppGameLevel;
|
||||
using PvZ_Fusion_Translator.AssetStore;
|
||||
using UnityEngine;
|
||||
|
||||
namespace PvZ_Fusion_Translator.Patches.Modes.Super_Editor.GameLevel
|
||||
|
|
@ -18,10 +22,259 @@ namespace PvZ_Fusion_Translator.Patches.Modes.Super_Editor.GameLevel
|
|||
[HarmonyPrefix]
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
//Filipino,
|
||||
Vietnamese,
|
||||
//Indonesian,
|
||||
Indonesian,
|
||||
//Russian, //NOTE: legacy language
|
||||
Japanese,
|
||||
|
||||
|
|
@ -574,6 +574,7 @@ namespace PvZ_Fusion_Translator
|
|||
{ LanguageEnum.German, "Deutsch"},
|
||||
{ LanguageEnum.Spanish, "Español"},
|
||||
{ LanguageEnum.Vietnamese, "Tiếng Việt"},
|
||||
{ LanguageEnum.Indonesian, "Bahasa Indonesia"},
|
||||
{ LanguageEnum.Japanese, "日本語"},
|
||||
{ LanguageEnum.Korean, "한국어"},
|
||||
{ LanguageEnum.Ukrainian, "українська"},
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue