diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index 1af1e957e..c9144f384 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -74,7 +74,6 @@ use pocketmine\inventory\CraftingGrid; use pocketmine\inventory\Inventory; use pocketmine\inventory\PlayerCursorInventory; use pocketmine\item\Consumable; -use pocketmine\item\Durable; use pocketmine\item\enchantment\EnchantmentInstance; use pocketmine\item\enchantment\MeleeWeaponEnchantment; use pocketmine\item\Item; @@ -1723,15 +1722,13 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, } public function equipItem(int $hotbarSlot) : bool{ - if(!$this->inventory->isHotbarSlot($hotbarSlot)){ - $this->inventory->sendContents($this); + if(!$this->inventory->isHotbarSlot($hotbarSlot)){ //TODO: exception here? return false; } $ev = new PlayerItemHeldEvent($this, $this->inventory->getItem($hotbarSlot), $hotbarSlot); $ev->call(); if($ev->isCancelled()){ - $this->inventory->sendHeldItem($this); return false; } @@ -1758,18 +1755,17 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, $ev->call(); if($ev->isCancelled()){ - $this->inventory->sendHeldItem($this); return false; } $result = $item->onClickAir($this, $directionVector); - if($result === ItemUseResult::SUCCESS()){ - $this->resetItemCooldown($item); - if($this->hasFiniteResources()){ - $this->inventory->setItemInHand($item); - } - }elseif($result === ItemUseResult::FAIL()){ - $this->inventory->sendHeldItem($this); + if($result !== ItemUseResult::SUCCESS()){ + return false; + } + + $this->resetItemCooldown($item); + if($this->hasFiniteResources()){ + $this->inventory->setItemInHand($item); } //TODO: check if item has a release action - if it doesn't, this shouldn't be set @@ -1781,7 +1777,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, /** * Consumes the currently-held item. * - * @return bool + * @return bool if the consumption succeeded. */ public function consumeHeldItem() : bool{ $slot = $this->inventory->getItemInHand(); @@ -1793,8 +1789,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, $ev->call(); if($ev->isCancelled() or !$this->consumeObject($slot)){ - $this->inventory->sendContents($this); - return true; + return false; } $this->resetItemCooldown($slot); @@ -1818,22 +1813,16 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, */ public function releaseHeldItem() : bool{ try{ - if($this->isUsingItem()){ - $item = $this->inventory->getItemInHand(); - if($this->hasItemCooldown($item)){ - $this->inventory->sendContents($this); - return false; - } - $result = $item->onReleaseUsing($this); - if($result === ItemUseResult::SUCCESS()){ - $this->resetItemCooldown($item); - $this->inventory->setItemInHand($item); - return true; - } - if($result === ItemUseResult::FAIL()){ - $this->inventory->sendContents($this); - return true; - } + $item = $this->inventory->getItemInHand(); + if(!$this->isUsingItem() or $this->hasItemCooldown($item)){ + return false; + } + + $result = $item->onReleaseUsing($this); + if($result === ItemUseResult::SUCCESS()){ + $this->resetItemCooldown($item); + $this->inventory->setItemInHand($item); + return true; } return false; @@ -1894,7 +1883,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, * @param Vector3 $pos * @param int $face * - * @return bool + * @return bool if an action took place successfully */ public function attackBlock(Vector3 $pos, int $face) : bool{ if($pos->distanceSquared($this) > 10000){ @@ -1906,9 +1895,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, $ev = new PlayerInteractEvent($this, $this->inventory->getItemInHand(), $target, null, $face, PlayerInteractEvent::LEFT_CLICK_BLOCK); $ev->call(); if($ev->isCancelled()){ - $this->world->sendBlocks([$this], [$target]); - $this->inventory->sendHeldItem($this); - return true; + return false; } if($target->onAttack($this->inventory->getItemInHand(), $face, $this)){ return true; @@ -2037,9 +2024,6 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, $entity->attack($ev); if($ev->isCancelled()){ - if($heldItem instanceof Durable and $this->hasFiniteResources()){ - $this->inventory->sendContents($this); - } return false; } diff --git a/src/pocketmine/network/mcpe/handler/InGameSessionHandler.php b/src/pocketmine/network/mcpe/handler/InGameSessionHandler.php index df32be217..619482037 100644 --- a/src/pocketmine/network/mcpe/handler/InGameSessionHandler.php +++ b/src/pocketmine/network/mcpe/handler/InGameSessionHandler.php @@ -280,7 +280,9 @@ class InGameSessionHandler extends SessionHandler{ } return true; case UseItemTransactionData::ACTION_CLICK_AIR: - $this->player->useHeldItem(); + if(!$this->player->useHeldItem()){ + $this->player->getInventory()->sendHeldItem($this->player); + } return true; } @@ -315,12 +317,17 @@ class InGameSessionHandler extends SessionHandler{ return false; } + //TODO: use transactiondata for rollbacks here switch($data->getActionType()){ case UseItemOnEntityTransactionData::ACTION_INTERACT: - $this->player->interactEntity($target, $data->getClickPos()); + if(!$this->player->interactEntity($target, $data->getClickPos())){ + $this->player->getInventory()->sendHeldItem($this->player); + } return true; case UseItemOnEntityTransactionData::ACTION_ATTACK: - $this->player->attackEntity($target); + if(!$this->player->attackEntity($target)){ + $this->player->getInventory()->sendHeldItem($this->player); + } return true; } @@ -328,12 +335,17 @@ class InGameSessionHandler extends SessionHandler{ } private function handleReleaseItemTransaction(ReleaseItemTransactionData $data) : bool{ + //TODO: use transactiondata for rollbacks here (resending entire inventory is very wasteful) switch($data->getActionType()){ case ReleaseItemTransactionData::ACTION_RELEASE: - $this->player->releaseHeldItem(); + if(!$this->player->releaseHeldItem()){ + $this->player->getInventory()->sendContents($this->player); + } return true; case ReleaseItemTransactionData::ACTION_CONSUME: - $this->player->consumeHeldItem(); + if(!$this->player->consumeHeldItem()){ + $this->player->getInventory()->sendHeldItem($this->player); + } return true; } @@ -341,7 +353,10 @@ class InGameSessionHandler extends SessionHandler{ } public function handleMobEquipment(MobEquipmentPacket $packet) : bool{ - return $this->player->equipItem($packet->hotbarSlot); + if(!$this->player->equipItem($packet->hotbarSlot)){ + $this->player->getInventory()->sendHeldItem($this->player); + } + return true; } public function handleMobArmorEquipment(MobArmorEquipmentPacket $packet) : bool{ @@ -373,7 +388,9 @@ class InGameSessionHandler extends SessionHandler{ switch($packet->action){ case PlayerActionPacket::ACTION_START_BREAK: - $this->player->attackBlock($pos, $packet->face); + if(!$this->player->attackBlock($pos, $packet->face)){ + $this->onFailedBlockAction($pos, $packet->face); + } break;