From 9eaf93d41d6745b877f8f52cf54b21050abefda1 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Wed, 25 Jul 2012 02:36:54 +0300 Subject: Detached inventory callbacks and reworked node metadata callbacks --- src/scriptapi.cpp | 410 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 396 insertions(+), 14 deletions(-) (limited to 'src/scriptapi.cpp') diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp index 9959ddd74..d28f8c7c1 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -4579,8 +4579,8 @@ static int l_get_inventory(lua_State *L) return 1; } -// create_detached_inventory(name) -static int l_create_detached_inventory(lua_State *L) +// create_detached_inventory_raw(name) +static int l_create_detached_inventory_raw(lua_State *L) { const char *name = luaL_checkstring(L, 1); if(get_server(L)->createDetachedInventory(name) != NULL){ @@ -4866,7 +4866,7 @@ static const struct luaL_Reg minetest_f [] = { {"chat_send_player", l_chat_send_player}, {"get_player_privs", l_get_player_privs}, {"get_inventory", l_get_inventory}, - {"create_detached_inventory", l_create_detached_inventory}, + {"create_detached_inventory_raw", l_create_detached_inventory_raw}, {"get_dig_params", l_get_dig_params}, {"get_hit_params", l_get_hit_params}, {"get_current_modname", l_get_current_modname}, @@ -5734,7 +5734,128 @@ void scriptapi_node_on_receive_fields(lua_State *L, v3s16 p, script_error(L, "error: %s", lua_tostring(L, -1)); } -void scriptapi_node_on_metadata_inventory_move(lua_State *L, v3s16 p, +/* + Node metadata inventory callbacks +*/ + +// Return number of accepted items to be moved +int scriptapi_nodemeta_inventory_allow_move(lua_State *L, v3s16 p, + const std::string &from_list, int from_index, + const std::string &to_list, int to_index, + int count, ServerActiveObject *player) +{ + realitycheck(L); + assert(lua_checkstack(L, 20)); + StackUnroller stack_unroller(L); + + INodeDefManager *ndef = get_server(L)->ndef(); + + // If node doesn't exist, we don't know what callback to call + MapNode node = get_env(L)->getMap().getNodeNoEx(p); + if(node.getContent() == CONTENT_IGNORE) + return 0; + + // Push callback function on stack + if(!get_item_callback(L, ndef->get(node).name.c_str(), + "allow_metadata_inventory_move")) + return count; + + // function(pos, from_list, from_index, to_list, to_index, count, player) + // pos + push_v3s16(L, p); + // from_list + lua_pushstring(L, from_list.c_str()); + // from_index + lua_pushinteger(L, from_index + 1); + // to_list + lua_pushstring(L, to_list.c_str()); + // to_index + lua_pushinteger(L, to_index + 1); + // count + lua_pushinteger(L, count); + // player + objectref_get_or_create(L, player); + if(lua_pcall(L, 7, 1, 0)) + script_error(L, "error: %s", lua_tostring(L, -1)); + return luaL_checkinteger(L, -1); +} + +// Return number of accepted items to be put +int scriptapi_nodemeta_inventory_allow_put(lua_State *L, v3s16 p, + const std::string &listname, int index, ItemStack &stack, + ServerActiveObject *player) +{ + realitycheck(L); + assert(lua_checkstack(L, 20)); + StackUnroller stack_unroller(L); + + INodeDefManager *ndef = get_server(L)->ndef(); + + // If node doesn't exist, we don't know what callback to call + MapNode node = get_env(L)->getMap().getNodeNoEx(p); + if(node.getContent() == CONTENT_IGNORE) + return 0; + + // Push callback function on stack + if(!get_item_callback(L, ndef->get(node).name.c_str(), + "allow_metadata_inventory_put")) + return stack.count; + + // Call function(pos, listname, index, stack, player) + // pos + push_v3s16(L, p); + // listname + lua_pushstring(L, listname.c_str()); + // index + lua_pushinteger(L, index + 1); + // stack + LuaItemStack::create(L, stack); + // player + objectref_get_or_create(L, player); + if(lua_pcall(L, 5, 1, 0)) + script_error(L, "error: %s", lua_tostring(L, -1)); + return luaL_checkinteger(L, -1); +} + +// Return number of accepted items to be taken +int scriptapi_nodemeta_inventory_allow_take(lua_State *L, v3s16 p, + const std::string &listname, int index, int count, + ServerActiveObject *player) +{ + realitycheck(L); + assert(lua_checkstack(L, 20)); + StackUnroller stack_unroller(L); + + INodeDefManager *ndef = get_server(L)->ndef(); + + // If node doesn't exist, we don't know what callback to call + MapNode node = get_env(L)->getMap().getNodeNoEx(p); + if(node.getContent() == CONTENT_IGNORE) + return 0; + + // Push callback function on stack + if(!get_item_callback(L, ndef->get(node).name.c_str(), + "allow_metadata_inventory_take")) + return count; + + // Call function(pos, listname, index, count, player) + // pos + push_v3s16(L, p); + // listname + lua_pushstring(L, listname.c_str()); + // index + lua_pushinteger(L, index + 1); + // count + lua_pushinteger(L, count); + // player + objectref_get_or_create(L, player); + if(lua_pcall(L, 5, 1, 0)) + script_error(L, "error: %s", lua_tostring(L, -1)); + return luaL_checkinteger(L, -1); +} + +// Report moved items +void scriptapi_nodemeta_inventory_on_move(lua_State *L, v3s16 p, const std::string &from_list, int from_index, const std::string &to_list, int to_index, int count, ServerActiveObject *player) @@ -5756,18 +5877,26 @@ void scriptapi_node_on_metadata_inventory_move(lua_State *L, v3s16 p, return; // function(pos, from_list, from_index, to_list, to_index, count, player) + // pos push_v3s16(L, p); + // from_list lua_pushstring(L, from_list.c_str()); + // from_index lua_pushinteger(L, from_index + 1); + // to_list lua_pushstring(L, to_list.c_str()); + // to_index lua_pushinteger(L, to_index + 1); + // count lua_pushinteger(L, count); + // player objectref_get_or_create(L, player); if(lua_pcall(L, 7, 0, 0)) script_error(L, "error: %s", lua_tostring(L, -1)); } -ItemStack scriptapi_node_on_metadata_inventory_offer(lua_State *L, v3s16 p, +// Report put items +void scriptapi_nodemeta_inventory_on_put(lua_State *L, v3s16 p, const std::string &listname, int index, ItemStack &stack, ServerActiveObject *player) { @@ -5780,25 +5909,30 @@ ItemStack scriptapi_node_on_metadata_inventory_offer(lua_State *L, v3s16 p, // If node doesn't exist, we don't know what callback to call MapNode node = get_env(L)->getMap().getNodeNoEx(p); if(node.getContent() == CONTENT_IGNORE) - return stack; + return; // Push callback function on stack if(!get_item_callback(L, ndef->get(node).name.c_str(), - "on_metadata_inventory_offer")) - return stack; + "on_metadata_inventory_put")) + return; // Call function(pos, listname, index, stack, player) + // pos push_v3s16(L, p); + // listname lua_pushstring(L, listname.c_str()); + // index lua_pushinteger(L, index + 1); + // stack LuaItemStack::create(L, stack); + // player objectref_get_or_create(L, player); - if(lua_pcall(L, 5, 1, 0)) + if(lua_pcall(L, 5, 0, 0)) script_error(L, "error: %s", lua_tostring(L, -1)); - return read_item(L, -1); } -ItemStack scriptapi_node_on_metadata_inventory_take(lua_State *L, v3s16 p, +// Report taken items +void scriptapi_nodemeta_inventory_on_take(lua_State *L, v3s16 p, const std::string &listname, int index, int count, ServerActiveObject *player) { @@ -5811,22 +5945,270 @@ ItemStack scriptapi_node_on_metadata_inventory_take(lua_State *L, v3s16 p, // If node doesn't exist, we don't know what callback to call MapNode node = get_env(L)->getMap().getNodeNoEx(p); if(node.getContent() == CONTENT_IGNORE) - return ItemStack(); + return; // Push callback function on stack if(!get_item_callback(L, ndef->get(node).name.c_str(), "on_metadata_inventory_take")) - return ItemStack(); + return; // Call function(pos, listname, index, count, player) + // pos push_v3s16(L, p); + // listname lua_pushstring(L, listname.c_str()); + // index lua_pushinteger(L, index + 1); + // count lua_pushinteger(L, count); + // player + objectref_get_or_create(L, player); + if(lua_pcall(L, 5, 0, 0)) + script_error(L, "error: %s", lua_tostring(L, -1)); +} + +/* + Detached inventory callbacks +*/ + +// Retrieves minetest.detached_inventories[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 +static bool get_detached_inventory_callback(lua_State *L, + const std::string &name, const char *callbackname) +{ + lua_getglobal(L, "minetest"); + lua_getfield(L, -1, "detached_inventories"); + lua_remove(L, -2); + luaL_checktype(L, -1, LUA_TTABLE); + lua_getfield(L, -1, name.c_str()); + lua_remove(L, -2); + // Should be a table + if(lua_type(L, -1) != LUA_TTABLE) + { + errorstream<<"Item \""<