1
0
Fork 0
Univerxel/src/world/Chunk.hpp

76 lines
2.3 KiB
C++

#pragma once
#include <memory>
#include <sstream>
#include "Generator.hpp"
#include "Voxel.hpp"
#include "../data/geometry/Faces.hpp"
#include "../data/math.hpp"
/// Chunk length
namespace world {
const auto CHUNK_LENGTH2 = CHUNK_LENGTH * CHUNK_LENGTH;
const auto CHUNK_SIZE = CHUNK_LENGTH2 * CHUNK_LENGTH;
constexpr auto RLE = true; //NOTE: only 2.7% gain after zstd
using namespace geometry;
/// World part as linear 3d voxel array
class Chunk {
public:
Chunk() {}
Chunk(const chunk_pos& pos, Generator& rnd);
Chunk(std::istream& str, bool rle = RLE);
~Chunk();
/// Update voxels
/// @return if modified neighbors to update
std::optional<Faces> update();
// Notify for render
inline void invalidate(Faces faces) {
upToDate = false;
toUpdate = toUpdate | faces;
modified = true;
}
// Get voxel from index
inline const Voxel& get(chunk_voxel_idx idx) const {
return voxels[idx];
}
// Get voxel from position
inline const Voxel& getAt(const chunk_voxel_pos& pos) const {
return get(glm::toIdx(pos));
}
// Set voxel from index
void set(chunk_voxel_idx idx, const Voxel& val);
// Set voxel from position
void setAt(const chunk_voxel_pos& pos, const Voxel& val) {
set(glm::toIdx(pos), val);
}
// Break voxel
std::optional<Item> replace(chunk_voxel_idx idx, const Voxel& val) {
const auto res = voxels[idx];
set(idx, val);
return {Item{res.density(), res.material()}}; //TODO: materials break table
}
// Is player modified
inline bool isModified() const { return modified; }
// Write to file.
void write(std::ostream& str, bool rle = RLE) const;
static std::optional<chunk_voxel_idx> getNeighborIdx(chunk_voxel_idx idx, Face dir);
private:
/// Chunk data
std::array<Voxel, CHUNK_SIZE> voxels;
/// Require update
bool upToDate = true;
/// Neighbors to update
Faces toUpdate = Faces::None;
/// Modified by player
bool modified = false;
};
/// Chunk full of air
static const std::shared_ptr<const Chunk> EMPTY_CHUNK = std::make_shared<Chunk>();
}