56 private array $caches = [];
65 $id = spl_object_id($manager);
66 if(!isset($this->caches[$id])){
67 $manager->getDestructorCallbacks()->add(
function() use ($id) :
void{
68 unset($this->caches[$id]);
71 unset($this->caches[$id]);
73 $this->caches[$id] = $this->buildCraftingDataCache($manager);
75 return $this->caches[$id];
81 private function buildCraftingDataCache(
CraftingManager $manager) : CraftingDataPacket{
82 Timings::$craftingDataCacheRebuild->startTiming();
84 $nullUUID = Uuid::fromString(Uuid::NIL);
85 $converter = TypeConverter::getInstance();
86 $recipesWithTypeIds = [];
88 $noUnlockingRequirement =
new RecipeUnlockingRequirement(
null);
89 $recipeNetId = self::RECIPE_ID_OFFSET;
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
145 foreach($manager->getFurnaceRecipeManager($furnaceType)->getAll() as $recipe){
146 $recipesWithTypeIds[] =
new ProtocolShapelessRecipe(
147 CraftingDataPacket::ENTRY_SHAPELESS,
148 BE::packUnsignedInt($recipeNetId),
149 [$converter->coreRecipeIngredientToNet($recipe->getInput())],
150 [$converter->coreItemStackToNet($recipe->getResult())],
154 $noUnlockingRequirement,
160 $potionTypeRecipes = [];
162 $input = $converter->coreRecipeIngredientToNet($recipe->getInput())->getDescriptor();
163 $ingredient = $converter->coreRecipeIngredientToNet($recipe->getIngredient())->getDescriptor();
164 if(!$input instanceof IntIdMetaItemDescriptor || !$ingredient instanceof IntIdMetaItemDescriptor){
165 throw new AssumptionFailedError();
167 $output = $converter->coreItemStackToNet($recipe->getOutput());
168 $potionTypeRecipes[] =
new ProtocolPotionTypeRecipe(
171 $ingredient->getId(),
172 $ingredient->getMeta(),
178 $potionContainerChangeRecipes = [];
179 $itemTypeDictionary = $converter->getItemTypeDictionary();
181 $input = $itemTypeDictionary->fromStringId($recipe->getInputItemId());
182 $ingredient = $converter->coreRecipeIngredientToNet($recipe->getIngredient())->getDescriptor();
183 if(!$ingredient instanceof IntIdMetaItemDescriptor){
184 throw new AssumptionFailedError();
186 $output = $itemTypeDictionary->fromStringId($recipe->getOutputItemId());
187 $potionContainerChangeRecipes[] =
new ProtocolPotionContainerChangeRecipe(
189 $ingredient->getId(),
194 Timings::$craftingDataCacheRebuild->stopTiming();