Expose collision information to LuaEntity on_step
authorsfan5 <sfan5@live.de>
Tue, 14 Apr 2020 12:11:33 +0000 (14:11 +0200)
committersfan5 <sfan5@live.de>
Mon, 27 Apr 2020 18:45:46 +0000 (20:45 +0200)
builtin/game/features.lua
doc/lua_api.txt
src/script/common/c_content.cpp
src/script/common/c_content.h
src/script/cpp_api/s_entity.cpp
src/script/cpp_api/s_entity.h
src/server/luaentity_sao.cpp

index 623f8183b6aa06f19ee07548466257e9188b8f06..a1547533348b9676548bee54f3441a60da312d40 100644 (file)
@@ -16,6 +16,7 @@ core.features = {
        formspec_version_element = true,
        area_store_persistent_ids = true,
        pathfinder_works = true,
+       object_step_has_moveresult = true,
 }
 
 function core.has_feature(arg)
index 3ca32649a553a16845e075ae52ed8e718cfc1390..5e4e18b62b74defbd681871cb3b169e5ea921692 100644 (file)
@@ -4147,6 +4147,8 @@ Utilities
           area_store_persistent_ids = true,
           -- Whether minetest.find_path is functional (5.2.0)
           pathfinder_works = true,
+          -- Whether Collision info is available to an objects' on_step (5.3.0)
+          object_step_has_moveresult = true,
       }
 
 * `minetest.has_feature(arg)`: returns `boolean, missing_features`
@@ -6579,7 +6581,10 @@ Used by `minetest.register_entity`.
 
         on_activate = function(self, staticdata, dtime_s),
 
-        on_step = function(self, dtime),
+        on_step = function(self, dtime, moveresult),
+        -- Called every server step
+        -- dtime: Elapsed time
+        -- moveresult: Table with collision info (only available if physical=true)
 
         on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir),
 
@@ -6594,6 +6599,24 @@ Used by `minetest.register_entity`.
         -- for more info) by using a '_' prefix
     }
 
+Collision info passed to `on_step`:
+
+    {
+        touching_ground = boolean,
+        collides = boolean,
+        standing_on_object = boolean,
+        collisions = {
+            {
+                type = string, -- "node" or "object",
+                axis = string, -- "x", "y" or "z"
+                node_pos = vector, -- if type is "node"
+                old_speed = vector,
+                new_speed = vector,
+            },
+            ...
+        }
+    }
+
 ABM (ActiveBlockModifier) definition
 ------------------------------------
 
index 8335fccb54f5fe212497bbd33ead0d99a10d2b84..6ff6427385b90be3395ae9b1bbf88c045e481108 100644 (file)
@@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "common/c_types.h"
 #include "nodedef.h"
 #include "object_properties.h"
+#include "collision.h"
 #include "cpp_api/s_node.h"
 #include "lua_api/l_object.h"
 #include "lua_api/l_item.h"
@@ -2002,3 +2003,56 @@ HudElementStat read_hud_change(lua_State *L, HudElement *elem, void **value)
        }
        return stat;
 }
+
+/******************************************************************************/
+
+// Indices must match values in `enum CollisionType` exactly!!
+static const char *collision_type_str[] = {
+       "node",
+       "object",
+};
+
+// Indices must match values in `enum CollisionAxis` exactly!!
+static const char *collision_axis_str[] = {
+       "x",
+       "y",
+       "z",
+};
+
+void push_collision_move_result(lua_State *L, const collisionMoveResult &res)
+{
+       lua_createtable(L, 0, 4);
+
+       setboolfield(L, -1, "touching_ground", res.touching_ground);
+       setboolfield(L, -1, "collides", res.collides);
+       setboolfield(L, -1, "standing_on_object", res.standing_on_object);
+
+       /* collisions */
+       lua_createtable(L, res.collisions.size(), 0);
+       int i = 1;
+       for (const auto &c : res.collisions) {
+               lua_createtable(L, 0, 5);
+
+               lua_pushstring(L, collision_type_str[c.type]);
+               lua_setfield(L, -2, "type");
+
+               assert(c.axis != COLLISION_AXIS_NONE);
+               lua_pushstring(L, collision_axis_str[c.axis]);
+               lua_setfield(L, -2, "axis");
+
+               if (c.type == COLLISION_NODE) {
+                       push_v3s16(L, c.node_p);
+                       lua_setfield(L, -2, "node_pos");
+               }
+
+               push_v3f(L, c.old_speed / BS);
+               lua_setfield(L, -2, "old_speed");
+
+               push_v3f(L, c.new_speed / BS);
+               lua_setfield(L, -2, "new_speed");
+
+               lua_rawseti(L, -2, i++);
+       }
+       lua_setfield(L, -2, "collisions");
+       /**/
+}
index 9e755682faeba29d2d5a43e9d36036be80868725..8f32e58eb76060095aad9c16611c582c744caf0a 100644 (file)
@@ -63,7 +63,9 @@ struct EnumString;
 struct NoiseParams;
 class Schematic;
 class ServerActiveObject;
+struct collisionMoveResult;
 
+extern struct EnumString es_TileAnimationType[];
 
 ContentFeatures    read_content_features     (lua_State *L, int index);
 void               push_content_features     (lua_State *L,
@@ -196,4 +198,4 @@ void               push_hud_element          (lua_State *L, HudElement *elem);
 
 HudElementStat     read_hud_change           (lua_State *L, HudElement *elem, void **value);
 
-extern struct EnumString es_TileAnimationType[];
+void               push_collision_move_result(lua_State *L, const collisionMoveResult &res);
index 26c7e8cd4eee3150c4e080644e3218a9c222c481..ea9320051e55cc075ddd25e4264c3ee354dc74e1 100644 (file)
@@ -178,12 +178,11 @@ void ScriptApiEntity::luaentity_GetProperties(u16 id,
        lua_pop(L, 1);
 }
 
-void ScriptApiEntity::luaentity_Step(u16 id, float dtime)
+void ScriptApiEntity::luaentity_Step(u16 id, float dtime,
+       const collisionMoveResult *moveresult)
 {
        SCRIPTAPI_PRECHECKHEADER
 
-       //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
-
        int error_handler = PUSH_ERROR_HANDLER(L);
 
        // Get core.luaentities[id]
@@ -199,9 +198,14 @@ void ScriptApiEntity::luaentity_Step(u16 id, float dtime)
        luaL_checktype(L, -1, LUA_TFUNCTION);
        lua_pushvalue(L, object); // self
        lua_pushnumber(L, dtime); // dtime
+       /* moveresult */
+       if (moveresult)
+               push_collision_move_result(L, *moveresult);
+       else
+               lua_pushnil(L);
 
        setOriginFromTable(object);
-       PCALL_RES(lua_pcall(L, 2, 0, error_handler));
+       PCALL_RES(lua_pcall(L, 3, 0, error_handler));
 
        lua_pop(L, 2); // Pop object and error handler
 }
index cc08c46e83e29d2b7155e1f77a21ca44d7029abf..b5f7a658633bc05e87ba456cac151a08bf233137 100644 (file)
@@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 struct ObjectProperties;
 struct ToolCapabilities;
+struct collisionMoveResult;
 
 class ScriptApiEntity
                : virtual public ScriptApiBase
@@ -36,7 +37,8 @@ public:
        std::string luaentity_GetStaticdata(u16 id);
        void luaentity_GetProperties(u16 id,
                        ServerActiveObject *self, ObjectProperties *prop);
-       void luaentity_Step(u16 id, float dtime);
+       void luaentity_Step(u16 id, float dtime,
+               const collisionMoveResult *moveresult);
        bool luaentity_Punch(u16 id,
                        ServerActiveObject *puncher, float time_from_last_punch,
                        const ToolCapabilities *toolcap, v3f dir, s16 damage);
index 1259392410c5418152e9d4038afa8cba63b1e6ea..51e1ca90ef33e8572a0c8c15c7bb6cbc5f726954 100644 (file)
@@ -135,6 +135,8 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
 
        m_last_sent_position_timer += dtime;
 
+       collisionMoveResult moveresult, *moveresult_p = nullptr;
+
        // Each frame, parent position is copied if the object is attached, otherwise it's calculated normally
        // If the object gets detached this comes into effect automatically from the last known origin
        if(isAttached())
@@ -150,7 +152,6 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
                        aabb3f box = m_prop.collisionbox;
                        box.MinEdge *= BS;
                        box.MaxEdge *= BS;
-                       collisionMoveResult moveresult;
                        f32 pos_max_d = BS*0.25; // Distance per iteration
                        v3f p_pos = m_base_position;
                        v3f p_velocity = m_velocity;
@@ -159,6 +160,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
                                        pos_max_d, box, m_prop.stepheight, dtime,
                                        &p_pos, &p_velocity, p_acceleration,
                                        this, m_prop.collideWithObjects);
+                       moveresult_p = &moveresult;
 
                        // Apply results
                        m_base_position = p_pos;
@@ -188,8 +190,8 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
                }
        }
 
-       if(m_registered){
-               m_env->getScriptIface()->luaentity_Step(m_id, dtime);
+       if(m_registered) {
+               m_env->getScriptIface()->luaentity_Step(m_id, dtime, moveresult_p);
        }
 
        if (!send_recommended)