From 13c423c0047c5fa969b75677dcbda892406c9b5c Mon Sep 17 00:00:00 2001 From: DmitriyMX Date: Sat, 18 Aug 2018 17:21:24 +0300 Subject: [PATCH] =?UTF-8?q?=D0=BF=D1=80=D0=BE=D0=B1=D1=83=D0=B5=D0=BC=20?= =?UTF-8?q?=D1=87=D0=B8=D1=82=D0=B0=D1=82=D1=8C=20=D1=80=D0=B5=D0=B3=D0=B8?= =?UTF-8?q?=D0=BE=D0=BD=D0=B0=D0=BB=D1=8C=D0=BD=D1=8B=D0=B5=20=D1=84=D0=B0?= =?UTF-8?q?=D0=B9=D0=BB=D1=8B=20(r.X.Z.mca)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- anvil-loader/build.gradle | 4 + .../src/main/java/mc/world/anvil/Main.java | 14 +-- .../main/java/mc/world/anvil/RegionFile.java | 95 +++++++++++++++++++ 3 files changed, 101 insertions(+), 12 deletions(-) create mode 100644 anvil-loader/src/main/java/mc/world/anvil/RegionFile.java diff --git a/anvil-loader/build.gradle b/anvil-loader/build.gradle index 4635131..f12d7e9 100644 --- a/anvil-loader/build.gradle +++ b/anvil-loader/build.gradle @@ -4,6 +4,10 @@ version '1.0-SNAPSHOT' dependencies { /* Core */ compile_excludeCopy project(':core') + + /* Simple log */ + compile_excludeCopy (group: 'org.slf4j', name: 'slf4j-simple', version: slf4j_version) + /* Named Binary Tags */ compile (group: 'com.flowpowered', name: 'flow-nbt', version: '1.0.0') } \ No newline at end of file diff --git a/anvil-loader/src/main/java/mc/world/anvil/Main.java b/anvil-loader/src/main/java/mc/world/anvil/Main.java index 6ff1a7a..4989c56 100644 --- a/anvil-loader/src/main/java/mc/world/anvil/Main.java +++ b/anvil-loader/src/main/java/mc/world/anvil/Main.java @@ -1,9 +1,5 @@ package mc.world.anvil; -import com.flowpowered.nbt.Tag; -import com.flowpowered.nbt.stream.NBTInputStream; - -import java.io.FileInputStream; import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; @@ -12,13 +8,7 @@ public class Main { public static void main(String[] args) throws IOException { final Path levelDatPath = Paths.get(args[0]); - FileInputStream fis = new FileInputStream(levelDatPath.toFile()); - NBTInputStream nbtInputStream = new NBTInputStream(fis); - - Tag rootTag = nbtInputStream.readTag(); - System.out.println(rootTag.toString()); - - nbtInputStream.close(); - fis.close(); + RegionFile regionFile = new RegionFile(levelDatPath.toFile()); + regionFile.getChunk(0,0); } } diff --git a/anvil-loader/src/main/java/mc/world/anvil/RegionFile.java b/anvil-loader/src/main/java/mc/world/anvil/RegionFile.java new file mode 100644 index 0000000..e9e8198 --- /dev/null +++ b/anvil-loader/src/main/java/mc/world/anvil/RegionFile.java @@ -0,0 +1,95 @@ +package mc.world.anvil; + +import com.flowpowered.nbt.Tag; +import com.flowpowered.nbt.stream.NBTInputStream; +import lombok.extern.slf4j.Slf4j; +import mc.core.world.chunk.Chunk; + +import javax.annotation.Nullable; +import java.io.*; +import java.util.ArrayList; +import java.util.List; +import java.util.zip.InflaterInputStream; + +@Slf4j +public class RegionFile implements Closeable { + private RandomAccessFile file; + private List sectorFree; //TODO заменить на Trove TByteList + private final int[] offsets = new int[1024]; + + public RegionFile(File file) throws IOException { + this.file = new RandomAccessFile(file, "rw"); + + int sizeOfSectorFree = (int)this.file.length() / 4096; + sectorFree = new ArrayList<>(sizeOfSectorFree); + sectorFree.add(false); + sectorFree.add(false); + for (int i = 0; i < sizeOfSectorFree-2; i++) { + sectorFree.add(true); + } + + for (int i = 0; i < offsets.length; ++i) { + int read = this.file.readInt(); + offsets[i] = read; + + if (read != 0 && (read >> 8) + (read & 255) <= this.sectorFree.size()) { + for (int j = 0; j < (read & 255); ++j) { + this.sectorFree.set((read >> 8) + j, false); + } + } + } + + this.file.skipBytes(1024); + } + + @Nullable + public Chunk getChunk(int x, int z) { + int offset = getOffset(x, z); + + if (offset == 0) return null; + + int v1 = offset >> 8; // j + int v2 = offset & 255; // k + + if (v1 + v2 > sectorFree.size()) return null; + + try { + file.seek((long) (v1 * 4096)); + int read = file.readInt(); + if (read <= 0 || read > 4096 * v2) return null; + + boolean gzippedData = (file.readByte() == 0x01); + + if (gzippedData) { + log.info("GZipped"); + } else { + log.info("Inflaten"); + + byte[] buffer = new byte[read - 1]; + file.read(buffer); + InflaterInputStream inputStream = new InflaterInputStream(new ByteArrayInputStream(buffer)); + + NBTInputStream nbtInputStream = new NBTInputStream(inputStream, false); + + Tag rootTag = nbtInputStream.readTag(); + log.info(rootTag.toString()); + + nbtInputStream.close(); + } + } catch (IOException e) { + log.error("Get chunk", e); + return null; + } + + return null; + } + + private int getOffset(int x, int z) { + return offsets[x + z * 32]; + } + + @Override + public void close() throws IOException { + if (file != null) file.close(); + } +}