diff --git a/res/scripts/internal_events.lua b/res/scripts/internal_events.lua index 06666d04..4f72e1b1 100644 --- a/res/scripts/internal_events.lua +++ b/res/scripts/internal_events.lua @@ -1,6 +1,8 @@ local updating_blocks = {} -local TYPE_REGISTER = 0 -local TYPE_UNREGISTER = 1 +local present_queues = {} +local TYPE_REGISTER = 1 +local TYPE_UPDATING = 2 +local TYPE_PRESENT = 4 block.__perform_ticks = function(delta) for id, entry in pairs(updating_blocks) do @@ -21,10 +23,45 @@ block.__perform_ticks = function(delta) end ::continue:: end + for id, queue in pairs(present_queues) do + queue.timer = queue.timer + delta + local steps = math.floor(queue.timer / queue.delta * #queue / 4) + if steps == 0 then + goto continue + end + queue.timer = 0.0 + local event = queue.event + local update_list = updating_blocks[id] + for i=1, steps do + local index = #queue - 3 + if index <= 0 then + break + end + local is_register = queue[index] + local x = queue[index + 1] + local y = queue[index + 2] + local z = queue[index + 3] + + for j=1,4 do + table.remove(queue, index) + end + events.emit(event, x, y, z) + + if queue.updating then + table.insert(update_list, x) + table.insert(update_list, y) + table.insert(update_list, z) + end + end + ::continue:: + end end +local block_pull_register_events = block.__pull_register_events +block.__pull_register_events = nil + block.__process_register_events = function() - local register_events = block.__pull_register_events() + local register_events = block_pull_register_events() if not register_events then return end @@ -36,31 +73,59 @@ block.__process_register_events = function() local y = register_events[i + 2] local z = register_events[i + 3] + local is_register = bit.band(event_bits, TYPE_REGISTER) ~= 0 + local is_updating = bit.band(event_bits, TYPE_UPDATING) ~= 0 + local is_present = bit.band(event_bits, TYPE_PRESENT) ~= 0 local list = updating_blocks[id] - if bit.band(event_bits, TYPE_REGISTER) ~= 0 then - if not list then - list = {} - list.event = block.name(id) .. ".blocktick" - list.tps = 20 / (block.properties[id]["tick-interval"] or 1) - list.delta = 1.0 / list.tps - list.timer = 0.0 - list.pointer = 0 - updating_blocks[id] = list + + if not list and is_register and is_updating then + list = {} + list.event = block.name(id) .. ".blocktick" + list.tps = 20 / (block.properties[id]["tick-interval"] or 1) + list.delta = 1.0 / list.tps + list.timer = 0.0 + list.pointer = 0 + updating_blocks[id] = list + end + + if is_register and is_present then + local present_queue = present_queues[id] + if not present_queue then + present_queue = {} + present_queue.event = block.name(id) .. ".blockpresent" + present_queue.tps = 20 / (block.properties[id]["tick-interval"] or 1) + present_queue.delta = 1.0 / present_queue.tps + present_queue.timer = 0.0 + present_queue.pointer = 0 + present_queue.updating = is_updating + present_queues[id] = present_queue end + table.insert(present_queue, is_register) + table.insert(present_queue, x) + table.insert(present_queue, y) + table.insert(present_queue, z) + goto continue + end + if not is_updating then + goto continue + end + if is_register then table.insert(list, x) table.insert(list, y) table.insert(list, z) - elseif bit.band(event_bits, TYPE_UNREGISTER) ~= 0 then - if list then - for j=1, #list, 3 do - if list[j] == x and list[j + 1] == y and list[j + 2] == z then - for k=1,3 do - table.remove(list, j) - end - j = j - 3 + else + if not list then + goto continue + end + for j=1, #list, 3 do + if list[j] == x and list[j + 1] == y and list[j + 2] == z then + for k=1,3 do + table.remove(list, j) end + j = j - 3 end end end + ::continue:: end end diff --git a/src/logic/ChunksController.cpp b/src/logic/ChunksController.cpp index 97bbdf99..b521b0d8 100644 --- a/src/logic/ChunksController.cpp +++ b/src/logic/ChunksController.cpp @@ -15,6 +15,7 @@ #include "voxels/Chunks.hpp" #include "voxels/GlobalChunks.hpp" #include "world/Level.hpp" +#include "world/LevelEvents.hpp" #include "world/World.hpp" #include "world/generator/WorldGenerator.hpp" @@ -172,13 +173,12 @@ void ChunksController::createChunk(const Player& player, int x, int z) const { auto chunk = level.chunks->create(x, z); player.chunks->putChunk(chunk); auto& chunkFlags = chunk->flags; - if (!chunkFlags.loaded) { generator->generate(chunk->voxels, x, z); chunkFlags.unsaved = true; } chunk->updateHeights(); - + level.events->trigger(LevelEventType::CHUNK_PRESENT, chunk.get()); if (!chunkFlags.loadedLights) { Lighting::prebuildSkyLight(*chunk, *level.content.getIndices()); } diff --git a/src/logic/scripting/scripting.cpp b/src/logic/scripting/scripting.cpp index 07b35d1e..fb2e997b 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -675,6 +675,8 @@ void scripting::load_content_script( register_event(env, "on_block_tick", prefix + ".blocktick"); funcsset.onblockstick = register_event(env, "on_blocks_tick", prefix + ".blockstick"); + funcsset.onblockpresent = + register_event(env, "on_block_present", prefix + ".blockpresent"); } void scripting::load_content_script( diff --git a/src/voxels/Block.hpp b/src/voxels/Block.hpp index 59115e84..9d091893 100644 --- a/src/voxels/Block.hpp +++ b/src/voxels/Block.hpp @@ -50,6 +50,7 @@ struct BlockFuncsSet { bool randupdate : 1; bool onblocktick : 1; bool onblockstick : 1; + bool onblockpresent : 1; }; struct CoordSystem { diff --git a/src/voxels/GlobalChunks.cpp b/src/voxels/GlobalChunks.cpp index 7451a563..66da7792 100644 --- a/src/voxels/GlobalChunks.cpp +++ b/src/voxels/GlobalChunks.cpp @@ -127,8 +127,6 @@ std::shared_ptr GlobalChunks::create(int x, int z) { chunk->flags.loadedLights = true; } chunk->blocksMetadata = regions.getBlocksData(chunk->x, chunk->z); - - level.events->trigger(LevelEventType::CHUNK_PRESENT, chunk.get()); return chunk; } diff --git a/src/voxels/blocks_agent.cpp b/src/voxels/blocks_agent.cpp index e4e17e27..fa71aad9 100644 --- a/src/voxels/blocks_agent.cpp +++ b/src/voxels/blocks_agent.cpp @@ -14,12 +14,12 @@ std::vector blocks_agent::pull_register_events() { return events; } -static uint16_t get_events_bits(bool present, const Block& def) { - uint16_t bits = 0; - if (def.rt.funcsset.onblocktick) { - bits |= present ? BlockRegisterEvent::REGISTER_UPDATING_BIT - : BlockRegisterEvent::UNREGISTER_UPDATING_BIT; - } +static uint8_t get_events_bits(bool reg, const Block& def) { + uint8_t bits = 0; + auto funcsset = def.rt.funcsset; + bits |= BlockRegisterEvent::REGISTER_BIT * reg; + bits |= BlockRegisterEvent::UPDATING_BIT * funcsset.onblocktick; + bits |= BlockRegisterEvent::PRESENT_EVENT_BIT * funcsset.onblockpresent; return bits; } @@ -28,10 +28,16 @@ static void on_chunk_register_event( const Chunk& chunk, bool present ) { - for (int i = 0; i < CHUNK_VOL; i++) { - const auto& def = - indices.blocks.require(chunk.voxels[i].id); - uint16_t bits = get_events_bits(present, def); + const auto& voxels = chunk.voxels; + + int totalBegin = chunk.bottom * (CHUNK_W * CHUNK_D); + int totalEnd = chunk.top * (CHUNK_W * CHUNK_D); + + for (int i = totalBegin; i <= totalEnd; i++) { + blockid_t id = voxels[i].id; + const auto& def = + indices.blocks.require(id); + uint8_t bits = get_events_bits(present, def); if (bits == 0) { continue; } @@ -39,7 +45,7 @@ static void on_chunk_register_event( int z = (i / CHUNK_W) % CHUNK_D + chunk.z * CHUNK_D; int y = (i / CHUNK_W / CHUNK_D); block_register_events.push_back(BlockRegisterEvent { - bits, def.rt.id, {x, y, z} + bits, id, {x, y, z} }); } } @@ -109,7 +115,7 @@ static void finalize_block( } } - uint16_t bits = get_events_bits(false, def); + uint8_t bits = get_events_bits(false, def); if (bits == 0) { return; } @@ -141,7 +147,7 @@ static void initialize_block( refresh_chunk_heights(chunk, id == BLOCK_AIR, y); mark_neighboirs_modified(chunks, cx, cz, lx, lz); - uint16_t bits = get_events_bits(true, def); + uint8_t bits = get_events_bits(true, def); if (bits == 0) { return; } diff --git a/src/voxels/blocks_agent.hpp b/src/voxels/blocks_agent.hpp index b5ca82a6..93a3c1ad 100644 --- a/src/voxels/blocks_agent.hpp +++ b/src/voxels/blocks_agent.hpp @@ -25,10 +25,10 @@ struct AABB; namespace blocks_agent { struct BlockRegisterEvent { - static inline constexpr uint16_t REGISTER_UPDATING_BIT = 0x1; - static inline constexpr uint16_t UNREGISTER_UPDATING_BIT = 0x2; - static inline constexpr uint16_t PRESENT_EVENT_BIT = 0x4; - uint16_t bits; + static inline constexpr uint8_t REGISTER_BIT = 0x1; + static inline constexpr uint8_t UPDATING_BIT = 0x2; + static inline constexpr uint8_t PRESENT_EVENT_BIT = 0x4; + uint8_t bits; blockid_t id; glm::ivec3 coord; };