diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index b20da0b71..ae250fcc1 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -2664,42 +2664,13 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ switch($packet->action){ case PlayerActionPacket::ACTION_START_BREAK: - if($pos->distanceSquared($this) > 10000){ - break; - } - - $target = $this->level->getBlock($pos); - - $ev = new PlayerInteractEvent($this, $this->inventory->getItemInHand(), $target, null, $packet->face, $target->getId() === 0 ? PlayerInteractEvent::LEFT_CLICK_AIR : PlayerInteractEvent::LEFT_CLICK_BLOCK); - if($this->level->checkSpawnProtection($this, $target)){ - $ev->setCancelled(); - } - - $this->getServer()->getPluginManager()->callEvent($ev); - if($ev->isCancelled()){ - $this->inventory->sendHeldItem($this); - break; - } - - $block = $target->getSide($packet->face); - if($block->getId() === Block::FIRE){ - $this->level->setBlock($block, BlockFactory::get(Block::AIR)); - break; - } - - if(!$this->isCreative()){ - //TODO: improve this to take stuff like swimming, ladders, enchanted tools into account, fix wrong tool break time calculations for bad tools (pmmp/PocketMine-MP#211) - $breakTime = ceil($target->getBreakTime($this->inventory->getItemInHand()) * 20); - if($breakTime > 0){ - $this->level->broadcastLevelEvent($pos, LevelEventPacket::EVENT_BLOCK_START_BREAK, (int) (65535 / $breakTime)); - } - } + $this->startBreakBlock($pos, $packet->face); break; case PlayerActionPacket::ACTION_ABORT_BREAK: case PlayerActionPacket::ACTION_STOP_BREAK: - $this->level->broadcastLevelEvent($pos, LevelEventPacket::EVENT_BLOCK_STOP_BREAK); + $this->stopBreakBlock($pos); break; case PlayerActionPacket::ACTION_START_SLEEPING: //unused @@ -2733,9 +2704,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ case PlayerActionPacket::ACTION_STOP_GLIDE: break; //TODO case PlayerActionPacket::ACTION_CONTINUE_BREAK: - $block = $this->level->getBlock($pos); - $this->level->broadcastLevelEvent($pos, LevelEventPacket::EVENT_PARTICLE_PUNCH_BLOCK, BlockFactory::toStaticRuntimeId($block->getId(), $block->getDamage()) | ($packet->face << 24)); - //TODO: destroy-progress level event + $this->continueBreakBlock($pos, $packet->face); break; case PlayerActionPacket::ACTION_START_SWIMMING: break; //TODO @@ -2752,6 +2721,56 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ return true; } + public function startBreakBlock(Vector3 $pos, int $face) : bool{ + if($pos->distanceSquared($this) > 10000){ + return false; //TODO: maybe this should throw an exception instead? + } + + $target = $this->level->getBlock($pos); + + $ev = new PlayerInteractEvent($this, $this->inventory->getItemInHand(), $target, null, $face, $target->getId() === 0 ? PlayerInteractEvent::LEFT_CLICK_AIR : PlayerInteractEvent::LEFT_CLICK_BLOCK); + if($this->level->checkSpawnProtection($this, $target)){ + $ev->setCancelled(); + } + + $this->getServer()->getPluginManager()->callEvent($ev); + if($ev->isCancelled()){ + $this->inventory->sendHeldItem($this); + return true; + } + + $block = $target->getSide($face); + if($block->getId() === Block::FIRE){ + $this->level->setBlock($block, BlockFactory::get(Block::AIR)); + return true; + } + + if(!$this->isCreative()){ + //TODO: improve this to take stuff like swimming, ladders, enchanted tools into account, fix wrong tool break time calculations for bad tools (pmmp/PocketMine-MP#211) + $breakTime = ceil($target->getBreakTime($this->inventory->getItemInHand()) * 20); + if($breakTime > 0){ + $this->level->broadcastLevelEvent($pos, LevelEventPacket::EVENT_BLOCK_START_BREAK, (int) (65535 / $breakTime)); + } + } + + return true; + } + + public function continueBreakBlock(Vector3 $pos, int $face) : void{ + $block = $this->level->getBlock($pos); + $this->level->broadcastLevelEvent( + $pos, + LevelEventPacket::EVENT_PARTICLE_PUNCH_BLOCK, + BlockFactory::toStaticRuntimeId($block->getId(), $block->getDamage()) | ($face << 24) + ); + + //TODO: destroy-progress level event + } + + public function stopBreakBlock(Vector3 $pos) : void{ + $this->level->broadcastLevelEvent($pos, LevelEventPacket::EVENT_BLOCK_STOP_BREAK); + } + public function toggleSprint(bool $sprint) : void{ $ev = new PlayerToggleSprintEvent($this, $sprint); $this->server->getPluginManager()->callEvent($ev);