Merge branch 'minor-next' into major-next

This commit is contained in:
Dylan K. Taylor 2023-07-24 12:07:55 +01:00
commit 3c0e7ae492
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
55 changed files with 247 additions and 224 deletions

View File

@ -13,7 +13,7 @@ jobs:
- uses: actions/checkout@v3
- name: Setup PHP and tools
uses: shivammathur/setup-php@2.25.2
uses: shivammathur/setup-php@2.25.4
with:
php-version: 8.1

View File

@ -18,7 +18,7 @@ jobs:
submodules: true
- name: Setup PHP
uses: shivammathur/setup-php@2.25.2
uses: shivammathur/setup-php@2.25.4
with:
php-version: 8.1

View File

@ -173,7 +173,7 @@ jobs:
- uses: actions/checkout@v3
- name: Setup PHP and tools
uses: shivammathur/setup-php@2.25.2
uses: shivammathur/setup-php@2.25.4
with:
php-version: 8.1
tools: php-cs-fixer:3.17

@ -1 +1 @@
Subproject commit e0c918d1379465964acefd562d9e48f87cfc2c9e
Subproject commit 46604f2f6a07e3f68a82e4f4d7efdd45629b101e

View File

@ -50,7 +50,7 @@
"pocketmine/raklib-ipc": "^0.2.0",
"pocketmine/snooze": "^0.5.0",
"ramsey/uuid": "~4.7.0",
"symfony/filesystem": "~6.2.0"
"symfony/filesystem": "~6.3.0"
},
"require-dev": {
"phpstan/phpstan": "1.10.16",

27
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "ee46ec27f8dfc8c767527b7776fe9992",
"content-hash": "74166e6c2f09b356c83a951efef349f2",
"packages": [
{
"name": "adhocore/json-comment",
@ -998,16 +998,16 @@
},
{
"name": "symfony/filesystem",
"version": "v6.2.12",
"version": "v6.3.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
"reference": "b0818e7203e53540f2a5c9a5017d97897df1e9bb"
"reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/b0818e7203e53540f2a5c9a5017d97897df1e9bb",
"reference": "b0818e7203e53540f2a5c9a5017d97897df1e9bb",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/edd36776956f2a6fcf577edb5b05eb0e3bdc52ae",
"reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae",
"shasum": ""
},
"require": {
@ -1041,7 +1041,7 @@
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/filesystem/tree/v6.2.12"
"source": "https://github.com/symfony/filesystem/tree/v6.3.1"
},
"funding": [
{
@ -1057,7 +1057,7 @@
"type": "tidelift"
}
],
"time": "2023-06-01T08:29:37+00:00"
"time": "2023-06-01T08:30:39+00:00"
},
{
"name": "symfony/polyfill-ctype",
@ -2546,16 +2546,16 @@
},
{
"name": "sebastian/global-state",
"version": "6.0.0",
"version": "6.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
"reference": "aab257c712de87b90194febd52e4d184551c2d44"
"reference": "7ea9ead78f6d380d2a667864c132c2f7b83055e4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/aab257c712de87b90194febd52e4d184551c2d44",
"reference": "aab257c712de87b90194febd52e4d184551c2d44",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/7ea9ead78f6d380d2a667864c132c2f7b83055e4",
"reference": "7ea9ead78f6d380d2a667864c132c2f7b83055e4",
"shasum": ""
},
"require": {
@ -2595,7 +2595,8 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/global-state/issues",
"source": "https://github.com/sebastianbergmann/global-state/tree/6.0.0"
"security": "https://github.com/sebastianbergmann/global-state/security/policy",
"source": "https://github.com/sebastianbergmann/global-state/tree/6.0.1"
},
"funding": [
{
@ -2603,7 +2604,7 @@
"type": "github"
}
],
"time": "2023-02-03T07:07:38+00:00"
"time": "2023-07-19T07:19:23+00:00"
},
{
"name": "sebastian/lines-of-code",

View File

@ -341,7 +341,7 @@ JIT_WARNING
if(ThreadManager::getInstance()->stopAll() > 0){
$logger->debug("Some threads could not be stopped, performing a force-kill");
Process::kill(Process::pid(), true);
Process::kill(Process::pid());
}
}while(false);

View File

@ -1011,7 +1011,7 @@ class Server{
$this->playerDataProvider = new DatFilePlayerDataProvider(Path::join($this->dataPath, "players"));
register_shutdown_function([$this, "crashDump"]);
register_shutdown_function($this->crashDump(...));
$loadErrorCount = 0;
$this->pluginManager->loadPlugins($this->pluginPath, $loadErrorCount);
@ -1429,7 +1429,7 @@ class Server{
private function forceShutdownExit() : void{
$this->forceShutdown();
Process::kill(Process::pid(), true);
Process::kill(Process::pid());
}
public function forceShutdown() : void{
@ -1497,7 +1497,7 @@ class Server{
}catch(\Throwable $e){
$this->logger->logException($e);
$this->logger->emergency("Crashed while crashing, killing process");
@Process::kill(Process::pid(), true);
@Process::kill(Process::pid());
}
}
@ -1651,7 +1651,7 @@ class Server{
echo "--- Waiting $spacing seconds to throttle automatic restart (you can kill the process safely now) ---" . PHP_EOL;
sleep($spacing);
}
@Process::kill(Process::pid(), true);
@Process::kill(Process::pid());
exit(1);
}

View File

@ -38,7 +38,7 @@ use function in_array;
abstract class BaseRail extends Flowable{
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($blockReplace->getSide(Facing::DOWN)->getSupportType(Facing::UP)->hasEdgeSupport()){
if($blockReplace->getAdjacentSupportType(Facing::DOWN)->hasEdgeSupport()){
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
@ -222,7 +222,7 @@ abstract class BaseRail extends Flowable{
public function onNearbyBlockChange() : void{
$world = $this->position->getWorld();
if(!$this->getSide(Facing::DOWN)->getSupportType(Facing::UP)->hasEdgeSupport()){
if(!$this->getAdjacentSupportType(Facing::DOWN)->hasEdgeSupport()){
$world->useBreakOn($this->position);
}else{
foreach($this->getCurrentShapeConnections() as $connection){

View File

@ -177,11 +177,11 @@ class Bed extends Transparent{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($this->canBeSupportedBy($this->getSide(Facing::DOWN))){
if($this->canBeSupportedAt($blockReplace)){
$this->facing = $player !== null ? $player->getHorizontalFacing() : Facing::NORTH;
$next = $this->getSide($this->getOtherHalfSide());
if($next->canBeReplaced() && $this->canBeSupportedBy($next->getSide(Facing::DOWN))){
if($next->canBeReplaced() && $this->canBeSupportedAt($next)){
$nextState = clone $this;
$nextState->head = true;
$tx->addBlock($blockReplace->position, $this)->addBlock($next->position, $nextState);
@ -208,8 +208,8 @@ class Bed extends Transparent{
return parent::getAffectedBlocks();
}
private function canBeSupportedBy(Block $block) : bool{
return !$block->getSupportType(Facing::UP)->equals(SupportType::NONE());
private function canBeSupportedAt(Block $block) : bool{
return !$block->getAdjacentSupportType(Facing::DOWN)->equals(SupportType::NONE());
}
public function getMaxStackSize() : int{ return 1; }

View File

@ -35,6 +35,7 @@ use pocketmine\math\Facing;
use pocketmine\math\RayTraceResult;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\world\BlockTransaction;
use pocketmine\world\sound\BellRingSound;
@ -87,46 +88,44 @@ final class Bell extends Transparent{
return $this;
}
private function canBeSupportedBy(Block $block, int $face) : bool{
return !$block->getSupportType($face)->equals(SupportType::NONE());
private function canBeSupportedAt(Block $block, int $face) : bool{
return !$block->getAdjacentSupportType($face)->equals(SupportType::NONE());
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->canBeSupportedAt($blockReplace, Facing::opposite($face))){
return false;
}
if($face === Facing::UP){
if(!$this->canBeSupportedBy($tx->fetchBlock($this->position->down()), Facing::UP)){
return false;
}
if($player !== null){
$this->setFacing(Facing::opposite($player->getHorizontalFacing()));
}
$this->setAttachmentType(BellAttachmentType::FLOOR());
}elseif($face === Facing::DOWN){
if(!$this->canBeSupportedBy($tx->fetchBlock($this->position->up()), Facing::DOWN)){
return false;
}
$this->setAttachmentType(BellAttachmentType::CEILING());
}else{
$this->setFacing($face);
if($this->canBeSupportedBy($tx->fetchBlock($this->position->getSide(Facing::opposite($face))), $face)){
$this->setAttachmentType(BellAttachmentType::ONE_WALL());
}else{
return false;
}
if($this->canBeSupportedBy($tx->fetchBlock($this->position->getSide($face)), Facing::opposite($face))){
$this->setAttachmentType(BellAttachmentType::TWO_WALLS());
}
$this->setAttachmentType(
$this->canBeSupportedAt($blockReplace, $face) ?
BellAttachmentType::TWO_WALLS() :
BellAttachmentType::ONE_WALL()
);
}
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
public function onNearbyBlockChange() : void{
if(
($this->attachmentType->equals(BellAttachmentType::CEILING()) && !$this->canBeSupportedBy($this->getSide(Facing::UP), Facing::DOWN)) ||
($this->attachmentType->equals(BellAttachmentType::FLOOR()) && !$this->canBeSupportedBy($this->getSide(Facing::DOWN), Facing::UP)) ||
($this->attachmentType->equals(BellAttachmentType::ONE_WALL()) && !$this->canBeSupportedBy($this->getSide(Facing::opposite($this->facing)), $this->facing)) ||
($this->attachmentType->equals(BellAttachmentType::TWO_WALLS()) && (!$this->canBeSupportedBy($this->getSide($this->facing), Facing::opposite($this->facing)) || !$this->canBeSupportedBy($this->getSide(Facing::opposite($this->facing)), $this->facing)))
){
$this->position->getWorld()->useBreakOn($this->position);
foreach(match($this->attachmentType){
BellAttachmentType::CEILING() => [Facing::UP],
BellAttachmentType::FLOOR() => [Facing::DOWN],
BellAttachmentType::ONE_WALL() => [Facing::opposite($this->facing)],
BellAttachmentType::TWO_WALLS() => [$this->facing, Facing::opposite($this->facing)],
default => throw new AssumptionFailedError("All cases of BellAttachmentType must be handled")
} as $supportBlockDirection){
if(!$this->canBeSupportedAt($this, $supportBlockDirection)){
$this->position->getWorld()->useBreakOn($this->position);
break;
}
}
}
@ -159,13 +158,11 @@ final class Bell extends Transparent{
}
private function isValidFaceToRing(int $faceHit) : bool{
return (
$this->attachmentType->equals(BellAttachmentType::CEILING()) ||
($this->attachmentType->equals(BellAttachmentType::FLOOR()) && Facing::axis($faceHit) === Facing::axis($this->facing)) ||
(
($this->attachmentType->equals(BellAttachmentType::ONE_WALL()) || $this->attachmentType->equals(BellAttachmentType::TWO_WALLS())) &&
($faceHit === Facing::rotateY($this->facing, false) || $faceHit === Facing::rotateY($this->facing, true))
)
);
return match($this->attachmentType){
BellAttachmentType::CEILING() => true,
BellAttachmentType::FLOOR() => Facing::axis($faceHit) === Facing::axis($this->facing),
BellAttachmentType::ONE_WALL(), BellAttachmentType::TWO_WALLS() => $faceHit === Facing::rotateY($this->facing, false) || $faceHit === Facing::rotateY($this->facing, true),
default => throw new AssumptionFailedError("All cases of BellAttachmentType must be handled")
};
}
}

View File

@ -41,6 +41,7 @@ use pocketmine\item\Item;
use pocketmine\item\ItemBlock;
use pocketmine\math\Axis;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
use pocketmine\math\RayTraceResult;
use pocketmine\math\Vector3;
use pocketmine\nbt\tag\CompoundTag;
@ -863,6 +864,10 @@ class Block{
return SupportType::FULL();
}
protected function getAdjacentSupportType(int $facing) : SupportType{
return $this->getSide($facing)->getSupportType(Facing::opposite($facing));
}
public function isFullCube() : bool{
$bb = $this->getCollisionBoxes();

View File

@ -52,7 +52,7 @@ abstract class Button extends Flowable{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($this->canBeSupportedBy($blockReplace->getSide(Facing::opposite($face)), $face)){
if($this->canBeSupportedAt($blockReplace, $face)){
$this->facing = $face;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
@ -83,12 +83,12 @@ abstract class Button extends Flowable{
}
public function onNearbyBlockChange() : void{
if(!$this->canBeSupportedBy($this->getSide(Facing::opposite($this->facing)), $this->facing)){
if(!$this->canBeSupportedAt($this, $this->facing)){
$this->position->getWorld()->useBreakOn($this->position);
}
}
private function canBeSupportedBy(Block $support, int $face) : bool{
return $support->getSupportType($face)->hasCenterSupport();
private function canBeSupportedAt(Block $block, int $face) : bool{
return $block->getAdjacentSupportType(Facing::opposite($face))->hasCenterSupport();
}
}

View File

@ -104,8 +104,7 @@ class Candle extends Transparent{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$down = $blockReplace->getSide(Facing::DOWN);
if(!$down->getSupportType(Facing::UP)->hasCenterSupport()){
if(!$blockReplace->getAdjacentSupportType(Facing::DOWN)->hasCenterSupport()){
return false;
}
$existing = $this->getCandleIfCompatibleType($blockReplace);

View File

@ -87,18 +87,18 @@ class CaveVines extends Flowable{
return $this->berries ? 14 : 0;
}
private function canBeSupportedBy(Block $block) : bool{
return $block->getSupportType(Facing::DOWN)->equals(SupportType::FULL()) || $block->hasSameTypeId($this);
private function canBeSupportedAt(Block $block) : bool{
return $block->getAdjacentSupportType(Facing::UP)->equals(SupportType::FULL()) || $block->hasSameTypeId($this);
}
public function onNearbyBlockChange() : void{
if(!$this->canBeSupportedBy($this->getSide(Facing::UP))){
if(!$this->canBeSupportedAt($this)){
$this->position->getWorld()->useBreakOn($this->position);
}
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->canBeSupportedBy($blockReplace->getSide(Facing::UP))){
if(!$this->canBeSupportedAt($blockReplace)){
return false;
}
$this->age = mt_rand(0, self::MAX_AGE);

View File

@ -32,7 +32,7 @@ use pocketmine\world\BlockTransaction;
final class Coral extends BaseCoral{
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->canBeSupportedBy($tx->fetchBlock($blockReplace->getPosition()->down()))){
if(!$this->canBeSupportedAt($blockReplace)){
return false;
}
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
@ -40,14 +40,14 @@ final class Coral extends BaseCoral{
public function onNearbyBlockChange() : void{
$world = $this->position->getWorld();
if(!$this->canBeSupportedBy($world->getBlock($this->position->down()))){
if(!$this->canBeSupportedAt($this)){
$world->useBreakOn($this->position);
}else{
parent::onNearbyBlockChange();
}
}
private function canBeSupportedBy(Block $block) : bool{
return $block->getSupportType(Facing::UP)->hasCenterSupport();
private function canBeSupportedAt(Block $block) : bool{
return $block->getAdjacentSupportType(Facing::DOWN)->hasCenterSupport();
}
}

View File

@ -106,7 +106,7 @@ class Door extends Transparent{
}
public function onNearbyBlockChange() : void{
if(!$this->canBeSupportedBy($this->getSide(Facing::DOWN)) && !$this->getSide(Facing::DOWN) instanceof Door){ //Replace with common break method
if(!$this->canBeSupportedAt($this) && !$this->getSide(Facing::DOWN) instanceof Door){ //Replace with common break method
$this->position->getWorld()->useBreakOn($this->position); //this will delete both halves if they exist
}
}
@ -114,8 +114,7 @@ class Door extends Transparent{
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($face === Facing::UP){
$blockUp = $this->getSide(Facing::UP);
$blockDown = $this->getSide(Facing::DOWN);
if(!$blockUp->canBeReplaced() || !$this->canBeSupportedBy($blockDown)){
if(!$blockUp->canBeReplaced() || !$this->canBeSupportedAt($blockReplace)){
return false;
}
@ -172,7 +171,7 @@ class Door extends Transparent{
return parent::getAffectedBlocks();
}
private function canBeSupportedBy(Block $block) : bool{
return $block->getSupportType(Facing::UP)->hasEdgeSupport();
private function canBeSupportedAt(Block $block) : bool{
return $block->getAdjacentSupportType(Facing::DOWN)->hasEdgeSupport();
}
}

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\event\block\BlockBurnEvent;
use pocketmine\event\block\BlockSpreadEvent;
@ -58,12 +59,16 @@ class Fire extends BaseFire{
return 1;
}
private function canBeSupportedBy(Block $block) : bool{
return $block->getSupportType(Facing::UP)->equals(SupportType::FULL());
}
public function onNearbyBlockChange() : void{
$world = $this->position->getWorld();
$down = $this->getSide(Facing::DOWN);
if(SoulFire::canBeSupportedBy($down)){
$world->setBlock($this->position, VanillaBlocks::SOUL_FIRE());
}elseif($down->isTransparent() && !$this->hasAdjacentFlammableBlocks()){
}elseif(!$this->canBeSupportedBy($this->getSide(Facing::DOWN)) && !$this->hasAdjacentFlammableBlocks()){
$world->setBlock($this->position, VanillaBlocks::AIR());
}else{
$world->scheduleDelayedBlockUpdate($this->position, mt_rand(30, 40));

View File

@ -53,7 +53,7 @@ final class FloorCoralFan extends BaseCoral{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->canBeSupportedBy($tx->fetchBlock($blockReplace->getPosition()->down()))){
if(!$this->canBeSupportedAt($blockReplace)){
return false;
}
if($player !== null){
@ -75,15 +75,15 @@ final class FloorCoralFan extends BaseCoral{
public function onNearbyBlockChange() : void{
$world = $this->position->getWorld();
if(!$this->canBeSupportedBy($world->getBlock($this->position->down()))){
if(!$this->canBeSupportedAt($this)){
$world->useBreakOn($this->position);
}else{
parent::onNearbyBlockChange();
}
}
private function canBeSupportedBy(Block $block) : bool{
return $block->getSupportType(Facing::UP)->hasCenterSupport();
private function canBeSupportedAt(Block $block) : bool{
return $block->getAdjacentSupportType(Facing::DOWN)->hasCenterSupport();
}
public function asItem() : Item{

View File

@ -90,7 +90,7 @@ class FlowerPot extends Flowable{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->canBeSupportedBy($this->getSide(Facing::DOWN))){
if(!$this->canBeSupportedAt($blockReplace)){
return false;
}
@ -98,13 +98,13 @@ class FlowerPot extends Flowable{
}
public function onNearbyBlockChange() : void{
if(!$this->canBeSupportedBy($this->getSide(Facing::DOWN))){
if(!$this->canBeSupportedAt($this)){
$this->position->getWorld()->useBreakOn($this->position);
}
}
private function canBeSupportedBy(Block $block) : bool{
return $block->getSupportType(Facing::UP)->hasCenterSupport();
private function canBeSupportedAt(Block $block) : bool{
return $block->getAdjacentSupportType(Facing::DOWN)->hasCenterSupport();
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{

View File

@ -48,12 +48,7 @@ class FrostedIce extends Ice{
}
public function onNearbyBlockChange() : void{
$world = $this->position->getWorld();
if(!$this->checkAdjacentBlocks(2)){
$world->useBreakOn($this->position);
}else{
$world->scheduleDelayedBlockUpdate($this->position, mt_rand(20, 40));
}
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, mt_rand(20, 40));
}
public function onRandomTick() : void{

View File

@ -121,7 +121,7 @@ class GlowLichen extends Transparent{
$changed = false;
foreach($this->faces as $face){
if(!$this->getSide($face)->getSupportType(Facing::opposite($face))->equals(SupportType::FULL())){
if(!$this->getAdjacentSupportType($face)->equals(SupportType::FULL())){
unset($this->faces[$face]);
$changed = true;
}
@ -275,7 +275,7 @@ class GlowLichen extends Transparent{
private function getAvailableFaces() : array{
$faces = [];
foreach(Facing::ALL as $face){
if(!$this->hasFace($face) && $this->getSide($face)->getSupportType(Facing::opposite($face))->equals(SupportType::FULL())){
if(!$this->hasFace($face) && $this->getAdjacentSupportType($face)->equals(SupportType::FULL())){
$faces[$face] = $face;
}
}

View File

@ -163,18 +163,18 @@ class ItemFrame extends Flowable{
return true;
}
private function canBeSupportedBy(Block $block, int $face) : bool{
return !$block->getSupportType($face)->equals(SupportType::NONE());
private function canBeSupportedAt(Block $block, int $face) : bool{
return !$block->getAdjacentSupportType($face)->equals(SupportType::NONE());
}
public function onNearbyBlockChange() : void{
if(!$this->canBeSupportedBy($this->getSide(Facing::opposite($this->facing)), $this->facing)){
if(!$this->canBeSupportedAt($this, Facing::opposite($this->facing))){
$this->position->getWorld()->useBreakOn($this->position);
}
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->canBeSupportedBy($blockReplace->getSide(Facing::opposite($face)), $face)){
if(!$this->canBeSupportedAt($blockReplace, Facing::opposite($face))){
return false;
}

View File

@ -70,7 +70,7 @@ class Ladder extends Transparent{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($this->canBeSupportedBy($blockReplace->getSide(Facing::opposite($face)), $face) && Facing::axis($face) !== Axis::Y){
if($this->canBeSupportedAt($blockReplace, Facing::opposite($face)) && Facing::axis($face) !== Axis::Y){
$this->facing = $face;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
@ -79,12 +79,12 @@ class Ladder extends Transparent{
}
public function onNearbyBlockChange() : void{
if(!$this->canBeSupportedBy($this->getSide(Facing::opposite($this->facing)), $this->facing)){ //Replace with common break method
if(!$this->canBeSupportedAt($this, Facing::opposite($this->facing))){ //Replace with common break method
$this->position->getWorld()->useBreakOn($this->position);
}
}
private function canBeSupportedBy(Block $block, int $face) : bool{
return $block->getSupportType($face)->equals(SupportType::FULL());
private function canBeSupportedAt(Block $block, int $face) : bool{
return $block->getAdjacentSupportType($face)->equals(SupportType::FULL());
}
}

View File

@ -77,22 +77,23 @@ class Lantern extends Transparent{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->canBeSupportedBy($blockReplace->getSide(Facing::UP), Facing::DOWN) && !$this->canBeSupportedBy($blockReplace->getSide(Facing::DOWN), Facing::UP)){
$downSupport = $this->canBeSupportedAt($blockReplace, Facing::DOWN);
if(!$downSupport && !$this->canBeSupportedAt($blockReplace, Facing::UP)){
return false;
}
$this->hanging = ($face === Facing::DOWN || !$this->canBeSupportedBy($this->position->getWorld()->getBlock($blockReplace->getPosition()->down()), Facing::UP));
$this->hanging = $face === Facing::DOWN || !$downSupport;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
public function onNearbyBlockChange() : void{
$face = $this->hanging ? Facing::UP : Facing::DOWN;
if(!$this->canBeSupportedBy($this->getSide($face), Facing::opposite($face))){
if(!$this->canBeSupportedAt($this, $face)){
$this->position->getWorld()->useBreakOn($this->position);
}
}
private function canBeSupportedBy(Block $block, int $face) : bool{
return $block->getSupportType($face)->hasCenterSupport();
private function canBeSupportedAt(Block $block, int $face) : bool{
return $block->getAdjacentSupportType($face)->hasCenterSupport();
}
}

View File

@ -66,7 +66,7 @@ class Lever extends Flowable{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->canBeSupportedBy($blockReplace->getSide(Facing::opposite($face)), $face)){
if(!$this->canBeSupportedAt($blockReplace, Facing::opposite($face))){
return false;
}
@ -90,8 +90,7 @@ class Lever extends Flowable{
}
public function onNearbyBlockChange() : void{
$facing = $this->facing->getFacing();
if(!$this->canBeSupportedBy($this->getSide(Facing::opposite($facing)), $facing)){
if(!$this->canBeSupportedAt($this, Facing::opposite($this->facing->getFacing()))){
$this->position->getWorld()->useBreakOn($this->position);
}
}
@ -107,8 +106,8 @@ class Lever extends Flowable{
return true;
}
private function canBeSupportedBy(Block $block, int $face) : bool{
return $block->getSupportType($face)->hasCenterSupport();
private function canBeSupportedAt(Block $block, int $face) : bool{
return $block->getAdjacentSupportType($face)->hasCenterSupport();
}
//TODO

View File

@ -312,7 +312,7 @@ abstract class Liquid extends Transparent{
}
if($adjacentDecay <= self::MAX_DECAY){
$calculator = new MinimumCostFlowCalculator($world, $this->getFlowDecayPerBlock(), \Closure::fromCallable([$this, 'canFlowInto']));
$calculator = new MinimumCostFlowCalculator($world, $this->getFlowDecayPerBlock(), $this->canFlowInto(...));
foreach($calculator->getOptimalFlowDirections($this->position->getFloorX(), $this->position->getFloorY(), $this->position->getFloorZ()) as $facing){
$this->flowIntoBlock($world->getBlock($this->position->getSide($facing)), $adjacentDecay, false);
}

View File

@ -83,16 +83,13 @@ class NetherVines extends Flowable{
return true;
}
private function getSupportFace() : int{
return Facing::opposite($this->growthFace);
}
private function canBeSupportedBy(Block $block) : bool{
return $block->getSupportType($this->getSupportFace())->hasCenterSupport() || $block->hasSameTypeId($this);
private function canBeSupportedAt(Block $block) : bool{
$supportBlock = $block->getSide(Facing::opposite($this->growthFace));
return $supportBlock->getSupportType($this->growthFace)->hasCenterSupport() || $supportBlock->hasSameTypeId($this);
}
public function onNearbyBlockChange() : void{
if(!$this->canBeSupportedBy($this->getSide($this->getSupportFace()))){
if(!$this->canBeSupportedAt($this)){
$this->position->getWorld()->useBreakOn($this->position);
}
}
@ -109,7 +106,7 @@ class NetherVines extends Flowable{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->canBeSupportedBy($blockReplace->getSide($this->getSupportFace()))){
if(!$this->canBeSupportedAt($blockReplace)){
return false;
}
$this->age = mt_rand(0, self::MAX_AGE - 1);

View File

@ -45,18 +45,18 @@ abstract class PressurePlate extends Transparent{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($this->canBeSupportedBy($blockReplace->getSide(Facing::DOWN))){
if($this->canBeSupportedAt($blockReplace)){
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
return false;
}
private function canBeSupportedBy(Block $block) : bool{
return !$block->getSupportType(Facing::UP)->equals(SupportType::NONE());
private function canBeSupportedAt(Block $block) : bool{
return !$block->getAdjacentSupportType(Facing::DOWN)->equals(SupportType::NONE());
}
public function onNearbyBlockChange() : void{
if(!$this->canBeSupportedBy($this->getSide(Facing::DOWN))){
if(!$this->canBeSupportedAt($this)){
$this->position->getWorld()->useBreakOn($this->position);
}
}

View File

@ -85,7 +85,7 @@ class RedstoneComparator extends Flowable{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($this->canBeSupportedBy($blockReplace->getSide(Facing::DOWN))){
if($this->canBeSupportedAt($blockReplace)){
if($player !== null){
$this->facing = Facing::opposite($player->getHorizontalFacing());
}
@ -102,13 +102,13 @@ class RedstoneComparator extends Flowable{
}
public function onNearbyBlockChange() : void{
if(!$this->canBeSupportedBy($this->getSide(Facing::DOWN))){
if(!$this->canBeSupportedAt($this)){
$this->position->getWorld()->useBreakOn($this->position);
}
}
private function canBeSupportedBy(Block $block) : bool{
return !$block->getSupportType(Facing::UP)->equals(SupportType::NONE());
private function canBeSupportedAt(Block $block) : bool{
return !$block->getAdjacentSupportType(Facing::DOWN)->equals(SupportType::NONE());
}
//TODO: redstone functionality

View File

@ -68,7 +68,7 @@ class RedstoneRepeater extends Flowable{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($this->canBeSupportedBy($blockReplace->getSide(Facing::DOWN))){
if($this->canBeSupportedAt($blockReplace)){
if($player !== null){
$this->facing = Facing::opposite($player->getHorizontalFacing());
}
@ -88,13 +88,13 @@ class RedstoneRepeater extends Flowable{
}
public function onNearbyBlockChange() : void{
if(!$this->canBeSupportedBy($this->getSide(Facing::DOWN))){
if(!$this->canBeSupportedAt($this)){
$this->position->getWorld()->useBreakOn($this->position);
}
}
private function canBeSupportedBy(Block $block) : bool{
return !$block->getSupportType(Facing::UP)->equals(SupportType::NONE());
private function canBeSupportedAt(Block $block) : bool{
return !$block->getAdjacentSupportType(Facing::DOWN)->equals(SupportType::NONE());
}
//TODO: redstone functionality

View File

@ -35,7 +35,7 @@ class RedstoneWire extends Flowable{
use AnalogRedstoneSignalEmitterTrait;
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($this->canBeSupportedBy($this->getSide(Facing::DOWN))){
if($this->canBeSupportedAt($blockReplace)){
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
return false;
@ -49,13 +49,13 @@ class RedstoneWire extends Flowable{
}
public function onNearbyBlockChange() : void{
if(!$this->canBeSupportedBy($this->getSide(Facing::DOWN))){
if(!$this->canBeSupportedAt($this)){
$this->position->getWorld()->useBreakOn($this->position);
}
}
private function canBeSupportedBy(Block $block) : bool{
return $block->getSupportType(Facing::UP)->hasCenterSupport();
private function canBeSupportedAt(Block $block) : bool{
return $block->getAdjacentSupportType(Facing::DOWN)->hasCenterSupport();
}
public function asItem() : Item{

View File

@ -25,6 +25,7 @@ namespace pocketmine\block;
use pocketmine\block\tile\ShulkerBox as TileShulkerBox;
use pocketmine\block\utils\AnyFacingTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Item;
use pocketmine\math\Vector3;
@ -110,4 +111,8 @@ class ShulkerBox extends Opaque{
return true;
}
public function getSupportType(int $facing) : SupportType{
return SupportType::NONE();
}
}

View File

@ -80,8 +80,8 @@ class SnowLayer extends Flowable implements Fallable{
return SupportType::NONE();
}
private function canBeSupportedBy(Block $b) : bool{
return $b->getSupportType(Facing::UP)->equals(SupportType::FULL());
private function canBeSupportedAt(Block $block) : bool{
return $block->getAdjacentSupportType(Facing::DOWN)->equals(SupportType::FULL());
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
@ -91,7 +91,7 @@ class SnowLayer extends Flowable implements Fallable{
}
$this->layers = $blockReplace->layers + 1;
}
if($this->canBeSupportedBy($blockReplace->getSide(Facing::DOWN))){
if($this->canBeSupportedAt($blockReplace)){
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}

View File

@ -32,12 +32,12 @@ use pocketmine\world\BlockTransaction;
final class SporeBlossom extends Flowable{
private function canBeSupportedBy(Block $block) : bool{
return $block->getSupportType(Facing::DOWN)->equals(SupportType::FULL());
private function canBeSupportedAt(Block $block) : bool{
return $block->getAdjacentSupportType(Facing::UP)->equals(SupportType::FULL());
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->canBeSupportedBy($blockReplace->getSide(Facing::UP))){
if(!$this->canBeSupportedAt($blockReplace)){
return false;
}
@ -45,7 +45,7 @@ final class SporeBlossom extends Flowable{
}
public function onNearbyBlockChange() : void{
if(!$this->canBeSupportedBy($this->getSide(Facing::UP))){
if(!$this->canBeSupportedAt($this)){
$this->position->getWorld()->useBreakOn($this->position);
}
}

View File

@ -26,7 +26,6 @@ namespace pocketmine\block;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Item;
use pocketmine\math\Axis;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
@ -56,15 +55,13 @@ class Torch extends Flowable{
}
public function onNearbyBlockChange() : void{
$face = Facing::opposite($this->facing);
if(!$this->canBeSupportedBy($this->getSide($face), $this->facing)){
if(!$this->canBeSupportedAt($this, Facing::opposite($this->facing))){
$this->position->getWorld()->useBreakOn($this->position);
}
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($face !== Facing::DOWN && $this->canBeSupportedBy($blockReplace->getSide(Facing::opposite($face)), $face)){
if($face !== Facing::DOWN && $this->canBeSupportedAt($blockReplace, Facing::opposite($face))){
$this->facing = $face;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}else{
@ -75,8 +72,7 @@ class Torch extends Flowable{
Facing::EAST,
Facing::DOWN
] as $side){
$block = $this->getSide($side);
if($this->canBeSupportedBy($block, Facing::opposite($side))){
if($this->canBeSupportedAt($blockReplace, $side)){
$this->facing = Facing::opposite($side);
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
@ -85,8 +81,9 @@ class Torch extends Flowable{
return false;
}
private function canBeSupportedBy(Block $support, int $face) : bool{
return ($face === Facing::UP && $support->getSupportType($face)->hasCenterSupport()) ||
(Facing::axis($face) !== Axis::Y && $support->getSupportType($face)->equals(SupportType::FULL()));
private function canBeSupportedAt(Block $block, int $face) : bool{
return $face === Facing::DOWN ?
$block->getAdjacentSupportType($face)->hasCenterSupport() :
$block->getAdjacentSupportType($face)->equals(SupportType::FULL());
}
}

View File

@ -42,7 +42,7 @@ final class WallCoralFan extends BaseCoral{
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$axis = Facing::axis($face);
if(($axis !== Axis::X && $axis !== Axis::Z) || !$this->canBeSupportedBy($blockReplace->getSide(Facing::opposite($face)), $face)){
if(($axis !== Axis::X && $axis !== Axis::Z) || !$this->canBeSupportedAt($blockReplace, Facing::opposite($face))){
return false;
}
$this->facing = $face;
@ -54,15 +54,15 @@ final class WallCoralFan extends BaseCoral{
public function onNearbyBlockChange() : void{
$world = $this->position->getWorld();
if(!$this->canBeSupportedBy($world->getBlock($this->position->getSide(Facing::opposite($this->facing))), $this->facing)){
if(!$this->canBeSupportedAt($this, Facing::opposite($this->facing))){
$world->useBreakOn($this->position);
}else{
parent::onNearbyBlockChange();
}
}
private function canBeSupportedBy(Block $block, int $face) : bool{
return $block->getSupportType($face)->hasCenterSupport();
private function canBeSupportedAt(Block $block, int $face) : bool{
return $block->getAdjacentSupportType($face)->hasCenterSupport();
}
public function asItem() : Item{

View File

@ -53,7 +53,7 @@ class KillCommand extends VanillaCommand{
return true;
}
$player->attack(new EntityDamageEvent($player, EntityDamageEvent::CAUSE_SUICIDE, 1000));
$player->attack(new EntityDamageEvent($player, EntityDamageEvent::CAUSE_SUICIDE, $player->getHealth()));
if($player === $sender){
$sender->sendMessage(KnownTranslationFactory::commands_kill_successful($sender->getName()));
}else{

View File

@ -94,4 +94,4 @@ while(!feof($socket)){
//For simplicity's sake, we don't bother with a graceful shutdown here.
//The parent process would normally forcibly terminate the child process anyway, so we only reach this point if the
//parent process was terminated forcibly and didn't clean up after itself.
Process::kill(Process::pid(), false);
Process::kill(Process::pid());

View File

@ -209,9 +209,6 @@ final class CraftingManagerFromDataHelper{
public static function make(string $directoryPath) : CraftingManager{
$result = new CraftingManager();
$ingredientDeserializerFunc = \Closure::fromCallable([self::class, "deserializeIngredient"]);
$itemDeserializerFunc = \Closure::fromCallable([self::class, 'deserializeItemStack']);
foreach(self::loadJsonArrayOfObjectsFile(Path::join($directoryPath, 'shapeless_crafting.json'), ShapelessRecipeData::class) as $recipe){
$recipeType = match($recipe->block){
"crafting_table" => ShapelessRecipeType::CRAFTING(),
@ -225,7 +222,7 @@ final class CraftingManagerFromDataHelper{
}
$inputs = [];
foreach($recipe->input as $inputData){
$input = $ingredientDeserializerFunc($inputData);
$input = self::deserializeIngredient($inputData);
if($input === null){ //unknown input item
continue 2;
}
@ -233,7 +230,7 @@ final class CraftingManagerFromDataHelper{
}
$outputs = [];
foreach($recipe->output as $outputData){
$output = $itemDeserializerFunc($outputData);
$output = self::deserializeItemStack($outputData);
if($output === null){ //unknown output item
continue 2;
}
@ -251,7 +248,7 @@ final class CraftingManagerFromDataHelper{
}
$inputs = [];
foreach(Utils::stringifyKeys($recipe->input) as $symbol => $inputData){
$input = $ingredientDeserializerFunc($inputData);
$input = self::deserializeIngredient($inputData);
if($input === null){ //unknown input item
continue 2;
}
@ -259,7 +256,7 @@ final class CraftingManagerFromDataHelper{
}
$outputs = [];
foreach($recipe->output as $outputData){
$output = $itemDeserializerFunc($outputData);
$output = self::deserializeItemStack($outputData);
if($output === null){ //unknown output item
continue 2;
}

View File

@ -519,7 +519,12 @@ abstract class Entity{
}
public function attack(EntityDamageEvent $source) : void{
if($this->isFireProof() && ($source->getCause() === EntityDamageEvent::CAUSE_FIRE || $source->getCause() === EntityDamageEvent::CAUSE_FIRE_TICK)){
if($this->isFireProof() && (
$source->getCause() === EntityDamageEvent::CAUSE_FIRE ||
$source->getCause() === EntityDamageEvent::CAUSE_FIRE_TICK ||
$source->getCause() === EntityDamageEvent::CAUSE_LAVA
)
){
$source->cancel();
}
$source->call();
@ -686,8 +691,10 @@ abstract class Entity{
if($fireTicks < 0 || $fireTicks > 0x7fff){
throw new \InvalidArgumentException("Fire ticks must be in range 0 ... " . 0x7fff . ", got $fireTicks");
}
$this->fireTicks = $fireTicks;
$this->networkPropertiesDirty = true;
if(!$this->isFireProof()){
$this->fireTicks = $fireTicks;
$this->networkPropertiesDirty = true;
}
}
public function extinguish() : void{
@ -700,12 +707,13 @@ abstract class Entity{
}
protected function doOnFireTick(int $tickDiff = 1) : bool{
if($this->isFireProof() && $this->fireTicks > 1){
$this->fireTicks = 1;
}else{
$this->fireTicks -= $tickDiff;
if($this->isFireProof() && $this->isOnFire()){
$this->extinguish();
return false;
}
$this->fireTicks -= $tickDiff;
if(($this->fireTicks % 20 === 0) || $tickDiff > 20){
$this->dealFireDamage();
}

View File

@ -507,7 +507,7 @@ abstract class Living extends Entity{
}
public function attack(EntityDamageEvent $source) : void{
if($this->noDamageTicks > 0){
if($this->noDamageTicks > 0 && $source->getCause() !== EntityDamageEvent::CAUSE_SUICIDE){
$source->cancel();
}
@ -520,7 +520,9 @@ abstract class Living extends Entity{
$source->cancel();
}
$this->applyDamageModifiers($source);
if($source->getCause() !== EntityDamageEvent::CAUSE_SUICIDE){
$this->applyDamageModifiers($source);
}
if($source instanceof EntityDamageByEntityEvent && (
$source->getCause() === EntityDamageEvent::CAUSE_BLOCK_EXPLOSION ||

View File

@ -108,7 +108,7 @@ class InventoryManager{
private NetworkSession $session
){
$this->containerOpenCallbacks = new ObjectSet();
$this->containerOpenCallbacks->add(\Closure::fromCallable([self::class, 'createContainerOpen']));
$this->containerOpenCallbacks->add(self::createContainerOpen(...));
$this->add(ContainerIds::INVENTORY, $this->player->getInventory());
$this->add(ContainerIds::OFFHAND, $this->player->getOffHandInventory());
@ -116,9 +116,7 @@ class InventoryManager{
$this->addComplex(UIInventorySlotOffset::CURSOR, $this->player->getCursorInventory());
$this->addComplex(UIInventorySlotOffset::CRAFTING2X2_INPUT, $this->player->getCraftingGrid());
$this->player->getInventory()->getHeldItemIndexChangeListeners()->add(function() : void{
$this->syncSelectedHotbarSlot();
});
$this->player->getInventory()->getHeldItemIndexChangeListeners()->add($this->syncSelectedHotbarSlot(...));
}
private function associateIdWithInventory(int $id, Inventory $inventory) : void{

View File

@ -197,7 +197,7 @@ class NetworkSession{
$this->setHandler(new SessionStartPacketHandler(
$this,
fn() => $this->onSessionStartSuccess()
$this->onSessionStartSuccess(...)
));
$this->manager->add($this);
@ -225,13 +225,13 @@ class NetworkSession{
$this->logger->setPrefix($this->getLogPrefix());
$this->manager->markLoginReceived($this);
},
\Closure::fromCallable([$this, "setAuthenticationStatus"])
$this->setAuthenticationStatus(...)
));
}
protected function createPlayer() : void{
$this->server->createPlayer($this, $this->info, $this->authenticated, $this->cachedOfflinePlayerData)->onCompletion(
\Closure::fromCallable([$this, 'onPlayerCreated']),
$this->onPlayerCreated(...),
function() : void{
//TODO: this should never actually occur... right?
$this->logger->error("Failed to create player");
@ -787,9 +787,7 @@ class NetworkSession{
$this->cipher = EncryptionContext::fakeGCM($encryptionKey);
$this->setHandler(new HandshakePacketHandler(function() : void{
$this->onServerLoginSuccess();
}));
$this->setHandler(new HandshakePacketHandler($this->onServerLoginSuccess(...)));
$this->logger->debug("Enabled encryption");
}));
}else{
@ -818,9 +816,7 @@ class NetworkSession{
public function notifyTerrainReady() : void{
$this->logger->debug("Sending spawn notification, waiting for spawn response");
$this->sendDataPacket(PlayStatusPacket::create(PlayStatusPacket::PLAYER_SPAWN));
$this->setHandler(new SpawnResponsePacketHandler(function() : void{
$this->onClientSpawnResponse();
}));
$this->setHandler(new SpawnResponsePacketHandler($this->onClientSpawnResponse(...)));
}
private function onClientSpawnResponse() : void{

View File

@ -139,6 +139,6 @@ final class StandardEntityEventBroadcaster implements EntityEventBroadcaster{
}
public function onEmote(array $recipients, Human $from, string $emoteId) : void{
$this->sendDataPacket($recipients, EmotePacket::create($from->getId(), $emoteId, "", "", EmotePacket::FLAG_SERVER));
$this->sendDataPacket($recipients, EmotePacket::create($from->getId(), $emoteId, "", "", EmotePacket::FLAG_SERVER | EmotePacket::FLAG_MUTE_ANNOUNCEMENT));
}
}

View File

@ -25,21 +25,17 @@ namespace pocketmine\network\mcpe\cache;
use pocketmine\crafting\CraftingManager;
use pocketmine\crafting\FurnaceType;
use pocketmine\crafting\RecipeIngredient;
use pocketmine\crafting\ShapedRecipe;
use pocketmine\crafting\ShapelessRecipe;
use pocketmine\crafting\ShapelessRecipeType;
use pocketmine\item\Item;
use pocketmine\network\mcpe\convert\TypeConverter;
use pocketmine\network\mcpe\protocol\CraftingDataPacket;
use pocketmine\network\mcpe\protocol\types\inventory\ItemStack;
use pocketmine\network\mcpe\protocol\types\recipe\CraftingRecipeBlockName;
use pocketmine\network\mcpe\protocol\types\recipe\FurnaceRecipe as ProtocolFurnaceRecipe;
use pocketmine\network\mcpe\protocol\types\recipe\FurnaceRecipeBlockName;
use pocketmine\network\mcpe\protocol\types\recipe\IntIdMetaItemDescriptor;
use pocketmine\network\mcpe\protocol\types\recipe\PotionContainerChangeRecipe as ProtocolPotionContainerChangeRecipe;
use pocketmine\network\mcpe\protocol\types\recipe\PotionTypeRecipe as ProtocolPotionTypeRecipe;
use pocketmine\network\mcpe\protocol\types\recipe\RecipeIngredient as ProtocolRecipeIngredient;
use pocketmine\network\mcpe\protocol\types\recipe\ShapedRecipe as ProtocolShapedRecipe;
use pocketmine\network\mcpe\protocol\types\recipe\ShapelessRecipe as ProtocolShapelessRecipe;
use pocketmine\timings\Timings;
@ -95,12 +91,8 @@ final class CraftingDataCache{
$recipesWithTypeIds[] = new ProtocolShapelessRecipe(
CraftingDataPacket::ENTRY_SHAPELESS,
Binary::writeInt($index),
array_map(function(RecipeIngredient $item) use ($converter) : ProtocolRecipeIngredient{
return $converter->coreRecipeIngredientToNet($item);
}, $recipe->getIngredientList()),
array_map(function(Item $item) use ($converter) : ItemStack{
return $converter->coreItemStackToNet($item);
}, $recipe->getResults()),
array_map($converter->coreRecipeIngredientToNet(...), $recipe->getIngredientList()),
array_map($converter->coreItemStackToNet(...), $recipe->getResults()),
$nullUUID,
$typeTag,
50,
@ -118,9 +110,7 @@ final class CraftingDataCache{
CraftingDataPacket::ENTRY_SHAPED,
Binary::writeInt($index),
$inputs,
array_map(function(Item $item) use ($converter) : ItemStack{
return $converter->coreItemStackToNet($item);
}, $recipe->getResults()),
array_map($converter->coreItemStackToNet(...), $recipe->getResults()),
$nullUUID,
CraftingRecipeBlockName::CRAFTING_TABLE,
50,

View File

@ -30,7 +30,7 @@ use const M_SQRT2;
final class ChunkSelector{
/**
* @preturn \Generator|int[]
* @return \Generator|int[]
* @phpstan-return \Generator<int, int, void, void>
*/
public function selectChunks(int $radius, int $centerX, int $centerZ) : \Generator{

View File

@ -1199,10 +1199,6 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
return !$this->gamemode->equals(GameMode::CREATIVE());
}
public function isFireProof() : bool{
return $this->isCreative();
}
public function getDrops() : array{
if($this->hasFiniteResources()){
return parent::getDrops();
@ -1440,6 +1436,10 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
$this->entityBaseTick($tickDiff);
Timings::$entityBaseTick->stopTiming();
if($this->isCreative() && $this->fireTicks > 1){
$this->fireTicks = 1;
}
if(!$this->isSpectator() && $this->isAlive()){
Timings::$playerCheckNearEntities->startTiming();
$this->checkNearEntities();

View File

@ -125,7 +125,10 @@ final class Process{
return count(ThreadManager::getInstance()->getAll()) + 2; //MainLogger + Main Thread
}
public static function kill(int $pid, bool $subprocesses) : void{
/**
* @param bool $subprocesses @deprecated
*/
public static function kill(int $pid, bool $subprocesses = false) : void{
$logger = \GlobalLogger::get();
if($logger instanceof MainLogger){
$logger->syncFlushBuffer();

View File

@ -121,8 +121,6 @@ trait RegistryTrait{
*/
private static function _registryGetAll() : array{
self::checkInit();
return array_map(function(object $o) : object{
return self::preprocessMember($o);
}, self::$members);
return array_map(self::preprocessMember(...), self::$members);
}
}

View File

@ -42,7 +42,7 @@ class ServerKiller extends Thread{
});
if(time() - $start >= $this->time){
echo "\nTook too long to stop, server was killed forcefully!\n";
@Process::kill(Process::pid(), true);
@Process::kill(Process::pid());
}
}

View File

@ -1610,7 +1610,7 @@ class World implements ChunkManager{
* the current weather and time of day.
*/
public function getHighestAdjacentFullLightAt(int $x, int $y, int $z) : int{
return $this->getHighestAdjacentLight($x, $y, $z, \Closure::fromCallable([$this, 'getFullLightAt']));
return $this->getHighestAdjacentLight($x, $y, $z, $this->getFullLightAt(...));
}
/**
@ -1706,7 +1706,7 @@ class World implements ChunkManager{
* Returns the highest potential level of sky light in the positions adjacent to the specified block coordinates.
*/
public function getHighestAdjacentPotentialBlockSkyLight(int $x, int $y, int $z) : int{
return $this->getHighestAdjacentLight($x, $y, $z, \Closure::fromCallable([$this, 'getPotentialBlockSkyLightAt']));
return $this->getHighestAdjacentLight($x, $y, $z, $this->getPotentialBlockSkyLightAt(...));
}
/**
@ -1721,7 +1721,7 @@ class World implements ChunkManager{
* Returns the highest block light level available in the positions adjacent to the specified block coordinates.
*/
public function getHighestAdjacentBlockLight(int $x, int $y, int $z) : int{
return $this->getHighestAdjacentLight($x, $y, $z, \Closure::fromCallable([$this, 'getBlockLightAt']));
return $this->getHighestAdjacentLight($x, $y, $z, $this->getBlockLightAt(...));
}
private function executeQueuedLightUpdates() : void{

View File

@ -41,13 +41,13 @@ final class WorldProviderManager{
private WritableWorldProviderManagerEntry $default;
public function __construct(){
$leveldb = new WritableWorldProviderManagerEntry(\Closure::fromCallable([LevelDB::class, 'isValid']), fn(string $path, \Logger $logger) => new LevelDB($path, $logger), \Closure::fromCallable([LevelDB::class, 'generate']));
$leveldb = new WritableWorldProviderManagerEntry(LevelDB::isValid(...), fn(string $path, \Logger $logger) => new LevelDB($path, $logger), LevelDB::generate(...));
$this->default = $leveldb;
$this->addProvider($leveldb, "leveldb");
$this->addProvider(new ReadOnlyWorldProviderManagerEntry(\Closure::fromCallable([Anvil::class, 'isValid']), fn(string $path, \Logger $logger) => new Anvil($path, $logger)), "anvil");
$this->addProvider(new ReadOnlyWorldProviderManagerEntry(\Closure::fromCallable([McRegion::class, 'isValid']), fn(string $path, \Logger $logger) => new McRegion($path, $logger)), "mcregion");
$this->addProvider(new ReadOnlyWorldProviderManagerEntry(\Closure::fromCallable([PMAnvil::class, 'isValid']), fn(string $path, \Logger $logger) => new PMAnvil($path, $logger)), "pmanvil");
$this->addProvider(new ReadOnlyWorldProviderManagerEntry(Anvil::isValid(...), fn(string $path, \Logger $logger) => new Anvil($path, $logger)), "anvil");
$this->addProvider(new ReadOnlyWorldProviderManagerEntry(McRegion::isValid(...), fn(string $path, \Logger $logger) => new McRegion($path, $logger)), "mcregion");
$this->addProvider(new ReadOnlyWorldProviderManagerEntry(PMAnvil::isValid(...), fn(string $path, \Logger $logger) => new PMAnvil($path, $logger)), "pmanvil");
}
/**

View File

@ -27,6 +27,7 @@ use pocketmine\block\Block;
use pocketmine\data\bedrock\BiomeIds;
use pocketmine\data\bedrock\block\BlockStateDeserializeException;
use pocketmine\nbt\LittleEndianNbtSerializer;
use pocketmine\nbt\NBT;
use pocketmine\nbt\NbtDataException;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\TreeRoot;
@ -155,7 +156,33 @@ class LevelDB extends BaseWorldProvider implements WritableWorldProvider{
$nbt = new LittleEndianNbtSerializer();
$palette = [];
$paletteSize = $bitsPerBlock === 0 ? 1 : $stream->getLInt();
if($bitsPerBlock === 0){
$paletteSize = 1;
/*
* Due to code copy-paste in a public plugin, some PM4 worlds have 0 bpb palettes with a length prefix.
* This is invalid and does not happen in vanilla.
* These palettes were accepted by PM4 despite being invalid, but PM5 considered them corrupt, causing loss
* of data. Since many users were affected by this, a workaround is therefore necessary to allow PM5 to read
* these worlds without data loss.
*
* References:
* - https://github.com/Refaltor77/CustomItemAPI/issues/68
* - https://github.com/pmmp/PocketMine-MP/issues/5911
*/
$offset = $stream->getOffset();
$byte1 = $stream->getByte();
$stream->setOffset($offset); //reset offset
if($byte1 !== NBT::TAG_Compound){ //normally the first byte would be the NBT of the blockstate
$susLength = $stream->getLInt();
if($susLength !== 1){ //make sure the data isn't complete garbage
throw new CorruptedChunkException("CustomItemAPI borked 0 bpb palette should always have a length of 1");
}
$logger->error("Unexpected palette size for 0 bpb palette");
}
}else{
$paletteSize = $stream->getLInt();
}
for($i = 0; $i < $paletteSize; ++$i){
try{
@ -276,6 +303,10 @@ class LevelDB extends BaseWorldProvider implements WritableWorldProvider{
$previous = $decoded;
if($nextIndex <= Chunk::MAX_SUBCHUNK_INDEX){ //older versions wrote additional superfluous biome palettes
$result[$nextIndex++] = $decoded;
}elseif($stream->feof()){
//not enough padding biome arrays for the given version - this is non-critical since we discard the excess anyway, but this should be logged
$logger->error("Wrong number of 3D biome palettes for this chunk version: expected $expectedCount, but got " . ($i + 1) . " - this is not a problem, but may indicate a corrupted chunk");
break;
}
}catch(BinaryDataException $e){
throw new CorruptedChunkException("Failed to deserialize biome palette $i: " . $e->getMessage(), 0, $e);

View File

@ -78,7 +78,7 @@ final class UnsafeForeachArrayOfStringRule implements Rule{
return $type;
});
if($hasCastableKeyTypes && !$expectsIntKeyTypes){
$func = \Closure::fromCallable([Utils::class, 'stringifyKeys']);
$func = Utils::stringifyKeys(...);
return [
RuleErrorBuilder::message(sprintf(
"Unsafe foreach on array with key type %s (they might be casted to int).",