57    private array $caches = [];
 
   66        $id = spl_object_id($manager);
 
   67        if(!isset($this->caches[$id])){
 
   68            $manager->getDestructorCallbacks()->add(
function() use ($id) : 
void{
 
   69                unset($this->caches[$id]);
 
   72                unset($this->caches[$id]);
 
   74            $this->caches[$id] = $this->buildCraftingDataCache($manager);
 
   76        return $this->caches[$id];
 
   82    private function buildCraftingDataCache(
CraftingManager $manager) : CraftingDataPacket{
 
   83        Timings::$craftingDataCacheRebuild->startTiming();
 
   85        $nullUUID = Uuid::fromString(Uuid::NIL);
 
   86        $converter = TypeConverter::getInstance();
 
   87        $recipesWithTypeIds = [];
 
   89        $noUnlockingRequirement = 
new RecipeUnlockingRequirement(
null);
 
   92            $recipeNetId = $index + self::RECIPE_ID_OFFSET;
 
   93            if($recipe instanceof ShapelessRecipe){
 
   94                $typeTag = match($recipe->getType()){
 
   95                    ShapelessRecipeType::CRAFTING => CraftingRecipeBlockName::CRAFTING_TABLE,
 
   96                    ShapelessRecipeType::STONECUTTER => CraftingRecipeBlockName::STONECUTTER,
 
   97                    ShapelessRecipeType::CARTOGRAPHY => CraftingRecipeBlockName::CARTOGRAPHY_TABLE,
 
   98                    ShapelessRecipeType::SMITHING => CraftingRecipeBlockName::SMITHING_TABLE,
 
  100                $recipesWithTypeIds[] = 
new ProtocolShapelessRecipe(
 
  101                    CraftingDataPacket::ENTRY_SHAPELESS,
 
  102                    BE::packUnsignedInt($recipeNetId), 
 
  103                    array_map($converter->coreRecipeIngredientToNet(...), $recipe->getIngredientList()),
 
  104                    array_map($converter->coreItemStackToNet(...), $recipe->getResults()),
 
  108                    $noUnlockingRequirement,
 
  111            }elseif($recipe instanceof ShapedRecipe){
 
  114                for($row = 0, $height = $recipe->getHeight(); $row < $height; ++$row){
 
  115                    for($column = 0, $width = $recipe->getWidth(); $column < $width; ++$column){
 
  116                        $inputs[$row][$column] = $converter->coreRecipeIngredientToNet($recipe->getIngredient($column, $row));
 
  119                $recipesWithTypeIds[] = $r = 
new ProtocolShapedRecipe(
 
  120                    CraftingDataPacket::ENTRY_SHAPED,
 
  121                    BE::packUnsignedInt($recipeNetId), 
 
  123                    array_map($converter->coreItemStackToNet(...), $recipe->getResults()),
 
  125                    CraftingRecipeBlockName::CRAFTING_TABLE,
 
  128                    $noUnlockingRequirement,
 
  136        foreach(FurnaceType::cases() as $furnaceType){
 
  137            $typeTag = match($furnaceType){
 
  138                FurnaceType::FURNACE => FurnaceRecipeBlockName::FURNACE,
 
  139                FurnaceType::BLAST_FURNACE => FurnaceRecipeBlockName::BLAST_FURNACE,
 
  140                FurnaceType::SMOKER => FurnaceRecipeBlockName::SMOKER,
 
  141                FurnaceType::CAMPFIRE => FurnaceRecipeBlockName::CAMPFIRE,
 
  142                FurnaceType::SOUL_CAMPFIRE => FurnaceRecipeBlockName::SOUL_CAMPFIRE
 
  144            foreach($manager->getFurnaceRecipeManager($furnaceType)->getAll() as $recipe){
 
  145                $input = $converter->coreRecipeIngredientToNet($recipe->getInput())->getDescriptor();
 
  146                if(!$input instanceof IntIdMetaItemDescriptor){
 
  147                    throw new AssumptionFailedError();
 
  149                $recipesWithTypeIds[] = 
new ProtocolFurnaceRecipe(
 
  150                    CraftingDataPacket::ENTRY_FURNACE_DATA,
 
  153                    $converter->coreItemStackToNet($recipe->getResult()),
 
  159        $potionTypeRecipes = [];
 
  161            $input = $converter->coreRecipeIngredientToNet($recipe->getInput())->getDescriptor();
 
  162            $ingredient = $converter->coreRecipeIngredientToNet($recipe->getIngredient())->getDescriptor();
 
  163            if(!$input instanceof IntIdMetaItemDescriptor || !$ingredient instanceof IntIdMetaItemDescriptor){
 
  164                throw new AssumptionFailedError();
 
  166            $output = $converter->coreItemStackToNet($recipe->getOutput());
 
  167            $potionTypeRecipes[] = 
new ProtocolPotionTypeRecipe(
 
  170                $ingredient->getId(),
 
  171                $ingredient->getMeta(),
 
  177        $potionContainerChangeRecipes = [];
 
  178        $itemTypeDictionary = $converter->getItemTypeDictionary();
 
  180            $input = $itemTypeDictionary->fromStringId($recipe->getInputItemId());
 
  181            $ingredient = $converter->coreRecipeIngredientToNet($recipe->getIngredient())->getDescriptor();
 
  182            if(!$ingredient instanceof IntIdMetaItemDescriptor){
 
  183                throw new AssumptionFailedError();
 
  185            $output = $itemTypeDictionary->fromStringId($recipe->getOutputItemId());
 
  186            $potionContainerChangeRecipes[] = 
new ProtocolPotionContainerChangeRecipe(
 
  188                $ingredient->getId(),
 
  193        Timings::$craftingDataCacheRebuild->stopTiming();