CraftingManagerFromDataHelper: do not register recipes with unknown outputs

fixes #5093

we don't need to check the inputs, since unknown input items shouldn't be obtainable anyway.
This commit is contained in:
Dylan K. Taylor
2022-08-12 17:19:47 +01:00
parent 44e4dabf6e
commit 566f5935a3

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\crafting; namespace pocketmine\crafting;
use pocketmine\item\Item; use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\utils\AssumptionFailedError; use pocketmine\utils\AssumptionFailedError;
use pocketmine\utils\Utils; use pocketmine\utils\Utils;
use function array_map; use function array_map;
@@ -33,6 +34,23 @@ use function json_decode;
final class CraftingManagerFromDataHelper{ final class CraftingManagerFromDataHelper{
/**
* @param Item[] $items
*/
private static function containsUnknownOutputs(array $items) : bool{
$factory = ItemFactory::getInstance();
foreach($items as $item){
if($item->hasAnyDamageValue()){
throw new \InvalidArgumentException("Recipe outputs must not have wildcard meta values");
}
if(!$factory->isRegistered($item->getId(), $item->getMeta())){
return true;
}
}
return false;
}
public static function make(string $filePath) : CraftingManager{ public static function make(string $filePath) : CraftingManager{
$recipes = json_decode(Utils::assumeNotFalse(file_get_contents($filePath), "Missing required resource file"), true); $recipes = json_decode(Utils::assumeNotFalse(file_get_contents($filePath), "Missing required resource file"), true);
if(!is_array($recipes)){ if(!is_array($recipes)){
@@ -52,9 +70,13 @@ final class CraftingManagerFromDataHelper{
if($recipeType === null){ if($recipeType === null){
continue; continue;
} }
$output = array_map($itemDeserializerFunc, $recipe["output"]);
if(self::containsUnknownOutputs($output)){
continue;
}
$result->registerShapelessRecipe(new ShapelessRecipe( $result->registerShapelessRecipe(new ShapelessRecipe(
array_map($itemDeserializerFunc, $recipe["input"]), array_map($itemDeserializerFunc, $recipe["input"]),
array_map($itemDeserializerFunc, $recipe["output"]), $output,
$recipeType $recipeType
)); ));
} }
@@ -62,10 +84,14 @@ final class CraftingManagerFromDataHelper{
if($recipe["block"] !== "crafting_table"){ //TODO: filter others out for now to avoid breaking economics if($recipe["block"] !== "crafting_table"){ //TODO: filter others out for now to avoid breaking economics
continue; continue;
} }
$output = array_map($itemDeserializerFunc, $recipe["output"]);
if(self::containsUnknownOutputs($output)){
continue;
}
$result->registerShapedRecipe(new ShapedRecipe( $result->registerShapedRecipe(new ShapedRecipe(
$recipe["shape"], $recipe["shape"],
array_map($itemDeserializerFunc, $recipe["input"]), array_map($itemDeserializerFunc, $recipe["input"]),
array_map($itemDeserializerFunc, $recipe["output"]) $output
)); ));
} }
foreach($recipes["smelting"] as $recipe){ foreach($recipes["smelting"] as $recipe){
@@ -79,19 +105,30 @@ final class CraftingManagerFromDataHelper{
if($furnaceType === null){ if($furnaceType === null){
continue; continue;
} }
$output = Item::jsonDeserialize($recipe["output"]);
if(self::containsUnknownOutputs([$output])){
continue;
}
$result->getFurnaceRecipeManager($furnaceType)->register(new FurnaceRecipe( $result->getFurnaceRecipeManager($furnaceType)->register(new FurnaceRecipe(
Item::jsonDeserialize($recipe["output"]), $output,
Item::jsonDeserialize($recipe["input"])) Item::jsonDeserialize($recipe["input"]))
); );
} }
foreach($recipes["potion_type"] as $recipe){ foreach($recipes["potion_type"] as $recipe){
$output = Item::jsonDeserialize($recipe["output"]);
if(self::containsUnknownOutputs([$output])){
continue;
}
$result->registerPotionTypeRecipe(new PotionTypeRecipe( $result->registerPotionTypeRecipe(new PotionTypeRecipe(
Item::jsonDeserialize($recipe["input"]), Item::jsonDeserialize($recipe["input"]),
Item::jsonDeserialize($recipe["ingredient"]), Item::jsonDeserialize($recipe["ingredient"]),
Item::jsonDeserialize($recipe["output"]) $output
)); ));
} }
foreach($recipes["potion_container_change"] as $recipe){ foreach($recipes["potion_container_change"] as $recipe){
if(!ItemFactory::getInstance()->isRegistered($recipe["output_item_id"])){
continue;
}
$result->registerPotionContainerChangeRecipe(new PotionContainerChangeRecipe( $result->registerPotionContainerChangeRecipe(new PotionContainerChangeRecipe(
$recipe["input_item_id"], $recipe["input_item_id"],
Item::jsonDeserialize($recipe["ingredient"]), Item::jsonDeserialize($recipe["ingredient"]),