mirror of
https://github.com/minetest/minetest.git
synced 2025-02-17 10:23:47 +01:00
Optimize pushing collision data for entity on_step
Since this is fixed overhead for every entity, this is important to optimize. This optimizes one very common case. before: push_collision_move_result [us] _____________ 64512x 3.562 after: push_collision_move_result [us] _____________ 72636x 0.831
This commit is contained in:
@ -97,3 +97,25 @@ function core.encode_png(width, height, data, compression)
|
||||
|
||||
return o_encode_png(width, height, data, compression or 6)
|
||||
end
|
||||
|
||||
-- Helper that pushes a collisionMoveResult structure
|
||||
if core.set_push_moveresult1 then
|
||||
-- must match CollisionAxis in collision.h
|
||||
local AXES = {"x", "y", "z"}
|
||||
-- <=> script/common/c_content.cpp push_collision_move_result()
|
||||
core.set_push_moveresult1(function(b0, b1, b2, axis, npx, npy, npz, v0x, v0y, v0z, v1x, v1y, v1z)
|
||||
return {
|
||||
touching_ground = b0,
|
||||
collides = b1,
|
||||
standing_on_object = b2,
|
||||
collisions = {{
|
||||
type = "node",
|
||||
axis = AXES[axis],
|
||||
node_pos = vector.new(npx, npy, npz),
|
||||
old_velocity = vector.new(v0x, v0y, v0z),
|
||||
new_velocity = vector.new(v1x, v1y, v1z),
|
||||
}},
|
||||
}
|
||||
end)
|
||||
core.set_push_moveresult1 = nil
|
||||
end
|
||||
|
@ -2480,6 +2480,27 @@ static const char *collision_axis_str[] = {
|
||||
|
||||
void push_collision_move_result(lua_State *L, const collisionMoveResult &res)
|
||||
{
|
||||
// use faster Lua helper if possible
|
||||
if (res.collisions.size() == 1 && res.collisions.front().type == COLLISION_NODE) {
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_PUSH_MOVERESULT1);
|
||||
const auto &c = res.collisions.front();
|
||||
lua_pushboolean(L, res.touching_ground);
|
||||
lua_pushboolean(L, res.collides);
|
||||
lua_pushboolean(L, res.standing_on_object);
|
||||
assert(c.axis != COLLISION_AXIS_NONE);
|
||||
lua_pushinteger(L, static_cast<int>(c.axis));
|
||||
lua_pushinteger(L, c.node_p.X);
|
||||
lua_pushinteger(L, c.node_p.Y);
|
||||
lua_pushinteger(L, c.node_p.Z);
|
||||
for (v3f v : {c.old_speed / BS, c.new_speed / BS}) {
|
||||
lua_pushnumber(L, v.X);
|
||||
lua_pushnumber(L, v.Y);
|
||||
lua_pushnumber(L, v.Z);
|
||||
}
|
||||
lua_call(L, 3 + 1 + 3 + 3 * 2, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
lua_createtable(L, 0, 4);
|
||||
|
||||
setboolfield(L, -1, "touching_ground", res.touching_ground);
|
||||
|
@ -58,12 +58,13 @@ enum {
|
||||
CUSTOM_RIDX_HTTP_API_LUA,
|
||||
CUSTOM_RIDX_METATABLE_MAP,
|
||||
|
||||
// The following four functions are implemented in Lua because LuaJIT can
|
||||
// The following functions are implemented in Lua because LuaJIT can
|
||||
// trace them and optimize tables/string better than from the C API.
|
||||
CUSTOM_RIDX_READ_VECTOR,
|
||||
CUSTOM_RIDX_PUSH_VECTOR,
|
||||
CUSTOM_RIDX_READ_NODE,
|
||||
CUSTOM_RIDX_PUSH_NODE,
|
||||
CUSTOM_RIDX_PUSH_MOVERESULT1,
|
||||
};
|
||||
|
||||
|
||||
|
@ -141,6 +141,11 @@ ScriptApiBase::ScriptApiBase(ScriptingType type):
|
||||
return 0;
|
||||
});
|
||||
lua_setfield(m_luastack, -2, "set_push_node");
|
||||
lua_pushcfunction(m_luastack, [](lua_State *L) -> int {
|
||||
lua_rawseti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_PUSH_MOVERESULT1);
|
||||
return 0;
|
||||
});
|
||||
lua_setfield(m_luastack, -2, "set_push_moveresult1");
|
||||
// Finally, put the table into the global environment:
|
||||
lua_setglobal(m_luastack, "core");
|
||||
|
||||
@ -195,29 +200,30 @@ void ScriptApiBase::clientOpenLibs(lua_State *L)
|
||||
}
|
||||
#endif
|
||||
|
||||
#define CHECK(ridx, name) do { \
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, ridx); \
|
||||
FATAL_ERROR_IF(lua_type(L, -1) != LUA_TFUNCTION, "missing " name); \
|
||||
lua_pop(L, 1); \
|
||||
} while (0)
|
||||
|
||||
void ScriptApiBase::checkSetByBuiltin()
|
||||
{
|
||||
lua_State *L = getStack();
|
||||
|
||||
if (m_gamedef) {
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_READ_VECTOR);
|
||||
FATAL_ERROR_IF(lua_type(L, -1) != LUA_TFUNCTION, "missing read_vector");
|
||||
lua_pop(L, 1);
|
||||
CHECK(CUSTOM_RIDX_READ_VECTOR, "read_vector");
|
||||
CHECK(CUSTOM_RIDX_PUSH_VECTOR, "push_vector");
|
||||
CHECK(CUSTOM_RIDX_READ_NODE, "read_node");
|
||||
CHECK(CUSTOM_RIDX_PUSH_NODE, "push_node");
|
||||
}
|
||||
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_PUSH_VECTOR);
|
||||
FATAL_ERROR_IF(lua_type(L, -1) != LUA_TFUNCTION, "missing push_vector");
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_READ_NODE);
|
||||
FATAL_ERROR_IF(lua_type(L, -1) != LUA_TFUNCTION, "missing read_node");
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_PUSH_NODE);
|
||||
FATAL_ERROR_IF(lua_type(L, -1) != LUA_TFUNCTION, "missing push_node");
|
||||
lua_pop(L, 1);
|
||||
if (getType() == ScriptingType::Server) {
|
||||
CHECK(CUSTOM_RIDX_PUSH_MOVERESULT1, "push_moveresult1");
|
||||
}
|
||||
}
|
||||
|
||||
#undef CHECK
|
||||
|
||||
std::string ScriptApiBase::getCurrentModNameInsecure(lua_State *L)
|
||||
{
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
|
||||
|
Reference in New Issue
Block a user