Crafting: Match recipe based only on transaction inputs/outputs

As of 1.2.13 release, the client now skips the crafting grid step when it crafts with right-click on the recipe book. This means that we can't validate crafting based on the crafting grid contents anymore. The only way to do it now is to use the inputs and outputs calculated by the transaction balance.
This commit is contained in:
Dylan K. Taylor 2018-04-04 12:48:17 +01:00
parent eb354916d4
commit 2660448601
2 changed files with 41 additions and 7 deletions

View File

@ -253,6 +253,29 @@ class CraftingManager{
return null;
}
/**
* @param Item[] $outputs
*
* @return CraftingRecipe[]|\Generator
*/
public function matchRecipeByOutputs(array $outputs) : \Generator{
//TODO: try to match special recipes before anything else (first they need to be implemented!)
$outputHash = self::hashOutputs($outputs);
if(isset($this->shapedRecipes[$outputHash])){
foreach($this->shapedRecipes[$outputHash] as $recipe){
yield $recipe;
}
}
if(isset($this->shapelessRecipes[$outputHash])){
foreach($this->shapelessRecipes[$outputHash] as $recipe){
yield $recipe;
}
}
}
/**
* @param Item $input
*

View File

@ -111,15 +111,26 @@ class CraftingTransaction extends InventoryTransaction{
$this->matchItems($this->outputs, $this->inputs);
$this->recipe = $this->source->getServer()->getCraftingManager()->matchRecipe($this->source->getCraftingGrid(), $this->outputs);
if($this->recipe === null){
throw new TransactionValidationException("Unable to match a recipe to transaction");
$failed = 0;
foreach($this->source->getServer()->getCraftingManager()->matchRecipeByOutputs($this->outputs) as $recipe){
try{
//compute number of times recipe was crafted
$this->repetitions = $this->matchRecipeItems($this->outputs, $recipe->getResultsFor($this->source->getCraftingGrid()), false);
//assert that $repetitions x recipe ingredients should be consumed
$this->matchRecipeItems($this->inputs, $recipe->getIngredientList(), true, $this->repetitions);
//Success!
$this->recipe = $recipe;
break;
}catch(TransactionValidationException $e){
//failed
++$failed;
}
}
//compute number of times recipe was crafted
$this->repetitions = $this->matchRecipeItems($this->outputs, $this->recipe->getResultsFor($this->source->getCraftingGrid()), false);
//assert that $repetitions x recipe ingredients should be consumed
$this->matchRecipeItems($this->inputs, $this->recipe->getIngredientList(), true, $this->repetitions);
if($this->recipe === null){
throw new TransactionValidationException("Unable to match a recipe to transaction (tried to match against $failed recipes)");
}
}
protected function callExecuteEvent() : bool{