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)
423 if(inp_max_y - inp_min_y != rec_max_y - rec_min_y)
426 // Verify that all item names in the bounding box are equal
427 unsigned int w = inp_max_x - inp_min_x + 1;
428 unsigned int h = inp_max_y - inp_min_y + 1;
429 for(unsigned int y=0; y<h; y++)
430 for(unsigned int x=0; x<w; x++)
432 unsigned int inp_x = inp_min_x + x;
433 unsigned int inp_y = inp_min_y + y;
434 unsigned int rec_x = rec_min_x + x;
435 unsigned int rec_y = rec_min_y + y;
437 if(!inputItemMatchesRecipe(
438 inp_names[inp_y * inp_width + inp_x],
439 rec_names[rec_y * rec_width + rec_x], gamedef->idef())
448 CraftOutput CraftDefinitionShaped::getOutput(const CraftInput &input, IGameDef *gamedef) const
450 return CraftOutput(output, 0);
453 CraftInput CraftDefinitionShaped::getInput(const CraftOutput &output, IGameDef *gamedef) const
455 return CraftInput(CRAFT_METHOD_NORMAL,width,craftGetItems(recipe,gamedef));
458 void CraftDefinitionShaped::decrementInput(CraftInput &input, IGameDef *gamedef) const
460 craftDecrementOrReplaceInput(input, replacements, gamedef);
463 std::string CraftDefinitionShaped::dump() const
465 std::ostringstream os(std::ios::binary);
466 os<<"(shaped, output=\""<<output
467 <<"\", recipe="<<craftDumpMatrix(recipe, width)
468 <<", replacements="<<replacements.dump()<<")";
472 void CraftDefinitionShaped::serializeBody(std::ostream &os) const
474 os<<serializeString(output);
476 writeU16(os, recipe.size());
477 for(u32 i=0; i<recipe.size(); i++)
478 os<<serializeString(recipe[i]);
479 replacements.serialize(os);
482 void CraftDefinitionShaped::deSerializeBody(std::istream &is, int version)
484 if(version != 1) throw SerializationError(
485 "unsupported CraftDefinitionShaped version");
486 output = deSerializeString(is);
489 u32 count = readU16(is);
490 for(u32 i=0; i<count; i++)
491 recipe.push_back(deSerializeString(is));
492 replacements.deSerialize(is);
496 CraftDefinitionShapeless
499 std::string CraftDefinitionShapeless::getName() const
504 bool CraftDefinitionShapeless::check(const CraftInput &input, IGameDef *gamedef) const
506 if(input.method != CRAFT_METHOD_NORMAL)
509 // Filter empty items out of input
510 std::vector<std::string> input_filtered;
511 for(std::vector<ItemStack>::const_iterator
512 i = input.items.begin();
513 i != input.items.end(); i++)
516 input_filtered.push_back(i->name);
519 // If there is a wrong number of items in input, no match
520 if(input_filtered.size() != recipe.size()){
521 /*dstream<<"Number of input items ("<<input_filtered.size()
522 <<") does not match recipe size ("<<recipe.size()<<") "
523 <<"of recipe with output="<<output<<std::endl;*/
527 // Try with all permutations of the recipe
528 std::vector<std::string> recipe_copy = craftGetItemNames(recipe, gamedef);
529 // Start from the lexicographically first permutation (=sorted)
530 std::sort(recipe_copy.begin(), recipe_copy.end());
531 //while(std::prev_permutation(recipe_copy.begin(), recipe_copy.end())){}
533 // If all items match, the recipe matches
534 bool all_match = true;
535 //dstream<<"Testing recipe (output="<<output<<"):";
536 for(size_t i=0; i<recipe.size(); i++){
537 //dstream<<" ("<<input_filtered[i]<<" == "<<recipe_copy[i]<<")";
538 if(!inputItemMatchesRecipe(input_filtered[i], recipe_copy[i],
544 //dstream<<" -> match="<<all_match<<std::endl;
547 }while(std::next_permutation(recipe_copy.begin(), recipe_copy.end()));
552 CraftOutput CraftDefinitionShapeless::getOutput(const CraftInput &input, IGameDef *gamedef) const
554 return CraftOutput(output, 0);
557 CraftInput CraftDefinitionShapeless::getInput(const CraftOutput &output, IGameDef *gamedef) const
559 return CraftInput(CRAFT_METHOD_NORMAL,0,craftGetItems(recipe,gamedef));
562 void CraftDefinitionShapeless::decrementInput(CraftInput &input, IGameDef *gamedef) const
564 craftDecrementOrReplaceInput(input, replacements, gamedef);
567 std::string CraftDefinitionShapeless::dump() const
569 std::ostringstream os(std::ios::binary);
570 os<<"(shapeless, output=\""<<output
571 <<"\", recipe="<<craftDumpMatrix(recipe, recipe.size())
572 <<", replacements="<<replacements.dump()<<")";
576 void CraftDefinitionShapeless::serializeBody(std::ostream &os) const
578 os<<serializeString(output);
579 writeU16(os, recipe.size());
580 for(u32 i=0; i<recipe.size(); i++)
581 os<<serializeString(recipe[i]);
582 replacements.serialize(os);
585 void CraftDefinitionShapeless::deSerializeBody(std::istream &is, int version)
587 if(version != 1) throw SerializationError(
588 "unsupported CraftDefinitionShapeless version");
589 output = deSerializeString(is);
591 u32 count = readU16(is);
592 for(u32 i=0; i<count; i++)
593 recipe.push_back(deSerializeString(is));
594 replacements.deSerialize(is);
598 CraftDefinitionToolRepair
601 static ItemStack craftToolRepair(
602 const ItemStack &item1,
603 const ItemStack &item2,
604 float additional_wear,
607 IItemDefManager *idef = gamedef->idef();
608 if(item1.count != 1 || item2.count != 1 || item1.name != item2.name
609 || idef->get(item1.name).type != ITEM_TOOL
610 || idef->get(item2.name).type != ITEM_TOOL)
616 s32 item1_uses = 65536 - (u32) item1.wear;
617 s32 item2_uses = 65536 - (u32) item2.wear;
618 s32 new_uses = item1_uses + item2_uses;
619 s32 new_wear = 65536 - new_uses + floor(additional_wear * 65536 + 0.5);
620 if(new_wear >= 65536)
625 ItemStack repaired = item1;
626 repaired.wear = new_wear;
630 std::string CraftDefinitionToolRepair::getName() const
635 bool CraftDefinitionToolRepair::check(const CraftInput &input, IGameDef *gamedef) const
637 if(input.method != CRAFT_METHOD_NORMAL)
642 for(std::vector<ItemStack>::const_iterator
643 i = input.items.begin();
644 i != input.items.end(); i++)
650 else if(item2.empty())
656 ItemStack repaired = craftToolRepair(item1, item2, additional_wear, gamedef);
657 return !repaired.empty();
660 CraftOutput CraftDefinitionToolRepair::getOutput(const CraftInput &input, IGameDef *gamedef) const
664 for(std::vector<ItemStack>::const_iterator
665 i = input.items.begin();
666 i != input.items.end(); i++)
672 else if(item2.empty())
676 ItemStack repaired = craftToolRepair(item1, item2, additional_wear, gamedef);
677 return CraftOutput(repaired.getItemString(), 0);
680 CraftInput CraftDefinitionToolRepair::getInput(const CraftOutput &output, IGameDef *gamedef) const
682 std::vector<ItemStack> stack;
683 stack.push_back(ItemStack());
684 return CraftInput(CRAFT_METHOD_COOKING,additional_wear,stack);
687 void CraftDefinitionToolRepair::decrementInput(CraftInput &input, IGameDef *gamedef) const
689 craftDecrementInput(input, gamedef);
692 std::string CraftDefinitionToolRepair::dump() const
694 std::ostringstream os(std::ios::binary);
695 os<<"(toolrepair, additional_wear="<<additional_wear<<")";
699 void CraftDefinitionToolRepair::serializeBody(std::ostream &os) const
701 writeF1000(os, additional_wear);
704 void CraftDefinitionToolRepair::deSerializeBody(std::istream &is, int version)
706 if(version != 1) throw SerializationError(
707 "unsupported CraftDefinitionToolRepair version");
708 additional_wear = readF1000(is);
712 CraftDefinitionCooking
715 std::string CraftDefinitionCooking::getName() const
720 bool CraftDefinitionCooking::check(const CraftInput &input, IGameDef *gamedef) const
722 if(input.method != CRAFT_METHOD_COOKING)
725 // Filter empty items out of input
726 std::vector<std::string> input_filtered;
727 for(std::vector<ItemStack>::const_iterator
728 i = input.items.begin();
729 i != input.items.end(); i++)
732 input_filtered.push_back(i->name);
735 // If there is a wrong number of items in input, no match
736 if(input_filtered.size() != 1){
737 /*dstream<<"Number of input items ("<<input_filtered.size()
738 <<") does not match recipe size (1) "
739 <<"of cooking recipe with output="<<output<<std::endl;*/
743 // Check the single input item
744 return inputItemMatchesRecipe(input_filtered[0], recipe, gamedef->idef());
747 CraftOutput CraftDefinitionCooking::getOutput(const CraftInput &input, IGameDef *gamedef) const
749 return CraftOutput(output, cooktime);
752 CraftInput CraftDefinitionCooking::getInput(const CraftOutput &output, IGameDef *gamedef) const
754 std::vector<std::string> rec;
755 rec.push_back(recipe);
756 return CraftInput(CRAFT_METHOD_COOKING,cooktime,craftGetItems(rec,gamedef));
759 void CraftDefinitionCooking::decrementInput(CraftInput &input, IGameDef *gamedef) const
761 craftDecrementOrReplaceInput(input, replacements, gamedef);
764 std::string CraftDefinitionCooking::dump() const
766 std::ostringstream os(std::ios::binary);
767 os<<"(cooking, output=\""<<output
768 <<"\", recipe=\""<<recipe
769 <<"\", cooktime="<<cooktime<<")"
770 <<", replacements="<<replacements.dump()<<")";
774 void CraftDefinitionCooking::serializeBody(std::ostream &os) const
776 os<<serializeString(output);
777 os<<serializeString(recipe);
778 writeF1000(os, cooktime);
779 replacements.serialize(os);
782 void CraftDefinitionCooking::deSerializeBody(std::istream &is, int version)
784 if(version != 1) throw SerializationError(
785 "unsupported CraftDefinitionCooking version");
786 output = deSerializeString(is);
787 recipe = deSerializeString(is);
788 cooktime = readF1000(is);
789 replacements.deSerialize(is);
796 std::string CraftDefinitionFuel::getName() const
801 bool CraftDefinitionFuel::check(const CraftInput &input, IGameDef *gamedef) const
803 if(input.method != CRAFT_METHOD_FUEL)
806 // Filter empty items out of input
807 std::vector<std::string> input_filtered;
808 for(std::vector<ItemStack>::const_iterator
809 i = input.items.begin();
810 i != input.items.end(); i++)
813 input_filtered.push_back(i->name);
816 // If there is a wrong number of items in input, no match
817 if(input_filtered.size() != 1){
818 /*dstream<<"Number of input items ("<<input_filtered.size()
819 <<") does not match recipe size (1) "
820 <<"of fuel recipe with burntime="<<burntime<<std::endl;*/
824 // Check the single input item
825 return inputItemMatchesRecipe(input_filtered[0], recipe, gamedef->idef());
828 CraftOutput CraftDefinitionFuel::getOutput(const CraftInput &input, IGameDef *gamedef) const
830 return CraftOutput("", burntime);
833 CraftInput CraftDefinitionFuel::getInput(const CraftOutput &output, IGameDef *gamedef) const
835 std::vector<std::string> rec;
836 rec.push_back(recipe);
837 return CraftInput(CRAFT_METHOD_COOKING,(int)burntime,craftGetItems(rec,gamedef));
840 void CraftDefinitionFuel::decrementInput(CraftInput &input, IGameDef *gamedef) const
842 craftDecrementOrReplaceInput(input, replacements, gamedef);
845 std::string CraftDefinitionFuel::dump() const
847 std::ostringstream os(std::ios::binary);
848 os<<"(fuel, recipe=\""<<recipe
849 <<"\", burntime="<<burntime<<")"
850 <<", replacements="<<replacements.dump()<<")";
854 void CraftDefinitionFuel::serializeBody(std::ostream &os) const
856 os<<serializeString(recipe);
857 writeF1000(os, burntime);
858 replacements.serialize(os);
861 void CraftDefinitionFuel::deSerializeBody(std::istream &is, int version)
863 if(version != 1) throw SerializationError(
864 "unsupported CraftDefinitionFuel version");
865 recipe = deSerializeString(is);
866 burntime = readF1000(is);
867 replacements.deSerialize(is);
871 Craft definition manager
874 class CCraftDefManager: public IWritableCraftDefManager
877 virtual ~CCraftDefManager()
881 virtual bool getCraftResult(CraftInput &input, CraftOutput &output,
882 bool decrementInput, IGameDef *gamedef) const
887 // If all input items are empty, abort.
888 bool all_empty = true;
889 for(std::vector<ItemStack>::const_iterator
890 i = input.items.begin();
891 i != input.items.end(); i++)
902 // Walk crafting definitions from back to front, so that later
903 // definitions can override earlier ones.
904 for(std::vector<CraftDefinition*>::const_reverse_iterator
905 i = m_craft_definitions.rbegin();
906 i != m_craft_definitions.rend(); i++)
908 CraftDefinition *def = *i;
910 /*infostream<<"Checking "<<input.dump()<<std::endl
911 <<" against "<<def->dump()<<std::endl;*/
914 if(def->check(input, gamedef))
916 // Get output, then decrement input (if requested)
917 output = def->getOutput(input, gamedef);
919 def->decrementInput(input, gamedef);
923 catch(SerializationError &e)
925 errorstream<<"getCraftResult: ERROR: "
926 <<"Serialization error in recipe "
927 <<def->dump()<<std::endl;
928 // then go on with the next craft definition
933 virtual bool getCraftRecipe(CraftInput &input, CraftOutput &output,
934 IGameDef *gamedef) const
940 // If output item is empty, abort.
941 if(output.item.empty())
944 // Walk crafting definitions from back to front, so that later
945 // definitions can override earlier ones.
946 for(std::vector<CraftDefinition*>::const_reverse_iterator
947 i = m_craft_definitions.rbegin();
948 i != m_craft_definitions.rend(); i++)
950 CraftDefinition *def = *i;
952 /*infostream<<"Checking "<<input.dump()<<std::endl
953 <<" against "<<def->dump()<<std::endl;*/
956 tmpout = def->getOutput(input, gamedef);
957 if(tmpout.item.substr(0,output.item.length()) == output.item)
959 // Get output, then decrement input (if requested)
960 input = def->getInput(output, gamedef);
964 catch(SerializationError &e)
966 errorstream<<"getCraftResult: ERROR: "
967 <<"Serialization error in recipe "
968 <<def->dump()<<std::endl;
969 // then go on with the next craft definition
974 virtual std::vector<CraftDefinition*> getCraftRecipes(CraftOutput &output,
975 IGameDef *gamedef) const
977 std::vector<CraftDefinition*> recipes_list;
983 for(std::vector<CraftDefinition*>::const_reverse_iterator
984 i = m_craft_definitions.rbegin();
985 i != m_craft_definitions.rend(); i++)
987 CraftDefinition *def = *i;
989 /*infostream<<"Checking "<<input.dump()<<std::endl
990 <<" against "<<def->dump()<<std::endl;*/
993 tmpout = def->getOutput(input, gamedef);
994 if(tmpout.item.substr(0,output.item.length()) == output.item)
996 // Get output, then decrement input (if requested)
997 input = def->getInput(output, gamedef);
998 recipes_list.push_back(*i);
1001 catch(SerializationError &e)
1003 errorstream<<"getCraftResult: ERROR: "
1004 <<"Serialization error in recipe "
1005 <<def->dump()<<std::endl;
1006 // then go on with the next craft definition
1009 return recipes_list;
1011 virtual std::string dump() const
1013 std::ostringstream os(std::ios::binary);
1014 os<<"Crafting definitions:\n";
1015 for(std::vector<CraftDefinition*>::const_iterator
1016 i = m_craft_definitions.begin();
1017 i != m_craft_definitions.end(); i++)
1019 os<<(*i)->dump()<<"\n";
1023 virtual void registerCraft(CraftDefinition *def)
1025 verbosestream<<"registerCraft: registering craft definition: "
1026 <<def->dump()<<std::endl;
1027 m_craft_definitions.push_back(def);
1029 virtual void clear()
1031 for(std::vector<CraftDefinition*>::iterator
1032 i = m_craft_definitions.begin();
1033 i != m_craft_definitions.end(); i++){
1036 m_craft_definitions.clear();
1038 virtual void serialize(std::ostream &os) const
1040 writeU8(os, 0); // version
1041 u16 count = m_craft_definitions.size();
1042 writeU16(os, count);
1043 for(std::vector<CraftDefinition*>::const_iterator
1044 i = m_craft_definitions.begin();
1045 i != m_craft_definitions.end(); i++){
1046 CraftDefinition *def = *i;
1047 // Serialize wrapped in a string
1048 std::ostringstream tmp_os(std::ios::binary);
1049 def->serialize(tmp_os);
1050 os<<serializeString(tmp_os.str());
1053 virtual void deSerialize(std::istream &is)
1058 int version = readU8(is);
1059 if(version != 0) throw SerializationError(
1060 "unsupported CraftDefManager version");
1061 u16 count = readU16(is);
1062 for(u16 i=0; i<count; i++){
1063 // Deserialize a string and grab a CraftDefinition from it
1064 std::istringstream tmp_is(deSerializeString(is), std::ios::binary);
1065 CraftDefinition *def = CraftDefinition::deSerialize(tmp_is);
1071 std::vector<CraftDefinition*> m_craft_definitions;
1074 IWritableCraftDefManager* createCraftDefManager()
1076 return new CCraftDefManager();