mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-05-11 00:09:39 +00:00
mostly rewrite internal entity metadata handling
- Only sync the metadata set when needed for sending - Don't use metadata set for storing data, add properties instead - Use objects inside metadata sets instead of arrays
This commit is contained in:
parent
6c0ae6bf0b
commit
e06ab0869a
@ -27,8 +27,15 @@ namespace pocketmine\entity;
|
|||||||
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataFlags;
|
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataFlags;
|
||||||
|
|
||||||
abstract class Animal extends Living implements Ageable{
|
abstract class Animal extends Living implements Ageable{
|
||||||
|
/** @var bool */
|
||||||
|
protected $baby = false;
|
||||||
|
|
||||||
public function isBaby() : bool{
|
public function isBaby() : bool{
|
||||||
return $this->getGenericFlag(EntityMetadataFlags::BABY);
|
return $this->baby;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function syncNetworkData() : void{
|
||||||
|
parent::syncNetworkData();
|
||||||
|
$this->propertyManager->setGenericFlag(EntityMetadataFlags::BABY, $this->baby);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ use pocketmine\network\mcpe\protocol\SetActorMotionPacket;
|
|||||||
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataCollection;
|
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataCollection;
|
||||||
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataFlags;
|
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataFlags;
|
||||||
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataProperties;
|
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataProperties;
|
||||||
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataTypes;
|
use pocketmine\network\mcpe\protocol\types\entity\MetadataProperty;
|
||||||
use pocketmine\player\Player;
|
use pocketmine\player\Player;
|
||||||
use pocketmine\Server;
|
use pocketmine\Server;
|
||||||
use pocketmine\timings\Timings;
|
use pocketmine\timings\Timings;
|
||||||
@ -195,6 +195,35 @@ abstract class Entity extends Location{
|
|||||||
/** @var TimingsHandler */
|
/** @var TimingsHandler */
|
||||||
protected $timings;
|
protected $timings;
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
protected $nameTag = "";
|
||||||
|
/** @var bool */
|
||||||
|
protected $nameTagVisible = true;
|
||||||
|
/** @var bool */
|
||||||
|
protected $alwaysShowNameTag = false;
|
||||||
|
/** @var string */
|
||||||
|
protected $scoreTag = "";
|
||||||
|
/** @var float */
|
||||||
|
protected $scale = 1.0;
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
protected $canClimb = false;
|
||||||
|
/** @var bool */
|
||||||
|
protected $canClimbWalls = false;
|
||||||
|
/** @var bool */
|
||||||
|
protected $immobile = false;
|
||||||
|
/** @var bool */
|
||||||
|
protected $invisible = false;
|
||||||
|
/** @var bool */
|
||||||
|
protected $sneaking = false;
|
||||||
|
/** @var bool */
|
||||||
|
protected $sprinting = false;
|
||||||
|
|
||||||
|
/** @var int|null */
|
||||||
|
protected $ownerId = null;
|
||||||
|
/** @var int|null */
|
||||||
|
protected $targetId = null;
|
||||||
|
|
||||||
public function __construct(World $world, CompoundTag $nbt){
|
public function __construct(World $world, CompoundTag $nbt){
|
||||||
$this->timings = Timings::getEntityTimings($this);
|
$this->timings = Timings::getEntityTimings($this);
|
||||||
|
|
||||||
@ -234,22 +263,10 @@ abstract class Entity extends Location{
|
|||||||
|
|
||||||
$this->propertyManager = new EntityMetadataCollection();
|
$this->propertyManager = new EntityMetadataCollection();
|
||||||
|
|
||||||
$this->propertyManager->setLong(EntityMetadataProperties::FLAGS, 0);
|
|
||||||
$this->propertyManager->setShort(EntityMetadataProperties::MAX_AIR, 400);
|
|
||||||
$this->propertyManager->setString(EntityMetadataProperties::NAMETAG, "");
|
|
||||||
$this->propertyManager->setLong(EntityMetadataProperties::LEAD_HOLDER_EID, -1);
|
|
||||||
$this->propertyManager->setFloat(EntityMetadataProperties::SCALE, 1);
|
|
||||||
$this->propertyManager->setFloat(EntityMetadataProperties::BOUNDING_BOX_WIDTH, $this->width);
|
|
||||||
$this->propertyManager->setFloat(EntityMetadataProperties::BOUNDING_BOX_HEIGHT, $this->height);
|
|
||||||
|
|
||||||
$this->attributeMap = new AttributeMap();
|
$this->attributeMap = new AttributeMap();
|
||||||
$this->addAttributes();
|
$this->addAttributes();
|
||||||
|
|
||||||
$this->setGenericFlag(EntityMetadataFlags::AFFECTED_BY_GRAVITY, true);
|
|
||||||
$this->setGenericFlag(EntityMetadataFlags::HAS_COLLISION, true);
|
|
||||||
|
|
||||||
$this->initEntity($nbt);
|
$this->initEntity($nbt);
|
||||||
$this->propertyManager->clearDirtyProperties(); //Prevents resending properties that were set during construction
|
|
||||||
|
|
||||||
$this->chunk->addEntity($this);
|
$this->chunk->addEntity($this);
|
||||||
$this->world->addEntity($this);
|
$this->world->addEntity($this);
|
||||||
@ -265,64 +282,63 @@ abstract class Entity extends Location{
|
|||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getNameTag() : string{
|
public function getNameTag() : string{
|
||||||
return $this->propertyManager->getString(EntityMetadataProperties::NAMETAG);
|
return $this->nameTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function isNameTagVisible() : bool{
|
public function isNameTagVisible() : bool{
|
||||||
return $this->getGenericFlag(EntityMetadataFlags::CAN_SHOW_NAMETAG);
|
return $this->nameTagVisible;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function isNameTagAlwaysVisible() : bool{
|
public function isNameTagAlwaysVisible() : bool{
|
||||||
return $this->propertyManager->getByte(EntityMetadataProperties::ALWAYS_SHOW_NAMETAG) === 1;
|
return $this->alwaysShowNameTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $name
|
* @param string $name
|
||||||
*/
|
*/
|
||||||
public function setNameTag(string $name) : void{
|
public function setNameTag(string $name) : void{
|
||||||
$this->propertyManager->setString(EntityMetadataProperties::NAMETAG, $name);
|
$this->nameTag = $name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param bool $value
|
* @param bool $value
|
||||||
*/
|
*/
|
||||||
public function setNameTagVisible(bool $value = true) : void{
|
public function setNameTagVisible(bool $value = true) : void{
|
||||||
$this->setGenericFlag(EntityMetadataFlags::CAN_SHOW_NAMETAG, $value);
|
$this->nameTagVisible = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param bool $value
|
* @param bool $value
|
||||||
*/
|
*/
|
||||||
public function setNameTagAlwaysVisible(bool $value = true) : void{
|
public function setNameTagAlwaysVisible(bool $value = true) : void{
|
||||||
$this->propertyManager->setByte(EntityMetadataProperties::ALWAYS_SHOW_NAMETAG, $value ? 1 : 0);
|
$this->alwaysShowNameTag = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string|null
|
* @return string|null
|
||||||
*/
|
*/
|
||||||
public function getScoreTag() : ?string{
|
public function getScoreTag() : ?string{
|
||||||
return $this->propertyManager->getString(EntityMetadataProperties::SCORE_TAG);
|
return $this->scoreTag; //TODO: maybe this shouldn't be nullable?
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $score
|
* @param string $score
|
||||||
*/
|
*/
|
||||||
public function setScoreTag(string $score) : void{
|
public function setScoreTag(string $score) : void{
|
||||||
$this->propertyManager->setString(EntityMetadataProperties::SCORE_TAG, $score);
|
$this->scoreTag = $score;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return float
|
* @return float
|
||||||
*/
|
*/
|
||||||
public function getScale() : float{
|
public function getScale() : float{
|
||||||
return $this->propertyManager->getFloat(EntityMetadataProperties::SCALE);
|
return $this->scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -338,9 +354,9 @@ abstract class Entity extends Location{
|
|||||||
$this->height *= $multiplier;
|
$this->height *= $multiplier;
|
||||||
$this->eyeHeight *= $multiplier;
|
$this->eyeHeight *= $multiplier;
|
||||||
|
|
||||||
$this->recalculateBoundingBox();
|
$this->scale = $value;
|
||||||
|
|
||||||
$this->propertyManager->setFloat(EntityMetadataProperties::SCALE, $value);
|
$this->recalculateBoundingBox();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getBoundingBox() : AxisAlignedBB{
|
public function getBoundingBox() : AxisAlignedBB{
|
||||||
@ -361,39 +377,39 @@ abstract class Entity extends Location{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function isSneaking() : bool{
|
public function isSneaking() : bool{
|
||||||
return $this->getGenericFlag(EntityMetadataFlags::SNEAKING);
|
return $this->sneaking;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setSneaking(bool $value = true) : void{
|
public function setSneaking(bool $value = true) : void{
|
||||||
$this->setGenericFlag(EntityMetadataFlags::SNEAKING, $value);
|
$this->sneaking = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isSprinting() : bool{
|
public function isSprinting() : bool{
|
||||||
return $this->getGenericFlag(EntityMetadataFlags::SPRINTING);
|
return $this->sprinting;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setSprinting(bool $value = true) : void{
|
public function setSprinting(bool $value = true) : void{
|
||||||
if($value !== $this->isSprinting()){
|
if($value !== $this->isSprinting()){
|
||||||
$this->setGenericFlag(EntityMetadataFlags::SPRINTING, $value);
|
$this->sprinting = $value;
|
||||||
$attr = $this->attributeMap->getAttribute(Attribute::MOVEMENT_SPEED);
|
$attr = $this->attributeMap->getAttribute(Attribute::MOVEMENT_SPEED);
|
||||||
$attr->setValue($value ? ($attr->getValue() * 1.3) : ($attr->getValue() / 1.3), false, true);
|
$attr->setValue($value ? ($attr->getValue() * 1.3) : ($attr->getValue() / 1.3), false, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isImmobile() : bool{
|
public function isImmobile() : bool{
|
||||||
return $this->getGenericFlag(EntityMetadataFlags::IMMOBILE);
|
return $this->immobile;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setImmobile(bool $value = true) : void{
|
public function setImmobile(bool $value = true) : void{
|
||||||
$this->setGenericFlag(EntityMetadataFlags::IMMOBILE, $value);
|
$this->immobile = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isInvisible() : bool{
|
public function isInvisible() : bool{
|
||||||
return $this->getGenericFlag(EntityMetadataFlags::INVISIBLE);
|
return $this->invisible;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setInvisible(bool $value = true) : void{
|
public function setInvisible(bool $value = true) : void{
|
||||||
$this->setGenericFlag(EntityMetadataFlags::INVISIBLE, $value);
|
$this->invisible = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -401,7 +417,7 @@ abstract class Entity extends Location{
|
|||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function canClimb() : bool{
|
public function canClimb() : bool{
|
||||||
return $this->getGenericFlag(EntityMetadataFlags::CAN_CLIMB);
|
return $this->canClimb;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -410,7 +426,7 @@ abstract class Entity extends Location{
|
|||||||
* @param bool $value
|
* @param bool $value
|
||||||
*/
|
*/
|
||||||
public function setCanClimb(bool $value = true) : void{
|
public function setCanClimb(bool $value = true) : void{
|
||||||
$this->setGenericFlag(EntityMetadataFlags::CAN_CLIMB, $value);
|
$this->canClimb = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -419,7 +435,7 @@ abstract class Entity extends Location{
|
|||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function canClimbWalls() : bool{
|
public function canClimbWalls() : bool{
|
||||||
return $this->getGenericFlag(EntityMetadataFlags::WALLCLIMBING);
|
return $this->canClimbWalls;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -428,7 +444,7 @@ abstract class Entity extends Location{
|
|||||||
* @param bool $value
|
* @param bool $value
|
||||||
*/
|
*/
|
||||||
public function setCanClimbWalls(bool $value = true) : void{
|
public function setCanClimbWalls(bool $value = true) : void{
|
||||||
$this->setGenericFlag(EntityMetadataFlags::WALLCLIMBING, $value);
|
$this->canClimbWalls = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -436,7 +452,7 @@ abstract class Entity extends Location{
|
|||||||
* @return int|null
|
* @return int|null
|
||||||
*/
|
*/
|
||||||
public function getOwningEntityId() : ?int{
|
public function getOwningEntityId() : ?int{
|
||||||
return $this->propertyManager->getLong(EntityMetadataProperties::OWNER_EID);
|
return $this->ownerId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -444,12 +460,7 @@ abstract class Entity extends Location{
|
|||||||
* @return Entity|null
|
* @return Entity|null
|
||||||
*/
|
*/
|
||||||
public function getOwningEntity() : ?Entity{
|
public function getOwningEntity() : ?Entity{
|
||||||
$eid = $this->getOwningEntityId();
|
return $this->ownerId !== null ? $this->server->getWorldManager()->findEntity($this->ownerId) : null;
|
||||||
if($eid !== null){
|
|
||||||
return $this->server->getWorldManager()->findEntity($eid);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -461,11 +472,11 @@ abstract class Entity extends Location{
|
|||||||
*/
|
*/
|
||||||
public function setOwningEntity(?Entity $owner) : void{
|
public function setOwningEntity(?Entity $owner) : void{
|
||||||
if($owner === null){
|
if($owner === null){
|
||||||
$this->propertyManager->removeProperty(EntityMetadataProperties::OWNER_EID);
|
$this->ownerId = null;
|
||||||
}elseif($owner->closed){
|
}elseif($owner->closed){
|
||||||
throw new \InvalidArgumentException("Supplied owning entity is garbage and cannot be used");
|
throw new \InvalidArgumentException("Supplied owning entity is garbage and cannot be used");
|
||||||
}else{
|
}else{
|
||||||
$this->propertyManager->setLong(EntityMetadataProperties::OWNER_EID, $owner->getId());
|
$this->ownerId = $owner->getId();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -474,7 +485,7 @@ abstract class Entity extends Location{
|
|||||||
* @return int|null
|
* @return int|null
|
||||||
*/
|
*/
|
||||||
public function getTargetEntityId() : ?int{
|
public function getTargetEntityId() : ?int{
|
||||||
return $this->propertyManager->getLong(EntityMetadataProperties::TARGET_EID);
|
return $this->targetId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -484,12 +495,7 @@ abstract class Entity extends Location{
|
|||||||
* @return Entity|null
|
* @return Entity|null
|
||||||
*/
|
*/
|
||||||
public function getTargetEntity() : ?Entity{
|
public function getTargetEntity() : ?Entity{
|
||||||
$eid = $this->getTargetEntityId();
|
return $this->targetId !== null ? $this->server->getWorldManager()->findEntity($eid) : null;
|
||||||
if($eid !== null){
|
|
||||||
return $this->server->getWorldManager()->findEntity($eid);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -501,11 +507,11 @@ abstract class Entity extends Location{
|
|||||||
*/
|
*/
|
||||||
public function setTargetEntity(?Entity $target) : void{
|
public function setTargetEntity(?Entity $target) : void{
|
||||||
if($target === null){
|
if($target === null){
|
||||||
$this->propertyManager->removeProperty(EntityMetadataProperties::TARGET_EID);
|
$this->targetId = null;
|
||||||
}elseif($target->closed){
|
}elseif($target->closed){
|
||||||
throw new \InvalidArgumentException("Supplied target entity is garbage and cannot be used");
|
throw new \InvalidArgumentException("Supplied target entity is garbage and cannot be used");
|
||||||
}else{
|
}else{
|
||||||
$this->propertyManager->setLong(EntityMetadataProperties::TARGET_EID, $target->getId());
|
$this->targetId = $target->getId();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -557,7 +563,6 @@ abstract class Entity extends Location{
|
|||||||
|
|
||||||
$nbt->setFloat("FallDistance", $this->fallDistance);
|
$nbt->setFloat("FallDistance", $this->fallDistance);
|
||||||
$nbt->setShort("Fire", $this->fireTicks);
|
$nbt->setShort("Fire", $this->fireTicks);
|
||||||
$nbt->setShort("Air", $this->propertyManager->getShort(EntityMetadataProperties::AIR));
|
|
||||||
$nbt->setByte("OnGround", $this->onGround ? 1 : 0);
|
$nbt->setByte("OnGround", $this->onGround ? 1 : 0);
|
||||||
$nbt->setByte("Invulnerable", $this->invulnerable ? 1 : 0);
|
$nbt->setByte("Invulnerable", $this->invulnerable ? 1 : 0);
|
||||||
|
|
||||||
@ -566,11 +571,7 @@ abstract class Entity extends Location{
|
|||||||
|
|
||||||
protected function initEntity(CompoundTag $nbt) : void{
|
protected function initEntity(CompoundTag $nbt) : void{
|
||||||
$this->fireTicks = $nbt->getShort("Fire", 0);
|
$this->fireTicks = $nbt->getShort("Fire", 0);
|
||||||
if($this->isOnFire()){
|
|
||||||
$this->setGenericFlag(EntityMetadataFlags::ONFIRE);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->propertyManager->setShort(EntityMetadataProperties::AIR, $nbt->getShort("Air", 300));
|
|
||||||
$this->onGround = $nbt->getByte("OnGround", 0) !== 0;
|
$this->onGround = $nbt->getByte("OnGround", 0) !== 0;
|
||||||
$this->invulnerable = $nbt->getByte("Invulnerable", 0) !== 0;
|
$this->invulnerable = $nbt->getByte("Invulnerable", 0) !== 0;
|
||||||
|
|
||||||
@ -717,7 +718,7 @@ abstract class Entity extends Location{
|
|||||||
|
|
||||||
$this->justCreated = false;
|
$this->justCreated = false;
|
||||||
|
|
||||||
$changedProperties = $this->propertyManager->getDirty();
|
$changedProperties = $this->getSyncedNetworkData(true);
|
||||||
if(!empty($changedProperties)){
|
if(!empty($changedProperties)){
|
||||||
$this->sendData($this->hasSpawned, $changedProperties);
|
$this->sendData($this->hasSpawned, $changedProperties);
|
||||||
$this->propertyManager->clearDirtyProperties();
|
$this->propertyManager->clearDirtyProperties();
|
||||||
@ -758,8 +759,6 @@ abstract class Entity extends Location{
|
|||||||
if($ticks > $this->getFireTicks()){
|
if($ticks > $this->getFireTicks()){
|
||||||
$this->setFireTicks($ticks);
|
$this->setFireTicks($ticks);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->setGenericFlag(EntityMetadataFlags::ONFIRE, $this->isOnFire());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -782,7 +781,6 @@ abstract class Entity extends Location{
|
|||||||
|
|
||||||
public function extinguish() : void{
|
public function extinguish() : void{
|
||||||
$this->fireTicks = 0;
|
$this->fireTicks = 0;
|
||||||
$this->setGenericFlag(EntityMetadataFlags::ONFIRE, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isFireProof() : bool{
|
public function isFireProof() : bool{
|
||||||
@ -1601,7 +1599,7 @@ abstract class Entity extends Location{
|
|||||||
$pk->headYaw = $this->yaw; //TODO
|
$pk->headYaw = $this->yaw; //TODO
|
||||||
$pk->pitch = $this->pitch;
|
$pk->pitch = $this->pitch;
|
||||||
$pk->attributes = $this->attributeMap->getAll();
|
$pk->attributes = $this->attributeMap->getAll();
|
||||||
$pk->metadata = $this->propertyManager->getAll();
|
$pk->metadata = $this->getSyncedNetworkData(false);
|
||||||
|
|
||||||
$player->sendDataPacket($pk);
|
$player->sendDataPacket($pk);
|
||||||
}
|
}
|
||||||
@ -1716,60 +1714,15 @@ abstract class Entity extends Location{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $propertyId
|
* @param Player[]|Player $player
|
||||||
* @param int $flagId
|
* @param MetadataProperty[] $data Properly formatted entity data, defaults to everything
|
||||||
* @param bool $value
|
|
||||||
* @param int $propertyType
|
|
||||||
*/
|
|
||||||
public function setDataFlag(int $propertyId, int $flagId, bool $value = true, int $propertyType = EntityMetadataTypes::LONG) : void{
|
|
||||||
if($this->getDataFlag($propertyId, $flagId) !== $value){
|
|
||||||
$flags = (int) $this->propertyManager->getPropertyValue($propertyId, $propertyType);
|
|
||||||
$flags ^= 1 << $flagId;
|
|
||||||
$this->propertyManager->setPropertyValue($propertyId, $propertyType, $flags);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $propertyId
|
|
||||||
* @param int $flagId
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function getDataFlag(int $propertyId, int $flagId) : bool{
|
|
||||||
return (((int) $this->propertyManager->getPropertyValue($propertyId, -1)) & (1 << $flagId)) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrapper around {@link Entity#getDataFlag} for generic data flag reading.
|
|
||||||
*
|
|
||||||
* @param int $flagId
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function getGenericFlag(int $flagId) : bool{
|
|
||||||
return $this->getDataFlag($flagId >= 64 ? EntityMetadataProperties::FLAGS2 : EntityMetadataProperties::FLAGS, $flagId % 64);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrapper around {@link Entity#setDataFlag} for generic data flag setting.
|
|
||||||
*
|
|
||||||
* @param int $flagId
|
|
||||||
* @param bool $value
|
|
||||||
*/
|
|
||||||
public function setGenericFlag(int $flagId, bool $value = true) : void{
|
|
||||||
$this->setDataFlag($flagId >= 64 ? EntityMetadataProperties::FLAGS2 : EntityMetadataProperties::FLAGS, $flagId % 64, $value, EntityMetadataTypes::LONG);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Player[]|Player $player
|
|
||||||
* @param array $data Properly formatted entity data, defaults to everything
|
|
||||||
*/
|
*/
|
||||||
public function sendData($player, ?array $data = null) : void{
|
public function sendData($player, ?array $data = null) : void{
|
||||||
if(!is_array($player)){
|
if(!is_array($player)){
|
||||||
$player = [$player];
|
$player = [$player];
|
||||||
}
|
}
|
||||||
|
|
||||||
$pk = SetActorDataPacket::create($this->getId(), $data ?? $this->propertyManager->getAll());
|
$pk = SetActorDataPacket::create($this->getId(), $data ?? $this->getSyncedNetworkData(false));
|
||||||
|
|
||||||
foreach($player as $p){
|
foreach($player as $p){
|
||||||
if($p === $this){
|
if($p === $this){
|
||||||
@ -1783,6 +1736,39 @@ abstract class Entity extends Location{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $dirtyOnly
|
||||||
|
*
|
||||||
|
* @return MetadataProperty[]
|
||||||
|
*/
|
||||||
|
final protected function getSyncedNetworkData(bool $dirtyOnly) : array{
|
||||||
|
$this->syncNetworkData();
|
||||||
|
|
||||||
|
return $dirtyOnly ? $this->propertyManager->getDirty() : $this->propertyManager->getAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function syncNetworkData() : void{
|
||||||
|
$this->propertyManager->setByte(EntityMetadataProperties::ALWAYS_SHOW_NAMETAG, $this->alwaysShowNameTag ? 1 : 0);
|
||||||
|
$this->propertyManager->setFloat(EntityMetadataProperties::BOUNDING_BOX_HEIGHT, $this->height);
|
||||||
|
$this->propertyManager->setFloat(EntityMetadataProperties::BOUNDING_BOX_WIDTH, $this->width);
|
||||||
|
$this->propertyManager->setFloat(EntityMetadataProperties::SCALE, $this->scale);
|
||||||
|
$this->propertyManager->setLong(EntityMetadataProperties::LEAD_HOLDER_EID, -1);
|
||||||
|
$this->propertyManager->setLong(EntityMetadataProperties::OWNER_EID, $this->ownerId ?? -1);
|
||||||
|
$this->propertyManager->setLong(EntityMetadataProperties::TARGET_EID, $this->targetId ?? -1);
|
||||||
|
$this->propertyManager->setString(EntityMetadataProperties::NAMETAG, $this->nameTag);
|
||||||
|
$this->propertyManager->setString(EntityMetadataProperties::SCORE_TAG, $this->scoreTag);
|
||||||
|
|
||||||
|
$this->propertyManager->setGenericFlag(EntityMetadataFlags::AFFECTED_BY_GRAVITY, true);
|
||||||
|
$this->propertyManager->setGenericFlag(EntityMetadataFlags::CAN_CLIMB, $this->canClimb);
|
||||||
|
$this->propertyManager->setGenericFlag(EntityMetadataFlags::CAN_SHOW_NAMETAG, $this->nameTagVisible);
|
||||||
|
$this->propertyManager->setGenericFlag(EntityMetadataFlags::HAS_COLLISION, true);
|
||||||
|
$this->propertyManager->setGenericFlag(EntityMetadataFlags::IMMOBILE, $this->immobile);
|
||||||
|
$this->propertyManager->setGenericFlag(EntityMetadataFlags::INVISIBLE, $this->invisible);
|
||||||
|
$this->propertyManager->setGenericFlag(EntityMetadataFlags::ONFIRE, $this->isOnFire());
|
||||||
|
$this->propertyManager->setGenericFlag(EntityMetadataFlags::SNEAKING, $this->sneaking);
|
||||||
|
$this->propertyManager->setGenericFlag(EntityMetadataFlags::WALLCLIMBING, $this->canClimbWalls);
|
||||||
|
}
|
||||||
|
|
||||||
public function broadcastEntityEvent(int $eventId, ?int $eventData = null, ?array $players = null) : void{
|
public function broadcastEntityEvent(int $eventId, ?int $eventData = null, ?array $players = null) : void{
|
||||||
$this->server->broadcastPacket($players ?? $this->getViewers(), ActorEventPacket::create($this->id, $eventId, $eventData ?? 0));
|
$this->server->broadcastPacket($players ?? $this->getViewers(), ActorEventPacket::create($this->id, $eventId, $eventData ?? 0));
|
||||||
}
|
}
|
||||||
|
@ -46,8 +46,7 @@ use pocketmine\network\mcpe\protocol\AddPlayerPacket;
|
|||||||
use pocketmine\network\mcpe\protocol\PlayerListPacket;
|
use pocketmine\network\mcpe\protocol\PlayerListPacket;
|
||||||
use pocketmine\network\mcpe\protocol\PlayerSkinPacket;
|
use pocketmine\network\mcpe\protocol\PlayerSkinPacket;
|
||||||
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataProperties;
|
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataProperties;
|
||||||
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataTypes;
|
use pocketmine\network\mcpe\protocol\types\entity\StringMetadataProperty;
|
||||||
use pocketmine\network\mcpe\protocol\types\entity\PlayerMetadataFlags;
|
|
||||||
use pocketmine\network\mcpe\protocol\types\PlayerListEntry;
|
use pocketmine\network\mcpe\protocol\types\PlayerListEntry;
|
||||||
use pocketmine\player\Player;
|
use pocketmine\player\Player;
|
||||||
use pocketmine\utils\UUID;
|
use pocketmine\utils\UUID;
|
||||||
@ -228,9 +227,6 @@ class Human extends Living implements ProjectileSource, InventoryHolder{
|
|||||||
$this->hungerManager = new HungerManager($this);
|
$this->hungerManager = new HungerManager($this);
|
||||||
$this->xpManager = new ExperienceManager($this);
|
$this->xpManager = new ExperienceManager($this);
|
||||||
|
|
||||||
$this->setPlayerFlag(PlayerMetadataFlags::SLEEP, false);
|
|
||||||
$this->propertyManager->setBlockPos(EntityMetadataProperties::PLAYER_BED_POSITION, null);
|
|
||||||
|
|
||||||
$this->inventory = new PlayerInventory($this);
|
$this->inventory = new PlayerInventory($this);
|
||||||
$this->enderChestInventory = new EnderChestInventory();
|
$this->enderChestInventory = new EnderChestInventory();
|
||||||
$this->initHumanData($nbt);
|
$this->initHumanData($nbt);
|
||||||
@ -422,11 +418,11 @@ class Human extends Living implements ProjectileSource, InventoryHolder{
|
|||||||
$pk->yaw = $this->yaw;
|
$pk->yaw = $this->yaw;
|
||||||
$pk->pitch = $this->pitch;
|
$pk->pitch = $this->pitch;
|
||||||
$pk->item = $this->getInventory()->getItemInHand();
|
$pk->item = $this->getInventory()->getItemInHand();
|
||||||
$pk->metadata = $this->propertyManager->getAll();
|
$pk->metadata = $this->getSyncedNetworkData(false);
|
||||||
$player->sendDataPacket($pk);
|
$player->sendDataPacket($pk);
|
||||||
|
|
||||||
//TODO: Hack for MCPE 1.2.13: DATA_NAMETAG is useless in AddPlayerPacket, so it has to be sent separately
|
//TODO: Hack for MCPE 1.2.13: DATA_NAMETAG is useless in AddPlayerPacket, so it has to be sent separately
|
||||||
$this->sendData($player, [EntityMetadataProperties::NAMETAG => [EntityMetadataTypes::STRING, $this->getNameTag()]]);
|
$this->sendData($player, [EntityMetadataProperties::NAMETAG => new StringMetadataProperty($this->getNameTag())]);
|
||||||
|
|
||||||
$player->getNetworkSession()->onMobArmorChange($this);
|
$player->getNetworkSession()->onMobArmorChange($this);
|
||||||
|
|
||||||
@ -448,25 +444,4 @@ class Human extends Living implements ProjectileSource, InventoryHolder{
|
|||||||
$this->xpManager = null;
|
$this->xpManager = null;
|
||||||
parent::destroyCycles();
|
parent::destroyCycles();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrapper around {@link Entity#getDataFlag} for player-specific data flag reading.
|
|
||||||
*
|
|
||||||
* @param int $flagId
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function getPlayerFlag(int $flagId) : bool{
|
|
||||||
return $this->getDataFlag(EntityMetadataProperties::PLAYER_FLAGS, $flagId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrapper around {@link Entity#setDataFlag} for player-specific data flag setting.
|
|
||||||
*
|
|
||||||
* @param int $flagId
|
|
||||||
* @param bool $value
|
|
||||||
*/
|
|
||||||
public function setPlayerFlag(int $flagId, bool $value = true) : void{
|
|
||||||
$this->setDataFlag(EntityMetadataProperties::PLAYER_FLAGS, $flagId, $value, EntityMetadataTypes::BYTE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -66,6 +66,7 @@ use function sqrt;
|
|||||||
use const M_PI;
|
use const M_PI;
|
||||||
|
|
||||||
abstract class Living extends Entity{
|
abstract class Living extends Entity{
|
||||||
|
protected const DEFAULT_BREATH_TICKS = 300;
|
||||||
|
|
||||||
protected $gravity = 0.08;
|
protected $gravity = 0.08;
|
||||||
protected $drag = 0.02;
|
protected $drag = 0.02;
|
||||||
@ -85,6 +86,13 @@ abstract class Living extends Entity{
|
|||||||
/** @var ArmorInventory */
|
/** @var ArmorInventory */
|
||||||
protected $armorInventory;
|
protected $armorInventory;
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
protected $breathing = true;
|
||||||
|
/** @var int */
|
||||||
|
protected $breathTicks = self::DEFAULT_BREATH_TICKS;
|
||||||
|
/** @var int */
|
||||||
|
protected $maxBreathTicks = self::DEFAULT_BREATH_TICKS;
|
||||||
|
|
||||||
abstract public function getName() : string;
|
abstract public function getName() : string;
|
||||||
|
|
||||||
protected function initEntity(CompoundTag $nbt) : void{
|
protected function initEntity(CompoundTag $nbt) : void{
|
||||||
@ -114,6 +122,8 @@ abstract class Living extends Entity{
|
|||||||
|
|
||||||
$this->setHealth($health);
|
$this->setHealth($health);
|
||||||
|
|
||||||
|
$this->setAirSupplyTicks($nbt->getShort("Air", self::DEFAULT_BREATH_TICKS));
|
||||||
|
|
||||||
/** @var CompoundTag[]|ListTag $activeEffectsTag */
|
/** @var CompoundTag[]|ListTag $activeEffectsTag */
|
||||||
$activeEffectsTag = $nbt->getListTag("ActiveEffects");
|
$activeEffectsTag = $nbt->getListTag("ActiveEffects");
|
||||||
if($activeEffectsTag !== null){
|
if($activeEffectsTag !== null){
|
||||||
@ -172,6 +182,8 @@ abstract class Living extends Entity{
|
|||||||
$nbt = parent::saveNBT();
|
$nbt = parent::saveNBT();
|
||||||
$nbt->setFloat("Health", $this->getHealth());
|
$nbt->setFloat("Health", $this->getHealth());
|
||||||
|
|
||||||
|
$nbt->setShort("Air", $this->getAirSupplyTicks());
|
||||||
|
|
||||||
if(!empty($this->effectManager->all())){
|
if(!empty($this->effectManager->all())){
|
||||||
$effects = [];
|
$effects = [];
|
||||||
foreach($this->effectManager->all() as $effect){
|
foreach($this->effectManager->all() as $effect){
|
||||||
@ -598,7 +610,7 @@ abstract class Living extends Entity{
|
|||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function isBreathing() : bool{
|
public function isBreathing() : bool{
|
||||||
return $this->getGenericFlag(EntityMetadataFlags::BREATHING);
|
return $this->breathing;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -608,7 +620,7 @@ abstract class Living extends Entity{
|
|||||||
* @param bool $value
|
* @param bool $value
|
||||||
*/
|
*/
|
||||||
public function setBreathing(bool $value = true) : void{
|
public function setBreathing(bool $value = true) : void{
|
||||||
$this->setGenericFlag(EntityMetadataFlags::BREATHING, $value);
|
$this->breathing = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -618,7 +630,7 @@ abstract class Living extends Entity{
|
|||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function getAirSupplyTicks() : int{
|
public function getAirSupplyTicks() : int{
|
||||||
return $this->propertyManager->getShort(EntityMetadataProperties::AIR);
|
return $this->breathTicks;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -627,7 +639,7 @@ abstract class Living extends Entity{
|
|||||||
* @param int $ticks
|
* @param int $ticks
|
||||||
*/
|
*/
|
||||||
public function setAirSupplyTicks(int $ticks) : void{
|
public function setAirSupplyTicks(int $ticks) : void{
|
||||||
$this->propertyManager->setShort(EntityMetadataProperties::AIR, $ticks);
|
$this->breathTicks = $ticks;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -635,7 +647,7 @@ abstract class Living extends Entity{
|
|||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function getMaxAirSupplyTicks() : int{
|
public function getMaxAirSupplyTicks() : int{
|
||||||
return $this->propertyManager->getShort(EntityMetadataProperties::MAX_AIR);
|
return $this->maxBreathTicks;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -644,7 +656,7 @@ abstract class Living extends Entity{
|
|||||||
* @param int $ticks
|
* @param int $ticks
|
||||||
*/
|
*/
|
||||||
public function setMaxAirSupplyTicks(int $ticks) : void{
|
public function setMaxAirSupplyTicks(int $ticks) : void{
|
||||||
$this->propertyManager->setShort(EntityMetadataProperties::MAX_AIR, $ticks);
|
$this->maxBreathTicks = $ticks;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -755,6 +767,17 @@ abstract class Living extends Entity{
|
|||||||
$player->getNetworkSession()->onMobArmorChange($this);
|
$player->getNetworkSession()->onMobArmorChange($this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function syncNetworkData() : void{
|
||||||
|
parent::syncNetworkData();
|
||||||
|
|
||||||
|
$this->propertyManager->setByte(EntityMetadataProperties::POTION_AMBIENT, $this->effectManager->hasOnlyAmbientEffects() ? 1 : 0);
|
||||||
|
$this->propertyManager->setInt(EntityMetadataProperties::POTION_COLOR, Binary::signInt($this->effectManager->getBubbleColor()->toARGB()));
|
||||||
|
$this->propertyManager->setShort(EntityMetadataProperties::AIR, $this->breathTicks);
|
||||||
|
$this->propertyManager->setShort(EntityMetadataProperties::MAX_AIR, $this->maxBreathTicks);
|
||||||
|
|
||||||
|
$this->propertyManager->setGenericFlag(EntityMetadataFlags::BREATHING, $this->breathing);
|
||||||
|
}
|
||||||
|
|
||||||
protected function onDispose() : void{
|
protected function onDispose() : void{
|
||||||
$this->armorInventory->removeAllViewers();
|
$this->armorInventory->removeAllViewers();
|
||||||
parent::onDispose();
|
parent::onDispose();
|
||||||
|
@ -40,6 +40,11 @@ class Villager extends Living implements Ageable{
|
|||||||
public $width = 0.6;
|
public $width = 0.6;
|
||||||
public $height = 1.8;
|
public $height = 1.8;
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
private $baby = false;
|
||||||
|
/** @var int */
|
||||||
|
private $profession = self::PROFESSION_FARMER;
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
return "Villager";
|
return "Villager";
|
||||||
}
|
}
|
||||||
@ -70,14 +75,21 @@ class Villager extends Living implements Ageable{
|
|||||||
* @param int $profession
|
* @param int $profession
|
||||||
*/
|
*/
|
||||||
public function setProfession(int $profession) : void{
|
public function setProfession(int $profession) : void{
|
||||||
$this->propertyManager->setInt(EntityMetadataProperties::VARIANT, $profession);
|
$this->profession = $profession; //TODO: validation
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getProfession() : int{
|
public function getProfession() : int{
|
||||||
return $this->propertyManager->getInt(EntityMetadataProperties::VARIANT);
|
return $this->profession;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isBaby() : bool{
|
public function isBaby() : bool{
|
||||||
return $this->getGenericFlag(EntityMetadataFlags::BABY);
|
return $this->baby;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function syncNetworkData() : void{
|
||||||
|
parent::syncNetworkData();
|
||||||
|
$this->propertyManager->setGenericFlag(EntityMetadataFlags::BABY, $this->baby);
|
||||||
|
|
||||||
|
$this->propertyManager->setInt(EntityMetadataProperties::VARIANT, $this->profession);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,9 +27,11 @@ use pocketmine\event\entity\EntityDamageEvent;
|
|||||||
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataFlags;
|
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataFlags;
|
||||||
|
|
||||||
abstract class WaterAnimal extends Living implements Ageable{
|
abstract class WaterAnimal extends Living implements Ageable{
|
||||||
|
/** @var bool */
|
||||||
|
protected $baby = false;
|
||||||
|
|
||||||
public function isBaby() : bool{
|
public function isBaby() : bool{
|
||||||
return $this->getGenericFlag(EntityMetadataFlags::BABY);
|
return $this->baby;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function canBreathe() : bool{
|
public function canBreathe() : bool{
|
||||||
@ -40,4 +42,9 @@ abstract class WaterAnimal extends Living implements Ageable{
|
|||||||
$ev = new EntityDamageEvent($this, EntityDamageEvent::CAUSE_SUFFOCATION, 2);
|
$ev = new EntityDamageEvent($this, EntityDamageEvent::CAUSE_SUFFOCATION, 2);
|
||||||
$this->attack($ev);
|
$this->attack($ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function syncNetworkData() : void{
|
||||||
|
parent::syncNetworkData();
|
||||||
|
$this->propertyManager->setGenericFlag(EntityMetadataFlags::BABY, $this->baby);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,6 @@ namespace pocketmine\entity\effect;
|
|||||||
use pocketmine\entity\Living;
|
use pocketmine\entity\Living;
|
||||||
use pocketmine\event\entity\EntityEffectAddEvent;
|
use pocketmine\event\entity\EntityEffectAddEvent;
|
||||||
use pocketmine\event\entity\EntityEffectRemoveEvent;
|
use pocketmine\event\entity\EntityEffectRemoveEvent;
|
||||||
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataProperties;
|
|
||||||
use pocketmine\utils\Color;
|
use pocketmine\utils\Color;
|
||||||
use function abs;
|
use function abs;
|
||||||
|
|
||||||
@ -38,8 +37,14 @@ class EffectManager{
|
|||||||
/** @var EffectInstance[] */
|
/** @var EffectInstance[] */
|
||||||
protected $effects = [];
|
protected $effects = [];
|
||||||
|
|
||||||
|
/** @var Color */
|
||||||
|
protected $bubbleColor;
|
||||||
|
/** @var bool */
|
||||||
|
protected $onlyAmbientEffects = false;
|
||||||
|
|
||||||
public function __construct(Living $entity){
|
public function __construct(Living $entity){
|
||||||
$this->entity = $entity;
|
$this->entity = $entity;
|
||||||
|
$this->bubbleColor = new Color(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -176,16 +181,29 @@ class EffectManager{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$propManager = $this->entity->getDataPropertyManager();
|
|
||||||
if(!empty($colors)){
|
if(!empty($colors)){
|
||||||
$propManager->setInt(EntityMetadataProperties::POTION_COLOR, Color::mix(...$colors)->toARGB());
|
$this->bubbleColor = Color::mix(...$colors);
|
||||||
$propManager->setByte(EntityMetadataProperties::POTION_AMBIENT, $ambient ? 1 : 0);
|
$this->onlyAmbientEffects = $ambient;
|
||||||
}else{
|
}else{
|
||||||
$propManager->setInt(EntityMetadataProperties::POTION_COLOR, 0);
|
$this->bubbleColor = new Color(0, 0, 0, 0);
|
||||||
$propManager->setByte(EntityMetadataProperties::POTION_AMBIENT, 0);
|
$this->onlyAmbientEffects = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Color
|
||||||
|
*/
|
||||||
|
public function getBubbleColor() : Color{
|
||||||
|
return $this->bubbleColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasOnlyAmbientEffects() : bool{
|
||||||
|
return $this->onlyAmbientEffects;
|
||||||
|
}
|
||||||
|
|
||||||
public function tick(int $tickDiff = 1) : bool{
|
public function tick(int $tickDiff = 1) : bool{
|
||||||
foreach($this->effects as $instance){
|
foreach($this->effects as $instance){
|
||||||
$type = $instance->getType();
|
$type = $instance->getType();
|
||||||
|
@ -107,12 +107,15 @@ class ExperienceOrb extends Entity{
|
|||||||
*/
|
*/
|
||||||
protected $targetPlayerRuntimeId = null;
|
protected $targetPlayerRuntimeId = null;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
protected $xpValue = 1;
|
||||||
|
|
||||||
protected function initEntity(CompoundTag $nbt) : void{
|
protected function initEntity(CompoundTag $nbt) : void{
|
||||||
parent::initEntity($nbt);
|
parent::initEntity($nbt);
|
||||||
|
|
||||||
$this->age = $nbt->getShort("Age", 0);
|
$this->age = $nbt->getShort("Age", 0);
|
||||||
|
|
||||||
$value = 0;
|
$value = 1;
|
||||||
if($nbt->hasTag(self::TAG_VALUE_PC, ShortTag::class)){ //PC
|
if($nbt->hasTag(self::TAG_VALUE_PC, ShortTag::class)){ //PC
|
||||||
$value = $nbt->getShort(self::TAG_VALUE_PC);
|
$value = $nbt->getShort(self::TAG_VALUE_PC);
|
||||||
}elseif($nbt->hasTag(self::TAG_VALUE_PE, IntTag::class)){ //PE save format
|
}elseif($nbt->hasTag(self::TAG_VALUE_PE, IntTag::class)){ //PE save format
|
||||||
@ -134,14 +137,14 @@ class ExperienceOrb extends Entity{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getXpValue() : int{
|
public function getXpValue() : int{
|
||||||
return $this->propertyManager->getInt(EntityMetadataProperties::EXPERIENCE_VALUE) ?? 0;
|
return $this->xpValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setXpValue(int $amount) : void{
|
public function setXpValue(int $amount) : void{
|
||||||
if($amount <= 0){
|
if($amount <= 0){
|
||||||
throw new \InvalidArgumentException("XP amount must be greater than 0, got $amount");
|
throw new \InvalidArgumentException("XP amount must be greater than 0, got $amount");
|
||||||
}
|
}
|
||||||
$this->propertyManager->setInt(EntityMetadataProperties::EXPERIENCE_VALUE, $amount);
|
$this->xpValue = $amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function hasTargetPlayer() : bool{
|
public function hasTargetPlayer() : bool{
|
||||||
@ -225,4 +228,10 @@ class ExperienceOrb extends Entity{
|
|||||||
public function canBeCollidedWith() : bool{
|
public function canBeCollidedWith() : bool{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function syncNetworkData() : void{
|
||||||
|
parent::syncNetworkData();
|
||||||
|
|
||||||
|
$this->propertyManager->setInt(EntityMetadataProperties::EXPERIENCE_VALUE, $this->xpValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,8 +71,6 @@ class FallingBlock extends Entity{
|
|||||||
$damage = $nbt->getByte("Data", 0);
|
$damage = $nbt->getByte("Data", 0);
|
||||||
|
|
||||||
$this->block = BlockFactory::get($blockId, $damage);
|
$this->block = BlockFactory::get($blockId, $damage);
|
||||||
|
|
||||||
$this->propertyManager->setInt(EntityMetadataProperties::VARIANT, $this->block->getRuntimeId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function canCollideWith(Entity $entity) : bool{
|
public function canCollideWith(Entity $entity) : bool{
|
||||||
@ -138,4 +136,10 @@ class FallingBlock extends Entity{
|
|||||||
|
|
||||||
return $nbt;
|
return $nbt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function syncNetworkData() : void{
|
||||||
|
parent::syncNetworkData();
|
||||||
|
|
||||||
|
$this->propertyManager->setInt(EntityMetadataProperties::VARIANT, $this->block->getRuntimeId());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -238,7 +238,7 @@ class ItemEntity extends Entity{
|
|||||||
$pk->position = $this->asVector3();
|
$pk->position = $this->asVector3();
|
||||||
$pk->motion = $this->getMotion();
|
$pk->motion = $this->getMotion();
|
||||||
$pk->item = $this->getItem();
|
$pk->item = $this->getItem();
|
||||||
$pk->metadata = $this->propertyManager->getAll();
|
$pk->metadata = $this->getSyncedNetworkData(false);
|
||||||
|
|
||||||
$player->sendDataPacket($pk);
|
$player->sendDataPacket($pk);
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,6 @@ use pocketmine\entity\Explosive;
|
|||||||
use pocketmine\event\entity\EntityDamageEvent;
|
use pocketmine\event\entity\EntityDamageEvent;
|
||||||
use pocketmine\event\entity\ExplosionPrimeEvent;
|
use pocketmine\event\entity\ExplosionPrimeEvent;
|
||||||
use pocketmine\nbt\tag\CompoundTag;
|
use pocketmine\nbt\tag\CompoundTag;
|
||||||
use pocketmine\nbt\tag\ShortTag;
|
|
||||||
use pocketmine\network\mcpe\protocol\types\entity\EntityLegacyIds;
|
use pocketmine\network\mcpe\protocol\types\entity\EntityLegacyIds;
|
||||||
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataFlags;
|
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataFlags;
|
||||||
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataProperties;
|
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataProperties;
|
||||||
@ -61,14 +60,7 @@ class PrimedTNT extends Entity implements Explosive{
|
|||||||
protected function initEntity(CompoundTag $nbt) : void{
|
protected function initEntity(CompoundTag $nbt) : void{
|
||||||
parent::initEntity($nbt);
|
parent::initEntity($nbt);
|
||||||
|
|
||||||
if($nbt->hasTag("Fuse", ShortTag::class)){
|
$this->fuse = $nbt->getShort("Fuse", 80, true);
|
||||||
$this->fuse = $nbt->getShort("Fuse");
|
|
||||||
}else{
|
|
||||||
$this->fuse = 80;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->setGenericFlag(EntityMetadataFlags::IGNITED, true);
|
|
||||||
$this->propertyManager->setInt(EntityMetadataProperties::FUSE_LENGTH, $this->fuse);
|
|
||||||
|
|
||||||
$this->world->addSound($this, new IgniteSound());
|
$this->world->addSound($this, new IgniteSound());
|
||||||
}
|
}
|
||||||
@ -92,10 +84,6 @@ class PrimedTNT extends Entity implements Explosive{
|
|||||||
|
|
||||||
$hasUpdate = parent::entityBaseTick($tickDiff);
|
$hasUpdate = parent::entityBaseTick($tickDiff);
|
||||||
|
|
||||||
if($this->fuse % 5 === 0){ //don't spam it every tick, it's not necessary
|
|
||||||
$this->propertyManager->setInt(EntityMetadataProperties::FUSE_LENGTH, $this->fuse);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!$this->isFlaggedForDespawn()){
|
if(!$this->isFlaggedForDespawn()){
|
||||||
$this->fuse -= $tickDiff;
|
$this->fuse -= $tickDiff;
|
||||||
|
|
||||||
@ -119,4 +107,11 @@ class PrimedTNT extends Entity implements Explosive{
|
|||||||
$explosion->explodeB();
|
$explosion->explodeB();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function syncNetworkData() : void{
|
||||||
|
parent::syncNetworkData();
|
||||||
|
|
||||||
|
$this->propertyManager->setGenericFlag(EntityMetadataFlags::IGNITED, true);
|
||||||
|
$this->propertyManager->setInt(EntityMetadataProperties::FUSE_LENGTH, $this->fuse);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,6 +67,9 @@ class Arrow extends Projectile{
|
|||||||
/** @var int */
|
/** @var int */
|
||||||
protected $collideTicks = 0;
|
protected $collideTicks = 0;
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
protected $critical = false;
|
||||||
|
|
||||||
public function __construct(World $world, CompoundTag $nbt, ?Entity $shootingEntity = null, bool $critical = false){
|
public function __construct(World $world, CompoundTag $nbt, ?Entity $shootingEntity = null, bool $critical = false){
|
||||||
parent::__construct($world, $nbt, $shootingEntity);
|
parent::__construct($world, $nbt, $shootingEntity);
|
||||||
$this->setCritical($critical);
|
$this->setCritical($critical);
|
||||||
@ -87,11 +90,11 @@ class Arrow extends Projectile{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function isCritical() : bool{
|
public function isCritical() : bool{
|
||||||
return $this->getGenericFlag(EntityMetadataFlags::CRITICAL);
|
return $this->critical;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setCritical(bool $value = true) : void{
|
public function setCritical(bool $value = true) : void{
|
||||||
$this->setGenericFlag(EntityMetadataFlags::CRITICAL, $value);
|
$this->critical = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getResultDamage() : int{
|
public function getResultDamage() : int{
|
||||||
@ -199,4 +202,10 @@ class Arrow extends Projectile{
|
|||||||
$playerInventory->addItem(clone $item);
|
$playerInventory->addItem(clone $item);
|
||||||
$this->flagForDespawn();
|
$this->flagForDespawn();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function syncNetworkData() : void{
|
||||||
|
parent::syncNetworkData();
|
||||||
|
|
||||||
|
$this->propertyManager->setGenericFlag(EntityMetadataFlags::CRITICAL, $this->critical);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,10 +49,15 @@ class SplashPotion extends Throwable{
|
|||||||
protected $gravity = 0.05;
|
protected $gravity = 0.05;
|
||||||
protected $drag = 0.01;
|
protected $drag = 0.01;
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
protected $linger = false;
|
||||||
|
/** @var int */
|
||||||
|
protected $potionId = Potion::WATER;
|
||||||
|
|
||||||
protected function initEntity(CompoundTag $nbt) : void{
|
protected function initEntity(CompoundTag $nbt) : void{
|
||||||
parent::initEntity($nbt);
|
parent::initEntity($nbt);
|
||||||
|
|
||||||
$this->setPotionId($nbt->getShort("PotionId", 0));
|
$this->setPotionId($nbt->getShort("PotionId", Potion::WATER));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function saveNBT() : CompoundTag{
|
public function saveNBT() : CompoundTag{
|
||||||
@ -139,14 +144,14 @@ class SplashPotion extends Throwable{
|
|||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function getPotionId() : int{
|
public function getPotionId() : int{
|
||||||
return $this->propertyManager->getShort(EntityMetadataProperties::POTION_AUX_VALUE) ?? 0;
|
return $this->potionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $id
|
* @param int $id
|
||||||
*/
|
*/
|
||||||
public function setPotionId(int $id) : void{
|
public function setPotionId(int $id) : void{
|
||||||
$this->propertyManager->setShort(EntityMetadataProperties::POTION_AUX_VALUE, $id);
|
$this->potionId = $id; //TODO: validation
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -154,7 +159,7 @@ class SplashPotion extends Throwable{
|
|||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function willLinger() : bool{
|
public function willLinger() : bool{
|
||||||
return $this->getDataFlag(EntityMetadataProperties::FLAGS, EntityMetadataFlags::LINGER);
|
return $this->linger;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -163,7 +168,7 @@ class SplashPotion extends Throwable{
|
|||||||
* @param bool $value
|
* @param bool $value
|
||||||
*/
|
*/
|
||||||
public function setLinger(bool $value = true) : void{
|
public function setLinger(bool $value = true) : void{
|
||||||
$this->setDataFlag(EntityMetadataProperties::FLAGS, EntityMetadataFlags::LINGER, $value);
|
$this->linger = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -172,4 +177,11 @@ class SplashPotion extends Throwable{
|
|||||||
public function getPotionEffects() : array{
|
public function getPotionEffects() : array{
|
||||||
return Potion::getPotionEffectsById($this->getPotionId());
|
return Potion::getPotionEffectsById($this->getPotionId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function syncNetworkData() : void{
|
||||||
|
parent::syncNetworkData();
|
||||||
|
|
||||||
|
$this->propertyManager->setShort(EntityMetadataProperties::POTION_AUX_VALUE, $this->potionId);
|
||||||
|
$this->propertyManager->setGenericFlag(EntityMetadataFlags::LINGER, $this->linger);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@ use pocketmine\network\BadPacketException;
|
|||||||
use pocketmine\network\mcpe\handler\PacketHandler;
|
use pocketmine\network\mcpe\handler\PacketHandler;
|
||||||
use pocketmine\network\mcpe\protocol\types\entity\EntityLegacyIds;
|
use pocketmine\network\mcpe\protocol\types\entity\EntityLegacyIds;
|
||||||
use pocketmine\network\mcpe\protocol\types\entity\EntityLink;
|
use pocketmine\network\mcpe\protocol\types\entity\EntityLink;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\entity\MetadataProperty;
|
||||||
use function array_search;
|
use function array_search;
|
||||||
use function count;
|
use function count;
|
||||||
|
|
||||||
@ -164,7 +165,7 @@ class AddActorPacket extends DataPacket implements ClientboundPacket{
|
|||||||
|
|
||||||
/** @var Attribute[] */
|
/** @var Attribute[] */
|
||||||
public $attributes = [];
|
public $attributes = [];
|
||||||
/** @var array */
|
/** @var MetadataProperty[] */
|
||||||
public $metadata = [];
|
public $metadata = [];
|
||||||
/** @var EntityLink[] */
|
/** @var EntityLink[] */
|
||||||
public $links = [];
|
public $links = [];
|
||||||
|
@ -28,6 +28,7 @@ namespace pocketmine\network\mcpe\protocol;
|
|||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\network\mcpe\handler\PacketHandler;
|
use pocketmine\network\mcpe\handler\PacketHandler;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\entity\MetadataProperty;
|
||||||
|
|
||||||
class AddItemActorPacket extends DataPacket implements ClientboundPacket{
|
class AddItemActorPacket extends DataPacket implements ClientboundPacket{
|
||||||
public const NETWORK_ID = ProtocolInfo::ADD_ITEM_ACTOR_PACKET;
|
public const NETWORK_ID = ProtocolInfo::ADD_ITEM_ACTOR_PACKET;
|
||||||
@ -42,7 +43,7 @@ class AddItemActorPacket extends DataPacket implements ClientboundPacket{
|
|||||||
public $position;
|
public $position;
|
||||||
/** @var Vector3|null */
|
/** @var Vector3|null */
|
||||||
public $motion;
|
public $motion;
|
||||||
/** @var array */
|
/** @var MetadataProperty[] */
|
||||||
public $metadata = [];
|
public $metadata = [];
|
||||||
/** @var bool */
|
/** @var bool */
|
||||||
public $isFromFishing = false;
|
public $isFromFishing = false;
|
||||||
|
@ -29,6 +29,7 @@ use pocketmine\item\Item;
|
|||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\network\mcpe\handler\PacketHandler;
|
use pocketmine\network\mcpe\handler\PacketHandler;
|
||||||
use pocketmine\network\mcpe\protocol\types\entity\EntityLink;
|
use pocketmine\network\mcpe\protocol\types\entity\EntityLink;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\entity\MetadataProperty;
|
||||||
use pocketmine\utils\UUID;
|
use pocketmine\utils\UUID;
|
||||||
use function count;
|
use function count;
|
||||||
|
|
||||||
@ -57,7 +58,7 @@ class AddPlayerPacket extends DataPacket implements ClientboundPacket{
|
|||||||
public $headYaw = null; //TODO
|
public $headYaw = null; //TODO
|
||||||
/** @var Item */
|
/** @var Item */
|
||||||
public $item;
|
public $item;
|
||||||
/** @var array */
|
/** @var MetadataProperty[] */
|
||||||
public $metadata = [];
|
public $metadata = [];
|
||||||
|
|
||||||
//TODO: adventure settings stuff
|
//TODO: adventure settings stuff
|
||||||
|
@ -27,16 +27,18 @@ namespace pocketmine\network\mcpe\protocol;
|
|||||||
|
|
||||||
|
|
||||||
use pocketmine\network\mcpe\handler\PacketHandler;
|
use pocketmine\network\mcpe\handler\PacketHandler;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\entity\MetadataProperty;
|
||||||
|
|
||||||
class SetActorDataPacket extends DataPacket implements ClientboundPacket, ServerboundPacket{ //TODO: check why this is serverbound
|
class SetActorDataPacket extends DataPacket implements ClientboundPacket, ServerboundPacket{ //TODO: check why this is serverbound
|
||||||
public const NETWORK_ID = ProtocolInfo::SET_ACTOR_DATA_PACKET;
|
public const NETWORK_ID = ProtocolInfo::SET_ACTOR_DATA_PACKET;
|
||||||
|
|
||||||
/** @var int */
|
/** @var int */
|
||||||
public $entityRuntimeId;
|
public $entityRuntimeId;
|
||||||
/** @var array */
|
/** @var MetadataProperty[] */
|
||||||
public $metadata;
|
public $metadata;
|
||||||
|
|
||||||
public static function create(int $entityRuntimeId, array $metadata) : self{
|
public static function create(int $entityRuntimeId, array $metadata) : self{
|
||||||
|
|
||||||
$result = new self;
|
$result = new self;
|
||||||
$result->entityRuntimeId = $entityRuntimeId;
|
$result->entityRuntimeId = $entityRuntimeId;
|
||||||
$result->metadata = $metadata;
|
$result->metadata = $metadata;
|
||||||
|
@ -0,0 +1,65 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ____ _ _ __ __ _ __ __ ____
|
||||||
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* @author PocketMine Team
|
||||||
|
* @link http://www.pocketmine.net/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace pocketmine\network\mcpe\protocol\types\entity;
|
||||||
|
|
||||||
|
use pocketmine\math\Vector3;
|
||||||
|
use pocketmine\network\mcpe\serializer\NetworkBinaryStream;
|
||||||
|
|
||||||
|
final class BlockPosMetadataProperty implements MetadataProperty{
|
||||||
|
|
||||||
|
/** @var Vector3 */
|
||||||
|
private $value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Vector3 $value
|
||||||
|
*/
|
||||||
|
public function __construct(Vector3 $value){
|
||||||
|
$this->value = $value->floor();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Vector3
|
||||||
|
*/
|
||||||
|
public function getValue() : Vector3{
|
||||||
|
return $this->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function id() : int{
|
||||||
|
return EntityMetadataTypes::POS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function read(NetworkBinaryStream $in) : self{
|
||||||
|
$vec = new Vector3(0, 0, 0);
|
||||||
|
$in->getSignedBlockPosition($vec->x, $vec->y, $vec->z);
|
||||||
|
return new self($vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function write(NetworkBinaryStream $out) : void{
|
||||||
|
$out->putSignedBlockPosition($this->value->x, $this->value->y, $this->value->z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function equals(MetadataProperty $other) : bool{
|
||||||
|
return $other instanceof $this and $other->value->equals($this->value);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ____ _ _ __ __ _ __ __ ____
|
||||||
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* @author PocketMine Team
|
||||||
|
* @link http://www.pocketmine.net/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace pocketmine\network\mcpe\protocol\types\entity;
|
||||||
|
|
||||||
|
use pocketmine\network\mcpe\serializer\NetworkBinaryStream;
|
||||||
|
|
||||||
|
final class ByteMetadataProperty implements MetadataProperty{
|
||||||
|
use IntegerishMetadataProperty;
|
||||||
|
|
||||||
|
protected function min() : int{
|
||||||
|
return -0x80;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function max() : int{
|
||||||
|
return 0x7f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function id() : int{
|
||||||
|
return EntityMetadataTypes::BYTE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function read(NetworkBinaryStream $in) : self{
|
||||||
|
return new self($in->getByte());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function write(NetworkBinaryStream $out) : void{
|
||||||
|
$out->putByte($this->value);
|
||||||
|
}
|
||||||
|
}
|
@ -25,51 +25,27 @@ namespace pocketmine\network\mcpe\protocol\types\entity;
|
|||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataTypes;
|
use function get_class;
|
||||||
use function assert;
|
|
||||||
use function is_float;
|
|
||||||
use function is_int;
|
|
||||||
use function is_string;
|
|
||||||
|
|
||||||
class EntityMetadataCollection{
|
class EntityMetadataCollection{
|
||||||
|
|
||||||
|
/** @var MetadataProperty[] */
|
||||||
private $properties = [];
|
private $properties = [];
|
||||||
|
/** @var MetadataProperty[] */
|
||||||
private $dirtyProperties = [];
|
private $dirtyProperties = [];
|
||||||
|
|
||||||
public function __construct(){
|
public function __construct(){
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $key
|
|
||||||
*
|
|
||||||
* @return int|null
|
|
||||||
*/
|
|
||||||
public function getByte(int $key) : ?int{
|
|
||||||
$value = $this->getPropertyValue($key, EntityMetadataTypes::BYTE);
|
|
||||||
assert(is_int($value) or $value === null);
|
|
||||||
return $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $key
|
* @param int $key
|
||||||
* @param int $value
|
* @param int $value
|
||||||
* @param bool $force
|
* @param bool $force
|
||||||
*/
|
*/
|
||||||
public function setByte(int $key, int $value, bool $force = false) : void{
|
public function setByte(int $key, int $value, bool $force = false) : void{
|
||||||
$this->setPropertyValue($key, EntityMetadataTypes::BYTE, $value, $force);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
$this->set($key, new ByteMetadataProperty($value), $force);
|
||||||
* @param int $key
|
|
||||||
*
|
|
||||||
* @return int|null
|
|
||||||
*/
|
|
||||||
public function getShort(int $key) : ?int{
|
|
||||||
$value = $this->getPropertyValue($key, EntityMetadataTypes::SHORT);
|
|
||||||
assert(is_int($value) or $value === null);
|
|
||||||
return $value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -78,18 +54,7 @@ class EntityMetadataCollection{
|
|||||||
* @param bool $force
|
* @param bool $force
|
||||||
*/
|
*/
|
||||||
public function setShort(int $key, int $value, bool $force = false) : void{
|
public function setShort(int $key, int $value, bool $force = false) : void{
|
||||||
$this->setPropertyValue($key, EntityMetadataTypes::SHORT, $value, $force);
|
$this->set($key, new ShortMetadataProperty($value), $force);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $key
|
|
||||||
*
|
|
||||||
* @return int|null
|
|
||||||
*/
|
|
||||||
public function getInt(int $key) : ?int{
|
|
||||||
$value = $this->getPropertyValue($key, EntityMetadataTypes::INT);
|
|
||||||
assert(is_int($value) or $value === null);
|
|
||||||
return $value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -98,18 +63,7 @@ class EntityMetadataCollection{
|
|||||||
* @param bool $force
|
* @param bool $force
|
||||||
*/
|
*/
|
||||||
public function setInt(int $key, int $value, bool $force = false) : void{
|
public function setInt(int $key, int $value, bool $force = false) : void{
|
||||||
$this->setPropertyValue($key, EntityMetadataTypes::INT, $value, $force);
|
$this->set($key, new IntMetadataProperty($value), $force);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $key
|
|
||||||
*
|
|
||||||
* @return float|null
|
|
||||||
*/
|
|
||||||
public function getFloat(int $key) : ?float{
|
|
||||||
$value = $this->getPropertyValue($key, EntityMetadataTypes::FLOAT);
|
|
||||||
assert(is_float($value) or $value === null);
|
|
||||||
return $value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -118,18 +72,7 @@ class EntityMetadataCollection{
|
|||||||
* @param bool $force
|
* @param bool $force
|
||||||
*/
|
*/
|
||||||
public function setFloat(int $key, float $value, bool $force = false) : void{
|
public function setFloat(int $key, float $value, bool $force = false) : void{
|
||||||
$this->setPropertyValue($key, EntityMetadataTypes::FLOAT, $value, $force);
|
$this->set($key, new FloatMetadataProperty($value), $force);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $key
|
|
||||||
*
|
|
||||||
* @return null|string
|
|
||||||
*/
|
|
||||||
public function getString(int $key) : ?string{
|
|
||||||
$value = $this->getPropertyValue($key, EntityMetadataTypes::STRING);
|
|
||||||
assert(is_string($value) or $value === null);
|
|
||||||
return $value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -138,19 +81,7 @@ class EntityMetadataCollection{
|
|||||||
* @param bool $force
|
* @param bool $force
|
||||||
*/
|
*/
|
||||||
public function setString(int $key, string $value, bool $force = false) : void{
|
public function setString(int $key, string $value, bool $force = false) : void{
|
||||||
$this->setPropertyValue($key, EntityMetadataTypes::STRING, $value, $force);
|
$this->set($key, new StringMetadataProperty($value), $force);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $key
|
|
||||||
*
|
|
||||||
* @return null|Item
|
|
||||||
*/
|
|
||||||
public function getItem(int $key) : ?Item{
|
|
||||||
$value = $this->getPropertyValue($key, EntityMetadataTypes::SLOT);
|
|
||||||
assert($value instanceof Item or $value === null);
|
|
||||||
|
|
||||||
return $value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -159,18 +90,7 @@ class EntityMetadataCollection{
|
|||||||
* @param bool $force
|
* @param bool $force
|
||||||
*/
|
*/
|
||||||
public function setItem(int $key, Item $value, bool $force = false) : void{
|
public function setItem(int $key, Item $value, bool $force = false) : void{
|
||||||
$this->setPropertyValue($key, EntityMetadataTypes::SLOT, $value, $force);
|
$this->set($key, new ItemStackMetadataProperty($value), $force);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $key
|
|
||||||
*
|
|
||||||
* @return null|Vector3
|
|
||||||
*/
|
|
||||||
public function getBlockPos(int $key) : ?Vector3{
|
|
||||||
$value = $this->getPropertyValue($key, EntityMetadataTypes::POS);
|
|
||||||
assert($value instanceof Vector3 or $value === null);
|
|
||||||
return $value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -179,18 +99,7 @@ class EntityMetadataCollection{
|
|||||||
* @param bool $force
|
* @param bool $force
|
||||||
*/
|
*/
|
||||||
public function setBlockPos(int $key, ?Vector3 $value, bool $force = false) : void{
|
public function setBlockPos(int $key, ?Vector3 $value, bool $force = false) : void{
|
||||||
$this->setPropertyValue($key, EntityMetadataTypes::POS, $value ? $value->floor() : null, $force);
|
$this->set($key, new BlockPosMetadataProperty($value ?? new Vector3(0, 0, 0)), $force);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $key
|
|
||||||
*
|
|
||||||
* @return int|null
|
|
||||||
*/
|
|
||||||
public function getLong(int $key) : ?int{
|
|
||||||
$value = $this->getPropertyValue($key, EntityMetadataTypes::LONG);
|
|
||||||
assert(is_int($value) or $value === null);
|
|
||||||
return $value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -199,18 +108,7 @@ class EntityMetadataCollection{
|
|||||||
* @param bool $force
|
* @param bool $force
|
||||||
*/
|
*/
|
||||||
public function setLong(int $key, int $value, bool $force = false) : void{
|
public function setLong(int $key, int $value, bool $force = false) : void{
|
||||||
$this->setPropertyValue($key, EntityMetadataTypes::LONG, $value, $force);
|
$this->set($key, new LongMetadataProperty($value), $force);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $key
|
|
||||||
*
|
|
||||||
* @return null|Vector3
|
|
||||||
*/
|
|
||||||
public function getVector3(int $key) : ?Vector3{
|
|
||||||
$value = $this->getPropertyValue($key, EntityMetadataTypes::VECTOR3F);
|
|
||||||
assert($value instanceof Vector3 or $value === null);
|
|
||||||
return $value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -219,74 +117,60 @@ class EntityMetadataCollection{
|
|||||||
* @param bool $force
|
* @param bool $force
|
||||||
*/
|
*/
|
||||||
public function setVector3(int $key, ?Vector3 $value, bool $force = false) : void{
|
public function setVector3(int $key, ?Vector3 $value, bool $force = false) : void{
|
||||||
$this->setPropertyValue($key, EntityMetadataTypes::VECTOR3F, $value ? $value->asVector3() : null, $force);
|
$this->set($key, new Vec3MetadataProperty($value ?? new Vector3(0, 0, 0)), $force);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $key
|
|
||||||
*/
|
|
||||||
public function removeProperty(int $key) : void{
|
|
||||||
unset($this->properties[$key]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $key
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function hasProperty(int $key) : bool{
|
|
||||||
return isset($this->properties[$key]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $key
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public function getPropertyType(int $key) : int{
|
|
||||||
if(isset($this->properties[$key])){
|
|
||||||
return $this->properties[$key][0];
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function checkType(int $key, int $type) : void{
|
|
||||||
if(isset($this->properties[$key]) and $this->properties[$key][0] !== $type){
|
|
||||||
throw new \RuntimeException("Expected type $type, but have " . $this->properties[$key][0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $key
|
|
||||||
* @param int $type
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function getPropertyValue(int $key, int $type){
|
|
||||||
if($type !== -1){
|
|
||||||
$this->checkType($key, $type);
|
|
||||||
}
|
|
||||||
return isset($this->properties[$key]) ? $this->properties[$key][1] : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $key
|
* @param int $key
|
||||||
* @param int $type
|
|
||||||
* @param mixed $value
|
* @param mixed $value
|
||||||
* @param bool $force
|
* @param bool $force
|
||||||
*/
|
*/
|
||||||
public function setPropertyValue(int $key, int $type, $value, bool $force = false) : void{
|
public function set(int $key, MetadataProperty $value, bool $force = false) : void{
|
||||||
if(!$force){
|
if(!$force and isset($this->properties[$key]) and !($this->properties[$key] instanceof $value)){
|
||||||
$this->checkType($key, $type);
|
throw new \InvalidArgumentException("Can't overwrite property with mismatching types (have " . get_class($this->properties[$key]) . ")");
|
||||||
|
}
|
||||||
|
if(!isset($this->properties[$key]) or !$this->properties[$key]->equals($value)){
|
||||||
|
$this->properties[$key] = $this->dirtyProperties[$key] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setGenericFlag(int $flagId, bool $value) : void{
|
||||||
|
$propertyId = $flagId >= 64 ? EntityMetadataProperties::FLAGS2 : EntityMetadataProperties::FLAGS;
|
||||||
|
$realFlagId = $flagId % 64;
|
||||||
|
$flagSetProp = $this->properties[$propertyId] ?? null;
|
||||||
|
if($flagSetProp === null){
|
||||||
|
$flagSet = 0;
|
||||||
|
}elseif($flagSetProp instanceof LongMetadataProperty){
|
||||||
|
$flagSet = $flagSetProp->getValue();
|
||||||
|
}else{
|
||||||
|
throw new \InvalidArgumentException("Wrong type found for flags, want long, but have " . get_class($flagSetProp));
|
||||||
|
}
|
||||||
|
|
||||||
|
if((($flagSet >> $realFlagId) & 1) !== ($value ? 1 : 0)){
|
||||||
|
$flagSet ^= (1 << $realFlagId);
|
||||||
|
$this->setLong($propertyId, $flagSet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setPlayerFlag(int $flagId, bool $value) : void{
|
||||||
|
$flagSetProp = $this->properties[EntityMetadataProperties::PLAYER_FLAGS] ?? null;
|
||||||
|
if($flagSetProp === null){
|
||||||
|
$flagSet = 0;
|
||||||
|
}elseif($flagSetProp instanceof ByteMetadataProperty){
|
||||||
|
$flagSet = $flagSetProp->getValue();
|
||||||
|
}else{
|
||||||
|
throw new \InvalidArgumentException("Wrong type found for flags, want byte, but have " . get_class($flagSetProp));
|
||||||
|
}
|
||||||
|
if((($flagSet >> $flagId) & 1) !== ($value ? 1 : 0)){
|
||||||
|
$flagSet ^= (1 << $flagId);
|
||||||
|
$this->setByte(EntityMetadataProperties::PLAYER_FLAGS, $flagSet);
|
||||||
}
|
}
|
||||||
$this->properties[$key] = $this->dirtyProperties[$key] = [$type, $value];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all properties.
|
* Returns all properties.
|
||||||
*
|
*
|
||||||
* @return array
|
* @return MetadataProperty[]
|
||||||
*/
|
*/
|
||||||
public function getAll() : array{
|
public function getAll() : array{
|
||||||
return $this->properties;
|
return $this->properties;
|
||||||
@ -295,7 +179,7 @@ class EntityMetadataCollection{
|
|||||||
/**
|
/**
|
||||||
* Returns properties that have changed and need to be broadcasted.
|
* Returns properties that have changed and need to be broadcasted.
|
||||||
*
|
*
|
||||||
* @return array
|
* @return MetadataProperty[]
|
||||||
*/
|
*/
|
||||||
public function getDirty() : array{
|
public function getDirty() : array{
|
||||||
return $this->dirtyProperties;
|
return $this->dirtyProperties;
|
||||||
|
@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ____ _ _ __ __ _ __ __ ____
|
||||||
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* @author PocketMine Team
|
||||||
|
* @link http://www.pocketmine.net/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace pocketmine\network\mcpe\protocol\types\entity;
|
||||||
|
|
||||||
|
use pocketmine\network\mcpe\serializer\NetworkBinaryStream;
|
||||||
|
|
||||||
|
final class FloatMetadataProperty implements MetadataProperty{
|
||||||
|
|
||||||
|
/** @var float */
|
||||||
|
private $value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param float $value
|
||||||
|
*/
|
||||||
|
public function __construct(float $value){
|
||||||
|
$this->value = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
|
public function getValue() : float{
|
||||||
|
return $this->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function id() : int{
|
||||||
|
return EntityMetadataTypes::FLOAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function equals(MetadataProperty $other) : bool{
|
||||||
|
return $other instanceof $this and $other->value === $this->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function read(NetworkBinaryStream $in) : self{
|
||||||
|
return new self($in->getLFloat());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function write(NetworkBinaryStream $out) : void{
|
||||||
|
$out->putLFloat($this->value);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ____ _ _ __ __ _ __ __ ____
|
||||||
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* @author PocketMine Team
|
||||||
|
* @link http://www.pocketmine.net/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace pocketmine\network\mcpe\protocol\types\entity;
|
||||||
|
|
||||||
|
use pocketmine\network\mcpe\serializer\NetworkBinaryStream;
|
||||||
|
|
||||||
|
final class IntMetadataProperty implements MetadataProperty{
|
||||||
|
use IntegerishMetadataProperty;
|
||||||
|
|
||||||
|
protected function min() : int{
|
||||||
|
return -0x80000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function max() : int{
|
||||||
|
return 0x7fffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function id() : int{
|
||||||
|
return EntityMetadataTypes::INT;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function read(NetworkBinaryStream $in) : self{
|
||||||
|
return new self($in->getVarInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function write(NetworkBinaryStream $out) : void{
|
||||||
|
$out->putVarInt($this->value);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ____ _ _ __ __ _ __ __ ____
|
||||||
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* @author PocketMine Team
|
||||||
|
* @link http://www.pocketmine.net/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace pocketmine\network\mcpe\protocol\types\entity;
|
||||||
|
|
||||||
|
trait IntegerishMetadataProperty{
|
||||||
|
/** @var int */
|
||||||
|
private $value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $value
|
||||||
|
*/
|
||||||
|
public function __construct(int $value){
|
||||||
|
if($value < $this->min() or $value > $this->max()){
|
||||||
|
throw new \InvalidArgumentException("Value is out of range " . $this->min() . " - " . $this->max());
|
||||||
|
}
|
||||||
|
$this->value = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract protected function min() : int;
|
||||||
|
|
||||||
|
abstract protected function max() : int;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getValue() : int{
|
||||||
|
return $this->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function equals(MetadataProperty $other) : bool{
|
||||||
|
return $other instanceof $this and $other->value === $this->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function buildFromFlags(array $flags) : self{
|
||||||
|
$value = 0;
|
||||||
|
foreach($flags as $flag => $v){
|
||||||
|
if($v){
|
||||||
|
$value |= 1 << $flag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new self($value);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ____ _ _ __ __ _ __ __ ____
|
||||||
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* @author PocketMine Team
|
||||||
|
* @link http://www.pocketmine.net/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace pocketmine\network\mcpe\protocol\types\entity;
|
||||||
|
|
||||||
|
use pocketmine\item\Item;
|
||||||
|
use pocketmine\network\mcpe\serializer\NetworkBinaryStream;
|
||||||
|
|
||||||
|
final class ItemStackMetadataProperty implements MetadataProperty{
|
||||||
|
/** @var Item */
|
||||||
|
private $value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Item $value
|
||||||
|
*/
|
||||||
|
public function __construct(Item $value){
|
||||||
|
$this->value = clone $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Item
|
||||||
|
*/
|
||||||
|
public function getValue() : Item{
|
||||||
|
return clone $this->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function id() : int{
|
||||||
|
return EntityMetadataTypes::SLOT;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function equals(MetadataProperty $other) : bool{
|
||||||
|
return $other instanceof $this and $other->value->equalsExact($this->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function read(NetworkBinaryStream $in) : self{
|
||||||
|
return new self($in->getSlot());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function write(NetworkBinaryStream $out) : void{
|
||||||
|
$out->putSlot($this->value);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ____ _ _ __ __ _ __ __ ____
|
||||||
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* @author PocketMine Team
|
||||||
|
* @link http://www.pocketmine.net/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace pocketmine\network\mcpe\protocol\types\entity;
|
||||||
|
|
||||||
|
use pocketmine\network\mcpe\serializer\NetworkBinaryStream;
|
||||||
|
use const PHP_INT_MAX;
|
||||||
|
use const PHP_INT_MIN;
|
||||||
|
|
||||||
|
final class LongMetadataProperty implements MetadataProperty{
|
||||||
|
use IntegerishMetadataProperty;
|
||||||
|
|
||||||
|
protected function min() : int{
|
||||||
|
return PHP_INT_MIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function max() : int{
|
||||||
|
return PHP_INT_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function id() : int{
|
||||||
|
return EntityMetadataTypes::LONG;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function read(NetworkBinaryStream $in) : self{
|
||||||
|
return new self($in->getVarLong());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function write(NetworkBinaryStream $out) : void{
|
||||||
|
$out->putVarLong($this->value);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ____ _ _ __ __ _ __ __ ____
|
||||||
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* @author PocketMine Team
|
||||||
|
* @link http://www.pocketmine.net/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace pocketmine\network\mcpe\protocol\types\entity;
|
||||||
|
|
||||||
|
use pocketmine\network\mcpe\serializer\NetworkBinaryStream;
|
||||||
|
|
||||||
|
interface MetadataProperty{
|
||||||
|
|
||||||
|
public static function id() : int;
|
||||||
|
|
||||||
|
public function write(NetworkBinaryStream $out) : void;
|
||||||
|
|
||||||
|
public function equals(MetadataProperty $other) : bool;
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ____ _ _ __ __ _ __ __ ____
|
||||||
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* @author PocketMine Team
|
||||||
|
* @link http://www.pocketmine.net/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace pocketmine\network\mcpe\protocol\types\entity;
|
||||||
|
|
||||||
|
use pocketmine\network\mcpe\serializer\NetworkBinaryStream;
|
||||||
|
|
||||||
|
final class ShortMetadataProperty implements MetadataProperty{
|
||||||
|
use IntegerishMetadataProperty;
|
||||||
|
|
||||||
|
protected function min() : int{
|
||||||
|
return -0x8000;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function max() : int{
|
||||||
|
return 0x7fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function id() : int{
|
||||||
|
return EntityMetadataTypes::SHORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function read(NetworkBinaryStream $in) : self{
|
||||||
|
return new self($in->getSignedLShort());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function write(NetworkBinaryStream $out) : void{
|
||||||
|
$out->putLShort($this->value);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ____ _ _ __ __ _ __ __ ____
|
||||||
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* @author PocketMine Team
|
||||||
|
* @link http://www.pocketmine.net/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace pocketmine\network\mcpe\protocol\types\entity;
|
||||||
|
|
||||||
|
use pocketmine\network\mcpe\serializer\NetworkBinaryStream;
|
||||||
|
|
||||||
|
final class StringMetadataProperty implements MetadataProperty{
|
||||||
|
/** @var string */
|
||||||
|
private $value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $value
|
||||||
|
*/
|
||||||
|
public function __construct(string $value){
|
||||||
|
$this->value = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function id() : int{
|
||||||
|
return EntityMetadataTypes::STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function read(NetworkBinaryStream $in) : self{
|
||||||
|
return new self($in->getString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function write(NetworkBinaryStream $out) : void{
|
||||||
|
$out->putString($this->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function equals(MetadataProperty $other) : bool{
|
||||||
|
return $other instanceof $this and $other->value === $this->value;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ____ _ _ __ __ _ __ __ ____
|
||||||
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* @author PocketMine Team
|
||||||
|
* @link http://www.pocketmine.net/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace pocketmine\network\mcpe\protocol\types\entity;
|
||||||
|
|
||||||
|
use pocketmine\math\Vector3;
|
||||||
|
use pocketmine\network\mcpe\serializer\NetworkBinaryStream;
|
||||||
|
|
||||||
|
class Vec3MetadataProperty implements MetadataProperty{
|
||||||
|
/** @var Vector3 */
|
||||||
|
private $value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Vector3 $value
|
||||||
|
*/
|
||||||
|
public function __construct(Vector3 $value){
|
||||||
|
$this->value = $value->asVector3();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Vector3
|
||||||
|
*/
|
||||||
|
public function getValue() : Vector3{
|
||||||
|
return clone $this->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function id() : int{
|
||||||
|
return EntityMetadataTypes::VECTOR3F;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function read(NetworkBinaryStream $in) : self{
|
||||||
|
return new self($in->getVector3());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function write(NetworkBinaryStream $out) : void{
|
||||||
|
$out->putVector3($this->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function equals(MetadataProperty $other) : bool{
|
||||||
|
return $other instanceof $this and $other->value->equals($this->value);
|
||||||
|
}
|
||||||
|
}
|
@ -37,8 +37,17 @@ use pocketmine\nbt\tag\IntTag;
|
|||||||
use pocketmine\nbt\TreeRoot;
|
use pocketmine\nbt\TreeRoot;
|
||||||
use pocketmine\network\BadPacketException;
|
use pocketmine\network\BadPacketException;
|
||||||
use pocketmine\network\mcpe\protocol\types\command\CommandOriginData;
|
use pocketmine\network\mcpe\protocol\types\command\CommandOriginData;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\entity\BlockPosMetadataProperty;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\entity\ByteMetadataProperty;
|
||||||
use pocketmine\network\mcpe\protocol\types\entity\EntityLink;
|
use pocketmine\network\mcpe\protocol\types\entity\EntityLink;
|
||||||
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataTypes;
|
use pocketmine\network\mcpe\protocol\types\entity\FloatMetadataProperty;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\entity\IntMetadataProperty;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\entity\ItemStackMetadataProperty;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\entity\LongMetadataProperty;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\entity\MetadataProperty;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\entity\ShortMetadataProperty;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\entity\StringMetadataProperty;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\entity\Vec3MetadataProperty;
|
||||||
use pocketmine\utils\BinaryDataException;
|
use pocketmine\utils\BinaryDataException;
|
||||||
use pocketmine\utils\BinaryStream;
|
use pocketmine\utils\BinaryStream;
|
||||||
use pocketmine\utils\UUID;
|
use pocketmine\utils\UUID;
|
||||||
@ -224,108 +233,51 @@ class NetworkBinaryStream extends BinaryStream{
|
|||||||
/**
|
/**
|
||||||
* Decodes entity metadata from the stream.
|
* Decodes entity metadata from the stream.
|
||||||
*
|
*
|
||||||
* @param bool $types Whether to include metadata types along with values in the returned array
|
* @return MetadataProperty[]
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*
|
*
|
||||||
* @throws BadPacketException
|
* @throws BadPacketException
|
||||||
* @throws BinaryDataException
|
* @throws BinaryDataException
|
||||||
*/
|
*/
|
||||||
public function getEntityMetadata(bool $types = true) : array{
|
public function getEntityMetadata() : array{
|
||||||
$count = $this->getUnsignedVarInt();
|
$count = $this->getUnsignedVarInt();
|
||||||
$data = [];
|
$data = [];
|
||||||
for($i = 0; $i < $count; ++$i){
|
for($i = 0; $i < $count; ++$i){
|
||||||
$key = $this->getUnsignedVarInt();
|
$key = $this->getUnsignedVarInt();
|
||||||
$type = $this->getUnsignedVarInt();
|
$type = $this->getUnsignedVarInt();
|
||||||
$value = null;
|
|
||||||
switch($type){
|
$data[$key] = $this->readMetadataProperty($type);
|
||||||
case EntityMetadataTypes::BYTE:
|
|
||||||
$value = $this->getByte();
|
|
||||||
break;
|
|
||||||
case EntityMetadataTypes::SHORT:
|
|
||||||
$value = $this->getSignedLShort();
|
|
||||||
break;
|
|
||||||
case EntityMetadataTypes::INT:
|
|
||||||
$value = $this->getVarInt();
|
|
||||||
break;
|
|
||||||
case EntityMetadataTypes::FLOAT:
|
|
||||||
$value = $this->getLFloat();
|
|
||||||
break;
|
|
||||||
case EntityMetadataTypes::STRING:
|
|
||||||
$value = $this->getString();
|
|
||||||
break;
|
|
||||||
case EntityMetadataTypes::SLOT:
|
|
||||||
$value = $this->getSlot();
|
|
||||||
break;
|
|
||||||
case EntityMetadataTypes::POS:
|
|
||||||
$value = new Vector3();
|
|
||||||
$this->getSignedBlockPosition($value->x, $value->y, $value->z);
|
|
||||||
break;
|
|
||||||
case EntityMetadataTypes::LONG:
|
|
||||||
$value = $this->getVarLong();
|
|
||||||
break;
|
|
||||||
case EntityMetadataTypes::VECTOR3F:
|
|
||||||
$value = $this->getVector3();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new BadPacketException("Unknown entity metadata type " . $type);
|
|
||||||
}
|
|
||||||
if($types){
|
|
||||||
$data[$key] = [$type, $value];
|
|
||||||
}else{
|
|
||||||
$data[$key] = $value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function readMetadataProperty(int $type) : MetadataProperty{
|
||||||
|
switch($type){
|
||||||
|
case ByteMetadataProperty::id(): return ByteMetadataProperty::read($this);
|
||||||
|
case ShortMetadataProperty::id(): return ShortMetadataProperty::read($this);
|
||||||
|
case IntMetadataProperty::id(): return IntMetadataProperty::read($this);
|
||||||
|
case FloatMetadataProperty::id(): return FloatMetadataProperty::read($this);
|
||||||
|
case StringMetadataProperty::id(): return StringMetadataProperty::read($this);
|
||||||
|
case ItemStackMetadataProperty::id(): return ItemStackMetadataProperty::read($this);
|
||||||
|
case BlockPosMetadataProperty::id(): return BlockPosMetadataProperty::read($this);
|
||||||
|
case LongMetadataProperty::id(): return LongMetadataProperty::read($this);
|
||||||
|
case Vec3MetadataProperty::id(): return Vec3MetadataProperty::read($this);
|
||||||
|
default:
|
||||||
|
throw new BadPacketException("Unknown entity metadata type " . $type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes entity metadata to the packet buffer.
|
* Writes entity metadata to the packet buffer.
|
||||||
*
|
*
|
||||||
* @param array $metadata
|
* @param MetadataProperty[] $metadata
|
||||||
*/
|
*/
|
||||||
public function putEntityMetadata(array $metadata) : void{
|
public function putEntityMetadata(array $metadata) : void{
|
||||||
$this->putUnsignedVarInt(count($metadata));
|
$this->putUnsignedVarInt(count($metadata));
|
||||||
foreach($metadata as $key => $d){
|
foreach($metadata as $key => $d){
|
||||||
$this->putUnsignedVarInt($key); //data key
|
$this->putUnsignedVarInt($key);
|
||||||
$this->putUnsignedVarInt($d[0]); //data type
|
$this->putUnsignedVarInt($d::id());
|
||||||
switch($d[0]){
|
$d->write($this);
|
||||||
case EntityMetadataTypes::BYTE:
|
|
||||||
$this->putByte($d[1]);
|
|
||||||
break;
|
|
||||||
case EntityMetadataTypes::SHORT:
|
|
||||||
$this->putLShort($d[1]); //SIGNED short!
|
|
||||||
break;
|
|
||||||
case EntityMetadataTypes::INT:
|
|
||||||
$this->putVarInt($d[1]);
|
|
||||||
break;
|
|
||||||
case EntityMetadataTypes::FLOAT:
|
|
||||||
$this->putLFloat($d[1]);
|
|
||||||
break;
|
|
||||||
case EntityMetadataTypes::STRING:
|
|
||||||
$this->putString($d[1]);
|
|
||||||
break;
|
|
||||||
case EntityMetadataTypes::SLOT:
|
|
||||||
$this->putSlot($d[1]);
|
|
||||||
break;
|
|
||||||
case EntityMetadataTypes::POS:
|
|
||||||
$v = $d[1];
|
|
||||||
if($v !== null){
|
|
||||||
$this->putSignedBlockPosition($v->x, $v->y, $v->z);
|
|
||||||
}else{
|
|
||||||
$this->putSignedBlockPosition(0, 0, 0);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case EntityMetadataTypes::LONG:
|
|
||||||
$this->putVarLong($d[1]);
|
|
||||||
break;
|
|
||||||
case EntityMetadataTypes::VECTOR3F:
|
|
||||||
$this->putVector3Nullable($d[1]);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new \InvalidArgumentException("Invalid data type " . $d[0]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -752,12 +752,11 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener,
|
|||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function isUsingItem() : bool{
|
public function isUsingItem() : bool{
|
||||||
return $this->getGenericFlag(EntityMetadataFlags::ACTION) and $this->startAction > -1;
|
return $this->startAction > -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setUsingItem(bool $value){
|
public function setUsingItem(bool $value){
|
||||||
$this->startAction = $value ? $this->server->getTick() : -1;
|
$this->startAction = $value ? $this->server->getTick() : -1;
|
||||||
$this->setGenericFlag(EntityMetadataFlags::ACTION, $value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1078,10 +1077,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener,
|
|||||||
$b->setOccupied();
|
$b->setOccupied();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->sleeping = clone $pos;
|
$this->sleeping = $pos;
|
||||||
|
|
||||||
$this->propertyManager->setBlockPos(EntityMetadataProperties::PLAYER_BED_POSITION, $pos);
|
|
||||||
$this->setPlayerFlag(PlayerMetadataFlags::SLEEP, true);
|
|
||||||
|
|
||||||
$this->setSpawn($pos);
|
$this->setSpawn($pos);
|
||||||
|
|
||||||
@ -1099,8 +1095,6 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener,
|
|||||||
(new PlayerBedLeaveEvent($this, $b))->call();
|
(new PlayerBedLeaveEvent($this, $b))->call();
|
||||||
|
|
||||||
$this->sleeping = null;
|
$this->sleeping = null;
|
||||||
$this->propertyManager->setBlockPos(EntityMetadataProperties::PLAYER_BED_POSITION, null);
|
|
||||||
$this->setPlayerFlag(PlayerMetadataFlags::SLEEP, false);
|
|
||||||
|
|
||||||
$this->world->setSleepTicks(0);
|
$this->world->setSleepTicks(0);
|
||||||
|
|
||||||
@ -2367,6 +2361,15 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener,
|
|||||||
parent::attack($source);
|
parent::attack($source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function syncNetworkData() : void{
|
||||||
|
parent::syncNetworkData();
|
||||||
|
|
||||||
|
$this->propertyManager->setGenericFlag(EntityMetadataFlags::ACTION, $this->startAction > -1);
|
||||||
|
|
||||||
|
$this->propertyManager->setPlayerFlag(PlayerMetadataFlags::SLEEP, $this->sleeping !== null);
|
||||||
|
$this->propertyManager->setBlockPos(EntityMetadataProperties::PLAYER_BED_POSITION, $this->sleeping ?? new Vector3(0, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
public function broadcastEntityEvent(int $eventId, ?int $eventData = null, ?array $players = null) : void{
|
public function broadcastEntityEvent(int $eventId, ?int $eventData = null, ?array $players = null) : void{
|
||||||
if($this->spawned and $players === null){
|
if($this->spawned and $players === null){
|
||||||
$players = $this->getViewers();
|
$players = $this->getViewers();
|
||||||
|
@ -32,7 +32,8 @@ use pocketmine\network\mcpe\protocol\PlayerListPacket;
|
|||||||
use pocketmine\network\mcpe\protocol\RemoveActorPacket;
|
use pocketmine\network\mcpe\protocol\RemoveActorPacket;
|
||||||
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataFlags;
|
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataFlags;
|
||||||
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataProperties;
|
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataProperties;
|
||||||
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataTypes;
|
use pocketmine\network\mcpe\protocol\types\entity\FloatMetadataProperty;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\entity\LongMetadataProperty;
|
||||||
use pocketmine\network\mcpe\protocol\types\PlayerListEntry;
|
use pocketmine\network\mcpe\protocol\types\PlayerListEntry;
|
||||||
use pocketmine\utils\UUID;
|
use pocketmine\utils\UUID;
|
||||||
use function str_repeat;
|
use function str_repeat;
|
||||||
@ -104,8 +105,8 @@ class FloatingTextParticle implements Particle{
|
|||||||
1 << EntityMetadataFlags::IMMOBILE
|
1 << EntityMetadataFlags::IMMOBILE
|
||||||
);
|
);
|
||||||
$pk->metadata = [
|
$pk->metadata = [
|
||||||
EntityMetadataProperties::FLAGS => [EntityMetadataTypes::LONG, $flags],
|
EntityMetadataProperties::FLAGS => new LongMetadataProperty($flags),
|
||||||
EntityMetadataProperties::SCALE => [EntityMetadataTypes::FLOAT, 0.01] //zero causes problems on debug builds
|
EntityMetadataProperties::SCALE => new FloatMetadataProperty(0.01) //zero causes problems on debug builds
|
||||||
];
|
];
|
||||||
|
|
||||||
$p[] = $pk;
|
$p[] = $pk;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user