Skip to content
Permalink
Browse files

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 groups
  • Loading branch information...
HybridDog authored and SmallJoker committed Apr 3, 2019
1 parent 1604b94 commit 12e3d3d12f919a141f5032645d03bda2ad4489f5
Showing with 62 additions and 15 deletions.
  1. +39 −15 src/craftdef.cpp
  2. +23 −0 src/craftdef.h
@@ -432,7 +432,13 @@ void CraftDefinitionShaped::initHash(IGameDef *gamedef)
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
@@ -543,7 +549,13 @@ void CraftDefinitionShapeless::initHash(IGameDef *gamedef)
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
@@ -723,10 +735,13 @@ void CraftDefinitionCooking::initHash(IGameDef *gamedef)
hash_inited = true;
recipe_name = craftGetItemName(recipe, gamedef);

if (isGroupRecipeStr(recipe_name))
if (isGroupRecipeStr(recipe_name)) {
hash_type = CRAFT_HASH_TYPE_COUNT;
else
priority = SHAPELESS_AND_GROUPS;
} else {
hash_type = CRAFT_HASH_TYPE_ITEM_NAMES;
priority = SHAPELESS;
}
}

std::string CraftDefinitionCooking::dump() const
@@ -813,10 +828,13 @@ void CraftDefinitionFuel::initHash(IGameDef *gamedef)
hash_inited = true;
recipe_name = craftGetItemName(recipe, gamedef);

if (isGroupRecipeStr(recipe_name))
if (isGroupRecipeStr(recipe_name)) {
hash_type = CRAFT_HASH_TYPE_COUNT;
else
priority = SHAPELESS_AND_GROUPS;
} else {
hash_type = CRAFT_HASH_TYPE_ITEM_NAMES;
priority = SHAPELESS;
}
}

std::string CraftDefinitionFuel::dump() const
@@ -867,7 +885,11 @@ class CCraftDefManager: public IWritableCraftDefManager
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.
// 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++) {
u64 hash = getHashForGrid((CraftHashType) type, input_names);

@@ -890,7 +912,9 @@ class CCraftDefManager: public IWritableCraftDefManager
/*errorstream << "Checking " << input.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
CraftOutput out = def->getOutput(input, gamedef);
ItemStack is;
@@ -901,17 +925,17 @@ class CCraftDefManager: public IWritableCraftDefManager
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;
priority_best = priority;
def_best = def;
}
}
}
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,
@@ -132,6 +132,23 @@ struct CraftReplacements
class CraftDefinition
{
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;
virtual ~CraftDefinition() = default;

@@ -140,6 +157,10 @@ class CraftDefinition

// Checks whether the recipe is applicable
virtual bool check(const CraftInput &input, IGameDef *gamedef) const=0;
RecipePriority getPriority() const
{
return priority;
}
// Returns the output structure, meaning depends on crafting method
// The implementation can assume that check(input) returns true
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const=0;
@@ -162,6 +183,7 @@ class CraftDefinition

protected:
CraftHashType hash_type;
RecipePriority priority;
};

/*
@@ -283,6 +305,7 @@ class CraftDefinitionToolRepair: public CraftDefinition
virtual void initHash(IGameDef *gamedef)
{
hash_type = CRAFT_HASH_TYPE_COUNT;
priority = TOOLREPAIR;
}

virtual std::string dump() const;

0 comments on commit 12e3d3d

Please sign in to comment.
You can’t perform that action at this time.