minetest.get_craft_result
authorPerttu Ahola <celeron55@gmail.com>
Sat, 2 Jun 2012 09:19:44 +0000 (12:19 +0300)
committerPerttu Ahola <celeron55@gmail.com>
Sun, 3 Jun 2012 19:31:01 +0000 (22:31 +0300)
doc/lua_api.txt
games/minimal/mods/default/init.lua
src/scriptapi.cpp

index 70ba82dc797d81ec2b7957b81dd27486836b4e67..22c1824c0a692909aaf92d48d3d39b56aac48a0f 100644 (file)
@@ -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)
index 603380d5ba552e2bd997d9a042380f008a45435c..fc5eb0953c976093c1feb97bde8a9a1b4f87db0f 100644 (file)
@@ -1572,6 +1572,57 @@ minetest.register_on_chat_message(function(name, message)
        end
 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
 --
index 76807b14b378dd10cf4d201cf0ee68aab01155de..320a45ff9f0d8d7d583e6b2e87a121042ffae8ed 100644 (file)
@@ -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}
 };