84 lines
2.6 KiB
C++
84 lines
2.6 KiB
C++
#include "Chunk.hpp"
|
|
|
|
#include <algorithm>
|
|
#include "core/geometry/math.hpp"
|
|
#include <Tracy.hpp>
|
|
#include <iostream>
|
|
|
|
using namespace world::server;
|
|
|
|
Chunk::Chunk(owner<world::ChunkEdits*> edits): world::EdittableChunk(edits, Voxel(0)) { }
|
|
Chunk::Chunk(owner<world::ChunkEdits*> edits, const chunk_pos &pos, const std::unique_ptr<generator::Abstract> &rnd): world::EdittableChunk(edits) {
|
|
rnd->generate5(glm::multiply(pos), voxels);
|
|
}
|
|
Chunk::Chunk(owner<world::ChunkEdits*> edits, std::istream& str): world::EdittableChunk(edits, str) { }
|
|
Chunk::~Chunk() { }
|
|
|
|
world::Voxel Chunk::write(std::ostream& str) const {
|
|
Voxel::material_t majMat = UINT16_MAX;
|
|
uint16_t majCounter = 1;
|
|
size_t visibleDensity = 0;
|
|
const auto doMaj = [&](const Voxel& current) {
|
|
if (current.material() == majMat) {
|
|
majCounter++;
|
|
} else {
|
|
majCounter--;
|
|
}
|
|
if (majCounter == 0) {
|
|
majMat = current.material();
|
|
majCounter = 1;
|
|
}
|
|
visibleDensity += current.density() * current.is_visible();
|
|
};
|
|
if constexpr(RLE) {
|
|
auto it = voxels.begin();
|
|
uint16_t counter = 1;
|
|
Voxel current = *it;
|
|
while(true) {
|
|
++it;
|
|
doMaj(current);
|
|
const auto end = (it == voxels.end());
|
|
if(end || current.value != it->value) {
|
|
str.write(reinterpret_cast<char *>(&counter), sizeof(counter));
|
|
str.write(reinterpret_cast<char *>(¤t), sizeof(current));
|
|
if(end)
|
|
break;
|
|
|
|
current = *it;
|
|
counter = 1;
|
|
} else {
|
|
counter++;
|
|
}
|
|
}
|
|
} else {
|
|
for(auto current: voxels) {
|
|
doMaj(current);
|
|
str.write(reinterpret_cast<char *>(¤t), sizeof(current));
|
|
}
|
|
}
|
|
if (majCounter-1 == INT16_MAX) { // Perfect majority
|
|
return Voxel(voxels.front().material(), voxels.front().density(), true);
|
|
}
|
|
return Voxel(majMat, visibleDensity / CHUNK_SIZE);
|
|
}
|
|
|
|
void Chunk::set(uint16_t idx, const world::Voxel& val) {
|
|
const auto same = get(idx).value == val.value;
|
|
if (!isHeavy()) {
|
|
if (same)
|
|
return;
|
|
|
|
flatten();
|
|
}
|
|
modified = modified || !same;
|
|
voxels[idx] = val;
|
|
}
|
|
void Chunk::setAt(const chunk_voxel_pos& pos, const world::Voxel& val) {
|
|
set(glm::toIdx(pos), val);
|
|
}
|
|
std::optional<world::Item> Chunk::replace(chunk_voxel_idx idx, const world::Voxel& val, float) {
|
|
const auto res = get(idx);
|
|
set(idx, val);
|
|
return {world::Item{res.density(), res.material()}};
|
|
}
|