add blocks_agent templates & remove block.get_slow
This commit is contained in:
parent
5bf56d1f64
commit
6157f8193d
@ -8,11 +8,8 @@ assert(player.get_name(pid) == "Xerxes")
|
|||||||
test.sleep_until(function() return world.count_chunks() >= 9 end, 1000)
|
test.sleep_until(function() return world.count_chunks() >= 9 end, 1000)
|
||||||
print(world.count_chunks())
|
print(world.count_chunks())
|
||||||
|
|
||||||
for i=1,3 do
|
timeit(10000000, block.get, 0, 0, 0)
|
||||||
print("---")
|
timeit(10000000, core.blank, 0, 0, 0)
|
||||||
timeit(1000000, block.get, 0, 0, 0)
|
|
||||||
timeit(1000000, block.get_slow, 0, 0, 0)
|
|
||||||
end
|
|
||||||
|
|
||||||
block.destruct(0, 0, 0, pid)
|
block.destruct(0, 0, 0, pid)
|
||||||
assert(block.get(0, 0, 0) == 0)
|
assert(block.get(0, 0, 0) == 0)
|
||||||
|
|||||||
@ -35,6 +35,11 @@ inline constexpr int CHUNK_D = 16;
|
|||||||
inline constexpr uint VOXEL_USER_BITS = 8;
|
inline constexpr uint VOXEL_USER_BITS = 8;
|
||||||
inline constexpr uint VOXEL_USER_BITS_OFFSET = sizeof(blockstate_t)*8-VOXEL_USER_BITS;
|
inline constexpr uint VOXEL_USER_BITS_OFFSET = sizeof(blockstate_t)*8-VOXEL_USER_BITS;
|
||||||
|
|
||||||
|
/// @brief % unordered map max average buckets load factor.
|
||||||
|
/// Low value gives significant performance impact by minimizing collisions and
|
||||||
|
/// lookup latency. Default value (1.0) shows x2 slower work.
|
||||||
|
inline constexpr float CHUNKS_MAP_MAX_LOAD_FACTOR = 0.1f;
|
||||||
|
|
||||||
/// @brief chunk volume (count of voxels per Chunk)
|
/// @brief chunk volume (count of voxels per Chunk)
|
||||||
inline constexpr int CHUNK_VOL = (CHUNK_W * CHUNK_H * CHUNK_D);
|
inline constexpr int CHUNK_VOL = (CHUNK_W * CHUNK_H * CHUNK_D);
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
#include "voxels/Chunks.hpp"
|
#include "voxels/Chunks.hpp"
|
||||||
#include "voxels/voxel.hpp"
|
#include "voxels/voxel.hpp"
|
||||||
#include "voxels/GlobalChunks.hpp"
|
#include "voxels/GlobalChunks.hpp"
|
||||||
|
#include "voxels/blocks_agent.hpp"
|
||||||
#include "world/Level.hpp"
|
#include "world/Level.hpp"
|
||||||
#include "maths/voxmaths.hpp"
|
#include "maths/voxmaths.hpp"
|
||||||
#include "data/StructLayout.hpp"
|
#include "data/StructLayout.hpp"
|
||||||
@ -15,13 +16,13 @@
|
|||||||
|
|
||||||
using namespace scripting;
|
using namespace scripting;
|
||||||
|
|
||||||
static const Block* require_block(lua::State* L) {
|
static inline const Block* require_block(lua::State* L) {
|
||||||
auto indices = content->getIndices();
|
auto indices = content->getIndices();
|
||||||
auto id = lua::tointeger(L, 1);
|
auto id = lua::tointeger(L, 1);
|
||||||
return indices->blocks.get(id);
|
return indices->blocks.get(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int l_get_def(lua::State* L) {
|
static inline int l_get_def(lua::State* L) {
|
||||||
if (auto def = require_block(L)) {
|
if (auto def = require_block(L)) {
|
||||||
return lua::pushstring(L, def->name);
|
return lua::pushstring(L, def->name);
|
||||||
}
|
}
|
||||||
@ -39,8 +40,7 @@ static int l_is_solid_at(lua::State* L) {
|
|||||||
auto x = lua::tointeger(L, 1);
|
auto x = lua::tointeger(L, 1);
|
||||||
auto y = lua::tointeger(L, 2);
|
auto y = lua::tointeger(L, 2);
|
||||||
auto z = lua::tointeger(L, 3);
|
auto z = lua::tointeger(L, 3);
|
||||||
|
return lua::pushboolean(L, blocks_agent::is_solid_at(*level->chunks, x, y, z));
|
||||||
return lua::pushboolean(L, level->chunks->isSolidBlock(x, y, z));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int l_count(lua::State* L) {
|
static int l_count(lua::State* L) {
|
||||||
@ -110,16 +110,7 @@ static int l_get(lua::State* L) {
|
|||||||
auto x = lua::tointeger(L, 1);
|
auto x = lua::tointeger(L, 1);
|
||||||
auto y = lua::tointeger(L, 2);
|
auto y = lua::tointeger(L, 2);
|
||||||
auto z = lua::tointeger(L, 3);
|
auto z = lua::tointeger(L, 3);
|
||||||
auto vox = level->chunks->get(x, y, z);
|
auto vox = blocks_agent::get(*level->chunksStorage, x, y, z);
|
||||||
int id = vox == nullptr ? -1 : vox->id;
|
|
||||||
return lua::pushinteger(L, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int l_get_slow(lua::State* L) {
|
|
||||||
auto x = lua::tointeger(L, 1);
|
|
||||||
auto y = lua::tointeger(L, 2);
|
|
||||||
auto z = lua::tointeger(L, 3);
|
|
||||||
auto vox = level->chunksStorage->get(x, y, z);
|
|
||||||
int id = vox == nullptr ? -1 : vox->id;
|
int id = vox == nullptr ? -1 : vox->id;
|
||||||
return lua::pushinteger(L, id);
|
return lua::pushinteger(L, id);
|
||||||
}
|
}
|
||||||
@ -128,7 +119,7 @@ static int l_get_x(lua::State* L) {
|
|||||||
auto x = lua::tointeger(L, 1);
|
auto x = lua::tointeger(L, 1);
|
||||||
auto y = lua::tointeger(L, 2);
|
auto y = lua::tointeger(L, 2);
|
||||||
auto z = lua::tointeger(L, 3);
|
auto z = lua::tointeger(L, 3);
|
||||||
auto vox = level->chunksStorage->get(x, y, z);
|
auto vox = blocks_agent::get(*level->chunksStorage, x, y, z);
|
||||||
if (vox == nullptr) {
|
if (vox == nullptr) {
|
||||||
return lua::pushivec_stack(L, glm::ivec3(1, 0, 0));
|
return lua::pushivec_stack(L, glm::ivec3(1, 0, 0));
|
||||||
}
|
}
|
||||||
@ -145,7 +136,7 @@ static int l_get_y(lua::State* L) {
|
|||||||
auto x = lua::tointeger(L, 1);
|
auto x = lua::tointeger(L, 1);
|
||||||
auto y = lua::tointeger(L, 2);
|
auto y = lua::tointeger(L, 2);
|
||||||
auto z = lua::tointeger(L, 3);
|
auto z = lua::tointeger(L, 3);
|
||||||
auto vox = level->chunksStorage->get(x, y, z);
|
auto vox = blocks_agent::get(*level->chunksStorage, x, y, z);
|
||||||
if (vox == nullptr) {
|
if (vox == nullptr) {
|
||||||
return lua::pushivec_stack(L, glm::ivec3(0, 1, 0));
|
return lua::pushivec_stack(L, glm::ivec3(0, 1, 0));
|
||||||
}
|
}
|
||||||
@ -162,7 +153,7 @@ static int l_get_z(lua::State* L) {
|
|||||||
auto x = lua::tointeger(L, 1);
|
auto x = lua::tointeger(L, 1);
|
||||||
auto y = lua::tointeger(L, 2);
|
auto y = lua::tointeger(L, 2);
|
||||||
auto z = lua::tointeger(L, 3);
|
auto z = lua::tointeger(L, 3);
|
||||||
auto vox = level->chunksStorage->get(x, y, z);
|
auto vox = blocks_agent::get(*level->chunksStorage, x, y, z);
|
||||||
if (vox == nullptr) {
|
if (vox == nullptr) {
|
||||||
return lua::pushivec_stack(L, glm::ivec3(0, 0, 1));
|
return lua::pushivec_stack(L, glm::ivec3(0, 0, 1));
|
||||||
}
|
}
|
||||||
@ -179,7 +170,7 @@ static int l_get_rotation(lua::State* L) {
|
|||||||
auto x = lua::tointeger(L, 1);
|
auto x = lua::tointeger(L, 1);
|
||||||
auto y = lua::tointeger(L, 2);
|
auto y = lua::tointeger(L, 2);
|
||||||
auto z = lua::tointeger(L, 3);
|
auto z = lua::tointeger(L, 3);
|
||||||
voxel* vox = level->chunksStorage->get(x, y, z);
|
auto vox = blocks_agent::get(*level->chunksStorage, x, y, z);
|
||||||
int rotation = vox == nullptr ? 0 : vox->state.rotation;
|
int rotation = vox == nullptr ? 0 : vox->state.rotation;
|
||||||
return lua::pushinteger(L, rotation);
|
return lua::pushinteger(L, rotation);
|
||||||
}
|
}
|
||||||
@ -197,7 +188,7 @@ static int l_get_states(lua::State* L) {
|
|||||||
auto x = lua::tointeger(L, 1);
|
auto x = lua::tointeger(L, 1);
|
||||||
auto y = lua::tointeger(L, 2);
|
auto y = lua::tointeger(L, 2);
|
||||||
auto z = lua::tointeger(L, 3);
|
auto z = lua::tointeger(L, 3);
|
||||||
auto vox = level->chunksStorage->get(x, y, z);
|
auto vox = blocks_agent::get(*level->chunksStorage, x, y, z);
|
||||||
int states = vox == nullptr ? 0 : blockstate2int(vox->state);
|
int states = vox == nullptr ? 0 : blockstate2int(vox->state);
|
||||||
return lua::pushinteger(L, states);
|
return lua::pushinteger(L, states);
|
||||||
}
|
}
|
||||||
@ -226,7 +217,7 @@ static int l_get_user_bits(lua::State* L) {
|
|||||||
auto offset = lua::tointeger(L, 4) + VOXEL_USER_BITS_OFFSET;
|
auto offset = lua::tointeger(L, 4) + VOXEL_USER_BITS_OFFSET;
|
||||||
auto bits = lua::tointeger(L, 5);
|
auto bits = lua::tointeger(L, 5);
|
||||||
|
|
||||||
auto vox = level->chunks->get(x, y, z);
|
auto vox = blocks_agent::get(*level->chunksStorage, x, y, z);
|
||||||
if (vox == nullptr) {
|
if (vox == nullptr) {
|
||||||
return lua::pushinteger(L, 0);
|
return lua::pushinteger(L, 0);
|
||||||
}
|
}
|
||||||
@ -352,7 +343,7 @@ static int l_place(lua::State* L) {
|
|||||||
if (static_cast<size_t>(id) >= indices->blocks.count()) {
|
if (static_cast<size_t>(id) >= indices->blocks.count()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (!level->chunks->get(x, y, z)) {
|
if (!blocks_agent::get(*level->chunksStorage, x, y, z)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
const auto def = level->content->getIndices()->blocks.get(id);
|
const auto def = level->content->getIndices()->blocks.get(id);
|
||||||
@ -373,11 +364,11 @@ static int l_destruct(lua::State* L) {
|
|||||||
auto y = lua::tointeger(L, 2);
|
auto y = lua::tointeger(L, 2);
|
||||||
auto z = lua::tointeger(L, 3);
|
auto z = lua::tointeger(L, 3);
|
||||||
auto playerid = lua::gettop(L) >= 4 ? lua::tointeger(L, 4) : -1;
|
auto playerid = lua::gettop(L) >= 4 ? lua::tointeger(L, 4) : -1;
|
||||||
auto voxel = level->chunks->get(x, y, z);
|
auto vox = blocks_agent::get(*level->chunksStorage, x, y, z);
|
||||||
if (voxel == nullptr) {
|
if (vox == nullptr) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
auto& def = level->content->getIndices()->blocks.require(voxel->id);
|
auto& def = level->content->getIndices()->blocks.require(vox->id);
|
||||||
auto player = level->players->get(playerid);
|
auto player = level->players->get(playerid);
|
||||||
controller->getBlocksController()->breakBlock(player, def, x, y, z);
|
controller->getBlocksController()->breakBlock(player, def, x, y, z);
|
||||||
return 0;
|
return 0;
|
||||||
@ -504,12 +495,15 @@ static int l_get_field(lua::State* L) {
|
|||||||
}
|
}
|
||||||
auto cx = floordiv(x, CHUNK_W);
|
auto cx = floordiv(x, CHUNK_W);
|
||||||
auto cz = floordiv(z, CHUNK_D);
|
auto cz = floordiv(z, CHUNK_D);
|
||||||
auto chunk = level->chunks->getChunk(cx, cz);
|
auto chunk = blocks_agent::get_chunk(*level->chunksStorage, cx, cz);
|
||||||
|
if (chunk == nullptr || y < 0 || y >= CHUNK_H) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
auto lx = x - cx * CHUNK_W;
|
auto lx = x - cx * CHUNK_W;
|
||||||
auto lz = z - cz * CHUNK_W;
|
auto lz = z - cz * CHUNK_W;
|
||||||
size_t voxelIndex = vox_index(lx, y, lz);
|
size_t voxelIndex = vox_index(lx, y, lz);
|
||||||
|
|
||||||
const auto& vox = level->chunks->require(x, y, z);
|
const auto& vox = chunk->voxels[voxelIndex];
|
||||||
const auto& def = content->getIndices()->blocks.require(vox.id);
|
const auto& def = content->getIndices()->blocks.require(vox.id);
|
||||||
if (def.dataStruct == nullptr) {
|
if (def.dataStruct == nullptr) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -568,15 +562,18 @@ static int l_set_field(lua::State* L) {
|
|||||||
if (lua::gettop(L) >= 6) {
|
if (lua::gettop(L) >= 6) {
|
||||||
index = lua::tointeger(L, 6);
|
index = lua::tointeger(L, 6);
|
||||||
}
|
}
|
||||||
auto vox = level->chunks->get(x, y, z);
|
|
||||||
auto cx = floordiv(x, CHUNK_W);
|
auto cx = floordiv(x, CHUNK_W);
|
||||||
auto cz = floordiv(z, CHUNK_D);
|
auto cz = floordiv(z, CHUNK_D);
|
||||||
auto chunk = level->chunks->getChunk(cx, cz);
|
|
||||||
auto lx = x - cx * CHUNK_W;
|
auto lx = x - cx * CHUNK_W;
|
||||||
auto lz = z - cz * CHUNK_W;
|
auto lz = z - cz * CHUNK_W;
|
||||||
|
auto chunk = blocks_agent::get_chunk(*level->chunksStorage, cx, cz);
|
||||||
|
if (chunk == nullptr || y < 0 || y >= CHUNK_H) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
size_t voxelIndex = vox_index(lx, y, lz);
|
size_t voxelIndex = vox_index(lx, y, lz);
|
||||||
|
const auto& vox = chunk->voxels[voxelIndex];
|
||||||
|
|
||||||
const auto& def = content->getIndices()->blocks.require(vox->id);
|
const auto& def = content->getIndices()->blocks.require(vox.id);
|
||||||
if (def.dataStruct == nullptr) {
|
if (def.dataStruct == nullptr) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -608,7 +605,6 @@ const luaL_Reg blocklib[] = {
|
|||||||
{"is_replaceable_at", lua::wrap<l_is_replaceable_at>},
|
{"is_replaceable_at", lua::wrap<l_is_replaceable_at>},
|
||||||
{"set", lua::wrap<l_set>},
|
{"set", lua::wrap<l_set>},
|
||||||
{"get", lua::wrap<l_get>},
|
{"get", lua::wrap<l_get>},
|
||||||
{"get_slow", lua::wrap<l_get_slow>},
|
|
||||||
{"get_X", lua::wrap<l_get_x>},
|
{"get_X", lua::wrap<l_get_x>},
|
||||||
{"get_Y", lua::wrap<l_get_y>},
|
{"get_Y", lua::wrap<l_get_y>},
|
||||||
{"get_Z", lua::wrap<l_get_z>},
|
{"get_Z", lua::wrap<l_get_z>},
|
||||||
|
|||||||
@ -16,6 +16,7 @@
|
|||||||
#include "logic/EngineController.hpp"
|
#include "logic/EngineController.hpp"
|
||||||
#include "logic/LevelController.hpp"
|
#include "logic/LevelController.hpp"
|
||||||
#include "util/listutil.hpp"
|
#include "util/listutil.hpp"
|
||||||
|
#include "util/platform.hpp"
|
||||||
#include "window/Events.hpp"
|
#include "window/Events.hpp"
|
||||||
#include "window/Window.hpp"
|
#include "window/Window.hpp"
|
||||||
#include "world/Level.hpp"
|
#include "world/Level.hpp"
|
||||||
@ -220,8 +221,6 @@ static int l_load_texture(lua::State* L) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "util/platform.hpp"
|
|
||||||
|
|
||||||
static int l_open_folder(lua::State* L) {
|
static int l_open_folder(lua::State* L) {
|
||||||
auto path = engine->getPaths()->resolve(lua::require_string(L, 1));
|
auto path = engine->getPaths()->resolve(lua::require_string(L, 1));
|
||||||
platform::open_folder(path);
|
platform::open_folder(path);
|
||||||
@ -239,7 +238,7 @@ static int l_blank(lua::State*) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const luaL_Reg corelib[] = {
|
const luaL_Reg corelib[] = {
|
||||||
{"nop", lua::wrap<l_blank>},
|
{"blank", lua::wrap<l_blank>},
|
||||||
{"get_version", lua::wrap<l_get_version>},
|
{"get_version", lua::wrap<l_get_version>},
|
||||||
{"new_world", lua::wrap<l_new_world>},
|
{"new_world", lua::wrap<l_new_world>},
|
||||||
{"open_world", lua::wrap<l_open_world>},
|
{"open_world", lua::wrap<l_open_world>},
|
||||||
|
|||||||
@ -23,6 +23,7 @@
|
|||||||
#include "Block.hpp"
|
#include "Block.hpp"
|
||||||
#include "Chunk.hpp"
|
#include "Chunk.hpp"
|
||||||
#include "voxel.hpp"
|
#include "voxel.hpp"
|
||||||
|
#include "blocks_agent.hpp"
|
||||||
|
|
||||||
Chunks::Chunks(
|
Chunks::Chunks(
|
||||||
int32_t w,
|
int32_t w,
|
||||||
@ -33,7 +34,7 @@ Chunks::Chunks(
|
|||||||
Level* level
|
Level* level
|
||||||
)
|
)
|
||||||
: level(level),
|
: level(level),
|
||||||
indices(level->content->getIndices()),
|
indices(level ? level->content->getIndices() : nullptr),
|
||||||
areaMap(w, d),
|
areaMap(w, d),
|
||||||
worldFiles(wfile) {
|
worldFiles(wfile) {
|
||||||
areaMap.setCenter(ox-w/2, oz-d/2);
|
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 {
|
voxel* Chunks::get(int32_t x, int32_t y, int32_t z) const {
|
||||||
if (y < 0 || y >= CHUNK_H) {
|
return blocks_agent::get(*this, x, y, z);
|
||||||
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];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
voxel& Chunks::require(int32_t x, int32_t y, int32_t z) const {
|
voxel& Chunks::require(int32_t x, int32_t y, int32_t z) const {
|
||||||
auto voxel = get(x, y, z);
|
return blocks_agent::require(*this, x, y, z);
|
||||||
if (voxel == nullptr) {
|
|
||||||
throw std::runtime_error("voxel does not exist");
|
|
||||||
}
|
|
||||||
return *voxel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const AABB* Chunks::isObstacleAt(float x, float y, float z) const {
|
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) {
|
bool Chunks::isSolidBlock(int32_t x, int32_t y, int32_t z) {
|
||||||
voxel* v = get(x, y, z);
|
return blocks_agent::is_solid_at(*this, x, y, z);
|
||||||
if (v == nullptr) return false;
|
|
||||||
return indices->blocks.require(v->id).rt.solid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Chunks::isReplaceableBlock(int32_t x, int32_t y, int32_t z) {
|
bool Chunks::isReplaceableBlock(int32_t x, int32_t y, int32_t z) {
|
||||||
|
|||||||
@ -152,4 +152,8 @@ public:
|
|||||||
size_t getVolume() const {
|
size_t getVolume() const {
|
||||||
return areaMap.area();
|
return areaMap.area();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ContentIndices& getContentIndices() const {
|
||||||
|
return *indices;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -16,10 +16,10 @@
|
|||||||
#include "Block.hpp"
|
#include "Block.hpp"
|
||||||
#include "Chunk.hpp"
|
#include "Chunk.hpp"
|
||||||
|
|
||||||
inline long long keyfrom(int x, int z) {
|
inline uint64_t keyfrom(int32_t x, int32_t z) {
|
||||||
union {
|
union {
|
||||||
int pos[2];
|
int32_t pos[2];
|
||||||
long long key;
|
uint64_t key;
|
||||||
} ekey;
|
} ekey;
|
||||||
ekey.pos[0] = x;
|
ekey.pos[0] = x;
|
||||||
ekey.pos[1] = z;
|
ekey.pos[1] = z;
|
||||||
@ -28,7 +28,9 @@ inline long long keyfrom(int x, int z) {
|
|||||||
|
|
||||||
static debug::Logger logger("chunks-storage");
|
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) {
|
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));
|
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) {
|
std::shared_ptr<Chunk> GlobalChunks::create(int x, int z) {
|
||||||
const auto& found = chunksMap.find(keyfrom(x, z));
|
const auto& found = chunksMap.find(keyfrom(x, z));
|
||||||
if (found != chunksMap.end()) {
|
if (found != chunksMap.end()) {
|
||||||
@ -84,22 +109,10 @@ std::shared_ptr<Chunk> GlobalChunks::create(int x, int z) {
|
|||||||
|
|
||||||
chunk->decode(data.get());
|
chunk->decode(data.get());
|
||||||
check_voxels(indices, *chunk);
|
check_voxels(indices, *chunk);
|
||||||
auto invs = regions.fetchInventories(chunk->x, chunk->z);
|
|
||||||
auto iterator = invs.begin();
|
chunk->setBlockInventories(
|
||||||
while (iterator != invs.end()) {
|
load_inventories(regions, *chunk, indices.blocks)
|
||||||
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));
|
|
||||||
|
|
||||||
auto entitiesData = regions.fetchEntities(chunk->x, chunk->z);
|
auto entitiesData = regions.fetchEntities(chunk->x, chunk->z);
|
||||||
if (entitiesData.getType() == dv::value_type::object) {
|
if (entitiesData.getType() == dv::value_type::object) {
|
||||||
@ -132,24 +145,6 @@ size_t GlobalChunks::size() const {
|
|||||||
return chunksMap.size();
|
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) {
|
void GlobalChunks::incref(Chunk* chunk) {
|
||||||
auto key = reinterpret_cast<ptrdiff_t>(chunk);
|
auto key = reinterpret_cast<ptrdiff_t>(chunk);
|
||||||
const auto& found = refCounters.find(key);
|
const auto& found = refCounters.find(key);
|
||||||
@ -209,3 +204,15 @@ void GlobalChunks::saveAll() {
|
|||||||
save(chunk.get());
|
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 Chunk;
|
||||||
class Level;
|
class Level;
|
||||||
|
class ContentIndices;
|
||||||
|
|
||||||
class GlobalChunks {
|
class GlobalChunks {
|
||||||
Level* level;
|
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<glm::ivec2, std::shared_ptr<Chunk>> pinnedChunks;
|
||||||
std::unordered_map<ptrdiff_t, int> refCounters;
|
std::unordered_map<ptrdiff_t, int> refCounters;
|
||||||
public:
|
public:
|
||||||
@ -27,8 +29,6 @@ public:
|
|||||||
void pinChunk(std::shared_ptr<Chunk> chunk);
|
void pinChunk(std::shared_ptr<Chunk> chunk);
|
||||||
void unpinChunk(int x, int z);
|
void unpinChunk(int x, int z);
|
||||||
|
|
||||||
voxel* get(int x, int y, int z) const;
|
|
||||||
|
|
||||||
size_t size() const;
|
size_t size() const;
|
||||||
|
|
||||||
void incref(Chunk* chunk);
|
void incref(Chunk* chunk);
|
||||||
@ -38,4 +38,12 @@ public:
|
|||||||
|
|
||||||
void save(Chunk* chunk);
|
void save(Chunk* chunk);
|
||||||
void saveAll();
|
void saveAll();
|
||||||
|
|
||||||
|
void putChunk(std::shared_ptr<Chunk> chunk);
|
||||||
|
|
||||||
|
Chunk* getChunk(int cx, int cz) const;
|
||||||
|
|
||||||
|
const ContentIndices& getContentIndices() const {
|
||||||
|
return *indices;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
58
src/voxels/blocks_agent.hpp
Normal file
58
src/voxels/blocks_agent.hpp
Normal file
@ -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
|
||||||
Loading…
x
Reference in New Issue
Block a user