From 7e0f6802894c973e89be0c9561cf410fa98a96f1 Mon Sep 17 00:00:00 2001 From: GameParrot <85067619+GameParrot@users.noreply.github.com> Date: Wed, 13 Nov 2024 10:15:15 -0500 Subject: [PATCH 1/7] Improve block break progress --- src/player/Player.php | 23 ++++++++++++++++++ src/player/SurvivalBlockBreakHandler.php | 30 +++++++++++++++++++----- 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/src/player/Player.php b/src/player/Player.php index 192e26a5f9a..4885b311eac 100644 --- a/src/player/Player.php +++ b/src/player/Player.php @@ -865,6 +865,29 @@ static function() : void{ Timings::$playerChunkSend->stopTiming(); } + /** + * Checks if the player is currently on the ground. This is more accurate than {@link Player::isOnGround()} but slower. + */ + public function isActuallyOnGround() : bool{ + $bb = $this->boundingBox->expandedCopy(0, 0.001, 0); + $maxY = (int) floor($this->location->y); + $minY = $maxY - 1; + $floorMinX = (int) floor($bb->minX); + $floorMinZ = (int) floor($bb->minZ); + $floorMaxX = (int) floor($bb->maxX); + $floorMaxZ = (int) floor($bb->maxZ); + for ($x = $floorMinX ; $x <= $floorMaxX ; $x++) { + for ($y = $minY ; $y <= $maxY ; $y++) { + for ($z = $floorMinZ ; $z <= $floorMaxZ ; $z++) { + if ($this->getWorld()->getBlockAt($x, $y, $z)->collidesWithBB($bb)) { + return true; + } + } + } + } + return false; + } + private function recheckBroadcastPermissions() : void{ foreach([ DefaultPermissionNames::BROADCAST_ADMIN => Server::BROADCAST_CHANNEL_ADMINISTRATIVE, diff --git a/src/player/SurvivalBlockBreakHandler.php b/src/player/SurvivalBlockBreakHandler.php index e31e77ef7c7..a1c0524e4bf 100644 --- a/src/player/SurvivalBlockBreakHandler.php +++ b/src/player/SurvivalBlockBreakHandler.php @@ -25,6 +25,8 @@ use pocketmine\block\Block; use pocketmine\entity\animation\ArmSwingAnimation; +use pocketmine\entity\effect\VanillaEffects; +use pocketmine\item\enchantment\VanillaEnchantments; use pocketmine\math\Facing; use pocketmine\math\Vector3; use pocketmine\network\mcpe\protocol\LevelEventPacket; @@ -62,14 +64,27 @@ public function __construct( * Returns the calculated break speed as percentage progress per game tick. */ private function calculateBreakProgressPerTick() : float{ - if(!$this->block->getBreakInfo()->isBreakable()){ + 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; - - if($breakTimePerTick > 0){ - return 1 / $breakTimePerTick; + if (!$this->player->isActuallyOnGround() && !$this->player->isFlying()) { + $breakTimePerTick *= 5; + } + if ($this->player->isUnderwater() && !$this->player->getArmorInventory()->getHelmet()->hasEnchantment(VanillaEnchantments::AQUA_AFFINITY())) { + $breakTimePerTick *= 5; + } + if($breakTimePerTick > 0) { + $progressPerTick = 1 / $breakTimePerTick; + if ($this->player->getEffects()->has(VanillaEffects::HASTE())) { + $amplifier = $this->player->getEffects()->get(VanillaEffects::HASTE())->getAmplifier() + 1; + $progressPerTick *= (1 + 0.2 * $amplifier) * (1.2 ** $amplifier); + } + if ($this->player->getEffects()->has(VanillaEffects::MINING_FATIGUE())) { + $amplifier = $this->player->getEffects()->get(VanillaEffects::MINING_FATIGUE())->getAmplifier() + 1; + $progressPerTick *= 0.21 ** $amplifier; + } + return $progressPerTick; } return 1; } @@ -82,7 +97,10 @@ public function update() : bool{ $newBreakSpeed = $this->calculateBreakProgressPerTick(); if(abs($newBreakSpeed - $this->breakSpeed) > 0.0001){ $this->breakSpeed = $newBreakSpeed; - //TODO: sync with client + $this->player->getWorld()->broadcastPacketToViewers( + $this->blockPos, + LevelEventPacket::create(LevelEvent::BLOCK_BREAK_SPEED, (int) (65535 * $this->breakSpeed), $this->blockPos) + ); } $this->breakProgress += $this->breakSpeed; From 020b2d18a2ae641a9b1c036d3ab2cacd34f1d12d Mon Sep 17 00:00:00 2001 From: GameParrot <85067619+GameParrot@users.noreply.github.com> Date: Wed, 13 Nov 2024 10:17:54 -0500 Subject: [PATCH 2/7] Fix CS --- src/player/SurvivalBlockBreakHandler.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/player/SurvivalBlockBreakHandler.php b/src/player/SurvivalBlockBreakHandler.php index a1c0524e4bf..175f3497d36 100644 --- a/src/player/SurvivalBlockBreakHandler.php +++ b/src/player/SurvivalBlockBreakHandler.php @@ -64,23 +64,23 @@ public function __construct( * Returns the calculated break speed as percentage progress per game tick. */ private function calculateBreakProgressPerTick() : float{ - if(!$this->block->getBreakInfo()->isBreakable()) { + if(!$this->block->getBreakInfo()->isBreakable()){ return 0.0; } $breakTimePerTick = $this->block->getBreakInfo()->getBreakTime($this->player->getInventory()->getItemInHand()) * 20; - if (!$this->player->isActuallyOnGround() && !$this->player->isFlying()) { + if (!$this->player->isActuallyOnGround() && !$this->player->isFlying()){ $breakTimePerTick *= 5; } - if ($this->player->isUnderwater() && !$this->player->getArmorInventory()->getHelmet()->hasEnchantment(VanillaEnchantments::AQUA_AFFINITY())) { + if ($this->player->isUnderwater() && !$this->player->getArmorInventory()->getHelmet()->hasEnchantment(VanillaEnchantments::AQUA_AFFINITY())){ $breakTimePerTick *= 5; } - if($breakTimePerTick > 0) { + if($breakTimePerTick > 0){ $progressPerTick = 1 / $breakTimePerTick; - if ($this->player->getEffects()->has(VanillaEffects::HASTE())) { + if ($this->player->getEffects()->has(VanillaEffects::HASTE())){ $amplifier = $this->player->getEffects()->get(VanillaEffects::HASTE())->getAmplifier() + 1; $progressPerTick *= (1 + 0.2 * $amplifier) * (1.2 ** $amplifier); } - if ($this->player->getEffects()->has(VanillaEffects::MINING_FATIGUE())) { + if ($this->player->getEffects()->has(VanillaEffects::MINING_FATIGUE())){ $amplifier = $this->player->getEffects()->get(VanillaEffects::MINING_FATIGUE())->getAmplifier() + 1; $progressPerTick *= 0.21 ** $amplifier; } From 38b2fbbdf54563d99d5702e12f9fb71ebe7f005c Mon Sep 17 00:00:00 2001 From: GameParrot <85067619+GameParrot@users.noreply.github.com> Date: Wed, 13 Nov 2024 10:44:12 -0500 Subject: [PATCH 3/7] Fix more CS --- src/player/Player.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/player/Player.php b/src/player/Player.php index 4885b311eac..863978927e3 100644 --- a/src/player/Player.php +++ b/src/player/Player.php @@ -876,10 +876,10 @@ public function isActuallyOnGround() : bool{ $floorMinZ = (int) floor($bb->minZ); $floorMaxX = (int) floor($bb->maxX); $floorMaxZ = (int) floor($bb->maxZ); - for ($x = $floorMinX ; $x <= $floorMaxX ; $x++) { - for ($y = $minY ; $y <= $maxY ; $y++) { - for ($z = $floorMinZ ; $z <= $floorMaxZ ; $z++) { - if ($this->getWorld()->getBlockAt($x, $y, $z)->collidesWithBB($bb)) { + for ($x = $floorMinX ; $x <= $floorMaxX ; $x++){ + for ($y = $minY ; $y <= $maxY ; $y++){ + for ($z = $floorMinZ ; $z <= $floorMaxZ ; $z++){ + if ($this->getWorld()->getBlockAt($x, $y, $z)->collidesWithBB($bb)){ return true; } } From 9f9878c5af96c0b2609eacec97df164cefb4c4fa Mon Sep 17 00:00:00 2001 From: GameParrot <85067619+GameParrot@users.noreply.github.com> Date: Wed, 13 Nov 2024 10:50:19 -0500 Subject: [PATCH 4/7] fix phpstan --- src/player/SurvivalBlockBreakHandler.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/player/SurvivalBlockBreakHandler.php b/src/player/SurvivalBlockBreakHandler.php index 175f3497d36..a25dc00011e 100644 --- a/src/player/SurvivalBlockBreakHandler.php +++ b/src/player/SurvivalBlockBreakHandler.php @@ -76,14 +76,19 @@ private function calculateBreakProgressPerTick() : float{ } if($breakTimePerTick > 0){ $progressPerTick = 1 / $breakTimePerTick; - if ($this->player->getEffects()->has(VanillaEffects::HASTE())){ - $amplifier = $this->player->getEffects()->get(VanillaEffects::HASTE())->getAmplifier() + 1; + + $haste = $this->player->getEffects()->get(VanillaEffects::HASTE()); + if ($haste !== null){ + $amplifier = $haste->getAmplifier() + 1; $progressPerTick *= (1 + 0.2 * $amplifier) * (1.2 ** $amplifier); } - if ($this->player->getEffects()->has(VanillaEffects::MINING_FATIGUE())){ - $amplifier = $this->player->getEffects()->get(VanillaEffects::MINING_FATIGUE())->getAmplifier() + 1; + + $miningFatigue = $this->player->getEffects()->get(VanillaEffects::MINING_FATIGUE()); + if ($miningFatigue !== null){ + $amplifier = $miningFatigue->getAmplifier() + 1; $progressPerTick *= 0.21 ** $amplifier; } + return $progressPerTick; } return 1; From 7e5b903cb05559ea564a2643c1748844177bb23e Mon Sep 17 00:00:00 2001 From: GameParrot <85067619+GameParrot@users.noreply.github.com> Date: Fri, 15 Nov 2024 15:36:38 -0500 Subject: [PATCH 5/7] Use getEffectLevel instead of getAmplifier --- src/player/SurvivalBlockBreakHandler.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/player/SurvivalBlockBreakHandler.php b/src/player/SurvivalBlockBreakHandler.php index a25dc00011e..2dbeeae9ff2 100644 --- a/src/player/SurvivalBlockBreakHandler.php +++ b/src/player/SurvivalBlockBreakHandler.php @@ -79,14 +79,14 @@ private function calculateBreakProgressPerTick() : float{ $haste = $this->player->getEffects()->get(VanillaEffects::HASTE()); if ($haste !== null){ - $amplifier = $haste->getAmplifier() + 1; - $progressPerTick *= (1 + 0.2 * $amplifier) * (1.2 ** $amplifier); + $hasteLevel = $haste->getEffectLevel(); + $progressPerTick *= (1 + 0.2 * $hasteLevel) * (1.2 ** $hasteLevel); } $miningFatigue = $this->player->getEffects()->get(VanillaEffects::MINING_FATIGUE()); if ($miningFatigue !== null){ - $amplifier = $miningFatigue->getAmplifier() + 1; - $progressPerTick *= 0.21 ** $amplifier; + $miningFatigueLevel = $miningFatigue->getEffectLevel(); + $progressPerTick *= 0.21 ** $miningFatigueLevel; } return $progressPerTick; From 0cadd6914da97db068993fffa916da763a38f029 Mon Sep 17 00:00:00 2001 From: GameParrot <85067619+GameParrot@users.noreply.github.com> Date: Fri, 15 Nov 2024 15:36:52 -0500 Subject: [PATCH 6/7] Fix insta break check --- src/player/Player.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/player/Player.php b/src/player/Player.php index 863978927e3..366cb5d3b97 100644 --- a/src/player/Player.php +++ b/src/player/Player.php @@ -1787,7 +1787,7 @@ public function attackBlock(Vector3 $pos, int $face) : bool{ return true; } - if(!$this->isCreative() && !$block->getBreakInfo()->breaksInstantly()){ + if(!$this->isCreative() && !$target->getBreakInfo()->breaksInstantly()){ $this->blockBreakHandler = new SurvivalBlockBreakHandler($this, $pos, $target, $face, 16); } From b51b9e3ba7b54062684543e71eea50e579d3974f Mon Sep 17 00:00:00 2001 From: GameParrot <85067619+GameParrot@users.noreply.github.com> Date: Thu, 21 Nov 2024 21:19:08 -0500 Subject: [PATCH 7/7] Fix floating point issue at high x/z coordinates --- src/player/Player.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/player/Player.php b/src/player/Player.php index 366cb5d3b97..85c69b92c19 100644 --- a/src/player/Player.php +++ b/src/player/Player.php @@ -869,7 +869,7 @@ static function() : void{ * Checks if the player is currently on the ground. This is more accurate than {@link Player::isOnGround()} but slower. */ public function isActuallyOnGround() : bool{ - $bb = $this->boundingBox->expandedCopy(0, 0.001, 0); + $bb = $this->boundingBox->expandedCopy(-0.001, 0.001, -0.001); $maxY = (int) floor($this->location->y); $minY = $maxY - 1; $floorMinX = (int) floor($bb->minX);