X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fcraftdef.cpp;h=9cd1d8c7ef12f2823c1e6622ce1bf787638c260d;hb=58e6d25e033c76dc91aaac18fdeda92ac23fe0e1;hp=d21a1b5e7cb4edf9795d6f71674998b7aba3aa12;hpb=f1d9880006cf713597c1fc573f83db75062712c9;p=oweals%2Fminetest.git diff --git a/src/craftdef.cpp b/src/craftdef.cpp index d21a1b5e7..9cd1d8c7e 100644 --- a/src/craftdef.cpp +++ b/src/craftdef.cpp @@ -1,18 +1,18 @@ /* -Minetest-c55 -Copyright (C) 2011 celeron55, Perttu Ahola +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. +GNU Lesser General Public License for more details. -You should have received a copy of the GNU General Public License along +You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -23,10 +23,41 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "log.h" #include #include -#include "utility.h" +#include #include "gamedef.h" #include "inventory.h" +#include "util/serialize.h" +#include "strfnd.h" +#include "exceptions.h" + +// Check if input matches recipe +// Takes recipe groups into account +static bool inputItemMatchesRecipe(const std::string &inp_name, + const std::string &rec_name, IItemDefManager *idef) +{ + // Exact name + if(inp_name == rec_name) + return true; + + // Group + if(rec_name.substr(0,6) == "group:" && idef->isKnown(inp_name)){ + const struct ItemDefinition &def = idef->get(inp_name); + Strfnd f(rec_name.substr(6)); + bool all_groups_match = true; + do{ + std::string check_group = f.next(","); + if(itemgroup_get(def.groups, check_group) == 0){ + all_groups_match = false; + break; + } + }while(!f.atend()); + if(all_groups_match) + return true; + } + // Didn't match + return false; +} // Deserialize an itemstring then return the name of the item static std::string craftGetItemName(const std::string &itemstring, IGameDef *gamedef) @@ -64,6 +95,20 @@ static std::vector craftGetItemNames( return result; } +// convert a list of item names, to ItemStacks. +static std::vector craftGetItems( + const std::vector &items, IGameDef *gamedef) +{ + std::vector result; + for(std::vector::const_iterator + i = items.begin(); + i != items.end(); i++) + { + result.push_back(ItemStack(std::string(*i),(u16)1,(u16)0,"",gamedef->getItemDefManager())); + } + return result; +} + // Compute bounding rectangle given a matrix of items // Returns false if every item is "" static bool craftGetBounds(const std::vector &items, unsigned int width, @@ -106,20 +151,6 @@ static bool craftGetBounds(const std::vector &items, unsigned int w return success; } -// Convert a list of item names to a multiset -static std::multiset craftMakeMultiset(const std::vector &names) -{ - std::multiset set; - for(std::vector::const_iterator - i = names.begin(); - i != names.end(); i++) - { - if(*i != "") - set.insert(*i); - } - return set; -} - // Removes 1 from each item stack static void craftDecrementInput(CraftInput &input, IGameDef *gamedef) { @@ -260,6 +291,7 @@ std::string CraftOutput::dump() const /* CraftReplacements */ + std::string CraftReplacements::dump() const { std::ostringstream os(std::ios::binary); @@ -276,6 +308,27 @@ std::string CraftReplacements::dump() const return os.str(); } +void CraftReplacements::serialize(std::ostream &os) const +{ + writeU16(os, pairs.size()); + for(u32 i=0; iidef()) ){ return false; } @@ -397,6 +450,11 @@ CraftOutput CraftDefinitionShaped::getOutput(const CraftInput &input, IGameDef * return CraftOutput(output, 0); } +CraftInput CraftDefinitionShaped::getInput(const CraftOutput &output, IGameDef *gamedef) const +{ + return CraftInput(CRAFT_METHOD_NORMAL,width,craftGetItems(recipe,gamedef)); +} + void CraftDefinitionShaped::decrementInput(CraftInput &input, IGameDef *gamedef) const { craftDecrementOrReplaceInput(input, replacements, gamedef); @@ -418,12 +476,7 @@ void CraftDefinitionShaped::serializeBody(std::ostream &os) const writeU16(os, recipe.size()); for(u32 i=0; i input_filtered; + for(std::vector::const_iterator + i = input.items.begin(); + i != input.items.end(); i++) + { + if(i->name != "") + input_filtered.push_back(i->name); + } - // Get input item multiset - std::vector inp_names = craftGetItemNames(input.items, gamedef); - std::multiset inp_names_multiset = craftMakeMultiset(inp_names); + // If there is a wrong number of items in input, no match + if(input_filtered.size() != recipe.size()){ + /*dstream<<"Number of input items ("<idef())){ + all_match = false; + break; + } + } + //dstream<<" -> match="< stack; + stack.push_back(ItemStack()); + return CraftInput(CRAFT_METHOD_COOKING,additional_wear,stack); +} + void CraftDefinitionToolRepair::decrementInput(CraftInput &input, IGameDef *gamedef) const { craftDecrementInput(input, gamedef); @@ -645,16 +722,26 @@ bool CraftDefinitionCooking::check(const CraftInput &input, IGameDef *gamedef) c if(input.method != CRAFT_METHOD_COOKING) return false; - // Get input item multiset - std::vector inp_names = craftGetItemNames(input.items, gamedef); - std::multiset inp_names_multiset = craftMakeMultiset(inp_names); - - // Get recipe item multiset - std::multiset rec_names_multiset; - rec_names_multiset.insert(craftGetItemName(recipe, gamedef)); + // Filter empty items out of input + std::vector input_filtered; + for(std::vector::const_iterator + i = input.items.begin(); + i != input.items.end(); i++) + { + if(i->name != "") + input_filtered.push_back(i->name); + } - // Recipe is matched when the multisets coincide - return inp_names_multiset == rec_names_multiset; + // If there is a wrong number of items in input, no match + if(input_filtered.size() != 1){ + /*dstream<<"Number of input items ("< inp_names = craftGetItemNames(input.items, gamedef); - std::multiset inp_names_multiset = craftMakeMultiset(inp_names); - - // Get recipe item multiset - std::multiset rec_names_multiset; - rec_names_multiset.insert(craftGetItemName(recipe, gamedef)); + // Filter empty items out of input + std::vector input_filtered; + for(std::vector::const_iterator + i = input.items.begin(); + i != input.items.end(); i++) + { + if(i->name != "") + input_filtered.push_back(i->name); + } - // Recipe is matched when the multisets coincide - return inp_names_multiset == rec_names_multiset; + // If there is a wrong number of items in input, no match + if(input_filtered.size() != 1){ + /*dstream<<"Number of input items ("< rec; + rec.push_back(recipe); + return CraftInput(CRAFT_METHOD_COOKING,(int)burntime,craftGetItems(rec,gamedef)); +} + void CraftDefinitionFuel::decrementInput(CraftInput &input, IGameDef *gamedef) const { - craftDecrementInput(input, gamedef); + craftDecrementOrReplaceInput(input, replacements, gamedef); } std::string CraftDefinitionFuel::dump() const { std::ostringstream os(std::ios::binary); os<<"(fuel, recipe=\""<::const_reverse_iterator + i = m_craft_definitions.rbegin(); + i != m_craft_definitions.rend(); i++) + { + CraftDefinition *def = *i; + + /*infostream<<"Checking "<dump()<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); + return true; + } + } + catch(SerializationError &e) + { + errorstream<<"getCraftResult: ERROR: " + <<"Serialization error in recipe " + <dump()< getCraftRecipes(CraftOutput &output, + IGameDef *gamedef) const + { + std::vector recipes_list; + CraftInput input; + CraftOutput tmpout; + tmpout.item = ""; + tmpout.time = 0; + + for(std::vector::const_reverse_iterator + i = m_craft_definitions.rbegin(); + i != m_craft_definitions.rend(); i++) + { + CraftDefinition *def = *i; + + /*infostream<<"Checking "<dump()<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 " + <dump()<