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"
32 // Check if input matches recipe
33 // Takes recipe groups into account
34 static bool inputItemMatchesRecipe(const std::string &inp_name,
35 const std::string &rec_name, IItemDefManager *idef)
38 if(inp_name == rec_name)
42 if(rec_name.substr(0,6) == "group:" && idef->isKnown(inp_name)){
43 const struct ItemDefinition &def = idef->get(inp_name);
44 Strfnd f(rec_name.substr(6));
45 bool all_groups_match = true;
47 std::string check_group = f.next(",");
48 if(itemgroup_get(def.groups, check_group) == 0){
49 all_groups_match = false;
61 // Deserialize an itemstring then return the name of the item
62 static std::string craftGetItemName(const std::string &itemstring, IGameDef *gamedef)
65 item.deSerialize(itemstring, gamedef->idef());
69 // (mapcar craftGetItemName itemstrings)
70 static std::vector<std::string> craftGetItemNames(
71 const std::vector<std::string> &itemstrings, IGameDef *gamedef)
73 std::vector<std::string> result;
74 for(std::vector<std::string>::const_iterator
75 i = itemstrings.begin();
76 i != itemstrings.end(); i++)
78 result.push_back(craftGetItemName(*i, gamedef));
83 // Get name of each item, and return them as a new list.
84 static std::vector<std::string> craftGetItemNames(
85 const std::vector<ItemStack> &items, IGameDef *gamedef)
87 std::vector<std::string> result;
88 for(std::vector<ItemStack>::const_iterator
90 i != items.end(); i++)
92 result.push_back(i->name);
97 // convert a list of item names, to ItemStacks.
98 static std::vector<ItemStack> craftGetItems(
99 const std::vector<std::string> &items, IGameDef *gamedef)
101 std::vector<ItemStack> result;
102 for(std::vector<std::string>::const_iterator
104 i != items.end(); i++)
106 result.push_back(ItemStack(std::string(*i),(u16)1,(u16)0,"",gamedef->getItemDefManager()));
111 // Compute bounding rectangle given a matrix of items
112 // Returns false if every item is ""
113 static bool craftGetBounds(const std::vector<std::string> &items, unsigned int width,
114 unsigned int &min_x, unsigned int &max_x,
115 unsigned int &min_y, unsigned int &max_y)
117 bool success = false;
120 for(std::vector<std::string>::const_iterator
122 i != items.end(); i++)
124 if(*i != "") // Is this an actual item?
128 // This is the first nonempty item
135 if(x < min_x) min_x = x;
136 if(x > max_x) max_x = x;
137 if(y < min_y) min_y = y;
138 if(y > max_y) max_y = y;
154 // This became useless when group support was added to shapeless recipes
155 // Convert a list of item names to a multiset
156 static std::multiset<std::string> craftMakeMultiset(const std::vector<std::string> &names)
158 std::multiset<std::string> set;
159 for(std::vector<std::string>::const_iterator
161 i != names.end(); i++)
170 // Removes 1 from each item stack
171 static void craftDecrementInput(CraftInput &input, IGameDef *gamedef)
173 for(std::vector<ItemStack>::iterator
174 i = input.items.begin();
175 i != input.items.end(); i++)
182 // Removes 1 from each item stack with replacement support
183 // Example: if replacements contains the pair ("bucket:bucket_water", "bucket:bucket_empty"),
184 // a water bucket will not be removed but replaced by an empty bucket.
185 static void craftDecrementOrReplaceInput(CraftInput &input,
186 const CraftReplacements &replacements,
189 if(replacements.pairs.empty())
191 craftDecrementInput(input, gamedef);
195 // Make a copy of the replacements pair list
196 std::vector<std::pair<std::string, std::string> > pairs = replacements.pairs;
198 for(std::vector<ItemStack>::iterator
199 i = input.items.begin();
200 i != input.items.end(); i++)
204 // Find an appropriate replacement
205 bool found_replacement = false;
206 for(std::vector<std::pair<std::string, std::string> >::iterator
208 j != pairs.end(); j++)
211 from_item.deSerialize(j->first, gamedef->idef());
212 if(i->name == from_item.name)
214 i->deSerialize(j->second, gamedef->idef());
215 found_replacement = true;
220 // No replacement was found, simply decrement count to zero
221 if(!found_replacement)
224 else if(i->count >= 2)
226 // Ignore replacements for items with count >= 2
232 // Dump an itemstring matrix
233 static std::string craftDumpMatrix(const std::vector<std::string> &items,
236 std::ostringstream os(std::ios::binary);
239 for(std::vector<std::string>::const_iterator
241 i != items.end(); i++, x++)
252 os<<"\""<<(*i)<<"\"";
258 // Dump an item matrix
259 std::string craftDumpMatrix(const std::vector<ItemStack> &items,
262 std::ostringstream os(std::ios::binary);
265 for(std::vector<ItemStack>::const_iterator
267 i != items.end(); i++, x++)
278 os<<"\""<<(i->getItemString())<<"\"";
289 std::string CraftInput::dump() const
291 std::ostringstream os(std::ios::binary);
292 os<<"(method="<<((int)method)<<", items="<<craftDumpMatrix(items, width)<<")";
300 std::string CraftOutput::dump() const
302 std::ostringstream os(std::ios::binary);
303 os<<"(item=\""<<item<<"\", time="<<time<<")";
311 std::string CraftReplacements::dump() const
313 std::ostringstream os(std::ios::binary);
315 const char *sep = "";
316 for(std::vector<std::pair<std::string, std::string> >::const_iterator
318 i != pairs.end(); i++)
320 os<<sep<<"\""<<(i->first)<<"\"=>\""<<(i->second)<<"\"";
327 void CraftReplacements::serialize(std::ostream &os) const
329 writeU16(os, pairs.size());
330 for(u32 i=0; i<pairs.size(); i++)
332 os<<serializeString(pairs[i].first);
333 os<<serializeString(pairs[i].second);
337 void CraftReplacements::deSerialize(std::istream &is)
340 u32 count = readU16(is);
341 for(u32 i=0; i<count; i++)
343 std::string first = deSerializeString(is);
344 std::string second = deSerializeString(is);
345 pairs.push_back(std::make_pair(first, second));
353 void CraftDefinition::serialize(std::ostream &os) const
355 writeU8(os, 1); // version
356 os<<serializeString(getName());
360 CraftDefinition* CraftDefinition::deSerialize(std::istream &is)
362 int version = readU8(is);
363 if(version != 1) throw SerializationError(
364 "unsupported CraftDefinition version");
365 std::string name = deSerializeString(is);
366 CraftDefinition *def = NULL;
369 def = new CraftDefinitionShaped;
371 else if(name == "shapeless")
373 def = new CraftDefinitionShapeless;
375 else if(name == "toolrepair")
377 def = new CraftDefinitionToolRepair;
379 else if(name == "cooking")
381 def = new CraftDefinitionCooking;
383 else if(name == "fuel")
385 def = new CraftDefinitionFuel;
389 infostream<<"Unknown CraftDefinition name=\""<<name<<"\""<<std::endl;
390 throw SerializationError("Unknown CraftDefinition name");
392 def->deSerializeBody(is, version);
397 CraftDefinitionShaped
400 std::string CraftDefinitionShaped::getName() const
405 bool CraftDefinitionShaped::check(const CraftInput &input, IGameDef *gamedef) const
407 if(input.method != CRAFT_METHOD_NORMAL)
410 // Get input item matrix
411 std::vector<std::string> inp_names = craftGetItemNames(input.items, gamedef);
412 unsigned int inp_width = input.width;
415 while(inp_names.size() % inp_width != 0)
416 inp_names.push_back("");
419 unsigned int inp_min_x=0, inp_max_x=0, inp_min_y=0, inp_max_y=0;
420 if(!craftGetBounds(inp_names, inp_width, inp_min_x, inp_max_x, inp_min_y, inp_max_y))
421 return false; // it was empty
423 // Get recipe item matrix
424 std::vector<std::string> rec_names = craftGetItemNames(recipe, gamedef);
425 unsigned int rec_width = width;
428 while(rec_names.size() % rec_width != 0)
429 rec_names.push_back("");
432 unsigned int rec_min_x=0, rec_max_x=0, rec_min_y=0, rec_max_y=0;
433 if(!craftGetBounds(rec_names, rec_width, rec_min_x, rec_max_x, rec_min_y, rec_max_y))
434 return false; // it was empty
437 if(inp_max_x - inp_min_x != rec_max_x - rec_min_x)
439 if(inp_max_y - inp_min_y != rec_max_y - rec_min_y)
442 // Verify that all item names in the bounding box are equal
443 unsigned int w = inp_max_x - inp_min_x + 1;
444 unsigned int h = inp_max_y - inp_min_y + 1;
445 for(unsigned int y=0; y<h; y++)
446 for(unsigned int x=0; x<w; x++)
448 unsigned int inp_x = inp_min_x + x;
449 unsigned int inp_y = inp_min_y + y;
450 unsigned int rec_x = rec_min_x + x;
451 unsigned int rec_y = rec_min_y + y;
453 if(!inputItemMatchesRecipe(
454 inp_names[inp_y * inp_width + inp_x],
455 rec_names[rec_y * rec_width + rec_x], gamedef->idef())
464 CraftOutput CraftDefinitionShaped::getOutput(const CraftInput &input, IGameDef *gamedef) const
466 return CraftOutput(output, 0);
469 CraftInput CraftDefinitionShaped::getInput(const CraftOutput &output, IGameDef *gamedef) const
471 return CraftInput(CRAFT_METHOD_NORMAL,width,craftGetItems(recipe,gamedef));
474 void CraftDefinitionShaped::decrementInput(CraftInput &input, IGameDef *gamedef) const
476 craftDecrementOrReplaceInput(input, replacements, gamedef);
479 std::string CraftDefinitionShaped::dump() const
481 std::ostringstream os(std::ios::binary);
482 os<<"(shaped, output=\""<<output
483 <<"\", recipe="<<craftDumpMatrix(recipe, width)
484 <<", replacements="<<replacements.dump()<<")";
488 void CraftDefinitionShaped::serializeBody(std::ostream &os) const
490 os<<serializeString(output);
492 writeU16(os, recipe.size());
493 for(u32 i=0; i<recipe.size(); i++)
494 os<<serializeString(recipe[i]);
495 replacements.serialize(os);
498 void CraftDefinitionShaped::deSerializeBody(std::istream &is, int version)
500 if(version != 1) throw SerializationError(
501 "unsupported CraftDefinitionShaped version");
502 output = deSerializeString(is);
505 u32 count = readU16(is);
506 for(u32 i=0; i<count; i++)
507 recipe.push_back(deSerializeString(is));
508 replacements.deSerialize(is);
512 CraftDefinitionShapeless
515 std::string CraftDefinitionShapeless::getName() const
520 bool CraftDefinitionShapeless::check(const CraftInput &input, IGameDef *gamedef) const
522 if(input.method != CRAFT_METHOD_NORMAL)
525 // Filter empty items out of input
526 std::vector<std::string> input_filtered;
527 for(std::vector<ItemStack>::const_iterator
528 i = input.items.begin();
529 i != input.items.end(); i++)
532 input_filtered.push_back(i->name);
535 // If there is a wrong number of items in input, no match
536 if(input_filtered.size() != recipe.size()){
537 /*dstream<<"Number of input items ("<<input_filtered.size()
538 <<") does not match recipe size ("<<recipe.size()<<") "
539 <<"of recipe with output="<<output<<std::endl;*/
543 // Try with all permutations of the recipe
544 std::vector<std::string> recipe_copy = recipe;
545 // Start from the lexicographically first permutation (=sorted)
546 std::sort(recipe_copy.begin(), recipe_copy.end());
547 //while(std::prev_permutation(recipe_copy.begin(), recipe_copy.end())){}
549 // If all items match, the recipe matches
550 bool all_match = true;
551 //dstream<<"Testing recipe (output="<<output<<"):";
552 for(size_t i=0; i<recipe.size(); i++){
553 //dstream<<" ("<<input_filtered[i]<<" == "<<recipe_copy[i]<<")";
554 if(!inputItemMatchesRecipe(input_filtered[i], recipe_copy[i],
560 //dstream<<" -> match="<<all_match<<std::endl;
563 }while(std::next_permutation(recipe_copy.begin(), recipe_copy.end()));
568 CraftOutput CraftDefinitionShapeless::getOutput(const CraftInput &input, IGameDef *gamedef) const
570 return CraftOutput(output, 0);
573 CraftInput CraftDefinitionShapeless::getInput(const CraftOutput &output, IGameDef *gamedef) const
575 return CraftInput(CRAFT_METHOD_NORMAL,0,craftGetItems(recipe,gamedef));
578 void CraftDefinitionShapeless::decrementInput(CraftInput &input, IGameDef *gamedef) const
580 craftDecrementOrReplaceInput(input, replacements, gamedef);
583 std::string CraftDefinitionShapeless::dump() const
585 std::ostringstream os(std::ios::binary);
586 os<<"(shapeless, output=\""<<output
587 <<"\", recipe="<<craftDumpMatrix(recipe, recipe.size())
588 <<", replacements="<<replacements.dump()<<")";
592 void CraftDefinitionShapeless::serializeBody(std::ostream &os) const
594 os<<serializeString(output);
595 writeU16(os, recipe.size());
596 for(u32 i=0; i<recipe.size(); i++)
597 os<<serializeString(recipe[i]);
598 replacements.serialize(os);
601 void CraftDefinitionShapeless::deSerializeBody(std::istream &is, int version)
603 if(version != 1) throw SerializationError(
604 "unsupported CraftDefinitionShapeless version");
605 output = deSerializeString(is);
607 u32 count = readU16(is);
608 for(u32 i=0; i<count; i++)
609 recipe.push_back(deSerializeString(is));
610 replacements.deSerialize(is);
614 CraftDefinitionToolRepair
617 static ItemStack craftToolRepair(
618 const ItemStack &item1,
619 const ItemStack &item2,
620 float additional_wear,
623 IItemDefManager *idef = gamedef->idef();
624 if(item1.count != 1 || item2.count != 1 || item1.name != item2.name
625 || idef->get(item1.name).type != ITEM_TOOL
626 || idef->get(item2.name).type != ITEM_TOOL)
632 s32 item1_uses = 65536 - (u32) item1.wear;
633 s32 item2_uses = 65536 - (u32) item2.wear;
634 s32 new_uses = item1_uses + item2_uses;
635 s32 new_wear = 65536 - new_uses + floor(additional_wear * 65536 + 0.5);
636 if(new_wear >= 65536)
641 ItemStack repaired = item1;
642 repaired.wear = new_wear;
646 std::string CraftDefinitionToolRepair::getName() const
651 bool CraftDefinitionToolRepair::check(const CraftInput &input, IGameDef *gamedef) const
653 if(input.method != CRAFT_METHOD_NORMAL)
658 for(std::vector<ItemStack>::const_iterator
659 i = input.items.begin();
660 i != input.items.end(); i++)
666 else if(item2.empty())
672 ItemStack repaired = craftToolRepair(item1, item2, additional_wear, gamedef);
673 return !repaired.empty();
676 CraftOutput CraftDefinitionToolRepair::getOutput(const CraftInput &input, IGameDef *gamedef) const
680 for(std::vector<ItemStack>::const_iterator
681 i = input.items.begin();
682 i != input.items.end(); i++)
688 else if(item2.empty())
692 ItemStack repaired = craftToolRepair(item1, item2, additional_wear, gamedef);
693 return CraftOutput(repaired.getItemString(), 0);
696 CraftInput CraftDefinitionToolRepair::getInput(const CraftOutput &output, IGameDef *gamedef) const
698 std::vector<ItemStack> stack;
699 stack.push_back(ItemStack());
700 return CraftInput(CRAFT_METHOD_COOKING,additional_wear,stack);
703 void CraftDefinitionToolRepair::decrementInput(CraftInput &input, IGameDef *gamedef) const
705 craftDecrementInput(input, gamedef);
708 std::string CraftDefinitionToolRepair::dump() const
710 std::ostringstream os(std::ios::binary);
711 os<<"(toolrepair, additional_wear="<<additional_wear<<")";
715 void CraftDefinitionToolRepair::serializeBody(std::ostream &os) const
717 writeF1000(os, additional_wear);
720 void CraftDefinitionToolRepair::deSerializeBody(std::istream &is, int version)
722 if(version != 1) throw SerializationError(
723 "unsupported CraftDefinitionToolRepair version");
724 additional_wear = readF1000(is);
728 CraftDefinitionCooking
731 std::string CraftDefinitionCooking::getName() const
736 bool CraftDefinitionCooking::check(const CraftInput &input, IGameDef *gamedef) const
738 if(input.method != CRAFT_METHOD_COOKING)
741 // Filter empty items out of input
742 std::vector<std::string> input_filtered;
743 for(std::vector<ItemStack>::const_iterator
744 i = input.items.begin();
745 i != input.items.end(); i++)
748 input_filtered.push_back(i->name);
751 // If there is a wrong number of items in input, no match
752 if(input_filtered.size() != 1){
753 /*dstream<<"Number of input items ("<<input_filtered.size()
754 <<") does not match recipe size (1) "
755 <<"of cooking recipe with output="<<output<<std::endl;*/
759 // Check the single input item
760 return inputItemMatchesRecipe(input_filtered[0], recipe, gamedef->idef());
763 CraftOutput CraftDefinitionCooking::getOutput(const CraftInput &input, IGameDef *gamedef) const
765 return CraftOutput(output, cooktime);
768 CraftInput CraftDefinitionCooking::getInput(const CraftOutput &output, IGameDef *gamedef) const
770 std::vector<std::string> rec;
771 rec.push_back(recipe);
772 return CraftInput(CRAFT_METHOD_COOKING,cooktime,craftGetItems(rec,gamedef));
775 void CraftDefinitionCooking::decrementInput(CraftInput &input, IGameDef *gamedef) const
777 craftDecrementOrReplaceInput(input, replacements, gamedef);
780 std::string CraftDefinitionCooking::dump() const
782 std::ostringstream os(std::ios::binary);
783 os<<"(cooking, output=\""<<output
784 <<"\", recipe=\""<<recipe
785 <<"\", cooktime="<<cooktime<<")"
786 <<", replacements="<<replacements.dump()<<")";
790 void CraftDefinitionCooking::serializeBody(std::ostream &os) const
792 os<<serializeString(output);
793 os<<serializeString(recipe);
794 writeF1000(os, cooktime);
795 replacements.serialize(os);
798 void CraftDefinitionCooking::deSerializeBody(std::istream &is, int version)
800 if(version != 1) throw SerializationError(
801 "unsupported CraftDefinitionCooking version");
802 output = deSerializeString(is);
803 recipe = deSerializeString(is);
804 cooktime = readF1000(is);
805 replacements.deSerialize(is);
812 std::string CraftDefinitionFuel::getName() const
817 bool CraftDefinitionFuel::check(const CraftInput &input, IGameDef *gamedef) const
819 if(input.method != CRAFT_METHOD_FUEL)
822 // Filter empty items out of input
823 std::vector<std::string> input_filtered;
824 for(std::vector<ItemStack>::const_iterator
825 i = input.items.begin();
826 i != input.items.end(); i++)
829 input_filtered.push_back(i->name);
832 // If there is a wrong number of items in input, no match
833 if(input_filtered.size() != 1){
834 /*dstream<<"Number of input items ("<<input_filtered.size()
835 <<") does not match recipe size (1) "
836 <<"of fuel recipe with burntime="<<burntime<<std::endl;*/
840 // Check the single input item
841 return inputItemMatchesRecipe(input_filtered[0], recipe, gamedef->idef());
844 CraftOutput CraftDefinitionFuel::getOutput(const CraftInput &input, IGameDef *gamedef) const
846 return CraftOutput("", burntime);
849 CraftInput CraftDefinitionFuel::getInput(const CraftOutput &output, IGameDef *gamedef) const
851 std::vector<std::string> rec;
852 rec.push_back(recipe);
853 return CraftInput(CRAFT_METHOD_COOKING,(int)burntime,craftGetItems(rec,gamedef));
856 void CraftDefinitionFuel::decrementInput(CraftInput &input, IGameDef *gamedef) const
858 craftDecrementOrReplaceInput(input, replacements, gamedef);
861 std::string CraftDefinitionFuel::dump() const
863 std::ostringstream os(std::ios::binary);
864 os<<"(fuel, recipe=\""<<recipe
865 <<"\", burntime="<<burntime<<")"
866 <<", replacements="<<replacements.dump()<<")";
870 void CraftDefinitionFuel::serializeBody(std::ostream &os) const
872 os<<serializeString(recipe);
873 writeF1000(os, burntime);
874 replacements.serialize(os);
877 void CraftDefinitionFuel::deSerializeBody(std::istream &is, int version)
879 if(version != 1) throw SerializationError(
880 "unsupported CraftDefinitionFuel version");
881 recipe = deSerializeString(is);
882 burntime = readF1000(is);
883 replacements.deSerialize(is);
887 Craft definition manager
890 class CCraftDefManager: public IWritableCraftDefManager
893 virtual ~CCraftDefManager()
897 virtual bool getCraftResult(CraftInput &input, CraftOutput &output,
898 bool decrementInput, IGameDef *gamedef) const
903 // If all input items are empty, abort.
904 bool all_empty = true;
905 for(std::vector<ItemStack>::const_iterator
906 i = input.items.begin();
907 i != input.items.end(); i++)
918 // Walk crafting definitions from back to front, so that later
919 // definitions can override earlier ones.
920 for(std::vector<CraftDefinition*>::const_reverse_iterator
921 i = m_craft_definitions.rbegin();
922 i != m_craft_definitions.rend(); i++)
924 CraftDefinition *def = *i;
926 /*infostream<<"Checking "<<input.dump()<<std::endl
927 <<" against "<<def->dump()<<std::endl;*/
930 if(def->check(input, gamedef))
932 // Get output, then decrement input (if requested)
933 output = def->getOutput(input, gamedef);
935 def->decrementInput(input, gamedef);
939 catch(SerializationError &e)
941 errorstream<<"getCraftResult: ERROR: "
942 <<"Serialization error in recipe "
943 <<def->dump()<<std::endl;
944 // then go on with the next craft definition
949 virtual bool getCraftRecipe(CraftInput &input, CraftOutput &output,
950 IGameDef *gamedef) const
956 // If output item is empty, abort.
957 if(output.item.empty())
960 // Walk crafting definitions from back to front, so that later
961 // definitions can override earlier ones.
962 for(std::vector<CraftDefinition*>::const_reverse_iterator
963 i = m_craft_definitions.rbegin();
964 i != m_craft_definitions.rend(); i++)
966 CraftDefinition *def = *i;
968 /*infostream<<"Checking "<<input.dump()<<std::endl
969 <<" against "<<def->dump()<<std::endl;*/
972 tmpout = def->getOutput(input, gamedef);
973 if(tmpout.item.substr(0,output.item.length()) == output.item)
975 // Get output, then decrement input (if requested)
976 input = def->getInput(output, gamedef);
980 catch(SerializationError &e)
982 errorstream<<"getCraftResult: ERROR: "
983 <<"Serialization error in recipe "
984 <<def->dump()<<std::endl;
985 // then go on with the next craft definition
990 virtual std::vector<CraftDefinition*> getCraftRecipes(CraftOutput &output,
991 IGameDef *gamedef) const
993 std::vector<CraftDefinition*> recipes_list;
999 for(std::vector<CraftDefinition*>::const_reverse_iterator
1000 i = m_craft_definitions.rbegin();
1001 i != m_craft_definitions.rend(); i++)
1003 CraftDefinition *def = *i;
1005 /*infostream<<"Checking "<<input.dump()<<std::endl
1006 <<" against "<<def->dump()<<std::endl;*/
1009 tmpout = def->getOutput(input, gamedef);
1010 if(tmpout.item.substr(0,output.item.length()) == output.item)
1012 // Get output, then decrement input (if requested)
1013 input = def->getInput(output, gamedef);
1014 recipes_list.push_back(*i);
1017 catch(SerializationError &e)
1019 errorstream<<"getCraftResult: ERROR: "
1020 <<"Serialization error in recipe "
1021 <<def->dump()<<std::endl;
1022 // then go on with the next craft definition
1025 return recipes_list;
1027 virtual std::string dump() const
1029 std::ostringstream os(std::ios::binary);
1030 os<<"Crafting definitions:\n";
1031 for(std::vector<CraftDefinition*>::const_iterator
1032 i = m_craft_definitions.begin();
1033 i != m_craft_definitions.end(); i++)
1035 os<<(*i)->dump()<<"\n";
1039 virtual void registerCraft(CraftDefinition *def)
1041 verbosestream<<"registerCraft: registering craft definition: "
1042 <<def->dump()<<std::endl;
1043 m_craft_definitions.push_back(def);
1045 virtual void clear()
1047 for(std::vector<CraftDefinition*>::iterator
1048 i = m_craft_definitions.begin();
1049 i != m_craft_definitions.end(); i++){
1052 m_craft_definitions.clear();
1054 virtual void serialize(std::ostream &os) const
1056 writeU8(os, 0); // version
1057 u16 count = m_craft_definitions.size();
1058 writeU16(os, count);
1059 for(std::vector<CraftDefinition*>::const_iterator
1060 i = m_craft_definitions.begin();
1061 i != m_craft_definitions.end(); i++){
1062 CraftDefinition *def = *i;
1063 // Serialize wrapped in a string
1064 std::ostringstream tmp_os(std::ios::binary);
1065 def->serialize(tmp_os);
1066 os<<serializeString(tmp_os.str());
1069 virtual void deSerialize(std::istream &is)
1074 int version = readU8(is);
1075 if(version != 0) throw SerializationError(
1076 "unsupported CraftDefManager version");
1077 u16 count = readU16(is);
1078 for(u16 i=0; i<count; i++){
1079 // Deserialize a string and grab a CraftDefinition from it
1080 std::istringstream tmp_is(deSerializeString(is), std::ios::binary);
1081 CraftDefinition *def = CraftDefinition::deSerialize(tmp_is);
1087 std::vector<CraftDefinition*> m_craft_definitions;
1090 IWritableCraftDefManager* createCraftDefManager()
1092 return new CCraftDefManager();