PocketMine-MP 5.17.1 git-df4ada81e5d74a14046f27cf44a37dcee69d657e
SurvivalBlockBreakHandler.php
1<?php
2
3/*
4 *
5 * ____ _ _ __ __ _ __ __ ____
6 * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
7 * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
8 * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
9 * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
10 *
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * @author PocketMine Team
17 * @link http://www.pocketmine.net/
18 *
19 *
20 */
21
22declare(strict_types=1);
23
24namespace pocketmine\player;
25
34use function abs;
35
37
38 public const DEFAULT_FX_INTERVAL_TICKS = 5;
39
40 private int $fxTicker = 0;
41 private float $breakSpeed;
42 private float $breakProgress = 0;
43
44 public function __construct(
45 private Player $player,
46 private Vector3 $blockPos,
47 private Block $block,
48 private int $targetedFace,
49 private int $maxPlayerDistance,
50 private int $fxTickInterval = self::DEFAULT_FX_INTERVAL_TICKS
51 ){
52 $this->breakSpeed = $this->calculateBreakProgressPerTick();
53 if($this->breakSpeed > 0){
54 $this->player->getWorld()->broadcastPacketToViewers(
55 $this->blockPos,
56 LevelEventPacket::create(LevelEvent::BLOCK_START_BREAK, (int) (65535 * $this->breakSpeed), $this->blockPos)
57 );
58 }
59 }
60
64 private function calculateBreakProgressPerTick() : float{
65 if(!$this->block->getBreakInfo()->isBreakable()){
66 return 0.0;
67 }
68 //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)
69 $breakTimePerTick = $this->block->getBreakInfo()->getBreakTime($this->player->getInventory()->getItemInHand()) * 20;
70
71 if($breakTimePerTick > 0){
72 return 1 / $breakTimePerTick;
73 }
74 return 1;
75 }
76
77 public function update() : bool{
78 if($this->player->getPosition()->distanceSquared($this->blockPos->add(0.5, 0.5, 0.5)) > $this->maxPlayerDistance ** 2){
79 return false;
80 }
81
82 $newBreakSpeed = $this->calculateBreakProgressPerTick();
83 if(abs($newBreakSpeed - $this->breakSpeed) > 0.0001){
84 $this->breakSpeed = $newBreakSpeed;
85 //TODO: sync with client
86 }
87
88 $this->breakProgress += $this->breakSpeed;
89
90 if(($this->fxTicker++ % $this->fxTickInterval) === 0 && $this->breakProgress < 1){
91 $this->player->getWorld()->addParticle($this->blockPos, new BlockPunchParticle($this->block, $this->targetedFace));
92 $this->player->getWorld()->addSound($this->blockPos, new BlockPunchSound($this->block));
93 $this->player->broadcastAnimation(new ArmSwingAnimation($this->player), $this->player->getViewers());
94 }
95
96 return $this->breakProgress < 1;
97 }
98
99 public function getBlockPos() : Vector3{
100 return $this->blockPos;
101 }
102
103 public function getTargetedFace() : int{
104 return $this->targetedFace;
105 }
106
107 public function setTargetedFace(int $face) : void{
108 Facing::validate($face);
109 $this->targetedFace = $face;
110 }
111
112 public function getBreakSpeed() : float{
113 return $this->breakSpeed;
114 }
115
116 public function getBreakProgress() : float{
117 return $this->breakProgress;
118 }
119
120 public function __destruct(){
121 if($this->player->getWorld()->isInLoadedTerrain($this->blockPos)){
122 $this->player->getWorld()->broadcastPacketToViewers(
123 $this->blockPos,
124 LevelEventPacket::create(LevelEvent::BLOCK_STOP_BREAK, 0, $this->blockPos)
125 );
126 }
127 }
128}
static validate(int $facing)
Definition: Facing.php:155
static create(int $eventId, int $eventData, ?Vector3 $position)