migrate blocks interaction (scripting) to global chunks storage (WIP)
This commit is contained in:
+114
-18
@@ -3,6 +3,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "content/Content.hpp"
|
||||
#include "coders/json.hpp"
|
||||
#include "debug/Logger.hpp"
|
||||
#include "files/WorldFiles.hpp"
|
||||
#include "items/Inventories.hpp"
|
||||
@@ -15,16 +16,27 @@
|
||||
#include "Block.hpp"
|
||||
#include "Chunk.hpp"
|
||||
|
||||
inline long long keyfrom(int x, int z) {
|
||||
union {
|
||||
int pos[2];
|
||||
long long key;
|
||||
} ekey;
|
||||
ekey.pos[0] = x;
|
||||
ekey.pos[1] = z;
|
||||
return ekey.key;
|
||||
}
|
||||
|
||||
static debug::Logger logger("chunks-storage");
|
||||
|
||||
ChunksStorage::ChunksStorage(Level* level)
|
||||
: level(level),
|
||||
chunksMap(std::make_shared<util::WeakPtrsMap<glm::ivec2, Chunk>>()) {
|
||||
ChunksStorage::ChunksStorage(Level* level) : level(level) {
|
||||
}
|
||||
|
||||
std::shared_ptr<Chunk> ChunksStorage::fetch(int x, int z) {
|
||||
std::lock_guard lock(*chunksMap);
|
||||
return chunksMap->fetch({x, z});
|
||||
const auto& found = chunksMap.find(keyfrom(x, z));
|
||||
if (found == chunksMap.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return found->second;
|
||||
}
|
||||
|
||||
static void check_voxels(const ContentIndices& indices, Chunk& chunk) {
|
||||
@@ -51,24 +63,22 @@ static void check_voxels(const ContentIndices& indices, Chunk& chunk) {
|
||||
}
|
||||
}
|
||||
|
||||
void ChunksStorage::erase(int x, int z) {
|
||||
chunksMap.erase(keyfrom(x, z));
|
||||
}
|
||||
|
||||
std::shared_ptr<Chunk> ChunksStorage::create(int x, int z) {
|
||||
if (auto ptr = chunksMap->fetch({x, z})) {
|
||||
return ptr;
|
||||
const auto& found = chunksMap.find(keyfrom(x, z));
|
||||
if (found != chunksMap.end()) {
|
||||
return found->second;
|
||||
}
|
||||
|
||||
auto chunk = std::make_shared<Chunk>(x, z);
|
||||
chunksMap[keyfrom(x, z)] = chunk;
|
||||
|
||||
World* world = level->getWorld();
|
||||
auto& regions = world->wfile.get()->getRegions();
|
||||
|
||||
auto& localChunksMap = chunksMap;
|
||||
auto chunk = std::shared_ptr<Chunk>(
|
||||
new Chunk(x, z),
|
||||
[localChunksMap, x, z](Chunk* ptr) {
|
||||
std::lock_guard lock(*localChunksMap);
|
||||
localChunksMap->erase({x, z});
|
||||
delete ptr;
|
||||
}
|
||||
);
|
||||
(*chunksMap)[glm::ivec2(chunk->x, chunk->z)] = chunk;
|
||||
if (auto data = regions.getVoxels(chunk->x, chunk->z)) {
|
||||
const auto& indices = *level->content->getIndices();
|
||||
|
||||
@@ -110,6 +120,92 @@ std::shared_ptr<Chunk> ChunksStorage::create(int x, int z) {
|
||||
return chunk;
|
||||
}
|
||||
|
||||
void ChunksStorage::pinChunk(std::shared_ptr<Chunk> chunk) {
|
||||
pinnedChunks[{chunk->x, chunk->z}] = std::move(chunk);
|
||||
}
|
||||
|
||||
void ChunksStorage::unpinChunk(int x, int z) {
|
||||
pinnedChunks.erase({x, z});
|
||||
}
|
||||
|
||||
size_t ChunksStorage::size() const {
|
||||
return chunksMap->size();
|
||||
return chunksMap.size();
|
||||
}
|
||||
|
||||
voxel* ChunksStorage::get(int x, int y, int z) const {
|
||||
if (y < 0 || y >= CHUNK_H) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int cx = floordiv<CHUNK_W>(x);
|
||||
int cz = floordiv<CHUNK_D>(z);
|
||||
|
||||
const auto& found = chunksMap.find(keyfrom(cx, cz));
|
||||
if (found == chunksMap.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
const auto& chunk = found->second;
|
||||
int lx = x - cx * CHUNK_W;
|
||||
int lz = z - cz * CHUNK_D;
|
||||
return &chunk->voxels[(y * CHUNK_D + lz) * CHUNK_W + lx];
|
||||
}
|
||||
|
||||
void ChunksStorage::incref(Chunk* chunk) {
|
||||
auto key = reinterpret_cast<ptrdiff_t>(chunk);
|
||||
const auto& found = refCounters.find(key);
|
||||
if (found == refCounters.end()) {
|
||||
refCounters[key] = 1;
|
||||
return;
|
||||
}
|
||||
found->second++;
|
||||
}
|
||||
|
||||
void ChunksStorage::decref(Chunk* chunk) {
|
||||
auto key = reinterpret_cast<ptrdiff_t>(chunk);
|
||||
const auto& found = refCounters.find(key);
|
||||
if (found == refCounters.end()) {
|
||||
abort();
|
||||
}
|
||||
if (--found->second == 0) {
|
||||
union {
|
||||
int pos[2];
|
||||
long long key;
|
||||
} ekey;
|
||||
ekey.pos[0] = chunk->x;
|
||||
ekey.pos[1] = chunk->z;
|
||||
|
||||
save(chunk);
|
||||
chunksMap.erase(ekey.key);
|
||||
refCounters.erase(found);
|
||||
}
|
||||
}
|
||||
|
||||
void ChunksStorage::save(Chunk* chunk) {
|
||||
if (chunk == nullptr) {
|
||||
return;
|
||||
}
|
||||
AABB aabb(
|
||||
glm::vec3(chunk->x * CHUNK_W, -INFINITY, chunk->z * CHUNK_D),
|
||||
glm::vec3(
|
||||
(chunk->x + 1) * CHUNK_W, INFINITY, (chunk->z + 1) * CHUNK_D
|
||||
)
|
||||
);
|
||||
auto entities = level->entities->getAllInside(aabb);
|
||||
auto root = dv::object();
|
||||
root["data"] = level->entities->serialize(entities);
|
||||
if (!entities.empty()) {
|
||||
level->entities->despawn(std::move(entities));
|
||||
chunk->flags.entities = true;
|
||||
}
|
||||
level->getWorld()->wfile->getRegions().put(
|
||||
chunk,
|
||||
chunk->flags.entities ? json::to_binary(root, true)
|
||||
: std::vector<ubyte>()
|
||||
);
|
||||
}
|
||||
|
||||
void ChunksStorage::saveAll() {
|
||||
for (const auto& [_, chunk] : chunksMap) {
|
||||
save(chunk.get());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user