3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include "irrlichttypes.h"
28 #include "inventory.h"
29 #include "util/serialize.h"
31 #include "exceptions.h"
33 // Check if input matches recipe
34 // Takes recipe groups into account
35 static bool inputItemMatchesRecipe(const std::string &inp_name,
36 const std::string &rec_name, IItemDefManager *idef)
39 if(inp_name == rec_name)
43 if(rec_name.substr(0,6) == "group:" && idef->isKnown(inp_name)){
44 const struct ItemDefinition &def = idef->get(inp_name);
45 Strfnd f(rec_name.substr(6));
46 bool all_groups_match = true;
48 std::string check_group = f.next(",");
49 if(itemgroup_get(def.groups, check_group) == 0){
50 all_groups_match = false;
62 // Deserialize an itemstring then return the name of the item
63 static std::string craftGetItemName(const std::string &itemstring, IGameDef *gamedef)
66 item.deSerialize(itemstring, gamedef->idef());
70 // (mapcar craftGetItemName itemstrings)
71 static std::vector<std::string> craftGetItemNames(
72 const std::vector<std::string> &itemstrings, IGameDef *gamedef)
74 std::vector<std::string> result;
75 for(std::vector<std::string>::const_iterator
76 i = itemstrings.begin();
77 i != itemstrings.end(); i++)
79 result.push_back(craftGetItemName(*i, gamedef));
84 // Get name of each item, and return them as a new list.
85 static std::vector<std::string> craftGetItemNames(
86 const std::vector<ItemStack> &items, IGameDef *gamedef)
88 std::vector<std::string> result;
89 for(std::vector<ItemStack>::const_iterator
91 i != items.end(); i++)
93 result.push_back(i->name);
98 // convert a list of item names, to ItemStacks.
99 static std::vector<ItemStack> craftGetItems(
100 const std::vector<std::string> &items, IGameDef *gamedef)
102 std::vector<ItemStack> result;
103 for(std::vector<std::string>::const_iterator
105 i != items.end(); i++)
107 result.push_back(ItemStack(std::string(*i),(u16)1,(u16)0,"",gamedef->getItemDefManager()));
112 // Compute bounding rectangle given a matrix of items
113 // Returns false if every item is ""
114 static bool craftGetBounds(const std::vector<std::string> &items, unsigned int width,
115 unsigned int &min_x, unsigned int &max_x,
116 unsigned int &min_y, unsigned int &max_y)
118 bool success = false;
121 for(std::vector<std::string>::const_iterator
123 i != items.end(); i++)
125 if(*i != "") // Is this an actual item?
129 // This is the first nonempty item
136 if(x < min_x) min_x = x;
137 if(x > max_x) max_x = x;
138 if(y < min_y) min_y = y;
139 if(y > max_y) max_y = y;
154 // Removes 1 from each item stack
155 static void craftDecrementInput(CraftInput &input, IGameDef *gamedef)
157 for(std::vector<ItemStack>::iterator
158 i = input.items.begin();
159 i != input.items.end(); i++)
166 // Removes 1 from each item stack with replacement support
167 // Example: if replacements contains the pair ("bucket:bucket_water", "bucket:bucket_empty"),
168 // a water bucket will not be removed but replaced by an empty bucket.
169 static void craftDecrementOrReplaceInput(CraftInput &input,
170 const CraftReplacements &replacements,
173 if(replacements.pairs.empty())
175 craftDecrementInput(input, gamedef);
179 // Make a copy of the replacements pair list
180 std::vector<std::pair<std::string, std::string> > pairs = replacements.pairs;
182 for(std::vector<ItemStack>::iterator
183 i = input.items.begin();
184 i != input.items.end(); i++)
188 // Find an appropriate replacement
189 bool found_replacement = false;
190 for(std::vector<std::pair<std::string, std::string> >::iterator
192 j != pairs.end(); j++)
195 from_item.deSerialize(j->first, gamedef->idef());
196 if(i->name == from_item.name)
198 i->deSerialize(j->second, gamedef->idef());
199 found_replacement = true;
204 // No replacement was found, simply decrement count to zero
205 if(!found_replacement)
208 else if(i->count >= 2)
210 // Ignore replacements for items with count >= 2
216 // Dump an itemstring matrix
217 static std::string craftDumpMatrix(const std::vector<std::string> &items,
220 std::ostringstream os(std::ios::binary);
223 for(std::vector<std::string>::const_iterator
225 i != items.end(); i++, x++)
236 os<<"\""<<(*i)<<"\"";
242 // Dump an item matrix
243 std::string craftDumpMatrix(const std::vector<ItemStack> &items,
246 std::ostringstream os(std::ios::binary);
249 for(std::vector<ItemStack>::const_iterator
251 i != items.end(); i++, x++)
262 os<<"\""<<(i->getItemString())<<"\"";
273 std::string CraftInput::dump() const
275 std::ostringstream os(std::ios::binary);
276 os<<"(method="<<((int)method)<<", items="<<craftDumpMatrix(items, width)<<")";
284 std::string CraftOutput::dump() const
286 std::ostringstream os(std::ios::binary);
287 os<<"(item=\""<<item<<"\", time="<<time<<")";
295 std::string CraftReplacements::dump() const
297 std::ostringstream os(std::ios::binary);
299 const char *sep = "";
300 for(std::vector<std::pair<std::string, std::string> >::const_iterator
302 i != pairs.end(); i++)
304 os<<sep<<"\""<<(i->first)<<"\"=>\""<<(i->second)<<"\"";
311 void CraftReplacements::serialize(std::ostream &os) const
313 writeU16(os, pairs.size());
314 for(u32 i=0; i<pairs.size(); i++)
316 os<<serializeString(pairs[i].first);
317 os<<serializeString(pairs[i].second);
321 void CraftReplacements::deSerialize(std::istream &is)
324 u32 count = readU16(is);
325 for(u32 i=0; i<count; i++)
327 std::string first = deSerializeString(is);
328 std::string second = deSerializeString(is);
329 pairs.push_back(std::make_pair(first, second));
337 void CraftDefinition::serialize(std::ostream &os) const
339 writeU8(os, 1); // version
340 os<<serializeString(getName());
344 CraftDefinition* CraftDefinition::deSerialize(std::istream &is)
346 int version = readU8(is);
347 if(version != 1) throw SerializationError(
348 "unsupported CraftDefinition version");
349 std::string name = deSerializeString(is);
350 CraftDefinition *def = NULL;
353 def = new CraftDefinitionShaped;
355 else if(name == "shapeless")
357 def = new CraftDefinitionShapeless;
359 else if(name == "toolrepair")
361 def = new CraftDefinitionToolRepair;
363 else if(name == "cooking")
365 def = new CraftDefinitionCooking;
367 else if(name == "fuel")
369 def = new CraftDefinitionFuel;
373 infostream<<"Unknown CraftDefinition name=\""<<name<<"\""<<std::endl;
374 throw SerializationError("Unknown CraftDefinition name");
376 def->deSerializeBody(is, version);
381 CraftDefinitionShaped
384 std::string CraftDefinitionShaped::getName() const
389 bool CraftDefinitionShaped::check(const CraftInput &input, IGameDef *gamedef) const
391 if(input.method != CRAFT_METHOD_NORMAL)
394 // Get input item matrix
395 std::vector<std::string> inp_names = craftGetItemNames(input.items, gamedef);
396 unsigned int inp_width = input.width;
399 while(inp_names.size() % inp_width != 0)
400 inp_names.push_back("");
403 unsigned int inp_min_x=0, inp_max_x=0, inp_min_y=0, inp_max_y=0;
404 if(!craftGetBounds(inp_names, inp_width, inp_min_x, inp_max_x, inp_min_y, inp_max_y))
405 return false; // it was empty
407 // Get recipe item matrix
408 std::vector<std::string> rec_names = craftGetItemNames(recipe, gamedef);
409 unsigned int rec_width = width;
412 while(rec_names.size() % rec_width != 0)
413 rec_names.push_back("");
416 unsigned int rec_min_x=0, rec_max_x=0, rec_min_y=0, rec_max_y=0;
417 if(!craftGetBounds(rec_names, rec_width, rec_min_x, rec_max_x, rec_min_y, rec_max_y))
418 return false; // it was empty
421 if(inp_max_x - inp_min_x != rec_max_x - rec_min_x ||
422 inp_max_y - inp_min_y != rec_max_y - rec_min_y)
425 // Verify that all item names in the bounding box are equal
426 unsigned int w = inp_max_x - inp_min_x + 1;
427 unsigned int h = inp_max_y - inp_min_y + 1;
429 for(unsigned int y=0; y < h; y++) {
430 unsigned int inp_y = (inp_min_y + y) * inp_width;
431 unsigned int rec_y = (rec_min_y + y) * rec_width;
433 for(unsigned int x=0; x < w; x++) {
434 unsigned int inp_x = inp_min_x + x;
435 unsigned int rec_x = rec_min_x + x;
437 if(!inputItemMatchesRecipe(
438 inp_names[inp_y + inp_x],
439 rec_names[rec_y + rec_x], gamedef->idef())
449 CraftOutput CraftDefinitionShaped::getOutput(const CraftInput &input, IGameDef *gamedef) const
451 return CraftOutput(output, 0);
454 CraftInput CraftDefinitionShaped::getInput(const CraftOutput &output, IGameDef *gamedef) const
456 return CraftInput(CRAFT_METHOD_NORMAL,width,craftGetItems(recipe,gamedef));
459 void CraftDefinitionShaped::decrementInput(CraftInput &input, IGameDef *gamedef) const
461 craftDecrementOrReplaceInput(input, replacements, gamedef);
464 std::string CraftDefinitionShaped::dump() const
466 std::ostringstream os(std::ios::binary);
467 os<<"(shaped, output=\""<<output
468 <<"\", recipe="<<craftDumpMatrix(recipe, width)
469 <<", replacements="<<replacements.dump()<<")";
473 void CraftDefinitionShaped::serializeBody(std::ostream &os) const
475 os<<serializeString(output);
477 writeU16(os, recipe.size());
478 for(u32 i=0; i<recipe.size(); i++)
479 os<<serializeString(recipe[i]);
480 replacements.serialize(os);
483 void CraftDefinitionShaped::deSerializeBody(std::istream &is, int version)
485 if(version != 1) throw SerializationError(
486 "unsupported CraftDefinitionShaped version");
487 output = deSerializeString(is);
490 u32 count = readU16(is);
491 for(u32 i=0; i<count; i++)
492 recipe.push_back(deSerializeString(is));
493 replacements.deSerialize(is);
497 CraftDefinitionShapeless
500 std::string CraftDefinitionShapeless::getName() const
505 bool CraftDefinitionShapeless::check(const CraftInput &input, IGameDef *gamedef) const
507 if(input.method != CRAFT_METHOD_NORMAL)
510 // Filter empty items out of input
511 std::vector<std::string> input_filtered;
512 for(std::vector<ItemStack>::const_iterator
513 i = input.items.begin();
514 i != input.items.end(); i++)
517 input_filtered.push_back(i->name);
520 // If there is a wrong number of items in input, no match
521 if(input_filtered.size() != recipe.size()){
522 /*dstream<<"Number of input items ("<<input_filtered.size()
523 <<") does not match recipe size ("<<recipe.size()<<") "
524 <<"of recipe with output="<<output<<std::endl;*/
528 // Try with all permutations of the recipe
529 std::vector<std::string> recipe_copy = craftGetItemNames(recipe, gamedef);
530 // Start from the lexicographically first permutation (=sorted)
531 std::sort(recipe_copy.begin(), recipe_copy.end());
532 //while(std::prev_permutation(recipe_copy.begin(), recipe_copy.end())){}
534 // If all items match, the recipe matches
535 bool all_match = true;
536 //dstream<<"Testing recipe (output="<<output<<"):";
537 for(size_t i=0; i<recipe.size(); i++){
538 //dstream<<" ("<<input_filtered[i]<<" == "<<recipe_copy[i]<<")";
539 if(!inputItemMatchesRecipe(input_filtered[i], recipe_copy[i],
545 //dstream<<" -> match="<<all_match<<std::endl;
548 }while(std::next_permutation(recipe_copy.begin(), recipe_copy.end()));
553 CraftOutput CraftDefinitionShapeless::getOutput(const CraftInput &input, IGameDef *gamedef) const
555 return CraftOutput(output, 0);
558 CraftInput CraftDefinitionShapeless::getInput(const CraftOutput &output, IGameDef *gamedef) const
560 return CraftInput(CRAFT_METHOD_NORMAL,0,craftGetItems(recipe,gamedef));
563 void CraftDefinitionShapeless::decrementInput(CraftInput &input, IGameDef *gamedef) const
565 craftDecrementOrReplaceInput(input, replacements, gamedef);
568 std::string CraftDefinitionShapeless::dump() const
570 std::ostringstream os(std::ios::binary);
571 os<<"(shapeless, output=\""<<output
572 <<"\", recipe="<<craftDumpMatrix(recipe, recipe.size())
573 <<", replacements="<<replacements.dump()<<")";
577 void CraftDefinitionShapeless::serializeBody(std::ostream &os) const
579 os<<serializeString(output);
580 writeU16(os, recipe.size());
581 for(u32 i=0; i<recipe.size(); i++)
582 os<<serializeString(recipe[i]);
583 replacements.serialize(os);
586 void CraftDefinitionShapeless::deSerializeBody(std::istream &is, int version)
588 if(version != 1) throw SerializationError(
589 "unsupported CraftDefinitionShapeless version");
590 output = deSerializeString(is);
592 u32 count = readU16(is);
593 for(u32 i=0; i<count; i++)
594 recipe.push_back(deSerializeString(is));
595 replacements.deSerialize(is);
599 CraftDefinitionToolRepair
602 static ItemStack craftToolRepair(
603 const ItemStack &item1,
604 const ItemStack &item2,
605 float additional_wear,
608 IItemDefManager *idef = gamedef->idef();
609 if(item1.count != 1 || item2.count != 1 || item1.name != item2.name
610 || idef->get(item1.name).type != ITEM_TOOL
611 || idef->get(item2.name).type != ITEM_TOOL)
617 s32 item1_uses = 65536 - (u32) item1.wear;
618 s32 item2_uses = 65536 - (u32) item2.wear;
619 s32 new_uses = item1_uses + item2_uses;
620 s32 new_wear = 65536 - new_uses + floor(additional_wear * 65536 + 0.5);
621 if(new_wear >= 65536)
626 ItemStack repaired = item1;
627 repaired.wear = new_wear;
631 std::string CraftDefinitionToolRepair::getName() const
636 bool CraftDefinitionToolRepair::check(const CraftInput &input, IGameDef *gamedef) const
638 if(input.method != CRAFT_METHOD_NORMAL)
643 for(std::vector<ItemStack>::const_iterator
644 i = input.items.begin();
645 i != input.items.end(); i++)
651 else if(item2.empty())
657 ItemStack repaired = craftToolRepair(item1, item2, additional_wear, gamedef);
658 return !repaired.empty();
661 CraftOutput CraftDefinitionToolRepair::getOutput(const CraftInput &input, IGameDef *gamedef) const
665 for(std::vector<ItemStack>::const_iterator
666 i = input.items.begin();
667 i != input.items.end(); i++)
673 else if(item2.empty())
677 ItemStack repaired = craftToolRepair(item1, item2, additional_wear, gamedef);
678 return CraftOutput(repaired.getItemString(), 0);
681 CraftInput CraftDefinitionToolRepair::getInput(const CraftOutput &output, IGameDef *gamedef) const
683 std::vector<ItemStack> stack;
684 stack.push_back(ItemStack());
685 return CraftInput(CRAFT_METHOD_COOKING,additional_wear,stack);
688 void CraftDefinitionToolRepair::decrementInput(CraftInput &input, IGameDef *gamedef) const
690 craftDecrementInput(input, gamedef);
693 std::string CraftDefinitionToolRepair::dump() const
695 std::ostringstream os(std::ios::binary);
696 os<<"(toolrepair, additional_wear="<<additional_wear<<")";
700 void CraftDefinitionToolRepair::serializeBody(std::ostream &os) const
702 writeF1000(os, additional_wear);
705 void CraftDefinitionToolRepair::deSerializeBody(std::istream &is, int version)
707 if(version != 1) throw SerializationError(
708 "unsupported CraftDefinitionToolRepair version");
709 additional_wear = readF1000(is);
713 CraftDefinitionCooking
716 std::string CraftDefinitionCooking::getName() const
721 bool CraftDefinitionCooking::check(const CraftInput &input, IGameDef *gamedef) const
723 if(input.method != CRAFT_METHOD_COOKING)
726 // Filter empty items out of input
727 std::vector<std::string> input_filtered;
728 for(std::vector<ItemStack>::const_iterator
729 i = input.items.begin();
730 i != input.items.end(); i++)
733 input_filtered.push_back(i->name);
736 // If there is a wrong number of items in input, no match
737 if(input_filtered.size() != 1){
738 /*dstream<<"Number of input items ("<<input_filtered.size()
739 <<") does not match recipe size (1) "
740 <<"of cooking recipe with output="<<output<<std::endl;*/
744 // Check the single input item
745 return inputItemMatchesRecipe(input_filtered[0], recipe, gamedef->idef());
748 CraftOutput CraftDefinitionCooking::getOutput(const CraftInput &input, IGameDef *gamedef) const
750 return CraftOutput(output, cooktime);
753 CraftInput CraftDefinitionCooking::getInput(const CraftOutput &output, IGameDef *gamedef) const
755 std::vector<std::string> rec;
756 rec.push_back(recipe);
757 return CraftInput(CRAFT_METHOD_COOKING,cooktime,craftGetItems(rec,gamedef));
760 void CraftDefinitionCooking::decrementInput(CraftInput &input, IGameDef *gamedef) const
762 craftDecrementOrReplaceInput(input, replacements, gamedef);
765 std::string CraftDefinitionCooking::dump() const
767 std::ostringstream os(std::ios::binary);
768 os<<"(cooking, output=\""<<output
769 <<"\", recipe=\""<<recipe
770 <<"\", cooktime="<<cooktime<<")"
771 <<", replacements="<<replacements.dump()<<")";
775 void CraftDefinitionCooking::serializeBody(std::ostream &os) const
777 os<<serializeString(output);
778 os<<serializeString(recipe);
779 writeF1000(os, cooktime);
780 replacements.serialize(os);
783 void CraftDefinitionCooking::deSerializeBody(std::istream &is, int version)
785 if(version != 1) throw SerializationError(
786 "unsupported CraftDefinitionCooking version");
787 output = deSerializeString(is);
788 recipe = deSerializeString(is);
789 cooktime = readF1000(is);
790 replacements.deSerialize(is);
797 std::string CraftDefinitionFuel::getName() const
802 bool CraftDefinitionFuel::check(const CraftInput &input, IGameDef *gamedef) const
804 if(input.method != CRAFT_METHOD_FUEL)
807 // Filter empty items out of input
808 std::vector<std::string> input_filtered;
809 for(std::vector<ItemStack>::const_iterator
810 i = input.items.begin();
811 i != input.items.end(); i++)
814 input_filtered.push_back(i->name);
817 // If there is a wrong number of items in input, no match
818 if(input_filtered.size() != 1){
819 /*dstream<<"Number of input items ("<<input_filtered.size()
820 <<") does not match recipe size (1) "
821 <<"of fuel recipe with burntime="<<burntime<<std::endl;*/
825 // Check the single input item
826 return inputItemMatchesRecipe(input_filtered[0], recipe, gamedef->idef());
829 CraftOutput CraftDefinitionFuel::getOutput(const CraftInput &input, IGameDef *gamedef) const
831 return CraftOutput("", burntime);
834 CraftInput CraftDefinitionFuel::getInput(const CraftOutput &output, IGameDef *gamedef) const
836 std::vector<std::string> rec;
837 rec.push_back(recipe);
838 return CraftInput(CRAFT_METHOD_COOKING,(int)burntime,craftGetItems(rec,gamedef));
841 void CraftDefinitionFuel::decrementInput(CraftInput &input, IGameDef *gamedef) const
843 craftDecrementOrReplaceInput(input, replacements, gamedef);
846 std::string CraftDefinitionFuel::dump() const
848 std::ostringstream os(std::ios::binary);
849 os<<"(fuel, recipe=\""<<recipe
850 <<"\", burntime="<<burntime<<")"
851 <<", replacements="<<replacements.dump()<<")";
855 void CraftDefinitionFuel::serializeBody(std::ostream &os) const
857 os<<serializeString(recipe);
858 writeF1000(os, burntime);
859 replacements.serialize(os);
862 void CraftDefinitionFuel::deSerializeBody(std::istream &is, int version)
864 if(version != 1) throw SerializationError(
865 "unsupported CraftDefinitionFuel version");
866 recipe = deSerializeString(is);
867 burntime = readF1000(is);
868 replacements.deSerialize(is);
872 Craft definition manager
875 class CCraftDefManager: public IWritableCraftDefManager
878 virtual ~CCraftDefManager()
882 virtual bool getCraftResult(CraftInput &input, CraftOutput &output,
883 bool decrementInput, IGameDef *gamedef) const
888 // If all input items are empty, abort.
889 bool all_empty = true;
890 for(std::vector<ItemStack>::const_iterator
891 i = input.items.begin();
892 i != input.items.end(); i++)
903 // Walk crafting definitions from back to front, so that later
904 // definitions can override earlier ones.
905 for(std::vector<CraftDefinition*>::const_reverse_iterator
906 i = m_craft_definitions.rbegin();
907 i != m_craft_definitions.rend(); i++)
909 CraftDefinition *def = *i;
911 /*infostream<<"Checking "<<input.dump()<<std::endl
912 <<" against "<<def->dump()<<std::endl;*/
915 if(def->check(input, gamedef))
917 // Get output, then decrement input (if requested)
918 output = def->getOutput(input, gamedef);
920 def->decrementInput(input, gamedef);
924 catch(SerializationError &e)
926 errorstream<<"getCraftResult: ERROR: "
927 <<"Serialization error in recipe "
928 <<def->dump()<<std::endl;
929 // then go on with the next craft definition
934 virtual bool getCraftRecipe(CraftInput &input, CraftOutput &output,
935 IGameDef *gamedef) const
941 // If output item is empty, abort.
942 if(output.item.empty())
945 // Walk crafting definitions from back to front, so that later
946 // definitions can override earlier ones.
947 for(std::vector<CraftDefinition*>::const_reverse_iterator
948 i = m_craft_definitions.rbegin();
949 i != m_craft_definitions.rend(); i++)
951 CraftDefinition *def = *i;
953 /*infostream<<"Checking "<<input.dump()<<std::endl
954 <<" against "<<def->dump()<<std::endl;*/
957 tmpout = def->getOutput(input, gamedef);
958 if((tmpout.item.substr(0,output.item.length()) == output.item) &&
959 ((tmpout.item[output.item.length()] == 0) ||
960 (tmpout.item[output.item.length()] == ' ')))
962 // Get output, then decrement input (if requested)
963 input = def->getInput(output, gamedef);
967 catch(SerializationError &e)
969 errorstream<<"getCraftResult: ERROR: "
970 <<"Serialization error in recipe "
971 <<def->dump()<<std::endl;
972 // then go on with the next craft definition
977 virtual std::vector<CraftDefinition*> getCraftRecipes(CraftOutput &output,
978 IGameDef *gamedef) const
980 std::vector<CraftDefinition*> recipes_list;
986 for(std::vector<CraftDefinition*>::const_reverse_iterator
987 i = m_craft_definitions.rbegin();
988 i != m_craft_definitions.rend(); i++)
990 CraftDefinition *def = *i;
992 /*infostream<<"Checking "<<input.dump()<<std::endl
993 <<" against "<<def->dump()<<std::endl;*/
996 tmpout = def->getOutput(input, gamedef);
997 if(tmpout.item.substr(0,output.item.length()) == output.item)
999 // Get output, then decrement input (if requested)
1000 input = def->getInput(output, gamedef);
1001 recipes_list.push_back(*i);
1004 catch(SerializationError &e)
1006 errorstream<<"getCraftResult: ERROR: "
1007 <<"Serialization error in recipe "
1008 <<def->dump()<<std::endl;
1009 // then go on with the next craft definition
1012 return recipes_list;
1014 virtual std::string dump() const
1016 std::ostringstream os(std::ios::binary);
1017 os<<"Crafting definitions:\n";
1018 for(std::vector<CraftDefinition*>::const_iterator
1019 i = m_craft_definitions.begin();
1020 i != m_craft_definitions.end(); i++)
1022 os<<(*i)->dump()<<"\n";
1026 virtual void registerCraft(CraftDefinition *def)
1028 verbosestream<<"registerCraft: registering craft definition: "
1029 <<def->dump()<<std::endl;
1030 m_craft_definitions.push_back(def);
1032 virtual void clear()
1034 for(std::vector<CraftDefinition*>::iterator
1035 i = m_craft_definitions.begin();
1036 i != m_craft_definitions.end(); i++){
1039 m_craft_definitions.clear();
1041 virtual void serialize(std::ostream &os) const
1043 writeU8(os, 0); // version
1044 u16 count = m_craft_definitions.size();
1045 writeU16(os, count);
1046 for(std::vector<CraftDefinition*>::const_iterator
1047 i = m_craft_definitions.begin();
1048 i != m_craft_definitions.end(); i++){
1049 CraftDefinition *def = *i;
1050 // Serialize wrapped in a string
1051 std::ostringstream tmp_os(std::ios::binary);
1052 def->serialize(tmp_os);
1053 os<<serializeString(tmp_os.str());
1056 virtual void deSerialize(std::istream &is)
1061 int version = readU8(is);
1062 if(version != 0) throw SerializationError(
1063 "unsupported CraftDefManager version");
1064 u16 count = readU16(is);
1065 for(u16 i=0; i<count; i++){
1066 // Deserialize a string and grab a CraftDefinition from it
1067 std::istringstream tmp_is(deSerializeString(is), std::ios::binary);
1068 CraftDefinition *def = CraftDefinition::deSerialize(tmp_is);
1074 std::vector<CraftDefinition*> m_craft_definitions;
1077 IWritableCraftDefManager* createCraftDefManager()
1079 return new CCraftDefManager();