add 'on_block_removed' event

This commit is contained in:
MihailRis 2025-11-18 22:11:44 +03:00
parent b3e5f2a1c0
commit f721731ecc
12 changed files with 61 additions and 16 deletions

View File

@ -1,8 +1,9 @@
local updating_blocks = {}
local present_queues = {}
local TYPE_REGISTER = 1
local TYPE_UPDATING = 2
local TYPE_PRESENT = 4
local REGISTER_BIT = 0x1
local UPDATING_BIT = 0x2
local PRESENT_BIT = 0x4
local REMOVED_BIT = 0x8
block.__perform_ticks = function(delta)
for id, entry in pairs(updating_blocks) do
@ -25,7 +26,7 @@ block.__perform_ticks = function(delta)
end
for id, queue in pairs(present_queues) do
queue.timer = queue.timer + delta
local steps = math.floor(queue.timer / queue.delta * #queue / 4)
local steps = math.floor(queue.timer / queue.delta * #queue / 3)
if steps == 0 then
goto continue
end
@ -33,16 +34,15 @@ block.__perform_ticks = function(delta)
local event = queue.event
local update_list = updating_blocks[id]
for i=1, steps do
local index = #queue - 3
local index = #queue - 2
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]
local x = queue[index]
local y = queue[index + 1]
local z = queue[index + 2]
for j=1,4 do
for j=1,3 do
table.remove(queue, index)
end
events.emit(event, x, y, z)
@ -65,6 +65,10 @@ block.__process_register_events = function()
if not register_events then
return
end
local emit_event = events.emit
local removed_events = {}
for i=1, #register_events, 4 do
local header = register_events[i]
local event_bits = bit.band(header, 0xFFFF)
@ -73,11 +77,21 @@ 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 is_register = bit.band(event_bits, REGISTER_BIT) ~= 0
local is_updating = bit.band(event_bits, UPDATING_BIT) ~= 0
local is_present = bit.band(event_bits, PRESENT_BIT) ~= 0
local is_removed = bit.band(event_bits, REMOVED_BIT) ~= 0
local list = updating_blocks[id]
if not is_register and is_removed then
local rm_event = removed_events[id]
if not rm_event then
rm_event = block.name(id) .. ".blockremoved"
removed_events[id] = rm_event
end
emit_event(rm_event, x, y, z)
end
if not list and is_register and is_updating then
list = {}
list.event = block.name(id) .. ".blocktick"
@ -100,7 +114,6 @@ block.__process_register_events = function()
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)

View File

@ -357,6 +357,10 @@ function __vc_on_world_tick(tps)
time.schedules.world:tick(1.0 / tps)
end
function __vc_process_before_quit()
block.__process_register_events()
end
function __vc_on_world_save()
local rule_values = {}
for name, rule in pairs(rules.rules) do

View File

@ -109,6 +109,7 @@ LevelScreen::~LevelScreen() {
scripting::on_frontend_close();
// unblock all bindings
input.getBindings().enableAll();
playerController->getPlayer()->chunks->saveAndClear();
controller->onWorldQuit();
engine.getPaths().setCurrentWorldFolder("");
}
@ -278,5 +279,6 @@ void LevelScreen::onEngineShutdown() {
if (hud->isInventoryOpen()) {
hud->closeInventory();
}
controller->processBeforeQuit();
controller->saveWorld();
}

View File

@ -366,7 +366,9 @@ void EngineController::reconfigPacks(
);
}
} else {
auto world = controller->getLevel()->getWorld();
auto level = controller->getLevel();
auto world = level->getWorld();
controller->processBeforeQuit();
controller->saveWorld();
auto names = PacksManager::getNames(world->getPacks());

View File

@ -27,7 +27,8 @@ LevelController::LevelController(
: settings(engine->getSettings()),
level(std::move(levelPtr)),
chunks(std::make_unique<ChunksController>(*level)),
playerTickClock(20, 3) {
playerTickClock(20, 3),
localPlayer(clientPlayer) {
level->events->listen(LevelEventType::CHUNK_PRESENT, [](auto, Chunk* chunk) {
scripting::on_chunk_present(*chunk, chunk->flags.loaded);
@ -121,6 +122,13 @@ void LevelController::update(float delta, bool pause) {
level->entities->clean();
}
void LevelController::processBeforeQuit() {
if (localPlayer) {
localPlayer->chunks->saveAndClear();
}
scripting::process_before_quit();
}
void LevelController::saveWorld() {
auto world = level->getWorld();
if (world->isNameless()) {

View File

@ -20,6 +20,7 @@ class LevelController {
std::unique_ptr<ChunksController> chunks;
util::Clock playerTickClock;
Player* localPlayer;
public:
LevelController(Engine* engine, std::unique_ptr<Level> level, Player* clientPlayer);
@ -27,6 +28,7 @@ public:
/// @param pause is world and player simulation paused
void update(float delta, bool pause);
void processBeforeQuit();
void saveWorld();
void onWorldQuit();

View File

@ -119,6 +119,7 @@ static int l_close_world(lua::State* L) {
if (controller == nullptr) {
throw std::runtime_error("no world open");
}
controller->processBeforeQuit();
bool save_world = lua::toboolean(L, 1);
if (save_world) {
controller->saveWorld();

View File

@ -341,6 +341,13 @@ void scripting::on_world_save() {
}
}
void scripting::process_before_quit() {
auto L = lua::get_main_state();
if (lua::getglobal(L, "__vc_process_before_quit")) {
lua::call_nothrow(L, 0, 0);
}
}
void scripting::on_world_quit() {
auto L = lua::get_main_state();
for (auto& pack : content_control->getAllContentPacks()) {
@ -677,6 +684,8 @@ void scripting::load_content_script(
register_event(env, "on_blocks_tick", prefix + ".blockstick");
funcsset.onblockpresent =
register_event(env, "on_block_present", prefix + ".blockpresent");
funcsset.onblockremoved =
register_event(env, "on_block_removed", prefix + ".blockremoved");
}
void scripting::load_content_script(

View File

@ -81,6 +81,7 @@ namespace scripting {
void on_world_load(LevelController* controller);
void on_world_tick(int tps);
void on_world_save();
void process_before_quit();
void on_world_quit();
void cleanup(const std::vector<std::string>& nonReset);
void on_blocks_tick(const Block& block, int tps);

View File

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

View File

@ -19,6 +19,7 @@ static uint8_t get_events_bits(const Block& def) {
auto funcsset = def.rt.funcsset;
bits |= BlockRegisterEvent::UPDATING_BIT * funcsset.onblocktick;
bits |= BlockRegisterEvent::PRESENT_EVENT_BIT * funcsset.onblockpresent;
bits |= BlockRegisterEvent::REMOVED_EVENT_BIT * funcsset.onblockremoved;
return bits;
}

View File

@ -28,6 +28,7 @@ struct BlockRegisterEvent {
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;
static inline constexpr uint8_t REMOVED_EVENT_BIT = 0x8;
uint8_t bits;
blockid_t id;
glm::ivec3 coord;