using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using MCI18n.Models; using MCI18n.Utilities; using Microsoft.Win32; using SharpNBT; using SharpNBT.SNBT; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; namespace MCI18n { public partial class MainWindowViewModel : ObservableObject { private List _oriQuestsData; private List _updatedChapters; private List _langs; [ObservableProperty] private ObservableCollection _chapters; [ObservableProperty] private ObservableCollection _selectedQuests; [ObservableProperty] private bool _loading = false; [RelayCommand] private void LoadQuests() { var openFolderDialog = new OpenFolderDialog { Title = "选择ftbquests文件夹", Multiselect = false }; if (openFolderDialog.ShowDialog() == true) { try { var folderPath = openFolderDialog.FolderName; GlobalContext.MultipleLangSupport = Path.Exists(Path.Combine(folderPath, "quests", "lang")); if (GlobalContext.MultipleLangSupport) { var enLangFile = Path.Combine(folderPath, "quests", "lang", "en_us.snbt"); var langData = StringNbt.Parse(File.ReadAllText(enLangFile)); _langs = []; foreach (var item in langData) { var langKeys = item.Name.Split('.'); var langItem = new QuestLangModel { Type = langKeys[0], Id = langKeys[1], DocType = langKeys[2], }; if (item is StringTag langTag) { langItem.Value = langTag.Value; } else if(item is ListTag valueList) { var descList = new StringBuilder(); foreach (var value in valueList) { descList.AppendLine((value as StringTag).Value); } langItem.Value = descList.ToString(); } _langs.Add(langItem); } } if(_langs != null) { var windowTitle = "FTB Quests Editor - " + _langs.FirstOrDefault(it => it.Type == "file" && it.Id == "0000000000000001" && it.DocType == "title").Value; Application.Current.MainWindow.Title = windowTitle; } if (Path.Exists(Path.Combine(folderPath, "quests", "chapters"))) { var fullQuestsPath = Path.Combine(folderPath, "quests", "chapters"); var questFiles = Directory.GetFiles(fullQuestsPath, "*.snbt", SearchOption.AllDirectories); _oriQuestsData = new List(); _updatedChapters = new List(); Chapters = new ObservableCollection(); foreach (var file in questFiles) { var questData = StringNbt.Parse(File.ReadAllText(file)); _oriQuestsData.Add(questData); var chapterId = (questData["id"] as StringTag)?.Value; var chapterName = (questData["filename"] as StringTag)?.Value ; var chapterTitle = questData.ContainsKey("title") ? (questData["title"] as StringTag)?.Value : ""; var chapter = new ChapterModel { Id = chapterId, Name = chapterName, Title = chapterTitle }; if (GlobalContext.MultipleLangSupport) { chapter.Title = GetMutliLang("chapter",chapter.Id, "title"); } Chapters.Add(chapter); var quests = questData["quests"]; if(quests is ListTag questList) { foreach (var item in questList) { if (item is CompoundTag questTag) { var questId = (questTag["id"] as StringTag)?.Value; var questTitle = ""; if (questTag.ContainsKey("title")) { questTitle = (questTag["title"] as StringTag)?.Value ?? ""; } else if (GlobalContext.MultipleLangSupport) { questTitle = GetMutliLang("quest", questId, "title"); } var questSubTitle = ""; if (questTag.ContainsKey("subtitle")) { questSubTitle = (questTag["subtitle"] as StringTag)?.Value ?? ""; } else if (GlobalContext.MultipleLangSupport) { questSubTitle = GetMutliLang("quest", questId, "quest_subtitle"); } var questDescriptions = new StringBuilder(); if (questTag.ContainsKey("description")) { if (questTag["description"] is ListTag descriptions) { foreach (var desc in descriptions) { questDescriptions.AppendLine((desc as StringTag)?.Value); } } } else if (GlobalContext.MultipleLangSupport) { var desc = GetMutliLang("quest", questId, "quest_desc"); questDescriptions.AppendLine(desc); } var questModel = new QuestModel { Id = questId, Title = questTitle, SubTitle = questSubTitle, Description = questDescriptions.ToString() }; chapter.Quests.Add(questModel); } } } } SelectedQuests = Chapters.First()?.Quests ?? []; } else { MessageBox.Show("文件夹选择错误!"); } //var questData = StringNbt.Parse(File.ReadAllText(CurrentFilePath)); //SnbtWriter.SaveToFile(questData, CurrentFilePath + ".r", prettyPrint: true); } catch (Exception ex) { MessageBox.Show($"加载文件失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error); } } } [RelayCommand] private void SaveQuest() { } [RelayCommand] private void SaveQuestAs() { if (GlobalContext.MultipleLangSupport) { /// 另存为多语言文件 var saveFileDialog = new SaveFileDialog { Title = "保存多语言文件", Filter = "SNBT 文件 (*.snbt)|*.snbt", FileName = "zh_cn.snbt", }; if (saveFileDialog.ShowDialog() == true) { try { var filePath = saveFileDialog.FileName; var langData = new CompoundTag(""); foreach (var chapter in Chapters) { langData.Add(new StringTag($"chapter.{chapter.Id}.title", chapter.Title)); if (chapter.Quests != null) { foreach (var quest in chapter.Quests) { langData.Add(new StringTag($"quest.{quest.Id}.title", quest.Title)); langData.Add(new StringTag($"quest.{quest.Id}.quest_subtitle", quest.SubTitle)); var descLines = quest.Description.Split(new[] { Environment.NewLine }, StringSplitOptions.None); var descList = new ListTag($"quest.{quest.Id}.quest_desc",TagType.String); foreach (var line in descLines) { descList.Add(new StringTag(null, line)); } langData.Add(descList); } } } SnbtWriter.SaveToFile(langData, filePath, prettyPrint: true); MessageBox.Show("多语言文件保存成功!", "成功", MessageBoxButton.OK, MessageBoxImage.Information); } catch (Exception ex) { MessageBox.Show($"保存文件失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error); } } } } [RelayCommand] private void CreateNewQuest() { } internal void ChapterSelectionChanged(ChapterModel selectedChapter) { if (selectedChapter != null && selectedChapter.Quests != null) { SelectedQuests = selectedChapter.Quests; } else { SelectedQuests = []; } } private string GetMutliLang(string type,string id,string docType) { return _langs?.FirstOrDefault(it => it.Type == type && it.Id == id && it.DocType == docType)?.Value ?? ""; } } }