diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index a3e8e1378..956139527 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -3590,6 +3590,14 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ } } + protected function onDeathUpdate(int $tickDiff) : bool{ + if(parent::onDeathUpdate($tickDiff)){ + $this->despawnFromAll(); //non-player entities rely on close() to do this for them + } + + return false; //never flag players for despawn + } + public function attack(EntityDamageEvent $source){ if(!$this->isAlive()){ return; diff --git a/src/pocketmine/entity/Entity.php b/src/pocketmine/entity/Entity.php index 3d4bd6a62..1d1068c76 100644 --- a/src/pocketmine/entity/Entity.php +++ b/src/pocketmine/entity/Entity.php @@ -393,10 +393,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{ /** @var bool */ public $onGround; /** @var int */ - public $deadTicks = 0; - /** @var int */ - protected $maxDeadTicks = 0; - /** @var int */ protected $age = 0; /** @var float */ @@ -878,6 +874,16 @@ abstract class Entity extends Location implements Metadatable, EntityIds{ $this->scheduleUpdate(); } + /** + * Called to tick entities while dead. Returns whether the entity should be flagged for despawn yet. + * + * @param int $tickDiff + * @return bool + */ + protected function onDeathUpdate(int $tickDiff) : bool{ + return true; + } + public function isAlive() : bool{ return $this->health > 0; } @@ -1267,13 +1273,10 @@ abstract class Entity extends Location implements Metadatable, EntityIds{ } if(!$this->isAlive()){ - $this->deadTicks += $tickDiff; - if($this->deadTicks >= $this->maxDeadTicks){ - $this->despawnFromAll(); - if(!$this->isPlayer){ - $this->flagForDespawn(); - } + if($this->onDeathUpdate($tickDiff)){ + $this->flagForDespawn(); } + return true; } diff --git a/src/pocketmine/entity/Living.php b/src/pocketmine/entity/Living.php index 6df27765f..e2bcc2098 100644 --- a/src/pocketmine/entity/Living.php +++ b/src/pocketmine/entity/Living.php @@ -50,6 +50,8 @@ abstract class Living extends Entity implements Damageable{ protected $attackTime = 0; + /** @var int */ + public $deadTicks = 0; /** @var int */ protected $maxDeadTicks = 20; @@ -377,11 +379,19 @@ abstract class Living extends Entity implements Damageable{ $this->setAbsorption(max(0, $this->getAbsorption() + $source->getDamage(EntityDamageEvent::MODIFIER_ABSORPTION))); - $this->broadcastEntityEvent($this->getHealth() <= 0 ? EntityEventPacket::DEATH_ANIMATION : EntityEventPacket::HURT_ANIMATION); //Ouch! + if($this->isAlive()){ + $this->doHitAnimation(); + }else{ + $this->startDeathAnimation(); + } $this->attackTime = 10; //0.5 seconds cooldown } + protected function doHitAnimation() : void{ + $this->broadcastEntityEvent(EntityEventPacket::HURT_ANIMATION); + } + public function knockBack(Entity $attacker, float $damage, float $x, float $z, float $base = 0.4){ $f = sqrt($x * $x + $z * $z); if($f <= 0){ @@ -421,6 +431,26 @@ abstract class Living extends Entity implements Damageable{ } } + protected function onDeathUpdate(int $tickDiff) : bool{ + if($this->deadTicks < $this->maxDeadTicks){ + $this->deadTicks += $tickDiff; + if($this->deadTicks >= $this->maxDeadTicks){ + $this->endDeathAnimation(); + //TODO: spawn experience orbs here + } + } + + return $this->deadTicks >= 20; + } + + protected function startDeathAnimation() : void{ + $this->broadcastEntityEvent(EntityEventPacket::DEATH_ANIMATION); + } + + protected function endDeathAnimation() : void{ + //TODO + } + public function entityBaseTick(int $tickDiff = 1) : bool{ Timings::$timerLivingEntityBaseTick->startTiming();