Skip to content

Commit

Permalink
Added 1.17 entities storage import support (fixing #65) (#87)
Browse files Browse the repository at this point in the history
  • Loading branch information
DartCZ authored Dec 10, 2021
1 parent a39347e commit 841a097
Showing 1 changed file with 64 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public class SWMImporter {

private static final Pattern MAP_FILE_PATTERN = Pattern.compile("^(?:map_([0-9]*).dat)$");
private static final int SECTOR_SIZE = 4096;
private static boolean entityCustomStorage;

public static void main(String[] args) {
if (args.length == 0) {
Expand Down Expand Up @@ -132,6 +133,14 @@ public static void importWorld(File worldFolder, File outputFile, boolean debug)
throw new InvalidWorldException(worldFolder, "The world appears to be corrupted");
}

File entitiesDir = new File(worldFolder, "entities");

if(entitiesDir.exists()) {
entityCustomStorage = true;

if(debug) System.out.println("Entities will be imported from custom storage (1.17 world or above)");
}

if(debug) System.out.println("Loading world...");

File levelFile = new File(worldFolder, "level.dat");
Expand Down Expand Up @@ -171,7 +180,7 @@ public static void importWorld(File worldFolder, File outputFile, boolean debug)

for (File file : regionDir.listFiles((dir, name) -> name.endsWith(".mca"))) {
try {
chunks.addAll(loadChunks(file, worldVersion, debug));
chunks.addAll(loadChunks(file, entitiesDir, worldVersion, debug));
} catch (IOException ex) {
throw new IOException("Failed to read region file", ex);
}
Expand Down Expand Up @@ -248,7 +257,7 @@ private static CompoundTag loadMap(File mapFile) throws IOException {
return tag;
}

private static List<SlimeChunk> loadChunks(File file, byte worldVersion, boolean debug) throws IOException {
private static List<SlimeChunk> loadChunks(File file, File entitiesDir, byte worldVersion, boolean debug) throws IOException {
if(debug) System.out.println("Loading chunks from region file '" + file.getName() + "':");

byte[] regionByteArray = Files.readAllBytes(file.toPath());
Expand Down Expand Up @@ -287,7 +296,12 @@ private static List<SlimeChunk> loadChunks(File file, byte worldVersion, boolean

CompoundTag levelCompound = (CompoundTag) globalMap.get("Level");

return readChunk(levelCompound, worldVersion);
List<CompoundTag> entityList = null;

if(entityCustomStorage)
entityList = readEntities(file, entitiesDir, entry.getOffset(), entry.getPaddedSize(), worldVersion, debug);

return readChunk(levelCompound, entityList, worldVersion);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
Expand All @@ -299,7 +313,46 @@ private static List<SlimeChunk> loadChunks(File file, byte worldVersion, boolean
return loadedChunks;
}

private static SlimeChunk readChunk(CompoundTag compound, byte worldVersion) {
private static List<CompoundTag> readEntities(File regionFile, File entityDir, int offset, int paddedSize, byte worldVersion, boolean debug) throws IOException {
File file = new File(entityDir.getPath(), regionFile.getName());
List<CompoundTag> entities = new ListTag<CompoundTag>("Entities", TagType.TAG_COMPOUND, new ArrayList<>()).getValue();

if(!file.exists()) {
return entities;
}

if(debug) System.out.println("Loading chunk entities from region file '" + file.getName() + "':");

byte[] regionByteArray = Files.readAllBytes(file.toPath());

try {
DataInputStream headerStream = new DataInputStream(new ByteArrayInputStream(regionByteArray, offset, paddedSize));

if(headerStream.available() <= 0) {
return entities;
}

int chunkSize = headerStream.readInt() - 1;

int compressionScheme = headerStream.readByte();

DataInputStream chunkStream = new DataInputStream(new ByteArrayInputStream(regionByteArray, offset + 5, chunkSize));
InputStream decompressorStream = compressionScheme == 1 ? new GZIPInputStream(chunkStream) : new InflaterInputStream(chunkStream);
NBTInputStream nbtStream = new NBTInputStream(decompressorStream, NBTInputStream.NO_COMPRESSION, ByteOrder.BIG_ENDIAN);
CompoundTag globalCompound = (CompoundTag) nbtStream.readTag();

entities = ((ListTag<CompoundTag>) globalCompound.getAsListTag("Entities")
.orElse(new ListTag<>("Entities", TagType.TAG_COMPOUND, new ArrayList<>()))).getValue();
} catch (IOException ex) {
throw new RuntimeException(ex);
}

if(debug) System.out.println( entities.size() + " entities loaded at " + regionFile.getName());

return entities;
}

private static SlimeChunk readChunk(CompoundTag compound, List<CompoundTag> entityList, byte worldVersion) {
int chunkX = compound.getAsIntTag("xPos").get().getValue();
int chunkZ = compound.getAsIntTag("zPos").get().getValue();
Optional<String> status = compound.getStringValue("Status");
Expand Down Expand Up @@ -336,8 +389,13 @@ private static SlimeChunk readChunk(CompoundTag compound, byte worldVersion) {

List<CompoundTag> tileEntities = ((ListTag<CompoundTag>) compound.getAsListTag("TileEntities")
.orElse(new ListTag<>("TileEntities", TagType.TAG_COMPOUND, new ArrayList<>()))).getValue();
List<CompoundTag> entities = ((ListTag<CompoundTag>) compound.getAsListTag("Entities")
.orElse(new ListTag<>("Entities", TagType.TAG_COMPOUND, new ArrayList<>()))).getValue();
List<CompoundTag> entities = null;
if(entityCustomStorage) {
entities = entityList;
} else {
entities = ((ListTag<CompoundTag>) compound.getAsListTag("Entities")
.orElse(new ListTag<>("Entities", TagType.TAG_COMPOUND, new ArrayList<>()))).getValue();
}
ListTag<CompoundTag> sectionsTag = (ListTag<CompoundTag>) compound.getAsListTag("Sections").get();
SlimeChunkSection[] sectionArray = new SlimeChunkSection[16];

Expand Down

0 comments on commit 841a097

Please sign in to comment.