From b85c5e367a2adea57ab0c3111e3d3b0cc924322b Mon Sep 17 00:00:00 2001 From: eliotbyte Date: Fri, 24 Oct 2025 20:13:05 +0300 Subject: [PATCH] fix extended block placement across chunk borders --- src/world/generator/StructurePlacement.hpp | 5 ++-- src/world/generator/WorldGenerator.cpp | 35 +++++++++++----------- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/world/generator/StructurePlacement.hpp b/src/world/generator/StructurePlacement.hpp index c2c174ab..d64b6d08 100644 --- a/src/world/generator/StructurePlacement.hpp +++ b/src/world/generator/StructurePlacement.hpp @@ -31,9 +31,10 @@ struct BlockPlacement { blockid_t block; glm::ivec3 position; uint8_t rotation; + bool mirror; - BlockPlacement(blockid_t block, glm::ivec3 position, uint8_t rotation) - : block(block), position(std::move(position)), rotation(rotation) { + BlockPlacement(blockid_t block, glm::ivec3 position, uint8_t rotation, bool mirror=false) + : block(block), position(std::move(position)), rotation(rotation), mirror(mirror) { } }; diff --git a/src/world/generator/WorldGenerator.cpp b/src/world/generator/WorldGenerator.cpp index 3125bff0..227b7d1d 100644 --- a/src/world/generator/WorldGenerator.cpp +++ b/src/world/generator/WorldGenerator.cpp @@ -238,7 +238,8 @@ void WorldGenerator::placeBlock(const BlockPlacement& block, int priority) { if (found != prototypes.end()) { // position becomes relative to prototype chunk glm::ivec3 rel = block.position - glm::ivec3(cx * CHUNK_W, 0, cz * CHUNK_D); - found->second->placements.emplace_back(priority, BlockPlacement{block.block, rel, block.rotation}); + bool owner = (cx == floordiv(block.position.x)) && (cz == floordiv(block.position.z)); + found->second->placements.emplace_back(priority, BlockPlacement{block.block, rel, block.rotation, !owner}); } } } @@ -643,26 +644,26 @@ void WorldGenerator::generateBlock( const auto& indices = content.getIndices()->blocks; const auto& def = indices.require(placement.block); - int cgx = chunkX * CHUNK_W; - int cgz = chunkZ * CHUNK_D; - - glm::ivec3 origin = placement.position; // already relative to chunk in placeBlock - - if (origin.x < 0 || origin.x >= CHUNK_W || - origin.z < 0 || origin.z >= CHUNK_D || - origin.y < 0 || origin.y >= CHUNK_H) { - return; + glm::ivec3 origin = placement.position; // relative; may be outside + int rotIndex = 0; + if (def.rotatable && def.rotations.variantsCount) { + rotIndex = placement.rotation % def.rotations.variantsCount; } - // write origin voxel - auto& vox = voxels[vox_index(origin.x, origin.y, origin.z)]; - vox.id = placement.block; - vox.state = {}; - vox.state.rotation = placement.rotation & 0b11; + // write origin only for owner chunk (mirror==false) and if inside bounds + if (!placement.mirror && + origin.x >= 0 && origin.x < CHUNK_W && + origin.y >= 0 && origin.y < CHUNK_H && + origin.z >= 0 && origin.z < CHUNK_D) { + auto& vox = voxels[vox_index(origin.x, origin.y, origin.z)]; + vox.id = placement.block; + vox.state = {}; + vox.state.rotation = rotIndex; + } // expand extended blocks if (def.rt.extended) { - const auto& rot = def.rotations.variants[vox.state.rotation]; + const auto& rot = def.rotations.variants[rotIndex]; const auto size = def.size; for (int sy = 0; sy < size.y; sy++) { for (int sz = 0; sz < size.z; sz++) { @@ -680,7 +681,7 @@ void WorldGenerator::generateBlock( struct voxel seg; seg.id = placement.block; seg.state = {}; - seg.state.rotation = vox.state.rotation; + seg.state.rotation = rotIndex; seg.state.segment = ((sx > 0) | ((sy > 0) << 1) | ((sz > 0) << 2)); voxels[vox_index(pos.x, pos.y, pos.z)] = seg; }