diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index c594d83bb..4f55285ca 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -46,6 +46,7 @@ use pocketmine\event\player\PlayerAchievementAwardedEvent; use pocketmine\event\player\PlayerAnimationEvent; use pocketmine\event\player\PlayerBedEnterEvent; use pocketmine\event\player\PlayerBedLeaveEvent; +use pocketmine\event\player\PlayerBlockPickEvent; use pocketmine\event\player\PlayerChatEvent; use pocketmine\event\player\PlayerCommandPreprocessEvent; use pocketmine\event\player\PlayerDeathEvent; @@ -2521,22 +2522,35 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ } public function handleBlockPickRequest(BlockPickRequestPacket $packet) : bool{ - if($this->isCreative()){ - $tile = $this->getLevel()->getTile($this->temporalVector->setComponents($packet->tileX, $packet->tileY, $packet->tileZ)); - if($tile instanceof Tile){ //TODO: check if the held item matches the target tile + $block = $this->level->getBlock($this->temporalVector->setComponents($packet->blockX, $packet->blockY, $packet->blockZ)); + + //TODO: this doesn't handle crops correctly (need more API work) + $item = Item::get($block->getItemId(), $block->getDamage() & $block->getVariantBitmask()); + + if($packet->addUserData){ + $tile = $this->getLevel()->getTile($block); + if($tile instanceof Tile){ $nbt = $tile->getCleanedNBT(); if($nbt instanceof CompoundTag){ - $item = $this->inventory->getItemInHand(); $item->setCustomBlockData($nbt); $item->setLore(["+(DATA)"]); - $this->inventory->setItemInHand($item); } - - return true; } } - return false; + $ev = new PlayerBlockPickEvent($this, $block, $item); + if(!$this->isCreative(true)){ + $this->server->getLogger()->debug("Got block-pick request from " . $this->getName() . " when not in creative mode (gamemode " . $this->getGamemode() . ")"); + $ev->setCancelled(); + } + + $this->server->getPluginManager()->callEvent($ev); + if(!$ev->isCancelled()){ + $this->inventory->setItemInHand($ev->getResultItem()); + } + + return true; + } public function handlePlayerAction(PlayerActionPacket $packet) : bool{ diff --git a/src/pocketmine/event/player/PlayerBlockPickEvent.php b/src/pocketmine/event/player/PlayerBlockPickEvent.php new file mode 100644 index 000000000..d28ca5902 --- /dev/null +++ b/src/pocketmine/event/player/PlayerBlockPickEvent.php @@ -0,0 +1,59 @@ +player = $player; + $this->blockClicked = $blockClicked; + $this->resultItem = $resultItem; + } + + public function getBlock() : Block{ + return $this->blockClicked; + } + + public function getResultItem() : Item{ + return $this->resultItem; + } + + public function setResultItem(Item $item) : void{ + $this->resultItem = clone $item; + } +} \ No newline at end of file diff --git a/src/pocketmine/network/mcpe/protocol/BlockPickRequestPacket.php b/src/pocketmine/network/mcpe/protocol/BlockPickRequestPacket.php index f53d047ef..4ac8f9267 100644 --- a/src/pocketmine/network/mcpe/protocol/BlockPickRequestPacket.php +++ b/src/pocketmine/network/mcpe/protocol/BlockPickRequestPacket.php @@ -33,24 +33,24 @@ class BlockPickRequestPacket extends DataPacket{ const NETWORK_ID = ProtocolInfo::BLOCK_PICK_REQUEST_PACKET; /** @var int */ - public $tileX; + public $blockX; /** @var int */ - public $tileY; + public $blockY; /** @var int */ - public $tileZ; + public $blockZ; /** @var bool */ public $addUserData = false; /** @var int */ public $hotbarSlot; protected function decodePayload(){ - $this->getSignedBlockPosition($this->tileX, $this->tileY, $this->tileZ); + $this->getSignedBlockPosition($this->blockX, $this->blockY, $this->blockZ); $this->addUserData = $this->getBool(); $this->hotbarSlot = $this->getByte(); } protected function encodePayload(){ - $this->putSignedBlockPosition($this->tileX, $this->tileY, $this->tileZ); + $this->putSignedBlockPosition($this->blockX, $this->blockY, $this->blockZ); $this->putBool($this->addUserData); $this->putByte($this->hotbarSlot); }