feat(core): add chunk storage and world container
This commit is contained in:
1 parent
e0f48fad20
commit
f556a9bcdb
2 files changed
+108
No files matched your search
@@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include "Block.h"
|
||||||
|
|
||||||
|
namespace vf {
|
||||||
|
|
||||||
|
constexpr int chunkSize = 16;
|
||||||
|
constexpr int chunkVolume = chunkSize * chunkSize * chunkSize;
|
||||||
|
|
||||||
|
inline bool inChunkBounds(int x, int y, int z) {
|
||||||
|
return x >= 0 && x < chunkSize && y >= 0 && y < chunkSize && z >= 0 && z < chunkSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int localIndex(int x, int y, int z) {
|
||||||
|
return (y * chunkSize + z) * chunkSize + x;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Chunk {
|
||||||
|
public:
|
||||||
|
Chunk() { blocks.fill(Block::Air); }
|
||||||
|
|
||||||
|
Block at(int x, int y, int z) const { return blocks[localIndex(x, y, z)]; }
|
||||||
|
void set(int x, int y, int z, Block b) { blocks[localIndex(x, y, z)] = b; }
|
||||||
|
|
||||||
|
bool empty() const {
|
||||||
|
for (Block b : blocks)
|
||||||
|
if (b != Block::Air) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::array<Block, chunkVolume>& raw() const { return blocks; }
|
||||||
|
std::array<Block, chunkVolume>& raw() { return blocks; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::array<Block, chunkVolume> blocks;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace vf
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <memory>
|
||||||
|
#include "Chunk.h"
|
||||||
|
#include "Math.h"
|
||||||
|
|
||||||
|
namespace vf {
|
||||||
|
|
||||||
|
inline int floorDiv(int a, int b) {
|
||||||
|
int q = a / b;
|
||||||
|
int r = a % b;
|
||||||
|
if (r != 0 && ((r < 0) != (b < 0))) --q;
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int floorMod(int a, int b) {
|
||||||
|
int r = a % b;
|
||||||
|
if (r != 0 && ((r < 0) != (b < 0))) r += b;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
class World {
|
||||||
|
public:
|
||||||
|
Chunk* chunkAt(const Vec3i& coord) {
|
||||||
|
auto it = chunks.find(coord);
|
||||||
|
return it == chunks.end() ? nullptr : it->second.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
const Chunk* chunkAt(const Vec3i& coord) const {
|
||||||
|
auto it = chunks.find(coord);
|
||||||
|
return it == chunks.end() ? nullptr : it->second.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
Chunk& ensureChunk(const Vec3i& coord) {
|
||||||
|
auto it = chunks.find(coord);
|
||||||
|
if (it != chunks.end()) return *it->second;
|
||||||
|
auto inserted = chunks.emplace(coord, std::make_unique<Chunk>());
|
||||||
|
return *inserted.first->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool removeChunk(const Vec3i& coord) { return chunks.erase(coord) != 0; }
|
||||||
|
|
||||||
|
Block blockAt(int gx, int gy, int gz) const {
|
||||||
|
Vec3i coord{floorDiv(gx, chunkSize), floorDiv(gy, chunkSize), floorDiv(gz, chunkSize)};
|
||||||
|
const Chunk* chunk = chunkAt(coord);
|
||||||
|
if (!chunk) return Block::Air;
|
||||||
|
return chunk->at(floorMod(gx, chunkSize), floorMod(gy, chunkSize), floorMod(gz, chunkSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
void setBlock(int gx, int gy, int gz, Block b) {
|
||||||
|
Vec3i coord{floorDiv(gx, chunkSize), floorDiv(gy, chunkSize), floorDiv(gz, chunkSize)};
|
||||||
|
Chunk& chunk = ensureChunk(coord);
|
||||||
|
chunk.set(floorMod(gx, chunkSize), floorMod(gy, chunkSize), floorMod(gz, chunkSize), b);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool solidAt(int gx, int gy, int gz) const { return isSolid(blockAt(gx, gy, gz)); }
|
||||||
|
|
||||||
|
const std::unordered_map<Vec3i, std::unique_ptr<Chunk>, Vec3iHash>& allChunks() const {
|
||||||
|
return chunks;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t chunkCount() const { return chunks.size(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<Vec3i, std::unique_ptr<Chunk>, Vec3iHash> chunks;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace vf
|
||||||
Reference in new issue
Block a user