// Return number of accepted items to be taken int ScriptApiDetached::detached_inventory_AllowTake( const std::string &name, const std::string &listname, int index, ItemStack &stack, ServerActiveObject *player) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); // Push callback function on stack if (!getDetachedInventoryCallback(name, "allow_take")) return stack.count; // All will be accepted // Call function(inv, listname, index, stack, player) InventoryLocation loc; loc.setDetached(name); InvRef::create(L, loc); // inv lua_pushstring(L, listname.c_str()); // listname lua_pushinteger(L, index + 1); // index LuaItemStack::create(L, stack); // stack objectrefGetOrCreate(L, player); // player PCALL_RES(lua_pcall(L, 5, 1, error_handler)); if (!lua_isnumber(L, -1)) throw LuaError("allow_take should return a number. name=" + name); int ret = luaL_checkinteger(L, -1); lua_pop(L, 2); // Pop integer and error handler return ret; }
// Return number of accepted items to be moved int ScriptApiDetached::detached_inventory_AllowMove( const std::string &name, const std::string &from_list, int from_index, const std::string &to_list, int to_index, int count, ServerActiveObject *player) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); // Push callback function on stack if (!getDetachedInventoryCallback(name, "allow_move")) return count; // function(inv, from_list, from_index, to_list, to_index, count, player) // inv InventoryLocation loc; loc.setDetached(name); InvRef::create(L, loc); lua_pushstring(L, from_list.c_str()); // from_list lua_pushinteger(L, from_index + 1); // from_index lua_pushstring(L, to_list.c_str()); // to_list lua_pushinteger(L, to_index + 1); // to_index lua_pushinteger(L, count); // count objectrefGetOrCreate(L, player); // player PCALL_RES(lua_pcall(L, 7, 1, error_handler)); if(!lua_isnumber(L, -1)) throw LuaError("allow_move should return a number. name=" + name); int ret = luaL_checkinteger(L, -1); lua_pop(L, 2); // Pop integer and error handler return ret; }
// Calls entity:on_rightclick(ObjectRef clicker) void ScriptApiEntity::luaentity_Rightclick(u16 id, ServerActiveObject *clicker) { SCRIPTAPI_PRECHECKHEADER //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl; // Get core.luaentities[id] luaentity_get(L, id); int object = lua_gettop(L); // State: object is at top of stack // Get function lua_getfield(L, -1, "on_rightclick"); if (lua_isnil(L, -1)) { lua_pop(L, 2); // Pop on_rightclick and entity return; } luaL_checktype(L, -1, LUA_TFUNCTION); lua_pushvalue(L, object); // self objectrefGetOrCreate(L, clicker); // Clicker reference // Call with 2 arguments, 0 results if (lua_pcall(L, 2, 0, m_errorhandler)) scriptError(); lua_pop(L, 1); // Pop object }
// Report taken items void ScriptApiDetached::detached_inventory_OnTake( const std::string &name, const std::string &listname, int index, ItemStack &stack, ServerActiveObject *player) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); // Push callback function on stack if (!getDetachedInventoryCallback(name, "on_take")) return; // Call function(inv, listname, index, stack, player) // inv InventoryLocation loc; loc.setDetached(name); InvRef::create(L, loc); lua_pushstring(L, listname.c_str()); // listname lua_pushinteger(L, index + 1); // index LuaItemStack::create(L, stack); // stack objectrefGetOrCreate(L, player); // player PCALL_RES(lua_pcall(L, 5, 0, error_handler)); lua_pop(L, 1); // Pop error handler }
// Report moved items void ScriptApiNodemeta::nodemeta_inventory_OnMove(v3s16 p, const std::string &from_list, int from_index, const std::string &to_list, int to_index, int count, ServerActiveObject *player) { SCRIPTAPI_PRECHECKHEADER lua_pushcfunction(L, script_error_handler); int errorhandler = lua_gettop(L); INodeDefManager *ndef = getServer()->ndef(); // If node doesn't exist, we don't know what callback to call MapNode node = getEnv()->getMap().getNodeNoEx(p); if(node.getContent() == CONTENT_IGNORE) return; // Push callback function on stack if(!getItemCallback(ndef->get(node).name.c_str(), "on_metadata_inventory_move")) return; // function(pos, from_list, from_index, to_list, to_index, count, player) push_v3s16(L, p); // pos lua_pushstring(L, from_list.c_str()); // from_list lua_pushinteger(L, from_index + 1); // from_index lua_pushstring(L, to_list.c_str()); // to_list lua_pushinteger(L, to_index + 1); // to_index lua_pushinteger(L, count); // count objectrefGetOrCreate(player); // player if(lua_pcall(L, 7, 0, errorhandler)) scriptError(); lua_pop(L, 1); // Pop error handler }
bool ScriptApiItem::item_OnUse(ItemStack &item, ServerActiveObject *user, const PointedThing &pointed) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); // Push callback function on stack if (!getItemCallback(item.name.c_str(), "on_use")) return false; // Call function LuaItemStack::create(L, item); objectrefGetOrCreate(L, user); pushPointedThing(pointed); PCALL_RES(lua_pcall(L, 3, 1, error_handler)); if(!lua_isnil(L, -1)) { try { item = read_item(L,-1, getServer()); } catch (LuaError &e) { throw LuaError(std::string(e.what()) + ". item=" + item.name); } } lua_pop(L, 2); // Pop item and error handler return true; }
void ScriptApiNode::node_on_receive_fields(v3s16 p, const std::string &formname, const std::map<std::string, std::string> &fields, ServerActiveObject *sender) { SCRIPTAPI_PRECHECKHEADER INodeDefManager *ndef = getServer()->ndef(); // If node doesn't exist, we don't know what callback to call MapNode node = getEnv()->getMap().getNodeNoEx(p); if (node.getContent() == CONTENT_IGNORE) return; // Push callback function on stack if (!getItemCallback(ndef->get(node).name.c_str(), "on_receive_fields")) return; // Call function push_v3s16(L, p); // pos lua_pushstring(L, formname.c_str()); // formname lua_newtable(L); // fields std::map<std::string, std::string>::const_iterator it; for (it = fields.begin(); it != fields.end(); it++){ const std::string &name = it->first; const std::string &value = it->second; lua_pushstring(L, name.c_str()); lua_pushlstring(L, value.c_str(), value.size()); lua_settable(L, -3); } objectrefGetOrCreate(sender); // player if (lua_pcall(L, 4, 0, m_errorhandler)) scriptError(); }
void ScriptApiPlayer::on_playerReceiveFields(ServerActiveObject *player, const std::string &formname, const std::map<std::string, std::string> &fields) { SCRIPTAPI_PRECHECKHEADER // Get minetest.registered_on_chat_messages lua_getglobal(L, "minetest"); lua_getfield(L, -1, "registered_on_player_receive_fields"); // Call callbacks // param 1 objectrefGetOrCreate(player); // param 2 lua_pushstring(L, formname.c_str()); // param 3 lua_newtable(L); for(std::map<std::string, std::string>::const_iterator i = fields.begin(); i != fields.end(); i++){ const std::string &name = i->first; const std::string &value = i->second; lua_pushstring(L, name.c_str()); lua_pushlstring(L, value.c_str(), value.size()); lua_settable(L, -3); } runCallbacks(3, RUN_CALLBACKS_MODE_OR_SC); }
bool ScriptApiEntity::luaentity_on_death(u16 id, ServerActiveObject *killer) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); // Get core.luaentities[id] luaentity_get(L, id); int object = lua_gettop(L); // State: object is at top of stack // Get function lua_getfield(L, -1, "on_death"); if (lua_isnil(L, -1)) { lua_pop(L, 2); // Pop on_death and entity return false; } luaL_checktype(L, -1, LUA_TFUNCTION); lua_pushvalue(L, object); // self objectrefGetOrCreate(L, killer); // killer reference setOriginFromTable(object); PCALL_RES(lua_pcall(L, 2, 1, error_handler)); bool retval = lua_toboolean(L, -1); lua_pop(L, 2); // Pop object and error handler return retval; }
// Return number of accepted items to be put int ScriptApiNodemeta::nodemeta_inventory_AllowPut(v3s16 p, const std::string &listname, int index, ItemStack &stack, ServerActiveObject *player) { SCRIPTAPI_PRECHECKHEADER INodeDefManager *ndef = getServer()->ndef(); // If node doesn't exist, we don't know what callback to call MapNode node = getEnv()->getMap().getNodeNoEx(p); if (node.getContent() == CONTENT_IGNORE) return 0; // Push callback function on stack std::string nodename = ndef->get(node).name; if (!getItemCallback(nodename.c_str(), "allow_metadata_inventory_put")) return stack.count; // Call function(pos, listname, index, stack, player) push_v3s16(L, p); // pos lua_pushstring(L, listname.c_str()); // listname lua_pushinteger(L, index + 1); // index LuaItemStack::create(L, stack); // stack objectrefGetOrCreate(L, player); // player if (lua_pcall(L, 5, 1, m_errorhandler)) scriptError(); if(!lua_isnumber(L, -1)) throw LuaError("allow_metadata_inventory_put should" " return a number, guilty node: " + nodename); int num = luaL_checkinteger(L, -1); lua_pop(L, 1); // Pop integer return num; }
bool ScriptApiItem::item_OnDrop(ItemStack &item, ServerActiveObject *dropper, v3f pos) { SCRIPTAPI_PRECHECKHEADER lua_pushcfunction(L, script_error_handler); int errorhandler = lua_gettop(L); // Push callback function on stack if(!getItemCallback(item.name.c_str(), "on_drop")) return false; // Call function LuaItemStack::create(L, item); objectrefGetOrCreate(dropper); pushFloatPos(L, pos); if(lua_pcall(L, 3, 1, errorhandler)) scriptError(); if(!lua_isnil(L, -1)) { try { item = read_item(L,-1, getServer()); } catch (LuaError &e) { throw LuaError(std::string(e.what()) + ". item=" + item.name); } } lua_pop(L, 2); // Pop item and error handler return true; }
// Calls entity:on_rightclick(ObjectRef clicker) void ScriptApiEntity::luaentity_Rightclick(u16 id, ServerActiveObject *clicker) { SCRIPTAPI_PRECHECKHEADER //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl; int error_handler = PUSH_ERROR_HANDLER(L); // Get core.luaentities[id] luaentity_get(L, id); int object = lua_gettop(L); // State: object is at top of stack // Get function lua_getfield(L, -1, "on_rightclick"); if (lua_isnil(L, -1)) { lua_pop(L, 2); // Pop on_rightclick and entity return; } luaL_checktype(L, -1, LUA_TFUNCTION); lua_pushvalue(L, object); // self objectrefGetOrCreate(L, clicker); // Clicker reference setOriginFromTable(object); PCALL_RES(lua_pcall(L, 2, 0, error_handler)); lua_pop(L, 2); // Pop object and error handler }
// Calls entity:on_punch(ObjectRef puncher, time_from_last_punch, // tool_capabilities, direction, damage) bool ScriptApiEntity::luaentity_Punch(u16 id, ServerActiveObject *puncher, float time_from_last_punch, const ToolCapabilities *toolcap, v3f dir, s16 damage) { SCRIPTAPI_PRECHECKHEADER //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl; int error_handler = PUSH_ERROR_HANDLER(L); // Get core.luaentities[id] luaentity_get(L,id); int object = lua_gettop(L); // State: object is at top of stack // Get function lua_getfield(L, -1, "on_punch"); if (lua_isnil(L, -1)) { lua_pop(L, 2); // Pop on_punch and entity return false; } luaL_checktype(L, -1, LUA_TFUNCTION); lua_pushvalue(L, object); // self objectrefGetOrCreate(L, puncher); // Clicker reference lua_pushnumber(L, time_from_last_punch); push_tool_capabilities(L, *toolcap); push_v3f(L, dir); lua_pushnumber(L, damage); setOriginFromTable(object); PCALL_RES(lua_pcall(L, 6, 1, error_handler)); bool retval = lua_toboolean(L, -1); lua_pop(L, 2); // Pop object and error handler return retval; }
// Report moved items void ScriptApiDetached::detached_inventory_OnMove( const std::string &name, const std::string &from_list, int from_index, const std::string &to_list, int to_index, int count, ServerActiveObject *player) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); // Push callback function on stack if (!getDetachedInventoryCallback(name, "on_move")) return; // function(inv, from_list, from_index, to_list, to_index, count, player) // inv InventoryLocation loc; loc.setDetached(name); InvRef::create(L, loc); lua_pushstring(L, from_list.c_str()); // from_list lua_pushinteger(L, from_index + 1); // from_index lua_pushstring(L, to_list.c_str()); // to_list lua_pushinteger(L, to_index + 1); // to_index lua_pushinteger(L, count); // count objectrefGetOrCreate(L, player); // player PCALL_RES(lua_pcall(L, 7, 0, error_handler)); lua_pop(L, 1); // Pop error handler }
// Report taken items void ScriptApiNodemeta::nodemeta_inventory_OnTake(v3s16 p, const std::string &listname, int index, ItemStack &stack, ServerActiveObject *player) { SCRIPTAPI_PRECHECKHEADER lua_pushcfunction(L, script_error_handler); int errorhandler = lua_gettop(L); INodeDefManager *ndef = getServer()->ndef(); // If node doesn't exist, we don't know what callback to call MapNode node = getEnv()->getMap().getNodeNoEx(p); if(node.getContent() == CONTENT_IGNORE) return; // Push callback function on stack if(!getItemCallback(ndef->get(node).name.c_str(), "on_metadata_inventory_take")) return; // Call function(pos, listname, index, stack, player) push_v3s16(L, p); // pos lua_pushstring(L, listname.c_str()); // listname lua_pushinteger(L, index + 1); // index LuaItemStack::create(L, stack); // stack objectrefGetOrCreate(player); // player if(lua_pcall(L, 5, 0, errorhandler)) scriptError(); lua_pop(L, 1); // Pop error handler }
bool ScriptApiItem::item_CraftPredict(ItemStack &item, ServerActiveObject *user, const InventoryList *old_craft_grid, const InventoryLocation &craft_inv) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); lua_getglobal(L, "core"); lua_getfield(L, -1, "craft_predict"); LuaItemStack::create(L, item); objectrefGetOrCreate(L, user); //Push inventory list std::vector<ItemStack> items; for (u32 i = 0; i < old_craft_grid->getSize(); i++) { items.push_back(old_craft_grid->getItem(i)); } push_items(L, items); InvRef::create(L, craft_inv); PCALL_RES(lua_pcall(L, 4, 1, error_handler)); if (!lua_isnil(L, -1)) { try { item = read_item(L,-1, getServer()); } catch (LuaError &e) { throw LuaError(std::string(e.what()) + ". item=" + item.name); } } lua_pop(L, 2); // Pop item and error handler return true; }
// Calls entity:on_punch(ObjectRef puncher, time_from_last_punch, // tool_capabilities, direction) void ScriptApiEntity::luaentity_Punch(u16 id, ServerActiveObject *puncher, float time_from_last_punch, const ToolCapabilities *toolcap, v3f dir) { SCRIPTAPI_PRECHECKHEADER //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl; // Get minetest.luaentities[id] luaentity_get(L,id); int object = lua_gettop(L); // State: object is at top of stack // Get function lua_getfield(L, -1, "on_punch"); if(lua_isnil(L, -1)) return; luaL_checktype(L, -1, LUA_TFUNCTION); lua_pushvalue(L, object); // self objectrefGetOrCreate(puncher); // Clicker reference lua_pushnumber(L, time_from_last_punch); push_tool_capabilities(L, *toolcap); push_v3f(L, dir); // Call with 5 arguments, 0 results if(lua_pcall(L, 5, 0, 0)) scriptError("error running function 'on_punch': %s\n", lua_tostring(L, -1)); }
void ScriptApiPlayer::on_playerReceiveFields(ServerActiveObject *player, const std::string &formname, const StringMap &fields) { SCRIPTAPI_PRECHECKHEADER // Get core.registered_on_chat_messages lua_getglobal(L, "core"); lua_getfield(L, -1, "registered_on_player_receive_fields"); // Call callbacks // param 1 objectrefGetOrCreate(L, player); // param 2 lua_pushstring(L, formname.c_str()); // param 3 lua_newtable(L); StringMap::const_iterator it; for (it = fields.begin(); it != fields.end(); ++it) { const std::string &name = it->first; const std::string &value = it->second; lua_pushstring(L, name.c_str()); lua_pushlstring(L, value.c_str(), value.size()); lua_settable(L, -3); } script_run_callbacks(L, 3, RUN_CALLBACKS_MODE_OR_SC); }
bool ScriptApiItem::item_OnCraft(ItemStack &item, ServerActiveObject *user, const InventoryList *old_craft_grid, const InventoryLocation &craft_inv) { SCRIPTAPI_PRECHECKHEADER lua_pushcfunction(L, script_error_handler); int errorhandler = lua_gettop(L); lua_getglobal(L, "minetest"); lua_getfield(L, -1, "on_craft"); LuaItemStack::create(L, item); objectrefGetOrCreate(user); //Push inventory list std::vector<ItemStack> items; for(u32 i=0; i<old_craft_grid->getSize(); i++) items.push_back(old_craft_grid->getItem(i)); push_items(L, items); InvRef::create(L, craft_inv); if(lua_pcall(L, 4, 1, errorhandler)) scriptError(); if(!lua_isnil(L, -1)) { try { item = read_item(L,-1, getServer()); } catch (LuaError &e) { throw LuaError(std::string(e.what()) + ". item=" + item.name); } } lua_pop(L, 2); // Pop item and error handler return true; }
void ScriptApiPlayer::on_dieplayer(ServerActiveObject *player) { SCRIPTAPI_PRECHECKHEADER // Get core.registered_on_dieplayers lua_getglobal(L, "core"); lua_getfield(L, -1, "registered_on_dieplayers"); // Call callbacks objectrefGetOrCreate(L, player); script_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST); }
void ScriptApiPlayer::on_leaveplayer(ServerActiveObject *player) { SCRIPTAPI_PRECHECKHEADER // Get minetest.registered_on_leaveplayers lua_getglobal(L, "minetest"); lua_getfield(L, -1, "registered_on_leaveplayers"); // Call callbacks objectrefGetOrCreate(player); runCallbacks(1, RUN_CALLBACKS_MODE_FIRST); }
bool ScriptApiPlayer::on_punchplayer(ServerActiveObject *player, ServerActiveObject *hitter, float time_from_last_punch, const ToolCapabilities *toolcap, v3f dir, s16 damage) { SCRIPTAPI_PRECHECKHEADER // Get core.registered_on_punchplayers lua_getglobal(L, "core"); lua_getfield(L, -1, "registered_on_punchplayers"); // Call callbacks objectrefGetOrCreate(L, player); objectrefGetOrCreate(L, hitter); lua_pushnumber(L, time_from_last_punch); push_tool_capabilities(L, *toolcap); push_v3f(L, dir); lua_pushnumber(L, damage); script_run_callbacks(L, 6, RUN_CALLBACKS_MODE_OR); return lua_toboolean(L, -1); }
void ScriptApiPlayer::on_leaveplayer(ServerActiveObject *player, bool timeout) { SCRIPTAPI_PRECHECKHEADER // Get core.registered_on_leaveplayers lua_getglobal(L, "core"); lua_getfield(L, -1, "registered_on_leaveplayers"); // Call callbacks objectrefGetOrCreate(L, player); lua_pushboolean(L, timeout); runCallbacks(2, RUN_CALLBACKS_MODE_FIRST); }
bool ScriptApiPlayer::on_respawnplayer(ServerActiveObject *player) { SCRIPTAPI_PRECHECKHEADER // Get core.registered_on_respawnplayers lua_getglobal(L, "core"); lua_getfield(L, -1, "registered_on_respawnplayers"); // Call callbacks objectrefGetOrCreate(L, player); script_run_callbacks(L, 1, RUN_CALLBACKS_MODE_OR); bool positioning_handled_by_some = lua_toboolean(L, -1); return positioning_handled_by_some; }
void ScriptApiPlayer::on_cheat(ServerActiveObject *player, const std::string &cheat_type) { SCRIPTAPI_PRECHECKHEADER // Get core.registered_on_cheats lua_getglobal(L, "core"); lua_getfield(L, -1, "registered_on_cheats"); // Call callbacks objectrefGetOrCreate(L, player); lua_newtable(L); lua_pushlstring(L, cheat_type.c_str(), cheat_type.size()); lua_setfield(L, -2, "type"); script_run_callbacks(L, 2, RUN_CALLBACKS_MODE_FIRST); }
void ScriptApiEnv::player_event(ServerActiveObject* player, std::string type) { SCRIPTAPI_PRECHECKHEADER // Get minetest.registered_playerevents lua_getglobal(L, "minetest"); lua_getfield(L, -1, "registered_playerevents"); // Call callbacks objectrefGetOrCreate(player); // player lua_pushstring(L,type.c_str()); // event type try { script_run_callbacks(L, 2, RUN_CALLBACKS_MODE_FIRST); } catch (LuaError &e) { getServer()->setAsyncFatalError(e.what()); } }
s16 ScriptApiPlayer::on_player_hpchange(ServerActiveObject *player, s16 hp_change) { SCRIPTAPI_PRECHECKHEADER // Get core.registered_on_player_hpchange lua_getglobal(L, "core"); lua_getfield(L, -1, "registered_on_player_hpchange"); lua_remove(L, -2); objectrefGetOrCreate(L, player); lua_pushnumber(L, hp_change); if (lua_pcall(L, 2, 1, m_errorhandler)) scriptError(); hp_change = lua_tointeger(L, -1); lua_pop(L, -1); return hp_change; }
bool ScriptApiNode::node_on_punch(v3s16 p, MapNode node, ServerActiveObject *puncher) { SCRIPTAPI_PRECHECKHEADER INodeDefManager *ndef = getServer()->ndef(); // Push callback function on stack if(!getItemCallback(ndef->get(node).name.c_str(), "on_punch")) return false; // Call function push_v3s16(L, p); pushnode(L, node, ndef); objectrefGetOrCreate(puncher); if(lua_pcall(L, 3, 0, 0)) scriptError("error: %s", lua_tostring(L, -1)); return true; }
s16 ScriptApiPlayer::on_player_hpchange(ServerActiveObject *player, s16 hp_change) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); // Get core.registered_on_player_hpchange lua_getglobal(L, "core"); lua_getfield(L, -1, "registered_on_player_hpchange"); lua_remove(L, -2); objectrefGetOrCreate(L, player); lua_pushnumber(L, hp_change); PCALL_RES(lua_pcall(L, 2, 1, error_handler)); hp_change = lua_tointeger(L, -1); lua_pop(L, 2); // Pop result and error handler return hp_change; }
bool ScriptApiNode::node_on_dig(v3s16 p, MapNode node, ServerActiveObject *digger) { SCRIPTAPI_PRECHECKHEADER int error_handler = PUSH_ERROR_HANDLER(L); INodeDefManager *ndef = getServer()->ndef(); // Push callback function on stack if (!getItemCallback(ndef->get(node).name.c_str(), "on_dig")) return false; // Call function push_v3s16(L, p); pushnode(L, node, ndef); objectrefGetOrCreate(L, digger); PCALL_RES(lua_pcall(L, 3, 0, error_handler)); lua_pop(L, 1); // Pop error handler return true; }