diff options
-rw-r--r-- | doc/lua_api.txt | 8 | ||||
-rw-r--r-- | games/minimal/mods/default/init.lua | 51 | ||||
-rw-r--r-- | src/scriptapi.cpp | 125 |
3 files changed, 158 insertions, 26 deletions
diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 70ba82dc7..22c1824c0 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -751,6 +751,14 @@ minetest.dir_to_wallmounted(dir) minetest.get_node_drops(nodename, toolname) ^ Returns list of item names. ^ Note: This will be removed or modified in a future version. +minetest.get_craft_result(input) -> output, decremented_input +^ input.method = 'normal' or 'cooking' or 'fuel' +^ input.width = for example 3 +^ input.items = for example { stack 1, stack 2, stack 3, stack 4, + stack 5, stack 6, stack 7, stack 8, stack 9 } +^ output.item = ItemStack, if unsuccessful: empty ItemStack +^ output.time = number, if unsuccessful: 0 +^ decremented_input = like input Defaults for the on_* item definition functions: (These return the leftover itemstack) diff --git a/games/minimal/mods/default/init.lua b/games/minimal/mods/default/init.lua index 603380d5b..fc5eb0953 100644 --- a/games/minimal/mods/default/init.lua +++ b/games/minimal/mods/default/init.lua @@ -1573,6 +1573,57 @@ minetest.register_on_chat_message(function(name, message) end) -- +-- Test some things +-- + +local function test_get_craft_result() + print("test_get_craft_result()") + -- normal + local input = { + method = "normal", + width = 2, + items = {"", "default:coal_lump", "", "default:stick"} + } + print("torch crafting input: "..dump(input)) + local output, decremented_input = minetest.get_craft_result(input) + print("torch crafting output: "..dump(output)) + print("torch crafting decremented input: "..dump(decremented_input)) + assert(output.item) + print("torch crafting output.item:to_table(): "..dump(output.item:to_table())) + assert(output.item:get_name() == "default:torch") + assert(output.item:get_count() == 4) + -- fuel + local input = { + method = "fuel", + width = 1, + items = {"default:coal_lump"} + } + print("coal fuel input: "..dump(input)) + local output, decremented_input = minetest.get_craft_result(input) + print("coal fuel output: "..dump(output)) + print("coal fuel decremented input: "..dump(decremented_input)) + assert(output.time) + assert(output.time > 0) + -- cook + local input = { + method = "cooking", + width = 1, + items = {"default:cobble"} + } + print("cobble cooking input: "..dump(output)) + local output, decremented_input = minetest.get_craft_result(input) + print("cobble cooking output: "..dump(output)) + print("cobble cooking decremented input: "..dump(decremented_input)) + assert(output.time) + assert(output.time > 0) + assert(output.item) + print("cobble cooking output.item:to_table(): "..dump(output.item:to_table())) + assert(output.item:get_name() == "default:stone") + assert(output.item:get_count() == 1) +end +test_get_craft_result() + +-- -- Done, print some random stuff -- diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp index 76807b14b..320a45ff9 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -418,6 +418,14 @@ struct EnumString es_NodeBoxType[] = {0, NULL}, }; +struct EnumString es_CraftMethod[] = +{ + {CRAFT_METHOD_NORMAL, "normal"}, + {CRAFT_METHOD_COOKING, "cooking"}, + {CRAFT_METHOD_FUEL, "fuel"}, + {0, NULL}, +}; + /* C struct <-> Lua table converter functions */ @@ -1173,6 +1181,9 @@ static ContentFeatures read_content_features(lua_State *L, int index) */ static ItemStack read_item(lua_State *L, int index); +static std::vector<ItemStack> read_items(lua_State *L, int index); +// creates a table of ItemStacks +static void push_items(lua_State *L, const std::vector<ItemStack> &items); static void inventory_set_list_from_lua(Inventory *inv, const char *name, lua_State *L, int tableindex, int forcesize=-1) @@ -1185,15 +1196,7 @@ static void inventory_set_list_from_lua(Inventory *inv, const char *name, return; } // Otherwise set list - std::vector<ItemStack> items; - luaL_checktype(L, tableindex, LUA_TTABLE); - lua_pushnil(L); - while(lua_next(L, tableindex) != 0){ - // key at index -2 and value at index -1 - items.push_back(read_item(L, -1)); - // removes value, keeps key for next iteration - lua_pop(L, 1); - } + std::vector<ItemStack> items = read_items(L, tableindex); int listsize = (forcesize != -1) ? forcesize : items.size(); InventoryList *invlist = inv->addList(name, listsize); int index = 0; @@ -1218,23 +1221,10 @@ static void inventory_get_list_to_lua(Inventory *inv, const char *name, lua_pushnil(L); return; } - // Get the table insert function - lua_getglobal(L, "table"); - lua_getfield(L, -1, "insert"); - int table_insert = lua_gettop(L); - // Create and fill table - lua_newtable(L); - int table = lua_gettop(L); - for(u32 i=0; i<invlist->getSize(); i++){ - ItemStack item = invlist->getItem(i); - lua_pushvalue(L, table_insert); - lua_pushvalue(L, table); - lua_pushstring(L, item.getItemString().c_str()); - if(lua_pcall(L, 2, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); - } - lua_remove(L, -2); // Remove table - lua_remove(L, -2); // Remove insert + std::vector<ItemStack> items; + for(u32 i=0; i<invlist->getSize(); i++) + items.push_back(invlist->getItem(i)); + push_items(L, items); } /* @@ -1640,6 +1630,45 @@ static ItemStack read_item(lua_State *L, int index) } } +static std::vector<ItemStack> read_items(lua_State *L, int index) +{ + if(index < 0) + index = lua_gettop(L) + 1 + index; + + std::vector<ItemStack> items; + luaL_checktype(L, index, LUA_TTABLE); + lua_pushnil(L); + while(lua_next(L, index) != 0){ + // key at index -2 and value at index -1 + items.push_back(read_item(L, -1)); + // removes value, keeps key for next iteration + lua_pop(L, 1); + } + return items; +} + +// creates a table of ItemStacks +static void push_items(lua_State *L, const std::vector<ItemStack> &items) +{ + // Get the table insert function + lua_getglobal(L, "table"); + lua_getfield(L, -1, "insert"); + int table_insert = lua_gettop(L); + // Create and fill table + lua_newtable(L); + int table = lua_gettop(L); + for(u32 i=0; i<items.size(); i++){ + ItemStack item = items[i]; + lua_pushvalue(L, table_insert); + lua_pushvalue(L, table); + LuaItemStack::create(L, item); + if(lua_pcall(L, 2, 0, 0)) + script_error(L, "error: %s", lua_tostring(L, -1)); + } + lua_remove(L, -2); // Remove table + lua_remove(L, -2); // Remove insert +} + /* InvRef */ @@ -4204,6 +4233,49 @@ static int l_notify_authentication_modified(lua_State *L) return 0; } +// get_craft_result(input) +static int l_get_craft_result(lua_State *L) +{ + int input_i = 1; + std::string method_s = getstringfield_default(L, input_i, "method", "normal"); + enum CraftMethod method = (CraftMethod)getenumfield(L, input_i, "method", + es_CraftMethod, CRAFT_METHOD_NORMAL); + int width = 1; + lua_getfield(L, input_i, "width"); + if(lua_isnumber(L, -1)) + width = luaL_checkinteger(L, -1); + lua_pop(L, 1); + lua_getfield(L, input_i, "items"); + std::vector<ItemStack> items = read_items(L, -1); + lua_pop(L, 1); // items + + IGameDef *gdef = get_server(L); + ICraftDefManager *cdef = gdef->cdef(); + CraftInput input(method, width, items); + CraftOutput output; + bool got = cdef->getCraftResult(input, output, true, gdef); + lua_newtable(L); // output table + if(got){ + ItemStack item; + item.deSerialize(output.item, gdef->idef()); + LuaItemStack::create(L, item); + lua_setfield(L, -2, "item"); + setintfield(L, -1, "time", output.time); + } else { + LuaItemStack::create(L, ItemStack()); + lua_setfield(L, -2, "item"); + setintfield(L, -1, "time", 0); + } + lua_newtable(L); // decremented input table + lua_pushstring(L, method_s.c_str()); + lua_setfield(L, -2, "method"); + lua_pushinteger(L, width); + lua_setfield(L, -2, "width"); + push_items(L, input.items); + lua_setfield(L, -2, "items"); + return 2; +} + static const struct luaL_Reg minetest_f [] = { {"debug", l_debug}, {"log", l_log}, @@ -4227,6 +4299,7 @@ static const struct luaL_Reg minetest_f [] = { {"is_singleplayer", l_is_singleplayer}, {"get_password_hash", l_get_password_hash}, {"notify_authentication_modified", l_notify_authentication_modified}, + {"get_craft_result", l_get_craft_result}, {NULL, NULL} }; |