Merge branch 'php/7.0' into mcpe-1.2

This commit is contained in:
Dylan K. Taylor 2017-09-01 23:10:58 +01:00
commit 5d75d3d5b6
54 changed files with 462 additions and 382 deletions

View File

@ -23,7 +23,7 @@ declare(strict_types=1);
namespace pocketmine;
abstract class Collectable extends \Threaded implements \Collectable{
abstract class Collectable extends \Threaded{
private $isGarbage = false;

View File

@ -2411,7 +2411,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$points += $armorItem->getDefensePoints();
}
$damage[EntityDamageEvent::MODIFIER_ARMOR] = -floor($damage[EntityDamageEvent::MODIFIER_BASE] * $points * 0.04);
$damage[EntityDamageEvent::MODIFIER_ARMOR] = -($damage[EntityDamageEvent::MODIFIER_BASE] * $points * 0.04);
}
$ev = new EntityDamageByEntityEvent($this, $target, EntityDamageEvent::CAUSE_ENTITY_ATTACK, $damage);

View File

@ -89,8 +89,8 @@ namespace pocketmine {
* Enjoy it as much as I did writing it. I don't want to do it again.
*/
if(version_compare("7.0", PHP_VERSION) > 0){
echo "[CRITICAL] You must use PHP >= 7.0" . PHP_EOL;
if(version_compare("7.0", PHP_VERSION) > 0 or version_compare("7.1", PHP_VERSION) <= 0){
echo "[CRITICAL] You must use PHP 7.0" . PHP_EOL;
echo "[CRITICAL] Please use the installer provided on the homepage." . PHP_EOL;
exit(1);
}

View File

@ -31,9 +31,10 @@ use pocketmine\level\Position;
*/
class BlockFactory{
/** @var \SplFixedArray<Block> */
public static $list = null;
private static $list = null;
/** @var \SplFixedArray<Block> */
public static $fullList = null;
private static $fullList = null;
/** @var \SplFixedArray<bool> */
public static $solid = null;
/** @var \SplFixedArray<bool> */
@ -59,6 +60,7 @@ class BlockFactory{
if(self::$list === null or $force){
self::$list = new \SplFixedArray(256);
self::$fullList = new \SplFixedArray(4096);
self::$light = new \SplFixedArray(256);
self::$lightFilter = new \SplFixedArray(256);
self::$solid = new \SplFixedArray(256);
@ -393,4 +395,12 @@ class BlockFactory{
return $block;
}
/**
* @internal
* @return \SplFixedArray
*/
public static function getBlockStatesArray() : \SplFixedArray{
return self::$fullList;
}
}

View File

@ -136,10 +136,6 @@ class Chest extends Transparent{
public function onActivate(Item $item, Player $player = null) : bool{
if($player instanceof Player){
$top = $this->getSide(Vector3::SIDE_UP);
if($top->isTransparent() !== true){
return true;
}
$t = $this->getLevel()->getTile($this);
$chest = null;
@ -157,10 +153,12 @@ class Chest extends Transparent{
$chest = Tile::createTile("Chest", $this->getLevel(), $nbt);
}
if(isset($chest->namedtag->Lock) and $chest->namedtag->Lock instanceof StringTag){
if($chest->namedtag->Lock->getValue() !== $item->getCustomName()){
return true;
}
if(
!$this->getSide(Vector3::SIDE_UP)->isTransparent() or
($chest->isPaired() and !$chest->getPair()->getBlock()->getSide(Vector3::SIDE_UP)->isTransparent()) or
(isset($chest->namedtag->Lock) and $chest->namedtag->Lock instanceof StringTag and $chest->namedtag->Lock->getValue() !== $item->getCustomName())
){
return true;
}
$player->addWindow($chest->getInventory());

View File

@ -254,48 +254,50 @@ abstract class Liquid extends Transparent{
//$this->updateFlow();
}
$bottomBlock = $this->level->getBlock($this->temporalVector->setComponents($this->x, $this->y - 1, $this->z));
if($decay >= 0){
$bottomBlock = $this->level->getBlock($this->temporalVector->setComponents($this->x, $this->y - 1, $this->z));
if($this instanceof Lava and $bottomBlock instanceof Water){
$this->getLevel()->setBlock($bottomBlock, BlockFactory::get(Block::STONE), true, true);
if($this instanceof Lava and $bottomBlock instanceof Water){
$this->getLevel()->setBlock($bottomBlock, BlockFactory::get(Block::STONE), true, true);
}elseif($bottomBlock->canBeFlowedInto() or ($bottomBlock instanceof Liquid and ($bottomBlock->getDamage() & 0x07) !== 0)){
$this->getLevel()->setBlock($bottomBlock, BlockFactory::get($this->id, $decay | 0x08), true, false);
$this->getLevel()->scheduleDelayedBlockUpdate($bottomBlock, $this->tickRate());
}elseif($bottomBlock->canBeFlowedInto() or ($bottomBlock instanceof Liquid and ($bottomBlock->getDamage() & 0x07) !== 0)){
$this->getLevel()->setBlock($bottomBlock, BlockFactory::get($this->id, $decay | 0x08), true, false);
$this->getLevel()->scheduleDelayedBlockUpdate($bottomBlock, $this->tickRate());
}elseif($decay >= 0 and ($decay === 0 or !$bottomBlock->canBeFlowedInto())){
$flags = $this->getOptimalFlowDirections();
}elseif($decay === 0 or !$bottomBlock->canBeFlowedInto()){
$flags = $this->getOptimalFlowDirections();
$l = $decay + $multiplier;
$l = $decay + $multiplier;
if($decay >= 8){
$l = 1;
if($decay >= 8){
$l = 1;
}
if($l >= 8){
$this->checkForHarden();
return;
}
if($flags[0]){
$this->flowIntoBlock($this->level->getBlock($this->temporalVector->setComponents($this->x - 1, $this->y, $this->z)), $l);
}
if($flags[1]){
$this->flowIntoBlock($this->level->getBlock($this->temporalVector->setComponents($this->x + 1, $this->y, $this->z)), $l);
}
if($flags[2]){
$this->flowIntoBlock($this->level->getBlock($this->temporalVector->setComponents($this->x, $this->y, $this->z - 1)), $l);
}
if($flags[3]){
$this->flowIntoBlock($this->level->getBlock($this->temporalVector->setComponents($this->x, $this->y, $this->z + 1)), $l);
}
}
if($l >= 8){
$this->checkForHarden();
return;
}
if($flags[0]){
$this->flowIntoBlock($this->level->getBlock($this->temporalVector->setComponents($this->x - 1, $this->y, $this->z)), $l);
}
if($flags[1]){
$this->flowIntoBlock($this->level->getBlock($this->temporalVector->setComponents($this->x + 1, $this->y, $this->z)), $l);
}
if($flags[2]){
$this->flowIntoBlock($this->level->getBlock($this->temporalVector->setComponents($this->x, $this->y, $this->z - 1)), $l);
}
if($flags[3]){
$this->flowIntoBlock($this->level->getBlock($this->temporalVector->setComponents($this->x, $this->y, $this->z + 1)), $l);
}
$this->checkForHarden();
}
$this->checkForHarden();
}
}

View File

@ -396,11 +396,10 @@ class Effect{
* Adds this effect to the Entity, performing effect overriding as specified.
*
* @param Entity $entity
* @param bool $modify
* @param Effect|null $oldEffect
*/
public function add(Entity $entity, bool $modify = false, Effect $oldEffect = null){
$entity->getLevel()->getServer()->getPluginManager()->callEvent($ev = new EntityEffectAddEvent($entity, $this, $modify, $oldEffect));
public function add(Entity $entity, Effect $oldEffect = null){
$entity->getLevel()->getServer()->getPluginManager()->callEvent($ev = new EntityEffectAddEvent($entity, $this, $oldEffect));
if($ev->isCancelled()){
return;
}
@ -411,7 +410,7 @@ class Effect{
$pk->amplifier = $this->getAmplifier();
$pk->particles = $this->isVisible();
$pk->duration = $this->getDuration();
if($ev->willModify()){
if($oldEffect !== null){
$pk->eventId = MobEffectPacket::EVENT_MODIFY;
}else{
$pk->eventId = MobEffectPacket::EVENT_ADD;
@ -420,6 +419,10 @@ class Effect{
$entity->dataPacket($pk);
}
if($oldEffect !== null){
$oldEffect->remove($entity, false);
}
switch($this->id){
case Effect::INVISIBILITY:
$entity->setGenericFlag(Entity::DATA_FLAG_INVISIBLE, true);
@ -427,35 +430,16 @@ class Effect{
break;
case Effect::SPEED:
$attr = $entity->getAttributeMap()->getAttribute(Attribute::MOVEMENT_SPEED);
if($ev->willModify() and $oldEffect !== null){
$speed = $attr->getValue() / (1 + 0.2 * $oldEffect->getEffectLevel());
}else{
$speed = $attr->getValue();
}
$speed *= (1 + 0.2 * $this->getEffectLevel());
$attr->setValue($speed);
$attr->setValue($attr->getValue() * (1 + 0.2 * $this->getEffectLevel()));
break;
case Effect::SLOWNESS:
$attr = $entity->getAttributeMap()->getAttribute(Attribute::MOVEMENT_SPEED);
if($ev->willModify() and $oldEffect !== null){
$speed = $attr->getValue() / (1 - 0.15 * $oldEffect->getEffectLevel());
}else{
$speed = $attr->getValue();
}
$speed *= (1 - 0.15 * $this->getEffectLevel());
$attr->setValue($speed, true);
$attr->setValue($attr->getValue() * (1 - 0.15 * $this->getEffectLevel()), true);
break;
case Effect::HEALTH_BOOST:
$attr = $entity->getAttributeMap()->getAttribute(Attribute::HEALTH);
if($ev->willModify() and $oldEffect !== null){
$max = $attr->getMaxValue() - (4 * $oldEffect->getEffectLevel());
}else{
$max = $attr->getMaxValue();
}
$max += (4 * $this->getEffectLevel());
$attr->setMaxValue($max);
$attr->setMaxValue($attr->getMaxValue() + 4 * $this->getEffectLevel());
break;
case Effect::ABSORPTION:
$new = (4 * $this->getEffectLevel());
@ -470,13 +454,15 @@ class Effect{
* Removes the effect from the entity, resetting any changed values back to their original defaults.
*
* @param Entity $entity
* @param bool $send
*/
public function remove(Entity $entity){
public function remove(Entity $entity, bool $send = true){
$entity->getLevel()->getServer()->getPluginManager()->callEvent($ev = new EntityEffectRemoveEvent($entity, $this));
if($ev->isCancelled()){
return;
}
if($entity instanceof Player){
if($send and $entity instanceof Player){
$pk = new MobEffectPacket();
$pk->entityRuntimeId = $entity->getId();
$pk->eventId = MobEffectPacket::EVENT_REMOVE;

View File

@ -307,8 +307,8 @@ abstract class Entity extends Location implements Metadatable{
/** @var float */
protected $baseOffset = 0.0;
/** @var int */
private $health = 20;
/** @var float */
private $health = 20.0;
private $maxHealth = 20;
/** @var float */
@ -931,9 +931,9 @@ abstract class Entity extends Location implements Metadatable{
}
/**
* @return int
* @return float
*/
public function getHealth(){
public function getHealth() : float{
return $this->health;
}
@ -944,11 +944,10 @@ abstract class Entity extends Location implements Metadatable{
/**
* Sets the health of the Entity. This won't send any update to the players
*
* @param int $amount
* @param float $amount
*/
public function setHealth($amount){
$amount = (int) $amount;
if($amount === $this->health){
public function setHealth(float $amount){
if($amount == $this->health){
return;
}
@ -957,7 +956,7 @@ abstract class Entity extends Location implements Metadatable{
$this->kill();
}
}elseif($amount <= $this->getMaxHealth() or $amount < $this->health){
$this->health = (int) $amount;
$this->health = $amount;
}else{
$this->health = $this->getMaxHealth();
}
@ -992,15 +991,15 @@ abstract class Entity extends Location implements Metadatable{
/**
* @return int
*/
public function getMaxHealth(){
public function getMaxHealth() : int{
return $this->maxHealth;
}
/**
* @param int $amount
*/
public function setMaxHealth($amount){
$this->maxHealth = (int) $amount;
public function setMaxHealth(int $amount){
$this->maxHealth = $amount;
}
public function canCollideWith(Entity $entity) : bool{

View File

@ -549,7 +549,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
* @param int $flagId
* @return bool
*/
public function getPlayerFlag(int $flagId){
public function getPlayerFlag(int $flagId) : bool{
return $this->getDataFlag(self::DATA_PLAYER_FLAGS, $flagId);
}

View File

@ -58,7 +58,7 @@ class Item extends Entity{
parent::initEntity();
$this->setMaxHealth(5);
$this->setHealth($this->namedtag["Health"]);
$this->setHealth((int) $this->namedtag["Health"]);
if(isset($this->namedtag->Age)){
$this->age = $this->namedtag["Age"];
}
@ -139,7 +139,7 @@ class Item extends Entity{
public function saveNBT(){
parent::saveNBT();
$this->namedtag->Item = $this->item->nbtSerialize(-1, "Item");
$this->namedtag->Health = new ShortTag("Health", $this->getHealth());
$this->namedtag->Health = new ShortTag("Health", (int) $this->getHealth());
$this->namedtag->Age = new ShortTag("Age", $this->age);
$this->namedtag->PickupDelay = new ShortTag("PickupDelay", $this->pickupDelay);
if($this->owner !== null){

View File

@ -73,7 +73,7 @@ abstract class Living extends Entity implements Damageable{
$this->namedtag->Health = new FloatTag("Health", (float) $this->getMaxHealth());
}
$this->setHealth($this->namedtag["Health"]);
$this->setHealth((float) $this->namedtag["Health"]);
if(isset($this->namedtag->ActiveEffects)){
foreach($this->namedtag->ActiveEffects->getValue() as $e){
@ -100,10 +100,10 @@ abstract class Living extends Entity implements Damageable{
$this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::ABSORPTION));
}
public function setHealth($amount){
public function setHealth(float $amount){
$wasAlive = $this->isAlive();
parent::setHealth($amount);
$this->attributeMap->getAttribute(Attribute::HEALTH)->setValue($this->getHealth(), true);
$this->attributeMap->getAttribute(Attribute::HEALTH)->setValue(ceil($this->getHealth()), true);
if($this->isAlive() and !$wasAlive){
$pk = new EntityEventPacket();
$pk->entityRuntimeId = $this->getId();
@ -112,11 +112,11 @@ abstract class Living extends Entity implements Damageable{
}
}
public function getMaxHealth(){
return $this->attributeMap->getAttribute(Attribute::HEALTH)->getMaxValue();
public function getMaxHealth() : int{
return (int) $this->attributeMap->getAttribute(Attribute::HEALTH)->getMaxValue();
}
public function setMaxHealth($amount){
public function setMaxHealth(int $amount){
$this->attributeMap->getAttribute(Attribute::HEALTH)->setMaxValue($amount);
}
@ -237,9 +237,9 @@ abstract class Living extends Entity implements Damageable{
){
return;
}
$effect->add($this, true, $oldEffect);
$effect->add($this, $oldEffect);
}else{
$effect->add($this, false);
$effect->add($this);
}
$this->effects[$effect->getId()] = $effect;

View File

@ -23,39 +23,7 @@ declare(strict_types=1);
namespace pocketmine\event\entity;
use pocketmine\entity\Entity;
use pocketmine\event\Cancellable;
use pocketmine\item\Item;
class EntityArmorChangeEvent extends EntityEvent implements Cancellable{
class EntityArmorChangeEvent extends EntityInventoryChangeEvent{
public static $handlerList = null;
private $oldItem;
private $newItem;
private $slot;
public function __construct(Entity $entity, Item $oldItem, Item $newItem, $slot){
$this->entity = $entity;
$this->oldItem = $oldItem;
$this->newItem = $newItem;
$this->slot = (int) $slot;
}
public function getSlot(){
return $this->slot;
}
public function getNewItem(){
return $this->newItem;
}
public function setNewItem(Item $item){
$this->newItem = $item;
}
public function getOldItem(){
return $this->oldItem;
}
}

View File

@ -33,7 +33,9 @@ use pocketmine\event\Cancellable;
class EntityBlockChangeEvent extends EntityEvent implements Cancellable{
public static $handlerList = null;
/** @var Block */
private $from;
/** @var Block */
private $to;
public function __construct(Entity $entity, Block $from, Block $to){
@ -45,14 +47,14 @@ class EntityBlockChangeEvent extends EntityEvent implements Cancellable{
/**
* @return Block
*/
public function getBlock(){
public function getBlock() : Block{
return $this->from;
}
/**
* @return Block
*/
public function getTo(){
public function getTo() : Block{
return $this->to;
}

View File

@ -28,6 +28,7 @@ use pocketmine\entity\Entity;
class EntityCombustByBlockEvent extends EntityCombustEvent{
/** @var Block */
protected $combuster;
/**
@ -35,7 +36,7 @@ class EntityCombustByBlockEvent extends EntityCombustEvent{
* @param Entity $combustee
* @param int $duration
*/
public function __construct(Block $combuster, Entity $combustee, $duration){
public function __construct(Block $combuster, Entity $combustee, int $duration){
parent::__construct($combustee, $duration);
$this->combuster = $combuster;
}
@ -43,7 +44,7 @@ class EntityCombustByBlockEvent extends EntityCombustEvent{
/**
* @return Block
*/
public function getCombuster(){
public function getCombuster() : Block{
return $this->combuster;
}

View File

@ -27,6 +27,7 @@ use pocketmine\entity\Entity;
class EntityCombustByEntityEvent extends EntityCombustEvent{
/** @var Entity */
protected $combuster;
/**
@ -34,7 +35,7 @@ class EntityCombustByEntityEvent extends EntityCombustEvent{
* @param Entity $combustee
* @param int $duration
*/
public function __construct(Entity $combuster, Entity $combustee, $duration){
public function __construct(Entity $combuster, Entity $combustee, int $duration){
parent::__construct($combustee, $duration);
$this->combuster = $combuster;
}
@ -42,7 +43,7 @@ class EntityCombustByEntityEvent extends EntityCombustEvent{
/**
* @return Entity
*/
public function getCombuster(){
public function getCombuster() : Entity{
return $this->combuster;
}

View File

@ -35,17 +35,21 @@ class EntityCombustEvent extends EntityEvent implements Cancellable{
* @param Entity $combustee
* @param int $duration
*/
public function __construct(Entity $combustee, $duration){
public function __construct(Entity $combustee, int $duration){
$this->entity = $combustee;
$this->duration = $duration;
}
public function getDuration(){
/**
* Returns the duration in seconds the entity will burn for.
* @return int
*/
public function getDuration() : int{
return $this->duration;
}
public function setDuration($duration){
$this->duration = (int) $duration;
public function setDuration(int $duration){
$this->duration = $duration;
}
}

View File

@ -36,12 +36,12 @@ class EntityDamageByBlockEvent extends EntityDamageEvent{
/**
* @param Block $damager
* @param Entity $entity
* @param int $cause
* @param int|int[] $damage
* @param Block $damager
* @param Entity $entity
* @param int $cause
* @param float|float[] $damage
*/
public function __construct(Block $damager, Entity $entity, $cause, $damage){
public function __construct(Block $damager, Entity $entity, int $cause, $damage){
$this->damager = $damager;
parent::__construct($entity, $cause, $damage);
}
@ -49,7 +49,7 @@ class EntityDamageByBlockEvent extends EntityDamageEvent{
/**
* @return Block
*/
public function getDamager(){
public function getDamager() : Block{
return $this->damager;
}

View File

@ -33,15 +33,14 @@ class EntityDamageByChildEntityEvent extends EntityDamageByEntityEvent{
/** @var int */
private $childEntityEid;
/**
* @param Entity $damager
* @param Entity $childEntity
* @param Entity $entity
* @param int $cause
* @param int|int[] $damage
* @param Entity $damager
* @param Entity $childEntity
* @param Entity $entity
* @param int $cause
* @param float|float[] $damage
*/
public function __construct(Entity $damager, Entity $childEntity, Entity $entity, $cause, $damage){
public function __construct(Entity $damager, Entity $childEntity, Entity $entity, int $cause, $damage){
$this->childEntityEid = $childEntity->getId();
parent::__construct($damager, $entity, $cause, $damage);
}

View File

@ -33,19 +33,19 @@ use pocketmine\entity\Living;
class EntityDamageByEntityEvent extends EntityDamageEvent{
/** @var int */
private $damagerEid;
private $damagerEntityId;
/** @var float */
private $knockBack;
/**
* @param Entity $damager
* @param Entity $entity
* @param int $cause
* @param int|int[] $damage
* @param float $knockBack
* @param Entity $damager
* @param Entity $entity
* @param int $cause
* @param float|float[] $damage
* @param float $knockBack
*/
public function __construct(Entity $damager, Entity $entity, $cause, $damage, $knockBack = 0.4){
$this->damagerEid = $damager->getId();
public function __construct(Entity $damager, Entity $entity, int $cause, $damage, float $knockBack = 0.4){
$this->damagerEntityId = $damager->getId();
$this->knockBack = $knockBack;
parent::__construct($entity, $cause, $damage);
$this->addAttackerModifiers($damager);
@ -69,20 +69,20 @@ class EntityDamageByEntityEvent extends EntityDamageEvent{
* @return Entity|null
*/
public function getDamager(){
return $this->getEntity()->getLevel()->getServer()->findEntity($this->damagerEid, $this->getEntity()->getLevel());
return $this->getEntity()->getLevel()->getServer()->findEntity($this->damagerEntityId, $this->getEntity()->getLevel());
}
/**
* @return float
*/
public function getKnockBack(){
public function getKnockBack() : float{
return $this->knockBack;
}
/**
* @param float $knockBack
*/
public function setKnockBack($knockBack){
public function setKnockBack(float $knockBack){
$this->knockBack = $knockBack;
}
}

View File

@ -55,21 +55,20 @@ class EntityDamageEvent extends EntityEvent implements Cancellable{
const CAUSE_CUSTOM = 14;
const CAUSE_STARVATION = 15;
/** @var int */
private $cause;
/** @var array */
/** @var float[] */
private $modifiers;
/** @var float[] */
private $originals;
/**
* @param Entity $entity
* @param int $cause
* @param int|int[] $damage
*
* @throws \Exception
* @param Entity $entity
* @param int $cause
* @param float|float[] $damage
*/
public function __construct(Entity $entity, $cause, $damage){
public function __construct(Entity $entity, int $cause, $damage){
$this->entity = $entity;
$this->cause = $cause;
if(is_array($damage)){
@ -90,43 +89,41 @@ class EntityDamageEvent extends EntityEvent implements Cancellable{
/**
* @return int
*/
public function getCause(){
public function getCause() : int{
return $this->cause;
}
/**
* @param int $type
*
* @return int
* @return float
*/
public function getOriginalDamage($type = self::MODIFIER_BASE){
public function getOriginalDamage(int $type = self::MODIFIER_BASE) : float{
if(isset($this->originals[$type])){
return $this->originals[$type];
}
return 0;
return 0.0;
}
/**
* @param int $type
*
* @return int
* @return float
*/
public function getDamage($type = self::MODIFIER_BASE){
public function getDamage(int $type = self::MODIFIER_BASE) : float{
if(isset($this->modifiers[$type])){
return $this->modifiers[$type];
}
return 0;
return 0.0;
}
/**
* @param float $damage
* @param int $type
*
* @throws \UnexpectedValueException
*/
public function setDamage($damage, $type = self::MODIFIER_BASE){
public function setDamage(float $damage, int $type = self::MODIFIER_BASE){
$this->modifiers[$type] = $damage;
}
@ -135,20 +132,15 @@ class EntityDamageEvent extends EntityEvent implements Cancellable{
*
* @return bool
*/
public function isApplicable($type){
public function isApplicable(int $type) : bool{
return isset($this->modifiers[$type]);
}
/**
* @return int
* @return float
*/
public function getFinalDamage(){
$damage = 0;
foreach($this->modifiers as $type => $d){
$damage += $d;
}
return $damage;
public function getFinalDamage() : float{
return array_sum($this->modifiers);
}
}

View File

@ -52,7 +52,7 @@ class EntityDeathEvent extends EntityEvent{
/**
* @return Item[]
*/
public function getDrops(){
public function getDrops() : array{
return $this->drops;
}

View File

@ -50,42 +50,42 @@ class EntityDespawnEvent extends EntityEvent{
/**
* @return int
*/
public function getType(){
public function getType() : int{
return $this->entityType;
}
/**
* @return bool
*/
public function isCreature(){
public function isCreature() : bool{
return $this->entity instanceof Creature;
}
/**
* @return bool
*/
public function isHuman(){
public function isHuman() : bool{
return $this->entity instanceof Human;
}
/**
* @return bool
*/
public function isProjectile(){
public function isProjectile() : bool{
return $this->entity instanceof Projectile;
}
/**
* @return bool
*/
public function isVehicle(){
public function isVehicle() : bool{
return $this->entity instanceof Vehicle;
}
/**
* @return bool
*/
public function isItem(){
public function isItem() : bool{
return $this->entity instanceof Item;
}

View File

@ -42,6 +42,9 @@ class EntityEatBlockEvent extends EntityEatEvent{
return parent::getResidue();
}
/**
* @param Block $residue
*/
public function setResidue($residue){
if(!($residue instanceof Block)){
throw new \InvalidArgumentException("Eating a Block can only result in a Block residue");

View File

@ -37,6 +37,7 @@ class EntityEatEvent extends EntityEvent implements Cancellable{
private $foodRestore;
/** @var float */
private $saturationRestore;
/** @var mixed */
private $residue;
/** @var Effect[] */
private $additionalEffects;
@ -50,7 +51,7 @@ class EntityEatEvent extends EntityEvent implements Cancellable{
$this->additionalEffects = $foodSource->getAdditionalEffects();
}
public function getFoodSource(){
public function getFoodSource() : FoodSource{
return $this->foodSource;
}
@ -70,10 +71,17 @@ class EntityEatEvent extends EntityEvent implements Cancellable{
$this->saturationRestore = $saturationRestore;
}
/**
* Returns the result of eating the food source.
* @return mixed
*/
public function getResidue(){
return $this->residue;
}
/**
* @param mixed $residue
*/
public function setResidue($residue){
$this->residue = $residue;
}
@ -81,7 +89,7 @@ class EntityEatEvent extends EntityEvent implements Cancellable{
/**
* @return Effect[]
*/
public function getAdditionalEffects(){
public function getAdditionalEffects() : array{
return $this->additionalEffects;
}

View File

@ -39,6 +39,9 @@ class EntityEatItemEvent extends EntityEatEvent{
return parent::getResidue();
}
/**
* @param Item $residue
*/
public function setResidue($residue){
if(!($residue instanceof Item)){
throw new \InvalidArgumentException("Eating an Item can only result in an Item residue");

View File

@ -26,28 +26,37 @@ namespace pocketmine\event\entity;
use pocketmine\entity\Effect;
use pocketmine\entity\Entity;
/**
* Called when an effect is added to an Entity.
*/
class EntityEffectAddEvent extends EntityEffectEvent{
public static $handlerList = null;
/** @var bool */
private $modify;
/** @var Effect */
/** @var Effect|null */
private $oldEffect;
public function __construct(Entity $entity, Effect $effect, $modify, $oldEffect){
/**
* @param Entity $entity
* @param Effect $effect
* @param Effect|null $oldEffect
*/
public function __construct(Entity $entity, Effect $effect, Effect $oldEffect = null){
parent::__construct($entity, $effect);
$this->modify = $modify;
$this->oldEffect = $oldEffect;
}
/**
* Returns whether the effect addition will replace an existing effect already applied to the entity.
*
* @return bool
*/
public function willModify() : bool{
return $this->modify;
}
public function setWillModify(bool $modify){
$this->modify = $modify;
return $this->hasOldEffect();
}
/**
* @return bool
*/
public function hasOldEffect() : bool{
return $this->oldEffect instanceof Effect;
}
@ -59,5 +68,4 @@ class EntityEffectAddEvent extends EntityEffectEvent{
return $this->oldEffect;
}
}

View File

@ -23,6 +23,9 @@ declare(strict_types=1);
namespace pocketmine\event\entity;
/**
* Called when an effect is removed from an entity.
*/
class EntityEffectRemoveEvent extends EntityEffectEvent{
public static $handlerList = null;

View File

@ -33,6 +33,9 @@ abstract class EntityEvent extends Event{
/** @var Entity */
protected $entity;
/**
* @return Entity
*/
public function getEntity(){
return $this->entity;
}

View File

@ -51,7 +51,7 @@ class EntityExplodeEvent extends EntityEvent implements Cancellable{
* @param Block[] $blocks
* @param float $yield
*/
public function __construct(Entity $entity, Position $position, array $blocks, $yield){
public function __construct(Entity $entity, Position $position, array $blocks, float $yield){
$this->entity = $entity;
$this->position = $position;
$this->blocks = $blocks;
@ -61,14 +61,14 @@ class EntityExplodeEvent extends EntityEvent implements Cancellable{
/**
* @return Position
*/
public function getPosition(){
public function getPosition() : Position{
return $this->position;
}
/**
* @return Block[]
*/
public function getBlockList(){
public function getBlockList() : array{
return $this->blocks;
}
@ -82,14 +82,14 @@ class EntityExplodeEvent extends EntityEvent implements Cancellable{
/**
* @return float
*/
public function getYield(){
public function getYield() : float{
return $this->yield;
}
/**
* @param float $yield
*/
public function setYield($yield){
public function setYield(float $yield){
$this->yield = $yield;
}

View File

@ -27,33 +27,54 @@ use pocketmine\entity\Entity;
use pocketmine\event\Cancellable;
use pocketmine\item\Item;
/**
* Called before a slot in an entity's inventory changes.
*/
class EntityInventoryChangeEvent extends EntityEvent implements Cancellable{
public static $handlerList = null;
/** @var Item */
private $oldItem;
/** @var Item */
private $newItem;
/** @var int */
private $slot;
public function __construct(Entity $entity, Item $oldItem, Item $newItem, $slot){
public function __construct(Entity $entity, Item $oldItem, Item $newItem, int $slot){
$this->entity = $entity;
$this->oldItem = $oldItem;
$this->newItem = $newItem;
$this->slot = (int) $slot;
$this->slot = $slot;
}
public function getSlot(){
/**
* Returns the inventory slot number affected by the event.
* @return int
*/
public function getSlot() : int{
return $this->slot;
}
public function getNewItem(){
/**
* Returns the item which will be in the slot after the event.
* @return Item
*/
public function getNewItem() : Item{
return $this->newItem;
}
/**
* @param Item $item
*/
public function setNewItem(Item $item){
$this->newItem = $item;
}
public function getOldItem(){
/**
* Returns the item currently in the slot.
* @return Item
*/
public function getOldItem() : Item{
return $this->oldItem;
}

View File

@ -30,7 +30,9 @@ use pocketmine\level\Level;
class EntityLevelChangeEvent extends EntityEvent implements Cancellable{
public static $handlerList = null;
/** @var Level */
private $originLevel;
/** @var Level */
private $targetLevel;
public function __construct(Entity $entity, Level $originLevel, Level $targetLevel){
@ -39,11 +41,11 @@ class EntityLevelChangeEvent extends EntityEvent implements Cancellable{
$this->targetLevel = $targetLevel;
}
public function getOrigin(){
public function getOrigin() : Level{
return $this->originLevel;
}
public function getTarget(){
public function getTarget() : Level{
return $this->targetLevel;
}
}

View File

@ -30,6 +30,7 @@ use pocketmine\math\Vector3;
class EntityMotionEvent extends EntityEvent implements Cancellable{
public static $handlerList = null;
/** @var Vector3 */
private $mot;
public function __construct(Entity $entity, Vector3 $mot){
@ -40,7 +41,7 @@ class EntityMotionEvent extends EntityEvent implements Cancellable{
/**
* @return Vector3
*/
public function getVector(){
public function getVector() : Vector3{
return $this->mot;
}

View File

@ -35,7 +35,9 @@ class EntityRegainHealthEvent extends EntityEvent implements Cancellable{
const CAUSE_CUSTOM = 3;
const CAUSE_SATURATION = 4;
/** @var float */
private $amount;
/** @var int */
private $reason;
@ -44,27 +46,31 @@ class EntityRegainHealthEvent extends EntityEvent implements Cancellable{
* @param float $amount
* @param int $regainReason
*/
public function __construct(Entity $entity, $amount, $regainReason){
public function __construct(Entity $entity, float $amount, int $regainReason){
$this->entity = $entity;
$this->amount = $amount;
$this->reason = (int) $regainReason;
$this->reason = $regainReason;
}
/**
* @return float
*/
public function getAmount(){
public function getAmount() : float{
return $this->amount;
}
/**
* @param float $amount
*/
public function setAmount($amount){
public function setAmount(float $amount){
$this->amount = $amount;
}
public function getRegainReason(){
/**
* Returns one of the CAUSE_* constants to indicate why this regeneration occurred.
* @return int
*/
public function getRegainReason() : int{
return $this->reason;
}

View File

@ -45,7 +45,7 @@ class EntityShootBowEvent extends EntityEvent implements Cancellable{
* @param Projectile $projectile
* @param float $force
*/
public function __construct(Living $shooter, Item $bow, Projectile $projectile, $force){
public function __construct(Living $shooter, Item $bow, Projectile $projectile, float $force){
$this->entity = $shooter;
$this->bow = $bow;
$this->projectile = $projectile;
@ -62,14 +62,18 @@ class EntityShootBowEvent extends EntityEvent implements Cancellable{
/**
* @return Item
*/
public function getBow(){
public function getBow() : Item{
return $this->bow;
}
/**
* Returns the entity considered as the projectile in this event.
*
* NOTE: This might not return a Projectile if a plugin modified the target entity.
*
* @return Entity
*/
public function getProjectile(){
public function getProjectile() : Entity{
return $this->projectile;
}
@ -89,14 +93,14 @@ class EntityShootBowEvent extends EntityEvent implements Cancellable{
/**
* @return float
*/
public function getForce(){
public function getForce() : float{
return $this->force;
}
/**
* @param float $force
*/
public function setForce($force){
public function setForce(float $force){
$this->force = $force;
}

View File

@ -51,49 +51,49 @@ class EntitySpawnEvent extends EntityEvent{
/**
* @return Position
*/
public function getPosition(){
public function getPosition() : Position{
return $this->entity->getPosition();
}
/**
* @return int
*/
public function getType(){
public function getType() : int{
return $this->entityType;
}
/**
* @return bool
*/
public function isCreature(){
public function isCreature() : bool{
return $this->entity instanceof Creature;
}
/**
* @return bool
*/
public function isHuman(){
public function isHuman() : bool{
return $this->entity instanceof Human;
}
/**
* @return bool
*/
public function isProjectile(){
public function isProjectile() : bool{
return $this->entity instanceof Projectile;
}
/**
* @return bool
*/
public function isVehicle(){
public function isVehicle() : bool{
return $this->entity instanceof Vehicle;
}
/**
* @return bool
*/
public function isItem(){
public function isItem() : bool{
return $this->entity instanceof Item;
}

View File

@ -44,11 +44,12 @@ class EntityTeleportEvent extends EntityEvent implements Cancellable{
/**
* @return Position
*/
public function getFrom(){
public function getFrom() : Position{
return $this->from;
}
/**
* @deprecated This method has no effect or use.
* @param Position $from
*/
public function setFrom(Position $from){
@ -58,7 +59,7 @@ class EntityTeleportEvent extends EntityEvent implements Cancellable{
/**
* @return Position
*/
public function getTo(){
public function getTo() : Position{
return $this->to;
}

View File

@ -32,14 +32,16 @@ use pocketmine\event\Cancellable;
class ExplosionPrimeEvent extends EntityEvent implements Cancellable{
public static $handlerList = null;
/** @var float */
protected $force;
/** @var bool */
private $blockBreaking;
/**
* @param Entity $entity
* @param float $force
*/
public function __construct(Entity $entity, $force){
public function __construct(Entity $entity, float $force){
$this->entity = $entity;
$this->force = $force;
$this->blockBreaking = true;
@ -48,26 +50,26 @@ class ExplosionPrimeEvent extends EntityEvent implements Cancellable{
/**
* @return float
*/
public function getForce(){
public function getForce() : float{
return $this->force;
}
public function setForce($force){
$this->force = (float) $force;
public function setForce(float $force){
$this->force = $force;
}
/**
* @return bool
*/
public function isBlockBreaking(){
public function isBlockBreaking() : bool{
return $this->blockBreaking;
}
/**
* @param bool $affectsBlocks
*/
public function setBlockBreaking($affectsBlocks){
$this->blockBreaking = (bool) $affectsBlocks;
public function setBlockBreaking(bool $affectsBlocks){
$this->blockBreaking = $affectsBlocks;
}
}

View File

@ -27,6 +27,7 @@ use pocketmine\block\Air;
use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
use pocketmine\block\Liquid;
use pocketmine\event\player\PlayerBucketEmptyEvent;
use pocketmine\event\player\PlayerBucketFillEvent;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
@ -70,7 +71,7 @@ class Bucket extends Item{
}elseif($targetBlock instanceof Liquid){
$result = clone $this;
$result->setDamage(0);
$player->getServer()->getPluginManager()->callEvent($ev = new PlayerBucketFillEvent($player, $block, $face, $this, $result));
$player->getServer()->getPluginManager()->callEvent($ev = new PlayerBucketEmptyEvent($player, $block, $face, $this, $result));
if(!$ev->isCancelled()){
$player->getLevel()->setBlock($block, $targetBlock, true, true);
if($player->isSurvival()){

View File

@ -202,7 +202,7 @@ class Item implements ItemIds, \JsonSerializable{
$this->id = $id & 0xffff;
$this->meta = $meta !== -1 ? $meta & 0xffff : -1;
$this->name = $name;
if(!isset($this->block) and $this->id <= 0xff and isset(BlockFactory::$list[$this->id])){
if(!isset($this->block) and $this->id <= 0xff){
$this->block = BlockFactory::get($this->id, $this->meta);
$this->name = $this->block->getName();
}

View File

@ -32,7 +32,7 @@ use pocketmine\nbt\tag\CompoundTag;
class ItemFactory{
/** @var \SplFixedArray */
public static $list = null;
private static $list = null;
public static function init(){
if(self::$list === null){

@ -1 +1 @@
Subproject commit 513b153f7081f0060b64723e640d7c87d0b69e6c
Subproject commit c37468585286514a9e5a47f696e534789af26359

View File

@ -270,7 +270,7 @@ class Level implements ChunkManager, Metadatable{
* @throws \Exception
*/
public function __construct(Server $server, string $name, string $path, string $provider){
$this->blockStates = BlockFactory::$fullList;
$this->blockStates = BlockFactory::getBlockStatesArray();
$this->levelId = static::$levelIdCounter++;
$this->blockMetadata = new BlockMetadataStore($this);
$this->server = $server;
@ -302,19 +302,12 @@ class Level implements ChunkManager, Metadatable{
$this->clearChunksOnTick = (bool) $this->server->getProperty("chunk-ticking.clear-tick-list", true);
$this->cacheChunks = (bool) $this->server->getProperty("chunk-sending.cache-chunks", false);
$this->randomTickBlocks = \SplFixedArray::fromArray(array_filter(BlockFactory::$list->toArray(), function(Block $block = null){
return $block !== null and $block->ticksRandomly();
}));
$this->randomTickBlocks->setSize(256);
$dontTickBlocks = $this->server->getProperty("chunk-ticking.disable-block-ticking", []);
foreach($dontTickBlocks as $id){
try{
if(isset($this->randomTickBlocks[$id])){
$this->randomTickBlocks[$id] = null;
}
}catch(\RuntimeException $e){
//index out of bounds
$this->randomTickBlocks = new \SplFixedArray(256);
foreach($this->randomTickBlocks as $id => $null){
$block = BlockFactory::get($id); //Make sure it's a copy
if(!isset($dontTickBlocks[$id]) and $block->ticksRandomly()){
$this->randomTickBlocks[$id] = $block;
}
}
@ -839,21 +832,15 @@ class Level implements ChunkManager, Metadatable{
$this->server->batchPackets($target, $packets, false, false);
}
public function clearCache(bool $full = false){
if($full){
public function clearCache(bool $force = false){
if($force){
$this->chunkCache = [];
$this->blockCache = [];
}else{
if(count($this->chunkCache) > 768){
$this->chunkCache = [];
}
if(count($this->blockCache) > 2048){
$this->blockCache = [];
}
}
}
public function clearChunkCache(int $chunkX, int $chunkZ){
@ -950,7 +937,7 @@ class Level implements ChunkManager, Metadatable{
*
* @return bool
*/
public function save(bool $force = false){
public function save(bool $force = false) : bool{
if(!$this->getAutoSave() and !$force){
return false;

View File

@ -634,7 +634,7 @@ class Chunk{
* @param Tile $tile
*/
public function addTile(Tile $tile){
if($tile->closed){
if($tile->isClosed()){
throw new \InvalidArgumentException("Attempted to add a garbage closed Tile to a chunk");
}
$this->tiles[$tile->getId()] = $tile;

View File

@ -23,84 +23,86 @@ declare(strict_types=1);
namespace pocketmine\level\format\io;
class ChunkUtils{
if(!extension_loaded('pocketmine_chunkutils')){
class ChunkUtils{
/**
* Re-orders a byte array (YZX -> XZY and vice versa)
*
* @param string $array length 4096
*
* @return string length 4096
*/
final public static function reorderByteArray(string $array) : string{
$result = str_repeat("\x00", 4096);
if($array !== $result){
$i = 0;
for($x = 0; $x < 16; ++$x){
$zM = $x + 256;
for($z = $x; $z < $zM; $z += 16){
$yM = $z + 4096;
for($y = $z; $y < $yM; $y += 256){
$result{$i} = $array{$y};
++$i;
}
}
}
}
return $result;
}
/**
* Re-orders a nibble array (YZX -> XZY and vice versa)
*
* @param string $array length 2048
* @param string $commonValue length 1 common value to fill the default array with and to expect, may improve sort time
*
* @return string length 2048
*/
final public static function reorderNibbleArray(string $array, string $commonValue = "\x00") : string{
$result = str_repeat($commonValue, 2048);
if($array !== $result){
$i = 0;
for($x = 0; $x < 8; ++$x){
for($z = 0; $z < 16; ++$z){
$zx = (($z << 3) | $x);
for($y = 0; $y < 8; ++$y){
$j = (($y << 8) | $zx);
$j80 = ($j | 0x80);
if($array{$j} === $commonValue and $array{$j80} === $commonValue){
//values are already filled
}else{
$i1 = ord($array{$j});
$i2 = ord($array{$j80});
$result{$i} = chr(($i2 << 4) | ($i1 & 0x0f));
$result{$i | 0x80} = chr(($i1 >> 4) | ($i2 & 0xf0));
/**
* Re-orders a byte array (YZX -> XZY and vice versa)
*
* @param string $array length 4096
*
* @return string length 4096
*/
final public static function reorderByteArray(string $array) : string{
$result = str_repeat("\x00", 4096);
if($array !== $result){
$i = 0;
for($x = 0; $x < 16; ++$x){
$zM = $x + 256;
for($z = $x; $z < $zM; $z += 16){
$yM = $z + 4096;
for($y = $z; $y < $yM; $y += 256){
$result{$i} = $array{$y};
++$i;
}
$i++;
}
}
$i += 128;
}
return $result;
}
return $result;
}
/**
* Re-orders a nibble array (YZX -> XZY and vice versa)
*
* @param string $array length 2048
* @param string $commonValue length 1 common value to fill the default array with and to expect, may improve sort time
*
* @return string length 2048
*/
final public static function reorderNibbleArray(string $array, string $commonValue = "\x00") : string{
$result = str_repeat($commonValue, 2048);
/**
* Converts pre-MCPE-1.0 biome color array to biome ID array.
*
* @param int[] $array of biome color values
*
* @return string
*/
public static function convertBiomeColors(array $array) : string{
$result = str_repeat("\x00", 256);
foreach($array as $i => $color){
$result{$i} = chr(($color >> 24) & 0xff);
if($array !== $result){
$i = 0;
for($x = 0; $x < 8; ++$x){
for($z = 0; $z < 16; ++$z){
$zx = (($z << 3) | $x);
for($y = 0; $y < 8; ++$y){
$j = (($y << 8) | $zx);
$j80 = ($j | 0x80);
if($array{$j} === $commonValue and $array{$j80} === $commonValue){
//values are already filled
}else{
$i1 = ord($array{$j});
$i2 = ord($array{$j80});
$result{$i} = chr(($i2 << 4) | ($i1 & 0x0f));
$result{$i | 0x80} = chr(($i1 >> 4) | ($i2 & 0xf0));
}
$i++;
}
}
$i += 128;
}
}
return $result;
}
return $result;
}
/**
* Converts pre-MCPE-1.0 biome color array to biome ID array.
*
* @param int[] $array of biome color values
*
* @return string
*/
public static function convertBiomeColors(array $array) : string{
$result = str_repeat("\x00", 256);
foreach($array as $i => $color){
$result{$i} = chr(($color >> 24) & 0xff);
}
return $result;
}
}
}

View File

@ -38,6 +38,7 @@ use pocketmine\nbt\tag\{
ByteTag, CompoundTag, FloatTag, IntTag, LongTag, StringTag
};
use pocketmine\network\mcpe\protocol\ProtocolInfo;
use pocketmine\Player;
use pocketmine\tile\Tile;
use pocketmine\utils\Binary;
use pocketmine\utils\BinaryStream;
@ -501,7 +502,9 @@ class LevelDB extends BaseLevelProvider{
$this->db->put($index . self::TAG_STATE_FINALISATION, chr(self::FINALISATION_DONE));
$this->writeTags($chunk->getTiles(), $index . self::TAG_BLOCK_ENTITY);
$this->writeTags($chunk->getEntities(), $index . self::TAG_ENTITY);
$this->writeTags(array_filter($chunk->getEntities(), function(Entity $entity) : bool{
return !($entity instanceof Player);
}), $index . self::TAG_ENTITY);
$this->db->delete($index . self::TAG_DATA_2D_LEGACY);
$this->db->delete($index . self::TAG_LEGACY_TERRAIN);
@ -514,8 +517,9 @@ class LevelDB extends BaseLevelProvider{
private function writeTags(array $targets, string $index){
$nbt = new NBT(NBT::LITTLE_ENDIAN);
$out = [];
/** @var Entity|Tile $target */
foreach($targets as $target){
if(!$target->closed){
if(!$target->isClosed()){
$target->saveNBT();
$out[] = $target->namedtag;
}

View File

@ -133,6 +133,8 @@ class RakLibInterface implements ServerInstance, AdvancedSourceInterface{
public function handleEncapsulated($identifier, EncapsulatedPacket $packet, $flags){
if(isset($this->players[$identifier])){
//get this now for blocking in case the player was closed before the exception was raised
$address = $this->players[$identifier]->getAddress();
try{
if($packet->buffer !== ""){
$pk = $this->getPacket($packet->buffer);
@ -143,7 +145,7 @@ class RakLibInterface implements ServerInstance, AdvancedSourceInterface{
$logger->debug("Packet " . (isset($pk) ? get_class($pk) : "unknown") . " 0x" . bin2hex($packet->buffer));
$logger->logException($e);
$this->interface->blockAddress($this->players[$identifier]->getAddress(), 5);
$this->interface->blockAddress($address, 5);
}
}
}

View File

@ -34,11 +34,11 @@ class PlaySoundPacket extends DataPacket{
/** @var string */
public $soundName;
/** @var int */
/** @var float */
public $x;
/** @var int */
/** @var float */
public $y;
/** @var int */
/** @var float */
public $z;
/** @var float */
public $volume;
@ -48,13 +48,16 @@ class PlaySoundPacket extends DataPacket{
protected function decodePayload(){
$this->soundName = $this->getString();
$this->getBlockPosition($this->x, $this->y, $this->z);
$this->x /= 8;
$this->y /= 8;
$this->z /= 8;
$this->volume = $this->getLFloat();
$this->pitch = $this->getLFloat();
}
protected function encodePayload(){
$this->putString($this->soundName);
$this->putBlockPosition($this->x, $this->y, $this->z);
$this->putBlockPosition((int) ($this->x * 8), (int) ($this->y * 8), (int) ($this->z * 8));
$this->putLFloat($this->volume);
$this->putLFloat($this->pitch);
}

View File

@ -23,12 +23,15 @@ declare(strict_types=1);
namespace pocketmine\plugin;
use pocketmine\network\mcpe\protocol\ProtocolInfo;
use pocketmine\permission\Permission;
class PluginDescription{
private $name;
private $main;
private $api;
/** @var int[] */
private $compatibleMcpeProtocols = [];
private $extensions = [];
private $depend = [];
private $softDepend = [];
@ -71,11 +74,13 @@ class PluginDescription{
$this->name = str_replace(" ", "_", $this->name);
$this->version = (string) $plugin["version"];
$this->main = $plugin["main"];
$this->api = array_map(function($v){ return (string) $v; }, !is_array($plugin["api"]) ? [$plugin["api"]] : $plugin["api"]);
if(stripos($this->main, "pocketmine\\") === 0){
throw new PluginException("Invalid PluginDescription main, cannot start within the PocketMine namespace");
}
$this->api = array_map("strval", (array) $plugin["api"] ?? []);
$this->compatibleMcpeProtocols = array_map("intval", (array) ($plugin["mcpe-protocol"] ?? []));
if(isset($plugin["commands"]) and is_array($plugin["commands"])){
$this->commands = $plugin["commands"];
}
@ -94,22 +99,17 @@ class PluginDescription{
$this->extensions[$k] = is_array($v) ? $v : [$v];
}
}
if(isset($plugin["softdepend"])){
$this->softDepend = (array) $plugin["softdepend"];
}
if(isset($plugin["loadbefore"])){
$this->loadBefore = (array) $plugin["loadbefore"];
}
if(isset($plugin["website"])){
$this->website = $plugin["website"];
}
if(isset($plugin["description"])){
$this->description = $plugin["description"];
}
if(isset($plugin["prefix"])){
$this->prefix = $plugin["prefix"];
}
$this->softDepend = (array) ($plugin["softdepend"] ?? $this->softDepend);
$this->loadBefore = (array) ($plugin["loadbefore"] ?? $this->loadBefore);
$this->website = (string) ($plugin["website"] ?? $this->website);
$this->description = (string) ($plugin["description"] ?? $this->description);
$this->prefix = (string) ($plugin["prefix"] ?? $this->prefix);
if(isset($plugin["load"])){
$order = strtoupper($plugin["load"]);
if(!defined(PluginLoadOrder::class . "::" . $order)){
@ -147,6 +147,13 @@ class PluginDescription{
return $this->api;
}
/**
* @return int[]
*/
public function getCompatibleMcpeProtocols() : array{
return $this->compatibleMcpeProtocols;
}
/**
* @return string[]
*/

View File

@ -32,6 +32,7 @@ use pocketmine\event\HandlerList;
use pocketmine\event\Listener;
use pocketmine\event\Timings;
use pocketmine\event\TimingsHandler;
use pocketmine\network\mcpe\protocol\ProtocolInfo;
use pocketmine\permission\Permissible;
use pocketmine\permission\Permission;
use pocketmine\Server;
@ -237,7 +238,7 @@ class PluginManager{
continue;
}
$pluginNumbers = array_map("intval", explode(".", $pluginApi[0]));
$pluginNumbers = array_map("intval", array_pad(explode(".", $pluginApi[0]), 3, "0")); //plugins might specify API like "3.0" or "3"
$serverNumbers = array_map("intval", explode(".", $serverApi[0]));
if($pluginNumbers[0] !== $serverNumbers[0]){ //Completely different API version
@ -254,10 +255,24 @@ class PluginManager{
}
if($compatible === false){
$this->server->getLogger()->error($this->server->getLanguage()->translateString("pocketmine.plugin.loadError", [$name, "%pocketmine.plugin.incompatibleAPI"]));
$this->server->getLogger()->error($this->server->getLanguage()->translateString("pocketmine.plugin.loadError", [
$name,
$this->server->getLanguage()->translateString("%pocketmine.plugin.incompatibleAPI", [implode(", ", $description->getCompatibleApis())])
]));
continue;
}
if(count($pluginMcpeProtocols = $description->getCompatibleMcpeProtocols()) > 0){
$serverMcpeProtocols = [ProtocolInfo::CURRENT_PROTOCOL];
if(count(array_intersect($pluginMcpeProtocols, $serverMcpeProtocols)) === 0){
$this->server->getLogger()->error($this->server->getLanguage()->translateString("pocketmine.plugin.loadError", [
$name,
$this->server->getLanguage()->translateString("%pocketmine.plugin.incompatibleProtocol", [implode(", ", $pluginMcpeProtocols)])
]));
continue;
}
}
$plugins[$name] = $file;
$softDependencies[$name] = $description->getSoftDepend();
@ -287,7 +302,10 @@ class PluginManager{
if(isset($loadedPlugins[$dependency]) or $this->getPlugin($dependency) instanceof Plugin){
unset($dependencies[$name][$key]);
}elseif(!isset($plugins[$dependency])){
$this->server->getLogger()->critical($this->server->getLanguage()->translateString("pocketmine.plugin.loadError", [$name, "%pocketmine.plugin.unknownDependency"]));
$this->server->getLogger()->critical($this->server->getLanguage()->translateString("pocketmine.plugin.loadError", [
$name,
$this->server->getLanguage()->translateString("%pocketmine.plugin.unknownDependency", [$dependency])
]));
break;
}
}

View File

@ -92,9 +92,9 @@ class AsyncPool{
$this->taskWorkers[$task->getTaskId()] = $worker;
}
public function submitTask(AsyncTask $task){
public function submitTask(AsyncTask $task) : int{
if(isset($this->tasks[$task->getTaskId()]) or $task->isGarbage()){
return;
return -1;
}
$selectedWorker = mt_rand(0, $this->size - 1);
@ -107,6 +107,7 @@ class AsyncPool{
}
$this->submitTaskToWorker($task, $selectedWorker);
return $selectedWorker;
}
private function removeTask(AsyncTask $task, bool $force = false){

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
/**
* Task scheduling related classes
*/
namespace pocketmine\scheduler;
use pocketmine\plugin\Plugin;
@ -75,16 +76,16 @@ class ServerScheduler{
*
* @param AsyncTask $task
*
* @return void
* @return int
*/
public function scheduleAsyncTask(AsyncTask $task){
public function scheduleAsyncTask(AsyncTask $task) : int{
if($task->getTaskId() !== null){
throw new \UnexpectedValueException("Attempt to schedule the same AsyncTask instance twice");
}
$id = $this->nextId();
$task->setTaskId($id);
$task->progressUpdates = new \Threaded;
$this->asyncPool->submitTask($task);
return $this->asyncPool->submitTask($task);
}
/**

View File

@ -64,8 +64,31 @@ class Sign extends Spawnable{
unset($this->namedtag->Creator);
}
/**
* Changes contents of the specific lines to the string provided.
* Leaves contents of the specifc lines as is if null is provided.
*
* @param null|string $line1
* @param null|string $line2
* @param null|string $line3
* @param null|string $line4
*
* @return bool
*/
public function setText($line1 = "", $line2 = "", $line3 = "", $line4 = ""){
$this->text = [$line1, $line2, $line3, $line4];
if($line1 !== null){
$this->text[0] = $line1;
}
if($line2 !== null){
$this->text[1] = $line2;
}
if($line3 !== null){
$this->text[2] = $line3;
}
if($line4 !== null){
$this->text[3] = $line4;
}
$this->onChanged();
}

View File

@ -180,6 +180,10 @@ abstract class Tile extends Position{
$this->level->updateTiles[$this->id] = $this;
}
public function isClosed() : bool{
return $this->closed;
}
public function __destruct(){
$this->close();
}

@ -1 +1 @@
Subproject commit 1fee79e4aac0f958ab720606e223b0aa690f5c47
Subproject commit 75b213db26755f67726784e0d5a36608158168cd