41 use DestructorCallbackTrait;
47 protected array $shapedRecipes = [];
52 protected array $shapelessRecipes = [];
58 private array $craftingRecipeIndex = [];
64 protected array $furnaceRecipeManagers = [];
70 protected array $potionTypeRecipes = [];
76 protected array $potionContainerChangeRecipes = [];
82 private array $brewingRecipeCache = [];
85 private ObjectSet $recipeRegisteredCallbacks;
87 public function __construct(){
88 $this->recipeRegisteredCallbacks =
new ObjectSet();
89 foreach(FurnaceType::cases() as $furnaceType){
93 $recipeRegisteredCallbacks = $this->recipeRegisteredCallbacks;
94 foreach($this->furnaceRecipeManagers as $furnaceRecipeManager){
95 $furnaceRecipeManager->getRecipeRegisteredCallbacks()->add(
static function(
FurnaceRecipe $recipe) use ($recipeRegisteredCallbacks) :
void{
96 foreach($recipeRegisteredCallbacks as $callback){
112 ($retval = $i1->getStateId() <=> $i2->getStateId()) === 0 && ($retval = $i1->getCount() <=> $i2->getCount()) === 0;
117 private static function hashOutput(
Item $output) : string{
118 $write = new ByteBufferWriter();
119 VarInt::writeSignedInt($write, $output->getStateId());
124 return $write->getData();
130 private static function hashOutputs(array $outputs) : string{
131 if(count($outputs) === 1){
132 return self::hashOutput(array_shift($outputs));
135 foreach($outputs as $o){
138 $hash = self::hashOutput($o);
139 $unique[$hash] = $hash;
141 ksort($unique, SORT_STRING);
142 return implode(
"", $unique);
150 return $this->shapelessRecipes;
158 return $this->shapedRecipes;
166 return $this->craftingRecipeIndex;
169 public function getCraftingRecipeFromIndex(
int $index) : ?
CraftingRecipe{
170 return $this->craftingRecipeIndex[$index] ?? null;
173 public function getFurnaceRecipeManager(FurnaceType $furnaceType) : FurnaceRecipeManager{
174 return $this->furnaceRecipeManagers[spl_object_id($furnaceType)];
182 return $this->potionTypeRecipes;
190 return $this->potionContainerChangeRecipes;
193 public function registerShapedRecipe(
ShapedRecipe $recipe) : void{
194 $this->shapedRecipes[self::hashOutputs($recipe->getResults())][] = $recipe;
195 $this->craftingRecipeIndex[] = $recipe;
197 foreach($this->recipeRegisteredCallbacks as $callback){
202 public function registerShapelessRecipe(ShapelessRecipe $recipe) : void{
203 $this->shapelessRecipes[self::hashOutputs($recipe->getResults())][] = $recipe;
204 $this->craftingRecipeIndex[] = $recipe;
206 foreach($this->recipeRegisteredCallbacks as $callback){
211 public function registerPotionTypeRecipe(PotionTypeRecipe $recipe) : void{
212 $this->potionTypeRecipes[] = $recipe;
214 foreach($this->recipeRegisteredCallbacks as $callback){
219 public function registerPotionContainerChangeRecipe(PotionContainerChangeRecipe $recipe) : void{
220 $this->potionContainerChangeRecipes[] = $recipe;
222 foreach($this->recipeRegisteredCallbacks as $callback){
233 $outputHash = self::hashOutputs($outputs);
235 if(isset($this->shapedRecipes[$outputHash])){
236 foreach($this->shapedRecipes[$outputHash] as $recipe){
237 if($recipe->matchesCraftingGrid($grid)){
243 if(isset($this->shapelessRecipes[$outputHash])){
244 foreach($this->shapelessRecipes[$outputHash] as $recipe){
245 if($recipe->matchesCraftingGrid($grid)){
263 $outputHash = self::hashOutputs($outputs);
265 if(isset($this->shapedRecipes[$outputHash])){
266 foreach($this->shapedRecipes[$outputHash] as $recipe){
271 if(isset($this->shapelessRecipes[$outputHash])){
272 foreach($this->shapelessRecipes[$outputHash] as $recipe){
278 public function matchBrewingRecipe(Item $input, Item $ingredient) : ?BrewingRecipe{
279 $inputHash = $input->getStateId();
280 $ingredientHash = $ingredient->getStateId();
281 $cached = $this->brewingRecipeCache[$inputHash][$ingredientHash] ??
null;
282 if($cached !==
null){
286 foreach($this->potionContainerChangeRecipes as $recipe){
287 if($recipe->getIngredient()->accepts($ingredient) && $recipe->getResultFor($input) !==
null){
288 return $this->brewingRecipeCache[$inputHash][$ingredientHash] = $recipe;
292 foreach($this->potionTypeRecipes as $recipe){
293 if($recipe->getIngredient()->accepts($ingredient) && $recipe->getResultFor($input) !==
null){
294 return $this->brewingRecipeCache[$inputHash][$ingredientHash] = $recipe;