Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SurvivalBlockBreakHandler: Take swimming, flying, climbing and effects into account #5581

Closed
wants to merge 10 commits into from
1 change: 1 addition & 0 deletions src/block/Vine.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ public function canBeReplaced() : bool{

public function onEntityInside(Entity $entity) : bool{
$entity->resetFallDistance();
$entity->onGround = true;
return true;
}

Expand Down
25 changes: 23 additions & 2 deletions src/player/SurvivalBlockBreakHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@

use pocketmine\block\Block;
use pocketmine\entity\animation\ArmSwingAnimation;
use pocketmine\entity\effect\VanillaEffects;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\network\mcpe\protocol\LevelEventPacket;
use pocketmine\network\mcpe\protocol\types\LevelEvent;
use pocketmine\world\particle\BlockPunchParticle;
use pocketmine\world\sound\BlockPunchSound;
use function abs;
use function min;

final class SurvivalBlockBreakHandler{

Expand Down Expand Up @@ -65,8 +67,27 @@ private function calculateBreakProgressPerTick() : float{
if(!$this->block->getBreakInfo()->isBreakable()){
return 0.0;
}
//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)
$breakTimePerTick = $this->block->getBreakInfo()->getBreakTime($this->player->getInventory()->getItemInHand()) * 20;
$breakTimePerSecond = $this->block->getBreakInfo()->getBreakTime($this->player->getInventory()->getItemInHand());
zSALLAZAR marked this conversation as resolved.
Show resolved Hide resolved

if($this->player->isUnderwater()){ //TODO: Aqua Affinity enchantment
$breakTimePerSecond *= 5;
}
if(!$this->player->onGround){
$breakTimePerSecond *= 5;
}
if($this->player->canClimb() && $this->player->getWorld()->getBlock($this->player->getPosition())->canClimb()){
$breakTimePerSecond *= 5;
}

$effects = $this->player->getEffects();
if(($miningFatigue = $effects->get(VanillaEffects::MINING_FATIGUE())) !== null){
$breakTimePerSecond *= $breakTimePerSecond / ($breakTimePerSecond * 0.2 ** $miningFatigue->getEffectLevel());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How confident are you in this? Last time I checked, the values were different for Bedrock, which is why I didn't implement this properly to begin with.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$breakTimePerTick = ceil($this->block->getBreakInfo()->getBreakTime($this->player->getInventory()->getItemInHand()) * 20);
       
        $breakTimePerTick *= 1 - (0.3 * $this->player->getEffects()->get(VanillaEffects::MINING_FATIGUE())?->getAmplifier() ?? 0);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know where is your code from but according to the wiki:

The mining speed is reduced to 0.30^level of the normal mining speed. For the in-game default level III, the speed is reduced to 0.33 (0.027×) of normal speed, taking 37 times longer than usual to break a block with the proper tool for that block. 

https://minecraft.fandom.com/wiki/Mining_Fatigue

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The values from the wiki are wrong. The mining animation was too fast and already finished although the block was not broken yet.

}
if(($haste = $effects->get(VanillaEffects::HASTE())) !== null){
$breakTimePerSecond -= $breakTimePerSecond * 0.2 * min($haste->getEffectLevel(), 5);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same again here - I'm pretty sure the values differ from Java.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$breakTimePerTick = ceil($this->block->getBreakInfo()->getBreakTime($this->player->getInventory()->getItemInHand()) * 20);
        $breakTimePerTick *= 1 - (0.2 * $this->player->getEffects()->get(VanillaEffects::HASTE())?->getAmplifier() ?? 0);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why maximize the haste level to 5? This is normally an effect that can theoretically have a level of up to 255. The only limit is haste 3 for arm animation.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably because the break time can become negative if the haste level is higher than 5

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably because the break time can become negative if the haste level is higher than 5

You're right. But I used the values from the wiki and it seems that they are wrong too. The animation is too fast.

}

$breakTimePerTick = $breakTimePerSecond * 20;

if($breakTimePerTick > 0){
return 1 / $breakTimePerTick;
Expand Down