1
0
Fork 0
Univerxel/src/server/world/region/Memory.hpp

59 lines
2.0 KiB
C++

#pragma once
#include <string>
#include <shared_mutex>
#include <fstream>
#include "../../../core/world/forward.h"
#include "../../../core/world/Voxel.hpp"
#include "../../../core/data/mem.hpp"
#include "../../../core/utils/zctx.hpp"
#include "../../../core/data/math.hpp"
namespace world::server {
///Group of chunks saved as a single file in memory
class MemoryRegion {
public:
MemoryRegion(const std::string& folderPath, const area_<region_pos> &pos);
~MemoryRegion();
template<typename D>
void averages(D &out) {
std::shared_lock lock(mutex);
out.resize(content.size() * (sizeof(region_chunk_pos) + sizeof(Voxel)));
data::in_view in((uint8_t*)out.data(), out.size());
for(const auto& r: content) {
if (r.second.average.has_value()) {
in.write((const uint8_t*)&r.first, sizeof(r.first));
in.write((const uint8_t*)&r.second.average.value(), sizeof(r.second.average.value()));
}
}
out.resize(in.cur);
}
bool read(const region_chunk_pos &pos, const zstd::read_ctx &ctx, std::vector<char> &out);
void write(const region_chunk_pos &pos, const zstd::write_ctx& ctx, const std::string_view &in, const std::optional<Voxel>& average);
private:
void save(bool force = true);
std::string path;
//TODO: use tickets to remove unused regions
enum Flags: unsigned char {
ZERO = 0,
HAS_AVERAGE = 1 << 0,
EMPTY = 1 << 1
};
std::shared_mutex mutex;
struct node {
node(const std::optional<Voxel>& a, std::unique_ptr<std::vector<char>> d):
average(a), data(std::move(d)) { }
std::optional<Voxel> average;
std::unique_ptr<std::vector<char>> data;
};
robin_hood::unordered_map<region_chunk_pos, node> content;
bool changed = false;
void load();
};
}