aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/lua_api.txt8
-rw-r--r--games/minimal/mods/default/init.lua51
-rw-r--r--src/scriptapi.cpp125
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}
};