diff --git a/src/inventory/transaction/AnvilTransaction.php b/src/inventory/transaction/AnvilTransaction.php index 03b6d0fa3..050900bbf 100644 --- a/src/inventory/transaction/AnvilTransaction.php +++ b/src/inventory/transaction/AnvilTransaction.php @@ -27,6 +27,7 @@ use pocketmine\block\Block; use pocketmine\item\Durable; use pocketmine\item\EnchantedBook; +use pocketmine\item\enchantment\AvailableEnchantmentRegistry; use pocketmine\item\enchantment\EnchantmentInstance; use pocketmine\item\enchantment\EnchantmentTransfer; use pocketmine\item\enchantment\IncompatibleEnchantMap; @@ -195,10 +196,10 @@ public function validate() : void{ public function execute() : void{ try{ parent::execute(); - }catch(TransactionException){ + }catch(TransactionException $e){ $networkSession = $this->source->getNetworkSession(); $networkSession->getEntityEventBroadcaster()->syncAttributes([$networkSession], $this->source, $this->source->getAttributeMap()->getAll()); - return; + throw $e; } $this->source->getXpManager()->subtractXpLevels($this->getXPCost()); $this->holder->getPosition()->getWorld()->addSound($this->holder->getPosition(), new AnvilUseSound()); @@ -212,13 +213,12 @@ public function execute() : void{ */ public static function getApplicableEnchants(Item $target, Item $source) : array{ $applicableEnchants = []; - $itemFlag = ItemRepairUtils::getItemFlagFor($target); + $availableEnchantment = AvailableEnchantmentRegistry::getInstance(); foreach($source->getEnchantments() as $enchantment){ $enchantmentType = $enchantment->getType(); if( - !$enchantmentType->hasPrimaryItemType($itemFlag) && - !$enchantmentType->hasSecondaryItemType($itemFlag) && + !$availableEnchantment->isAvailableForItem($enchantmentType, $target) && !$target instanceof EnchantedBook // enchanted books let in any compatible ){ continue; diff --git a/src/network/mcpe/handler/ItemStackRequestExecutor.php b/src/network/mcpe/handler/ItemStackRequestExecutor.php index 8273068ab..371353839 100644 --- a/src/network/mcpe/handler/ItemStackRequestExecutor.php +++ b/src/network/mcpe/handler/ItemStackRequestExecutor.php @@ -23,11 +23,13 @@ namespace pocketmine\network\mcpe\handler; +use pocketmine\block\inventory\AnvilInventory; use pocketmine\block\inventory\EnchantInventory; use pocketmine\inventory\Inventory; use pocketmine\inventory\transaction\action\CreateItemAction; use pocketmine\inventory\transaction\action\DestroyItemAction; use pocketmine\inventory\transaction\action\DropItemAction; +use pocketmine\inventory\transaction\AnvilTransaction; use pocketmine\inventory\transaction\CraftingTransaction; use pocketmine\inventory\transaction\EnchantTransaction; use pocketmine\inventory\transaction\InventoryTransaction; @@ -39,6 +41,7 @@ use pocketmine\network\mcpe\protocol\types\inventory\stackrequest\CraftingConsumeInputStackRequestAction; use pocketmine\network\mcpe\protocol\types\inventory\stackrequest\CraftingCreateSpecificResultStackRequestAction; use pocketmine\network\mcpe\protocol\types\inventory\stackrequest\CraftRecipeAutoStackRequestAction; +use pocketmine\network\mcpe\protocol\types\inventory\stackrequest\CraftRecipeOptionalStackRequestAction; use pocketmine\network\mcpe\protocol\types\inventory\stackrequest\CraftRecipeStackRequestAction; use pocketmine\network\mcpe\protocol\types\inventory\stackrequest\CreativeCreateStackRequestAction; use pocketmine\network\mcpe\protocol\types\inventory\stackrequest\DeprecatedCraftingResultsStackRequestAction; @@ -289,7 +292,7 @@ protected function takeCreatedItem(int $count) : Item{ * @throws ItemStackRequestProcessException */ private function assertDoingCrafting() : void{ - if(!$this->specialTransaction instanceof CraftingTransaction && !$this->specialTransaction instanceof EnchantTransaction){ + if(!$this->specialTransaction instanceof CraftingTransaction && !$this->specialTransaction instanceof EnchantTransaction && !$this->specialTransaction instanceof AnvilTransaction){ if($this->specialTransaction === null){ throw new ItemStackRequestProcessException("Expected CraftRecipe or CraftRecipeAuto action to precede this action"); }else{ @@ -347,6 +350,21 @@ protected function processItemStackRequestAction(ItemStackRequestAction $action) } }elseif($action instanceof CraftRecipeAutoStackRequestAction){ $this->beginCrafting($action->getRecipeId(), $action->getRepetitions()); + }elseif($action instanceof CraftRecipeOptionalStackRequestAction){ + $window = $this->player->getCurrentWindow(); + if($window instanceof AnvilInventory){ + $filterStrings = $this->request->getFilterStrings(); + $filterStringIndex = $action->getFilterStringIndex(); + + $this->specialTransaction = new AnvilTransaction( + $this->player, + $this->player->getWorld()->getBlock($window->getHolder()), + $window->getItem(AnvilInventory::SLOT_INPUT), + $window->getItem(AnvilInventory::SLOT_MATERIAL), + $filterStringIndex >= 0 ? ($filterStrings[$filterStringIndex] ?? null) : null, [] + ); + $this->setNextCreatedItem($this->specialTransaction->getResult()); + } }elseif($action instanceof CraftingConsumeInputStackRequestAction){ $this->assertDoingCrafting(); $this->removeItemFromSlot($action->getSource(), $action->getCount()); //output discarded - we allow CraftingTransaction to verify the balance