diff --git a/doc/en/scripting/ecs.md b/doc/en/scripting/ecs.md index 7b1f87a1a..878452928 100644 --- a/doc/en/scripting/ecs.md +++ b/doc/en/scripting/ecs.md @@ -180,6 +180,10 @@ rig:get_color() -> vec3 rig:set_color(color: vec3) ``` +> [!WARNING] +> When an entity moves outside the loaded area, it is removed, triggering the event. +> When it re-enters the loaded area, the entity is spawned again. + ## Component events ```lua diff --git a/doc/en/scripting/events.md b/doc/en/scripting/events.md index fea9de7df..75180edc3 100644 --- a/doc/en/scripting/events.md +++ b/doc/en/scripting/events.md @@ -152,6 +152,17 @@ function on_block_interact(blockid, x, y, z, playerid) -> bool Called on block RMB click interaction. Prevents block placing if **true** returned. +```lua +function on_entity_spawn(uid) +``` +Called after an entity is spawned. + +```lua +function on_entity_despawn(uid) +``` + +Called before an entity is despawned. + ### Chunk Events (world.lua) ```lua diff --git a/doc/ru/scripting/ecs.md b/doc/ru/scripting/ecs.md index 4f9d45f08..1a5f6ccf3 100644 --- a/doc/ru/scripting/ecs.md +++ b/doc/ru/scripting/ecs.md @@ -180,6 +180,10 @@ rig:get_color() -> vec3 rig:set_color(color: vec3) ``` +> [!WARNING] +> При выходе сущности за пределы зоны прогрузки она удаляется, вызывая события. +> При повторном попадании в зону прогрузки сущность спавнится заново. + ## События компонента ```lua diff --git a/doc/ru/scripting/events.md b/doc/ru/scripting/events.md index 7dbe7bc07..ff4bfb456 100644 --- a/doc/ru/scripting/events.md +++ b/doc/ru/scripting/events.md @@ -156,6 +156,18 @@ function on_block_interact(blockid, x, y, z, playerid) -> bool Вызывается при нажатии на блок ПКМ. Предотвращает установку блоков, если возвращает `true` +```lua +function on_entity_spawn(uid) +``` + +Вызывается после спавна сущности + +```lua +function on_entity_despawn(uid) +``` + +Вызывается перед удалением сущности + ```lua function on_player_tick(playerid: int, tps: int) ``` diff --git a/src/content/ContentPack.hpp b/src/content/ContentPack.hpp index a4548d038..06a8cf4dc 100644 --- a/src/content/ContentPack.hpp +++ b/src/content/ContentPack.hpp @@ -127,6 +127,8 @@ struct WorldFuncsSet { bool onchunkremove; bool oninventoryopen; bool oninventoryclosed; + bool onentityspawn; + bool onentitydespawn; }; class ContentPackRuntime { diff --git a/src/logic/scripting/scripting.cpp b/src/logic/scripting/scripting.cpp index bba9f6837..341470c17 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -781,6 +781,10 @@ void scripting::load_world_script( register_event(env, "on_inventory_open", prefix + ":.inventoryopen"); funcsset.oninventoryclosed = register_event(env, "on_inventory_closed", prefix + ":.inventoryclosed"); + funcsset.onentityspawn = + register_event(env, "on_entity_spawn", prefix + ":.entityspawn"); + funcsset.onentitydespawn = + register_event(env, "on_entity_despawn", prefix + ":.entitydespawn"); } void scripting::load_content_script( diff --git a/src/logic/scripting/scripting_entities.cpp b/src/logic/scripting/scripting_entities.cpp index c068d7007..32a396b25 100644 --- a/src/logic/scripting/scripting_entities.cpp +++ b/src/logic/scripting/scripting_entities.cpp @@ -6,6 +6,8 @@ #include "objects/Entity.hpp" #include "objects/Player.hpp" #include "util/stringutil.hpp" +#include "content/Content.hpp" +#include "content/ContentPack.hpp" using namespace scripting; @@ -129,6 +131,15 @@ void scripting::on_entity_spawn( for (auto& component : components) { create_component(L, -1, *component, args, saved); } + + for (auto& [packid, pack] : content->getPacks()) { + if (pack->worldfuncsset.onentityspawn) { + lua::emit_event(L, packid + ":.entityspawn", [&](lua::State* L) { + lua::pushinteger(L, eid); + return 1; + }); + } + } } static void process_entity_callback( @@ -170,9 +181,21 @@ void scripting::on_entity_despawn(const Entity& entity) { process_entity_callback( entity, "on_despawn", &EntityFuncsSet::on_despawn, nullptr ); + auto L = lua::get_main_state(); + entityid_t uid = entity.getUID(); + + for (auto& [packid, pack] : content->getPacks()) { + if (pack->worldfuncsset.onentitydespawn) { + lua::emit_event(L, packid + ":.entitydespawn", [&](lua::State* L) { + lua::pushinteger(L, uid); + return 1; + }); + } + } + lua::get_from(L, "stdcomp", "remove_Entity", true); - lua::pushinteger(L, entity.getUID()); + lua::pushinteger(L, uid); lua::call(L, 1, 0); }