mirror of
				https://github.com/luanti-org/luanti.git
				synced 2025-11-04 09:15:29 +01:00 
			
		
		
		
	Expose collision information to LuaEntity on_step
This commit is contained in:
		@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
------------------------------------
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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");
 | 
			
		||||
	/**/
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user