*/ private array $caches = []; public function getCache(CraftingManager $manager) : CraftingDataPacket{ $id = spl_object_id($manager); if(!isset($this->caches[$id])){ $manager->getDestructorCallbacks()->add(function() use ($id) : void{ unset($this->caches[$id]); }); $manager->getRecipeRegisteredCallbacks()->add(function() use ($id) : void{ unset($this->caches[$id]); }); $this->caches[$id] = $this->buildCraftingDataCache($manager); } return $this->caches[$id]; } /** * Rebuilds the cached CraftingDataPacket. */ private function buildCraftingDataCache(CraftingManager $manager) : CraftingDataPacket{ Timings::$craftingDataCacheRebuild->startTiming(); $counter = 0; $nullUUID = Uuid::fromString(Uuid::NIL); $converter = TypeConverter::getInstance(); $recipesWithTypeIds = []; foreach($manager->getShapelessRecipes() as $list){ foreach($list as $recipe){ $typeTag = match($recipe->getType()->id()){ ShapelessRecipeType::CRAFTING()->id() => CraftingRecipeBlockName::CRAFTING_TABLE, ShapelessRecipeType::STONECUTTER()->id() => CraftingRecipeBlockName::STONECUTTER, default => throw new AssumptionFailedError("Unreachable"), }; $recipesWithTypeIds[] = new ProtocolShapelessRecipe( CraftingDataPacket::ENTRY_SHAPELESS, Binary::writeInt(++$counter), array_map(function(RecipeIngredient $item) use ($converter) : ProtocolRecipeIngredient{ return $converter->coreRecipeIngredientToNet($item); }, $recipe->getIngredientList()), array_map(function(Item $item) use ($converter) : ItemStack{ return $converter->coreItemStackToNet($item); }, $recipe->getResults()), $nullUUID, $typeTag, 50, $counter ); } } foreach($manager->getShapedRecipes() as $list){ foreach($list as $recipe){ $inputs = []; for($row = 0, $height = $recipe->getHeight(); $row < $height; ++$row){ for($column = 0, $width = $recipe->getWidth(); $column < $width; ++$column){ $inputs[$row][$column] = $converter->coreRecipeIngredientToNet($recipe->getIngredient($column, $row)); } } $recipesWithTypeIds[] = $r = new ProtocolShapedRecipe( CraftingDataPacket::ENTRY_SHAPED, Binary::writeInt(++$counter), $inputs, array_map(function(Item $item) use ($converter) : ItemStack{ return $converter->coreItemStackToNet($item); }, $recipe->getResults()), $nullUUID, CraftingRecipeBlockName::CRAFTING_TABLE, 50, $counter ); } } foreach(FurnaceType::getAll() as $furnaceType){ $typeTag = match($furnaceType->id()){ FurnaceType::FURNACE()->id() => FurnaceRecipeBlockName::FURNACE, FurnaceType::BLAST_FURNACE()->id() => FurnaceRecipeBlockName::BLAST_FURNACE, FurnaceType::SMOKER()->id() => FurnaceRecipeBlockName::SMOKER, default => throw new AssumptionFailedError("Unreachable"), }; foreach($manager->getFurnaceRecipeManager($furnaceType)->getAll() as $recipe){ $input = $converter->coreRecipeIngredientToNet($recipe->getInput()); $recipesWithTypeIds[] = new ProtocolFurnaceRecipe( CraftingDataPacket::ENTRY_FURNACE_DATA, $input->getId(), $input->getMeta(), $converter->coreItemStackToNet($recipe->getResult()), $typeTag ); } } $potionTypeRecipes = []; foreach($manager->getPotionTypeRecipes() as $recipes){ foreach($recipes as $recipe){ $input = $converter->coreItemStackToNet($recipe->getInput()); $ingredient = $converter->coreItemStackToNet($recipe->getIngredient()); $output = $converter->coreItemStackToNet($recipe->getOutput()); $potionTypeRecipes[] = new ProtocolPotionTypeRecipe( $input->getId(), $input->getMeta(), $ingredient->getId(), $ingredient->getMeta(), $output->getId(), $output->getMeta() ); } } $potionContainerChangeRecipes = []; $itemTranslator = ItemTranslator::getInstance(); foreach($manager->getPotionContainerChangeRecipes() as $recipes){ foreach($recipes as $recipe){ $input = $itemTranslator->toNetworkId(ItemFactory::getInstance()->get($recipe->getInputItemId(), 0)); $ingredient = $itemTranslator->toNetworkId($recipe->getIngredient()); $output = $itemTranslator->toNetworkId(ItemFactory::getInstance()->get($recipe->getOutputItemId(), 0)); $potionContainerChangeRecipes[] = new ProtocolPotionContainerChangeRecipe( $input[0], $ingredient[0], $output[0] ); } } Timings::$craftingDataCacheRebuild->stopTiming(); return CraftingDataPacket::create($recipesWithTypeIds, $potionTypeRecipes, $potionContainerChangeRecipes, [], true); } }