Merge branch 'stable' into next-minor

This commit is contained in:
Dylan K. Taylor 2022-09-24 18:07:56 +01:00
commit a7dfa0907c
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
11 changed files with 168 additions and 30 deletions

@ -1 +1 @@
Subproject commit cf79c0172283a0a26f2c3695af260d100e0fdabd
Subproject commit 50062b5861235fbb9fe6e5d5b30684f4cb464470

View File

@ -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"

28
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": "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",
@ -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",

View File

@ -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{
$world = $this->position->getWorld();
$world->getOrLoadChunkAtPosition($this->position)->setFullBlock($this->position->x & Chunk::COORD_MASK, $this->position->y, $this->position->z & Chunk::COORD_MASK, $this->getFullId());
@ -168,7 +203,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{
@ -199,22 +234,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{
}
@ -254,7 +303,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{
@ -275,8 +324,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.
*/
@ -284,11 +332,19 @@ 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;
}
/**
* Returns the amount of light emitted by this block.
*
* @return int 0-15
*/
public function getLightLevel() : int{
@ -331,10 +387,6 @@ class Block{
return false;
}
public function hasEntityCollision() : bool{
return false;
}
/**
* Returns whether entities can climb up this block.
*/
@ -342,10 +394,6 @@ class Block{
return false;
}
public function addVelocityToEntity(Entity $entity) : ?Vector3{
return null;
}
final public function getPosition() : Position{
return $this->position;
}
@ -428,6 +476,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();
@ -551,7 +600,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){
@ -563,10 +612,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.
*/
@ -574,6 +634,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.
@ -583,6 +656,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{
@ -613,6 +693,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();
}
@ -623,6 +707,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){

View File

@ -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{

View File

@ -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{

View File

@ -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 = [];

View File

@ -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{

View File

@ -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){

View File

@ -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());
}
}
}

View File

@ -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;
}