mirror of
https://github.com/neocturne/MinedMap.git
synced 2025-03-05 17:44:52 +01:00
World: factor out Section handling to a generic interface
This commit is contained in:
parent
dd432af298
commit
210f651807
7 changed files with 248 additions and 143 deletions
|
@ -15,6 +15,7 @@ add_executable(MinedMap
|
||||||
World/ChunkData.cpp
|
World/ChunkData.cpp
|
||||||
World/Level.cpp
|
World/Level.cpp
|
||||||
World/Region.cpp
|
World/Region.cpp
|
||||||
|
World/Section.cpp
|
||||||
)
|
)
|
||||||
set_target_properties(MinedMap PROPERTIES COMPILE_FLAGS "-std=c++11 -Wall")
|
set_target_properties(MinedMap PROPERTIES COMPILE_FLAGS "-std=c++11 -Wall")
|
||||||
target_link_libraries(MinedMap ${ZLIB_LIBRARIES} ${PNG_LIBRARIES})
|
target_link_libraries(MinedMap ${ZLIB_LIBRARIES} ${PNG_LIBRARIES})
|
||||||
|
|
|
@ -26,14 +26,12 @@
|
||||||
|
|
||||||
#include "Block.hpp"
|
#include "Block.hpp"
|
||||||
#include "../Resource/Biome.hpp"
|
#include "../Resource/Biome.hpp"
|
||||||
#include "../Resource/BlockType.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace MinedMap {
|
namespace MinedMap {
|
||||||
namespace World {
|
namespace World {
|
||||||
|
|
||||||
uint32_t Block::getColor() const {
|
uint32_t Block::getColor() const {
|
||||||
const Resource::BlockType *type = Resource::LEGACY_BLOCK_TYPES.types[id][data];
|
|
||||||
if (!type || !type->opaque)
|
if (!type || !type->opaque)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
|
@ -26,28 +26,25 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint>
|
#include "../NBT/CompoundTag.hpp"
|
||||||
|
#include "../Resource/BlockType.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace MinedMap {
|
namespace MinedMap {
|
||||||
namespace World {
|
namespace World {
|
||||||
|
|
||||||
struct Block {
|
struct Block {
|
||||||
uint8_t id;
|
const Resource::BlockType *type;
|
||||||
uint8_t data;
|
|
||||||
|
|
||||||
unsigned height;
|
unsigned height;
|
||||||
|
|
||||||
uint8_t blockLight;
|
uint8_t blockLight;
|
||||||
uint8_t skyLight;
|
|
||||||
|
|
||||||
uint8_t biome;
|
uint8_t biome;
|
||||||
|
|
||||||
Block() : id(0), data(0), height(0), blockLight(0), skyLight(0), biome(0) {}
|
|
||||||
Block(uint8_t id0, uint8_t data0, unsigned height0, uint8_t blockLight0, uint8_t skyLight0, uint8_t biome0)
|
|
||||||
: id(id0), data(data0), height(height0), blockLight(blockLight0), skyLight(skyLight0), biome(biome0) {}
|
|
||||||
|
|
||||||
uint32_t getColor() const;
|
uint32_t getColor() const;
|
||||||
|
|
||||||
|
operator bool() const {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,14 +25,11 @@
|
||||||
|
|
||||||
|
|
||||||
#include "Chunk.hpp"
|
#include "Chunk.hpp"
|
||||||
#include "../Resource/BlockType.hpp"
|
#include "../NBT/ListTag.hpp"
|
||||||
|
#include "../NBT/StringTag.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <stdexcept>
|
||||||
#include <zlib.h>
|
|
||||||
|
|
||||||
|
|
||||||
namespace MinedMap {
|
namespace MinedMap {
|
||||||
|
@ -41,100 +38,77 @@ namespace World {
|
||||||
Chunk::Chunk(const ChunkData *data) {
|
Chunk::Chunk(const ChunkData *data) {
|
||||||
level = assertValue(data->getRoot().get<NBT::CompoundTag>("Level"));
|
level = assertValue(data->getRoot().get<NBT::CompoundTag>("Level"));
|
||||||
|
|
||||||
std::shared_ptr<const NBT::ByteTag> lightPopulatedTag = level->get<NBT::ByteTag>("LightPopulated");
|
std::shared_ptr<const NBT::ListTag> sectionsTag = level->get<NBT::ListTag>("Sections");
|
||||||
bool lightPopulated = lightPopulatedTag && lightPopulatedTag->getValue();
|
if (!sectionsTag)
|
||||||
|
return;
|
||||||
|
|
||||||
sections = assertValue(level->get<NBT::ListTag>("Sections"));
|
biomeBytes = level->get<NBT::ByteArrayTag>("Biomes");
|
||||||
const NBT::CompoundTag *lastSection = assertValue(dynamic_cast<const NBT::CompoundTag *>(sections->back().get()));
|
biomeInts = level->get<NBT::IntArrayTag>("Biomes");
|
||||||
maxY = (assertValue(lastSection->get<NBT::ByteTag>("Y"))->getValue() + 1) * SIZE;
|
assertValue(biomeBytes || biomeInts);
|
||||||
|
|
||||||
|
if (biomeBytes && biomeBytes->getLength() != SIZE*SIZE)
|
||||||
std::shared_ptr<const NBT::ByteArrayTag> biomeTag = assertValue(level->get<NBT::ByteArrayTag>("Biomes"));
|
throw std::invalid_argument("corrupt biome data");
|
||||||
if (biomeTag->getLength() != SIZE*SIZE)
|
else if (biomeInts && biomeInts->getLength() != SIZE*SIZE)
|
||||||
throw std::invalid_argument("corrupt biome data");
|
throw std::invalid_argument("corrupt biome data");
|
||||||
|
|
||||||
biomes = biomeTag->getValue();
|
for (auto &sTag : *sectionsTag) {
|
||||||
|
auto s = std::dynamic_pointer_cast<const NBT::CompoundTag>(sTag);
|
||||||
blockIDs.reset(new uint8_t[maxY * SIZE * SIZE]);
|
std::unique_ptr<Section> section = Section::makeSection(s);
|
||||||
blockData.reset(new uint8_t[maxY * SIZE * SIZE / 2]);
|
size_t Y = section->getY();
|
||||||
blockSkyLight.reset(new uint8_t[maxY * SIZE * SIZE / 2]);
|
sections.resize(Y);
|
||||||
blockBlockLight.reset(new uint8_t[maxY * SIZE * SIZE / 2]);
|
sections.push_back(std::move(section));
|
||||||
|
|
||||||
std::memset(blockIDs.get(), 0, maxY * SIZE * SIZE);
|
|
||||||
std::memset(blockData.get(), 0, maxY * SIZE * SIZE / 2);
|
|
||||||
std::memset(blockSkyLight.get(), 0xff, maxY * SIZE * SIZE / 2);
|
|
||||||
std::memset(blockBlockLight.get(), 0, maxY * SIZE * SIZE / 2);
|
|
||||||
|
|
||||||
|
|
||||||
for (auto §ionTag : *sections) {
|
|
||||||
const NBT::CompoundTag *section = assertValue(dynamic_cast<const NBT::CompoundTag *>(sectionTag.get()));
|
|
||||||
std::shared_ptr<const NBT::ByteArrayTag> blocks = assertValue(section->get<NBT::ByteArrayTag>("Blocks"));
|
|
||||||
std::shared_ptr<const NBT::ByteArrayTag> data = assertValue(section->get<NBT::ByteArrayTag>("Data"));
|
|
||||||
size_t Y = assertValue(section->get<NBT::ByteTag>("Y"))->getValue();
|
|
||||||
|
|
||||||
if (blocks->getLength() != SIZE*SIZE*SIZE || data->getLength() != SIZE*SIZE*SIZE/2)
|
|
||||||
throw std::invalid_argument("corrupt chunk data");
|
|
||||||
|
|
||||||
if (lightPopulated) {
|
|
||||||
std::shared_ptr<const NBT::ByteArrayTag> blockLight = assertValue(section->get<NBT::ByteArrayTag>("BlockLight"));
|
|
||||||
std::shared_ptr<const NBT::ByteArrayTag> skyLight = assertValue(section->get<NBT::ByteArrayTag>("SkyLight"));
|
|
||||||
|
|
||||||
if (blockLight->getLength() != SIZE*SIZE*SIZE/2 || skyLight->getLength() != SIZE*SIZE*SIZE/2)
|
|
||||||
throw std::invalid_argument("corrupt chunk data");
|
|
||||||
|
|
||||||
std::memcpy(blockBlockLight.get() + Y*SIZE*SIZE*SIZE/2, blockLight->getValue(), SIZE*SIZE*SIZE/2);
|
|
||||||
std::memcpy(blockSkyLight.get() + Y*SIZE*SIZE*SIZE/2, skyLight->getValue(), SIZE*SIZE*SIZE/2);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::memcpy(blockIDs.get() + Y*SIZE*SIZE*SIZE, blocks->getValue(), SIZE*SIZE*SIZE);
|
|
||||||
std::memcpy(blockData.get() + Y*SIZE*SIZE*SIZE/2, data->getValue(), SIZE*SIZE*SIZE/2);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Block Chunk::getBlock(size_t x, size_t y, size_t z) const {
|
bool Chunk::getBlock(Block *block, const Section *section, size_t x, size_t y, size_t z, uint8_t prev_light) const {
|
||||||
size_t y2 = y;
|
if (block->height > 0)
|
||||||
if (y2 < maxY-1)
|
return false;
|
||||||
y2++;
|
|
||||||
|
|
||||||
unsigned h;
|
const Resource::BlockType *type = section->getBlockStateAt(x, y, z);
|
||||||
for (h = y; h > 0; h--) {
|
if (!type || !type->opaque)
|
||||||
uint8_t id2 = getBlockAt(x, h, z);
|
return false;
|
||||||
if (id2 != 8 && id2 != 9)
|
|
||||||
break;
|
if (!block->type) {
|
||||||
|
block->type = type;
|
||||||
|
block->blockLight = prev_light;
|
||||||
|
block->biome = getBiomeAt(x, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Block(
|
if (type->blue)
|
||||||
getBlockAt(x, y, z),
|
return false;
|
||||||
getDataAt(x, y, z),
|
|
||||||
h,
|
block->height = SIZE*section->getY() + y;
|
||||||
getBlockLightAt(x, y2, z),
|
|
||||||
getSkyLightAt(x, y2, z),
|
return true;
|
||||||
getBiomeAt(x, z)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Chunk::Blocks Chunk::getTopLayer() const {
|
Chunk::Blocks Chunk::getTopLayer() const {
|
||||||
size_t done = 0;
|
size_t done = 0;
|
||||||
Blocks ret;
|
Blocks ret = {};
|
||||||
|
uint8_t prev_light[SIZE][SIZE] = {};
|
||||||
|
|
||||||
for (ssize_t y = maxY-1; y >= 0; y--) {
|
for (ssize_t Y = sections.size() - 1; Y >= 0; Y--) {
|
||||||
if (done == SIZE*SIZE)
|
if (done == SIZE*SIZE)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
for (size_t z = 0; z < SIZE; z++) {
|
if (!sections[Y]) {
|
||||||
for (size_t x = 0; x < SIZE; x++) {
|
std::memset(prev_light, 0, sizeof(prev_light));
|
||||||
if (ret.blocks[x][z].id)
|
continue;
|
||||||
continue;
|
}
|
||||||
|
|
||||||
uint8_t id = getBlockAt(x, y, z);
|
const Section *section = sections[Y].get();
|
||||||
uint8_t data = getDataAt(x, y, z);
|
|
||||||
|
|
||||||
const Resource::BlockType *type = Resource::LEGACY_BLOCK_TYPES.types[id][data];
|
for (ssize_t y = SIZE-1; y >= 0; y--) {
|
||||||
if (!type || !type->opaque)
|
if (done == SIZE*SIZE)
|
||||||
continue;
|
break;
|
||||||
|
|
||||||
ret.blocks[x][z] = getBlock(x, y, z);
|
for (size_t z = 0; z < SIZE; z++) {
|
||||||
done++;
|
for (size_t x = 0; x < SIZE; x++) {
|
||||||
|
if (getBlock(&ret.blocks[x][z], section, x, y, z, prev_light[x][z]))
|
||||||
|
done++;
|
||||||
|
|
||||||
|
prev_light[x][z] = section->getBlockLightAt(x, y, z);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,13 +29,13 @@
|
||||||
|
|
||||||
#include "Block.hpp"
|
#include "Block.hpp"
|
||||||
#include "ChunkData.hpp"
|
#include "ChunkData.hpp"
|
||||||
#include "../Util.hpp"
|
#include "Section.hpp"
|
||||||
#include "../NBT/ListTag.hpp"
|
|
||||||
#include "../NBT/ByteTag.hpp"
|
|
||||||
#include "../NBT/ByteArrayTag.hpp"
|
#include "../NBT/ByteArrayTag.hpp"
|
||||||
|
#include "../NBT/IntArrayTag.hpp"
|
||||||
|
#include "../Resource/BlockType.hpp"
|
||||||
|
#include "../Util.hpp"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <tuple>
|
|
||||||
|
|
||||||
|
|
||||||
namespace MinedMap {
|
namespace MinedMap {
|
||||||
|
@ -43,63 +43,28 @@ namespace World {
|
||||||
|
|
||||||
class Chunk {
|
class Chunk {
|
||||||
public:
|
public:
|
||||||
static const size_t SIZE = 16;
|
static const size_t SIZE = Section::SIZE;
|
||||||
|
|
||||||
struct Blocks {
|
struct Blocks {
|
||||||
Block blocks[SIZE][SIZE];
|
Block blocks[SIZE][SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<const NBT::CompoundTag> level;
|
std::shared_ptr<const NBT::CompoundTag> level;
|
||||||
std::shared_ptr<const NBT::ListTag> sections;
|
std::vector<std::unique_ptr<Section>> sections;
|
||||||
|
|
||||||
|
std::shared_ptr<const NBT::ByteArrayTag> biomeBytes;
|
||||||
unsigned maxY;
|
std::shared_ptr<const NBT::IntArrayTag> biomeInts;
|
||||||
|
|
||||||
std::unique_ptr<uint8_t[]> blockIDs;
|
|
||||||
std::unique_ptr<uint8_t[]> blockData;
|
|
||||||
std::unique_ptr<uint8_t[]> blockSkyLight;
|
|
||||||
std::unique_ptr<uint8_t[]> blockBlockLight;
|
|
||||||
const uint8_t *biomes;
|
|
||||||
|
|
||||||
|
|
||||||
size_t getIndex(size_t x, size_t y, size_t z) const {
|
|
||||||
if (x >= SIZE || y >= maxY || z >= SIZE)
|
|
||||||
throw std::range_error("Chunk::getIndex(): bad coordinates");
|
|
||||||
|
|
||||||
return SIZE*SIZE*y + SIZE*z + x;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t getHalf(const uint8_t *v, size_t x, size_t y, size_t z) const {
|
|
||||||
size_t i = getIndex(x, y, z);
|
|
||||||
|
|
||||||
if (i % 2)
|
|
||||||
return (v[i/2] >> 4);
|
|
||||||
else
|
|
||||||
return (v[i/2] & 0xf);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t getBlockAt(size_t x, size_t y, size_t z) const {
|
|
||||||
return blockIDs[getIndex(x, y, z)];
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t getDataAt(size_t x, size_t y, size_t z) const {
|
|
||||||
return getHalf(blockData.get(), x, y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t getBlockLightAt(size_t x, size_t y, size_t z) const {
|
|
||||||
return getHalf(blockBlockLight.get(), x, y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t getSkyLightAt(size_t x, size_t y, size_t z) const {
|
|
||||||
return getHalf(blockSkyLight.get(), x, y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t getBiomeAt(size_t x, size_t z) const {
|
uint8_t getBiomeAt(size_t x, size_t z) const {
|
||||||
return biomes[z*SIZE + x];
|
if (biomeBytes)
|
||||||
|
return biomeBytes->getValue()[z*SIZE + x];
|
||||||
|
else
|
||||||
|
return biomeInts->getValue(z*SIZE + x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool getBlock(Block *block, const Section *section, size_t x, size_t y, size_t z, uint8_t prev_light) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Chunk(const ChunkData *data);
|
Chunk(const ChunkData *data);
|
||||||
|
|
||||||
|
@ -107,11 +72,15 @@ public:
|
||||||
return *level;
|
return *level;
|
||||||
}
|
}
|
||||||
|
|
||||||
const NBT::ListTag & getSections() const {
|
const Resource::BlockType * getBlockStateAt(size_t x, size_t y, size_t z) const {
|
||||||
return *sections;
|
size_t Y = y / SIZE;
|
||||||
|
|
||||||
|
if (Y >= sections.size() || !sections[Y])
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return sections[Y]->getBlockStateAt(x, y % SIZE, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
Block getBlock(size_t x, size_t y, size_t z) const;
|
|
||||||
Blocks getTopLayer() const;
|
Blocks getTopLayer() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
56
src/World/Section.cpp
Normal file
56
src/World/Section.cpp
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2015-2018, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "Section.hpp"
|
||||||
|
#include "../NBT/ByteTag.hpp"
|
||||||
|
#include "../Util.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace MinedMap {
|
||||||
|
namespace World {
|
||||||
|
|
||||||
|
Section::Section(const std::shared_ptr<const NBT::CompoundTag> §ion) {
|
||||||
|
Y = assertValue(section->get<NBT::ByteTag>("Y"))->getValue();
|
||||||
|
blockLight = section->get<NBT::ByteArrayTag>("BlockLight");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::unique_ptr<Section> Section::makeSection(const std::shared_ptr<const NBT::CompoundTag> §ion) {
|
||||||
|
std::shared_ptr<const NBT::ByteArrayTag> blocks = assertValue(section->get<NBT::ByteArrayTag>("Blocks"));
|
||||||
|
std::shared_ptr<const NBT::ByteArrayTag> data = assertValue(section->get<NBT::ByteArrayTag>("Data"));
|
||||||
|
|
||||||
|
return std::unique_ptr<Section>(new LegacySection(section, std::move(blocks), std::move(data)));
|
||||||
|
}
|
||||||
|
|
||||||
|
const Resource::BlockType * LegacySection::getBlockStateAt(size_t x, size_t y, size_t z) const {
|
||||||
|
uint8_t type = getBlockAt(x, y, z);
|
||||||
|
uint8_t data = getDataAt(x, y, z);
|
||||||
|
|
||||||
|
return Resource::LEGACY_BLOCK_TYPES.types[type][data];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
110
src/World/Section.hpp
Normal file
110
src/World/Section.hpp
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2015-2018, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||||
|
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 "../NBT/ByteArrayTag.hpp"
|
||||||
|
#include "../NBT/CompoundTag.hpp"
|
||||||
|
#include "../Resource/BlockType.hpp"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
|
||||||
|
namespace MinedMap {
|
||||||
|
namespace World {
|
||||||
|
|
||||||
|
class Section {
|
||||||
|
public:
|
||||||
|
static const size_t SIZE = 16;
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t Y;
|
||||||
|
std::shared_ptr<const NBT::ByteArrayTag> blockLight;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
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 SIZE*SIZE*y + SIZE*z + x;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t getHalf(const uint8_t *v, size_t x, size_t y, size_t z) {
|
||||||
|
size_t i = getIndex(x, y, z);
|
||||||
|
|
||||||
|
if (i % 2)
|
||||||
|
return (v[i/2] >> 4);
|
||||||
|
else
|
||||||
|
return (v[i/2] & 0xf);
|
||||||
|
}
|
||||||
|
|
||||||
|
Section(const std::shared_ptr<const NBT::CompoundTag> §ion);
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~Section() {}
|
||||||
|
|
||||||
|
size_t getY() const { return Y; };
|
||||||
|
|
||||||
|
virtual const Resource::BlockType * getBlockStateAt(size_t x, size_t y, size_t z) const = 0;
|
||||||
|
|
||||||
|
uint8_t getBlockLightAt(size_t x, size_t y, size_t z) const {
|
||||||
|
if (!blockLight)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return getHalf(blockLight->getValue(), x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::unique_ptr<Section> makeSection(const std::shared_ptr<const NBT::CompoundTag> §ion);
|
||||||
|
};
|
||||||
|
|
||||||
|
class LegacySection : public Section {
|
||||||
|
private:
|
||||||
|
std::shared_ptr<const NBT::ByteArrayTag> blocks;
|
||||||
|
std::shared_ptr<const NBT::ByteArrayTag> data;
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t getBlockAt(size_t x, size_t y, size_t z) const {
|
||||||
|
return blocks->getValue()[getIndex(x, y, z)];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t getDataAt(size_t x, size_t y, size_t z) const {
|
||||||
|
return getHalf(data->getValue(), x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
LegacySection(
|
||||||
|
const std::shared_ptr<const NBT::CompoundTag> §ion,
|
||||||
|
std::shared_ptr<const NBT::ByteArrayTag> &&blocks0,
|
||||||
|
std::shared_ptr<const NBT::ByteArrayTag> &&data0
|
||||||
|
) : Section(section), blocks(blocks0), data(data0) {}
|
||||||
|
|
||||||
|
virtual const Resource::BlockType * getBlockStateAt(size_t x, size_t y, size_t z) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue