Merge branch 'minor-next' into major-next

This commit is contained in:
Dylan K. Taylor 2023-07-18 22:22:43 +01:00
commit f2f30143b0
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
28 changed files with 896 additions and 28 deletions

View File

@ -27,6 +27,7 @@ use pocketmine\block\utils\BellAttachmentType;
use pocketmine\block\utils\CopperOxidation;
use pocketmine\block\utils\CoralType;
use pocketmine\block\utils\DirtType;
use pocketmine\block\utils\DripleafState;
use pocketmine\block\utils\DyeColor;
use pocketmine\block\utils\FroglightType;
use pocketmine\block\utils\LeverFacing;
@ -145,6 +146,7 @@ $enumsUsed = [
CopperOxidation::getAll(),
CoralType::getAll(),
DirtType::getAll(),
DripleafState::getAll(),
DyeColor::getAll(),
FroglightType::getAll(),
LeverFacing::getAll(),

View File

@ -24,3 +24,9 @@ Released 14th July 2023.
## Fixes
- Hardened validation of JWT signing keys in `LoginPacket`.
- Fixed server crash due to a bug in upstream dependency [`netresearch/jsonmapper`](https://github.com/cweiske/JsonMapper).
# 4.23.2
Released 18th July 2023.
## Fixes
- Fixed login errors due to a new `sandboxId` field appearing in the Xbox Live authentication data in `LoginPacket`. All clients, regardless of version, are affected by this change.

View File

@ -31,3 +31,19 @@ Released 14th July 2023.
## General
- Updated `build/php` submodule to pmmp/PHP-Binaries@e0c918d1379465964acefd562d9e48f87cfc2c9e.
# 5.3.2
Released 18th July 2023.
## Included releases
**This release includes changes from the following releases:**
- [4.23.2](https://github.com/pmmp/PocketMine-MP/blob/4.23.2/changelogs/4.23.md#4232) - Fix for `sandboxId`-related login errors
## Documentation
- Fixed documentation error in `StringToTParser`.
## Fixes
- Fixed turtle helmet not being able to be unequipped.
## Internals
- Armor pieces are no longer set back into the armor inventory if no change was made. This reduces the number of slot updates sent to clients, as well as avoiding unnecessary updates for armor pieces which have Unbreaking enchantments.

24
composer.lock generated
View File

@ -276,16 +276,16 @@
},
{
"name": "pocketmine/bedrock-protocol",
"version": "23.0.0+bedrock-1.20.10",
"version": "23.0.1+bedrock-1.20.10",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BedrockProtocol.git",
"reference": "0cfaafdc02cca882a50773d6c02ebfeb622614e2"
"reference": "db48400736799cc3833a2644a02e308992a98fa8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/0cfaafdc02cca882a50773d6c02ebfeb622614e2",
"reference": "0cfaafdc02cca882a50773d6c02ebfeb622614e2",
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/db48400736799cc3833a2644a02e308992a98fa8",
"reference": "db48400736799cc3833a2644a02e308992a98fa8",
"shasum": ""
},
"require": {
@ -317,9 +317,9 @@
"description": "An implementation of the Minecraft: Bedrock Edition protocol in PHP",
"support": {
"issues": "https://github.com/pmmp/BedrockProtocol/issues",
"source": "https://github.com/pmmp/BedrockProtocol/tree/23.0.0+bedrock-1.20.10"
"source": "https://github.com/pmmp/BedrockProtocol/tree/23.0.1+bedrock-1.20.10"
},
"time": "2023-07-12T12:19:40+00:00"
"time": "2023-07-18T21:07:24+00:00"
},
{
"name": "pocketmine/binaryutils",
@ -1937,16 +1937,16 @@
},
{
"name": "phpunit/phpunit",
"version": "10.2.5",
"version": "10.2.6",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "15a89f123d8ca9c1e1598d6d87a56a8bf28c72cd"
"reference": "1c17815c129f133f3019cc18e8d0c8622e6d9bcd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/15a89f123d8ca9c1e1598d6d87a56a8bf28c72cd",
"reference": "15a89f123d8ca9c1e1598d6d87a56a8bf28c72cd",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1c17815c129f133f3019cc18e8d0c8622e6d9bcd",
"reference": "1c17815c129f133f3019cc18e8d0c8622e6d9bcd",
"shasum": ""
},
"require": {
@ -2018,7 +2018,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
"source": "https://github.com/sebastianbergmann/phpunit/tree/10.2.5"
"source": "https://github.com/sebastianbergmann/phpunit/tree/10.2.6"
},
"funding": [
{
@ -2034,7 +2034,7 @@
"type": "tidelift"
}
],
"time": "2023-07-14T04:18:47+00:00"
"time": "2023-07-17T12:08:28+00:00"
},
{
"name": "sebastian/cli-parser",

View File

@ -31,7 +31,7 @@ use function str_repeat;
final class VersionInfo{
public const NAME = "PocketMine-MP";
public const BASE_VERSION = "5.3.2";
public const BASE_VERSION = "5.3.3";
public const IS_DEVELOPMENT_BUILD = true;
public const BUILD_CHANNEL = "stable";

View File

@ -0,0 +1,136 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\event\block\StructureGrowEvent;
use pocketmine\item\Fertilizer;
use pocketmine\item\Item;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
abstract class BaseBigDripleaf extends Transparent{
use HorizontalFacingTrait;
abstract protected function isHead() : bool;
private function canBeSupportedBy(Block $block, bool $head) : bool{
//TODO: Moss block
return
($block instanceof BaseBigDripleaf && $block->isHead() === $head) ||
$block->getTypeId() === BlockTypeIds::CLAY ||
$block->hasTypeTag(BlockTypeTags::DIRT) ||
$block->hasTypeTag(BlockTypeTags::MUD);
}
public function onNearbyBlockChange() : void{
if(
(!$this->isHead() && !$this->getSide(Facing::UP) instanceof BaseBigDripleaf) ||
!$this->canBeSupportedBy($this->getSide(Facing::DOWN), false)
){
$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{
$block = $blockReplace->getSide(Facing::DOWN);
if(!$this->canBeSupportedBy($block, true)){
return false;
}
if($player !== null){
$this->facing = Facing::opposite($player->getHorizontalFacing());
}
if($block instanceof BaseBigDripleaf){
$this->facing = $block->getFacing();
$tx->addBlock($block->getPosition(), VanillaBlocks::BIG_DRIPLEAF_STEM()->setFacing($this->facing));
}
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($item instanceof Fertilizer && $this->grow($player)){
$item->pop();
return true;
}
return false;
}
private function seekToHead() : ?BaseBigDripleaf{
if($this->isHead()){
return $this;
}
$step = 1;
while(($next = $this->getSide(Facing::UP, $step)) instanceof BaseBigDripleaf){
if($next->isHead()){
return $next;
}
$step++;
}
return null;
}
private function grow(?Player $player) : bool{
$head = $this->seekToHead();
if($head === null){
return false;
}
$pos = $head->getPosition();
$up = $pos->up();
$world = $pos->getWorld();
if(
!$world->isInWorld($up->getFloorX(), $up->getFloorY(), $up->getFloorZ()) ||
$world->getBlock($up)->getTypeId() !== BlockTypeIds::AIR
){
return false;
}
$tx = new BlockTransaction($world);
$tx->addBlock($pos, VanillaBlocks::BIG_DRIPLEAF_STEM()->setFacing($head->getFacing()));
$tx->addBlock($up, VanillaBlocks::BIG_DRIPLEAF_HEAD()->setFacing($head->getFacing()));
$ev = new StructureGrowEvent($head, $tx, $player);
$ev->call();
if(!$ev->isCancelled()){
return $tx->apply();
}
return false;
}
public function getFlameEncouragement() : int{
return 15;
}
public function getFlammability() : int{
return 100;
}
public function getSupportType(int $facing) : SupportType{
return SupportType::NONE();
}
}

View File

@ -0,0 +1,132 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\DripleafState;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\entity\Entity;
use pocketmine\entity\projectile\Projectile;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
use pocketmine\math\RayTraceResult;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\world\sound\DripleafTiltDownSound;
use pocketmine\world\sound\DripleafTiltUpSound;
class BigDripleafHead extends BaseBigDripleaf{
protected DripleafState $leafState;
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
$this->leafState = DripleafState::STABLE();
parent::__construct($idInfo, $name, $typeInfo);
}
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
parent::describeBlockOnlyState($w);
$w->dripleafState($this->leafState);
}
protected function isHead() : bool{
return true;
}
public function getLeafState() : DripleafState{
return $this->leafState;
}
/** @return $this */
public function setLeafState(DripleafState $leafState) : self{
$this->leafState = $leafState;
return $this;
}
public function hasEntityCollision() : bool{
return true;
}
private function setTiltAndScheduleTick(DripleafState $tilt) : void{
$this->position->getWorld()->setBlock($this->position, $this->setLeafState($tilt));
$delay = $tilt->getScheduledUpdateDelayTicks();
if($delay !== null){
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, $delay);
}
}
private function getLeafTopOffset() : float{
return match($this->leafState){
DripleafState::STABLE(), DripleafState::UNSTABLE() => 1 / 16,
DripleafState::PARTIAL_TILT() => 3 / 16,
default => 0
};
}
public function onEntityInside(Entity $entity) : bool{
if(!$entity instanceof Projectile && $this->leafState->equals(DripleafState::STABLE())){
//the entity must be standing on top of the leaf - do not collapse if the entity is standing underneath
$intersection = AxisAlignedBB::one()
->offset($this->position->x, $this->position->y, $this->position->z)
->trim(Facing::DOWN, 1 - $this->getLeafTopOffset());
if($entity->getBoundingBox()->intersectsWith($intersection)){
$this->setTiltAndScheduleTick(DripleafState::UNSTABLE());
return false;
}
}
return true;
}
public function onProjectileHit(Projectile $projectile, RayTraceResult $hitResult) : void{
if(!$this->leafState->equals(DripleafState::FULL_TILT())){
$this->setTiltAndScheduleTick(DripleafState::FULL_TILT());
$this->position->getWorld()->addSound($this->position, new DripleafTiltDownSound());
}
}
public function onScheduledUpdate() : void{
if(!$this->leafState->equals(DripleafState::STABLE())){
if($this->leafState->equals(DripleafState::FULL_TILT())){
$this->position->getWorld()->setBlock($this->position, $this->setLeafState(DripleafState::STABLE()));
$this->position->getWorld()->addSound($this->position, new DripleafTiltUpSound());
}else{
$this->setTiltAndScheduleTick(match($this->leafState->id()){
DripleafState::UNSTABLE()->id() => DripleafState::PARTIAL_TILT(),
DripleafState::PARTIAL_TILT()->id() => DripleafState::FULL_TILT(),
default => throw new AssumptionFailedError("All types should be covered")
});
$this->position->getWorld()->addSound($this->position, new DripleafTiltDownSound());
}
}
}
protected function recalculateCollisionBoxes() : array{
if(!$this->leafState->equals(DripleafState::FULL_TILT())){
return [
AxisAlignedBB::one()
->trim(Facing::DOWN, 11 / 16)
->trim(Facing::UP, $this->getLeafTopOffset())
];
}
return [];
}
}

View File

@ -0,0 +1,41 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
class BigDripleafStem extends BaseBigDripleaf{
protected function isHead() : bool{
return false;
}
protected function recalculateCollisionBoxes() : array{
return [];
}
public function asItem() : Item{
return VanillaBlocks::BIG_DRIPLEAF_HEAD()->asItem();
}
}

View File

@ -733,8 +733,11 @@ final class BlockTypeIds{
public const CHERRY_TRAPDOOR = 10703;
public const CHERRY_WALL_SIGN = 10704;
public const CHERRY_WOOD = 10705;
public const SMALL_DRIPLEAF = 10706;
public const BIG_DRIPLEAF_HEAD = 10707;
public const BIG_DRIPLEAF_STEM = 10708;
public const FIRST_UNUSED_BLOCK_ID = 10706;
public const FIRST_UNUSED_BLOCK_ID = 10709;
private static int $nextDynamicId = self::FIRST_UNUSED_BLOCK_ID;

170
src/block/SmallDripleaf.php Normal file
View File

@ -0,0 +1,170 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\event\block\StructureGrowEvent;
use pocketmine\item\Fertilizer;
use pocketmine\item\Item;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
use pocketmine\world\Position;
use function mt_rand;
class SmallDripleaf extends Transparent{
use HorizontalFacingTrait;
protected bool $top = false;
public function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->horizontalFacing($this->facing);
$w->bool($this->top);
}
public function isTop() : bool{
return $this->top;
}
/** @return $this */
public function setTop(bool $top) : self{
$this->top = $top;
return $this;
}
private function canBeSupportedBy(Block $block) : bool{
//TODO: Moss
//TODO: Small Dripleaf also can be placed on dirt, coarse dirt, farmland, grass blocks,
// podzol, rooted dirt, mycelium, and mud if these blocks are underwater (needs waterlogging)
return $block->getTypeId() === BlockTypeIds::CLAY;
}
public function onNearbyBlockChange() : void{
if(!$this->top && !$this->canBeSupportedBy($this->getSide(Facing::DOWN))){
$this->position->getWorld()->useBreakOn($this->position);
return;
}
$face = $this->top ? Facing::DOWN : Facing::UP;
if(!$this->getSide($face)->hasSameTypeId($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{
$block = $blockReplace->getSide(Facing::UP);
if($block->getTypeId() !== BlockTypeIds::AIR || !$this->canBeSupportedBy($blockReplace->getSide(Facing::DOWN))){
return false;
}
if($player !== null){
$this->facing = Facing::opposite($player->getHorizontalFacing());
}
$tx->addBlock($block->getPosition(), VanillaBlocks::SMALL_DRIPLEAF()
->setFacing($this->facing)
->setTop(true)
);
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($item instanceof Fertilizer && $this->grow($player)){
$item->pop();
return true;
}
return false;
}
private function canGrowTo(Position $pos) : bool{
$world = $pos->getWorld();
if(!$world->isInWorld($pos->getFloorX(), $pos->getFloorY(), $pos->getFloorZ())){
return false;
}
$block = $world->getBlock($pos);
return $block->hasSameTypeId($this) || $block->getTypeId() === BlockTypeIds::AIR;
}
private function grow(?Player $player) : bool{
$bottomBlock = $this->top ? $this->getSide(Facing::DOWN) : $this;
if(!$this->hasSameTypeId($bottomBlock)){
return false;
}
$world = $this->position->getWorld();
$tx = new BlockTransaction($world);
$height = mt_rand(2, 5);
$grown = 0;
for($i = 0; $i < $height; $i++){
$pos = $bottomBlock->getSide(Facing::UP, $i)->getPosition();
if(!$this->canGrowTo($pos)){
break;
}
$block = ++$grown < $height && $this->canGrowTo($pos->getSide(Facing::UP)) ?
VanillaBlocks::BIG_DRIPLEAF_STEM() :
VanillaBlocks::BIG_DRIPLEAF_HEAD();
$tx->addBlock($pos, $block->setFacing($this->facing));
}
if($grown > 1){
$ev = new StructureGrowEvent($bottomBlock, $tx, $player);
$ev->call();
if(!$ev->isCancelled()){
return $tx->apply();
}
}
return false;
}
public function getAffectedBlocks() : array{
$other = $this->getSide($this->top ? Facing::DOWN : Facing::UP);
if($other->hasSameTypeId($this)){
return [$this, $other];
}
return parent::getAffectedBlocks();
}
public function getDropsForCompatibleTool(Item $item) : array{
if(!$this->top){
return [$this->asItem()];
}
return [];
}
public function getFlameEncouragement() : int{
return 15;
}
public function getFlammability() : int{
return 100;
}
public function getSupportType(int $facing) : SupportType{
return SupportType::NONE();
}
protected function recalculateCollisionBoxes() : array{
return [];
}
}

View File

@ -55,6 +55,7 @@ abstract class Stem extends Crops{
if($this->facing !== Facing::UP && !$this->getSide($this->facing)->hasSameTypeId($this->getPlant())){
$this->position->getWorld()->setBlock($this->position, $this->setFacing(Facing::UP));
}
parent::onNearbyBlockChange();
}
public function onRandomTick() : void{

View File

@ -113,6 +113,8 @@ use function mb_strtolower;
* @method static Bedrock BEDROCK()
* @method static Beetroot BEETROOTS()
* @method static Bell BELL()
* @method static BigDripleafHead BIG_DRIPLEAF_HEAD()
* @method static BigDripleafStem BIG_DRIPLEAF_STEM()
* @method static WoodenButton BIRCH_BUTTON()
* @method static WoodenDoor BIRCH_DOOR()
* @method static WoodenFence BIRCH_FENCE()
@ -658,6 +660,7 @@ use function mb_strtolower;
* @method static Opaque SHROOMLIGHT()
* @method static ShulkerBox SHULKER_BOX()
* @method static Slime SLIME()
* @method static SmallDripleaf SMALL_DRIPLEAF()
* @method static SmithingTable SMITHING_TABLE()
* @method static Furnace SMOKER()
* @method static Opaque SMOOTH_BASALT()
@ -1598,6 +1601,10 @@ final class VanillaBlocks{
self::register("hanging_roots", new HangingRoots(new BID(Ids::HANGING_ROOTS), "Hanging Roots", new Info(BreakInfo::instant(ToolType::SHEARS, 1))));
self::register("cave_vines", new CaveVines(new BID(Ids::CAVE_VINES), "Cave Vines", new Info(BreakInfo::instant())));
self::register("small_dripleaf", new SmallDripleaf(new BID(Ids::SMALL_DRIPLEAF), "Small Dripleaf", new Info(BreakInfo::instant(BlockToolType::SHEARS, toolHarvestLevel: 1))));
self::register("big_dripleaf_head", new BigDripleafHead(new BID(Ids::BIG_DRIPLEAF_HEAD), "Big Dripleaf", new Info(BreakInfo::instant())));
self::register("big_dripleaf_stem", new BigDripleafStem(new BID(Ids::BIG_DRIPLEAF_STEM), "Big Dripleaf Stem", new Info(BreakInfo::instant())));
}
private static function registerBlocksR18() : void{

View File

@ -0,0 +1,65 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block\utils;
use pocketmine\utils\EnumTrait;
/**
* This doc-block is generated automatically, do not modify it manually.
* This must be regenerated whenever registry members are added, removed or changed.
* @see build/generate-registry-annotations.php
* @generate-registry-docblock
*
* @method static DripleafState FULL_TILT()
* @method static DripleafState PARTIAL_TILT()
* @method static DripleafState STABLE()
* @method static DripleafState UNSTABLE()
*/
final class DripleafState{
use EnumTrait {
register as Enum_register;
__construct as Enum___construct;
}
protected static function setup() : void{
self::registerAll(
new self("stable", null),
new self("unstable", 10),
new self("partial_tilt", 10),
new self("full_tilt", 100)
);
}
private function __construct(
string $enumName,
private ?int $scheduledUpdateDelayTicks
){
$this->Enum___construct($enumName);
}
public function getScheduledUpdateDelayTicks() : ?int{
return $this->scheduledUpdateDelayTicks;
}
}

View File

@ -31,6 +31,8 @@ use pocketmine\block\Barrel;
use pocketmine\block\Bed;
use pocketmine\block\Beetroot;
use pocketmine\block\Bell;
use pocketmine\block\BigDripleafHead;
use pocketmine\block\BigDripleafStem;
use pocketmine\block\Block;
use pocketmine\block\BoneBlock;
use pocketmine\block\BrewingStand;
@ -115,6 +117,7 @@ use pocketmine\block\SeaPickle;
use pocketmine\block\SimplePillar;
use pocketmine\block\SimplePressurePlate;
use pocketmine\block\Slab;
use pocketmine\block\SmallDripleaf;
use pocketmine\block\SnowLayer;
use pocketmine\block\Sponge;
use pocketmine\block\StainedGlass;
@ -138,6 +141,7 @@ use pocketmine\block\UnderwaterTorch;
use pocketmine\block\utils\BrewingStandSlot;
use pocketmine\block\utils\CoralType;
use pocketmine\block\utils\DirtType;
use pocketmine\block\utils\DripleafState;
use pocketmine\block\utils\DyeColor;
use pocketmine\block\utils\FroglightType;
use pocketmine\block\utils\LeverFacing;
@ -958,6 +962,24 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
->writeLegacyHorizontalFacing($block->getFacing());
});
$this->map(Blocks::BIG_DRIPLEAF_HEAD(), function(BigDripleafHead $block) : Writer{
return Writer::create(Ids::BIG_DRIPLEAF)
->writeLegacyHorizontalFacing($block->getFacing())
->writeString(StateNames::BIG_DRIPLEAF_TILT, match($block->getLeafState()->id()){
DripleafState::STABLE()->id() => StringValues::BIG_DRIPLEAF_TILT_NONE,
DripleafState::UNSTABLE()->id() => StringValues::BIG_DRIPLEAF_TILT_UNSTABLE,
DripleafState::PARTIAL_TILT()->id() => StringValues::BIG_DRIPLEAF_TILT_PARTIAL_TILT,
DripleafState::FULL_TILT()->id() => StringValues::BIG_DRIPLEAF_TILT_FULL_TILT,
default => throw new BlockStateSerializeException("Invalid Dripleaf tilt type " . $block->getLeafState()->name())
})
->writeBool(StateNames::BIG_DRIPLEAF_HEAD, true);
});
$this->map(Blocks::BIG_DRIPLEAF_STEM(), function(BigDripleafStem $block) : Writer{
return Writer::create(Ids::BIG_DRIPLEAF)
->writeLegacyHorizontalFacing($block->getFacing())
->writeString(StateNames::BIG_DRIPLEAF_TILT, StringValues::BIG_DRIPLEAF_TILT_NONE)
->writeBool(StateNames::BIG_DRIPLEAF_HEAD, false);
});
$this->map(Blocks::BIRCH_SAPLING(), fn(Sapling $block) => Helper::encodeSapling($block, StringValues::SAPLING_TYPE_BIRCH));
$this->mapSlab(Blocks::BLACKSTONE_SLAB(), Ids::BLACKSTONE_SLAB, Ids::BLACKSTONE_DOUBLE_SLAB);
$this->mapStairs(Blocks::BLACKSTONE_STAIRS(), Ids::BLACKSTONE_STAIRS);
@ -1454,6 +1476,11 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
->writeBool(StateNames::DEAD_BIT, !$block->isUnderwater())
->writeInt(StateNames::CLUSTER_COUNT, $block->getCount() - 1);
});
$this->map(Blocks::SMALL_DRIPLEAF(), function(SmallDripleaf $block) : Writer{
return Writer::create(Ids::SMALL_DRIPLEAF_BLOCK)
->writeLegacyHorizontalFacing($block->getFacing())
->writeBool(StateNames::UPPER_BLOCK_BIT, $block->isTop());
});
$this->map(Blocks::SMOKER(), fn(Furnace $block) => Helper::encodeFurnace($block, Ids::SMOKER, Ids::LIT_SMOKER));
$this->map(Blocks::SMOOTH_QUARTZ(), fn() => Helper::encodeQuartz(StringValues::CHISEL_TYPE_SMOOTH, Axis::Y));
$this->map(Blocks::SMOOTH_QUARTZ_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab4($block, StringValues::STONE_SLAB_TYPE_4_SMOOTH_QUARTZ));

View File

@ -35,6 +35,7 @@ use pocketmine\block\utils\BrewingStandSlot;
use pocketmine\block\utils\CopperOxidation;
use pocketmine\block\utils\CoralType;
use pocketmine\block\utils\DirtType;
use pocketmine\block\utils\DripleafState;
use pocketmine\block\utils\DyeColor;
use pocketmine\block\utils\FroglightType;
use pocketmine\block\utils\LeverFacing;
@ -826,6 +827,22 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
->setFacing($in->readLegacyHorizontalFacing())
->setAttachmentType($in->readBellAttachmentType());
});
$this->map(Ids::BIG_DRIPLEAF, function(Reader $in) : Block{
if($in->readBool(StateNames::BIG_DRIPLEAF_HEAD)){
return Blocks::BIG_DRIPLEAF_HEAD()
->setFacing($in->readLegacyHorizontalFacing())
->setLeafState(match($type = $in->readString(StateNames::BIG_DRIPLEAF_TILT)){
StringValues::BIG_DRIPLEAF_TILT_NONE => DripleafState::STABLE(),
StringValues::BIG_DRIPLEAF_TILT_UNSTABLE => DripleafState::UNSTABLE(),
StringValues::BIG_DRIPLEAF_TILT_PARTIAL_TILT => DripleafState::PARTIAL_TILT(),
StringValues::BIG_DRIPLEAF_TILT_FULL_TILT => DripleafState::FULL_TILT(),
default => throw $in->badValueException(StateNames::BIG_DRIPLEAF_TILT, $type),
});
}else{
$in->ignored(StateNames::BIG_DRIPLEAF_TILT);
return Blocks::BIG_DRIPLEAF_STEM()->setFacing($in->readLegacyHorizontalFacing());
}
});
$this->mapSlab(Ids::BLACKSTONE_SLAB, Ids::BLACKSTONE_DOUBLE_SLAB, fn() => Blocks::BLACKSTONE_SLAB());
$this->mapStairs(Ids::BLACKSTONE_STAIRS, fn() => Blocks::BLACKSTONE_STAIRS());
$this->map(Ids::BLACKSTONE_WALL, fn(Reader $in) => Helper::decodeWall(Blocks::BLACKSTONE_WALL(), $in));
@ -1332,6 +1349,11 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
->setFacing($in->readHorizontalFacing())
->setLit(false);
});
$this->map(Ids::SMALL_DRIPLEAF_BLOCK, function(Reader $in) : Block{
return Blocks::SMALL_DRIPLEAF()
->setFacing($in->readLegacyHorizontalFacing())
->setTop($in->readBool(StateNames::UPPER_BLOCK_BIT));
});
$this->mapStairs(Ids::SMOOTH_QUARTZ_STAIRS, fn() => Blocks::SMOOTH_QUARTZ_STAIRS());
$this->mapStairs(Ids::SMOOTH_RED_SANDSTONE_STAIRS, fn() => Blocks::SMOOTH_RED_SANDSTONE_STAIRS());
$this->mapStairs(Ids::SMOOTH_SANDSTONE_STAIRS, fn() => Blocks::SMOOTH_SANDSTONE_STAIRS());

View File

@ -37,6 +37,8 @@ interface RuntimeEnumDescriber{
public function dirtType(\pocketmine\block\utils\DirtType &$value) : void;
public function dripleafState(\pocketmine\block\utils\DripleafState &$value) : void;
public function dyeColor(\pocketmine\block\utils\DyeColor &$value) : void;
public function froglightType(\pocketmine\block\utils\FroglightType &$value) : void;

View File

@ -71,6 +71,16 @@ trait RuntimeEnumDeserializerTrait{
};
}
public function dripleafState(\pocketmine\block\utils\DripleafState &$value) : void{
$value = match($this->readInt(2)){
0 => \pocketmine\block\utils\DripleafState::FULL_TILT(),
1 => \pocketmine\block\utils\DripleafState::PARTIAL_TILT(),
2 => \pocketmine\block\utils\DripleafState::STABLE(),
3 => \pocketmine\block\utils\DripleafState::UNSTABLE(),
default => throw new InvalidSerializedRuntimeDataException("Invalid serialized value for DripleafState")
};
}
public function dyeColor(\pocketmine\block\utils\DyeColor &$value) : void{
$value = match($this->readInt(4)){
0 => \pocketmine\block\utils\DyeColor::BLACK(),

View File

@ -71,6 +71,16 @@ trait RuntimeEnumSerializerTrait{
});
}
public function dripleafState(\pocketmine\block\utils\DripleafState &$value) : void{
$this->writeInt(2, match($value){
\pocketmine\block\utils\DripleafState::FULL_TILT() => 0,
\pocketmine\block\utils\DripleafState::PARTIAL_TILT() => 1,
\pocketmine\block\utils\DripleafState::STABLE() => 2,
\pocketmine\block\utils\DripleafState::UNSTABLE() => 3,
default => throw new \pocketmine\utils\AssumptionFailedError("All DripleafState cases should be covered")
});
}
public function dyeColor(\pocketmine\block\utils\DyeColor &$value) : void{
$this->writeInt(4, match($value){
\pocketmine\block\utils\DyeColor::BLACK() => 0,

View File

@ -47,6 +47,10 @@ trait RuntimeEnumSizeCalculatorTrait{
$this->addBits(2);
}
public function dripleafState(\pocketmine\block\utils\DripleafState &$value) : void{
$this->addBits(2);
}
public function dyeColor(\pocketmine\block\utils\DyeColor &$value) : void{
$this->addBits(4);
}

View File

@ -487,14 +487,16 @@ abstract class Living extends Entity{
public function damageArmor(float $damage) : void{
$durabilityRemoved = (int) max(floor($damage / 4), 1);
$armor = $this->armorInventory->getContents(true);
foreach($armor as $item){
$armor = $this->armorInventory->getContents();
foreach($armor as $slotId => $item){
if($item instanceof Armor){
$oldItem = clone $item;
$this->damageItem($item, $durabilityRemoved);
if(!$item->equalsExact($oldItem)){
$this->armorInventory->setItem($slotId, $item);
}
}
}
$this->armorInventory->setContents($armor);
}
private function damageItem(Durable $item, int $durabilityRemoved) : void{
@ -640,9 +642,12 @@ abstract class Living extends Entity{
}
foreach($this->armorInventory->getContents() as $index => $item){
$oldItem = clone $item;
if($item->onTickWorn($this)){
$hasUpdate = true;
$this->armorInventory->setItem($index, $item);
if(!$item->equalsExact($oldItem)){
$this->armorInventory->setItem($index, $item);
}
}
}
}

View File

@ -155,6 +155,7 @@ final class StringToItemParser extends StringToTParser{
$result->registerBlock("beetroot_block", fn() => Blocks::BEETROOTS());
$result->registerBlock("beetroots", fn() => Blocks::BEETROOTS());
$result->registerBlock("bell", fn() => Blocks::BELL());
$result->registerBlock("big_dripleaf", fn() => Blocks::BIG_DRIPLEAF_HEAD());
$result->registerBlock("birch_button", fn() => Blocks::BIRCH_BUTTON());
$result->registerBlock("birch_door", fn() => Blocks::BIRCH_DOOR());
$result->registerBlock("birch_door_block", fn() => Blocks::BIRCH_DOOR());
@ -972,6 +973,7 @@ final class StringToItemParser extends StringToTParser{
$result->registerBlock("slabs", fn() => Blocks::SMOOTH_STONE_SLAB());
$result->registerBlock("slime", fn() => Blocks::SLIME());
$result->registerBlock("slime_block", fn() => Blocks::SLIME());
$result->registerBlock("small_dripleaf", fn() => Blocks::SMALL_DRIPLEAF());
$result->registerBlock("smoker", fn() => Blocks::SMOKER());
$result->registerBlock("smooth_basalt", fn() => Blocks::SMOOTH_BASALT());
$result->registerBlock("smooth_quartz", fn() => Blocks::SMOOTH_QUARTZ());

View File

@ -259,7 +259,7 @@ class AsyncPool{
if($task->isTerminated()){
$this->checkCrashedWorker($worker, $task);
throw new AssumptionFailedError("checkCrashedWorker() should have thrown an exception, making this unreachable");
}elseif(!$task->hasCancelledRun()){
}else{
/*
* It's possible for a task to submit a progress update and then finish before the progress
* update is detected by the parent thread, so here we consume any missed updates.

View File

@ -72,17 +72,14 @@ abstract class AsyncTask extends Runnable{
private ?ThreadSafeArray $progressUpdates = null;
private ThreadSafe|string|int|bool|null|float $result = null;
private bool $cancelRun = false;
private bool $submitted = false;
private bool $submitted = false;
private bool $finished = false;
public function run() : void{
$this->result = null;
if(!$this->cancelRun){
$this->onRun();
}
$this->onRun();
$this->finished = true;
$worker = NativeThread::getCurrentThread();
@ -123,12 +120,18 @@ abstract class AsyncTask extends Runnable{
$this->result = is_scalar($result) || is_null($result) || $result instanceof ThreadSafe ? $result : new NonThreadSafeValue($result);
}
/**
* @deprecated
*/
public function cancelRun() : void{
$this->cancelRun = true;
//NOOP
}
/**
* @deprecated
*/
public function hasCancelledRun() : bool{
return $this->cancelRun;
return false;
}
public function setSubmitted() : void{

View File

@ -0,0 +1,132 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\world\generator\object;
use pocketmine\block\VanillaBlocks;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\utils\Random;
use pocketmine\world\BlockTransaction;
use function abs;
use function array_rand;
final class AcaciaTree extends Tree{
private const MIN_HEIGHT = 5;
private ?Vector3 $mainBranchTip = null;
private ?Vector3 $secondBranchTip = null;
public function __construct(){
parent::__construct(
VanillaBlocks::ACACIA_LOG(),
VanillaBlocks::ACACIA_LEAVES(),
0 //we don't use this anyway - everything is overridden
);
}
protected function generateTrunkHeight(Random $random) : int{
//50% chance of 2 extra blocks, 33% chance 1 or 3, 17% chance 0 or 4
return self::MIN_HEIGHT + $random->nextRange(0, 2) + $random->nextRange(0, 2);
}
protected function placeTrunk(int $x, int $y, int $z, Random $random, int $trunkHeight, BlockTransaction $transaction) : void{
// The base dirt block
$transaction->addBlockAt($x, $y - 1, $z, VanillaBlocks::DIRT());
$firstBranchHeight = $trunkHeight - 1 - $random->nextRange(0, 3);
for($yy = 0; $yy <= $firstBranchHeight; ++$yy){
$transaction->addBlockAt($x, $y + $yy, $z, $this->trunkBlock);
}
$mainBranchFacing = Facing::HORIZONTAL[array_rand(Facing::HORIZONTAL)];
//this branch may grow a second trunk if the diagonal length is less than the max length
$this->mainBranchTip = $this->placeBranch(
$transaction,
new Vector3($x, $y + $firstBranchHeight, $z),
$mainBranchFacing,
$random->nextRange(1, 3),
$trunkHeight - $firstBranchHeight
);
$secondBranchFacing = Facing::HORIZONTAL[array_rand(Facing::HORIZONTAL)];
if($secondBranchFacing !== $mainBranchFacing){
$secondBranchLength = $random->nextRange(1, 3);
$this->secondBranchTip = $this->placeBranch(
$transaction,
new Vector3($x, $y + ($firstBranchHeight - $random->nextRange(0, 1)), $z),
$secondBranchFacing,
$secondBranchLength,
$secondBranchLength //the secondary branch may not form a second trunk
);
}
}
protected function placeBranch(BlockTransaction $transaction, Vector3 $start, int $branchFacing, int $maxDiagonal, int $length) : Vector3{
$diagonalPlaced = 0;
$nextBlockPos = $start;
for($yy = 0; $yy < $length; $yy++){
$nextBlockPos = $nextBlockPos->up();
if($diagonalPlaced < $maxDiagonal){
$nextBlockPos = $nextBlockPos->getSide($branchFacing);
$diagonalPlaced++;
}
$transaction->addBlock($nextBlockPos, $this->trunkBlock);
}
return $nextBlockPos;
}
protected function placeCanopyLayer(BlockTransaction $transaction, Vector3 $center, int $radius, int $maxTaxicabDistance) : void{
$centerX = $center->getFloorX();
$centerY = $center->getFloorY();
$centerZ = $center->getFloorZ();
for($x = $centerX - $radius; $x <= $centerX + $radius; ++$x){
for($z = $centerZ - $radius; $z <= $centerZ + $radius; ++$z){
if(
abs($x - $centerX) + abs($z - $centerZ) <= $maxTaxicabDistance &&
$transaction->fetchBlockAt($x, $centerY, $z)->canBeReplaced()
){
$transaction->addBlockAt($x, $centerY, $z, $this->leafBlock);
}
}
}
}
protected function placeCanopy(int $x, int $y, int $z, Random $random, BlockTransaction $transaction) : void{
$mainBranchTip = $this->mainBranchTip;
if($mainBranchTip !== null){
$this->placeCanopyLayer($transaction, $mainBranchTip, radius: 3, maxTaxicabDistance: 5);
$this->placeCanopyLayer($transaction, $mainBranchTip->up(), radius: 2, maxTaxicabDistance: 2);
}
$secondBranchTip = $this->secondBranchTip;
if($secondBranchTip !== null){
$this->placeCanopyLayer($transaction, $secondBranchTip, radius: 2, maxTaxicabDistance: 3);
$this->placeCanopyLayer($transaction, $secondBranchTip->up(), radius: 1, maxTaxicabDistance: 2);
}
}
}

View File

@ -49,6 +49,8 @@ final class TreeFactory{
}else{*/
//}
}elseif($type->equals(TreeType::ACACIA())){
return new AcaciaTree();
}
return null;
}

View File

@ -0,0 +1,35 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\world\sound;
use pocketmine\math\Vector3;
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
use pocketmine\network\mcpe\protocol\types\LevelSoundEvent;
class DripleafTiltDownSound implements Sound{
public function encode(Vector3 $pos) : array{
return [LevelSoundEventPacket::nonActorSound(LevelSoundEvent::TILT_DOWN_BIG_DRIPLEAF, $pos, false)];
}
}

View File

@ -0,0 +1,35 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\world\sound;
use pocketmine\math\Vector3;
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
use pocketmine\network\mcpe\protocol\types\LevelSoundEvent;
class DripleafTiltUpSound implements Sound{
public function encode(Vector3 $pos) : array{
return [LevelSoundEventPacket::nonActorSound(LevelSoundEvent::TILT_UP_BIG_DRIPLEAF, $pos, false)];
}
}

File diff suppressed because one or more lines are too long