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 it = input.items.begin(); it != input.items.end(); it++) { if (!it->empty()) { all_empty = false; break; } } if (all_empty) return false; std::vector<std::string> input_names; input_names = craftGetItemNames(input.items, gamedef); std::sort(input_names.begin(), input_names.end()); // Try hash types with increasing collision rate, and return if found. for (int type = 0; type <= craft_hash_type_max; type++) { u64 hash = getHashForGrid((CraftHashType) type, input_names); /*errorstream << "Checking type " << type << " with hash " << hash << std::endl;*/ // We'd like to do "const [...] hash_collisions = m_craft_defs[type][hash];" // but that doesn't compile for some reason. This does. std::map<u64, std::vector<CraftDefinition*> >::const_iterator col_iter = (m_craft_defs[type]).find(hash); if (col_iter == (m_craft_defs[type]).end()) continue; const std::vector<CraftDefinition*> &hash_collisions = col_iter->second; // Walk crafting definitions from back to front, so that later // definitions can override earlier ones. for (std::vector<CraftDefinition*>::const_reverse_iterator it = hash_collisions.rbegin(); it != hash_collisions.rend(); it++) { CraftDefinition *def = *it; /*errorstream << "Checking " << input.dump() << std::endl << " against " << def->dump() << std::endl;*/ if (def->check(input, gamedef)) { // Get output, then decrement input (if requested) output = def->getOutput(input, gamedef); if (decrementInput) def->decrementInput(input, gamedef); /*errorstream << "Check RETURNS TRUE" << std::endl;*/ return true; } } } return false; }
u64 CraftDefinitionShapeless::getHash(CraftHashType type) const { assert(hash_inited); // Pre-condition assert(type == CRAFT_HASH_TYPE_ITEM_NAMES || type == CRAFT_HASH_TYPE_COUNT); // Pre-condition return getHashForGrid(type, recipe_names); }
u64 CraftDefinitionShaped::getHash(CraftHashType type) const { assert(hash_inited); // Pre-condition assert((type == CRAFT_HASH_TYPE_ITEM_NAMES) || (type == CRAFT_HASH_TYPE_COUNT)); // Pre-condition std::vector<std::string> rec_names = recipe_names; std::sort(rec_names.begin(), rec_names.end()); return getHashForGrid(type, rec_names); }
u64 CraftDefinitionShapeless::getHash(CraftHashType type) const { assert(hash_inited); //pre-condition if (type == CRAFT_HASH_TYPE_ITEM_NAMES || type == CRAFT_HASH_TYPE_COUNT) { return getHashForGrid(type, recipe_names); } else { //illegal hash type for this CraftDefinition (pre-condition) assert(false); return 0; } }
u64 CraftDefinitionShaped::getHash(CraftHashType type) const { assert(hash_inited); //pre-condition if ((type == CRAFT_HASH_TYPE_ITEM_NAMES) || (type == CRAFT_HASH_TYPE_COUNT)) { std::vector<std::string> rec_names = recipe_names; std::sort(rec_names.begin(), rec_names.end()); return getHashForGrid(type, rec_names); } else { //illegal hash type for this CraftDefinition (pre-condition) assert(false); return 0; } }
virtual bool getCraftResult(CraftInput &input, CraftOutput &output, std::vector<ItemStack> &output_replacement, bool decrementInput, IGameDef *gamedef) const { output.item = ""; output.time = 0; // If all input items are empty, abort. bool all_empty = true; for (const auto &item : input.items) { if (!item.empty()) { all_empty = false; break; } } if (all_empty) return false; std::vector<std::string> input_names; input_names = craftGetItemNames(input.items, gamedef); std::sort(input_names.begin(), input_names.end()); // Try hash types with increasing collision rate, and return if found. for (int type = 0; type <= craft_hash_type_max; type++) { u64 hash = getHashForGrid((CraftHashType) type, input_names); /*errorstream << "Checking type " << type << " with hash " << hash << std::endl;*/ // We'd like to do "const [...] hash_collisions = m_craft_defs[type][hash];" // but that doesn't compile for some reason. This does. auto col_iter = (m_craft_defs[type]).find(hash); if (col_iter == (m_craft_defs[type]).end()) continue; const std::vector<CraftDefinition*> &hash_collisions = col_iter->second; // Walk crafting definitions from back to front, so that later // definitions can override earlier ones. for (std::vector<CraftDefinition*>::size_type i = hash_collisions.size(); i > 0; i--) { CraftDefinition *def = hash_collisions[i - 1]; /*errorstream << "Checking " << input.dump() << std::endl << " against " << def->dump() << std::endl;*/ if (def->check(input, gamedef)) { // Check if the crafted node/item exists CraftOutput out = def->getOutput(input, gamedef); ItemStack is; is.deSerialize(out.item, gamedef->idef()); if (!is.isKnown(gamedef->idef())) { infostream << "trying to craft non-existent " << out.item << ", ignoring recipe" << std::endl; continue; } // Get output, then decrement input (if requested) output = out; if (decrementInput) def->decrementInput(input, output_replacement, gamedef); /*errorstream << "Check RETURNS TRUE" << std::endl;*/ return true; } } } return false; }