From b5313723d3df2c9ada1c413b276e5b2933f0be80 Mon Sep 17 00:00:00 2001 From: DmitriyMX Date: Thu, 18 Oct 2018 01:30:32 +0300 Subject: [PATCH] =?UTF-8?q?=D0=BF=D0=B5=D1=80=D0=B2=D1=8B=D0=B5=20=D0=BD?= =?UTF-8?q?=D0=B0=D0=BC=D1=91=D1=82=D0=BA=D0=B8=20Anvil=20chunk=20provider?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/mc/world/anvil/AnvilBlock.java | 54 ++++++++++++++ .../main/java/mc/world/anvil/AnvilChunk.java | 70 +++++++++++++++++++ .../mc/world/anvil/AnvilChunkProvider.java | 32 +++++++++ .../mc/world/anvil/AnvilChunkSection.java | 67 ++++++++++++++++++ .../src/main/java/mc/world/anvil/Main.java | 28 +++++--- 5 files changed, 243 insertions(+), 8 deletions(-) create mode 100644 anvil-loader/src/main/java/mc/world/anvil/AnvilBlock.java create mode 100644 anvil-loader/src/main/java/mc/world/anvil/AnvilChunk.java create mode 100644 anvil-loader/src/main/java/mc/world/anvil/AnvilChunkProvider.java create mode 100644 anvil-loader/src/main/java/mc/world/anvil/AnvilChunkSection.java diff --git a/anvil-loader/src/main/java/mc/world/anvil/AnvilBlock.java b/anvil-loader/src/main/java/mc/world/anvil/AnvilBlock.java new file mode 100644 index 0000000..7770eb7 --- /dev/null +++ b/anvil-loader/src/main/java/mc/world/anvil/AnvilBlock.java @@ -0,0 +1,54 @@ +package mc.world.anvil; + +import com.flowpowered.nbt.Tag; +import mc.core.world.block.Block; +import mc.core.world.block.BlockLocation; +import mc.core.world.block.BlockType; + +import java.util.stream.Stream; + +public class AnvilBlock implements Block { + private final AnvilChunkSection chunkSection; + private final BlockLocation location; + + public AnvilBlock(AnvilChunkSection chunkSection, int x, int y, int z) { + this.chunkSection = chunkSection; + this.location = new BlockLocation(x, y, z); + } + + @Override + public int getLight() { + return chunkSection.getBlockLight().get(((16 * location.getZ()) * location.getY()) + location.getX()); + } + + @Override + public void setLight(int light) { + + } + + @Override + public BlockType getBlockType() { + byte id = chunkSection.getBlocks().get(((16 * location.getZ()) * location.getY()) + location.getX()); + return BlockType.getByIdMeta(id, 0/*FIXME*/); + } + + @Override + public BlockLocation getLocation() { + return location; + } + + @Override + public Tag getTag(String name) { + return null; + } + + @Override + public void setTag(Tag tag) { + + } + + @Override + public Stream> tagStream() { + return null; + } +} diff --git a/anvil-loader/src/main/java/mc/world/anvil/AnvilChunk.java b/anvil-loader/src/main/java/mc/world/anvil/AnvilChunk.java new file mode 100644 index 0000000..caa04a5 --- /dev/null +++ b/anvil-loader/src/main/java/mc/world/anvil/AnvilChunk.java @@ -0,0 +1,70 @@ +package mc.world.anvil; + +import com.flowpowered.nbt.*; +import gnu.trove.list.TByteList; +import gnu.trove.list.array.TByteArrayList; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import mc.core.world.Biome; +import mc.core.world.chunk.Chunk; +import mc.core.world.chunk.ChunkSection; + +import java.util.ArrayList; +import java.util.List; + +@Slf4j +@Getter +public class AnvilChunk implements Chunk { + private int x; + private int z; + private TByteList biomes = new TByteArrayList(256); + private List sections; + + @SuppressWarnings("unchecked") + AnvilChunk(CompoundTag chunkTag) { + log.info(chunkTag.toString()); + CompoundMap levelTagMap = ((CompoundTag) chunkTag.getValue().get("Level")).getValue(); + + this.x = ((IntTag) levelTagMap.get("xPos")).getValue(); + this.z = ((IntTag) levelTagMap.get("zPos")).getValue(); + + biomes.add(((ByteArrayTag) levelTagMap.get("Biomes")).getValue()); + + List sections = ((ListTag) levelTagMap.get("Sections")).getValue(); + this.sections = new ArrayList<>(sections.size()); + + for (CompoundTag sectionTag : sections) { + CompoundMap sectionTagValue = sectionTag.getValue(); + + AnvilChunkSection chunkSection = new AnvilChunkSection(); + chunkSection.setParent(this); + chunkSection.setY(((ByteTag) sectionTagValue.get("Y")).getValue()); + + chunkSection.getBlockLight().add(((ByteArrayTag) sectionTagValue.get("BlockLight")).getValue()); + chunkSection.getSkyLight().add(((ByteArrayTag) sectionTagValue.get("SkyLight")).getValue()); + chunkSection.getBlocks().add(((ByteArrayTag) sectionTagValue.get("Blocks")).getValue()); + + this.sections.add(chunkSection); + } + } + + @Override + public ChunkSection getChunkSection(int height) { + return sections.get(height); + } + + @Override + public void setChunkSection(int height, ChunkSection chunkSection) { + // nope... + } + + @Override + public Biome getBiome(int localX, int localZ) { + return Biome.getById( biomes.get( localZ << 4 | localX ) & 255 ); + } + + @Override + public void setBiome(int localX, int localZ, Biome biome) { + // nope... + } +} diff --git a/anvil-loader/src/main/java/mc/world/anvil/AnvilChunkProvider.java b/anvil-loader/src/main/java/mc/world/anvil/AnvilChunkProvider.java new file mode 100644 index 0000000..6b59e6e --- /dev/null +++ b/anvil-loader/src/main/java/mc/world/anvil/AnvilChunkProvider.java @@ -0,0 +1,32 @@ +package mc.world.anvil; + +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import mc.core.world.chunk.Chunk; +import mc.core.world.chunk.ChunkProvider; + +@Slf4j +@Setter +public class AnvilChunkProvider implements ChunkProvider { + private RegionManager regionManager; + + @Override + public Chunk getChunk(int x, int z) { + log.info("r.{}.{}", x/32, z/32); + + Region region = regionManager.getRegion(x / 32, z / 32); + if (region == null) return null; + + return region.getChunk(x, z); + } + + @Override + public void saveChunk(Chunk chunk) { + // nope + } + + @Override + public void saveChunk(Chunk... chunks) { + // nope + } +} diff --git a/anvil-loader/src/main/java/mc/world/anvil/AnvilChunkSection.java b/anvil-loader/src/main/java/mc/world/anvil/AnvilChunkSection.java new file mode 100644 index 0000000..315e8ee --- /dev/null +++ b/anvil-loader/src/main/java/mc/world/anvil/AnvilChunkSection.java @@ -0,0 +1,67 @@ +package mc.world.anvil; + +import gnu.trove.list.TByteList; +import gnu.trove.list.linked.TByteLinkedList; +import lombok.Getter; +import lombok.Setter; +import mc.core.world.Biome; +import mc.core.world.block.Block; +import mc.core.world.chunk.ChunkSection; + +@Getter +public class AnvilChunkSection implements ChunkSection { + @Setter + private AnvilChunk parent; + + @Setter + private int y; + + private TByteList blocks = new TByteLinkedList(); + private TByteList blockLight = new TByteLinkedList(); + private TByteList skyLight = new TByteLinkedList(); + + @Override + public int getX() { + return parent.getX(); + } + + @Override + public int getZ() { + return parent.getZ(); + } + + @Override + public Block getBlock(int x, int y, int z) { + return new AnvilBlock(this, x, y, z); + } + + @Override + public void setBlock(Block block) { + + } + + @Override + public int getSkyLight(int x, int y, int z) { + return skyLight.get(((16 * z) * y) + x); + } + + @Override + public void setSkyLight(int x, int y, int z, int lightLevel) { + + } + + @Override + public int getAddition(int x, int y, int z) { + return 0; + } + + @Override + public void setAddition(int x, int y, int z, int value) { + + } + + @Override + public Biome getBiome(int localX, int localZ) { + return parent.getBiome(localX, localZ); + } +} 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 dbde304..7a475d6 100644 --- a/anvil-loader/src/main/java/mc/world/anvil/Main.java +++ b/anvil-loader/src/main/java/mc/world/anvil/Main.java @@ -4,6 +4,8 @@ import com.flowpowered.nbt.CompoundTag; import com.flowpowered.nbt.Tag; import com.flowpowered.nbt.stream.NBTInputStream; import lombok.extern.slf4j.Slf4j; +import mc.core.world.chunk.Chunk; +import mc.core.world.chunk.ChunkProvider; import java.io.FileInputStream; import java.io.IOException; @@ -12,18 +14,28 @@ import java.nio.file.Paths; @Slf4j public class Main { + private static LevelInfo buildLevelInfo(Path levelDatPath) throws IOException { + try (NBTInputStream nbtInputStream = new NBTInputStream(new FileInputStream(levelDatPath.toFile()))) { + Tag rootTag = nbtInputStream.readTag(); + return new LevelInfo((CompoundTag) rootTag); + } + } + public static void main(String[] args) throws IOException { final Path worldPath = Paths.get(args[0]); // level.dat - FileInputStream fis = new FileInputStream(worldPath.resolve("level.dat").toFile()); - NBTInputStream nbtInputStream = new NBTInputStream(fis); - - Tag rootTag = nbtInputStream.readTag(); - LevelInfo levelInfo = new LevelInfo((CompoundTag) rootTag); - nbtInputStream.close(); - fis.close(); - + LevelInfo levelInfo = buildLevelInfo(worldPath.resolve("level.dat")); log.info(levelInfo.toString()); + + // regions + RegionManager regionManager = new RegionManager(worldPath.resolve("region")); + AnvilChunkProvider chunkProvider = new AnvilChunkProvider(); + chunkProvider.setRegionManager(regionManager); + + Chunk chunk = chunkProvider.getChunk(0, 0); + log.info("{}", chunk.getBiome(0,0)); + log.info("{}", chunk.getChunkSection(0).getBiome(0,0)); + log.info("{}", chunk.getChunkSection(0).getBlock(0,0,0).getBlockType()); } }