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/Level.cpp
|
||||
World/Region.cpp
|
||||
World/Section.cpp
|
||||
)
|
||||
set_target_properties(MinedMap PROPERTIES COMPILE_FLAGS "-std=c++11 -Wall")
|
||||
target_link_libraries(MinedMap ${ZLIB_LIBRARIES} ${PNG_LIBRARIES})
|
||||
|
|
|
@ -26,14 +26,12 @@
|
|||
|
||||
#include "Block.hpp"
|
||||
#include "../Resource/Biome.hpp"
|
||||
#include "../Resource/BlockType.hpp"
|
||||
|
||||
|
||||
namespace MinedMap {
|
||||
namespace World {
|
||||
|
||||
uint32_t Block::getColor() const {
|
||||
const Resource::BlockType *type = Resource::LEGACY_BLOCK_TYPES.types[id][data];
|
||||
if (!type || !type->opaque)
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -26,28 +26,25 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include "../NBT/CompoundTag.hpp"
|
||||
#include "../Resource/BlockType.hpp"
|
||||
|
||||
|
||||
namespace MinedMap {
|
||||
namespace World {
|
||||
|
||||
struct Block {
|
||||
uint8_t id;
|
||||
uint8_t data;
|
||||
|
||||
const Resource::BlockType *type;
|
||||
unsigned height;
|
||||
|
||||
uint8_t blockLight;
|
||||
uint8_t skyLight;
|
||||
|
||||
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;
|
||||
|
||||
operator bool() const {
|
||||
return type;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -25,14 +25,11 @@
|
|||
|
||||
|
||||
#include "Chunk.hpp"
|
||||
#include "../Resource/BlockType.hpp"
|
||||
#include "../NBT/ListTag.hpp"
|
||||
#include "../NBT/StringTag.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include <zlib.h>
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
namespace MinedMap {
|
||||
|
@ -41,100 +38,77 @@ namespace World {
|
|||
Chunk::Chunk(const ChunkData *data) {
|
||||
level = assertValue(data->getRoot().get<NBT::CompoundTag>("Level"));
|
||||
|
||||
std::shared_ptr<const NBT::ByteTag> lightPopulatedTag = level->get<NBT::ByteTag>("LightPopulated");
|
||||
bool lightPopulated = lightPopulatedTag && lightPopulatedTag->getValue();
|
||||
std::shared_ptr<const NBT::ListTag> sectionsTag = level->get<NBT::ListTag>("Sections");
|
||||
if (!sectionsTag)
|
||||
return;
|
||||
|
||||
sections = assertValue(level->get<NBT::ListTag>("Sections"));
|
||||
const NBT::CompoundTag *lastSection = assertValue(dynamic_cast<const NBT::CompoundTag *>(sections->back().get()));
|
||||
maxY = (assertValue(lastSection->get<NBT::ByteTag>("Y"))->getValue() + 1) * SIZE;
|
||||
biomeBytes = level->get<NBT::ByteArrayTag>("Biomes");
|
||||
biomeInts = level->get<NBT::IntArrayTag>("Biomes");
|
||||
assertValue(biomeBytes || biomeInts);
|
||||
|
||||
|
||||
std::shared_ptr<const NBT::ByteArrayTag> biomeTag = assertValue(level->get<NBT::ByteArrayTag>("Biomes"));
|
||||
if (biomeTag->getLength() != SIZE*SIZE)
|
||||
if (biomeBytes && biomeBytes->getLength() != SIZE*SIZE)
|
||||
throw std::invalid_argument("corrupt biome data");
|
||||
else if (biomeInts && biomeInts->getLength() != SIZE*SIZE)
|
||||
throw std::invalid_argument("corrupt biome data");
|
||||
|
||||
biomes = biomeTag->getValue();
|
||||
|
||||
blockIDs.reset(new uint8_t[maxY * SIZE * SIZE]);
|
||||
blockData.reset(new uint8_t[maxY * SIZE * SIZE / 2]);
|
||||
blockSkyLight.reset(new uint8_t[maxY * SIZE * SIZE / 2]);
|
||||
blockBlockLight.reset(new uint8_t[maxY * SIZE * SIZE / 2]);
|
||||
|
||||
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);
|
||||
for (auto &sTag : *sectionsTag) {
|
||||
auto s = std::dynamic_pointer_cast<const NBT::CompoundTag>(sTag);
|
||||
std::unique_ptr<Section> section = Section::makeSection(s);
|
||||
size_t Y = section->getY();
|
||||
sections.resize(Y);
|
||||
sections.push_back(std::move(section));
|
||||
}
|
||||
}
|
||||
|
||||
Block Chunk::getBlock(size_t x, size_t y, size_t z) const {
|
||||
size_t y2 = y;
|
||||
if (y2 < maxY-1)
|
||||
y2++;
|
||||
bool Chunk::getBlock(Block *block, const Section *section, size_t x, size_t y, size_t z, uint8_t prev_light) const {
|
||||
if (block->height > 0)
|
||||
return false;
|
||||
|
||||
unsigned h;
|
||||
for (h = y; h > 0; h--) {
|
||||
uint8_t id2 = getBlockAt(x, h, z);
|
||||
if (id2 != 8 && id2 != 9)
|
||||
break;
|
||||
const Resource::BlockType *type = section->getBlockStateAt(x, y, z);
|
||||
if (!type || !type->opaque)
|
||||
return false;
|
||||
|
||||
if (!block->type) {
|
||||
block->type = type;
|
||||
block->blockLight = prev_light;
|
||||
block->biome = getBiomeAt(x, z);
|
||||
}
|
||||
|
||||
return Block(
|
||||
getBlockAt(x, y, z),
|
||||
getDataAt(x, y, z),
|
||||
h,
|
||||
getBlockLightAt(x, y2, z),
|
||||
getSkyLightAt(x, y2, z),
|
||||
getBiomeAt(x, z)
|
||||
);
|
||||
if (type->blue)
|
||||
return false;
|
||||
|
||||
block->height = SIZE*section->getY() + y;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Chunk::Blocks Chunk::getTopLayer() const {
|
||||
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)
|
||||
break;
|
||||
|
||||
if (!sections[Y]) {
|
||||
std::memset(prev_light, 0, sizeof(prev_light));
|
||||
continue;
|
||||
}
|
||||
|
||||
const Section *section = sections[Y].get();
|
||||
|
||||
for (ssize_t y = SIZE-1; y >= 0; y--) {
|
||||
if (done == SIZE*SIZE)
|
||||
break;
|
||||
|
||||
for (size_t z = 0; z < SIZE; z++) {
|
||||
for (size_t x = 0; x < SIZE; x++) {
|
||||
if (ret.blocks[x][z].id)
|
||||
continue;
|
||||
|
||||
uint8_t id = getBlockAt(x, y, z);
|
||||
uint8_t data = getDataAt(x, y, z);
|
||||
|
||||
const Resource::BlockType *type = Resource::LEGACY_BLOCK_TYPES.types[id][data];
|
||||
if (!type || !type->opaque)
|
||||
continue;
|
||||
|
||||
ret.blocks[x][z] = getBlock(x, y, z);
|
||||
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 "ChunkData.hpp"
|
||||
#include "../Util.hpp"
|
||||
#include "../NBT/ListTag.hpp"
|
||||
#include "../NBT/ByteTag.hpp"
|
||||
#include "Section.hpp"
|
||||
#include "../NBT/ByteArrayTag.hpp"
|
||||
#include "../NBT/IntArrayTag.hpp"
|
||||
#include "../Resource/BlockType.hpp"
|
||||
#include "../Util.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <tuple>
|
||||
|
||||
|
||||
namespace MinedMap {
|
||||
|
@ -43,63 +43,28 @@ namespace World {
|
|||
|
||||
class Chunk {
|
||||
public:
|
||||
static const size_t SIZE = 16;
|
||||
static const size_t SIZE = Section::SIZE;
|
||||
|
||||
struct Blocks {
|
||||
Block blocks[SIZE][SIZE];
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
std::shared_ptr<const NBT::CompoundTag> level;
|
||||
std::shared_ptr<const NBT::ListTag> sections;
|
||||
std::vector<std::unique_ptr<Section>> sections;
|
||||
|
||||
|
||||
unsigned maxY;
|
||||
|
||||
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);
|
||||
}
|
||||
std::shared_ptr<const NBT::ByteArrayTag> biomeBytes;
|
||||
std::shared_ptr<const NBT::IntArrayTag> biomeInts;
|
||||
|
||||
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:
|
||||
Chunk(const ChunkData *data);
|
||||
|
||||
|
@ -107,11 +72,15 @@ public:
|
|||
return *level;
|
||||
}
|
||||
|
||||
const NBT::ListTag & getSections() const {
|
||||
return *sections;
|
||||
const Resource::BlockType * getBlockStateAt(size_t x, size_t y, size_t z) const {
|
||||
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;
|
||||
};
|
||||
|
||||
|
|
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