From d1c75da14b02ba7a7e324e68004d0335c5c7f227 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Tue, 20 Sep 2022 21:53:51 +0100 Subject: [PATCH 01/13] Player: lock flight state in spectator mode players should not be able to stop flying in spectator mode --- src/player/Player.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/player/Player.php b/src/player/Player.php index 336ff6f8c..7a32e7a48 100644 --- a/src/player/Player.php +++ b/src/player/Player.php @@ -1021,7 +1021,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{ protected function internalSetGameMode(GameMode $gameMode) : void{ $this->gamemode = $gameMode; - $this->allowFlight = $this->isCreative(); + $this->allowFlight = $this->gamemode->equals(GameMode::CREATIVE()); $this->hungerManager->setEnabled($this->isSurvival()); if($this->isSpectator()){ From 481bda8cd5a2a0a2068be3b89e5822e7106ae569 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Sep 2022 12:43:06 +0100 Subject: [PATCH 02/13] Bump build/php from `cf79c01` to `50062b5` (#5293) Bumps [build/php](https://github.com/pmmp/php-build-scripts) from `cf79c01` to `50062b5`. - [Release notes](https://github.com/pmmp/php-build-scripts/releases) - [Commits](https://github.com/pmmp/php-build-scripts/compare/cf79c0172283a0a26f2c3695af260d100e0fdabd...50062b5861235fbb9fe6e5d5b30684f4cb464470) --- updated-dependencies: - dependency-name: build/php dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build/php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/php b/build/php index cf79c0172..50062b586 160000 --- a/build/php +++ b/build/php @@ -1 +1 @@ -Subproject commit cf79c0172283a0a26f2c3695af260d100e0fdabd +Subproject commit 50062b5861235fbb9fe6e5d5b30684f4cb464470 From 780417284666abd484189d8013125be5c9a914d9 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 21 Sep 2022 14:38:44 +0100 Subject: [PATCH 03/13] Player: added API documentation for some functions --- src/player/Player.php | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/player/Player.php b/src/player/Player.php index 7a32e7a48..f93ac2dfc 100644 --- a/src/player/Player.php +++ b/src/player/Player.php @@ -418,6 +418,15 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{ return $this->lastPlayed - $this->firstPlayed > 1; // microtime(true) - microtime(true) may have less than one millisecond difference } + /** + * Sets whether the player is allowed to toggle flight mode. + * + * If set to false, the player will be locked in its current flight mode (flying/not flying), and attempts by the + * player to enter or exit flight mode will be prevented. + * + * Note: Setting this to false DOES NOT change whether the player is currently flying. Use + * {@link Player::setFlying()} for that purpose. + */ public function setAllowFlight(bool $value) : void{ if($this->allowFlight !== $value){ $this->allowFlight = $value; @@ -425,10 +434,24 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{ } } + /** + * Returns whether the player is allowed to toggle its flight state. + * + * If false, the player is locked in its current flight mode (flying/not flying), and attempts by the player to + * enter or exit flight mode will be prevented. + */ public function getAllowFlight() : bool{ return $this->allowFlight; } + /** + * Sets whether the player's movement may be obstructed by blocks with collision boxes. + * If set to false, the player can move through any block unobstructed. + * + * Note: Enabling flight mode in conjunction with this is recommended. A non-flying player will simply fall through + * the ground into the void. + * @see Player::setFlying() + */ public function setHasBlockCollision(bool $value) : void{ if($this->blockCollision !== $value){ $this->blockCollision = $value; @@ -436,6 +459,10 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{ } } + /** + * Returns whether blocks may obstruct the player's movement. + * If false, the player can move through any block unobstructed. + */ public function hasBlockCollision() : bool{ return $this->blockCollision; } From e4fc523251c8b32f9669c4745aa838ed7a45b4e7 Mon Sep 17 00:00:00 2001 From: famima65536 Date: Fri, 23 Sep 2022 19:37:08 +0900 Subject: [PATCH 04/13] Introduce Player::sendToastNotification() (#5102) --- src/network/mcpe/NetworkSession.php | 5 +++++ src/player/Player.php | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/src/network/mcpe/NetworkSession.php b/src/network/mcpe/NetworkSession.php index 156f65978..3b868e0f5 100644 --- a/src/network/mcpe/NetworkSession.php +++ b/src/network/mcpe/NetworkSession.php @@ -88,6 +88,7 @@ use pocketmine\network\mcpe\protocol\SetTimePacket; use pocketmine\network\mcpe\protocol\SetTitlePacket; use pocketmine\network\mcpe\protocol\TakeItemActorPacket; use pocketmine\network\mcpe\protocol\TextPacket; +use pocketmine\network\mcpe\protocol\ToastRequestPacket; use pocketmine\network\mcpe\protocol\TransferPacket; use pocketmine\network\mcpe\protocol\types\BlockPosition; use pocketmine\network\mcpe\protocol\types\command\CommandData; @@ -1100,6 +1101,10 @@ class NetworkSession{ $this->sendDataPacket(EmotePacket::create($from->getId(), $emoteId, EmotePacket::FLAG_SERVER)); } + public function onToastNotification(string $title, string $body) : void{ + $this->sendDataPacket(ToastRequestPacket::create($title, $body)); + } + public function tick() : void{ if($this->info === null){ if(time() >= $this->connectTime + 10){ diff --git a/src/player/Player.php b/src/player/Player.php index 139dc5add..8a6a10fea 100644 --- a/src/player/Player.php +++ b/src/player/Player.php @@ -1986,6 +1986,13 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{ $this->getNetworkSession()->onTip($message); } + /** + * Sends a toast message to the player, or queue to send it if a toast message is already shown. + */ + public function sendToastNotification(string $title, string $body) : void{ + $this->getNetworkSession()->onToastNotification($title, $body); + } + /** * Sends a Form to the player, or queue to send it if a form is already open. * From 93d4475111a254a4d985d7ce5b36444a205bc9d5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 23 Sep 2022 11:42:50 +0100 Subject: [PATCH 05/13] Bump phpstan/phpstan from 1.8.5 to 1.8.6 (#5299) Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.8.5 to 1.8.6. - [Release notes](https://github.com/phpstan/phpstan/releases) - [Changelog](https://github.com/phpstan/phpstan/blob/1.8.x/CHANGELOG.md) - [Commits](https://github.com/phpstan/phpstan/compare/1.8.5...1.8.6) --- updated-dependencies: - dependency-name: phpstan/phpstan dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- composer.json | 2 +- composer.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index 4bed6daac..957fbb4b1 100644 --- a/composer.json +++ b/composer.json @@ -53,7 +53,7 @@ "webmozart/path-util": "^2.3" }, "require-dev": { - "phpstan/phpstan": "1.8.5", + "phpstan/phpstan": "1.8.6", "phpstan/phpstan-phpunit": "^1.1.0", "phpstan/phpstan-strict-rules": "^1.2.0", "phpunit/phpunit": "^9.2" diff --git a/composer.lock b/composer.lock index b4b27c130..59a95e713 100644 --- a/composer.lock +++ b/composer.lock @@ -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": "0f6c845836d4ec6f221415d2f9dd1fc5", + "content-hash": "29badb76ebb63167718947cad48bd37d", "packages": [ { "name": "adhocore/json-comment", @@ -1506,16 +1506,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.8.5", + "version": "1.8.6", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "f6598a5ff12ca4499a836815e08b4d77a2ddeb20" + "reference": "c386ab2741e64cc9e21729f891b28b2b10fe6618" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/f6598a5ff12ca4499a836815e08b4d77a2ddeb20", - "reference": "f6598a5ff12ca4499a836815e08b4d77a2ddeb20", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/c386ab2741e64cc9e21729f891b28b2b10fe6618", + "reference": "c386ab2741e64cc9e21729f891b28b2b10fe6618", "shasum": "" }, "require": { @@ -1545,7 +1545,7 @@ ], "support": { "issues": "https://github.com/phpstan/phpstan/issues", - "source": "https://github.com/phpstan/phpstan/tree/1.8.5" + "source": "https://github.com/phpstan/phpstan/tree/1.8.6" }, "funding": [ { @@ -1561,7 +1561,7 @@ "type": "tidelift" } ], - "time": "2022-09-07T16:05:32+00:00" + "time": "2022-09-23T09:54:39+00:00" }, { "name": "phpstan/phpstan-phpunit", From 3c55db531d78d774bde73852427875a57cf0c377 Mon Sep 17 00:00:00 2001 From: Ali <47182802+UnknownOre@users.noreply.github.com> Date: Sat, 24 Sep 2022 15:45:12 +0300 Subject: [PATCH 06/13] HealthBoostEffect: Ensure that current health is within limits after reducing max health on removal(#5303) --- src/entity/effect/HealthBoostEffect.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/entity/effect/HealthBoostEffect.php b/src/entity/effect/HealthBoostEffect.php index 90c5ee680..022015d42 100644 --- a/src/entity/effect/HealthBoostEffect.php +++ b/src/entity/effect/HealthBoostEffect.php @@ -33,5 +33,8 @@ class HealthBoostEffect extends Effect{ public function remove(Living $entity, EffectInstance $instance) : void{ $entity->setMaxHealth($entity->getMaxHealth() - 4 * $instance->getEffectLevel()); + if($entity->getHealth() > $entity->getMaxHealth()){ + $entity->setHealth($entity->getMaxHealth()); + } } } From 3f7d8a3777b7f4bd8f85bd83b44b29322c09c1ec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 24 Sep 2022 13:45:39 +0100 Subject: [PATCH 07/13] Bump phpstan/phpstan-strict-rules from 1.4.3 to 1.4.4 (#5300) Bumps [phpstan/phpstan-strict-rules](https://github.com/phpstan/phpstan-strict-rules) from 1.4.3 to 1.4.4. - [Release notes](https://github.com/phpstan/phpstan-strict-rules/releases) - [Commits](https://github.com/phpstan/phpstan-strict-rules/compare/1.4.3...1.4.4) --- updated-dependencies: - dependency-name: phpstan/phpstan-strict-rules dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- composer.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/composer.lock b/composer.lock index 59a95e713..51710b868 100644 --- a/composer.lock +++ b/composer.lock @@ -1617,21 +1617,21 @@ }, { "name": "phpstan/phpstan-strict-rules", - "version": "1.4.3", + "version": "1.4.4", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-strict-rules.git", - "reference": "431b3d6e8040075de196680cd5bc95735987b4ae" + "reference": "23e5f377ee6395a1a04842d3d6ed4bd25e7b44a6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/431b3d6e8040075de196680cd5bc95735987b4ae", - "reference": "431b3d6e8040075de196680cd5bc95735987b4ae", + "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/23e5f377ee6395a1a04842d3d6ed4bd25e7b44a6", + "reference": "23e5f377ee6395a1a04842d3d6ed4bd25e7b44a6", "shasum": "" }, "require": { "php": "^7.2 || ^8.0", - "phpstan/phpstan": "^1.8.3" + "phpstan/phpstan": "^1.8.6" }, "require-dev": { "nikic/php-parser": "^4.13.0", @@ -1659,9 +1659,9 @@ "description": "Extra strict and opinionated rules for PHPStan", "support": { "issues": "https://github.com/phpstan/phpstan-strict-rules/issues", - "source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.4.3" + "source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.4.4" }, - "time": "2022-08-26T15:05:46+00:00" + "time": "2022-09-21T11:38:17+00:00" }, { "name": "phpunit/php-code-coverage", From 83a136a176df9a09f85064370b993da4060c7dd4 Mon Sep 17 00:00:00 2001 From: IvanCraft623 <57236932+IvanCraft623@users.noreply.github.com> Date: Sat, 24 Sep 2022 07:55:24 -0500 Subject: [PATCH 08/13] EntityFactory: Avoid code duplication on validation of creation functions (#5294) --- src/entity/EntityFactory.php | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/src/entity/EntityFactory.php b/src/entity/EntityFactory.php index cd1f96a5e..fb3a1f33d 100644 --- a/src/entity/EntityFactory.php +++ b/src/entity/EntityFactory.php @@ -175,20 +175,6 @@ final class EntityFactory{ }, ['Human']); } - /** - * @phpstan-param \Closure(World, CompoundTag) : Entity $creationFunc - */ - private static function validateCreationFunc(\Closure $creationFunc) : void{ - $sig = new CallbackType( - new ReturnType(Entity::class), - new ParameterType("world", World::class), - new ParameterType("nbt", CompoundTag::class) - ); - if(!$sig->isSatisfiedBy($creationFunc)){ - throw new \TypeError("Declaration of callable `" . CallbackType::createFromCallable($creationFunc) . "` must be compatible with `" . $sig . "`"); - } - } - /** * Registers an entity type into the index. * @@ -207,7 +193,11 @@ final class EntityFactory{ throw new \InvalidArgumentException("At least one save name must be provided"); } Utils::testValidInstance($className, Entity::class); - self::validateCreationFunc($creationFunc); + Utils::validateCallableSignature(new CallbackType( + new ReturnType(Entity::class), + new ParameterType("world", World::class), + new ParameterType("nbt", CompoundTag::class) + ), $creationFunc); foreach($saveNames as $name){ $this->creationFuncs[$name] = $creationFunc; From cb7c136035683c2da24c09f5ce8f09a14cc1dfea Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sat, 24 Sep 2022 16:54:21 +0100 Subject: [PATCH 09/13] Added documentation for some base Block classes --- src/block/Flowable.php | 4 ++++ src/block/Opaque.php | 4 ++++ src/block/Thin.php | 3 +++ src/block/Transparent.php | 6 ++++++ src/block/UnknownBlock.php | 3 +++ 5 files changed, 20 insertions(+) diff --git a/src/block/Flowable.php b/src/block/Flowable.php index c3d6f3eb5..2b4e8a02b 100644 --- a/src/block/Flowable.php +++ b/src/block/Flowable.php @@ -26,6 +26,10 @@ namespace pocketmine\block; use pocketmine\block\utils\SupportType; use pocketmine\math\AxisAlignedBB; +/** + * "Flowable" blocks are destroyed if water flows into the same space as the block. These blocks usually don't have any + * collision boxes, and can't provide support for other blocks. + */ abstract class Flowable extends Transparent{ public function canBeFlowedInto() : bool{ diff --git a/src/block/Opaque.php b/src/block/Opaque.php index 43e4e95d6..c699bc258 100644 --- a/src/block/Opaque.php +++ b/src/block/Opaque.php @@ -23,6 +23,10 @@ declare(strict_types=1); namespace pocketmine\block; +/** + * Opaque blocks do not allow light to pass through. They are usually collidable full-cube blocks. + * Most blocks in Minecraft fall into this category. + */ class Opaque extends Block{ public function isSolid() : bool{ diff --git a/src/block/Thin.php b/src/block/Thin.php index ad5824494..f6e41d43a 100644 --- a/src/block/Thin.php +++ b/src/block/Thin.php @@ -29,6 +29,9 @@ use pocketmine\math\AxisAlignedBB; use pocketmine\math\Facing; use function count; +/** + * Thin blocks behave like glass panes. They connect to full-cube blocks horizontally adjacent to them if possible. + */ class Thin extends Transparent{ /** @var bool[] facing => dummy */ protected array $connections = []; diff --git a/src/block/Transparent.php b/src/block/Transparent.php index b4489cebf..e1ad9588a 100644 --- a/src/block/Transparent.php +++ b/src/block/Transparent.php @@ -23,6 +23,12 @@ declare(strict_types=1); namespace pocketmine\block; +/** + * Transparent blocks do not block any light from propagating through them. + * + * Note: This does **not** imply that the block is **visually** transparent. For example, chests allow light to pass + * through, but the player cannot see through them except at the edges. + */ class Transparent extends Block{ public function isTransparent() : bool{ diff --git a/src/block/UnknownBlock.php b/src/block/UnknownBlock.php index 81a2af259..e81e0ed19 100644 --- a/src/block/UnknownBlock.php +++ b/src/block/UnknownBlock.php @@ -25,6 +25,9 @@ namespace pocketmine\block; use pocketmine\item\Item; +/** + * Represents a block which is unrecognized or not implemented. + */ class UnknownBlock extends Transparent{ public function __construct(BlockIdentifier $idInfo, BlockBreakInfo $breakInfo){ From 140a809c407e72fbb29ffc6d191a89b737a1ceb8 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sat, 24 Sep 2022 17:04:42 +0100 Subject: [PATCH 10/13] Block: improve documentation of hasEntityCollision() and onEntityInside() --- src/block/Block.php | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/block/Block.php b/src/block/Block.php index a7839e8ee..dfc1635d6 100644 --- a/src/block/Block.php +++ b/src/block/Block.php @@ -329,10 +329,6 @@ class Block{ return false; } - public function hasEntityCollision() : bool{ - return false; - } - /** * Returns whether entities can climb up this block. */ @@ -561,10 +557,21 @@ class Block{ return false; } + /** + * Returns whether the block has actions to be executed when an entity enters its cell (full cube space). + * + * @see Block::onEntityInside() + */ + public function hasEntityCollision() : bool{ + return false; + } + /** * Called when an entity's bounding box clips inside this block's cell. Note that the entity may not be intersecting * with the collision box or bounding box. * + * WARNING: This will not be called if {@link Block::hasEntityCollision()} returns false. + * * @return bool Whether the block is still the same after the intersection. If it changed (e.g. due to an explosive * being ignited), this should return false. */ From 77a18d0aea868077dd8858f65e662877c20dadcc Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sat, 24 Sep 2022 17:05:38 +0100 Subject: [PATCH 11/13] Block: add documentation for getFrictionFactor() has no one ever questioned the fact that a higher _friction_ factor _reduces_ the block's friction??? --- src/block/Block.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/block/Block.php b/src/block/Block.php index dfc1635d6..266e4c785 100644 --- a/src/block/Block.php +++ b/src/block/Block.php @@ -282,6 +282,12 @@ class Block{ return false; } + /** + * Returns a multiplier applied to the velocity of entities moving on top of this block. A higher value will make + * the block more slippery (like ice). + * + * @return float 0.0-1.0 + */ public function getFrictionFactor() : float{ return 0.6; } From 6a0c54f850c263f58e7551257265c6922aeac5d5 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sat, 24 Sep 2022 17:24:35 +0100 Subject: [PATCH 12/13] Block: Relocate and document addVelocityToEntity() maybe we should consider merging this with onEntityInside(), since they are both called for the same reasons? ... --- src/block/Block.php | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/block/Block.php b/src/block/Block.php index 266e4c785..41983df64 100644 --- a/src/block/Block.php +++ b/src/block/Block.php @@ -342,10 +342,6 @@ class Block{ return false; } - public function addVelocityToEntity(Entity $entity) : ?Vector3{ - return null; - } - final public function getPosition() : Position{ return $this->position; } @@ -585,6 +581,19 @@ class Block{ return true; } + /** + * Returns a direction vector describing which way an entity intersecting this block should be pushed. + * This is used by liquids to push entities in liquid currents. + * + * The returned vector is summed with vectors from every other block the entity is intersecting, and normalized to + * produce a final direction vector. + * + * WARNING: This will not be called if {@link Block::hasEntityCollision()} does not return true! + */ + public function addVelocityToEntity(Entity $entity) : ?Vector3{ + return null; + } + /** * Called when an entity lands on this block (usually due to falling). * @return float|null The new vertical velocity of the entity, or null if unchanged. From f448b2e6855c3fb9f6cda182c2a827975aada616 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sat, 24 Sep 2022 18:06:46 +0100 Subject: [PATCH 13/13] Block: Improve documentation for a whole bunch of methods --- src/block/Block.php | 78 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 72 insertions(+), 6 deletions(-) diff --git a/src/block/Block.php b/src/block/Block.php index 41983df64..73e1b1ccb 100644 --- a/src/block/Block.php +++ b/src/block/Block.php @@ -78,25 +78,47 @@ class Block{ $this->position = clone $this->position; } + /** + * Returns an object containing information about how to identify and store this block type, such as its legacy + * numeric ID(s), tile type (if any), and legacy variant metadata. + */ public function getIdInfo() : BlockIdentifier{ return $this->idInfo; } + /** + * Returns the printable English name of the block. + */ public function getName() : string{ return $this->fallbackName; } + /** + * @deprecated + * + * Returns the legacy numeric Minecraft block ID. + */ public function getId() : int{ return $this->idInfo->getBlockId(); } /** * @internal + * + * Returns the full blockstate ID of this block. This is a compact way of representing a blockstate used to store + * blocks in chunks at runtime. + * + * This ID can be used to later obtain a copy of this block using {@link BlockFactory::get()}. */ public function getFullId() : int{ return ($this->getId() << self::INTERNAL_METADATA_BITS) | $this->getMeta(); } + /** + * Returns the block as an item. + * State information such as facing, powered/unpowered, open/closed, etc., is discarded. + * Type information such as colour, wood type, etc. is preserved. + */ public function asItem() : Item{ return ItemFactory::getInstance()->get( $this->idInfo->getItemId(), @@ -104,6 +126,12 @@ class Block{ ); } + /** + * @deprecated + * + * Returns the legacy Minecraft block meta value. This is a mixed-purpose value, which is used to store different + * things for different blocks. + */ public function getMeta() : int{ $stateMeta = $this->writeStateToMeta(); assert(($stateMeta & ~$this->getStateBitmask()) === 0); @@ -116,6 +144,7 @@ class Block{ /** * Returns a bitmask used to extract state bits from block metadata. + * This is used to remove unwanted information from the legacy meta value when getting the block as an item. */ public function getStateBitmask() : int{ return 0; @@ -143,6 +172,12 @@ class Block{ $this->collisionBoxes = null; } + /** + * Writes information about the block into the world. This writes the blockstate ID into the chunk, and creates + * and/or removes tiles as necessary. + * + * Note: Do not call this directly. Pass the block to {@link World::setBlock()} instead. + */ public function writeStateToWorld() : void{ $this->position->getWorld()->getOrLoadChunkAtPosition($this->position)->setFullBlock($this->position->x & Chunk::COORD_MASK, $this->position->y, $this->position->z & Chunk::COORD_MASK, $this->getFullId()); @@ -167,7 +202,7 @@ class Block{ } /** - * Returns a type ID that identifies this type of block. This does not include information like facing, colour, + * Returns a type ID that identifies this type of block. This does not include information like facing, open/closed, * powered/unpowered, etc. */ public function getTypeId() : int{ @@ -198,22 +233,36 @@ class Block{ return true; } + /** + * Returns whether this block can be replaced by another block placed in the same position. + */ public function canBeReplaced() : bool{ return false; } + /** + * Returns whether this block can replace the given block in the given placement conditions. + * This is used to allow slabs of the same type to combine into double slabs. + */ public function canBePlacedAt(Block $blockReplace, Vector3 $clickVector, int $face, bool $isClickedBlock) : bool{ return $blockReplace->canBeReplaced(); } /** - * Places the Block, using block space and block target, and side. Returns if the block has been placed. + * Generates a block transaction to set all blocks affected by placing this block. Usually this is just the block + * itself, but may be multiple blocks in some cases (such as doors). + * + * @return bool whether the placement should go ahead */ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ $tx->addBlock($blockReplace->position, $this); return true; } + /** + * Called immediately after the block has been placed in the world. Since placement uses a block transaction, some + * things may not be possible until after the transaction has been executed. + */ public function onPostPlace() : void{ } @@ -252,7 +301,7 @@ class Block{ /** * Called when this block is randomly updated due to chunk ticking. - * WARNING: This will not be called if ticksRandomly() does not return true! + * WARNING: This will not be called if {@link Block::ticksRandomly()} does not return true! */ public function onRandomTick() : void{ @@ -273,8 +322,7 @@ class Block{ } /** - * Called when this block is attacked (left-clicked). This is called when a player left-clicks the block to try and - * start to break it in survival mode. + * Called when this block is attacked (left-clicked) by a player attempting to start breaking it in survival. * * @return bool if an action took place, prevents starting to break the block if true. */ @@ -293,6 +341,8 @@ class Block{ } /** + * Returns the amount of light emitted by this block. + * * @return int 0-15 */ public function getLightLevel() : int{ @@ -424,6 +474,7 @@ class Block{ /** * Returns the item that players will equip when middle-clicking on this block. + * If addUserData is true, additional data may be added, such as banner patterns, chest contents, etc. */ public function getPickedItem(bool $addUserData = false) : Item{ $item = $this->asItem(); @@ -547,7 +598,7 @@ class Block{ } /** - * Checks for collision against an AxisAlignedBB + * Returns whether any of the block's collision boxes intersect with the given AxisAlignedBB. */ public function collidesWithBB(AxisAlignedBB $bb) : bool{ foreach($this->getCollisionBoxes() as $bb2){ @@ -603,6 +654,13 @@ class Block{ } /** + * Returns an array of collision bounding boxes for this block. + * These are used for: + * - entity movement collision checks (to ensure entities can't clip through blocks) + * - projectile flight paths + * - block placement (to ensure the player can't place blocks inside itself or another entity) + * - anti-cheat checks in plugins + * * @return AxisAlignedBB[] */ final public function getCollisionBoxes() : array{ @@ -633,6 +691,10 @@ class Block{ return [AxisAlignedBB::one()]; } + /** + * Returns the type of support that the block can provide on the given face. This is used to determine whether + * blocks placed on the given face can be supported by this block. + */ public function getSupportType(int $facing) : SupportType{ return SupportType::FULL(); } @@ -643,6 +705,10 @@ class Block{ return count($bb) === 1 && $bb[0]->getAverageEdgeLength() >= 1 && $bb[0]->isCube(); } + /** + * Performs a ray trace along the line between the two positions using the block's collision boxes. + * Returns the intersection point closest to pos1, or null if no intersection occurred. + */ public function calculateIntercept(Vector3 $pos1, Vector3 $pos2) : ?RayTraceResult{ $bbs = $this->getCollisionBoxes(); if(count($bbs) === 0){