From cd45c4009c606bceb11a1d4202204ecd0969b5ef Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sun, 1 Feb 2015 07:47:22 +0100 Subject: Compute top non-air layer This doesn't yet ignore non-opaque blocks. --- src/World/Block.hpp | 41 ++++++++++++++++++++++++++++++++++++++ src/World/Chunk.cpp | 57 ++++++++++++++++++++++++++++++++++++++++++----------- src/World/Chunk.hpp | 25 ++++++++++++++--------- 3 files changed, 102 insertions(+), 21 deletions(-) create mode 100644 src/World/Block.hpp (limited to 'src/World') diff --git a/src/World/Block.hpp b/src/World/Block.hpp new file mode 100644 index 0000000..4bf0a0d --- /dev/null +++ b/src/World/Block.hpp @@ -0,0 +1,41 @@ +/* + Copyright (c) 2015, Matthias Schiffer + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#pragma once + +#include + + +namespace MinedMap { +namespace World { + +struct Block { + uint8_t id; + uint8_t data; +}; + +} +} diff --git a/src/World/Chunk.cpp b/src/World/Chunk.cpp index 915e5f3..2dc9014 100644 --- a/src/World/Chunk.cpp +++ b/src/World/Chunk.cpp @@ -39,6 +39,20 @@ namespace MinedMap { namespace World { +Chunk::Chunk(Buffer buffer) { + size_t size = buffer.get32(); + + Buffer buffer2(buffer.get(size), size); + + uint8_t format = buffer2.get8(); + if (format != 2) + throw std::invalid_argument("unknown chunk format"); + + inflateChunk(buffer2); + parseChunk(); + analyzeChunk(); +} + void Chunk::inflateChunk(Buffer buffer) { size_t outlen = 0; uint8_t *output = nullptr; @@ -97,11 +111,11 @@ void Chunk::analyzeChunk() { } } -uint8_t Chunk::getBlockAt(const std::shared_ptr §ion, size_t x, size_t y, size_t z) { +uint8_t Chunk::getBlockAt(const std::shared_ptr §ion, size_t x, size_t y, size_t z) const { return (*section->get("Blocks"))[getIndex(x, y, z)]; } -uint8_t Chunk::getDataAt(const std::shared_ptr §ion, size_t x, size_t y, size_t z) { +uint8_t Chunk::getDataAt(const std::shared_ptr §ion, size_t x, size_t y, size_t z) const { size_t i = getIndex(x, y, z); uint8_t v = (*section->get("Data"))[i / 2]; @@ -111,18 +125,37 @@ uint8_t Chunk::getDataAt(const std::shared_ptr §ion, return (v & 0xf); } -Chunk::Chunk(Buffer buffer) { - size_t size = buffer.get32(); +Chunk::Blocks Chunk::getTopLayer() const { + size_t done = 0; + Blocks blocks = {}; + + for (auto it = sections->rbegin(); it != sections->rend(); ++it) { + if (done == SIZE*SIZE) + break; + + for (ssize_t y = SIZE-1; y >= 0; y--) { + if (done == SIZE*SIZE) + break; + + for (size_t x = 0; x < SIZE; x++) { + for (size_t z = 0; z < SIZE; z++) { + if (blocks.blocks[x][z].id) + continue; + + uint8_t block = getBlockAt(*it, x, y, z); + if (block) { + blocks.blocks[x][z].id = block; + blocks.blocks[x][z].data = getDataAt(*it, x, y, z); + done++; + } + } + } + } + } - Buffer buffer2(buffer.get(size), size); + std::cerr << "Done: " << done << std::endl; - uint8_t format = buffer2.get8(); - if (format != 2) - throw std::invalid_argument("unknown chunk format"); - - inflateChunk(buffer2); - parseChunk(); - analyzeChunk(); + return blocks; } } diff --git a/src/World/Chunk.hpp b/src/World/Chunk.hpp index d063d48..22054db 100644 --- a/src/World/Chunk.hpp +++ b/src/World/Chunk.hpp @@ -27,6 +27,7 @@ #pragma once +#include "Block.hpp" #include "../Buffer.hpp" #include "../UniqueCPtr.hpp" #include "../NBT/CompoundTag.hpp" @@ -43,7 +44,18 @@ class Chunk : public std::shared_ptr { public: static const size_t SIZE = 16; + struct Blocks { + Block blocks[SIZE][SIZE]; + }; + private: + static size_t getIndex(size_t x, size_t y, size_t z) { + if (x >= SIZE || y >= SIZE || z >= SIZE) + throw std::range_error("Chunk::getIndex(): bad coordinates"); + + return 256*y + 16*z + x; + } + size_t len; UniqueCPtr data; @@ -56,15 +68,8 @@ private: void parseChunk(); void analyzeChunk(); - size_t getIndex(size_t x, size_t y, size_t z) { - if (x >= SIZE || y >= SIZE || z >= SIZE) - throw std::range_error("Chunk::getIndex(): bad coordinates"); - - return 256*y + 16*z + x; - } - - uint8_t getBlockAt(const std::shared_ptr §ion, size_t x, size_t y, size_t z); - uint8_t getDataAt(const std::shared_ptr §ion, size_t x, size_t y, size_t z); + uint8_t getBlockAt(const std::shared_ptr §ion, size_t x, size_t y, size_t z) const; + uint8_t getDataAt(const std::shared_ptr §ion, size_t x, size_t y, size_t z) const; public: Chunk(Buffer buffer); @@ -72,6 +77,8 @@ public: const NBT::ListTag & getSections() const { return *sections; } + + Blocks getTopLayer() const; }; } -- cgit v1.2.3