Browse Source

Add on_deactivate callback for luaentities (#10723)

pull/9110/merge
hecks 1 month ago
committed by GitHub
parent
commit
dd5a732fa9
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 106 additions and 27 deletions
  1. +1
    -0
      builtin/profiler/instrumentation.lua
  2. +2
    -0
      doc/lua_api.txt
  3. +3
    -0
      games/devtest/mods/testentities/callbacks.lua
  4. +26
    -0
      src/script/cpp_api/s_entity.cpp
  5. +1
    -0
      src/script/cpp_api/s_entity.h
  6. +1
    -1
      src/script/lua_api/l_object.cpp
  7. +11
    -2
      src/server/luaentity_sao.cpp
  8. +5
    -0
      src/server/luaentity_sao.h
  9. +1
    -1
      src/server/player_sao.cpp
  10. +16
    -0
      src/server/serveractiveobject.cpp
  11. +31
    -19
      src/server/serveractiveobject.h
  12. +8
    -4
      src/serverenvironment.cpp

+ 1
- 0
builtin/profiler/instrumentation.lua View File

@@ -160,6 +160,7 @@ local function init()
-- Simple iteration would ignore lookup via __index.
local entity_instrumentation = {
"on_activate",
"on_deactivate",
"on_step",
"on_punch",
"on_rightclick",


+ 2
- 0
doc/lua_api.txt View File

@@ -4207,6 +4207,8 @@ Callbacks:
* Called when the object is instantiated.
* `dtime_s` is the time passed since the object was unloaded, which can be
used for updating the entity state.
* `on_deactivate(self)
* Called when the object is about to get removed or unloaded.
* `on_step(self, dtime)`
* Called on every server tick, after movement and collision processing.
`dtime` is usually 0.1 seconds, as per the `dedicated_server_step` setting


+ 3
- 0
games/devtest/mods/testentities/callbacks.lua View File

@@ -31,6 +31,9 @@ minetest.register_entity("testentities:callback", {
on_activate = function(self, staticdata, dtime_s)
message("Callback entity: on_activate! pos="..spos(self).."; dtime_s="..dtime_s)
end,
on_deactivate = function(self)
message("Callback entity: on_deactivate! pos="..spos(self))
end,
on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir, damage)
local name = get_object_name(puncher)
message(


+ 26
- 0
src/script/cpp_api/s_entity.cpp View File

@@ -103,6 +103,32 @@ void ScriptApiEntity::luaentity_Activate(u16 id,
lua_pop(L, 2); // Pop object and error handler
}

void ScriptApiEntity::luaentity_Deactivate(u16 id)
{
SCRIPTAPI_PRECHECKHEADER

verbosestream << "scriptapi_luaentity_deactivate: id=" << id << std::endl;

int error_handler = PUSH_ERROR_HANDLER(L);

// Get the entity
luaentity_get(L, id);
int object = lua_gettop(L);

// Get on_deactivate
lua_getfield(L, -1, "on_deactivate");
if (!lua_isnil(L, -1)) {
luaL_checktype(L, -1, LUA_TFUNCTION);
lua_pushvalue(L, object);

setOriginFromTable(object);
PCALL_RES(lua_pcall(L, 1, 0, error_handler));
} else {
lua_pop(L, 1);
}
lua_pop(L, 2); // Pop object and error handler
}

void ScriptApiEntity::luaentity_Remove(u16 id)
{
SCRIPTAPI_PRECHECKHEADER


+ 1
- 0
src/script/cpp_api/s_entity.h View File

@@ -33,6 +33,7 @@ public:
bool luaentity_Add(u16 id, const char *name);
void luaentity_Activate(u16 id,
const std::string &staticdata, u32 dtime_s);
void luaentity_Deactivate(u16 id);
void luaentity_Remove(u16 id);
std::string luaentity_GetStaticdata(u16 id);
void luaentity_GetProperties(u16 id,


+ 1
- 1
src/script/lua_api/l_object.cpp View File

@@ -110,7 +110,7 @@ int ObjectRef::l_remove(lua_State *L)
sao->clearParentAttachment();

verbosestream << "ObjectRef::l_remove(): id=" << sao->getId() << std::endl;
sao->m_pending_removal = true;
sao->markForRemoval();
return 0;
}



+ 11
- 2
src/server/luaentity_sao.cpp View File

@@ -112,6 +112,15 @@ void LuaEntitySAO::addedToEnvironment(u32 dtime_s)
}
}

void LuaEntitySAO::dispatchScriptDeactivate()
{
// Ensure that this is in fact a registered entity,
// and that it isn't already gone.
// The latter also prevents this from ever being called twice.
if (m_registered && !isGone())
m_env->getScriptIface()->luaentity_Deactivate(m_id);
}

void LuaEntitySAO::step(float dtime, bool send_recommended)
{
if(!m_properties_sent)
@@ -302,7 +311,7 @@ u16 LuaEntitySAO::punch(v3f dir,
{
if (!m_registered) {
// Delete unknown LuaEntities when punched
m_pending_removal = true;
markForRemoval();
return 0;
}

@@ -335,7 +344,7 @@ u16 LuaEntitySAO::punch(v3f dir,
clearParentAttachment();
clearChildAttachments();
m_env->getScriptIface()->luaentity_on_death(m_id, puncher);
m_pending_removal = true;
markForRemoval();
}

actionstream << puncher->getDescription() << " (id=" << puncher->getId() <<


+ 5
- 0
src/server/luaentity_sao.h View File

@@ -71,6 +71,11 @@ public:
bool getSelectionBox(aabb3f *toset) const;
bool collideWithObjects() const;

protected:
void dispatchScriptDeactivate();
virtual void onMarkedForDeactivation() { dispatchScriptDeactivate(); }
virtual void onMarkedForRemoval() { dispatchScriptDeactivate(); }

private:
std::string getPropertyPacket();
void sendPosition(bool do_interpolate, bool is_movement_end);


+ 1
- 1
src/server/player_sao.cpp View File

@@ -531,7 +531,7 @@ bool PlayerSAO::setWieldedItem(const ItemStack &item)
void PlayerSAO::disconnected()
{
m_peer_id = PEER_ID_INEXISTENT;
m_pending_removal = true;
markForRemoval();
}

void PlayerSAO::unlinkPlayerSessionAndSave()


+ 16
- 0
src/server/serveractiveobject.cpp View File

@@ -73,3 +73,19 @@ void ServerActiveObject::dumpAOMessagesToQueue(std::queue<ActiveObjectMessage> &
m_messages_out.pop();
}
}

void ServerActiveObject::markForRemoval()
{
if (!m_pending_removal) {
onMarkedForRemoval();
m_pending_removal = true;
}
}

void ServerActiveObject::markForDeactivation()
{
if (!m_pending_deactivation) {
onMarkedForDeactivation();
m_pending_deactivation = true;
}
}

+ 31
- 19
src/server/serveractiveobject.h View File

@@ -70,6 +70,10 @@ public:
virtual bool environmentDeletes() const
{ return true; }

// Safely mark the object for removal or deactivation
void markForRemoval();
void markForDeactivation();

// Create a certain type of ServerActiveObject
static ServerActiveObject* create(ActiveObjectType type,
ServerEnvironment *env, u16 id, v3f pos,
@@ -213,25 +217,6 @@ public:
*/
u16 m_known_by_count = 0;

/*
- Whether this object is to be removed when nobody knows about
it anymore.
- Removal is delayed to preserve the id for the time during which
it could be confused to some other object by some client.
- This is usually set to true by the step() method when the object wants
to be deleted but can be set by anything else too.
*/
bool m_pending_removal = false;

/*
Same purpose as m_pending_removal but for deactivation.
deactvation = save static data in block, remove active object

If this is set alongside with m_pending_removal, removal takes
priority.
*/
bool m_pending_deactivation = false;

/*
A getter that unifies the above to answer the question:
"Can the environment still interact with this object?"
@@ -239,6 +224,9 @@ public:
inline bool isGone() const
{ return m_pending_removal || m_pending_deactivation; }

inline bool isPendingRemoval() const
{ return m_pending_removal; }

/*
Whether the object's static data has been stored to a block
*/
@@ -250,6 +238,9 @@ public:
v3s16 m_static_block = v3s16(1337,1337,1337);

protected:
virtual void onMarkedForDeactivation() {}
virtual void onMarkedForRemoval() {}

virtual void onAttach(int parent_id) {}
virtual void onDetach(int parent_id) {}

@@ -257,6 +248,27 @@ protected:
v3f m_base_position;
std::unordered_set<u32> m_attached_particle_spawners;

/*
Same purpose as m_pending_removal but for deactivation.
deactvation = save static data in block, remove active object

If this is set alongside with m_pending_removal, removal takes
priority.
Note: Do not assign this directly, use markForDeactivation() instead.
*/
bool m_pending_deactivation = false;

/*
- Whether this object is to be removed when nobody knows about
it anymore.
- Removal is delayed to preserve the id for the time during which
it could be confused to some other object by some client.
- This is usually set to true by the step() method when the object wants
to be deleted but can be set by anything else too.
Note: Do not assign this directly, use markForRemoval() instead.
*/
bool m_pending_removal = false;

/*
Queue of messages to be sent to the client
*/


+ 8
- 4
src/serverenvironment.cpp View File

@@ -1164,7 +1164,7 @@ void ServerEnvironment::clearObjects(ClearObjectsMode mode)

// If known by some client, don't delete immediately
if (obj->m_known_by_count > 0) {
obj->m_pending_removal = true;
obj->markForRemoval();
return false;
}

@@ -1792,7 +1792,7 @@ void ServerEnvironment::removeRemovedObjects()
/*
Delete static data from block if removed
*/
if (obj->m_pending_removal)
if (obj->isPendingRemoval())
deleteStaticFromBlock(obj, id, MOD_REASON_REMOVE_OBJECTS_REMOVE, false);

// If still known by clients, don't actually remove. On some future
@@ -1803,7 +1803,7 @@ void ServerEnvironment::removeRemovedObjects()
/*
Move static data from active to stored if deactivated
*/
if (!obj->m_pending_removal && obj->m_static_exists) {
if (!obj->isPendingRemoval() && obj->m_static_exists) {
MapBlock *block = m_map->emergeBlock(obj->m_static_block, false);
if (block) {
const auto i = block->m_static_objects.m_active.find(id);
@@ -1991,6 +1991,7 @@ void ServerEnvironment::deactivateFarObjects(bool _force_delete)
if (!force_delete && obj->m_static_exists &&
!m_active_blocks.contains(obj->m_static_block) &&
m_active_blocks.contains(blockpos_o)) {

// Delete from block where object was located
deleteStaticFromBlock(obj, id, MOD_REASON_STATIC_DATA_REMOVED, false);

@@ -2068,6 +2069,10 @@ void ServerEnvironment::deactivateFarObjects(bool _force_delete)
force_delete = true;
}

// Regardless of what happens to the object at this point, deactivate it first.
// This ensures that LuaEntity on_deactivate is always called.
obj->markForDeactivation();

/*
If known by some client, set pending deactivation.
Otherwise delete it immediately.
@@ -2077,7 +2082,6 @@ void ServerEnvironment::deactivateFarObjects(bool _force_delete)
<< "object id=" << id << " is known by clients"
<< "; not deleting yet" << std::endl;

obj->m_pending_deactivation = true;
return false;
}



Loading…
Cancel
Save