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 Binary::writeInt($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 Binary::writeInt($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();