PocketMine-MP 5.21.2 git-b2aa6396c3cc2cafdd815eacc360e1ad89599899
Loading...
Searching...
No Matches
CraftingDataCache.php
1<?php
2
3/*
4 *
5 * ____ _ _ __ __ _ __ __ ____
6 * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
7 * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
8 * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
9 * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
10 *
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * @author PocketMine Team
17 * @link http://www.pocketmine.net/
18 *
19 *
20 */
21
22declare(strict_types=1);
23
24namespace pocketmine\network\mcpe\cache;
25
27use pocketmine\crafting\FurnaceType;
30use pocketmine\crafting\ShapelessRecipeType;
45use pocketmine\utils\SingletonTrait;
46use Ramsey\Uuid\Uuid;
47use function array_map;
48use function spl_object_id;
49
51 use SingletonTrait;
52
57 private array $caches = [];
58
59 public function getCache(CraftingManager $manager) : CraftingDataPacket{
60 $id = spl_object_id($manager);
61 if(!isset($this->caches[$id])){
62 $manager->getDestructorCallbacks()->add(function() use ($id) : void{
63 unset($this->caches[$id]);
64 });
65 $manager->getRecipeRegisteredCallbacks()->add(function() use ($id) : void{
66 unset($this->caches[$id]);
67 });
68 $this->caches[$id] = $this->buildCraftingDataCache($manager);
69 }
70 return $this->caches[$id];
71 }
72
76 private function buildCraftingDataCache(CraftingManager $manager) : CraftingDataPacket{
77 Timings::$craftingDataCacheRebuild->startTiming();
78
79 $nullUUID = Uuid::fromString(Uuid::NIL);
80 $converter = TypeConverter::getInstance();
81 $recipesWithTypeIds = [];
82
83 $noUnlockingRequirement = new RecipeUnlockingRequirement(null);
84 foreach($manager->getCraftingRecipeIndex() as $index => $recipe){
85 if($recipe instanceof ShapelessRecipe){
86 $typeTag = match($recipe->getType()){
87 ShapelessRecipeType::CRAFTING => CraftingRecipeBlockName::CRAFTING_TABLE,
88 ShapelessRecipeType::STONECUTTER => CraftingRecipeBlockName::STONECUTTER,
89 ShapelessRecipeType::CARTOGRAPHY => CraftingRecipeBlockName::CARTOGRAPHY_TABLE,
90 ShapelessRecipeType::SMITHING => CraftingRecipeBlockName::SMITHING_TABLE,
91 };
92 $recipesWithTypeIds[] = new ProtocolShapelessRecipe(
93 CraftingDataPacket::ENTRY_SHAPELESS,
94 Binary::writeInt($index),
95 array_map($converter->coreRecipeIngredientToNet(...), $recipe->getIngredientList()),
96 array_map($converter->coreItemStackToNet(...), $recipe->getResults()),
97 $nullUUID,
98 $typeTag,
99 50,
100 $noUnlockingRequirement,
101 $index
102 );
103 }elseif($recipe instanceof ShapedRecipe){
104 $inputs = [];
105
106 for($row = 0, $height = $recipe->getHeight(); $row < $height; ++$row){
107 for($column = 0, $width = $recipe->getWidth(); $column < $width; ++$column){
108 $inputs[$row][$column] = $converter->coreRecipeIngredientToNet($recipe->getIngredient($column, $row));
109 }
110 }
111 $recipesWithTypeIds[] = $r = new ProtocolShapedRecipe(
112 CraftingDataPacket::ENTRY_SHAPED,
113 Binary::writeInt($index),
114 $inputs,
115 array_map($converter->coreItemStackToNet(...), $recipe->getResults()),
116 $nullUUID,
117 CraftingRecipeBlockName::CRAFTING_TABLE,
118 50,
119 true,
120 $noUnlockingRequirement,
121 $index,
122 );
123 }else{
124 //TODO: probably special recipe types
125 }
126 }
127
128 foreach(FurnaceType::cases() as $furnaceType){
129 $typeTag = match($furnaceType){
130 FurnaceType::FURNACE => FurnaceRecipeBlockName::FURNACE,
131 FurnaceType::BLAST_FURNACE => FurnaceRecipeBlockName::BLAST_FURNACE,
132 FurnaceType::SMOKER => FurnaceRecipeBlockName::SMOKER,
133 FurnaceType::CAMPFIRE => FurnaceRecipeBlockName::CAMPFIRE,
134 FurnaceType::SOUL_CAMPFIRE => FurnaceRecipeBlockName::SOUL_CAMPFIRE
135 };
136 foreach($manager->getFurnaceRecipeManager($furnaceType)->getAll() as $recipe){
137 $input = $converter->coreRecipeIngredientToNet($recipe->getInput())->getDescriptor();
138 if(!$input instanceof IntIdMetaItemDescriptor){
139 throw new AssumptionFailedError();
140 }
141 $recipesWithTypeIds[] = new ProtocolFurnaceRecipe(
142 CraftingDataPacket::ENTRY_FURNACE_DATA,
143 $input->getId(),
144 $input->getMeta(),
145 $converter->coreItemStackToNet($recipe->getResult()),
146 $typeTag
147 );
148 }
149 }
150
151 $potionTypeRecipes = [];
152 foreach($manager->getPotionTypeRecipes() as $recipe){
153 $input = $converter->coreRecipeIngredientToNet($recipe->getInput())->getDescriptor();
154 $ingredient = $converter->coreRecipeIngredientToNet($recipe->getIngredient())->getDescriptor();
155 if(!$input instanceof IntIdMetaItemDescriptor || !$ingredient instanceof IntIdMetaItemDescriptor){
156 throw new AssumptionFailedError();
157 }
158 $output = $converter->coreItemStackToNet($recipe->getOutput());
159 $potionTypeRecipes[] = new ProtocolPotionTypeRecipe(
160 $input->getId(),
161 $input->getMeta(),
162 $ingredient->getId(),
163 $ingredient->getMeta(),
164 $output->getId(),
165 $output->getMeta()
166 );
167 }
168
169 $potionContainerChangeRecipes = [];
170 $itemTypeDictionary = $converter->getItemTypeDictionary();
171 foreach($manager->getPotionContainerChangeRecipes() as $recipe){
172 $input = $itemTypeDictionary->fromStringId($recipe->getInputItemId());
173 $ingredient = $converter->coreRecipeIngredientToNet($recipe->getIngredient())->getDescriptor();
174 if(!$ingredient instanceof IntIdMetaItemDescriptor){
175 throw new AssumptionFailedError();
176 }
177 $output = $itemTypeDictionary->fromStringId($recipe->getOutputItemId());
178 $potionContainerChangeRecipes[] = new ProtocolPotionContainerChangeRecipe(
179 $input,
180 $ingredient->getId(),
181 $output
182 );
183 }
184
185 Timings::$craftingDataCacheRebuild->stopTiming();
186 return CraftingDataPacket::create($recipesWithTypeIds, $potionTypeRecipes, $potionContainerChangeRecipes, [], true);
187 }
188}
static create(array $recipesWithTypeIds, array $potionTypeRecipes, array $potionContainerRecipes, array $materialReducerRecipes, bool $cleanRecipes)