mirror of
https://github.com/jie65535/GrasscutterCommandGenerator.git
synced 2026-05-07 21:07:57 +08:00
Improve TextMap loading to support multiple files
This commit is contained in:
@@ -30,6 +30,14 @@ namespace GrasscutterTools.Forms
|
|||||||
{
|
{
|
||||||
public partial class FormTextMapBrowser : Form
|
public partial class FormTextMapBrowser : Form
|
||||||
{
|
{
|
||||||
|
private static readonly Dictionary<string, string> LanguageDisplayNames = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
["zh-cn"] = "简体中文",
|
||||||
|
["zh-tw"] = "繁體中文",
|
||||||
|
["en-us"] = "English",
|
||||||
|
["ru-ru"] = "Русский",
|
||||||
|
};
|
||||||
|
|
||||||
public FormTextMapBrowser()
|
public FormTextMapBrowser()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
@@ -61,12 +69,21 @@ namespace GrasscutterTools.Forms
|
|||||||
}
|
}
|
||||||
|
|
||||||
CmbLanguage.Items.Clear();
|
CmbLanguage.Items.Clear();
|
||||||
CmbLanguage.Items.AddRange(data.TextMapFiles);
|
foreach (var lang in LanguageDisplayNames)
|
||||||
|
{
|
||||||
|
CmbLanguage.Items.Add($"{lang.Value} ({lang.Key})");
|
||||||
|
}
|
||||||
if (!string.IsNullOrEmpty(Settings.Default.TextMapFileName))
|
if (!string.IsNullOrEmpty(Settings.Default.TextMapFileName))
|
||||||
{
|
{
|
||||||
var i = CmbLanguage.Items.IndexOf(Settings.Default.TextMapFileName);
|
var i = CmbLanguage.Items.IndexOf(Settings.Default.TextMapFileName);
|
||||||
if (i != -1)
|
if (i != -1)
|
||||||
CmbLanguage.SelectedIndex = i;
|
CmbLanguage.SelectedIndex = i;
|
||||||
|
else
|
||||||
|
CmbLanguage.SelectedIndex = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CmbLanguage.SelectedIndex = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -100,10 +117,17 @@ namespace GrasscutterTools.Forms
|
|||||||
{
|
{
|
||||||
Cursor = Cursors.WaitCursor;
|
Cursor = Cursors.WaitCursor;
|
||||||
Application.DoEvents();
|
Application.DoEvents();
|
||||||
data.LoadTextMap(data.TextMapFilePaths[CmbLanguage.SelectedIndex]);
|
|
||||||
|
|
||||||
|
// 从显示名称中提取语言代码
|
||||||
|
var selectedText = CmbLanguage.Text;
|
||||||
|
var languageCode = LanguageDisplayNames.FirstOrDefault(kv => selectedText.Contains($"{kv.Value} ({kv.Key}")).Key;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(languageCode))
|
||||||
|
{
|
||||||
|
data.LoadTextMapByLanguage(languageCode);
|
||||||
GenLines();
|
GenLines();
|
||||||
Settings.Default.TextMapFileName = CmbLanguage.Text;
|
Settings.Default.TextMapFileName = selectedText;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -161,10 +161,10 @@ namespace GrasscutterTools.Game.Data
|
|||||||
|
|
||||||
private Dictionary<string, string> Languages = new Dictionary<string, string>
|
private Dictionary<string, string> Languages = new Dictionary<string, string>
|
||||||
{
|
{
|
||||||
["zh-cn"] = "TextMapCHS",
|
["zh-cn"] = "zh-cn",
|
||||||
["zh-tw"] = "TextMapCHT",
|
["zh-tw"] = "zh-tw",
|
||||||
["en-us"] = "TextMapEN",
|
["en-us"] = "en-us",
|
||||||
// ["ru-ru"] = "TextMapRU",
|
["ru-ru"] = "ru-ru",
|
||||||
};
|
};
|
||||||
|
|
||||||
public void ConvertResources(string projectResourcesDir)
|
public void ConvertResources(string projectResourcesDir)
|
||||||
@@ -176,7 +176,7 @@ namespace GrasscutterTools.Game.Data
|
|||||||
foreach (var language in Languages)
|
foreach (var language in Languages)
|
||||||
{
|
{
|
||||||
var dir = Path.Combine(projectResourcesDir, language.Key);
|
var dir = Path.Combine(projectResourcesDir, language.Key);
|
||||||
TextMapData.LoadTextMap(TextMapData.TextMapFilePaths[Array.IndexOf(TextMapData.TextMapFiles, language.Value)]);
|
TextMapData.LoadTextMapByLanguage(language.Value);
|
||||||
|
|
||||||
Thread.CurrentThread.CurrentUICulture = new CultureInfo(language.Key);
|
Thread.CurrentThread.CurrentUICulture = new CultureInfo(language.Key);
|
||||||
GameData.LoadResources();
|
GameData.LoadResources();
|
||||||
|
|||||||
@@ -28,11 +28,24 @@ namespace GrasscutterTools.Game
|
|||||||
{
|
{
|
||||||
internal class TextMapData
|
internal class TextMapData
|
||||||
{
|
{
|
||||||
|
// 语言代码到TextMap文件标识符的映射
|
||||||
|
// 匹配规则:文件名必须包含标识符,如 TextMapCHS.json, TextMap_MediumCHS.json, TextMapRU_0.json 等
|
||||||
|
private static readonly Dictionary<string, string[]> LanguageIdentifiers = new Dictionary<string, string[]>
|
||||||
|
{
|
||||||
|
["zh-cn"] = new[] { "CHS" },
|
||||||
|
["zh-tw"] = new[] { "CHT" },
|
||||||
|
["en-us"] = new[] { "EN" },
|
||||||
|
["ru-ru"] = new[] { "RU" },
|
||||||
|
};
|
||||||
|
|
||||||
|
private string _textMapDirPath;
|
||||||
|
|
||||||
public TextMapData(string resourcesDirPath)
|
public TextMapData(string resourcesDirPath)
|
||||||
{
|
{
|
||||||
LoadManualTextMap(Path.Combine(resourcesDirPath, "ExcelBinOutput", "ManualTextMapConfigData.json"));
|
LoadManualTextMap(Path.Combine(resourcesDirPath, "ExcelBinOutput", "ManualTextMapConfigData.json"));
|
||||||
LoadTextMaps(Path.Combine(resourcesDirPath, "TextMap"));
|
_textMapDirPath = Path.Combine(resourcesDirPath, "TextMap");
|
||||||
LoadTextMap(TextMapFilePaths[Array.IndexOf(TextMapFiles, "TextMapCHS")]);
|
LoadTextMaps(_textMapDirPath);
|
||||||
|
LoadTextMapByLanguage("zh-cn");
|
||||||
DefaultTextMap = TextMap;
|
DefaultTextMap = TextMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,24 +97,89 @@ namespace GrasscutterTools.Game
|
|||||||
TextMapFiles = TextMapFilePaths.Select(n => Path.GetFileNameWithoutExtension(n)).ToArray();
|
TextMapFiles = TextMapFilePaths.Select(n => Path.GetFileNameWithoutExtension(n)).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LoadTextMap(string textMapPath)
|
/// <summary>
|
||||||
|
/// 根据语言代码加载TextMap,自动匹配并合并所有相关文件
|
||||||
|
/// 匹配规则:文件名以"TextMap"开头,并包含对应的语言标识符
|
||||||
|
/// 例如:TextMapCHS.json, TextMap_MediumCHS.json, TextMapRU_0.json, TextMapRU_1.json
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="languageCode">语言代码,如 "zh-cn", "en-us", "ru-ru"</param>
|
||||||
|
public void LoadTextMapByLanguage(string languageCode)
|
||||||
{
|
{
|
||||||
using (var fs = File.OpenRead(textMapPath))
|
TextMap = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
if (!LanguageIdentifiers.ContainsKey(languageCode))
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Warning: Language code '{languageCode}' not found in LanguageIdentifiers, falling back to zh-cn");
|
||||||
|
languageCode = "zh-cn";
|
||||||
|
}
|
||||||
|
|
||||||
|
var identifiers = LanguageIdentifiers[languageCode];
|
||||||
|
var loadedFiles = new List<string>();
|
||||||
|
|
||||||
|
foreach (var identifier in identifiers)
|
||||||
|
{
|
||||||
|
// 查找所有包含该标识符的文件
|
||||||
|
// 例如:TextMap*CHS*.json 会匹配 TextMapCHS.json, TextMap_MediumCHS.json 等
|
||||||
|
var matchingFiles = TextMapFilePaths
|
||||||
|
.Where(f =>
|
||||||
|
{
|
||||||
|
var fileNameWithoutExt = Path.GetFileNameWithoutExtension(f);
|
||||||
|
return fileNameWithoutExt.StartsWith("TextMap") &&
|
||||||
|
fileNameWithoutExt.Contains(identifier);
|
||||||
|
})
|
||||||
|
.OrderBy(f => f) // 按文件名排序
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
foreach (var file in matchingFiles)
|
||||||
|
{
|
||||||
|
if (loadedFiles.Contains(file))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
LoadTextMapFile(file, TextMap);
|
||||||
|
loadedFiles.Add(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loadedFiles.Count == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Warning: No TextMap files found for language '{languageCode}' with identifiers: {string.Join(", ", identifiers)}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Loaded {loadedFiles.Count} TextMap file(s) for language '{languageCode}': {string.Join(", ", loadedFiles.Select(Path.GetFileName))}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 从单个文件加载TextMap并合并到目标字典
|
||||||
|
/// </summary>
|
||||||
|
private void LoadTextMapFile(string filePath, Dictionary<string, string> targetDict)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var fs = File.OpenRead(filePath))
|
||||||
using (var sr = new StreamReader(fs))
|
using (var sr = new StreamReader(fs))
|
||||||
using (var reader = new JsonTextReader(sr))
|
using (var reader = new JsonTextReader(sr))
|
||||||
{
|
{
|
||||||
TextMap = new Dictionary<string, string>();
|
|
||||||
while (reader.Read())
|
while (reader.Read())
|
||||||
{
|
{
|
||||||
if (reader.TokenType == JsonToken.PropertyName)
|
if (reader.TokenType == JsonToken.PropertyName)
|
||||||
{
|
{
|
||||||
TextMap.Add((string)reader.Value, reader.ReadAsString());
|
var key = (string)reader.Value;
|
||||||
|
var value = reader.ReadAsString();
|
||||||
|
|
||||||
|
// 如果key已存在,新值覆盖旧值(后加载的文件优先)
|
||||||
|
targetDict[key] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Error loading TextMap file '{filePath}': {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public bool Contains(string textMapPath) => TextMap.ContainsKey(textMapPath) || DefaultTextMap.ContainsKey(textMapPath);
|
|
||||||
|
|
||||||
public string GetText(string textMapHash)
|
public string GetText(string textMapHash)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -155,10 +155,10 @@ namespace GrasscutterTools.Pages
|
|||||||
|
|
||||||
TextMapData ??= new TextMapData(TxtGcResRoot.Text);
|
TextMapData ??= new TextMapData(TxtGcResRoot.Text);
|
||||||
|
|
||||||
UpdateActivityForLanguage(activityItems, "TextMapCHS", "zh-cn");
|
UpdateActivityForLanguage(activityItems, "zh-cn");
|
||||||
UpdateActivityForLanguage(activityItems, "TextMapCHT", "zh-tw");
|
UpdateActivityForLanguage(activityItems, "zh-tw");
|
||||||
UpdateActivityForLanguage(activityItems, "TextMapEN", "en-us");
|
UpdateActivityForLanguage(activityItems, "en-us");
|
||||||
// UpdateActivityForLanguage(activityItems, "TextMapRU", "ru-ru");
|
UpdateActivityForLanguage(activityItems, "ru-ru");
|
||||||
MessageBox.Show("OK", Resources.Tips, MessageBoxButtons.OK);
|
MessageBox.Show("OK", Resources.Tips, MessageBoxButtons.OK);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -167,10 +167,9 @@ namespace GrasscutterTools.Pages
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateActivityForLanguage(IReadOnlyCollection<NewActivityItem> activityItems, string textMap, string language)
|
private void UpdateActivityForLanguage(IReadOnlyCollection<NewActivityItem> activityItems, string languageCode)
|
||||||
{
|
{
|
||||||
var i = Array.IndexOf(TextMapData.TextMapFiles, textMap);
|
TextMapData.LoadTextMapByLanguage(languageCode);
|
||||||
TextMapData.LoadTextMap(TextMapData.TextMapFilePaths[i]);
|
|
||||||
|
|
||||||
var activityMap = new Dictionary<int, string>(activityItems.Count);
|
var activityMap = new Dictionary<int, string>(activityItems.Count);
|
||||||
foreach (var item in activityItems)
|
foreach (var item in activityItems)
|
||||||
@@ -186,21 +185,15 @@ namespace GrasscutterTools.Pages
|
|||||||
buffer.AppendLine(activityMap.TryGetValue(id, out var title) ? title : item.Value[id]);
|
buffer.AppendLine(activityMap.TryGetValue(id, out var title) ? title : item.Value[id]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var activityFilePath = Path.Combine(TxtProjectResRoot.Text, language, "Activity.txt");
|
var activityFilePath = Path.Combine(TxtProjectResRoot.Text, languageCode, "Activity.txt");
|
||||||
File.WriteAllText(activityFilePath, buffer.ToString(), Encoding.UTF8);
|
File.WriteAllText(activityFilePath, buffer.ToString(), Encoding.UTF8);
|
||||||
|
|
||||||
//File.WriteAllLines(
|
|
||||||
// activityFilePath,
|
|
||||||
// activityItems.Select(it => $"{it.ActivityId}:{TextMapData.GetText(it.NameTextMapHash)}"),
|
|
||||||
// Encoding.UTF8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void UpdateGachaResourceForLanguage(string textMap, string language)
|
private void UpdateGachaResourceForLanguage(string languageCode)
|
||||||
{
|
{
|
||||||
var i = Array.IndexOf(TextMapData.TextMapFiles, textMap);
|
TextMapData.LoadTextMapByLanguage(languageCode);
|
||||||
TextMapData.LoadTextMap(TextMapData.TextMapFilePaths[i]);
|
|
||||||
|
|
||||||
var titleBuffer = new StringBuilder();
|
var titleBuffer = new StringBuilder();
|
||||||
const string titlePattern = "UI_GACHA_SHOW_PANEL_([^_]+?)_TITLE";
|
const string titlePattern = "UI_GACHA_SHOW_PANEL_([^_]+?)_TITLE";
|
||||||
@@ -216,7 +209,7 @@ namespace GrasscutterTools.Pages
|
|||||||
.AppendLine(Regex.Replace(text, markPattern, ""));
|
.AppendLine(Regex.Replace(text, markPattern, ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
var titleFilePath = Path.Combine(TxtProjectResRoot.Text, language, "GachaBannerTitle.txt");
|
var titleFilePath = Path.Combine(TxtProjectResRoot.Text, languageCode, "GachaBannerTitle.txt");
|
||||||
File.WriteAllText(titleFilePath, titleBuffer.ToString(), Encoding.UTF8);
|
File.WriteAllText(titleFilePath, titleBuffer.ToString(), Encoding.UTF8);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -229,10 +222,10 @@ namespace GrasscutterTools.Pages
|
|||||||
|
|
||||||
TextMapData ??= new TextMapData(TxtGcResRoot.Text);
|
TextMapData ??= new TextMapData(TxtGcResRoot.Text);
|
||||||
|
|
||||||
UpdateGachaResourceForLanguage("TextMapCHS", "zh-cn");
|
UpdateGachaResourceForLanguage("zh-cn");
|
||||||
UpdateGachaResourceForLanguage("TextMapCHT", "zh-tw");
|
UpdateGachaResourceForLanguage("zh-tw");
|
||||||
UpdateGachaResourceForLanguage("TextMapEN", "en-us");
|
UpdateGachaResourceForLanguage("en-us");
|
||||||
// UpdateGachaResourceForLanguage("TextMapRU", "ru-ru");
|
UpdateGachaResourceForLanguage("ru-ru");
|
||||||
MessageBox.Show("OK", Resources.Tips, MessageBoxButtons.OK);
|
MessageBox.Show("OK", Resources.Tips, MessageBoxButtons.OK);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
Reference in New Issue
Block a user