add blocks_agent templates & remove block.get_slow
This commit is contained in:
+5
-25
@@ -23,6 +23,7 @@
|
||||
#include "Block.hpp"
|
||||
#include "Chunk.hpp"
|
||||
#include "voxel.hpp"
|
||||
#include "blocks_agent.hpp"
|
||||
|
||||
Chunks::Chunks(
|
||||
int32_t w,
|
||||
@@ -33,7 +34,7 @@ Chunks::Chunks(
|
||||
Level* level
|
||||
)
|
||||
: level(level),
|
||||
indices(level->content->getIndices()),
|
||||
indices(level ? level->content->getIndices() : nullptr),
|
||||
areaMap(w, d),
|
||||
worldFiles(wfile) {
|
||||
areaMap.setCenter(ox-w/2, oz-d/2);
|
||||
@@ -43,30 +44,11 @@ Chunks::Chunks(
|
||||
}
|
||||
|
||||
voxel* Chunks::get(int32_t x, int32_t y, int32_t z) const {
|
||||
if (y < 0 || y >= CHUNK_H) {
|
||||
return nullptr;
|
||||
}
|
||||
int cx = floordiv<CHUNK_W>(x);
|
||||
int cz = floordiv<CHUNK_D>(z);
|
||||
auto ptr = areaMap.getIf(cx, cz);
|
||||
if (ptr == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
Chunk* chunk = ptr->get();
|
||||
if (chunk == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
int lx = x - cx * CHUNK_W;
|
||||
int lz = z - cz * CHUNK_D;
|
||||
return &chunk->voxels[(y * CHUNK_D + lz) * CHUNK_W + lx];
|
||||
return blocks_agent::get(*this, x, y, z);
|
||||
}
|
||||
|
||||
voxel& Chunks::require(int32_t x, int32_t y, int32_t z) const {
|
||||
auto voxel = get(x, y, z);
|
||||
if (voxel == nullptr) {
|
||||
throw std::runtime_error("voxel does not exist");
|
||||
}
|
||||
return *voxel;
|
||||
return blocks_agent::require(*this, x, y, z);
|
||||
}
|
||||
|
||||
const AABB* Chunks::isObstacleAt(float x, float y, float z) const {
|
||||
@@ -103,9 +85,7 @@ const AABB* Chunks::isObstacleAt(float x, float y, float z) const {
|
||||
}
|
||||
|
||||
bool Chunks::isSolidBlock(int32_t x, int32_t y, int32_t z) {
|
||||
voxel* v = get(x, y, z);
|
||||
if (v == nullptr) return false;
|
||||
return indices->blocks.require(v->id).rt.solid;
|
||||
return blocks_agent::is_solid_at(*this, x, y, z);
|
||||
}
|
||||
|
||||
bool Chunks::isReplaceableBlock(int32_t x, int32_t y, int32_t z) {
|
||||
|
||||
@@ -152,4 +152,8 @@ public:
|
||||
size_t getVolume() const {
|
||||
return areaMap.area();
|
||||
}
|
||||
|
||||
const ContentIndices& getContentIndices() const {
|
||||
return *indices;
|
||||
}
|
||||
};
|
||||
|
||||
+45
-38
@@ -16,10 +16,10 @@
|
||||
#include "Block.hpp"
|
||||
#include "Chunk.hpp"
|
||||
|
||||
inline long long keyfrom(int x, int z) {
|
||||
inline uint64_t keyfrom(int32_t x, int32_t z) {
|
||||
union {
|
||||
int pos[2];
|
||||
long long key;
|
||||
int32_t pos[2];
|
||||
uint64_t key;
|
||||
} ekey;
|
||||
ekey.pos[0] = x;
|
||||
ekey.pos[1] = z;
|
||||
@@ -28,7 +28,9 @@ inline long long keyfrom(int x, int z) {
|
||||
|
||||
static debug::Logger logger("chunks-storage");
|
||||
|
||||
GlobalChunks::GlobalChunks(Level* level) : level(level) {
|
||||
GlobalChunks::GlobalChunks(Level* level)
|
||||
: level(level), indices(level ? level->content->getIndices() : nullptr) {
|
||||
chunksMap.max_load_factor(CHUNKS_MAP_MAX_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
std::shared_ptr<Chunk> GlobalChunks::fetch(int x, int z) {
|
||||
@@ -67,6 +69,29 @@ void GlobalChunks::erase(int x, int z) {
|
||||
chunksMap.erase(keyfrom(x, z));
|
||||
}
|
||||
|
||||
static inline auto load_inventories(
|
||||
WorldRegions& regions,
|
||||
const Chunk& chunk,
|
||||
const ContentUnitIndices<Block>& defs
|
||||
) {
|
||||
auto invs = regions.fetchInventories(chunk.x, chunk.z);
|
||||
auto iterator = invs.begin();
|
||||
while (iterator != invs.end()) {
|
||||
uint index = iterator->first;
|
||||
const auto& def = defs.require(chunk.voxels[index].id);
|
||||
if (def.inventorySize == 0) {
|
||||
iterator = invs.erase(iterator);
|
||||
continue;
|
||||
}
|
||||
auto& inventory = iterator->second;
|
||||
if (def.inventorySize != inventory->size()) {
|
||||
inventory->resize(def.inventorySize);
|
||||
}
|
||||
++iterator;
|
||||
}
|
||||
return invs;
|
||||
}
|
||||
|
||||
std::shared_ptr<Chunk> GlobalChunks::create(int x, int z) {
|
||||
const auto& found = chunksMap.find(keyfrom(x, z));
|
||||
if (found != chunksMap.end()) {
|
||||
@@ -84,22 +109,10 @@ std::shared_ptr<Chunk> GlobalChunks::create(int x, int z) {
|
||||
|
||||
chunk->decode(data.get());
|
||||
check_voxels(indices, *chunk);
|
||||
auto invs = regions.fetchInventories(chunk->x, chunk->z);
|
||||
auto iterator = invs.begin();
|
||||
while (iterator != invs.end()) {
|
||||
uint index = iterator->first;
|
||||
const auto& def = indices.blocks.require(chunk->voxels[index].id);
|
||||
if (def.inventorySize == 0) {
|
||||
iterator = invs.erase(iterator);
|
||||
continue;
|
||||
}
|
||||
auto& inventory = iterator->second;
|
||||
if (def.inventorySize != inventory->size()) {
|
||||
inventory->resize(def.inventorySize);
|
||||
}
|
||||
++iterator;
|
||||
}
|
||||
chunk->setBlockInventories(std::move(invs));
|
||||
|
||||
chunk->setBlockInventories(
|
||||
load_inventories(regions, *chunk, indices.blocks)
|
||||
);
|
||||
|
||||
auto entitiesData = regions.fetchEntities(chunk->x, chunk->z);
|
||||
if (entitiesData.getType() == dv::value_type::object) {
|
||||
@@ -132,24 +145,6 @@ size_t GlobalChunks::size() const {
|
||||
return chunksMap.size();
|
||||
}
|
||||
|
||||
voxel* GlobalChunks::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 GlobalChunks::incref(Chunk* chunk) {
|
||||
auto key = reinterpret_cast<ptrdiff_t>(chunk);
|
||||
const auto& found = refCounters.find(key);
|
||||
@@ -209,3 +204,15 @@ void GlobalChunks::saveAll() {
|
||||
save(chunk.get());
|
||||
}
|
||||
}
|
||||
|
||||
void GlobalChunks::putChunk(std::shared_ptr<Chunk> chunk) {
|
||||
chunksMap[keyfrom(chunk->x, chunk->z)] = std::move(chunk);
|
||||
}
|
||||
|
||||
Chunk* GlobalChunks::getChunk(int cx, int cz) const {
|
||||
const auto& found = chunksMap.find(keyfrom(cx, cz));
|
||||
if (found == chunksMap.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return found->second.get();
|
||||
}
|
||||
|
||||
@@ -11,10 +11,12 @@
|
||||
|
||||
class Chunk;
|
||||
class Level;
|
||||
class ContentIndices;
|
||||
|
||||
class GlobalChunks {
|
||||
Level* level;
|
||||
std::unordered_map<long long, std::shared_ptr<Chunk>> chunksMap;
|
||||
const ContentIndices* indices;
|
||||
std::unordered_map<uint64_t, std::shared_ptr<Chunk>> chunksMap;
|
||||
std::unordered_map<glm::ivec2, std::shared_ptr<Chunk>> pinnedChunks;
|
||||
std::unordered_map<ptrdiff_t, int> refCounters;
|
||||
public:
|
||||
@@ -27,8 +29,6 @@ public:
|
||||
void pinChunk(std::shared_ptr<Chunk> chunk);
|
||||
void unpinChunk(int x, int z);
|
||||
|
||||
voxel* get(int x, int y, int z) const;
|
||||
|
||||
size_t size() const;
|
||||
|
||||
void incref(Chunk* chunk);
|
||||
@@ -38,4 +38,12 @@ public:
|
||||
|
||||
void save(Chunk* chunk);
|
||||
void saveAll();
|
||||
|
||||
void putChunk(std::shared_ptr<Chunk> chunk);
|
||||
|
||||
Chunk* getChunk(int cx, int cz) const;
|
||||
|
||||
const ContentIndices& getContentIndices() const {
|
||||
return *indices;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include "voxel.hpp"
|
||||
#include "typedefs.hpp"
|
||||
#include "maths/voxmaths.hpp"
|
||||
|
||||
class Chunk;
|
||||
class Chunks;
|
||||
class GlobalChunks;
|
||||
|
||||
/// Using templates to minimize OOP overhead
|
||||
|
||||
namespace blocks_agent {
|
||||
|
||||
template<class Storage>
|
||||
inline Chunk* get_chunk(const Storage& chunks, int cx, int cz) {
|
||||
return chunks.getChunk(cx, cz);
|
||||
}
|
||||
|
||||
template<class Storage>
|
||||
inline voxel* get(const Storage& chunks, int32_t x, int32_t y, int32_t z) {
|
||||
if (y < 0 || y >= CHUNK_H) {
|
||||
return nullptr;
|
||||
}
|
||||
int cx = floordiv<CHUNK_W>(x);
|
||||
int cz = floordiv<CHUNK_D>(z);
|
||||
Chunk* chunk = get_chunk(chunks, cx, cz);
|
||||
if (chunk == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
int lx = x - cx * CHUNK_W;
|
||||
int lz = z - cz * CHUNK_D;
|
||||
return &chunk->voxels[(y * CHUNK_D + lz) * CHUNK_W + lx];
|
||||
}
|
||||
|
||||
template<class Storage>
|
||||
inline voxel& require(const Storage& chunks, int32_t x, int32_t y, int32_t z) {
|
||||
auto vox = get(chunks, x, y, z);
|
||||
if (vox == nullptr) {
|
||||
throw std::runtime_error("voxel does not exist");
|
||||
}
|
||||
return *vox;
|
||||
}
|
||||
|
||||
template<class Storage>
|
||||
inline const Block& get_block_def(const Storage& chunks, blockid_t id) {
|
||||
return chunks.getContentIndices().blocks.require(id);
|
||||
}
|
||||
|
||||
template<class Storage>
|
||||
inline bool is_solid_at(const Storage& chunks, int32_t x, int32_t y, int32_t z) {
|
||||
if (auto vox = get(chunks, x, y, z)) {
|
||||
return get_block_def(chunks, vox->id).rt.solid;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // blocks_agent
|
||||
Reference in New Issue
Block a user