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:
Matthias Schiffer 2021-11-17 12:25:26 +01:00
parent d4be401bcd
commit 457e993c92
Signed by: neocturne
GPG key ID: 16EF3F64CB201D9C
13 changed files with 123 additions and 92 deletions

View file

@ -1,4 +1,4 @@
Copyright (c) 2015-2019, Matthias Schiffer <mschiffer@universe-factory.net> Copyright (c) 2015-2021, Matthias Schiffer <mschiffer@universe-factory.net>
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: BSD-2-Clause // 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. All rights reserved.
*/ */
@ -32,15 +32,15 @@
namespace MinedMap { namespace MinedMap {
static const int BIOME_SMOOTH = 3; static const int BIOME_SMOOTH = 3;
static const size_t DIM = World::Region::SIZE*World::Chunk::SIZE; static const uint32_t DIM = World::Region::SIZE*World::Chunk::SIZE;
static void addChunkBiome(uint8_t biomemap[DIM*DIM], size_t X, size_t Z, const World::ChunkData *data) { static void addChunkBiome(uint8_t biomemap[DIM*DIM], chunk_idx_t X, chunk_idx_t Z, const World::ChunkData *data) {
World::Chunk chunk(data); World::Chunk chunk(data);
World::Chunk::Heightmap layer = chunk.getTopLayer(0); World::Chunk::Heightmap layer = chunk.getTopLayer(0);
for (size_t x = 0; x < World::Chunk::SIZE; x++) { for (block_idx_t x = 0; x < World::Chunk::SIZE; x++) {
for (size_t z = 0; z < World::Chunk::SIZE; z++) { for (block_idx_t z = 0; z < World::Chunk::SIZE; z++) {
size_t i = (Z*World::Chunk::SIZE+z)*DIM + X*World::Chunk::SIZE+x; size_t i = (Z*World::Chunk::SIZE+z)*DIM + X*World::Chunk::SIZE+x;
const World::Chunk::Height &height = layer.v[x][z]; const World::Chunk::Height &height = layer.v[x][z];
biomemap[i] = chunk.getBiome(x, height.y, z); biomemap[i] = chunk.getBiome(x, height.y, z);
@ -48,20 +48,20 @@ static void addChunkBiome(uint8_t biomemap[DIM*DIM], size_t X, size_t Z, const W
} }
} }
static uint8_t biomeAt(ssize_t x, ssize_t z, const std::unique_ptr<uint8_t[]> biomemaps[3][3]) { static uint8_t biomeAt(int16_t x, int16_t z, const std::unique_ptr<uint8_t[]> biomemaps[3][3]) {
size_t a = 1, b = 1; size_t a = 1, b = 1;
if (x < 0) { if (x < 0) {
a--; a--;
x += DIM; x += DIM;
} else if (x >= (ssize_t)DIM) { } else if (x >= (int32_t)DIM) {
a++; a++;
x -= DIM; x -= DIM;
} }
if (z < 0) { if (z < 0) {
b--; b--;
z += DIM; z += DIM;
} else if (z >= (ssize_t)DIM) { } else if (z >= (int32_t)DIM) {
b++; b++;
z -= DIM; z -= DIM;
} }
@ -69,10 +69,13 @@ static uint8_t biomeAt(ssize_t x, ssize_t z, const std::unique_ptr<uint8_t[]> bi
return biomemaps[a][b].get()[z*DIM + x]; return biomemaps[a][b].get()[z*DIM + x];
} }
static Resource::Color collectColors(size_t x, size_t z, const World::Block &block, const std::unique_ptr<uint8_t[]> biomemaps[3][3]) { static Resource::Color collectColors(
std::unordered_map<uint8_t, size_t> biomes; region_block_idx_t x, region_block_idx_t z,
for (int dx = -BIOME_SMOOTH; dx <= BIOME_SMOOTH; dx++) { const World::Block &block, const std::unique_ptr<uint8_t[]> biomemaps[3][3]
for (int dz = -BIOME_SMOOTH; dz <= BIOME_SMOOTH; dz++) { ) {
std::unordered_map<uint8_t, unsigned> biomes;
for (int16_t dx = -BIOME_SMOOTH; dx <= BIOME_SMOOTH; dx++) {
for (int16_t dz = -BIOME_SMOOTH; dz <= BIOME_SMOOTH; dz++) {
if (std::abs(dx) + std::abs(dz) > BIOME_SMOOTH) if (std::abs(dx) + std::abs(dz) > BIOME_SMOOTH)
continue; continue;
@ -85,11 +88,11 @@ static Resource::Color collectColors(size_t x, size_t z, const World::Block &blo
} }
Resource::FloatColor c = {}; Resource::FloatColor c = {};
size_t total = 0; unsigned total = 0;
for (const auto &e : biomes) { for (const auto &e : biomes) {
uint8_t biome = e.first; uint8_t biome = e.first;
size_t count = e.second; unsigned count = e.second;
if (biome == 0xff) if (biome == 0xff)
continue; continue;
@ -104,14 +107,14 @@ static Resource::Color collectColors(size_t x, size_t z, const World::Block &blo
return (1.0f / total) * c; return (1.0f / total) * c;
} }
static void addChunk(Resource::Color image[DIM*DIM], uint8_t lightmap[2*DIM*DIM], size_t X, size_t Z, static void addChunk(Resource::Color image[DIM*DIM], uint8_t lightmap[2*DIM*DIM], chunk_idx_t X, chunk_idx_t Z,
const World::ChunkData *data, const std::unique_ptr<uint8_t[]> biomemaps[3][3] const World::ChunkData *data, const std::unique_ptr<uint8_t[]> biomemaps[3][3]
) { ) {
World::Chunk chunk(data); World::Chunk chunk(data);
World::Chunk::Heightmap layer = chunk.getTopLayer(World::Chunk::WITH_DEPTH); World::Chunk::Heightmap layer = chunk.getTopLayer(World::Chunk::WITH_DEPTH);
for (size_t x = 0; x < World::Chunk::SIZE; x++) { for (block_idx_t x = 0; x < World::Chunk::SIZE; x++) {
for (size_t z = 0; z < World::Chunk::SIZE; z++) { for (block_idx_t z = 0; z < World::Chunk::SIZE; z++) {
size_t i = (Z*World::Chunk::SIZE+z)*DIM + X*World::Chunk::SIZE+x; size_t i = (Z*World::Chunk::SIZE+z)*DIM + X*World::Chunk::SIZE+x;
const World::Chunk::Height &height = layer.v[x][z]; const World::Chunk::Height &height = layer.v[x][z];
World::Block block = chunk.getBlock(x, height, z); World::Block block = chunk.getBlock(x, height, z);
@ -261,7 +264,7 @@ static void makeBiome(const std::string &regiondir, const std::string &outputdir
std::unique_ptr<uint8_t[]> biomemap(new uint8_t[DIM*DIM]); std::unique_ptr<uint8_t[]> biomemap(new uint8_t[DIM*DIM]);
std::memset(biomemap.get(), 0xff, DIM*DIM); std::memset(biomemap.get(), 0xff, DIM*DIM);
World::Region::visitChunks(input.c_str(), [&] (size_t X, size_t Z, const World::ChunkData *chunk) { World::Region::visitChunks(input.c_str(), [&] (chunk_idx_t X, chunk_idx_t Z, const World::ChunkData *chunk) {
addChunkBiome(biomemap.get(), X, Z, chunk); addChunkBiome(biomemap.get(), X, Z, chunk);
}); });
@ -289,8 +292,8 @@ static void makeMap(const std::string &regiondir, const std::string &outputdir,
if (intime == INT64_MIN) if (intime == INT64_MIN)
return; return;
for (size_t i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
for (size_t j = 0; j < 3; j++) { for (int j = 0; j < 3; j++) {
biomenames[i][j] = outputdir + "/biome/" + formatTileName(x + i - 1, z + j - 1, "png"); biomenames[i][j] = outputdir + "/biome/" + formatTileName(x + i - 1, z + j - 1, "png");
intime = std::max(intime, getModTime(biomenames[i][j])); intime = std::max(intime, getModTime(biomenames[i][j]));
} }
@ -304,8 +307,8 @@ static void makeMap(const std::string &regiondir, const std::string &outputdir,
try { try {
std::unique_ptr<uint8_t[]> biomemaps[3][3]; std::unique_ptr<uint8_t[]> biomemaps[3][3];
for (size_t i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
for (size_t j = 0; j < 3; j++) { for (int j = 0; j < 3; j++) {
biomemaps[i][j].reset(new uint8_t[DIM*DIM]); biomemaps[i][j].reset(new uint8_t[DIM*DIM]);
std::memset(biomemaps[i][j].get(), 0, DIM*DIM); std::memset(biomemaps[i][j].get(), 0, DIM*DIM);
@ -320,7 +323,7 @@ static void makeMap(const std::string &regiondir, const std::string &outputdir,
std::unique_ptr<uint8_t[]> lightmap(new uint8_t[2*DIM*DIM]); std::unique_ptr<uint8_t[]> lightmap(new uint8_t[2*DIM*DIM]);
std::memset(lightmap.get(), 0, 2*DIM*DIM); std::memset(lightmap.get(), 0, 2*DIM*DIM);
World::Region::visitChunks(input.c_str(), [&] (size_t X, size_t Z, const World::ChunkData *chunk) { World::Region::visitChunks(input.c_str(), [&] (chunk_idx_t X, chunk_idx_t Z, const World::ChunkData *chunk) {
addChunk(image.get(), lightmap.get(), X, Z, chunk, biomemaps); addChunk(image.get(), lightmap.get(), X, Z, chunk, biomemaps);
}); });
@ -355,7 +358,7 @@ static bool makeMipmap(const std::string &dir, size_t level, int x, int z, PNG::
const char *se = se_str.c_str(); const char *se = se_str.c_str();
int64_t t = INT64_MIN; int64_t t = INT64_MIN;
size_t count = 0; unsigned count = 0;
for (auto name : {&nw, &ne, &sw, &se}) { for (auto name : {&nw, &ne, &sw, &se}) {
struct stat s; struct stat s;
if (stat(*name, &s) < 0) { if (stat(*name, &s) < 0) {

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: BSD-2-Clause // 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>
Copyright (c) 2019, Roman Shishkin <spark@uwtech.org> Copyright (c) 2019, Roman Shishkin <spark@uwtech.org>
All rights reserved. All rights reserved.
*/ */
@ -9,7 +9,6 @@
#include "Biome.hpp" #include "Biome.hpp"
#include "BlockType.hpp" #include "BlockType.hpp"
#include "../Util.hpp"
namespace MinedMap { namespace MinedMap {
@ -42,7 +41,7 @@ FloatColor Biome::getFoliageColor(float temp, float rain) const {
} }
FloatColor Biome::getBlockColor(const BlockType *type, unsigned height) const { FloatColor Biome::getBlockColor(const BlockType *type, y_idx_t height) const {
FloatColor c = { FloatColor c = {
float(type->color.r), float(type->color.r),
float(type->color.g), float(type->color.g),

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: BSD-2-Clause // 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. All rights reserved.
*/ */
@ -8,6 +8,7 @@
#pragma once #pragma once
#include "Color.hpp" #include "Color.hpp"
#include "../Util.hpp"
namespace MinedMap { namespace MinedMap {
@ -30,7 +31,7 @@ public:
Biome(float temp0, float rain0, FloatColor water0 = {0.247f, 0.463f, 0.894f}) Biome(float temp0, float rain0, FloatColor water0 = {0.247f, 0.463f, 0.894f})
: temp(temp0), rain(rain0), water(water0) {} : temp(temp0), rain(rain0), water(water0) {}
FloatColor getBlockColor(const BlockType *type, unsigned height) const; FloatColor getBlockColor(const BlockType *type, y_idx_t height) const;
}; };
extern const Biome *const BIOME_DEFAULT; extern const Biome *const BIOME_DEFAULT;

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: BSD-2-Clause // 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. All rights reserved.
*/ */
@ -8,6 +8,7 @@
#pragma once #pragma once
#include <algorithm> #include <algorithm>
#include <cstdint>
#include <stdexcept> #include <stdexcept>
#include <utility> #include <utility>
@ -25,4 +26,16 @@ static inline float clamp(float v, float min, float max) {
return std::max(std::min(v, max), min); return std::max(std::min(v, max), min);
} }
// A block coordinate relative to a chunk/section (X/Y/Z)
typedef uint8_t block_idx_t;
// A section index in a chunk (Y)
typedef uint8_t section_idx_t;
// A chunk coordinate relative to a region (X/Z)
typedef uint8_t chunk_idx_t;
// A block coordinate relative to a region (X/Z)
typedef uint16_t region_block_idx_t;
// A block coordinate (Y)
typedef uint16_t y_idx_t;
} }

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: BSD-2-Clause // 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. All rights reserved.
*/ */
@ -17,7 +17,7 @@ namespace World {
struct Block { struct Block {
const Resource::BlockType *type; const Resource::BlockType *type;
unsigned depth; y_idx_t depth;
uint8_t blockLight; uint8_t blockLight;
bool isVisible() const { bool isVisible() const {

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: BSD-2-Clause // 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. All rights reserved.
*/ */
@ -42,13 +42,13 @@ Chunk::Chunk(const ChunkData *data) {
for (auto &sTag : *sectionsTag) { for (auto &sTag : *sectionsTag) {
auto s = std::dynamic_pointer_cast<const NBT::CompoundTag>(sTag); auto s = std::dynamic_pointer_cast<const NBT::CompoundTag>(sTag);
std::unique_ptr<Section> section = Section::makeSection(s, dataVersion); std::unique_ptr<Section> section = Section::makeSection(s, dataVersion);
size_t Y = section->getY(); section_idx_t Y = section->getY();
sections.resize(Y); sections.resize(Y);
sections.push_back(std::move(section)); 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) if (x > SIZE || y > MAXY || z > SIZE)
throw std::invalid_argument("corrupt chunk data"); 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; 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 block = {};
block.depth = height.depth; block.depth = height.depth;
size_t Y = height.y / SIZE; section_idx_t Y = height.y / SIZE;
size_t y = height.y % SIZE; block_idx_t y = height.y % SIZE;
if (Y < sections.size() && sections[Y]) if (Y < sections.size() && sections[Y])
block.type = sections[Y]->getBlockStateAt(x, y, z); block.type = sections[Y]->getBlockStateAt(x, y, z);
size_t Yt = (height.y + 1) / SIZE; section_idx_t Yt = (height.y + 1) / SIZE;
size_t yt = (height.y + 1) % SIZE; block_idx_t yt = (height.y + 1) % SIZE;
if (Yt < sections.size() && sections[Yt]) if (Yt < sections.size() && sections[Yt])
block.blockLight = sections[Yt]->getBlockLightAt(x, yt, z); 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; 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) if (height->depth > 0)
return false; 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 { Chunk::Heightmap Chunk::getTopLayer(int flags) const {
size_t done = 0; uint32_t done = 0;
Heightmap ret = {}; 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) if (done == SIZE*SIZE)
break; break;
@ -120,12 +123,12 @@ Chunk::Heightmap Chunk::getTopLayer(int flags) const {
const Section *section = sections[Y].get(); 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) if (done == SIZE*SIZE)
break; break;
for (size_t z = 0; z < SIZE; z++) { for (block_idx_t z = 0; z < SIZE; z++) {
for (size_t x = 0; x < SIZE; x++) { for (block_idx_t x = 0; x < SIZE; x++) {
if (getHeight(&ret.v[x][z], section, x, y, z, flags)) if (getHeight(&ret.v[x][z], section, x, y, z, flags))
done++; done++;
} }

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: BSD-2-Clause // 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. All rights reserved.
*/ */
@ -24,19 +24,25 @@ namespace World {
class Chunk { class Chunk {
public: public:
static const size_t SIZE = Section::SIZE; // Number of blocks in a chunk in x/z dimensions
static const size_t MAXY = 256; static const uint32_t SIZE = Section::SIZE;
// Maximum Y value
static const y_idx_t MAXY = 256;
static const size_t BGROUP = 4; // Since Minecraft 1.15, biome information is stored for
static const size_t BSIZE = SIZE / BGROUP; // 4x4x4 block groups
static const size_t BMAXY = MAXY / BGROUP; 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 // Flags
static const int WITH_DEPTH = (1 << 0); static const int WITH_DEPTH = (1 << 0);
struct Height { struct Height {
unsigned y; y_idx_t y;
unsigned depth; y_idx_t depth;
}; };
struct Heightmap { struct Heightmap {
@ -51,10 +57,13 @@ private:
std::shared_ptr<const NBT::IntArrayTag> biomeIntsPre115; std::shared_ptr<const NBT::IntArrayTag> biomeIntsPre115;
std::shared_ptr<const NBT::IntArrayTag> biomeInts; 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 { const Resource::BlockType * getBlockStateAt(block_idx_t x, y_idx_t y, block_idx_t z) const {
size_t Y = y / SIZE; section_idx_t Y = y / SIZE;
if (Y >= sections.size() || !sections[Y]) if (Y >= sections.size() || !sections[Y])
return nullptr; return nullptr;
@ -70,8 +79,8 @@ public:
return *level; return *level;
} }
uint8_t getBiome(size_t x, size_t y, size_t z) const; uint8_t getBiome(block_idx_t x, y_idx_t y, block_idx_t z) const;
Block getBlock(size_t x, Height y, size_t z) const; Block getBlock(block_idx_t x, Height y, block_idx_t z) const;
Heightmap getTopLayer(int flags) const; Heightmap getTopLayer(int flags) const;
}; };

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: BSD-2-Clause // 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. All rights reserved.
*/ */
@ -18,16 +18,16 @@ namespace World {
Region::ChunkMap Region::processHeader(const uint8_t header[4096]) { Region::ChunkMap Region::processHeader(const uint8_t header[4096]) {
ChunkMap map; ChunkMap map;
for (size_t z = 0; z < 32; z++) { for (chunk_idx_t z = 0; z < 32; z++) {
for (size_t x = 0; x < 32; x++) { for (chunk_idx_t x = 0; x < 32; x++) {
const uint8_t *p = &header[128*z + x*4]; 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) if (!offset)
continue; continue;
size_t len = p[3]; uint8_t len = p[3];
map.emplace(offset, ChunkDesc(x, z, len)); map.emplace(offset, ChunkDesc(x, z, len));
} }
@ -61,8 +61,9 @@ void Region::visitChunks(const char *filename, const ChunkVisitor &visitor) {
continue; continue;
} }
size_t x, z, len; chunk_idx_t x = std::get<0>(it->second);
std::tie(x, z, len) = it->second; chunk_idx_t z = std::get<1>(it->second);
size_t len = std::get<2>(it->second);
if (seen[x][z]) if (seen[x][z])
throw std::invalid_argument("duplicate chunk"); throw std::invalid_argument("duplicate chunk");

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: BSD-2-Clause // 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. All rights reserved.
*/ */
@ -21,15 +21,16 @@ namespace World {
class Region { class Region {
public: 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; Region() = delete;
private: private:
typedef std::tuple<size_t, size_t, size_t> ChunkDesc; typedef std::tuple<chunk_idx_t, chunk_idx_t, uint8_t> ChunkDesc;
typedef std::unordered_map<size_t, ChunkDesc> ChunkMap; typedef std::unordered_map<uint32_t, ChunkDesc> ChunkMap;
static ChunkMap processHeader(const uint8_t header[4096]); static ChunkMap processHeader(const uint8_t header[4096]);

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: BSD-2-Clause // 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. All rights reserved.
*/ */
@ -8,7 +8,6 @@
#include "Section.hpp" #include "Section.hpp"
#include "../NBT/ByteTag.hpp" #include "../NBT/ByteTag.hpp"
#include "../NBT/StringTag.hpp" #include "../NBT/StringTag.hpp"
#include "../Util.hpp"
#include <cstdio> #include <cstdio>
@ -21,7 +20,7 @@ Section::Section(const std::shared_ptr<const NBT::CompoundTag> &section) {
blockLight = section->get<NBT::ByteArrayTag>("BlockLight"); 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; 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 type = getBlockAt(x, y, z);
uint8_t data = getDataAt(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 index = getIndex(x, y, z);
size_t bitIndex; 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 pos = bitIndex >> 3;
size_t shift = bitIndex & 7; unsigned shift = bitIndex & 7;
uint16_t mask = (1u << bits) - 1; uint16_t mask = (1u << bits) - 1;
uint32_t v = blockStates->getPointer()[mangleByteIndex(pos)]; uint32_t v = blockStates->getPointer()[mangleByteIndex(pos)];

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: BSD-2-Clause // 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. All rights reserved.
*/ */
@ -13,6 +13,7 @@
#include "../NBT/ListTag.hpp" #include "../NBT/ListTag.hpp"
#include "../NBT/LongArrayTag.hpp" #include "../NBT/LongArrayTag.hpp"
#include "../Resource/BlockType.hpp" #include "../Resource/BlockType.hpp"
#include "../Util.hpp"
#include <cstdint> #include <cstdint>
#include <stdexcept> #include <stdexcept>
@ -23,21 +24,22 @@ namespace World {
class Section { class Section {
public: public:
static const size_t SIZE = 16; // Number of blocks in a section in each dimension
static const uint32_t SIZE = 16;
private: private:
size_t Y; section_idx_t Y;
std::shared_ptr<const NBT::ByteArrayTag> blockLight; std::shared_ptr<const NBT::ByteArrayTag> blockLight;
protected: 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) if (x >= SIZE || y >= SIZE || z >= SIZE)
throw std::range_error("Chunk::getIndex(): bad coordinates"); throw std::range_error("Chunk::getIndex(): bad coordinates");
return SIZE*SIZE*y + SIZE*z + x; 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); size_t i = getIndex(x, y, z);
if (i % 2) if (i % 2)
@ -51,11 +53,11 @@ protected:
public: public:
virtual ~Section() {} 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) if (!blockLight)
return 0; return 0;
@ -71,11 +73,11 @@ private:
std::shared_ptr<const NBT::ByteArrayTag> data; 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)); 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); return getHalf(data->getPointer(), x, y, z);
} }
@ -86,7 +88,7 @@ public:
std::shared_ptr<const NBT::ByteArrayTag> &&data0 std::shared_ptr<const NBT::ByteArrayTag> &&data0
) : Section(section), blocks(blocks0), data(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 { class PaletteSection : public Section {
@ -111,7 +113,7 @@ public:
uint32_t dataVersion0 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;
}; };
} }

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: BSD-2-Clause // SPDX-License-Identifier: BSD-2-Clause
/* /*
Copyright (c) 2018, Matthias Schiffer <mschiffer@universe-factory.net> Copyright (c) 2018-2021, Matthias Schiffer <mschiffer@universe-factory.net>
All rights reserved. All rights reserved.
*/ */
@ -23,7 +23,7 @@ int main(int argc, char *argv[]) {
return 1; return 1;
} }
World::Region::visitChunks(argv[1], [&] (size_t X, size_t Z, const World::ChunkData *chunk) { World::Region::visitChunks(argv[1], [&] (chunk_idx_t X, chunk_idx_t Z, const World::ChunkData *chunk) {
std::cout << "Chunk(" << X << ", " << Z << "): " std::cout << "Chunk(" << X << ", " << Z << "): "
<< chunk->getRoot() << std::endl; << chunk->getRoot() << std::endl;
}); });