formspec_version_element = true,
area_store_persistent_ids = true,
pathfinder_works = true,
+ object_step_has_moveresult = true,
}
function core.has_feature(arg)
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`
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),
-- 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
------------------------------------
#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"
}
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");
+ /**/
+}
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,
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);
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]
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
}
struct ObjectProperties;
struct ToolCapabilities;
+struct collisionMoveResult;
class ScriptApiEntity
: virtual public ScriptApiBase
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);
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())
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;
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;
}
}
- 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)