mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-22 08:44:01 +00:00
Re-organise some Entity methods
This commit is contained in:
parent
50be26958a
commit
0a19a2611a
@ -844,81 +844,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Player[]
|
||||
*/
|
||||
public function getViewers() : array{
|
||||
return $this->hasSpawned;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Player $player
|
||||
*/
|
||||
public function spawnTo(Player $player){
|
||||
if(!isset($this->hasSpawned[$player->getLoaderId()]) and isset($player->usedChunks[Level::chunkHash($this->chunk->getX(), $this->chunk->getZ())])){
|
||||
$this->hasSpawned[$player->getLoaderId()] = $player;
|
||||
|
||||
$this->sendSpawnPacket($player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by spawnTo() to send whatever packets needed to spawn the entity to the client.
|
||||
* @param Player $player
|
||||
*/
|
||||
protected function sendSpawnPacket(Player $player) : void{
|
||||
$pk = new AddEntityPacket();
|
||||
$pk->entityRuntimeId = $this->getId();
|
||||
$pk->type = static::NETWORK_ID;
|
||||
$pk->position = $this->asVector3();
|
||||
$pk->motion = $this->getMotion();
|
||||
$pk->yaw = $this->yaw;
|
||||
$pk->pitch = $this->pitch;
|
||||
$pk->metadata = $this->dataProperties;
|
||||
|
||||
$player->dataPacket($pk);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Player[]|Player $player
|
||||
* @param array $data Properly formatted entity data, defaults to everything
|
||||
*/
|
||||
public function sendData($player, array $data = null){
|
||||
if(!is_array($player)){
|
||||
$player = [$player];
|
||||
}
|
||||
|
||||
$pk = new SetEntityDataPacket();
|
||||
$pk->entityRuntimeId = $this->getId();
|
||||
$pk->metadata = $data ?? $this->dataProperties;
|
||||
|
||||
foreach($player as $p){
|
||||
if($p === $this){
|
||||
continue;
|
||||
}
|
||||
$p->dataPacket(clone $pk);
|
||||
}
|
||||
|
||||
if($this instanceof Player){
|
||||
$this->dataPacket($pk);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Player $player
|
||||
* @param bool $send
|
||||
*/
|
||||
public function despawnFrom(Player $player, bool $send = true){
|
||||
if(isset($this->hasSpawned[$player->getLoaderId()])){
|
||||
if($send){
|
||||
$pk = new RemoveEntityPacket();
|
||||
$pk->entityUniqueId = $this->id;
|
||||
$player->dataPacket($pk);
|
||||
}
|
||||
unset($this->hasSpawned[$player->getLoaderId()]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EntityDamageEvent $source
|
||||
*/
|
||||
@ -945,6 +870,15 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
$this->setHealth($this->getHealth() + $source->getAmount());
|
||||
}
|
||||
|
||||
public function kill(){
|
||||
$this->health = 0;
|
||||
$this->scheduleUpdate();
|
||||
}
|
||||
|
||||
public function isAlive() : bool{
|
||||
return $this->health > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
@ -952,10 +886,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
return $this->health;
|
||||
}
|
||||
|
||||
public function isAlive() : bool{
|
||||
return $this->health > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the health of the Entity. This won't send any update to the players
|
||||
*
|
||||
@ -977,6 +907,20 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getMaxHealth() : int{
|
||||
return $this->maxHealth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $amount
|
||||
*/
|
||||
public function setMaxHealth(int $amount){
|
||||
$this->maxHealth = $amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EntityDamageEvent $type
|
||||
*/
|
||||
@ -995,24 +939,177 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
return $this->attributeMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getMaxHealth() : int{
|
||||
return $this->maxHealth;
|
||||
public function entityBaseTick(int $tickDiff = 1) : bool{
|
||||
//TODO: check vehicles
|
||||
|
||||
$this->justCreated = false;
|
||||
|
||||
if(count($this->changedDataProperties) > 0){
|
||||
$this->sendData($this->hasSpawned, $this->changedDataProperties);
|
||||
$this->changedDataProperties = [];
|
||||
}
|
||||
|
||||
$hasUpdate = false;
|
||||
|
||||
$this->checkBlockCollision();
|
||||
|
||||
if($this->y <= -16 and $this->isAlive()){
|
||||
$ev = new EntityDamageEvent($this, EntityDamageEvent::CAUSE_VOID, 10);
|
||||
$this->attack($ev);
|
||||
$hasUpdate = true;
|
||||
}
|
||||
|
||||
if($this->isOnFire()){
|
||||
$hasUpdate = ($hasUpdate || $this->doOnFireTick($tickDiff));
|
||||
}
|
||||
|
||||
if($this->noDamageTicks > 0){
|
||||
$this->noDamageTicks -= $tickDiff;
|
||||
if($this->noDamageTicks < 0){
|
||||
$this->noDamageTicks = 0;
|
||||
}
|
||||
}
|
||||
|
||||
$this->age += $tickDiff;
|
||||
$this->ticksLived += $tickDiff;
|
||||
|
||||
return $hasUpdate;
|
||||
}
|
||||
|
||||
public function isOnFire() : bool{
|
||||
return $this->fireTicks > 0;
|
||||
}
|
||||
|
||||
public function setOnFire(int $seconds){
|
||||
$ticks = $seconds * 20;
|
||||
if($ticks > $this->fireTicks){
|
||||
$this->fireTicks = $ticks;
|
||||
}
|
||||
|
||||
$this->setGenericFlag(self::DATA_FLAG_ONFIRE, true);
|
||||
}
|
||||
|
||||
public function extinguish(){
|
||||
$this->fireTicks = 0;
|
||||
$this->setGenericFlag(self::DATA_FLAG_ONFIRE, false);
|
||||
}
|
||||
|
||||
public function isFireProof() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function doOnFireTick(int $tickDiff = 1) : bool{
|
||||
if($this->isFireProof() and $this->fireTicks > 1){
|
||||
$this->fireTicks = 1;
|
||||
}else{
|
||||
$this->fireTicks -= $tickDiff;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(($this->fireTicks % 20 === 0) or $tickDiff > 20){
|
||||
$this->dealFireDamage();
|
||||
}
|
||||
|
||||
if(!$this->isOnFire()){
|
||||
$this->extinguish();
|
||||
}else{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $amount
|
||||
* Called to deal damage to entities when they are on fire.
|
||||
*/
|
||||
public function setMaxHealth(int $amount){
|
||||
$this->maxHealth = $amount;
|
||||
protected function dealFireDamage(){
|
||||
$ev = new EntityDamageEvent($this, EntityDamageEvent::CAUSE_FIRE_TICK, 1);
|
||||
$this->attack($ev);
|
||||
}
|
||||
|
||||
public function canCollideWith(Entity $entity) : bool{
|
||||
return !$this->justCreated and $entity !== $this;
|
||||
}
|
||||
|
||||
protected function updateMovement(){
|
||||
$diffPosition = ($this->x - $this->lastX) ** 2 + ($this->y - $this->lastY) ** 2 + ($this->z - $this->lastZ) ** 2;
|
||||
$diffRotation = ($this->yaw - $this->lastYaw) ** 2 + ($this->pitch - $this->lastPitch) ** 2;
|
||||
|
||||
$diffMotion = ($this->motionX - $this->lastMotionX) ** 2 + ($this->motionY - $this->lastMotionY) ** 2 + ($this->motionZ - $this->lastMotionZ) ** 2;
|
||||
|
||||
if($diffPosition > 0.0001 or $diffRotation > 1.0){
|
||||
$this->lastX = $this->x;
|
||||
$this->lastY = $this->y;
|
||||
$this->lastZ = $this->z;
|
||||
|
||||
$this->lastYaw = $this->yaw;
|
||||
$this->lastPitch = $this->pitch;
|
||||
|
||||
$this->broadcastMovement();
|
||||
}
|
||||
|
||||
if($diffMotion > 0.0025 or ($diffMotion > 0.0001 and $this->getMotion()->lengthSquared() <= 0.0001)){ //0.05 ** 2
|
||||
$this->lastMotionX = $this->motionX;
|
||||
$this->lastMotionY = $this->motionY;
|
||||
$this->lastMotionZ = $this->motionZ;
|
||||
|
||||
$this->broadcastMotion();
|
||||
}
|
||||
}
|
||||
|
||||
public function getOffsetPosition(Vector3 $vector3) : Vector3{
|
||||
return new Vector3($vector3->x, $vector3->y + $this->baseOffset, $vector3->z);
|
||||
}
|
||||
|
||||
protected function broadcastMovement(){
|
||||
$pk = new MoveEntityPacket();
|
||||
$pk->entityRuntimeId = $this->id;
|
||||
$pk->position = $this->getOffsetPosition($this);
|
||||
$pk->yaw = $this->yaw;
|
||||
$pk->pitch = $this->pitch;
|
||||
$pk->headYaw = $this->yaw; //TODO
|
||||
|
||||
$this->level->addChunkPacket($this->chunk->getX(), $this->chunk->getZ(), $pk);
|
||||
}
|
||||
|
||||
protected function broadcastMotion(){
|
||||
$pk = new SetEntityMotionPacket();
|
||||
$pk->entityRuntimeId = $this->id;
|
||||
$pk->motion = $this->getMotion();
|
||||
|
||||
$this->level->addChunkPacket($this->chunk->getX(), $this->chunk->getZ(), $pk);
|
||||
}
|
||||
|
||||
protected function applyDragBeforeGravity() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function applyGravity(){
|
||||
$this->motionY -= $this->gravity;
|
||||
}
|
||||
|
||||
protected function tryChangeMovement(){
|
||||
$friction = 1 - $this->drag;
|
||||
|
||||
if($this->applyDragBeforeGravity()){
|
||||
$this->motionY *= $friction;
|
||||
}
|
||||
|
||||
$this->applyGravity();
|
||||
|
||||
if(!$this->applyDragBeforeGravity()){
|
||||
$this->motionY *= $friction;
|
||||
}
|
||||
|
||||
if($this->onGround){
|
||||
$friction *= $this->level->getBlock($this->floor()->subtract(0, 1, 0))->getFrictionFactor();
|
||||
}
|
||||
|
||||
$this->motionX *= $friction;
|
||||
$this->motionZ *= $friction;
|
||||
}
|
||||
|
||||
protected function checkObstruction(float $x, float $y, float $z) : bool{
|
||||
if(count($this->level->getCollisionCubes($this, $this->getBoundingBox(), false)) === 0){
|
||||
return false;
|
||||
@ -1108,151 +1205,27 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function entityBaseTick(int $tickDiff = 1) : bool{
|
||||
//TODO: check vehicles
|
||||
|
||||
$this->justCreated = false;
|
||||
|
||||
if(count($this->changedDataProperties) > 0){
|
||||
$this->sendData($this->hasSpawned, $this->changedDataProperties);
|
||||
$this->changedDataProperties = [];
|
||||
}
|
||||
|
||||
$hasUpdate = false;
|
||||
|
||||
$this->checkBlockCollision();
|
||||
|
||||
if($this->y <= -16 and $this->isAlive()){
|
||||
$ev = new EntityDamageEvent($this, EntityDamageEvent::CAUSE_VOID, 10);
|
||||
$this->attack($ev);
|
||||
$hasUpdate = true;
|
||||
}
|
||||
|
||||
if($this->isOnFire()){
|
||||
$hasUpdate = ($hasUpdate || $this->doOnFireTick($tickDiff));
|
||||
}
|
||||
|
||||
if($this->noDamageTicks > 0){
|
||||
$this->noDamageTicks -= $tickDiff;
|
||||
if($this->noDamageTicks < 0){
|
||||
$this->noDamageTicks = 0;
|
||||
}
|
||||
}
|
||||
|
||||
$this->age += $tickDiff;
|
||||
$this->ticksLived += $tickDiff;
|
||||
|
||||
return $hasUpdate;
|
||||
}
|
||||
|
||||
protected function doOnFireTick(int $tickDiff = 1) : bool{
|
||||
if($this->isFireProof() and $this->fireTicks > 1){
|
||||
$this->fireTicks = 1;
|
||||
}else{
|
||||
$this->fireTicks -= $tickDiff;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(($this->fireTicks % 20 === 0) or $tickDiff > 20){
|
||||
$this->dealFireDamage();
|
||||
}
|
||||
|
||||
if(!$this->isOnFire()){
|
||||
$this->extinguish();
|
||||
}else{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to deal damage to entities when they are on fire.
|
||||
* @return int|null
|
||||
*/
|
||||
protected function dealFireDamage(){
|
||||
$ev = new EntityDamageEvent($this, EntityDamageEvent::CAUSE_FIRE_TICK, 1);
|
||||
$this->attack($ev);
|
||||
}
|
||||
|
||||
protected function updateMovement(){
|
||||
$diffPosition = ($this->x - $this->lastX) ** 2 + ($this->y - $this->lastY) ** 2 + ($this->z - $this->lastZ) ** 2;
|
||||
$diffRotation = ($this->yaw - $this->lastYaw) ** 2 + ($this->pitch - $this->lastPitch) ** 2;
|
||||
|
||||
$diffMotion = ($this->motionX - $this->lastMotionX) ** 2 + ($this->motionY - $this->lastMotionY) ** 2 + ($this->motionZ - $this->lastMotionZ) ** 2;
|
||||
|
||||
if($diffPosition > 0.0001 or $diffRotation > 1.0){
|
||||
$this->lastX = $this->x;
|
||||
$this->lastY = $this->y;
|
||||
$this->lastZ = $this->z;
|
||||
|
||||
$this->lastYaw = $this->yaw;
|
||||
$this->lastPitch = $this->pitch;
|
||||
|
||||
$this->broadcastMovement();
|
||||
public function getDirection(){
|
||||
$rotation = ($this->yaw - 90) % 360;
|
||||
if($rotation < 0){
|
||||
$rotation += 360.0;
|
||||
}
|
||||
|
||||
if($diffMotion > 0.0025 or ($diffMotion > 0.0001 and $this->getMotion()->lengthSquared() <= 0.0001)){ //0.05 ** 2
|
||||
$this->lastMotionX = $this->motionX;
|
||||
$this->lastMotionY = $this->motionY;
|
||||
$this->lastMotionZ = $this->motionZ;
|
||||
|
||||
$this->broadcastMotion();
|
||||
if((0 <= $rotation and $rotation < 45) or (315 <= $rotation and $rotation < 360)){
|
||||
return 2; //North
|
||||
}elseif(45 <= $rotation and $rotation < 135){
|
||||
return 3; //East
|
||||
}elseif(135 <= $rotation and $rotation < 225){
|
||||
return 0; //South
|
||||
}elseif(225 <= $rotation and $rotation < 315){
|
||||
return 1; //West
|
||||
}else{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public function getOffsetPosition(Vector3 $vector3) : Vector3{
|
||||
return new Vector3($vector3->x, $vector3->y + $this->baseOffset, $vector3->z);
|
||||
}
|
||||
|
||||
protected function broadcastMovement(){
|
||||
$pk = new MoveEntityPacket();
|
||||
$pk->entityRuntimeId = $this->id;
|
||||
$pk->position = $this->getOffsetPosition($this);
|
||||
$pk->yaw = $this->yaw;
|
||||
$pk->pitch = $this->pitch;
|
||||
$pk->headYaw = $this->yaw; //TODO
|
||||
|
||||
$this->level->addChunkPacket($this->chunk->getX(), $this->chunk->getZ(), $pk);
|
||||
}
|
||||
|
||||
protected function broadcastMotion(){
|
||||
$pk = new SetEntityMotionPacket();
|
||||
$pk->entityRuntimeId = $this->id;
|
||||
$pk->motion = $this->getMotion();
|
||||
|
||||
$this->level->addChunkPacket($this->chunk->getX(), $this->chunk->getZ(), $pk);
|
||||
}
|
||||
|
||||
protected function applyDragBeforeGravity() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function applyGravity(){
|
||||
$this->motionY -= $this->gravity;
|
||||
}
|
||||
|
||||
protected function tryChangeMovement(){
|
||||
$friction = 1 - $this->drag;
|
||||
|
||||
if($this->applyDragBeforeGravity()){
|
||||
$this->motionY *= $friction;
|
||||
}
|
||||
|
||||
$this->applyGravity();
|
||||
|
||||
if(!$this->applyDragBeforeGravity()){
|
||||
$this->motionY *= $friction;
|
||||
}
|
||||
|
||||
if($this->onGround){
|
||||
$friction *= $this->level->getBlock($this->floor()->subtract(0, 1, 0))->getFrictionFactor();
|
||||
}
|
||||
|
||||
$this->motionX *= $friction;
|
||||
$this->motionZ *= $friction;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Vector3
|
||||
*/
|
||||
@ -1360,49 +1333,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
);
|
||||
}
|
||||
|
||||
public function isOnFire() : bool{
|
||||
return $this->fireTicks > 0;
|
||||
}
|
||||
|
||||
public function setOnFire(int $seconds){
|
||||
$ticks = $seconds * 20;
|
||||
if($ticks > $this->fireTicks){
|
||||
$this->fireTicks = $ticks;
|
||||
}
|
||||
|
||||
$this->setGenericFlag(self::DATA_FLAG_ONFIRE, true);
|
||||
}
|
||||
|
||||
public function extinguish(){
|
||||
$this->fireTicks = 0;
|
||||
$this->setGenericFlag(self::DATA_FLAG_ONFIRE, false);
|
||||
}
|
||||
|
||||
public function isFireProof() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|null
|
||||
*/
|
||||
public function getDirection(){
|
||||
$rotation = ($this->yaw - 90) % 360;
|
||||
if($rotation < 0){
|
||||
$rotation += 360.0;
|
||||
}
|
||||
if((0 <= $rotation and $rotation < 45) or (315 <= $rotation and $rotation < 360)){
|
||||
return 2; //North
|
||||
}elseif(45 <= $rotation and $rotation < 135){
|
||||
return 3; //East
|
||||
}elseif(135 <= $rotation and $rotation < 225){
|
||||
return 0; //South
|
||||
}elseif(225 <= $rotation and $rotation < 315){
|
||||
return 1; //West
|
||||
}else{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public function canTriggerWalking() : bool{
|
||||
return true;
|
||||
}
|
||||
@ -1451,39 +1381,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
|
||||
}
|
||||
|
||||
protected function switchLevel(Level $targetLevel) : bool{
|
||||
if($this->closed){
|
||||
return false;
|
||||
}
|
||||
|
||||
if($this->isValid()){
|
||||
$this->server->getPluginManager()->callEvent($ev = new EntityLevelChangeEvent($this, $this->level, $targetLevel));
|
||||
if($ev->isCancelled()){
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->level->removeEntity($this);
|
||||
if($this->chunk !== null){
|
||||
$this->chunk->removeEntity($this);
|
||||
}
|
||||
$this->despawnFromAll();
|
||||
}
|
||||
|
||||
$this->setLevel($targetLevel);
|
||||
$this->level->addEntity($this);
|
||||
$this->chunk = null;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getPosition() : Position{
|
||||
return $this->asPosition();
|
||||
}
|
||||
|
||||
public function getLocation() : Location{
|
||||
return $this->asLocation();
|
||||
}
|
||||
|
||||
public function isInsideOfWater() : bool{
|
||||
$block = $this->level->getBlock($this->temporalVector->setComponents(Math::floorFloat($this->x), Math::floorFloat($y = ($this->y + $this->getEyeHeight())), Math::floorFloat($this->z)));
|
||||
|
||||
@ -1756,6 +1653,43 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
}
|
||||
}
|
||||
|
||||
public function getPosition() : Position{
|
||||
return $this->asPosition();
|
||||
}
|
||||
|
||||
public function getLocation() : Location{
|
||||
return $this->asLocation();
|
||||
}
|
||||
|
||||
public function setPosition(Vector3 $pos){
|
||||
if($this->closed){
|
||||
return false;
|
||||
}
|
||||
|
||||
if($pos instanceof Position and $pos->level !== null and $pos->level !== $this->level){
|
||||
if($this->switchLevel($pos->getLevel()) === false){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$this->x = $pos->x;
|
||||
$this->y = $pos->y;
|
||||
$this->z = $pos->z;
|
||||
|
||||
$radius = $this->width / 2;
|
||||
$this->boundingBox->setBounds($pos->x - $radius, $pos->y, $pos->z - $radius, $pos->x + $radius, $pos->y + $this->height, $pos->z + $radius);
|
||||
|
||||
$this->checkChunks();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function setRotation(float $yaw, float $pitch){
|
||||
$this->yaw = $yaw;
|
||||
$this->pitch = $pitch;
|
||||
$this->scheduleUpdate();
|
||||
}
|
||||
|
||||
public function setPositionAndRotation(Vector3 $pos, float $yaw, float $pitch) : bool{
|
||||
if($this->setPosition($pos) === true){
|
||||
$this->setRotation($yaw, $pitch);
|
||||
@ -1766,12 +1700,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function setRotation(float $yaw, float $pitch){
|
||||
$this->yaw = $yaw;
|
||||
$this->pitch = $pitch;
|
||||
$this->scheduleUpdate();
|
||||
}
|
||||
|
||||
protected function checkChunks(){
|
||||
if($this->chunk === null or ($this->chunk->getX() !== ($this->x >> 4) or $this->chunk->getZ() !== ($this->z >> 4))){
|
||||
if($this->chunk !== null){
|
||||
@ -1801,29 +1729,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
}
|
||||
}
|
||||
|
||||
public function setPosition(Vector3 $pos){
|
||||
if($this->closed){
|
||||
return false;
|
||||
}
|
||||
|
||||
if($pos instanceof Position and $pos->level !== null and $pos->level !== $this->level){
|
||||
if($this->switchLevel($pos->getLevel()) === false){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$this->x = $pos->x;
|
||||
$this->y = $pos->y;
|
||||
$this->z = $pos->z;
|
||||
|
||||
$radius = $this->width / 2;
|
||||
$this->boundingBox->setBounds($pos->x - $radius, $pos->y, $pos->z - $radius, $pos->x + $radius, $pos->y + $this->height, $pos->z + $radius);
|
||||
|
||||
$this->checkChunks();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function resetLastMovements(){
|
||||
list($this->lastX, $this->lastY, $this->lastZ) = [$this->x, $this->y, $this->z];
|
||||
list($this->lastYaw, $this->lastPitch) = [$this->yaw, $this->pitch];
|
||||
@ -1857,11 +1762,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
return $this->onGround === true;
|
||||
}
|
||||
|
||||
public function kill(){
|
||||
$this->health = 0;
|
||||
$this->scheduleUpdate();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Vector3|Position|Location $pos
|
||||
* @param float|null $yaw
|
||||
@ -1903,14 +1803,68 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function switchLevel(Level $targetLevel) : bool{
|
||||
if($this->closed){
|
||||
return false;
|
||||
}
|
||||
|
||||
if($this->isValid()){
|
||||
$this->server->getPluginManager()->callEvent($ev = new EntityLevelChangeEvent($this, $this->level, $targetLevel));
|
||||
if($ev->isCancelled()){
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->level->removeEntity($this);
|
||||
if($this->chunk !== null){
|
||||
$this->chunk->removeEntity($this);
|
||||
}
|
||||
$this->despawnFromAll();
|
||||
}
|
||||
|
||||
$this->setLevel($targetLevel);
|
||||
$this->level->addEntity($this);
|
||||
$this->chunk = null;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getId() : int{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function respawnToAll(){
|
||||
foreach($this->hasSpawned as $key => $player){
|
||||
unset($this->hasSpawned[$key]);
|
||||
$this->spawnTo($player);
|
||||
/**
|
||||
* @return Player[]
|
||||
*/
|
||||
public function getViewers() : array{
|
||||
return $this->hasSpawned;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by spawnTo() to send whatever packets needed to spawn the entity to the client.
|
||||
*
|
||||
* @param Player $player
|
||||
*/
|
||||
protected function sendSpawnPacket(Player $player) : void{
|
||||
$pk = new AddEntityPacket();
|
||||
$pk->entityRuntimeId = $this->getId();
|
||||
$pk->type = static::NETWORK_ID;
|
||||
$pk->position = $this->asVector3();
|
||||
$pk->motion = $this->getMotion();
|
||||
$pk->yaw = $this->yaw;
|
||||
$pk->pitch = $this->pitch;
|
||||
$pk->metadata = $this->dataProperties;
|
||||
|
||||
$player->dataPacket($pk);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Player $player
|
||||
*/
|
||||
public function spawnTo(Player $player){
|
||||
if(!isset($this->hasSpawned[$player->getLoaderId()]) and isset($player->usedChunks[Level::chunkHash($this->chunk->getX(), $this->chunk->getZ())])){
|
||||
$this->hasSpawned[$player->getLoaderId()] = $player;
|
||||
|
||||
$this->sendSpawnPacket($player);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1925,6 +1879,28 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
}
|
||||
}
|
||||
|
||||
public function respawnToAll(){
|
||||
foreach($this->hasSpawned as $key => $player){
|
||||
unset($this->hasSpawned[$key]);
|
||||
$this->spawnTo($player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Player $player
|
||||
* @param bool $send
|
||||
*/
|
||||
public function despawnFrom(Player $player, bool $send = true){
|
||||
if(isset($this->hasSpawned[$player->getLoaderId()])){
|
||||
if($send){
|
||||
$pk = new RemoveEntityPacket();
|
||||
$pk->entityUniqueId = $this->id;
|
||||
$player->dataPacket($pk);
|
||||
}
|
||||
unset($this->hasSpawned[$player->getLoaderId()]);
|
||||
}
|
||||
}
|
||||
|
||||
public function despawnFromAll(){
|
||||
foreach($this->hasSpawned as $player){
|
||||
$this->despawnFrom($player);
|
||||
@ -2054,11 +2030,35 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
$this->setDataFlag(self::DATA_FLAGS, $flagId, $value, self::DATA_TYPE_LONG);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Player[]|Player $player
|
||||
* @param array $data Properly formatted entity data, defaults to everything
|
||||
*/
|
||||
public function sendData($player, array $data = null){
|
||||
if(!is_array($player)){
|
||||
$player = [$player];
|
||||
}
|
||||
|
||||
$pk = new SetEntityDataPacket();
|
||||
$pk->entityRuntimeId = $this->getId();
|
||||
$pk->metadata = $data ?? $this->dataProperties;
|
||||
|
||||
foreach($player as $p){
|
||||
if($p === $this){
|
||||
continue;
|
||||
}
|
||||
$p->dataPacket(clone $pk);
|
||||
}
|
||||
|
||||
if($this instanceof Player){
|
||||
$this->dataPacket($pk);
|
||||
}
|
||||
}
|
||||
|
||||
public function __destruct(){
|
||||
$this->close();
|
||||
}
|
||||
|
||||
|
||||
public function setMetadata(string $metadataKey, MetadataValue $newMetadataValue){
|
||||
$this->server->getEntityMetadata()->setMetadata($this, $metadataKey, $newMetadataValue);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user