move block set logic to the blocks_agent
This commit is contained in:
parent
6157f8193d
commit
87c19d69dc
@ -98,7 +98,7 @@ static int l_set(lua::State* L) {
|
||||
if (!level->chunks->get(x, y, z)) {
|
||||
return 0;
|
||||
}
|
||||
level->chunks->set(x, y, z, id, int2blockstate(state));
|
||||
blocks_agent::set(*level->chunksStorage, x, y, z, id, int2blockstate(state));
|
||||
level->lighting->onBlockSet(x, y, z, id);
|
||||
if (!noupdate) {
|
||||
blocks->updateSides(x, y, z);
|
||||
@ -269,7 +269,9 @@ static int l_is_replaceable_at(lua::State* L) {
|
||||
auto x = lua::tointeger(L, 1);
|
||||
auto y = lua::tointeger(L, 2);
|
||||
auto z = lua::tointeger(L, 3);
|
||||
return lua::pushboolean(L, level->chunks->isReplaceableBlock(x, y, z));
|
||||
return lua::pushboolean(
|
||||
L, blocks_agent::is_replaceable_at(*level->chunksStorage, x, y, z)
|
||||
);
|
||||
}
|
||||
|
||||
static int l_caption(lua::State* L) {
|
||||
|
||||
@ -89,9 +89,7 @@ bool Chunks::isSolidBlock(int32_t x, int32_t y, int32_t z) {
|
||||
}
|
||||
|
||||
bool Chunks::isReplaceableBlock(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).replaceable;
|
||||
return blocks_agent::is_replaceable_at(*this, x, y, z);
|
||||
}
|
||||
|
||||
bool Chunks::isObstacleBlock(int32_t x, int32_t y, int32_t z) {
|
||||
@ -184,50 +182,13 @@ glm::ivec3 Chunks::seekOrigin(
|
||||
void Chunks::eraseSegments(
|
||||
const Block& def, blockstate state, int x, int y, int z
|
||||
) {
|
||||
const auto& rotation = def.rotations.variants[state.rotation];
|
||||
for (int sy = 0; sy < def.size.y; sy++) {
|
||||
for (int sz = 0; sz < def.size.z; sz++) {
|
||||
for (int sx = 0; sx < def.size.x; sx++) {
|
||||
if ((sx | sy | sz) == 0) {
|
||||
continue;
|
||||
}
|
||||
glm::ivec3 pos(x, y, z);
|
||||
pos += rotation.axisX * sx;
|
||||
pos += rotation.axisY * sy;
|
||||
pos += rotation.axisZ * sz;
|
||||
set(pos.x, pos.y, pos.z, 0, {});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr uint8_t segment_to_int(int sx, int sy, int sz) {
|
||||
return ((sx > 0) | ((sy > 0) << 1) | ((sz > 0) << 2));
|
||||
blocks_agent::erase_segments(*this, def, state, x, y, z);
|
||||
}
|
||||
|
||||
void Chunks::repairSegments(
|
||||
const Block& def, blockstate state, int x, int y, int z
|
||||
) {
|
||||
const auto& rotation = def.rotations.variants[state.rotation];
|
||||
const auto id = def.rt.id;
|
||||
const auto size = def.size;
|
||||
for (int sy = 0; sy < size.y; sy++) {
|
||||
for (int sz = 0; sz < size.z; sz++) {
|
||||
for (int sx = 0; sx < size.x; sx++) {
|
||||
if ((sx | sy | sz) == 0) {
|
||||
continue;
|
||||
}
|
||||
blockstate segState = state;
|
||||
segState.segment = segment_to_int(sx, sy, sz);
|
||||
|
||||
glm::ivec3 pos(x, y, z);
|
||||
pos += rotation.axisX * sx;
|
||||
pos += rotation.axisY * sy;
|
||||
pos += rotation.axisZ * sz;
|
||||
set(pos.x, pos.y, pos.z, id, segState);
|
||||
}
|
||||
}
|
||||
}
|
||||
blocks_agent::repair_segments(*this, def, state, x, y, z);
|
||||
}
|
||||
|
||||
bool Chunks::checkReplaceability(
|
||||
@ -283,7 +244,7 @@ void Chunks::setRotationExtended(
|
||||
pos += rotation.axisZ * sz;
|
||||
|
||||
blockstate segState = newstate;
|
||||
segState.segment = segment_to_int(sx, sy, sz);
|
||||
segState.segment = blocks_agent::segment_to_int(sx, sy, sz);
|
||||
|
||||
auto vox = get(pos);
|
||||
// checked for nullptr by checkReplaceability
|
||||
@ -344,68 +305,7 @@ void Chunks::setRotation(int32_t x, int32_t y, int32_t z, uint8_t index) {
|
||||
void Chunks::set(
|
||||
int32_t x, int32_t y, int32_t z, uint32_t id, blockstate state
|
||||
) {
|
||||
if (y < 0 || y >= CHUNK_H) {
|
||||
return;
|
||||
}
|
||||
int cx = floordiv<CHUNK_W>(x);
|
||||
int cz = floordiv<CHUNK_D>(z);
|
||||
auto ptr = areaMap.getIf(cx, cz);
|
||||
if (ptr == nullptr) {
|
||||
return;
|
||||
}
|
||||
Chunk* chunk = ptr->get();
|
||||
if (chunk == nullptr) {
|
||||
return;
|
||||
}
|
||||
int lx = x - cx * CHUNK_W;
|
||||
int lz = z - cz * CHUNK_D;
|
||||
size_t index = vox_index(lx, y, lz);
|
||||
|
||||
// block finalization
|
||||
voxel& vox = chunk->voxels[(y * CHUNK_D + lz) * CHUNK_W + lx];
|
||||
const auto& prevdef = indices->blocks.require(vox.id);
|
||||
if (prevdef.inventorySize != 0) {
|
||||
chunk->removeBlockInventory(lx, y, lz);
|
||||
}
|
||||
if (prevdef.rt.extended && !vox.state.segment) {
|
||||
eraseSegments(prevdef, vox.state, x, y, z);
|
||||
}
|
||||
if (prevdef.dataStruct) {
|
||||
if (auto found = chunk->blocksMetadata.find(index)) {
|
||||
chunk->blocksMetadata.free(found);
|
||||
chunk->flags.unsaved = true;
|
||||
chunk->flags.blocksData = true;
|
||||
}
|
||||
}
|
||||
|
||||
// block initialization
|
||||
const auto& newdef = indices->blocks.require(id);
|
||||
vox.id = id;
|
||||
vox.state = state;
|
||||
chunk->setModifiedAndUnsaved();
|
||||
if (!state.segment && newdef.rt.extended) {
|
||||
repairSegments(newdef, state, x, y, z);
|
||||
}
|
||||
|
||||
if (y < chunk->bottom)
|
||||
chunk->bottom = y;
|
||||
else if (y + 1 > chunk->top)
|
||||
chunk->top = y + 1;
|
||||
else if (id == 0)
|
||||
chunk->updateHeights();
|
||||
|
||||
if (lx == 0 && (chunk = getChunk(cx - 1, cz))) {
|
||||
chunk->flags.modified = true;
|
||||
}
|
||||
if (lz == 0 && (chunk = getChunk(cx, cz - 1))) {
|
||||
chunk->flags.modified = true;
|
||||
}
|
||||
if (lx == CHUNK_W - 1 && (chunk = getChunk(cx + 1, cz))) {
|
||||
chunk->flags.modified = true;
|
||||
}
|
||||
if (lz == CHUNK_D - 1 && (chunk = getChunk(cx, cz + 1))) {
|
||||
chunk->flags.modified = true;
|
||||
}
|
||||
blocks_agent::set(*this, x, y, z, id, state);
|
||||
}
|
||||
|
||||
voxel* Chunks::rayCast(
|
||||
@ -652,6 +552,7 @@ void Chunks::resize(uint32_t newW, uint32_t newD) {
|
||||
|
||||
bool Chunks::putChunk(const std::shared_ptr<Chunk>& chunk) {
|
||||
if (areaMap.set(chunk->x, chunk->z, chunk)) {
|
||||
if (level)
|
||||
level->events->trigger(LevelEventType::EVT_CHUNK_SHOWN, chunk.get());
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -16,16 +16,6 @@
|
||||
#include "Block.hpp"
|
||||
#include "Chunk.hpp"
|
||||
|
||||
inline uint64_t keyfrom(int32_t x, int32_t z) {
|
||||
union {
|
||||
int32_t pos[2];
|
||||
uint64_t key;
|
||||
} ekey;
|
||||
ekey.pos[0] = x;
|
||||
ekey.pos[1] = z;
|
||||
return ekey.key;
|
||||
}
|
||||
|
||||
static debug::Logger logger("chunks-storage");
|
||||
|
||||
GlobalChunks::GlobalChunks(Level* level)
|
||||
@ -208,11 +198,3 @@ void GlobalChunks::saveAll() {
|
||||
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();
|
||||
}
|
||||
|
||||
@ -14,6 +14,16 @@ class Level;
|
||||
class ContentIndices;
|
||||
|
||||
class GlobalChunks {
|
||||
static inline uint64_t keyfrom(int32_t x, int32_t z) {
|
||||
union {
|
||||
int32_t pos[2];
|
||||
uint64_t key;
|
||||
} ekey;
|
||||
ekey.pos[0] = x;
|
||||
ekey.pos[1] = z;
|
||||
return ekey.key;
|
||||
}
|
||||
|
||||
Level* level;
|
||||
const ContentIndices* indices;
|
||||
std::unordered_map<uint64_t, std::shared_ptr<Chunk>> chunksMap;
|
||||
@ -41,7 +51,13 @@ public:
|
||||
|
||||
void putChunk(std::shared_ptr<Chunk> chunk);
|
||||
|
||||
Chunk* getChunk(int cx, int cz) const;
|
||||
inline Chunk* getChunk(int cx, int cz) const {
|
||||
const auto& found = chunksMap.find(keyfrom(cx, cz));
|
||||
if (found == chunksMap.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return found->second.get();
|
||||
}
|
||||
|
||||
const ContentIndices& getContentIndices() const {
|
||||
return *indices;
|
||||
|
||||
95
src/voxels/blocks_agent.cpp
Normal file
95
src/voxels/blocks_agent.cpp
Normal file
@ -0,0 +1,95 @@
|
||||
#include "blocks_agent.hpp"
|
||||
|
||||
using namespace blocks_agent;
|
||||
|
||||
template <class Storage>
|
||||
static inline void set_block(
|
||||
Storage& chunks,
|
||||
int32_t x,
|
||||
int32_t y,
|
||||
int32_t z,
|
||||
uint32_t id,
|
||||
blockstate state
|
||||
) {
|
||||
if (y < 0 || y >= CHUNK_H) {
|
||||
return;
|
||||
}
|
||||
const auto& indices = chunks.getContentIndices();
|
||||
int cx = floordiv<CHUNK_W>(x);
|
||||
int cz = floordiv<CHUNK_D>(z);
|
||||
Chunk* chunk = get_chunk(chunks, cx, cz);
|
||||
if (chunk == nullptr) {
|
||||
return;
|
||||
}
|
||||
int lx = x - cx * CHUNK_W;
|
||||
int lz = z - cz * CHUNK_D;
|
||||
size_t index = vox_index(lx, y, lz);
|
||||
|
||||
// block finalization
|
||||
voxel& vox = chunk->voxels[(y * CHUNK_D + lz) * CHUNK_W + lx];
|
||||
const auto& prevdef = indices.blocks.require(vox.id);
|
||||
if (prevdef.inventorySize != 0) {
|
||||
chunk->removeBlockInventory(lx, y, lz);
|
||||
}
|
||||
if (prevdef.rt.extended && !vox.state.segment) {
|
||||
erase_segments(chunks, prevdef, vox.state, x, y, z);
|
||||
}
|
||||
if (prevdef.dataStruct) {
|
||||
if (auto found = chunk->blocksMetadata.find(index)) {
|
||||
chunk->blocksMetadata.free(found);
|
||||
chunk->flags.unsaved = true;
|
||||
chunk->flags.blocksData = true;
|
||||
}
|
||||
}
|
||||
|
||||
// block initialization
|
||||
const auto& newdef = indices.blocks.require(id);
|
||||
vox.id = id;
|
||||
vox.state = state;
|
||||
chunk->setModifiedAndUnsaved();
|
||||
if (!state.segment && newdef.rt.extended) {
|
||||
repair_segments(chunks, newdef, state, x, y, z);
|
||||
}
|
||||
|
||||
if (y < chunk->bottom)
|
||||
chunk->bottom = y;
|
||||
else if (y + 1 > chunk->top)
|
||||
chunk->top = y + 1;
|
||||
else if (id == 0)
|
||||
chunk->updateHeights();
|
||||
|
||||
if (lx == 0 && (chunk = get_chunk(chunks, cx - 1, cz))) {
|
||||
chunk->flags.modified = true;
|
||||
}
|
||||
if (lz == 0 && (chunk = get_chunk(chunks, cx, cz - 1))) {
|
||||
chunk->flags.modified = true;
|
||||
}
|
||||
if (lx == CHUNK_W - 1 && (chunk = get_chunk(chunks, cx + 1, cz))) {
|
||||
chunk->flags.modified = true;
|
||||
}
|
||||
if (lz == CHUNK_D - 1 && (chunk = get_chunk(chunks, cx, cz + 1))) {
|
||||
chunk->flags.modified = true;
|
||||
}
|
||||
}
|
||||
|
||||
void blocks_agent::set(
|
||||
Chunks& chunks,
|
||||
int32_t x,
|
||||
int32_t y,
|
||||
int32_t z,
|
||||
uint32_t id,
|
||||
blockstate state
|
||||
) {
|
||||
set_block(chunks, x, y, z, id, state);
|
||||
}
|
||||
|
||||
void blocks_agent::set(
|
||||
GlobalChunks& chunks,
|
||||
int32_t x,
|
||||
int32_t y,
|
||||
int32_t z,
|
||||
uint32_t id,
|
||||
blockstate state
|
||||
) {
|
||||
set_block(chunks, x, y, z, id, state);
|
||||
}
|
||||
@ -1,12 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "voxel.hpp"
|
||||
#include "Block.hpp"
|
||||
#include "Chunk.hpp"
|
||||
#include "Chunks.hpp"
|
||||
#include "GlobalChunks.hpp"
|
||||
#include "constants.hpp"
|
||||
#include "typedefs.hpp"
|
||||
#include "content/Content.hpp"
|
||||
#include "maths/voxmaths.hpp"
|
||||
|
||||
class Chunk;
|
||||
class Chunks;
|
||||
class GlobalChunks;
|
||||
#include <stdexcept>
|
||||
|
||||
/// Using templates to minimize OOP overhead
|
||||
|
||||
@ -55,4 +59,81 @@ inline bool is_solid_at(const Storage& chunks, int32_t x, int32_t y, int32_t z)
|
||||
return false;
|
||||
}
|
||||
|
||||
template<class Storage>
|
||||
inline bool is_replaceable_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).replaceable;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void set(
|
||||
Chunks& chunks,
|
||||
int32_t x,
|
||||
int32_t y,
|
||||
int32_t z,
|
||||
uint32_t id,
|
||||
blockstate state
|
||||
);
|
||||
|
||||
void set(
|
||||
GlobalChunks& chunks,
|
||||
int32_t x,
|
||||
int32_t y,
|
||||
int32_t z,
|
||||
uint32_t id,
|
||||
blockstate state
|
||||
);
|
||||
|
||||
template<class Storage>
|
||||
inline void erase_segments(
|
||||
Storage& chunks, const Block& def, blockstate state, int x, int y, int z
|
||||
) {
|
||||
const auto& rotation = def.rotations.variants[state.rotation];
|
||||
for (int sy = 0; sy < def.size.y; sy++) {
|
||||
for (int sz = 0; sz < def.size.z; sz++) {
|
||||
for (int sx = 0; sx < def.size.x; sx++) {
|
||||
if ((sx | sy | sz) == 0) {
|
||||
continue;
|
||||
}
|
||||
glm::ivec3 pos(x, y, z);
|
||||
pos += rotation.axisX * sx;
|
||||
pos += rotation.axisY * sy;
|
||||
pos += rotation.axisZ * sz;
|
||||
set(chunks, pos.x, pos.y, pos.z, 0, {});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr uint8_t segment_to_int(int sx, int sy, int sz) {
|
||||
return ((sx > 0) | ((sy > 0) << 1) | ((sz > 0) << 2));
|
||||
}
|
||||
|
||||
template <class Storage>
|
||||
inline void repair_segments(
|
||||
Storage& chunks, const Block& def, blockstate state, int x, int y, int z
|
||||
) {
|
||||
const auto& rotation = def.rotations.variants[state.rotation];
|
||||
const auto id = def.rt.id;
|
||||
const auto size = def.size;
|
||||
for (int sy = 0; sy < size.y; sy++) {
|
||||
for (int sz = 0; sz < size.z; sz++) {
|
||||
for (int sx = 0; sx < size.x; sx++) {
|
||||
if ((sx | sy | sz) == 0) {
|
||||
continue;
|
||||
}
|
||||
blockstate segState = state;
|
||||
segState.segment = segment_to_int(sx, sy, sz);
|
||||
|
||||
glm::ivec3 pos(x, y, z);
|
||||
pos += rotation.axisX * sx;
|
||||
pos += rotation.axisY * sy;
|
||||
pos += rotation.axisZ * sz;
|
||||
set(chunks, pos.x, pos.y, pos.z, id, segState);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // blocks_agent
|
||||
|
||||
@ -189,10 +189,10 @@ void WorldGenerator::placeLine(const LinePlacement& line, int priority) {
|
||||
aabb.fix();
|
||||
aabb.a -= line.radius;
|
||||
aabb.b += line.radius;
|
||||
int cxa = floordiv(aabb.a.x, CHUNK_W);
|
||||
int cza = floordiv(aabb.a.z, CHUNK_D);
|
||||
int cxb = floordiv(aabb.b.x, CHUNK_W);
|
||||
int czb = floordiv(aabb.b.z, CHUNK_D);
|
||||
int cxa = floordiv<CHUNK_W>(aabb.a.x);
|
||||
int cza = floordiv<CHUNK_D>(aabb.a.z);
|
||||
int cxb = floordiv<CHUNK_W>(aabb.b.x);
|
||||
int czb = floordiv<CHUNK_D>(aabb.b.z);
|
||||
for (int cz = cza; cz <= czb; cz++) {
|
||||
for (int cx = cxa; cx <= cxb; cx++) {
|
||||
const auto& found = prototypes.find({cx, cz});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user