Prioritise craft recipes
When multiple recipes are applicable, the recipes are prioritised in this order: toolrepair < shapeless with groups < shapeless < shaped with groups < shaped For cooking and fuel, items are prioritised over item groupsmaster
parent
1604b949fd
commit
12e3d3d12f
|
@ -432,7 +432,13 @@ void CraftDefinitionShaped::initHash(IGameDef *gamedef)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hash_type = has_group ? CRAFT_HASH_TYPE_COUNT : CRAFT_HASH_TYPE_ITEM_NAMES;
|
if (has_group) {
|
||||||
|
hash_type = CRAFT_HASH_TYPE_COUNT;
|
||||||
|
priority = SHAPED_AND_GROUPS;
|
||||||
|
} else {
|
||||||
|
hash_type = CRAFT_HASH_TYPE_ITEM_NAMES;
|
||||||
|
priority = SHAPED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CraftDefinitionShaped::dump() const
|
std::string CraftDefinitionShaped::dump() const
|
||||||
|
@ -543,7 +549,13 @@ void CraftDefinitionShapeless::initHash(IGameDef *gamedef)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hash_type = has_group ? CRAFT_HASH_TYPE_COUNT : CRAFT_HASH_TYPE_ITEM_NAMES;
|
if (has_group) {
|
||||||
|
hash_type = CRAFT_HASH_TYPE_COUNT;
|
||||||
|
priority = SHAPELESS_AND_GROUPS;
|
||||||
|
} else {
|
||||||
|
hash_type = CRAFT_HASH_TYPE_ITEM_NAMES;
|
||||||
|
priority = SHAPELESS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CraftDefinitionShapeless::dump() const
|
std::string CraftDefinitionShapeless::dump() const
|
||||||
|
@ -723,10 +735,13 @@ void CraftDefinitionCooking::initHash(IGameDef *gamedef)
|
||||||
hash_inited = true;
|
hash_inited = true;
|
||||||
recipe_name = craftGetItemName(recipe, gamedef);
|
recipe_name = craftGetItemName(recipe, gamedef);
|
||||||
|
|
||||||
if (isGroupRecipeStr(recipe_name))
|
if (isGroupRecipeStr(recipe_name)) {
|
||||||
hash_type = CRAFT_HASH_TYPE_COUNT;
|
hash_type = CRAFT_HASH_TYPE_COUNT;
|
||||||
else
|
priority = SHAPELESS_AND_GROUPS;
|
||||||
|
} else {
|
||||||
hash_type = CRAFT_HASH_TYPE_ITEM_NAMES;
|
hash_type = CRAFT_HASH_TYPE_ITEM_NAMES;
|
||||||
|
priority = SHAPELESS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CraftDefinitionCooking::dump() const
|
std::string CraftDefinitionCooking::dump() const
|
||||||
|
@ -813,10 +828,13 @@ void CraftDefinitionFuel::initHash(IGameDef *gamedef)
|
||||||
hash_inited = true;
|
hash_inited = true;
|
||||||
recipe_name = craftGetItemName(recipe, gamedef);
|
recipe_name = craftGetItemName(recipe, gamedef);
|
||||||
|
|
||||||
if (isGroupRecipeStr(recipe_name))
|
if (isGroupRecipeStr(recipe_name)) {
|
||||||
hash_type = CRAFT_HASH_TYPE_COUNT;
|
hash_type = CRAFT_HASH_TYPE_COUNT;
|
||||||
else
|
priority = SHAPELESS_AND_GROUPS;
|
||||||
|
} else {
|
||||||
hash_type = CRAFT_HASH_TYPE_ITEM_NAMES;
|
hash_type = CRAFT_HASH_TYPE_ITEM_NAMES;
|
||||||
|
priority = SHAPELESS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CraftDefinitionFuel::dump() const
|
std::string CraftDefinitionFuel::dump() const
|
||||||
|
@ -867,7 +885,11 @@ public:
|
||||||
input_names = craftGetItemNames(input.items, gamedef);
|
input_names = craftGetItemNames(input.items, gamedef);
|
||||||
std::sort(input_names.begin(), input_names.end());
|
std::sort(input_names.begin(), input_names.end());
|
||||||
|
|
||||||
// Try hash types with increasing collision rate, and return if found.
|
// Try hash types with increasing collision rate
|
||||||
|
// while remembering the latest, highest priority recipe.
|
||||||
|
CraftDefinition::RecipePriority priority_best =
|
||||||
|
CraftDefinition::NO_RECIPE;
|
||||||
|
CraftDefinition *def_best = nullptr;
|
||||||
for (int type = 0; type <= craft_hash_type_max; type++) {
|
for (int type = 0; type <= craft_hash_type_max; type++) {
|
||||||
u64 hash = getHashForGrid((CraftHashType) type, input_names);
|
u64 hash = getHashForGrid((CraftHashType) type, input_names);
|
||||||
|
|
||||||
|
@ -890,7 +912,9 @@ public:
|
||||||
/*errorstream << "Checking " << input.dump() << std::endl
|
/*errorstream << "Checking " << input.dump() << std::endl
|
||||||
<< " against " << def->dump() << std::endl;*/
|
<< " against " << def->dump() << std::endl;*/
|
||||||
|
|
||||||
if (def->check(input, gamedef)) {
|
CraftDefinition::RecipePriority priority = def->getPriority();
|
||||||
|
if (priority > priority_best
|
||||||
|
&& def->check(input, gamedef)) {
|
||||||
// Check if the crafted node/item exists
|
// Check if the crafted node/item exists
|
||||||
CraftOutput out = def->getOutput(input, gamedef);
|
CraftOutput out = def->getOutput(input, gamedef);
|
||||||
ItemStack is;
|
ItemStack is;
|
||||||
|
@ -901,17 +925,17 @@ public:
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get output, then decrement input (if requested)
|
|
||||||
output = out;
|
output = out;
|
||||||
|
priority_best = priority;
|
||||||
if (decrementInput)
|
def_best = def;
|
||||||
def->decrementInput(input, output_replacement, gamedef);
|
|
||||||
/*errorstream << "Check RETURNS TRUE" << std::endl;*/
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
if (priority_best == CraftDefinition::NO_RECIPE)
|
||||||
|
return false;
|
||||||
|
if (decrementInput)
|
||||||
|
def_best->decrementInput(input, output_replacement, gamedef);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::vector<CraftDefinition*> getCraftRecipes(CraftOutput &output,
|
virtual std::vector<CraftDefinition*> getCraftRecipes(CraftOutput &output,
|
||||||
|
|
|
@ -132,6 +132,23 @@ struct CraftReplacements
|
||||||
class CraftDefinition
|
class CraftDefinition
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/*
|
||||||
|
Craft recipe priorities, from low to high
|
||||||
|
|
||||||
|
Recipes are searched from latest to first.
|
||||||
|
If a recipe with higher priority than a previous found one is
|
||||||
|
encountered, it is selected instead.
|
||||||
|
*/
|
||||||
|
enum RecipePriority
|
||||||
|
{
|
||||||
|
NO_RECIPE,
|
||||||
|
TOOLREPAIR,
|
||||||
|
SHAPELESS_AND_GROUPS,
|
||||||
|
SHAPELESS,
|
||||||
|
SHAPED_AND_GROUPS,
|
||||||
|
SHAPED,
|
||||||
|
};
|
||||||
|
|
||||||
CraftDefinition() = default;
|
CraftDefinition() = default;
|
||||||
virtual ~CraftDefinition() = default;
|
virtual ~CraftDefinition() = default;
|
||||||
|
|
||||||
|
@ -140,6 +157,10 @@ public:
|
||||||
|
|
||||||
// Checks whether the recipe is applicable
|
// Checks whether the recipe is applicable
|
||||||
virtual bool check(const CraftInput &input, IGameDef *gamedef) const=0;
|
virtual bool check(const CraftInput &input, IGameDef *gamedef) const=0;
|
||||||
|
RecipePriority getPriority() const
|
||||||
|
{
|
||||||
|
return priority;
|
||||||
|
}
|
||||||
// Returns the output structure, meaning depends on crafting method
|
// Returns the output structure, meaning depends on crafting method
|
||||||
// The implementation can assume that check(input) returns true
|
// The implementation can assume that check(input) returns true
|
||||||
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const=0;
|
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const=0;
|
||||||
|
@ -162,6 +183,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CraftHashType hash_type;
|
CraftHashType hash_type;
|
||||||
|
RecipePriority priority;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -283,6 +305,7 @@ public:
|
||||||
virtual void initHash(IGameDef *gamedef)
|
virtual void initHash(IGameDef *gamedef)
|
||||||
{
|
{
|
||||||
hash_type = CRAFT_HASH_TYPE_COUNT;
|
hash_type = CRAFT_HASH_TYPE_COUNT;
|
||||||
|
priority = TOOLREPAIR;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::string dump() const;
|
virtual std::string dump() const;
|
||||||
|
|
Loading…
Reference in New Issue