virtual void registerCraft(const CraftDefinition &def) { infostream<<"registerCraft: registering craft definition: " <<def.dump()<<std::endl; if(def.input.width > 3 || def.input.height() > 3){ errorstream<<"registerCraft: input size is larger than 3x3," <<" ignoring"<<std::endl; return; } m_craft_definitions.push_back(new CraftDefinition(def)); }
virtual bool getCraftResult(CraftInput &input, CraftOutput &output, bool decrementInput, IGameDef *gamedef) const { output.item = ""; output.time = 0; // If all input items are empty, abort. bool all_empty = true; for(std::vector<ItemStack>::const_iterator i = input.items.begin(); i != input.items.end(); i++) { if(!i->empty()) { all_empty = false; break; } } if(all_empty) return false; // Walk crafting definitions from back to front, so that later // definitions can override earlier ones. 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 { if(def->check(input, gamedef)) { // Get output, then decrement input (if requested) output = def->getOutput(input, gamedef); if(decrementInput) def->decrementInput(input, gamedef); return true; } } catch(SerializationError &e) { errorstream<<"getCraftResult: ERROR: " <<"Serialization error in recipe " <<def->dump()<<std::endl; // then go on with the next craft definition } } return false; }
virtual bool getCraftRecipe(CraftInput &input, CraftOutput &output, IGameDef *gamedef) const { CraftOutput tmpout; tmpout.item = ""; tmpout.time = 0; // If output item is empty, abort. if(output.item.empty()) return false; // Walk crafting definitions from back to front, so that later // definitions can override earlier ones. 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); return true; } } catch(SerializationError &e) { errorstream<<"getCraftResult: ERROR: " <<"Serialization error in recipe " <<def->dump()<<std::endl; // then go on with the next craft definition } } return false; }
virtual InventoryItem* getCraftResult(const CraftPointerInput &input_cpi, IGameDef *gamedef) const { if(input_cpi.width > 3){ errorstream<<"getCraftResult(): ERROR: " <<"input_cpi.width > 3; Failing to craft."<<std::endl; return NULL; } InventoryItem *input_items[9]; for(u32 y=0; y<3; y++) for(u32 x=0; x<3; x++) { u32 i=y*3+x; if(x >= input_cpi.width || y >= input_cpi.height()) input_items[i] = NULL; else input_items[i] = input_cpi.items[y*input_cpi.width+x]; } for(core::list<CraftDefinition*>::ConstIterator i = m_craft_definitions.begin(); i != m_craft_definitions.end(); i++) { CraftDefinition *def = *i; /*infostream<<"Checking "<<createInput(input_cpi).dump()<<std::endl <<" against "<<def->input.dump() <<" (output=\""<<def->output<<"\")"<<std::endl;*/ try { CraftPointerInput spec_cpi = createPointerInput(def->input, gamedef); if(spec_cpi.width > 3){ errorstream<<"getCraftResult: ERROR: " <<"spec_cpi.width > 3 in recipe " <<def->dump()<<std::endl; continue; } InventoryItem *spec_items[9]; for(u32 y=0; y<3; y++) for(u32 x=0; x<3; x++) { u32 i=y*3+x; if(x >= spec_cpi.width || y >= spec_cpi.height()) spec_items[i] = NULL; else spec_items[i] = spec_cpi.items[y*spec_cpi.width+x]; } bool match = checkItemCombination(input_items, spec_items); if(match){ std::istringstream iss(def->output, std::ios::binary); return InventoryItem::deSerialize(iss, gamedef); } } catch(SerializationError &e) { errorstream<<"getCraftResult: ERROR: " <<"Serialization error in recipe " <<def->dump()<<std::endl; // then go on with the next craft definition } } return NULL; }