mirror of
https://github.com/neocturne/MinedMap.git
synced 2025-07-08 08:39:07 +02:00
Introduce separate types for block/section/chunk indices
Newtypes are cumbersome in C++, so this is mostly documentation for now. Also replace lots of questionable uses of size_t with int or types with explicit width and add a few comments for constants.
This commit is contained in:
parent
d4be401bcd
commit
457e993c92
13 changed files with 123 additions and 92 deletions
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2015, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) 2015-2021, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
@ -17,7 +17,7 @@ namespace World {
|
|||
|
||||
struct Block {
|
||||
const Resource::BlockType *type;
|
||||
unsigned depth;
|
||||
y_idx_t depth;
|
||||
uint8_t blockLight;
|
||||
|
||||
bool isVisible() const {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2015-2019, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) 2015-2021, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
@ -42,13 +42,13 @@ Chunk::Chunk(const ChunkData *data) {
|
|||
for (auto &sTag : *sectionsTag) {
|
||||
auto s = std::dynamic_pointer_cast<const NBT::CompoundTag>(sTag);
|
||||
std::unique_ptr<Section> section = Section::makeSection(s, dataVersion);
|
||||
size_t Y = section->getY();
|
||||
section_idx_t Y = section->getY();
|
||||
sections.resize(Y);
|
||||
sections.push_back(std::move(section));
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t Chunk::getBiome(size_t x, size_t y, size_t z) const {
|
||||
uint8_t Chunk::getBiome(block_idx_t x, y_idx_t y, block_idx_t z) const {
|
||||
if (x > SIZE || y > MAXY || z > SIZE)
|
||||
throw std::invalid_argument("corrupt chunk data");
|
||||
|
||||
|
@ -62,19 +62,19 @@ uint8_t Chunk::getBiome(size_t x, size_t y, size_t z) const {
|
|||
return 0xff;
|
||||
}
|
||||
|
||||
Block Chunk::getBlock(size_t x, Chunk::Height height, size_t z) const {
|
||||
Block Chunk::getBlock(block_idx_t x, Chunk::Height height, block_idx_t z) const {
|
||||
Block block = {};
|
||||
|
||||
block.depth = height.depth;
|
||||
|
||||
size_t Y = height.y / SIZE;
|
||||
size_t y = height.y % SIZE;
|
||||
section_idx_t Y = height.y / SIZE;
|
||||
block_idx_t y = height.y % SIZE;
|
||||
|
||||
if (Y < sections.size() && sections[Y])
|
||||
block.type = sections[Y]->getBlockStateAt(x, y, z);
|
||||
|
||||
size_t Yt = (height.y + 1) / SIZE;
|
||||
size_t yt = (height.y + 1) % SIZE;
|
||||
section_idx_t Yt = (height.y + 1) / SIZE;
|
||||
block_idx_t yt = (height.y + 1) % SIZE;
|
||||
|
||||
if (Yt < sections.size() && sections[Yt])
|
||||
block.blockLight = sections[Yt]->getBlockLightAt(x, yt, z);
|
||||
|
@ -82,7 +82,10 @@ Block Chunk::getBlock(size_t x, Chunk::Height height, size_t z) const {
|
|||
return block;
|
||||
}
|
||||
|
||||
bool Chunk::getHeight(Chunk::Height *height, const Section *section, size_t x, size_t y, size_t z, int flags) const {
|
||||
bool Chunk::getHeight(
|
||||
Chunk::Height *height, const Section *section,
|
||||
block_idx_t x, block_idx_t y, block_idx_t z, int flags
|
||||
) const {
|
||||
if (height->depth > 0)
|
||||
return false;
|
||||
|
||||
|
@ -108,10 +111,10 @@ bool Chunk::getHeight(Chunk::Height *height, const Section *section, size_t x, s
|
|||
}
|
||||
|
||||
Chunk::Heightmap Chunk::getTopLayer(int flags) const {
|
||||
size_t done = 0;
|
||||
uint32_t done = 0;
|
||||
Heightmap ret = {};
|
||||
|
||||
for (ssize_t Y = sections.size() - 1; Y >= 0; Y--) {
|
||||
for (int16_t Y = sections.size() - 1; Y >= 0; Y--) {
|
||||
if (done == SIZE*SIZE)
|
||||
break;
|
||||
|
||||
|
@ -120,12 +123,12 @@ Chunk::Heightmap Chunk::getTopLayer(int flags) const {
|
|||
|
||||
const Section *section = sections[Y].get();
|
||||
|
||||
for (ssize_t y = SIZE-1; y >= 0; y--) {
|
||||
for (int8_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++) {
|
||||
for (block_idx_t z = 0; z < SIZE; z++) {
|
||||
for (block_idx_t x = 0; x < SIZE; x++) {
|
||||
if (getHeight(&ret.v[x][z], section, x, y, z, flags))
|
||||
done++;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2015-2018, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) 2015-2021, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
@ -24,19 +24,25 @@ namespace World {
|
|||
|
||||
class Chunk {
|
||||
public:
|
||||
static const size_t SIZE = Section::SIZE;
|
||||
static const size_t MAXY = 256;
|
||||
// Number of blocks in a chunk in x/z dimensions
|
||||
static const uint32_t SIZE = Section::SIZE;
|
||||
// Maximum Y value
|
||||
static const y_idx_t MAXY = 256;
|
||||
|
||||
static const size_t BGROUP = 4;
|
||||
static const size_t BSIZE = SIZE / BGROUP;
|
||||
static const size_t BMAXY = MAXY / BGROUP;
|
||||
// Since Minecraft 1.15, biome information is stored for
|
||||
// 4x4x4 block groups
|
||||
static const uint32_t BGROUP = 4;
|
||||
// Number of biome values in a chunk in x/z dimensions
|
||||
static const uint32_t BSIZE = SIZE / BGROUP;
|
||||
// Number of biome values in a chunk in y dimension
|
||||
static const uint32_t BMAXY = MAXY / BGROUP;
|
||||
|
||||
// Flags
|
||||
static const int WITH_DEPTH = (1 << 0);
|
||||
|
||||
struct Height {
|
||||
unsigned y;
|
||||
unsigned depth;
|
||||
y_idx_t y;
|
||||
y_idx_t depth;
|
||||
};
|
||||
|
||||
struct Heightmap {
|
||||
|
@ -51,10 +57,13 @@ private:
|
|||
std::shared_ptr<const NBT::IntArrayTag> biomeIntsPre115;
|
||||
std::shared_ptr<const NBT::IntArrayTag> biomeInts;
|
||||
|
||||
bool getHeight(Height *height, const Section *section, size_t x, size_t y, size_t z, int flags) const;
|
||||
bool getHeight(
|
||||
Height *height, const Section *section,
|
||||
block_idx_t x, block_idx_t y, block_idx_t z, int flags
|
||||
) const;
|
||||
|
||||
const Resource::BlockType * getBlockStateAt(size_t x, size_t y, size_t z) const {
|
||||
size_t Y = y / SIZE;
|
||||
const Resource::BlockType * getBlockStateAt(block_idx_t x, y_idx_t y, block_idx_t z) const {
|
||||
section_idx_t Y = y / SIZE;
|
||||
|
||||
if (Y >= sections.size() || !sections[Y])
|
||||
return nullptr;
|
||||
|
@ -70,8 +79,8 @@ public:
|
|||
return *level;
|
||||
}
|
||||
|
||||
uint8_t getBiome(size_t x, size_t y, size_t z) const;
|
||||
Block getBlock(size_t x, Height y, size_t z) const;
|
||||
uint8_t getBiome(block_idx_t x, y_idx_t y, block_idx_t z) const;
|
||||
Block getBlock(block_idx_t x, Height y, block_idx_t z) const;
|
||||
|
||||
Heightmap getTopLayer(int flags) const;
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2015, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) 2015-2021, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
@ -18,16 +18,16 @@ namespace World {
|
|||
Region::ChunkMap Region::processHeader(const uint8_t header[4096]) {
|
||||
ChunkMap map;
|
||||
|
||||
for (size_t z = 0; z < 32; z++) {
|
||||
for (size_t x = 0; x < 32; x++) {
|
||||
for (chunk_idx_t z = 0; z < 32; z++) {
|
||||
for (chunk_idx_t x = 0; x < 32; x++) {
|
||||
const uint8_t *p = &header[128*z + x*4];
|
||||
|
||||
size_t offset = (p[0] << 16) | (p[1] << 8) | p[2];
|
||||
uint32_t offset = (p[0] << 16) | (p[1] << 8) | p[2];
|
||||
|
||||
if (!offset)
|
||||
continue;
|
||||
|
||||
size_t len = p[3];
|
||||
uint8_t len = p[3];
|
||||
|
||||
map.emplace(offset, ChunkDesc(x, z, len));
|
||||
}
|
||||
|
@ -61,8 +61,9 @@ void Region::visitChunks(const char *filename, const ChunkVisitor &visitor) {
|
|||
continue;
|
||||
}
|
||||
|
||||
size_t x, z, len;
|
||||
std::tie(x, z, len) = it->second;
|
||||
chunk_idx_t x = std::get<0>(it->second);
|
||||
chunk_idx_t z = std::get<1>(it->second);
|
||||
size_t len = std::get<2>(it->second);
|
||||
|
||||
if (seen[x][z])
|
||||
throw std::invalid_argument("duplicate chunk");
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2015, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) 2015-2021, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
@ -21,15 +21,16 @@ namespace World {
|
|||
|
||||
class Region {
|
||||
public:
|
||||
static const size_t SIZE = 32;
|
||||
// Number of chunks in a region in each dimension
|
||||
static const uint32_t SIZE = 32;
|
||||
|
||||
typedef std::function<void (size_t, size_t, const ChunkData *)> ChunkVisitor;
|
||||
typedef std::function<void (chunk_idx_t, chunk_idx_t, const ChunkData *)> ChunkVisitor;
|
||||
|
||||
Region() = delete;
|
||||
|
||||
private:
|
||||
typedef std::tuple<size_t, size_t, size_t> ChunkDesc;
|
||||
typedef std::unordered_map<size_t, ChunkDesc> ChunkMap;
|
||||
typedef std::tuple<chunk_idx_t, chunk_idx_t, uint8_t> ChunkDesc;
|
||||
typedef std::unordered_map<uint32_t, ChunkDesc> ChunkMap;
|
||||
|
||||
static ChunkMap processHeader(const uint8_t header[4096]);
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2015-2019, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) 2015-2021, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
@ -8,7 +8,6 @@
|
|||
#include "Section.hpp"
|
||||
#include "../NBT/ByteTag.hpp"
|
||||
#include "../NBT/StringTag.hpp"
|
||||
#include "../Util.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
|
@ -21,7 +20,7 @@ Section::Section(const std::shared_ptr<const NBT::CompoundTag> §ion) {
|
|||
blockLight = section->get<NBT::ByteArrayTag>("BlockLight");
|
||||
}
|
||||
|
||||
const Resource::BlockType * Section::getBlockStateAt(size_t, size_t, size_t) const {
|
||||
const Resource::BlockType * Section::getBlockStateAt(block_idx_t, block_idx_t, block_idx_t) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -44,7 +43,7 @@ std::unique_ptr<Section> Section::makeSection(const std::shared_ptr<const NBT::C
|
|||
}
|
||||
|
||||
|
||||
const Resource::BlockType * LegacySection::getBlockStateAt(size_t x, size_t y, size_t z) const {
|
||||
const Resource::BlockType * LegacySection::getBlockStateAt(block_idx_t x, block_idx_t y, block_idx_t z) const {
|
||||
uint8_t type = getBlockAt(x, y, z);
|
||||
uint8_t data = getDataAt(x, y, z);
|
||||
|
||||
|
@ -97,7 +96,7 @@ PaletteSection::PaletteSection(
|
|||
}
|
||||
}
|
||||
|
||||
const Resource::BlockType * PaletteSection::getBlockStateAt(size_t x, size_t y, size_t z) const {
|
||||
const Resource::BlockType * PaletteSection::getBlockStateAt(block_idx_t x, block_idx_t y, block_idx_t z) const {
|
||||
size_t index = getIndex(x, y, z);
|
||||
size_t bitIndex;
|
||||
|
||||
|
@ -110,7 +109,7 @@ const Resource::BlockType * PaletteSection::getBlockStateAt(size_t x, size_t y,
|
|||
}
|
||||
|
||||
size_t pos = bitIndex >> 3;
|
||||
size_t shift = bitIndex & 7;
|
||||
unsigned shift = bitIndex & 7;
|
||||
uint16_t mask = (1u << bits) - 1;
|
||||
|
||||
uint32_t v = blockStates->getPointer()[mangleByteIndex(pos)];
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2015-2019, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) 2015-2021, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
|||
#include "../NBT/ListTag.hpp"
|
||||
#include "../NBT/LongArrayTag.hpp"
|
||||
#include "../Resource/BlockType.hpp"
|
||||
#include "../Util.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
|
@ -23,21 +24,22 @@ namespace World {
|
|||
|
||||
class Section {
|
||||
public:
|
||||
static const size_t SIZE = 16;
|
||||
// Number of blocks in a section in each dimension
|
||||
static const uint32_t SIZE = 16;
|
||||
|
||||
private:
|
||||
size_t Y;
|
||||
section_idx_t Y;
|
||||
std::shared_ptr<const NBT::ByteArrayTag> blockLight;
|
||||
|
||||
protected:
|
||||
static size_t getIndex(size_t x, size_t y, size_t z) {
|
||||
static size_t getIndex(block_idx_t x, block_idx_t y, block_idx_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) {
|
||||
static uint8_t getHalf(const uint8_t *v, block_idx_t x, block_idx_t y, block_idx_t z) {
|
||||
size_t i = getIndex(x, y, z);
|
||||
|
||||
if (i % 2)
|
||||
|
@ -51,11 +53,11 @@ protected:
|
|||
public:
|
||||
virtual ~Section() {}
|
||||
|
||||
size_t getY() const { return Y; };
|
||||
section_idx_t getY() const { return Y; };
|
||||
|
||||
virtual const Resource::BlockType * getBlockStateAt(size_t x, size_t y, size_t z) const;
|
||||
virtual const Resource::BlockType * getBlockStateAt(block_idx_t x, block_idx_t y, block_idx_t z) const;
|
||||
|
||||
uint8_t getBlockLightAt(size_t x, size_t y, size_t z) const {
|
||||
uint8_t getBlockLightAt(block_idx_t x, block_idx_t y, block_idx_t z) const {
|
||||
if (!blockLight)
|
||||
return 0;
|
||||
|
||||
|
@ -71,11 +73,11 @@ private:
|
|||
std::shared_ptr<const NBT::ByteArrayTag> data;
|
||||
|
||||
|
||||
uint8_t getBlockAt(size_t x, size_t y, size_t z) const {
|
||||
uint8_t getBlockAt(block_idx_t x, block_idx_t y, block_idx_t z) const {
|
||||
return blocks->getValue(getIndex(x, y, z));
|
||||
}
|
||||
|
||||
uint8_t getDataAt(size_t x, size_t y, size_t z) const {
|
||||
uint8_t getDataAt(block_idx_t x, block_idx_t y, block_idx_t z) const {
|
||||
return getHalf(data->getPointer(), x, y, z);
|
||||
}
|
||||
|
||||
|
@ -86,7 +88,7 @@ public:
|
|||
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;
|
||||
virtual const Resource::BlockType * getBlockStateAt(block_idx_t x, block_idx_t y, block_idx_t z) const;
|
||||
};
|
||||
|
||||
class PaletteSection : public Section {
|
||||
|
@ -111,7 +113,7 @@ public:
|
|||
uint32_t dataVersion0
|
||||
);
|
||||
|
||||
virtual const Resource::BlockType * getBlockStateAt(size_t x, size_t y, size_t z) const;
|
||||
virtual const Resource::BlockType * getBlockStateAt(block_idx_t x, block_idx_t y, block_idx_t z) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue