1
0
Fork 0
Univerxel/src/server/world/Chunk.cpp

84 lines
2.6 KiB
C++
Raw Normal View History

2020-07-10 17:49:16 +00:00
#include "Chunk.hpp"
2020-07-31 17:09:44 +00:00
#include <algorithm>
#include "core/geometry/math.hpp"
#include <Tracy.hpp>
#include <iostream>
2020-07-10 17:49:16 +00:00
2020-09-20 16:41:54 +00:00
using namespace world::server;
2020-07-25 16:45:03 +00:00
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);
2020-07-10 17:49:16 +00:00
}
Chunk::Chunk(owner<world::ChunkEdits*> edits, std::istream& str): world::EdittableChunk(edits, str) { }
2020-07-10 17:49:16 +00:00
Chunk::~Chunk() { }
world::Voxel Chunk::write(std::ostream& str) const {
2020-11-06 16:32:00 +00:00
Voxel::material_t majMat = UINT16_MAX;
2020-11-11 19:25:03 +00:00
uint16_t majCounter = 1;
2020-11-06 16:32:00 +00:00
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) {
2020-11-11 19:25:03 +00:00
auto it = voxels.begin();
uint16_t counter = 1;
2020-08-02 09:47:25 +00:00
Voxel current = *it;
while(true) {
2020-08-02 20:15:53 +00:00
++it;
2020-11-06 16:32:00 +00:00
doMaj(current);
2020-08-02 09:47:25 +00:00
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 *>(&current), sizeof(current));
if(end)
break;
2020-07-26 20:53:14 +00:00
2020-08-02 09:47:25 +00:00
current = *it;
counter = 1;
} else {
counter++;
}
}
} else {
for(auto current: voxels) {
2020-11-06 16:32:00 +00:00
doMaj(current);
2020-08-02 09:47:25 +00:00
str.write(reinterpret_cast<char *>(&current), sizeof(current));
2020-07-26 20:53:14 +00:00
}
}
2020-11-06 16:32:00 +00:00
if (majCounter-1 == INT16_MAX) { // Perfect majority
return Voxel(voxels.front().material(), voxels.front().density(), true);
}
return Voxel(majMat, visibleDensity / CHUNK_SIZE);
2020-07-26 20:53:14 +00:00
}
2020-11-11 19:25:03 +00:00
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;
}
2020-11-11 19:25:03 +00:00
void Chunk::setAt(const chunk_voxel_pos& pos, const world::Voxel& val) {
2020-09-20 16:41:54 +00:00
set(glm::toIdx(pos), val);
}
2020-11-11 19:25:03 +00:00
std::optional<world::Item> Chunk::replace(chunk_voxel_idx idx, const world::Voxel& val, float) {
const auto res = get(idx);
2020-09-20 16:41:54 +00:00
set(idx, val);
2020-09-24 19:55:44 +00:00
return {world::Item{res.density(), res.material()}};
2020-07-10 17:49:16 +00:00
}