From 566f5935a306dc5857e083f7d195fcfc2a8219e4 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Fri, 12 Aug 2022 17:19:47 +0100 Subject: [PATCH] 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. --- .../CraftingManagerFromDataHelper.php | 45 +++++++++++++++++-- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/src/crafting/CraftingManagerFromDataHelper.php b/src/crafting/CraftingManagerFromDataHelper.php index 05612e66d..e91cb4ba6 100644 --- a/src/crafting/CraftingManagerFromDataHelper.php +++ b/src/crafting/CraftingManagerFromDataHelper.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace pocketmine\crafting; use pocketmine\item\Item; +use pocketmine\item\ItemFactory; use pocketmine\utils\AssumptionFailedError; use pocketmine\utils\Utils; use function array_map; @@ -33,6 +34,23 @@ use function json_decode; 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{ $recipes = json_decode(Utils::assumeNotFalse(file_get_contents($filePath), "Missing required resource file"), true); if(!is_array($recipes)){ @@ -52,9 +70,13 @@ final class CraftingManagerFromDataHelper{ if($recipeType === null){ continue; } + $output = array_map($itemDeserializerFunc, $recipe["output"]); + if(self::containsUnknownOutputs($output)){ + continue; + } $result->registerShapelessRecipe(new ShapelessRecipe( array_map($itemDeserializerFunc, $recipe["input"]), - array_map($itemDeserializerFunc, $recipe["output"]), + $output, $recipeType )); } @@ -62,10 +84,14 @@ final class CraftingManagerFromDataHelper{ if($recipe["block"] !== "crafting_table"){ //TODO: filter others out for now to avoid breaking economics continue; } + $output = array_map($itemDeserializerFunc, $recipe["output"]); + if(self::containsUnknownOutputs($output)){ + continue; + } $result->registerShapedRecipe(new ShapedRecipe( $recipe["shape"], array_map($itemDeserializerFunc, $recipe["input"]), - array_map($itemDeserializerFunc, $recipe["output"]) + $output )); } foreach($recipes["smelting"] as $recipe){ @@ -79,19 +105,30 @@ final class CraftingManagerFromDataHelper{ if($furnaceType === null){ continue; } + $output = Item::jsonDeserialize($recipe["output"]); + if(self::containsUnknownOutputs([$output])){ + continue; + } $result->getFurnaceRecipeManager($furnaceType)->register(new FurnaceRecipe( - Item::jsonDeserialize($recipe["output"]), + $output, Item::jsonDeserialize($recipe["input"])) ); } foreach($recipes["potion_type"] as $recipe){ + $output = Item::jsonDeserialize($recipe["output"]); + if(self::containsUnknownOutputs([$output])){ + continue; + } $result->registerPotionTypeRecipe(new PotionTypeRecipe( Item::jsonDeserialize($recipe["input"]), Item::jsonDeserialize($recipe["ingredient"]), - Item::jsonDeserialize($recipe["output"]) + $output )); } foreach($recipes["potion_container_change"] as $recipe){ + if(!ItemFactory::getInstance()->isRegistered($recipe["output_item_id"])){ + continue; + } $result->registerPotionContainerChangeRecipe(new PotionContainerChangeRecipe( $recipe["input_item_id"], Item::jsonDeserialize($recipe["ingredient"]),