diff --git a/src/lighting/Lightmap.cpp b/src/lighting/Lightmap.cpp index cb077b8b..24581e24 100644 --- a/src/lighting/Lightmap.cpp +++ b/src/lighting/Lightmap.cpp @@ -2,16 +2,15 @@ #include "util/data_io.hpp" -#include +#include +#include void Lightmap::set(const Lightmap* lightmap) { set(lightmap->map); } void Lightmap::set(const light_t* map) { - for (size_t i = 0; i < CHUNK_VOL; i++) { - this->map[i] = map[i]; - } + std::memcpy(this->map, map, sizeof(light_t) * CHUNK_VOL); } static_assert(sizeof(light_t) == 2, "replace dataio calls to new light_t"); diff --git a/src/util/WeakPtrsMap.hpp b/src/util/WeakPtrsMap.hpp new file mode 100644 index 00000000..0d206d65 --- /dev/null +++ b/src/util/WeakPtrsMap.hpp @@ -0,0 +1,43 @@ +#include +#include +#include + +namespace util { + template + class WeakPtrsMap { + std::unordered_map> map; + std::mutex mutex; + public: + std::weak_ptr& operator[](const K& k) { + return map[k]; + } + + std::shared_ptr fetch(const K& k) { + auto found = map.find(k); + if (found == map.end()) { + return nullptr; + } + auto ptr = found->second.lock(); + if (ptr == nullptr) { + map.erase(found); + } + return ptr; + } + + void erase(const K& k) { + map.erase(k); + } + + size_t size() const { + return map.size(); + } + + void lock() { + mutex.lock(); + } + + void unlock() { + mutex.unlock(); + } + }; +} diff --git a/src/voxels/ChunksStorage.cpp b/src/voxels/ChunksStorage.cpp index 26b4fbd3..60e3b544 100644 --- a/src/voxels/ChunksStorage.cpp +++ b/src/voxels/ChunksStorage.cpp @@ -17,34 +17,28 @@ static debug::Logger logger("chunks-storage"); -ChunksStorage::ChunksStorage(Level* level) : level(level) { +ChunksStorage::ChunksStorage(Level* level) + : level(level), + chunksMap(std::make_shared>()) { } std::shared_ptr ChunksStorage::fetch(int x, int z) { - std::lock_guard lock(mutex); - - auto found = chunksMap.find(glm::ivec2(x, z)); - if (found == chunksMap.end()) { - return nullptr; - } - auto ptr = found->second.lock(); - if (ptr == nullptr) { - chunksMap.erase(found); - } - return ptr; + std::lock_guard lock(*chunksMap); + return chunksMap->fetch({x, z}); } -static void check_voxels(const ContentIndices& indices, Chunk* chunk) { +static void check_voxels(const ContentIndices& indices, Chunk& chunk) { bool corrupted = false; + blockid_t defsCount = indices.blocks.count(); for (size_t i = 0; i < CHUNK_VOL; i++) { - blockid_t id = chunk->voxels[i].id; - if (indices.blocks.get(id) == nullptr) { + blockid_t id = chunk.voxels[i].id; + if (id >= defsCount) { if (!corrupted) { #ifdef NDEBUG // release auto logline = logger.error(); logline << "corruped blocks detected at " << i << " of chunk "; - logline << chunk->x << "x" << chunk->z; + logline << chunk.x << "x" << chunk.z; logline << " -> " << id; corrupted = true; #else @@ -52,33 +46,34 @@ static void check_voxels(const ContentIndices& indices, Chunk* chunk) { abort(); #endif } - chunk->voxels[i].id = BLOCK_AIR; + chunk.voxels[i].id = BLOCK_AIR; } } } std::shared_ptr ChunksStorage::create(int x, int z) { - std::lock_guard lock(mutex); - - auto found = chunksMap.find(glm::ivec2(x, z)); - if (found != chunksMap.end()) { - auto chunk = found->second.lock(); - if (chunk) { - return chunk; - } + if (auto ptr = chunksMap->fetch({x, z})) { + return ptr; } World* world = level->getWorld(); auto& regions = world->wfile.get()->getRegions(); - auto chunk = std::make_shared(x, z); - chunksMap[glm::ivec2(chunk->x, chunk->z)] = chunk; + auto& localChunksMap = chunksMap; + auto chunk = std::shared_ptr( + new Chunk(x, z), + [localChunksMap, x, z](auto 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(); chunk->decode(data.get()); - check_voxels(indices, chunk.get()); - + check_voxels(indices, *chunk); auto invs = regions.fetchInventories(chunk->x, chunk->z); auto iterator = invs.begin(); while (iterator != invs.end()) { diff --git a/src/voxels/ChunksStorage.hpp b/src/voxels/ChunksStorage.hpp index 78bc03d0..62cccaf3 100644 --- a/src/voxels/ChunksStorage.hpp +++ b/src/voxels/ChunksStorage.hpp @@ -1,19 +1,16 @@ #pragma once -#include -#include -#include - #define GLM_ENABLE_EXPERIMENTAL #include +#include "util/WeakPtrsMap.hpp" + class Chunk; class Level; class ChunksStorage { Level* level; - std::mutex mutex; - std::unordered_map> chunksMap; + std::shared_ptr> chunksMap; public: ChunksStorage(Level* level); ~ChunksStorage() = default;