123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 |
- /*
- Minetest
- Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
- You should have received a copy of the GNU Lesser General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
- #include "cpp_api/s_item.h"
- #include "cpp_api/s_internal.h"
- #include "common/c_converter.h"
- #include "common/c_content.h"
- #include "lua_api/l_item.h"
- #include "lua_api/l_inventory.h"
- #include "server.h"
- #include "log.h"
- #include "util/pointedthing.h"
- #include "inventory.h"
- #include "inventorymanager.h"
- #define WRAP_LUAERROR(e, detail) \
- LuaError(std::string(__FUNCTION__) + ": " + (e).what() + ". " detail)
- bool ScriptApiItem::item_OnDrop(ItemStack &item,
- ServerActiveObject *dropper, v3f pos)
- {
- SCRIPTAPI_PRECHECKHEADER
- int error_handler = PUSH_ERROR_HANDLER(L);
- // Push callback function on stack
- if (!getItemCallback(item.name.c_str(), "on_drop"))
- return false;
- // Call function
- LuaItemStack::create(L, item);
- objectrefGetOrCreate(L, dropper);
- pushFloatPos(L, pos);
- PCALL_RES(lua_pcall(L, 3, 1, error_handler));
- if (!lua_isnil(L, -1)) {
- try {
- item = read_item(L, -1, getServer()->idef());
- } catch (LuaError &e) {
- throw WRAP_LUAERROR(e, "item=" + item.name);
- }
- }
- lua_pop(L, 2); // Pop item and error handler
- return true;
- }
- bool ScriptApiItem::item_OnPlace(Optional<ItemStack> &ret_item,
- ServerActiveObject *placer, const PointedThing &pointed)
- {
- SCRIPTAPI_PRECHECKHEADER
- int error_handler = PUSH_ERROR_HANDLER(L);
- const ItemStack &item = *ret_item;
- // Push callback function on stack
- if (!getItemCallback(item.name.c_str(), "on_place"))
- return false;
- // Call function
- LuaItemStack::create(L, item);
- if (!placer)
- lua_pushnil(L);
- else
- objectrefGetOrCreate(L, placer);
- pushPointedThing(pointed);
- PCALL_RES(lua_pcall(L, 3, 1, error_handler));
- if (!lua_isnil(L, -1)) {
- try {
- ret_item = read_item(L, -1, getServer()->idef());
- } catch (LuaError &e) {
- throw WRAP_LUAERROR(e, "item=" + item.name);
- }
- } else {
- ret_item = nullopt;
- }
- lua_pop(L, 2); // Pop item and error handler
- return true;
- }
- bool ScriptApiItem::item_OnUse(Optional<ItemStack> &ret_item,
- ServerActiveObject *user, const PointedThing &pointed)
- {
- SCRIPTAPI_PRECHECKHEADER
- int error_handler = PUSH_ERROR_HANDLER(L);
- const ItemStack &item = *ret_item;
- // 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 {
- ret_item = read_item(L, -1, getServer()->idef());
- } catch (LuaError &e) {
- throw WRAP_LUAERROR(e, "item=" + item.name);
- }
- } else {
- ret_item = nullopt;
- }
- lua_pop(L, 2); // Pop item and error handler
- return true;
- }
- bool ScriptApiItem::item_OnSecondaryUse(Optional<ItemStack> &ret_item,
- ServerActiveObject *user, const PointedThing &pointed)
- {
- SCRIPTAPI_PRECHECKHEADER
- int error_handler = PUSH_ERROR_HANDLER(L);
- const ItemStack &item = *ret_item;
- if (!getItemCallback(item.name.c_str(), "on_secondary_use"))
- return false;
- LuaItemStack::create(L, item);
- objectrefGetOrCreate(L, user);
- pushPointedThing(pointed);
- PCALL_RES(lua_pcall(L, 3, 1, error_handler));
- if (!lua_isnil(L, -1)) {
- try {
- ret_item = read_item(L, -1, getServer()->idef());
- } catch (LuaError &e) {
- throw WRAP_LUAERROR(e, "item=" + item.name);
- }
- } else {
- ret_item = nullopt;
- }
- lua_pop(L, 2); // Pop item and error handler
- return true;
- }
- bool ScriptApiItem::item_OnCraft(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, "on_craft");
- 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()->idef());
- } catch (LuaError &e) {
- throw WRAP_LUAERROR(e, "item=" + item.name);
- }
- }
- lua_pop(L, 2); // Pop item and error handler
- return true;
- }
- bool ScriptApiItem::item_CraftPredict(ItemStack &item, ServerActiveObject *user,
- const InventoryList *old_craft_grid, const InventoryLocation &craft_inv)
- {
- SCRIPTAPI_PRECHECKHEADER
- sanity_check(old_craft_grid);
- 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()->idef());
- } catch (LuaError &e) {
- throw WRAP_LUAERROR(e, "item=" + item.name);
- }
- }
- lua_pop(L, 2); // Pop item and error handler
- return true;
- }
- // Retrieves core.registered_items[name][callbackname]
- // If that is nil or on error, return false and stack is unchanged
- // If that is a function, returns true and pushes the
- // function onto the stack
- // If core.registered_items[name] doesn't exist, core.nodedef_default
- // is tried instead so unknown items can still be manipulated to some degree
- bool ScriptApiItem::getItemCallback(const char *name, const char *callbackname,
- const v3s16 *p)
- {
- lua_State* L = getStack();
- lua_getglobal(L, "core");
- lua_getfield(L, -1, "registered_items");
- lua_remove(L, -2); // Remove core
- luaL_checktype(L, -1, LUA_TTABLE);
- lua_getfield(L, -1, name);
- lua_remove(L, -2); // Remove registered_items
- // Should be a table
- if (lua_type(L, -1) != LUA_TTABLE) {
- // Report error and clean up
- errorstream << "Item \"" << name << "\" not defined";
- if (p)
- errorstream << " at position " << PP(*p);
- errorstream << std::endl;
- lua_pop(L, 1);
- // Try core.nodedef_default instead
- lua_getglobal(L, "core");
- lua_getfield(L, -1, "nodedef_default");
- lua_remove(L, -2);
- luaL_checktype(L, -1, LUA_TTABLE);
- }
- setOriginFromTable(-1);
- lua_getfield(L, -1, callbackname);
- lua_remove(L, -2); // Remove item def
- // Should be a function or nil
- if (lua_type(L, -1) == LUA_TFUNCTION) {
- return true;
- }
- if (!lua_isnil(L, -1)) {
- errorstream << "Item \"" << name << "\" callback \""
- << callbackname << "\" is not a function" << std::endl;
- }
- lua_pop(L, 1);
- return false;
- }
- void ScriptApiItem::pushPointedThing(const PointedThing &pointed, bool hitpoint)
- {
- lua_State* L = getStack();
- push_pointed_thing(L, pointed, false, hitpoint);
- }
|