add 'on_block_present' event

This commit is contained in:
MihailRis 2025-11-17 23:50:52 +03:00
parent 1c81f8b7ad
commit ca3bc45d0f
7 changed files with 113 additions and 41 deletions

View File

@ -1,6 +1,8 @@
local updating_blocks = {} local updating_blocks = {}
local TYPE_REGISTER = 0 local present_queues = {}
local TYPE_UNREGISTER = 1 local TYPE_REGISTER = 1
local TYPE_UPDATING = 2
local TYPE_PRESENT = 4
block.__perform_ticks = function(delta) block.__perform_ticks = function(delta)
for id, entry in pairs(updating_blocks) do for id, entry in pairs(updating_blocks) do
@ -21,10 +23,45 @@ block.__perform_ticks = function(delta)
end end
::continue:: ::continue::
end 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 end
local block_pull_register_events = block.__pull_register_events
block.__pull_register_events = nil
block.__process_register_events = function() block.__process_register_events = function()
local register_events = block.__pull_register_events() local register_events = block_pull_register_events()
if not register_events then if not register_events then
return return
end end
@ -36,31 +73,59 @@ block.__process_register_events = function()
local y = register_events[i + 2] local y = register_events[i + 2]
local z = register_events[i + 3] 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] local list = updating_blocks[id]
if bit.band(event_bits, TYPE_REGISTER) ~= 0 then
if not list then if not list and is_register and is_updating then
list = {} list = {}
list.event = block.name(id) .. ".blocktick" list.event = block.name(id) .. ".blocktick"
list.tps = 20 / (block.properties[id]["tick-interval"] or 1) list.tps = 20 / (block.properties[id]["tick-interval"] or 1)
list.delta = 1.0 / list.tps list.delta = 1.0 / list.tps
list.timer = 0.0 list.timer = 0.0
list.pointer = 0 list.pointer = 0
updating_blocks[id] = list 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 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, x)
table.insert(list, y) table.insert(list, y)
table.insert(list, z) table.insert(list, z)
elseif bit.band(event_bits, TYPE_UNREGISTER) ~= 0 then else
if list then if not list then
for j=1, #list, 3 do goto continue
if list[j] == x and list[j + 1] == y and list[j + 2] == z then end
for k=1,3 do for j=1, #list, 3 do
table.remove(list, j) if list[j] == x and list[j + 1] == y and list[j + 2] == z then
end for k=1,3 do
j = j - 3 table.remove(list, j)
end end
j = j - 3
end end
end end
end end
::continue::
end end
end end

View File

@ -15,6 +15,7 @@
#include "voxels/Chunks.hpp" #include "voxels/Chunks.hpp"
#include "voxels/GlobalChunks.hpp" #include "voxels/GlobalChunks.hpp"
#include "world/Level.hpp" #include "world/Level.hpp"
#include "world/LevelEvents.hpp"
#include "world/World.hpp" #include "world/World.hpp"
#include "world/generator/WorldGenerator.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); auto chunk = level.chunks->create(x, z);
player.chunks->putChunk(chunk); player.chunks->putChunk(chunk);
auto& chunkFlags = chunk->flags; auto& chunkFlags = chunk->flags;
if (!chunkFlags.loaded) { if (!chunkFlags.loaded) {
generator->generate(chunk->voxels, x, z); generator->generate(chunk->voxels, x, z);
chunkFlags.unsaved = true; chunkFlags.unsaved = true;
} }
chunk->updateHeights(); chunk->updateHeights();
level.events->trigger(LevelEventType::CHUNK_PRESENT, chunk.get());
if (!chunkFlags.loadedLights) { if (!chunkFlags.loadedLights) {
Lighting::prebuildSkyLight(*chunk, *level.content.getIndices()); Lighting::prebuildSkyLight(*chunk, *level.content.getIndices());
} }

View File

@ -675,6 +675,8 @@ void scripting::load_content_script(
register_event(env, "on_block_tick", prefix + ".blocktick"); register_event(env, "on_block_tick", prefix + ".blocktick");
funcsset.onblockstick = funcsset.onblockstick =
register_event(env, "on_blocks_tick", prefix + ".blockstick"); register_event(env, "on_blocks_tick", prefix + ".blockstick");
funcsset.onblockpresent =
register_event(env, "on_block_present", prefix + ".blockpresent");
} }
void scripting::load_content_script( void scripting::load_content_script(

View File

@ -50,6 +50,7 @@ struct BlockFuncsSet {
bool randupdate : 1; bool randupdate : 1;
bool onblocktick : 1; bool onblocktick : 1;
bool onblockstick : 1; bool onblockstick : 1;
bool onblockpresent : 1;
}; };
struct CoordSystem { struct CoordSystem {

View File

@ -127,8 +127,6 @@ std::shared_ptr<Chunk> GlobalChunks::create(int x, int z) {
chunk->flags.loadedLights = true; chunk->flags.loadedLights = true;
} }
chunk->blocksMetadata = regions.getBlocksData(chunk->x, chunk->z); chunk->blocksMetadata = regions.getBlocksData(chunk->x, chunk->z);
level.events->trigger(LevelEventType::CHUNK_PRESENT, chunk.get());
return chunk; return chunk;
} }

View File

@ -14,12 +14,12 @@ std::vector<BlockRegisterEvent> blocks_agent::pull_register_events() {
return events; return events;
} }
static uint16_t get_events_bits(bool present, const Block& def) { static uint8_t get_events_bits(bool reg, const Block& def) {
uint16_t bits = 0; uint8_t bits = 0;
if (def.rt.funcsset.onblocktick) { auto funcsset = def.rt.funcsset;
bits |= present ? BlockRegisterEvent::REGISTER_UPDATING_BIT bits |= BlockRegisterEvent::REGISTER_BIT * reg;
: BlockRegisterEvent::UNREGISTER_UPDATING_BIT; bits |= BlockRegisterEvent::UPDATING_BIT * funcsset.onblocktick;
} bits |= BlockRegisterEvent::PRESENT_EVENT_BIT * funcsset.onblockpresent;
return bits; return bits;
} }
@ -28,10 +28,16 @@ static void on_chunk_register_event(
const Chunk& chunk, const Chunk& chunk,
bool present bool present
) { ) {
for (int i = 0; i < CHUNK_VOL; i++) { const auto& voxels = chunk.voxels;
const auto& def =
indices.blocks.require(chunk.voxels[i].id); int totalBegin = chunk.bottom * (CHUNK_W * CHUNK_D);
uint16_t bits = get_events_bits(present, def); 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) { if (bits == 0) {
continue; continue;
} }
@ -39,7 +45,7 @@ static void on_chunk_register_event(
int z = (i / CHUNK_W) % CHUNK_D + chunk.z * CHUNK_D; int z = (i / CHUNK_W) % CHUNK_D + chunk.z * CHUNK_D;
int y = (i / CHUNK_W / CHUNK_D); int y = (i / CHUNK_W / CHUNK_D);
block_register_events.push_back(BlockRegisterEvent { 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) { if (bits == 0) {
return; return;
} }
@ -141,7 +147,7 @@ static void initialize_block(
refresh_chunk_heights(chunk, id == BLOCK_AIR, y); refresh_chunk_heights(chunk, id == BLOCK_AIR, y);
mark_neighboirs_modified(chunks, cx, cz, lx, lz); 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) { if (bits == 0) {
return; return;
} }

View File

@ -25,10 +25,10 @@ struct AABB;
namespace blocks_agent { namespace blocks_agent {
struct BlockRegisterEvent { struct BlockRegisterEvent {
static inline constexpr uint16_t REGISTER_UPDATING_BIT = 0x1; static inline constexpr uint8_t REGISTER_BIT = 0x1;
static inline constexpr uint16_t UNREGISTER_UPDATING_BIT = 0x2; static inline constexpr uint8_t UPDATING_BIT = 0x2;
static inline constexpr uint16_t PRESENT_EVENT_BIT = 0x4; static inline constexpr uint8_t PRESENT_EVENT_BIT = 0x4;
uint16_t bits; uint8_t bits;
blockid_t id; blockid_t id;
glm::ivec3 coord; glm::ivec3 coord;
}; };