Browse Source

Added method to get all registered recipes for item(node)

RealBadAngel 11 years ago
parent
commit
5af8acfa6e
4 changed files with 120 additions and 0 deletions
  1. 5 0
      doc/lua_api.txt
  2. 37 0
      src/craftdef.cpp
  3. 4 0
      src/craftdef.h
  4. 74 0
      src/scriptapi.cpp

+ 5 - 0
doc/lua_api.txt

@@ -922,12 +922,17 @@ minetest.get_craft_result(input) -> output, decremented_input
 ^ output.time = number, if unsuccessful: 0
 ^ decremented_input = like input
 minetest.get_craft_recipe(output) -> input
+^ returns last registered recipe for output item (node)
 ^ output is a node or item type such as 'default:torch'
 ^ 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 }
 ^ input.items = nil if no recipe found
+minetest.get_all_craft_recipes(output) -> table or nil
+^ returns table with all registered recipes for output item (node)
+^ returns nil if no recipe was found
+^ table entries have same format as minetest.get_craft_recipe
 minetest.handle_node_drops(pos, drops, digger)
 ^ drops: list of itemstrings
 ^ Handles drops from nodes after digging: Default action is to put them into

+ 37 - 0
src/craftdef.cpp

@@ -987,6 +987,43 @@ public:
 		}
 		return false;
 	}
+	virtual std::vector<CraftDefinition*> getCraftRecipes(CraftOutput &output,
+			IGameDef *gamedef) const
+	{
+		std::vector<CraftDefinition*> recipes_list;
+		CraftInput input;
+		CraftOutput tmpout;
+		tmpout.item = "";
+		tmpout.time = 0;
+
+		for(std::vector<CraftDefinition*>::const_reverse_iterator
+				i = m_craft_definitions.rbegin();
+				i != m_craft_definitions.rend(); i++)
+		{
+			CraftDefinition *def = *i;
+
+			/*infostream<<"Checking "<<input.dump()<<std::endl
+					<<" against "<<def->dump()<<std::endl;*/
+
+			try {
+				tmpout = def->getOutput(input, gamedef);
+				if(tmpout.item.substr(0,output.item.length()) == output.item)
+				{
+					// Get output, then decrement input (if requested)
+					input = def->getInput(output, gamedef);
+					recipes_list.push_back(*i);
+				}
+			}
+			catch(SerializationError &e)
+			{
+				errorstream<<"getCraftResult: ERROR: "
+						<<"Serialization error in recipe "
+						<<def->dump()<<std::endl;
+				// then go on with the next craft definition
+			}
+		}
+		return recipes_list;
+	}
 	virtual std::string dump() const
 	{
 		std::ostringstream os(std::ios::binary);

+ 4 - 0
src/craftdef.h

@@ -358,6 +358,8 @@ public:
 			bool decrementInput, IGameDef *gamedef) const=0;
 	virtual bool getCraftRecipe(CraftInput &input, CraftOutput &output,
 			IGameDef *gamedef) const=0;
+	virtual std::vector<CraftDefinition*> getCraftRecipes(CraftOutput &output,
+			IGameDef *gamedef) const=0;
 	
 	// Print crafting recipes for debugging
 	virtual std::string dump() const=0;
@@ -376,6 +378,8 @@ public:
 			bool decrementInput, IGameDef *gamedef) const=0;
 	virtual bool getCraftRecipe(CraftInput &input, CraftOutput &output,
 			IGameDef *gamedef) const=0;
+	virtual std::vector<CraftDefinition*> getCraftRecipes(CraftOutput &output, 
+			IGameDef *gamedef) const=0;
 
 	// Print crafting recipes for debugging
 	virtual std::string dump() const=0;

+ 74 - 0
src/scriptapi.cpp

@@ -1000,6 +1000,79 @@ static int l_notify_authentication_modified(lua_State *L)
 	return 0;
 }
 
+// get_craft_recipes(result item)
+static int l_get_all_craft_recipes(lua_State *L)
+{
+	char tmp[20];
+	int input_i = 1;
+	std::string o_item = luaL_checkstring(L,input_i);
+	IGameDef *gdef = get_server(L);
+	ICraftDefManager *cdef = gdef->cdef();
+	CraftInput input;
+	CraftOutput output(o_item,0);
+	std::vector<CraftDefinition*> recipes_list = cdef->getCraftRecipes(output, gdef);
+	if (recipes_list.empty())
+	{
+		lua_pushnil(L);
+		return 1;
+	}
+	// Get the table insert function
+	lua_getglobal(L, "table");
+	lua_getfield(L, -1, "insert");
+	int table_insert = lua_gettop(L);
+	lua_newtable(L);
+	int table = lua_gettop(L);
+	for(std::vector<CraftDefinition*>::const_iterator
+		i = recipes_list.begin();
+		i != recipes_list.end(); i++)
+	{
+		CraftOutput tmpout;
+		tmpout.item = "";
+		tmpout.time = 0;
+		CraftDefinition *def = *i;
+		tmpout = def->getOutput(input, gdef);
+		if(tmpout.item.substr(0,output.item.length()) == output.item)
+		{
+			input = def->getInput(output, gdef);
+			lua_pushvalue(L, table_insert);
+			lua_pushvalue(L, table);
+			lua_newtable(L);
+			int k = 0;
+			lua_newtable(L);
+			for(std::vector<ItemStack>::const_iterator
+				i = input.items.begin();
+				i != input.items.end(); i++, k++)
+			{
+				if (i->empty()) continue;
+				sprintf(tmp,"%d",k);
+				lua_pushstring(L,tmp);
+				lua_pushstring(L,i->name.c_str());
+				lua_settable(L, -3);
+			}
+			lua_setfield(L, -2, "items");
+			setintfield(L, -1, "width", input.width);
+			switch (input.method)
+				{
+				case CRAFT_METHOD_NORMAL:
+					lua_pushstring(L,"normal");
+					break;
+				case CRAFT_METHOD_COOKING:
+					lua_pushstring(L,"cooking");
+					break;
+				case CRAFT_METHOD_FUEL:
+					lua_pushstring(L,"fuel");
+					break;
+				default:
+					lua_pushstring(L,"unknown");
+				}
+			lua_setfield(L, -2, "type");
+			if(lua_pcall(L, 2, 0, 0))
+			script_error(L, "error: %s", lua_tostring(L, -1));
+		}
+	}
+	return 1;
+}
+
 // rollback_get_last_node_actor(p, range, seconds) -> actor, p, seconds
 static int l_rollback_get_last_node_actor(lua_State *L)
 {
@@ -1086,6 +1159,7 @@ static const struct luaL_Reg minetest_f [] = {
 	{"notify_authentication_modified", l_notify_authentication_modified},
 	{"get_craft_result", l_get_craft_result},
 	{"get_craft_recipe", l_get_craft_recipe},
+	{"get_all_craft_recipes", l_get_all_craft_recipes},
 	{"rollback_get_last_node_actor", l_rollback_get_last_node_actor},
 	{"rollback_revert_actions_by", l_rollback_revert_actions_by},
 	{NULL, NULL}