1
0
Fork 0
Univerxel/src/server/world/Region.hpp

77 lines
2.9 KiB
C++
Raw Normal View History

2020-07-31 20:26:07 +00:00
#pragma once
#include <string>
#include <shared_mutex>
#include "core/world/Area.hpp"
#include "core/world/Voxel.hpp"
#include "core/memory.hpp"
#include "core/utils/zctx.hpp"
2020-07-31 20:26:07 +00:00
2020-09-20 16:41:54 +00:00
namespace world::server {
2020-07-31 20:26:07 +00:00
///Group of chunks saved as a single file in memory
class Region {
2020-07-31 20:26:07 +00:00
public:
Region(const std::string& folderPath, const area_region_ref &id);
~Region();
2020-07-31 20:26:07 +00:00
2020-11-06 16:32:00 +00:00
template<typename D>
void averages(D &out) {
std::shared_lock lock(mutex);
out.resize(content.size() * (sizeof(region_chunk_pos) + sizeof(Voxel)));
memory::write_view in((uint8_t*)out.data(), out.size() * sizeof(D));
2020-11-06 16:32:00 +00:00
for(const auto& r: content) {
if (r.second.average.has_value()) {
in.write(r.first);
in.write(r.second.average.value());
2020-11-06 16:32:00 +00:00
}
}
out.resize(in.current());
2020-11-06 16:32:00 +00:00
}
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);
2020-07-31 20:26:07 +00:00
static void Read(const std::string& folder, const part_ref& id, const zstd::read_ctx &ctx, const std::function<void(const region_chunk_pos&, const std::vector<char>&)>& out);
static void Write(const std::string& folder, const part_ref& id, const zstd::write_ctx &ctx, size_t size, const std::function<std::pair<region_chunk_pos, std::string>()>& next);
2020-07-31 20:26:07 +00:00
private:
static size_t Read(const std::string &path, const std::function<void(const region_chunk_pos &, const std::optional<Voxel> &, std::vector<char> &&)> &out);
2020-07-31 20:26:07 +00:00
void save(bool force = true);
std::string path;
//TODO: use tickets to remove unused regions
2020-11-06 16:32:00 +00:00
enum Flags: unsigned char {
ZERO = 0,
HAS_AVERAGE = 1 << 0,
EMPTY = 1 << 1
};
2020-07-31 20:26:07 +00:00
std::shared_mutex mutex;
2020-11-06 16:32:00 +00:00
struct node {
node(const std::optional<Voxel>& a, std::vector<char>&& d):
2020-11-06 16:32:00 +00:00
average(a), data(std::move(d)) { }
std::optional<Voxel> average;
std::vector<char> data;
2020-11-06 16:32:00 +00:00
};
robin_hood::unordered_map<region_chunk_pos, node> content;
struct save_throttler {
save_throttler();
/// Counter of currently unsaved
size_t changes = 0;
/// Save when changes > (1 << it)
/// MAYBE: decrease with time
size_t nextSaveExponent;
inline void change() { changes++; }
inline constexpr bool isUnsaved() const { return changes > 0; }
inline constexpr bool mustSave() const { return changes > (1ull << nextSaveExponent); }
inline void save() {
changes = 0;
nextSaveExponent++;
}
} saveThrottler;
2020-07-31 20:26:07 +00:00
void load();
};
}