From f1a015d3e7fb3857cf656ca36685216178f40e1a Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 28 Jan 2026 23:04:06 +0300 Subject: [PATCH 1/7] optimize BlocksController::randomTick & reduce small allocations count --- src/logic/BlocksController.cpp | 17 +++-------------- src/logic/BlocksController.hpp | 1 + src/voxels/Chunk.hpp | 2 ++ 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/src/logic/BlocksController.cpp b/src/logic/BlocksController.cpp index 08e2aae7c..f859a8455 100644 --- a/src/logic/BlocksController.cpp +++ b/src/logic/BlocksController.cpp @@ -1,7 +1,5 @@ #include "BlocksController.hpp" -#include - #include "content/Content.hpp" #include "items/Inventories.hpp" #include "items/Inventory.hpp" @@ -175,12 +173,8 @@ void BlocksController::randomTick( void BlocksController::randomTick(int tickid, int parts, uint padding) { auto indices = level.content.getIndices(); - std::set chunksIterated; - for (const auto& [pid, player] : *level.players) { const auto& chunks = *player->chunks; - int offsetX = chunks.getOffsetX(); - int offsetY = chunks.getOffsetY(); int width = chunks.getWidth(); int height = chunks.getHeight(); int segments = 4; @@ -195,20 +189,15 @@ void BlocksController::randomTick(int tickid, int parts, uint padding) { if (chunk == nullptr || !chunk->flags.lighted) { continue; } - union { - int32_t pos[2]; - uint64_t key; - } posU; - posU.pos[0] = x + offsetX; - posU.pos[1] = z + offsetY; - if (chunksIterated.find(posU.key) != chunksIterated.end()) { + if (chunk->lastRandomTickId == randomTickId) { continue; } - chunksIterated.insert(posU.key); + chunk->lastRandomTickId = randomTickId; randomTick(*chunk, segments, indices); } } } + randomTickId++; } int64_t BlocksController::createBlockInventory(int x, int y, int z) { diff --git a/src/logic/BlocksController.hpp b/src/logic/BlocksController.hpp index f3fa5f67a..8b26e0190 100644 --- a/src/logic/BlocksController.hpp +++ b/src/logic/BlocksController.hpp @@ -33,6 +33,7 @@ class BlocksController { util::Clock worldTickClock; FastRandom random {}; std::vector blockInteractionCallbacks; + uint64_t randomTickId = 0; public: BlocksController(const Level& level, Lighting* lighting); diff --git a/src/voxels/Chunk.hpp b/src/voxels/Chunk.hpp index 393f05f8a..5d45629ea 100644 --- a/src/voxels/Chunk.hpp +++ b/src/voxels/Chunk.hpp @@ -40,6 +40,8 @@ public: bool dirtyHeights : 1; } flags {}; + uint64_t lastRandomTickId = -1; + /// @brief Block inventories map where key is index of block in voxels array ChunkInventoriesMap inventories; /// @brief Blocks metadata heap From 99f06c96253ef17d1733cd3bf8159f70db46c9e2 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Thu, 29 Jan 2026 18:36:23 +0300 Subject: [PATCH 2/7] add util::array_queue --- src/util/array_queue.hpp | 76 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 src/util/array_queue.hpp diff --git a/src/util/array_queue.hpp b/src/util/array_queue.hpp new file mode 100644 index 000000000..3e8799152 --- /dev/null +++ b/src/util/array_queue.hpp @@ -0,0 +1,76 @@ +#pragma once + +#include +#include +#include + +namespace util { + template + class array_queue { + public: + array_queue(size_t initCapacity = 8) + : _capacity(initCapacity), + _size(0), + _front(0), + _back(0), + _data(new T[_capacity]) { + if (initCapacity == 0 || (initCapacity & (initCapacity - 1)) != 0) { + throw std::invalid_argument("initCapacity must be positive power of 2"); + } + } + + ~array_queue() { + // todo + delete[] _data; + } + + void push(T&& value) { + if (_back == _front && _size) { + grow(); + } + _data[_back] = std::forward(value); + _back = (_back + 1) & (_capacity - 1); + ++_size; + } + + T& front() { + return _data[_front]; + } + + void pop() { + _data[_front].~T(); + _front = (_front + 1) & (_capacity - 1); + --_size; + } + + bool empty() const { + return _size == 0; + } + + size_t size() const { + return _size; + } + + private: + size_t _capacity; + size_t _size; + size_t _front; + size_t _back; + T* _data; + + void grow() { + size_t newCapacity = _capacity * 2; + T* newData = new T[newCapacity]; + + std::move(_data + _front, _data + _capacity, newData); + std::move(_data, _data + _front, newData + (_capacity - _front)); + + _back = _size; + _front = 0; + + delete[] _data; + _data = newData; + _capacity = newCapacity; + } + }; +} From 5c64d567667355eb5eea0e1a1ff24264ae2e3d6f Mon Sep 17 00:00:00 2001 From: MihailRis Date: Thu, 29 Jan 2026 18:37:20 +0300 Subject: [PATCH 3/7] replace deque with array_queue in LightSolver --- src/lighting/LightSolver.cpp | 49 ++++++++++++++++++------------------ src/lighting/LightSolver.hpp | 6 ++--- 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/src/lighting/LightSolver.cpp b/src/lighting/LightSolver.cpp index cda3ccc88..b6091fdc5 100644 --- a/src/lighting/LightSolver.cpp +++ b/src/lighting/LightSolver.cpp @@ -55,7 +55,7 @@ void LightSolver::remove(int x, int y, int z) { lightmap.set(x-chunk->x*CHUNK_W, y, z-chunk->z*CHUNK_D, channel, 0); } -void LightSolver::solve(){ +void LightSolver::solve() { const int coords[] = { 0, 0, 1, 0, 0,-1, @@ -66,47 +66,48 @@ void LightSolver::solve(){ }; while (!remqueue.empty()){ - const lightentry entry = remqueue.front(); + lightentry entry = std::move(remqueue.front()); remqueue.pop(); for (int i = 0; i < 6; i++) { - int imul3 = i*3; + int imul3 = i * 3; int x = entry.x+coords[imul3]; int y = entry.y+coords[imul3+1]; int z = entry.z+coords[imul3+2]; Chunk* chunk = chunks.getChunkByVoxel(x,y,z); - if (chunk) { - int lx = x - chunk->x * CHUNK_W; - int lz = z - chunk->z * CHUNK_D; - chunk->flags.modified = true; + if (chunk == nullptr) { + continue; + } + int lx = x - chunk->x * CHUNK_W; + int lz = z - chunk->z * CHUNK_D; + chunk->flags.modified = true; - assert(chunk->lightmap != nullptr); - auto& lightmap = *chunk->lightmap; + assert(chunk->lightmap != nullptr); + auto& lightmap = *chunk->lightmap; - ubyte light = lightmap.get(lx,y,lz, channel); - if (light != 0 && light == entry.light-1){ - voxel* vox = chunks.get(x, y, z); - if (vox && vox->id != 0) { - const Block* block = blockDefs[vox->id]; - if (uint8_t emission = block->emission[channel]) { - addqueue.push(lightentry {x, y, z, emission}); - lightmap.set(lx, y, lz, channel, emission); - } - else lightmap.set(lx, y, lz, channel, 0); + ubyte light = lightmap.get(lx,y,lz, channel); + if (light != 0 && light == entry.light-1) { + voxel* vox = chunks.get(x, y, z); + if (vox && vox->id != 0) { + const Block* block = blockDefs[vox->id]; + if (uint8_t emission = block->emission[channel]) { + addqueue.push(lightentry {x, y, z, emission}); + lightmap.set(lx, y, lz, channel, emission); } else lightmap.set(lx, y, lz, channel, 0); - remqueue.push(lightentry {x, y, z, light}); - } - else if (light >= entry.light){ - addqueue.push(lightentry {x, y, z, light}); } + else lightmap.set(lx, y, lz, channel, 0); + remqueue.push(lightentry {x, y, z, light}); + } + else if (light >= entry.light) { + addqueue.push(lightentry {x, y, z, light}); } } } while (!addqueue.empty()){ - const lightentry entry = addqueue.front(); + lightentry entry = std::move(addqueue.front()); addqueue.pop(); for (int i = 0; i < 6; i++) { diff --git a/src/lighting/LightSolver.hpp b/src/lighting/LightSolver.hpp index e51863e1e..1e36a0e1d 100644 --- a/src/lighting/LightSolver.hpp +++ b/src/lighting/LightSolver.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include "util/array_queue.hpp" class Chunks; class ContentIndices; @@ -14,8 +14,8 @@ struct lightentry { }; class LightSolver { - std::queue addqueue; - std::queue remqueue; + util::array_queue addqueue; + util::array_queue remqueue; const Block* const* blockDefs; Chunks& chunks; int channel; From 117199a3ecc43a32eed6324ab1c4193e9c49b6cb Mon Sep 17 00:00:00 2001 From: MihailRis Date: Thu, 29 Jan 2026 19:28:24 +0300 Subject: [PATCH 4/7] update array_queue memory management --- src/util/array_queue.hpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/util/array_queue.hpp b/src/util/array_queue.hpp index 3e8799152..649ec2282 100644 --- a/src/util/array_queue.hpp +++ b/src/util/array_queue.hpp @@ -9,19 +9,20 @@ namespace util { class array_queue { public: array_queue(size_t initCapacity = 8) - : _capacity(initCapacity), - _size(0), - _front(0), - _back(0), - _data(new T[_capacity]) { + : _capacity(initCapacity), + _size(0), + _front(0), + _back(0), + _data(std::make_unique(_capacity)) { if (initCapacity == 0 || (initCapacity & (initCapacity - 1)) != 0) { throw std::invalid_argument("initCapacity must be positive power of 2"); } } ~array_queue() { - // todo - delete[] _data; + while (!empty()) { + pop(); + } } void push(T&& value) { @@ -56,20 +57,19 @@ namespace util { size_t _size; size_t _front; size_t _back; - T* _data; + std::unique_ptr _data; void grow() { size_t newCapacity = _capacity * 2; - T* newData = new T[newCapacity]; + auto newData = std::make_unique(newCapacity); - std::move(_data + _front, _data + _capacity, newData); - std::move(_data, _data + _front, newData + (_capacity - _front)); + std::move(_data.get() + _front, _data.get() + _capacity, newData.get()); + std::move(_data.get(), _data.get() + _front, newData.get() + (_capacity - _front)); _back = _size; _front = 0; - delete[] _data; - _data = newData; + _data.reset(newData.release()); _capacity = newCapacity; } }; From bf7732f68a53d99c57a4e41d87a4f7fdc3c142d7 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Thu, 29 Jan 2026 19:52:47 +0300 Subject: [PATCH 5/7] reduce Chunks.getChunkByVoxel calls in LightSolver --- src/lighting/LightSolver.cpp | 27 +++++++++++++++++-------- src/lighting/LightSolver.hpp | 3 ++- src/lighting/Lighting.cpp | 38 +++++++++++++++++++----------------- src/voxels/Chunk.hpp | 6 ++++++ 4 files changed, 47 insertions(+), 27 deletions(-) diff --git a/src/lighting/LightSolver.cpp b/src/lighting/LightSolver.cpp index b6091fdc5..f43b4d487 100644 --- a/src/lighting/LightSolver.cpp +++ b/src/lighting/LightSolver.cpp @@ -1,6 +1,3 @@ -#include -#include - #include "LightSolver.hpp" #include "Lightmap.hpp" #include "content/Content.hpp" @@ -9,6 +6,8 @@ #include "voxels/voxel.hpp" #include "voxels/Block.hpp" +#include + LightSolver::LightSolver(const ContentIndices& contentIds, Chunks& chunks, int channel) : blockDefs(contentIds.blocks.getDefs()), chunks(chunks), @@ -55,7 +54,7 @@ void LightSolver::remove(int x, int y, int z) { lightmap.set(x-chunk->x*CHUNK_W, y, z-chunk->z*CHUNK_D, channel, 0); } -void LightSolver::solve() { +void LightSolver::solve(Chunk* prevailingChunk) { const int coords[] = { 0, 0, 1, 0, 0,-1, @@ -75,10 +74,16 @@ void LightSolver::solve() { int y = entry.y+coords[imul3+1]; int z = entry.z+coords[imul3+2]; - Chunk* chunk = chunks.getChunkByVoxel(x,y,z); - if (chunk == nullptr) { + Chunk* chunk = prevailingChunk; + if (chunk == nullptr || !chunk->isBlockInside(x, z)) { + chunk = chunks.getChunkByVoxel(x,y,z); + if (chunk == nullptr) { + continue; + } + } else if (y < 0 || y >= CHUNK_H) { continue; } + int lx = x - chunk->x * CHUNK_W; int lz = z - chunk->z * CHUNK_D; chunk->flags.modified = true; @@ -116,10 +121,16 @@ void LightSolver::solve() { int y = entry.y+coords[imul3+1]; int z = entry.z+coords[imul3+2]; - Chunk* chunk = chunks.getChunkByVoxel(x,y,z); - if (chunk == nullptr) { + Chunk* chunk = prevailingChunk; + if (chunk == nullptr || !chunk->isBlockInside(x, z)) { + chunk = chunks.getChunkByVoxel(x,y,z); + if (chunk == nullptr) { + continue; + } + } else if (y < 0 || y >= CHUNK_H) { continue; } + assert(chunk->lightmap != nullptr); auto& lightmap = *chunk->lightmap; int lx = x - chunk->x * CHUNK_W; diff --git a/src/lighting/LightSolver.hpp b/src/lighting/LightSolver.hpp index 1e36a0e1d..31c33a804 100644 --- a/src/lighting/LightSolver.hpp +++ b/src/lighting/LightSolver.hpp @@ -2,6 +2,7 @@ #include "util/array_queue.hpp" +class Chunk; class Chunks; class ContentIndices; class Block; @@ -25,5 +26,5 @@ public: void add(int x, int y, int z); void add(int x, int y, int z, int emission); void remove(int x, int y, int z); - void solve(); + void solve(Chunk* prevailingChunk = nullptr); }; diff --git a/src/lighting/Lighting.cpp b/src/lighting/Lighting.cpp index 9101c72ac..8f90540bb 100644 --- a/src/lighting/Lighting.cpp +++ b/src/lighting/Lighting.cpp @@ -167,10 +167,10 @@ void Lighting::onChunkLoaded(int cx, int cz, bool expand) { } } } - solverR.solve(); - solverG.solve(); - solverB.solve(); - solverS.solve(); + solverR.solve(chunk); + solverG.solve(chunk); + solverB.solve(chunk); + solverS.solve(chunk); } void Lighting::onBlockSet(int x, int y, int z, blockid_t id){ @@ -180,9 +180,10 @@ void Lighting::onBlockSet(int x, int y, int z, blockid_t id){ solverB->remove(x,y,z); if (id == 0){ - solverR->solve(); - solverG->solve(); - solverB->solve(); + auto chunk = chunks.getChunkByVoxel(glm::ivec3{x, y, z}); + solverR->solve(chunk); + solverG->solve(chunk); + solverB->solve(chunk); if (chunks.getLight(x,y+1,z, 3) == 0xF){ for (int i = y; i >= 0; i--){ voxel* vox = chunks.get(x,i,z); @@ -197,11 +198,12 @@ void Lighting::onBlockSet(int x, int y, int z, blockid_t id){ solverR->add(x-1,y,z); solverG->add(x-1,y,z); solverB->add(x-1,y,z); solverS->add(x-1,y,z); solverR->add(x,y,z+1); solverG->add(x,y,z+1); solverB->add(x,y,z+1); solverS->add(x,y,z+1); solverR->add(x,y,z-1); solverG->add(x,y,z-1); solverB->add(x,y,z-1); solverS->add(x,y,z-1); - solverR->solve(); - solverG->solve(); - solverB->solve(); - solverS->solve(); + solverR->solve(chunk); + solverG->solve(chunk); + solverB->solve(chunk); + solverS->solve(chunk); } else { + auto chunk = chunks.getChunkByVoxel(glm::ivec3{x, y, z}); if (!block.skyLightPassing){ solverS->remove(x,y,z); for (int i = y-1; i >= 0; i--){ @@ -210,19 +212,19 @@ void Lighting::onBlockSet(int x, int y, int z, blockid_t id){ break; } } - solverS->solve(); + solverS->solve(chunk); } - solverR->solve(); - solverG->solve(); - solverB->solve(); + solverR->solve(chunk); + solverG->solve(chunk); + solverB->solve(chunk); if (block.emission[0] || block.emission[1] || block.emission[2]){ solverR->add(x,y,z,block.emission[0]); solverG->add(x,y,z,block.emission[1]); solverB->add(x,y,z,block.emission[2]); - solverR->solve(); - solverG->solve(); - solverB->solve(); + solverR->solve(chunk); + solverG->solve(chunk); + solverB->solve(chunk); } } } diff --git a/src/voxels/Chunk.hpp b/src/voxels/Chunk.hpp index 5d45629ea..5377df020 100644 --- a/src/voxels/Chunk.hpp +++ b/src/voxels/Chunk.hpp @@ -83,4 +83,10 @@ public: glm::vec3((x + 1) * CHUNK_W, INFINITY, (z + 1) * CHUNK_D) ); } + + bool isBlockInside(int x, int z) const { + x -= this->x * CHUNK_W; + z -= this->z * CHUNK_D; + return x >= 0 && z >= 0 && x < CHUNK_W && z < CHUNK_D; + } }; From 0012419651c938896709a9a2c29355d192d44773 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Thu, 29 Jan 2026 20:30:38 +0300 Subject: [PATCH 6/7] test content events names cache --- src/content/ContentLoader.cpp | 3 ++- src/items/ItemDef.hpp | 5 +++++ src/logic/scripting/scripting.cpp | 23 ++++++++++++++--------- src/logic/scripting/scripting.hpp | 8 ++++++-- src/voxels/Block.hpp | 7 +++++++ 5 files changed, 34 insertions(+), 12 deletions(-) diff --git a/src/content/ContentLoader.cpp b/src/content/ContentLoader.cpp index e2bf81f2d..e2a463cac 100644 --- a/src/content/ContentLoader.cpp +++ b/src/content/ContentLoader.cpp @@ -441,7 +441,8 @@ static void load_script(const Content& content, T& def) { def.name, scriptfile, def.scriptFile, - def.rt.funcsset + def.rt.funcsset, + def.rt.eventNames ); } } diff --git a/src/items/ItemDef.hpp b/src/items/ItemDef.hpp index ee37215a6..3f16e04b1 100644 --- a/src/items/ItemDef.hpp +++ b/src/items/ItemDef.hpp @@ -15,6 +15,9 @@ struct ItemFuncsSet { bool on_block_break_by : 1; }; +struct ItemFuncNamesCache { +}; + enum class ItemIconType { NONE, // invisible (core:empty) must not be rendered SPRITE, // textured quad: icon is `atlas_name:texture_name` @@ -75,6 +78,8 @@ struct ItemDef { bool emissive = false; std::set tags; + + ItemFuncNamesCache eventNames; } rt {}; ItemDef(const std::string& name); diff --git a/src/logic/scripting/scripting.cpp b/src/logic/scripting/scripting.cpp index 4af1a4287..ca1ab3164 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -1,8 +1,5 @@ #include "scripting.hpp" -#include -#include - #include "scripting_commons.hpp" #include "content/Content.hpp" #include "content/ContentPack.hpp" @@ -28,6 +25,9 @@ #include "world/World.hpp" #include "interfaces/Process.hpp" +#include +#include + using namespace scripting; static debug::Logger logger("scripting"); @@ -391,15 +391,15 @@ void scripting::on_blocks_tick(const Block& block, int tps) { } void scripting::update_block(const Block& block, const glm::ivec3& pos) { - std::string name = block.name + ".update"; - lua::emit_event(lua::get_main_state(), name, [pos](auto L) { + lua::emit_event(lua::get_main_state(), block.rt.eventNames.update, + [pos](auto L) { return lua::pushivec_stack(L, pos); }); } void scripting::random_update_block(const Block& block, const glm::ivec3& pos) { - std::string name = block.name + ".randupdate"; - lua::emit_event(lua::get_main_state(), name, [pos](auto L) { + lua::emit_event(lua::get_main_state(), block.rt.eventNames.randomUpdate, + [pos](auto L) { return lua::pushivec_stack(L, pos); }); } @@ -660,7 +660,8 @@ void scripting::load_content_script( const std::string& prefix, const io::path& file, const std::string& fileName, - BlockFuncsSet& funcsset + BlockFuncsSet& funcsset, + BlockFuncNamesCache& namesCache ) { int env = *senv; lua::pop(lua::get_main_state(), load_script(env, "block", file, fileName)); @@ -686,6 +687,9 @@ void scripting::load_content_script( register_event(env, "on_block_present", prefix + ".blockpresent"); funcsset.onblockremoved = register_event(env, "on_block_removed", prefix + ".blockremoved"); + + namesCache.randomUpdate = prefix + ".update"; + namesCache.randomUpdate = prefix + ".randupdate"; } void scripting::load_content_script( @@ -693,7 +697,8 @@ void scripting::load_content_script( const std::string& prefix, const io::path& file, const std::string& fileName, - ItemFuncsSet& funcsset + ItemFuncsSet& funcsset, + ItemFuncNamesCache& namesCache ) { int env = *senv; lua::pop(lua::get_main_state(), load_script(env, "item", file, fileName)); diff --git a/src/logic/scripting/scripting.hpp b/src/logic/scripting/scripting.hpp index 298130c99..64fa1a3d1 100644 --- a/src/logic/scripting/scripting.hpp +++ b/src/logic/scripting/scripting.hpp @@ -23,7 +23,9 @@ struct ItemDef; class Inventory; class UiDocument; struct BlockFuncsSet; +struct BlockFuncNamesCache; struct ItemFuncsSet; +struct ItemFuncNamesCache; struct WorldFuncsSet; struct UserComponent; struct uidocscript; @@ -168,7 +170,8 @@ namespace scripting { const std::string& prefix, const io::path& file, const std::string& fileName, - BlockFuncsSet& funcsset + BlockFuncsSet& funcsset, + BlockFuncNamesCache& namesCache ); /// @brief Load script associated with an Item @@ -182,7 +185,8 @@ namespace scripting { const std::string& prefix, const io::path& file, const std::string& fileName, - ItemFuncsSet& funcsset + ItemFuncsSet& funcsset, + ItemFuncNamesCache& namesCache ); /// @brief Load component script diff --git a/src/voxels/Block.hpp b/src/voxels/Block.hpp index 96620c8f9..99b9dee70 100644 --- a/src/voxels/Block.hpp +++ b/src/voxels/Block.hpp @@ -54,6 +54,11 @@ struct BlockFuncsSet { bool onblockremoved : 1; }; +struct BlockFuncNamesCache { + std::string update; + std::string randomUpdate; +}; + struct CoordSystem { std::array axes; /// @brief Grid 3d position fix offset (for negative vectors) @@ -296,6 +301,8 @@ public: blockid_t surfaceReplacement = 0; std::set tags; + + BlockFuncNamesCache eventNames; } rt {}; Block(const std::string& name); From 9c4c82376a5906775966bc36e35ece98f0389c32 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Thu, 29 Jan 2026 21:21:13 +0300 Subject: [PATCH 7/7] cleanup a bit --- src/lighting/Lighting.cpp | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/src/lighting/Lighting.cpp b/src/lighting/Lighting.cpp index 8f90540bb..b17b6f333 100644 --- a/src/lighting/Lighting.cpp +++ b/src/lighting/Lighting.cpp @@ -192,16 +192,28 @@ void Lighting::onBlockSet(int x, int y, int z, blockid_t id){ solverS->add(x,i,z, 0xF); } } - solverR->add(x,y+1,z); solverG->add(x,y+1,z); solverB->add(x,y+1,z); solverS->add(x,y+1,z); - solverR->add(x,y-1,z); solverG->add(x,y-1,z); solverB->add(x,y-1,z); solverS->add(x,y-1,z); - solverR->add(x+1,y,z); solverG->add(x+1,y,z); solverB->add(x+1,y,z); solverS->add(x+1,y,z); - solverR->add(x-1,y,z); solverG->add(x-1,y,z); solverB->add(x-1,y,z); solverS->add(x-1,y,z); - solverR->add(x,y,z+1); solverG->add(x,y,z+1); solverB->add(x,y,z+1); solverS->add(x,y,z+1); - solverR->add(x,y,z-1); solverG->add(x,y,z-1); solverB->add(x,y,z-1); solverS->add(x,y,z-1); - solverR->solve(chunk); - solverG->solve(chunk); - solverB->solve(chunk); - solverS->solve(chunk); + const int coords[] = { + 0, 0, 1, + 0, 0,-1, + 0, 1, 0, + 0,-1, 0, + 1, 0, 0, + -1, 0, 0 + }; + for (int i = 0; i < 6; i++) { + int lx = x + coords[i * 3]; + int ly = y + coords[i * 3 + 1]; + int lz = z + coords[i * 3 + 2]; + + solverR->add(lx, ly, lz); + solverG->add(lx, ly, lz); + solverB->add(lx, ly, lz); + solverS->add(lx, ly, lz); + solverR->solve(chunk); + solverG->solve(chunk); + solverB->solve(chunk); + solverS->solve(chunk); + } } else { auto chunk = chunks.getChunkByVoxel(glm::ivec3{x, y, z}); if (!block.skyLightPassing){