Partial export-to-vanilla
This commit is contained in:
parent
09783034b2
commit
a013bf69b1
32587
javascript/classes.js
32587
javascript/classes.js
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -1,19 +1,19 @@
|
|||
package net.lax1dude.eaglercraft.sp;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.Map;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import net.minecraft.src.NBTBase;
|
||||
import net.minecraft.src.ChunkCoordIntPair;
|
||||
import org.teavm.jso.JSBody;
|
||||
import org.teavm.jso.JSFunctor;
|
||||
import org.teavm.jso.JSObject;
|
||||
|
@ -277,16 +277,99 @@ public class IntegratedServer {
|
|||
byte[] b = i.getAllBytes();
|
||||
c.append(i.path.substring(pfx.length()), b);
|
||||
bytesWritten[0] += b.length;
|
||||
if(bytesWritten[0] - lastUpdate[0] > 10000) {
|
||||
if (bytesWritten[0] - lastUpdate[0] > 10000) {
|
||||
lastUpdate[0] = bytesWritten[0];
|
||||
updateStatusString("selectWorld.progress.exporting." + pkt.request, bytesWritten[0]);
|
||||
}
|
||||
});
|
||||
sendIPCPacket(new IPCPacket09RequestResponse(c.complete()));
|
||||
}catch(Throwable t) {
|
||||
} catch (Throwable t) {
|
||||
throwExceptionToClient("Failed to export world '" + pkt.worldName + "' as EPK", t);
|
||||
sendTaskFailed();
|
||||
}
|
||||
}else if(pkt.request == IPCPacket05RequestData.REQUEST_LEVEL_MCA) {
|
||||
try {
|
||||
final int[] bytesWritten = new int[1];
|
||||
final int[] lastUpdate = new int[1];
|
||||
String pfx = "worlds/" + pkt.worldName + "/";
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ZipOutputStream c = new ZipOutputStream(baos);
|
||||
c.setComment("contains backup of world '" + pkt.worldName + "'");
|
||||
Map<ChunkCoordIntPair, byte[]> regions = new HashMap<>();
|
||||
Map<ChunkCoordIntPair, byte[]> regions1 = new HashMap<>();
|
||||
Map<ChunkCoordIntPair, byte[]> regionsn1 = new HashMap<>();
|
||||
SYS.VFS.iterateFiles(pfx, false, (i) -> {
|
||||
String currPath = i.path.substring(pfx.length());
|
||||
System.out.println(currPath); // 12yee
|
||||
try {
|
||||
byte[] b = i.getAllBytes();
|
||||
if (currPath.startsWith("region/")) {
|
||||
regions.put(VFSChunkLoader.getChunkCoords(currPath.substring(7, -4)), b);
|
||||
} else if (currPath.startsWith("DIM1/region/")) {
|
||||
regions1.put(VFSChunkLoader.getChunkCoords(currPath.substring(12, -4)), b);
|
||||
} else if (currPath.startsWith("DIM-1/region/")) {
|
||||
regionsn1.put(VFSChunkLoader.getChunkCoords(currPath.substring(13, -4)), b);
|
||||
} else {
|
||||
ZipEntry zipEntry = new ZipEntry(currPath);
|
||||
c.putNextEntry(zipEntry);
|
||||
c.write(b); // 12yee
|
||||
c.closeEntry();
|
||||
bytesWritten[0] += b.length;
|
||||
if (bytesWritten[0] - lastUpdate[0] > 10000) {
|
||||
lastUpdate[0] = bytesWritten[0];
|
||||
updateStatusString("selectWorld.progress.exporting." + pkt.request, bytesWritten[0]);
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
throwExceptionToClient("Failed to export file '" + currPath + "'", t);
|
||||
sendTaskFailed();
|
||||
}
|
||||
});
|
||||
Map<String, byte[]> regionsOut = MCAConverter.convertToMCA(regions);
|
||||
for (String path : regionsOut.keySet()) {
|
||||
byte[] b = regionsOut.get(path);
|
||||
ZipEntry zipEntry = new ZipEntry("region/" + path + ".dat");
|
||||
c.putNextEntry(zipEntry);
|
||||
c.write(b); // 12yee
|
||||
c.closeEntry();
|
||||
bytesWritten[0] += b.length;
|
||||
if (bytesWritten[0] - lastUpdate[0] > 10000) {
|
||||
lastUpdate[0] = bytesWritten[0];
|
||||
updateStatusString("selectWorld.progress.exporting." + pkt.request, bytesWritten[0]);
|
||||
}
|
||||
}
|
||||
Map<String, byte[]> regions1Out = MCAConverter.convertToMCA(regions1);
|
||||
for (String path : regions1Out.keySet()) {
|
||||
byte[] b = regions1Out.get(path);
|
||||
ZipEntry zipEntry = new ZipEntry("DIM1/region/" + path + ".dat");
|
||||
c.putNextEntry(zipEntry);
|
||||
c.write(b); // 12yee
|
||||
c.closeEntry();
|
||||
bytesWritten[0] += b.length;
|
||||
if (bytesWritten[0] - lastUpdate[0] > 10000) {
|
||||
lastUpdate[0] = bytesWritten[0];
|
||||
updateStatusString("selectWorld.progress.exporting." + pkt.request, bytesWritten[0]);
|
||||
}
|
||||
}
|
||||
Map<String, byte[]> regionsn1Out = MCAConverter.convertToMCA(regionsn1);
|
||||
for (String path : regionsn1Out.keySet()) {
|
||||
byte[] b = regionsn1Out.get(path);
|
||||
ZipEntry zipEntry = new ZipEntry("DIM-1/region/" + path + ".dat");
|
||||
c.putNextEntry(zipEntry);
|
||||
c.write(b); // 12yee
|
||||
c.closeEntry();
|
||||
bytesWritten[0] += b.length;
|
||||
if (bytesWritten[0] - lastUpdate[0] > 10000) {
|
||||
lastUpdate[0] = bytesWritten[0];
|
||||
updateStatusString("selectWorld.progress.exporting." + pkt.request, bytesWritten[0]);
|
||||
}
|
||||
}
|
||||
c.close();
|
||||
sendIPCPacket(new IPCPacket09RequestResponse(baos.toByteArray()));
|
||||
} catch (Throwable t) {
|
||||
throwExceptionToClient("Failed to export world '" + pkt.worldName + "' as MCA", t);
|
||||
sendTaskFailed();
|
||||
}
|
||||
}else {
|
||||
System.err.println("Unknown IPCPacket05RequestData type '" + pkt.request + "'");
|
||||
sendTaskFailed();
|
||||
|
@ -361,9 +444,9 @@ public class IntegratedServer {
|
|||
List<char[]> fileNames = new ArrayList<>();
|
||||
while((folderNameFile = folderNames.getNextEntry()) != null) {
|
||||
if (folderNameFile.getName().contains("__MACOSX/")) continue;
|
||||
if (folderNameFile.getName().toLowerCase().endsWith(".txt")) continue;
|
||||
if (folderNameFile.getName().toLowerCase().endsWith(".lnk")) continue;
|
||||
if (folderNameFile.isDirectory()) continue;
|
||||
String lowerName = folderNameFile.getName().toLowerCase();
|
||||
if (!(lowerName.endsWith(".dat") || lowerName.endsWith(".dat_old") || lowerName.endsWith(".dat_mcr") || lowerName.endsWith(".mca") || lowerName.endsWith(".mcr"))) continue;
|
||||
fileNames.add(folderNameFile.getName().toCharArray());
|
||||
}
|
||||
final int[] i = new int[] { 0 };
|
||||
|
@ -376,9 +459,9 @@ public class IntegratedServer {
|
|||
byte[] bb = new byte[16000];
|
||||
while ((f = dc.getNextEntry()) != null) {
|
||||
if (f.getName().contains("__MACOSX/")) continue;
|
||||
if (f.getName().toLowerCase().endsWith(".txt")) continue;
|
||||
if (f.getName().toLowerCase().endsWith(".lnk")) continue;
|
||||
if (f.isDirectory()) continue;
|
||||
String lowerName = f.getName().toLowerCase();
|
||||
if (!(lowerName.endsWith(".dat") || lowerName.endsWith(".dat_old") || lowerName.endsWith(".dat_mcr") || lowerName.endsWith(".mca") || lowerName.endsWith(".mcr"))) continue;
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
int len;
|
||||
while ((len = dc.read(bb)) != -1) {
|
||||
|
@ -394,7 +477,7 @@ public class IntegratedServer {
|
|||
b = CompressedStreamTools.compress(worldDatNBT);
|
||||
}
|
||||
if (fileName.endsWith(".mcr") || fileName.endsWith(".mca")) {
|
||||
MCAConverter.convertMCA(dir, b, fileName);
|
||||
MCAConverter.convertFromMCA(dir, b, fileName);
|
||||
} else {
|
||||
VFile ff = new VFile(dir, fileName);
|
||||
ff.setAllBytes(b);
|
||||
|
|
|
@ -1,12 +1,20 @@
|
|||
package net.lax1dude.eaglercraft.sp;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import com.jcraft.jzlib.GZIPOutputStream;
|
||||
import net.minecraft.src.ChunkCoordIntPair;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.zip.DeflaterOutputStream;
|
||||
import java.util.zip.InflaterInputStream;
|
||||
|
||||
public class MCAConverter {
|
||||
public static void convertMCA(VFile dir, byte[] file, String fileName) {
|
||||
public static void convertFromMCA(VFile dir, byte[] file, String fileName) {
|
||||
VFile levelDir = new VFile(dir, "level" + (fileName.startsWith("region/") ? "0" : fileName.substring(3, fileName.indexOf('/'))));
|
||||
|
||||
String[] xz = fileName.substring(fileName.lastIndexOf('r') + 2, fileName.length() - 4).split("\\.");
|
||||
|
@ -58,4 +66,81 @@ public class MCAConverter {
|
|||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static Map<String, byte[]> convertToMCA(Map<ChunkCoordIntPair, byte[]> regions) {
|
||||
Map<String, byte[]> regionsOut = new HashMap<>();
|
||||
|
||||
try {
|
||||
int timestamp = (int) System.currentTimeMillis();
|
||||
|
||||
int maxX = Integer.MIN_VALUE;
|
||||
int maxZ = Integer.MIN_VALUE;
|
||||
int minX = Integer.MAX_VALUE;
|
||||
int minZ = Integer.MAX_VALUE;
|
||||
|
||||
for (ChunkCoordIntPair coords : regions.keySet()) {
|
||||
if (maxX < coords.chunkXPos) maxX = coords.chunkXPos;
|
||||
if (maxZ < coords.chunkZPos) maxZ = coords.chunkZPos;
|
||||
if (minX > coords.chunkXPos) minX = coords.chunkXPos;
|
||||
if (minZ > coords.chunkZPos) minZ = coords.chunkZPos;
|
||||
}
|
||||
|
||||
for (int x = minX - (minX % 32); x <= maxX + (maxX % 32); x += 32) {
|
||||
for (int z = minZ - (minZ % 32); z <= maxZ + (maxZ % 32); z += 32) {
|
||||
ByteArrayOutputStream offsets = new ByteArrayOutputStream();
|
||||
DataOutputStream offsetsDos = new DataOutputStream(offsets);
|
||||
ByteArrayOutputStream timestamps = new ByteArrayOutputStream();
|
||||
DataOutputStream timestampsDos = new DataOutputStream(timestamps);
|
||||
ByteArrayOutputStream chunks = new ByteArrayOutputStream();
|
||||
DataOutputStream chunksDos = new DataOutputStream(chunks);
|
||||
for (int cx = 0; cx < 32; ++cx) {
|
||||
for (int cz = 0; cz < 32; ++cz) {
|
||||
int tx = x + cx;
|
||||
int tz = z + cz;
|
||||
|
||||
byte[] region = regions.get(new ChunkCoordIntPair(tx, tz));
|
||||
if (region == null) {
|
||||
offsetsDos.writeInt(0);
|
||||
timestampsDos.writeInt(0);
|
||||
} else {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DeflaterOutputStream dos = new DeflaterOutputStream(baos);
|
||||
dos.write(region);
|
||||
dos.close();
|
||||
byte[] zlibbed = baos.toByteArray();
|
||||
|
||||
int offset = chunksDos.size();
|
||||
offsetsDos.write((offset >> 16) & 0xff);
|
||||
offsetsDos.write((offset >> 8) & 0xff);
|
||||
offsetsDos.write(offset & 0xff);
|
||||
offsetsDos.write(5 + zlibbed.length);
|
||||
|
||||
timestampsDos.writeInt(timestamp);
|
||||
|
||||
chunksDos.writeInt(region.length);
|
||||
chunksDos.write(2);
|
||||
chunksDos.write(zlibbed);
|
||||
}
|
||||
}
|
||||
}
|
||||
offsetsDos.close();
|
||||
timestampsDos.close();
|
||||
chunksDos.close();
|
||||
|
||||
byte[] offsetsOut = offsets.toByteArray();
|
||||
byte[] timestampsOut = timestamps.toByteArray();
|
||||
byte[] chunksOut = chunks.toByteArray();
|
||||
|
||||
byte[] regionFile = new byte[offsetsOut.length + timestampsOut.length + chunksOut.length];
|
||||
System.arraycopy(offsetsOut, 0, regionFile, 0, offsetsOut.length);
|
||||
System.arraycopy(timestampsOut, 0, regionFile, offsetsOut.length, timestampsOut.length);
|
||||
System.arraycopy(chunksOut, 0, regionFile, offsetsOut.length + timestampsOut.length, chunksOut.length);
|
||||
regionsOut.put("r." + (x / 32) + "." + (z / 32), regionFile);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return regionsOut;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import java.util.Iterator;
|
|||
import java.util.List;
|
||||
|
||||
import net.minecraft.src.Chunk;
|
||||
import net.minecraft.src.ChunkCoordIntPair;
|
||||
import net.minecraft.src.CompressedStreamTools;
|
||||
import net.minecraft.src.Entity;
|
||||
import net.minecraft.src.EntityList;
|
||||
|
@ -36,6 +37,21 @@ public class VFSChunkLoader implements IChunkLoader {
|
|||
|
||||
return new String(path);
|
||||
}
|
||||
|
||||
public static ChunkCoordIntPair getChunkCoords(String filename) {
|
||||
String strX = filename.substring(0, 6);
|
||||
String strZ = filename.substring(6);
|
||||
|
||||
int retX = 0;
|
||||
int retZ = 0;
|
||||
|
||||
for(int i = 0; i < 6; ++i) {
|
||||
retX |= hex.indexOf(strX.charAt(i)) << (i << 2);
|
||||
retZ |= hex.indexOf(strZ.charAt(i)) << (i << 2);
|
||||
}
|
||||
|
||||
return new ChunkCoordIntPair(retX - 1900000, retZ - 1900000);
|
||||
}
|
||||
|
||||
public VFSChunkLoader(VFile chunkDirectory) {
|
||||
this.chunkDirectory = chunkDirectory;
|
||||
|
|
|
@ -79,7 +79,15 @@ public class GuiScreenBackupWorld extends GuiScreen {
|
|||
return false;
|
||||
}));
|
||||
}else if(par1GuiButton.id == 4) {
|
||||
this.mc.displayGuiScreen(new GuiScreenSingleplayerNotImplemented(this, "export vanilla 1.5.2 world"));
|
||||
IntegratedServer.exportWorld(worldName, IPCPacket05RequestData.REQUEST_LEVEL_MCA);
|
||||
this.mc.displayGuiScreen(new GuiScreenSingleplayerLoading(selectWorld, "selectWorld.progress.exporting.1", () -> {
|
||||
byte[] b = IntegratedServer.getExportResponse();
|
||||
if(b != null) {
|
||||
EaglerAdapter.downloadBytes(worldName + ".zip", b);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user