#pragma once #include #include #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 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 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 getNeighborIdx(chunk_voxel_idx idx, Face dir); private: /// Chunk data std::array 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 EMPTY_CHUNK = std::make_shared(); }