private int GetChunkCount(string filename) { if (!File.Exists(filename)) { throw new FileNotFoundException("指定されたmcaファイルが見つかりません。"); } using (RegionFileAccess.RegionFile rf = new RegionFileAccess.RegionFile(filename)) { rf.LoadFile(); int chunkNum = 0; for (int i = 0; i < rf.ChunkData.Count; i++) { // 未使用チャンクはnullになってる if (null != rf.ChunkData[i]) { chunkNum++; } if (i % 32 == 0) { System.Threading.Thread.Sleep(1); } } return(chunkNum); } }
private void chunkConvertWorker_DoWork(object sender, DoWorkEventArgs e) { // 出力先ディレクトリチェック if (Directory.Exists(outputPath.Text)) { DialogResult result = MessageBox.Show("出力先ディレクトリを上書きします。", "確認", MessageBoxButtons.OKCancel); if (result != System.Windows.Forms.DialogResult.OK) { return; } } else { Directory.CreateDirectory(outputPath.Text); } // 総チャンク数をプログレスバーの最大値にセット if (chunkConvertProgressBar.InvokeRequired) { chunkConvertProgressBar.Invoke((Action)(() => { chunkConvertProgressBar.Maximum = int.Parse(chunkCount.Text); inputPath.Enabled = false; inputRef.Enabled = false; outputPath.Enabled = false; outputRef.Enabled = false; startFix.Visible = false; chunkConvertProgressBar.Visible = true; })); } // level.datのPlayerデータを書き換え FixPlayerSackData(inputPath.Text + "\\level.dat", InputToOutputPath(inputPath.Text + "\\level.dat"), "//Data/Player/Inventory"); // Playerフォルダの個別データを書き換え Directory.CreateDirectory(outputPath.Text + "\\players"); foreach (string playerFile in Directory.GetFiles(inputPath.Text + "\\players", "*.dat")) { FixPlayerSackData(playerFile, InputToOutputPath(playerFile), "//Inventory"); } // 処理済みチャンク数 int fixChunkNum = 0; // 袋のID int itemSackId = int.Parse(itemSackID.Text); foreach (string regionDir in Directory.GetDirectories(inputPath.Text, "region")) { // 出力先regionフォルダの作成 Directory.CreateDirectory(InputToOutputPath(regionDir)); foreach (string mcaFile in Directory.GetFiles(regionDir, "*.mca")) { using (RegionFileAccess.RegionFile rf = new RegionFileAccess.RegionFile(mcaFile)) { rf.LoadFile(); for (int i = 0; i < rf.ChunkData.Count; i++) { if (null != rf.ChunkData[i]) { fNbt.NbtCompound nbtRoot = rf.ChunkData[i].GetRootNBT(); #if DEBUG using (StreamWriter sw = new StreamWriter(InputToOutputPath(mcaFile) + "_nbt_" + i + ".txt", false, Encoding.UTF8)) { sw.Write(nbtRoot.ToString()); } #endif // TileEntities差し替え fNbt.NbtList tileEntities = fNbt.NbtQuery.Get <fNbt.NbtList>(nbtRoot, "//Level/TileEntities"); foreach (fNbt.NbtCompound tileEntity in tileEntities) { fNbt.NbtList items; if (tileEntity.TryGet <fNbt.NbtList>("Items", out items)) { foreach (fNbt.NbtCompound item in items) { FixItemSackData(item, itemSackId); } } } // Entities差し替え fNbt.NbtList entities = fNbt.NbtQuery.Get <fNbt.NbtList>(nbtRoot, "//Level/Entities"); foreach (fNbt.NbtCompound entity in entities) { fNbt.NbtList items; // チェストトロッコ等のインベントリ if (entity.TryGet <fNbt.NbtList>("Items", out items)) { foreach (fNbt.NbtCompound item in items) { FixItemSackData(item, itemSackId); } } fNbt.NbtCompound tag; // ドロップアイテム if (entity.TryGet <fNbt.NbtCompound>("Item", out tag)) { FixItemSackData(tag, itemSackId); } } // チャンクデータ更新 rf.ChunkData[i].SetRootNbt(nbtRoot); chunkConvertWorker.ReportProgress(++fixChunkNum); } if (i % 16 == 0) { System.Threading.Thread.Sleep(2); } } rf.SaveFile(InputToOutputPath(mcaFile)); } } } }