|
|
|
@ -50,111 +50,113 @@ public class WorldConverterMCA {
|
|
|
|
|
folderName += "_";
|
|
|
|
|
worldDir = EaglerIntegratedServerWorker.saveFormat.getSaveLoader(folderName, false).getWorldDirectory();
|
|
|
|
|
}
|
|
|
|
|
ZipInputStream zis = new ZipInputStream(new EaglerInputStream(archiveContents));
|
|
|
|
|
ZipEntry folderNameFile = null;
|
|
|
|
|
List<char[]> fileNames = new ArrayList<>();
|
|
|
|
|
while((folderNameFile = zis.getNextEntry()) != null) {
|
|
|
|
|
if (folderNameFile.getName().contains("__MACOSX/")) continue;
|
|
|
|
|
if (folderNameFile.isDirectory()) continue;
|
|
|
|
|
String lowerName = folderNameFile.getName().toLowerCase();
|
|
|
|
|
if (!(lowerName.endsWith(".dat") || lowerName.endsWith(".dat_old") || lowerName.endsWith(".mca") || lowerName.endsWith(".mcr"))) continue;
|
|
|
|
|
fileNames.add(folderNameFile.getName().toCharArray());
|
|
|
|
|
try(ZipInputStream zis = new ZipInputStream(new EaglerInputStream(archiveContents))) {
|
|
|
|
|
ZipEntry folderNameFile = null;
|
|
|
|
|
while((folderNameFile = zis.getNextEntry()) != null) {
|
|
|
|
|
if (folderNameFile.getName().contains("__MACOSX/")) continue;
|
|
|
|
|
if (folderNameFile.isDirectory()) continue;
|
|
|
|
|
String lowerName = folderNameFile.getName().toLowerCase();
|
|
|
|
|
if (!(lowerName.endsWith(".dat") || lowerName.endsWith(".dat_old") || lowerName.endsWith(".mca") || lowerName.endsWith(".mcr"))) continue;
|
|
|
|
|
fileNames.add(folderNameFile.getName().toCharArray());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
final int[] i = new int[] { 0 };
|
|
|
|
|
while(fileNames.get(0).length > i[0] && fileNames.stream().allMatch(w -> w[i[0]] == fileNames.get(0)[i[0]])) i[0]++;
|
|
|
|
|
int folderPrefixOffset = i[0];
|
|
|
|
|
zis = new ZipInputStream(new EaglerInputStream(archiveContents));
|
|
|
|
|
ZipEntry f = null;
|
|
|
|
|
int lastProgUpdate = 0;
|
|
|
|
|
int prog = 0;
|
|
|
|
|
byte[] bb = new byte[16384];
|
|
|
|
|
while ((f = zis.getNextEntry()) != null) {
|
|
|
|
|
if (f.getName().contains("__MACOSX/")) continue;
|
|
|
|
|
if (f.isDirectory()) continue;
|
|
|
|
|
String lowerName = f.getName().toLowerCase();
|
|
|
|
|
if (!(lowerName.endsWith(".dat") || lowerName.endsWith(".dat_old") || lowerName.endsWith(".mca") || lowerName.endsWith(".mcr") || lowerName.endsWith(".bmp"))) continue;
|
|
|
|
|
EaglerOutputStream baos = new EaglerOutputStream();
|
|
|
|
|
int len;
|
|
|
|
|
while ((len = zis.read(bb)) != -1) {
|
|
|
|
|
baos.write(bb, 0, len);
|
|
|
|
|
}
|
|
|
|
|
baos.close();
|
|
|
|
|
byte[] b = baos.toByteArray();
|
|
|
|
|
String fileName = f.getName().substring(folderPrefixOffset);
|
|
|
|
|
if (fileName.equals("level.dat") || fileName.equals("level.dat_old")) {
|
|
|
|
|
NBTTagCompound worldDatNBT = CompressedStreamTools.readCompressed(new EaglerInputStream(b));
|
|
|
|
|
|
|
|
|
|
NBTTagCompound gameRulesNBT = worldDatNBT.getCompoundTag("Data").getCompoundTag("GameRules");
|
|
|
|
|
gameRulesNBT.setString("loadSpawnChunks", (gameRules & 2) != 0 ? "true" : "false");
|
|
|
|
|
String s = (gameRules & 1) != 0 ? "true" : "false";
|
|
|
|
|
gameRulesNBT.setString("bedSpawnPoint", s);
|
|
|
|
|
gameRulesNBT.setString("clickToRide", "false");
|
|
|
|
|
gameRulesNBT.setString("clickToSit", s);
|
|
|
|
|
gameRulesNBT.setString("colorCodes", s);
|
|
|
|
|
gameRulesNBT.setString("doSignEditing", s);
|
|
|
|
|
worldDatNBT.getCompoundTag("Data").setTag("GameRules", gameRulesNBT);
|
|
|
|
|
|
|
|
|
|
worldDatNBT.getCompoundTag("Data").setString("LevelName", newName);
|
|
|
|
|
worldDatNBT.getCompoundTag("Data").setLong("LastPlayed", System.currentTimeMillis());
|
|
|
|
|
EaglerOutputStream bo = new EaglerOutputStream();
|
|
|
|
|
CompressedStreamTools.writeCompressed(worldDatNBT, bo);
|
|
|
|
|
b = bo.toByteArray();
|
|
|
|
|
VFile2 ff = new VFile2(worldDir, fileName);
|
|
|
|
|
ff.setAllBytes(b);
|
|
|
|
|
prog += b.length;
|
|
|
|
|
} else if ((fileName.endsWith(".mcr") || fileName.endsWith(".mca")) && (fileName.startsWith("region/") || fileName.startsWith("DIM1/region/") || fileName.startsWith("DIM-1/region/"))) {
|
|
|
|
|
VFile2 chunkFolder = new VFile2(worldDir, fileName.startsWith("DIM1") ? "level1" : (fileName.startsWith("DIM-1") ? "level-1" : "level0"));
|
|
|
|
|
RegionFile mca = new RegionFile(new RandomAccessMemoryFile(b, b.length));
|
|
|
|
|
int loadChunksCount = 0;
|
|
|
|
|
for(int j = 0; j < 32; ++j) {
|
|
|
|
|
for(int k = 0; k < 32; ++k) {
|
|
|
|
|
if(mca.isChunkSaved(j, k)) {
|
|
|
|
|
NBTTagCompound chunkNBT;
|
|
|
|
|
NBTTagCompound chunkLevel;
|
|
|
|
|
try {
|
|
|
|
|
chunkNBT = CompressedStreamTools.read(mca.getChunkDataInputStream(j, k));
|
|
|
|
|
if(!chunkNBT.hasKey("Level", 10)) {
|
|
|
|
|
throw new IOException("Chunk is missing level data!");
|
|
|
|
|
try(ZipInputStream zis = new ZipInputStream(new EaglerInputStream(archiveContents))) {
|
|
|
|
|
ZipEntry f = null;
|
|
|
|
|
int lastProgUpdate = 0;
|
|
|
|
|
int prog = 0;
|
|
|
|
|
byte[] bb = new byte[16384];
|
|
|
|
|
while ((f = zis.getNextEntry()) != null) {
|
|
|
|
|
if (f.getName().contains("__MACOSX/")) continue;
|
|
|
|
|
if (f.isDirectory()) continue;
|
|
|
|
|
String lowerName = f.getName().toLowerCase();
|
|
|
|
|
if (!(lowerName.endsWith(".dat") || lowerName.endsWith(".dat_old") || lowerName.endsWith(".mca") || lowerName.endsWith(".mcr") || lowerName.endsWith(".bmp"))) continue;
|
|
|
|
|
EaglerOutputStream baos = new EaglerOutputStream();
|
|
|
|
|
int len;
|
|
|
|
|
while ((len = zis.read(bb)) != -1) {
|
|
|
|
|
baos.write(bb, 0, len);
|
|
|
|
|
}
|
|
|
|
|
baos.close();
|
|
|
|
|
byte[] b = baos.toByteArray();
|
|
|
|
|
String fileName = f.getName().substring(folderPrefixOffset);
|
|
|
|
|
if (fileName.equals("level.dat") || fileName.equals("level.dat_old")) {
|
|
|
|
|
NBTTagCompound worldDatNBT = CompressedStreamTools.readCompressed(new EaglerInputStream(b));
|
|
|
|
|
|
|
|
|
|
NBTTagCompound gameRulesNBT = worldDatNBT.getCompoundTag("Data").getCompoundTag("GameRules");
|
|
|
|
|
gameRulesNBT.setString("loadSpawnChunks", (gameRules & 2) != 0 ? "true" : "false");
|
|
|
|
|
String s = (gameRules & 1) != 0 ? "true" : "false";
|
|
|
|
|
gameRulesNBT.setString("bedSpawnPoint", s);
|
|
|
|
|
gameRulesNBT.setString("clickToRide", "false");
|
|
|
|
|
gameRulesNBT.setString("clickToSit", s);
|
|
|
|
|
gameRulesNBT.setString("colorCodes", s);
|
|
|
|
|
gameRulesNBT.setString("doSignEditing", s);
|
|
|
|
|
worldDatNBT.getCompoundTag("Data").setTag("GameRules", gameRulesNBT);
|
|
|
|
|
|
|
|
|
|
worldDatNBT.getCompoundTag("Data").setString("LevelName", newName);
|
|
|
|
|
worldDatNBT.getCompoundTag("Data").setLong("LastPlayed", System.currentTimeMillis());
|
|
|
|
|
EaglerOutputStream bo = new EaglerOutputStream();
|
|
|
|
|
CompressedStreamTools.writeCompressed(worldDatNBT, bo);
|
|
|
|
|
b = bo.toByteArray();
|
|
|
|
|
VFile2 ff = new VFile2(worldDir, fileName);
|
|
|
|
|
ff.setAllBytes(b);
|
|
|
|
|
prog += b.length;
|
|
|
|
|
} else if ((fileName.endsWith(".mcr") || fileName.endsWith(".mca")) && (fileName.startsWith("region/") || fileName.startsWith("DIM1/region/") || fileName.startsWith("DIM-1/region/"))) {
|
|
|
|
|
VFile2 chunkFolder = new VFile2(worldDir, fileName.startsWith("DIM1") ? "level1" : (fileName.startsWith("DIM-1") ? "level-1" : "level0"));
|
|
|
|
|
RegionFile mca = new RegionFile(new RandomAccessMemoryFile(b, b.length));
|
|
|
|
|
int loadChunksCount = 0;
|
|
|
|
|
for(int j = 0; j < 32; ++j) {
|
|
|
|
|
for(int k = 0; k < 32; ++k) {
|
|
|
|
|
if(mca.isChunkSaved(j, k)) {
|
|
|
|
|
NBTTagCompound chunkNBT;
|
|
|
|
|
NBTTagCompound chunkLevel;
|
|
|
|
|
try {
|
|
|
|
|
chunkNBT = CompressedStreamTools.read(mca.getChunkDataInputStream(j, k));
|
|
|
|
|
if(!chunkNBT.hasKey("Level", 10)) {
|
|
|
|
|
throw new IOException("Chunk is missing level data!");
|
|
|
|
|
}
|
|
|
|
|
chunkLevel = chunkNBT.getCompoundTag("Level");
|
|
|
|
|
}catch(Throwable t) {
|
|
|
|
|
logger.error("{}: Could not read chunk: {}, {}", fileName, j, k);
|
|
|
|
|
logger.error(t);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
chunkLevel = chunkNBT.getCompoundTag("Level");
|
|
|
|
|
}catch(Throwable t) {
|
|
|
|
|
logger.error("{}: Could not read chunk: {}, {}", fileName, j, k);
|
|
|
|
|
logger.error(t);
|
|
|
|
|
continue;
|
|
|
|
|
int chunkX = chunkLevel.getInteger("xPos");
|
|
|
|
|
int chunkZ = chunkLevel.getInteger("zPos");
|
|
|
|
|
VFile2 chunkOut = new VFile2(chunkFolder, EaglerChunkLoader.getChunkPath(chunkX, chunkZ) + ".dat");
|
|
|
|
|
if(chunkOut.exists()) {
|
|
|
|
|
logger.error("{}: Chunk already exists: {}", fileName, chunkOut.getPath());
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
EaglerOutputStream bao = new EaglerOutputStream();
|
|
|
|
|
CompressedStreamTools.writeCompressed(chunkNBT, bao);
|
|
|
|
|
b = bao.toByteArray();
|
|
|
|
|
chunkOut.setAllBytes(b);
|
|
|
|
|
prog += b.length;
|
|
|
|
|
if (prog - lastProgUpdate > 25000) {
|
|
|
|
|
lastProgUpdate = prog;
|
|
|
|
|
EaglerIntegratedServerWorker.sendProgress("singleplayer.busy.importing.2", prog);
|
|
|
|
|
}
|
|
|
|
|
++loadChunksCount;
|
|
|
|
|
}
|
|
|
|
|
int chunkX = chunkLevel.getInteger("xPos");
|
|
|
|
|
int chunkZ = chunkLevel.getInteger("zPos");
|
|
|
|
|
VFile2 chunkOut = new VFile2(chunkFolder, EaglerChunkLoader.getChunkPath(chunkX, chunkZ) + ".dat");
|
|
|
|
|
if(chunkOut.exists()) {
|
|
|
|
|
logger.error("{}: Chunk already exists: {}", fileName, chunkOut.getPath());
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
EaglerOutputStream bao = new EaglerOutputStream();
|
|
|
|
|
CompressedStreamTools.writeCompressed(chunkNBT, bao);
|
|
|
|
|
b = bao.toByteArray();
|
|
|
|
|
chunkOut.setAllBytes(b);
|
|
|
|
|
prog += b.length;
|
|
|
|
|
if (prog - lastProgUpdate > 25000) {
|
|
|
|
|
lastProgUpdate = prog;
|
|
|
|
|
EaglerIntegratedServerWorker.sendProgress("singleplayer.busy.importing.2", prog);
|
|
|
|
|
}
|
|
|
|
|
++loadChunksCount;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
logger.info("{}: Imported {} chunks successfully ({} bytes)", fileName, loadChunksCount, prog);
|
|
|
|
|
} else if (fileName.startsWith("playerdata/") || fileName.startsWith("stats/")) {
|
|
|
|
|
//TODO: LAN player inventories
|
|
|
|
|
} else if (fileName.startsWith("data/") || fileName.startsWith("players/") || fileName.startsWith("eagler/skulls/")) {
|
|
|
|
|
VFile2 ff = new VFile2(worldDir, fileName);
|
|
|
|
|
ff.setAllBytes(b);
|
|
|
|
|
prog += b.length;
|
|
|
|
|
} else if (!fileName.equals("level.dat_mcr") && !fileName.equals("session.lock")) {
|
|
|
|
|
logger.info("Skipping file: {}", fileName);
|
|
|
|
|
}
|
|
|
|
|
if (prog - lastProgUpdate > 25000) {
|
|
|
|
|
lastProgUpdate = prog;
|
|
|
|
|
EaglerIntegratedServerWorker.sendProgress("singleplayer.busy.importing.2", prog);
|
|
|
|
|
}
|
|
|
|
|
logger.info("{}: Imported {} chunks successfully ({} bytes)", fileName, loadChunksCount, prog);
|
|
|
|
|
} else if (fileName.startsWith("playerdata/") || fileName.startsWith("stats/")) {
|
|
|
|
|
//TODO: LAN player inventories
|
|
|
|
|
} else if (fileName.startsWith("data/") || fileName.startsWith("players/") || fileName.startsWith("eagler/skulls/")) {
|
|
|
|
|
VFile2 ff = new VFile2(worldDir, fileName);
|
|
|
|
|
ff.setAllBytes(b);
|
|
|
|
|
prog += b.length;
|
|
|
|
|
} else if (!fileName.equals("level.dat_mcr") && !fileName.equals("session.lock")) {
|
|
|
|
|
logger.info("Skipping file: {}", fileName);
|
|
|
|
|
}
|
|
|
|
|
if (prog - lastProgUpdate > 25000) {
|
|
|
|
|
lastProgUpdate = prog;
|
|
|
|
|
EaglerIntegratedServerWorker.sendProgress("singleplayer.busy.importing.2", prog);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
logger.info("MCA was successfully extracted into directory \"{}\"", worldDir.getPath());
|
|
|
|
@ -172,129 +174,130 @@ public class WorldConverterMCA {
|
|
|
|
|
|
|
|
|
|
public static byte[] exportWorld(String folderName) throws IOException {
|
|
|
|
|
EaglerOutputStream bao = new EaglerOutputStream();
|
|
|
|
|
ZipOutputStream zos = new ZipOutputStream(bao);
|
|
|
|
|
zos.setComment("contains backup of world '" + folderName + "'");
|
|
|
|
|
VFile2 worldFolder = EaglerIntegratedServerWorker.saveFormat.getSaveLoader(folderName, false).getWorldDirectory();
|
|
|
|
|
logger.info("Exporting world directory \"{}\" as MCA", worldFolder.getPath());
|
|
|
|
|
VFile2 vf = new VFile2(worldFolder, "level.dat");
|
|
|
|
|
byte[] b;
|
|
|
|
|
int lastProgUpdate = 0;
|
|
|
|
|
int prog = 0;
|
|
|
|
|
boolean safe = false;
|
|
|
|
|
if(vf.exists()) {
|
|
|
|
|
zos.putNextEntry(new ZipEntry(folderName + "/level.dat"));
|
|
|
|
|
b = vf.getAllBytes();
|
|
|
|
|
zos.write(b);
|
|
|
|
|
prog += b.length;
|
|
|
|
|
safe = true;
|
|
|
|
|
}
|
|
|
|
|
vf = new VFile2(worldFolder, "level.dat_old");
|
|
|
|
|
if(vf.exists()) {
|
|
|
|
|
zos.putNextEntry(new ZipEntry(folderName + "/level.dat_old"));
|
|
|
|
|
b = vf.getAllBytes();
|
|
|
|
|
zos.write(b);
|
|
|
|
|
prog += b.length;
|
|
|
|
|
safe = true;
|
|
|
|
|
}
|
|
|
|
|
if (prog - lastProgUpdate > 25000) {
|
|
|
|
|
lastProgUpdate = prog;
|
|
|
|
|
EaglerIntegratedServerWorker.sendProgress("singleplayer.busy.exporting.2", prog);
|
|
|
|
|
}
|
|
|
|
|
String[] srcFolderNames = new String[] { "level0", "level-1", "level1" };
|
|
|
|
|
String[] dstFolderNames = new String[] { "/region/", "/DIM-1/region/", "/DIM1/region/" };
|
|
|
|
|
List<VFile2> fileList;
|
|
|
|
|
for(int i = 0; i < 3; ++i) {
|
|
|
|
|
vf = new VFile2(worldFolder, srcFolderNames[i]);
|
|
|
|
|
fileList = vf.listFiles(true);
|
|
|
|
|
String regionFolder = folderName + dstFolderNames[i];
|
|
|
|
|
logger.info("Converting chunks in \"{}\" as MCA to \"{}\"...", vf.getPath(), regionFolder);
|
|
|
|
|
Map<String,RegionFile> regionFiles = new HashMap();
|
|
|
|
|
for(int k = 0, l = fileList.size(); k < l; ++k) {
|
|
|
|
|
VFile2 chunkFile = fileList.get(k);
|
|
|
|
|
NBTTagCompound chunkNBT;
|
|
|
|
|
NBTTagCompound chunkLevel;
|
|
|
|
|
try {
|
|
|
|
|
b = chunkFile.getAllBytes();
|
|
|
|
|
chunkNBT = CompressedStreamTools.readCompressed(new EaglerInputStream(b));
|
|
|
|
|
if(!chunkNBT.hasKey("Level", 10)) {
|
|
|
|
|
throw new IOException("Chunk is missing level data!");
|
|
|
|
|
VFile2 worldFolder;
|
|
|
|
|
try(ZipOutputStream zos = new ZipOutputStream(bao)) {
|
|
|
|
|
zos.setComment("contains backup of world '" + folderName + "'");
|
|
|
|
|
worldFolder = EaglerIntegratedServerWorker.saveFormat.getSaveLoader(folderName, false).getWorldDirectory();
|
|
|
|
|
logger.info("Exporting world directory \"{}\" as MCA", worldFolder.getPath());
|
|
|
|
|
VFile2 vf = new VFile2(worldFolder, "level.dat");
|
|
|
|
|
byte[] b;
|
|
|
|
|
int lastProgUpdate = 0;
|
|
|
|
|
int prog = 0;
|
|
|
|
|
boolean safe = false;
|
|
|
|
|
if(vf.exists()) {
|
|
|
|
|
zos.putNextEntry(new ZipEntry(folderName + "/level.dat"));
|
|
|
|
|
b = vf.getAllBytes();
|
|
|
|
|
zos.write(b);
|
|
|
|
|
prog += b.length;
|
|
|
|
|
safe = true;
|
|
|
|
|
}
|
|
|
|
|
vf = new VFile2(worldFolder, "level.dat_old");
|
|
|
|
|
if(vf.exists()) {
|
|
|
|
|
zos.putNextEntry(new ZipEntry(folderName + "/level.dat_old"));
|
|
|
|
|
b = vf.getAllBytes();
|
|
|
|
|
zos.write(b);
|
|
|
|
|
prog += b.length;
|
|
|
|
|
safe = true;
|
|
|
|
|
}
|
|
|
|
|
if (prog - lastProgUpdate > 25000) {
|
|
|
|
|
lastProgUpdate = prog;
|
|
|
|
|
EaglerIntegratedServerWorker.sendProgress("singleplayer.busy.exporting.2", prog);
|
|
|
|
|
}
|
|
|
|
|
String[] srcFolderNames = new String[] { "level0", "level-1", "level1" };
|
|
|
|
|
String[] dstFolderNames = new String[] { "/region/", "/DIM-1/region/", "/DIM1/region/" };
|
|
|
|
|
List<VFile2> fileList;
|
|
|
|
|
for(int i = 0; i < 3; ++i) {
|
|
|
|
|
vf = new VFile2(worldFolder, srcFolderNames[i]);
|
|
|
|
|
fileList = vf.listFiles(true);
|
|
|
|
|
String regionFolder = folderName + dstFolderNames[i];
|
|
|
|
|
logger.info("Converting chunks in \"{}\" as MCA to \"{}\"...", vf.getPath(), regionFolder);
|
|
|
|
|
Map<String,RegionFile> regionFiles = new HashMap();
|
|
|
|
|
for(int k = 0, l = fileList.size(); k < l; ++k) {
|
|
|
|
|
VFile2 chunkFile = fileList.get(k);
|
|
|
|
|
NBTTagCompound chunkNBT;
|
|
|
|
|
NBTTagCompound chunkLevel;
|
|
|
|
|
try {
|
|
|
|
|
b = chunkFile.getAllBytes();
|
|
|
|
|
chunkNBT = CompressedStreamTools.readCompressed(new EaglerInputStream(b));
|
|
|
|
|
if(!chunkNBT.hasKey("Level", 10)) {
|
|
|
|
|
throw new IOException("Chunk is missing level data!");
|
|
|
|
|
}
|
|
|
|
|
chunkLevel = chunkNBT.getCompoundTag("Level");
|
|
|
|
|
}catch(IOException t) {
|
|
|
|
|
logger.error("Could not read chunk: {}", chunkFile.getPath());
|
|
|
|
|
logger.error(t);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
chunkLevel = chunkNBT.getCompoundTag("Level");
|
|
|
|
|
}catch(IOException t) {
|
|
|
|
|
logger.error("Could not read chunk: {}", chunkFile.getPath());
|
|
|
|
|
logger.error(t);
|
|
|
|
|
int chunkX = chunkLevel.getInteger("xPos");
|
|
|
|
|
int chunkZ = chunkLevel.getInteger("zPos");
|
|
|
|
|
String regionFileName = "r." + (chunkX >> 5) + "." + (chunkZ >> 5) + ".mca";
|
|
|
|
|
RegionFile rf = regionFiles.get(regionFileName);
|
|
|
|
|
if(rf == null) {
|
|
|
|
|
rf = new RegionFile(new RandomAccessMemoryFile(new byte[65536], 0));
|
|
|
|
|
regionFiles.put(regionFileName, rf);
|
|
|
|
|
}
|
|
|
|
|
try(DataOutputStream dos = rf.getChunkDataOutputStream(chunkX & 31, chunkZ & 31)) {
|
|
|
|
|
CompressedStreamTools.write(chunkNBT, dos);
|
|
|
|
|
}catch(IOException t) {
|
|
|
|
|
logger.error("Could not write chunk to {}: {}", regionFileName, chunkFile.getPath());
|
|
|
|
|
logger.error(t);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
prog += b.length;
|
|
|
|
|
if (prog - lastProgUpdate > 25000) {
|
|
|
|
|
lastProgUpdate = prog;
|
|
|
|
|
EaglerIntegratedServerWorker.sendProgress("singleplayer.busy.exporting.2", prog);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(regionFiles.isEmpty()) {
|
|
|
|
|
logger.info("No region files were generated");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
int chunkX = chunkLevel.getInteger("xPos");
|
|
|
|
|
int chunkZ = chunkLevel.getInteger("zPos");
|
|
|
|
|
String regionFileName = "r." + (chunkX >> 5) + "." + (chunkZ >> 5) + ".mca";
|
|
|
|
|
RegionFile rf = regionFiles.get(regionFileName);
|
|
|
|
|
if(rf == null) {
|
|
|
|
|
rf = new RegionFile(new RandomAccessMemoryFile(new byte[65536], 0));
|
|
|
|
|
regionFiles.put(regionFileName, rf);
|
|
|
|
|
}
|
|
|
|
|
try(DataOutputStream dos = rf.getChunkDataOutputStream(chunkX & 31, chunkZ & 31)) {
|
|
|
|
|
CompressedStreamTools.write(chunkNBT, dos);
|
|
|
|
|
}catch(IOException t) {
|
|
|
|
|
logger.error("Could not write chunk to {}: {}", regionFileName, chunkFile.getPath());
|
|
|
|
|
logger.error(t);
|
|
|
|
|
continue;
|
|
|
|
|
for(Entry<String,RegionFile> etr : regionFiles.entrySet()) {
|
|
|
|
|
String regionPath = regionFolder + etr.getKey();
|
|
|
|
|
logger.info("Writing region file: {}", regionPath);
|
|
|
|
|
zos.putNextEntry(new ZipEntry(regionPath));
|
|
|
|
|
zos.write(etr.getValue().getFile().getByteArray());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
logger.info("Copying extra world data...");
|
|
|
|
|
fileList = (new VFile2(worldFolder, "data")).listFiles(false);
|
|
|
|
|
for(int k = 0, l = fileList.size(); k < l; ++k) {
|
|
|
|
|
VFile2 dataFile = fileList.get(k);
|
|
|
|
|
zos.putNextEntry(new ZipEntry(folderName + "/data/" + dataFile.getName()));
|
|
|
|
|
b = dataFile.getAllBytes();
|
|
|
|
|
zos.write(b);
|
|
|
|
|
prog += b.length;
|
|
|
|
|
if (prog - lastProgUpdate > 25000) {
|
|
|
|
|
lastProgUpdate = prog;
|
|
|
|
|
EaglerIntegratedServerWorker.sendProgress("singleplayer.busy.exporting.2", prog);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(regionFiles.isEmpty()) {
|
|
|
|
|
logger.info("No region files were generated");
|
|
|
|
|
continue;
|
|
|
|
|
fileList = (new VFile2(worldFolder, "players")).listFiles(false);
|
|
|
|
|
for(int k = 0, l = fileList.size(); k < l; ++k) {
|
|
|
|
|
VFile2 dataFile = fileList.get(k);
|
|
|
|
|
zos.putNextEntry(new ZipEntry(folderName + "/players/" + dataFile.getName()));
|
|
|
|
|
b = dataFile.getAllBytes();
|
|
|
|
|
zos.write(b);
|
|
|
|
|
prog += b.length;
|
|
|
|
|
if (prog - lastProgUpdate > 25000) {
|
|
|
|
|
lastProgUpdate = prog;
|
|
|
|
|
EaglerIntegratedServerWorker.sendProgress("singleplayer.busy.exporting.2", prog);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for(Entry<String,RegionFile> etr : regionFiles.entrySet()) {
|
|
|
|
|
String regionPath = regionFolder + etr.getKey();
|
|
|
|
|
logger.info("Writing region file: {}", regionPath);
|
|
|
|
|
zos.putNextEntry(new ZipEntry(regionPath));
|
|
|
|
|
zos.write(etr.getValue().getFile().getByteArray());
|
|
|
|
|
fileList = (new VFile2(worldFolder, "eagler/skulls")).listFiles(false);
|
|
|
|
|
for(int k = 0, l = fileList.size(); k < l; ++k) {
|
|
|
|
|
VFile2 dataFile = fileList.get(k);
|
|
|
|
|
zos.putNextEntry(new ZipEntry(folderName + "/eagler/skulls/" + dataFile.getName()));
|
|
|
|
|
b = dataFile.getAllBytes();
|
|
|
|
|
zos.write(b);
|
|
|
|
|
prog += b.length;
|
|
|
|
|
if (prog - lastProgUpdate > 25000) {
|
|
|
|
|
lastProgUpdate = prog;
|
|
|
|
|
EaglerIntegratedServerWorker.sendProgress("singleplayer.busy.exporting.2", prog);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
logger.info("Copying extra world data...");
|
|
|
|
|
fileList = (new VFile2(worldFolder, "data")).listFiles(false);
|
|
|
|
|
for(int k = 0, l = fileList.size(); k < l; ++k) {
|
|
|
|
|
VFile2 dataFile = fileList.get(k);
|
|
|
|
|
zos.putNextEntry(new ZipEntry(folderName + "/data/" + dataFile.getName()));
|
|
|
|
|
b = dataFile.getAllBytes();
|
|
|
|
|
zos.write(b);
|
|
|
|
|
prog += b.length;
|
|
|
|
|
if (prog - lastProgUpdate > 25000) {
|
|
|
|
|
lastProgUpdate = prog;
|
|
|
|
|
EaglerIntegratedServerWorker.sendProgress("singleplayer.busy.exporting.2", prog);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fileList = (new VFile2(worldFolder, "players")).listFiles(false);
|
|
|
|
|
for(int k = 0, l = fileList.size(); k < l; ++k) {
|
|
|
|
|
VFile2 dataFile = fileList.get(k);
|
|
|
|
|
zos.putNextEntry(new ZipEntry(folderName + "/players/" + dataFile.getName()));
|
|
|
|
|
b = dataFile.getAllBytes();
|
|
|
|
|
zos.write(b);
|
|
|
|
|
prog += b.length;
|
|
|
|
|
if (prog - lastProgUpdate > 25000) {
|
|
|
|
|
lastProgUpdate = prog;
|
|
|
|
|
EaglerIntegratedServerWorker.sendProgress("singleplayer.busy.exporting.2", prog);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fileList = (new VFile2(worldFolder, "eagler/skulls")).listFiles(false);
|
|
|
|
|
for(int k = 0, l = fileList.size(); k < l; ++k) {
|
|
|
|
|
VFile2 dataFile = fileList.get(k);
|
|
|
|
|
zos.putNextEntry(new ZipEntry(folderName + "/eagler/skulls/" + dataFile.getName()));
|
|
|
|
|
b = dataFile.getAllBytes();
|
|
|
|
|
zos.write(b);
|
|
|
|
|
prog += b.length;
|
|
|
|
|
if (prog - lastProgUpdate > 25000) {
|
|
|
|
|
lastProgUpdate = prog;
|
|
|
|
|
EaglerIntegratedServerWorker.sendProgress("singleplayer.busy.exporting.2", prog);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
zos.close();
|
|
|
|
|
logger.info("World directory \"{}\" was successfully exported as MCA", worldFolder.getPath());
|
|
|
|
|
return bao.toByteArray();
|
|
|
|
|
}
|
|
|
|
|