Use entity IDs in EntityDamageBy*EntityEvents, fixed memory leaks related to PvP/PvE/PvM (#418)

This commit is contained in:
Dylan K. Taylor 2017-03-13 10:30:31 +00:00 committed by GitHub
parent 083d1e9ef8
commit 92193fd27b
8 changed files with 63 additions and 17 deletions

View File

@ -1087,6 +1087,31 @@ class Server{
return true; return true;
} }
/**
* Searches all levels for the entity with the specified ID.
* Useful for tracking entities across multiple worlds without needing strong references.
*
* @param int $entityId
* @param Level|null $expectedLevel Level to look in first for the target
*
* @return Entity|null
*/
public function findEntity(int $entityId, Level $expectedLevel = null){
$levels = $this->levels;
if($expectedLevel !== null){
array_unshift($levels, $expectedLevel);
}
foreach($levels as $level){
assert(!$level->isClosed());
if(($entity = $level->getEntity($entityId)) instanceof Entity){
return $entity;
}
}
return null;
}
/** /**
* @param string $variable * @param string $variable
* @param string $defaultValue * @param string $defaultValue

View File

@ -1652,6 +1652,7 @@ abstract class Entity extends Location implements Metadatable{
} }
$this->namedtag = null; $this->namedtag = null;
$this->lastDamageCause = null;
} }
} }

View File

@ -123,13 +123,15 @@ abstract class Living extends Entity implements Damageable{
$e = $source->getChild(); $e = $source->getChild();
} }
if($e->isOnFire() > 0){ if($e !== null){
$this->setOnFire(2 * $this->server->getDifficulty()); if($e->isOnFire() > 0){
} $this->setOnFire(2 * $this->server->getDifficulty());
}
$deltaX = $this->x - $e->x; $deltaX = $this->x - $e->x;
$deltaZ = $this->z - $e->z; $deltaZ = $this->z - $e->z;
$this->knockBack($e, $damage, $deltaX, $deltaZ, $source->getKnockBack()); $this->knockBack($e, $damage, $deltaX, $deltaZ, $source->getKnockBack());
}
} }
$pk = new EntityEventPacket(); $pk = new EntityEventPacket();

View File

@ -60,7 +60,9 @@ class Squid extends WaterAnimal implements Ageable{
if($source instanceof EntityDamageByEntityEvent){ if($source instanceof EntityDamageByEntityEvent){
$this->swimSpeed = mt_rand(150, 350) / 2000; $this->swimSpeed = mt_rand(150, 350) / 2000;
$e = $source->getDamager(); $e = $source->getDamager();
$this->swimDirection = (new Vector3($this->x - $e->x, $this->y - $e->y, $this->z - $e->z))->normalize(); if($e !== null){
$this->swimDirection = (new Vector3($this->x - $e->x, $this->y - $e->y, $this->z - $e->z))->normalize();
}
$pk = new EntityEventPacket(); $pk = new EntityEventPacket();
$pk->eid = $this->getId(); $pk->eid = $this->getId();

View File

@ -24,6 +24,9 @@ namespace pocketmine\event\entity;
use pocketmine\block\Block; use pocketmine\block\Block;
use pocketmine\entity\Entity; use pocketmine\entity\Entity;
/**
* Called when an entity takes damage from a block.
*/
class EntityDamageByBlockEvent extends EntityDamageEvent{ class EntityDamageByBlockEvent extends EntityDamageEvent{
/** @var Block */ /** @var Block */

View File

@ -23,10 +23,13 @@ namespace pocketmine\event\entity;
use pocketmine\entity\Entity; use pocketmine\entity\Entity;
/**
* Called when an entity takes damage from an entity sourced from another entity, for example being hit by a snowball thrown by a Player.
*/
class EntityDamageByChildEntityEvent extends EntityDamageByEntityEvent{ class EntityDamageByChildEntityEvent extends EntityDamageByEntityEvent{
/** @var Entity */ /** @var int */
private $childEntity; private $childEntityEid;
/** /**
@ -37,15 +40,17 @@ class EntityDamageByChildEntityEvent extends EntityDamageByEntityEvent{
* @param int|int[] $damage * @param int|int[] $damage
*/ */
public function __construct(Entity $damager, Entity $childEntity, Entity $entity, $cause, $damage){ public function __construct(Entity $damager, Entity $childEntity, Entity $entity, $cause, $damage){
$this->childEntity = $childEntity; $this->childEntityEid = $childEntity->getId();
parent::__construct($damager, $entity, $cause, $damage); parent::__construct($damager, $entity, $cause, $damage);
} }
/** /**
* @return Entity * Returns the entity which caused the damage, or null if the entity has been killed or closed.
*
* @return Entity|null
*/ */
public function getChild(){ public function getChild(){
return $this->childEntity; return $this->getEntity()->getLevel()->getServer()->findEntity($this->childEntityEid, $this->getEntity()->getLevel());
} }

View File

@ -24,10 +24,13 @@ namespace pocketmine\event\entity;
use pocketmine\entity\Effect; use pocketmine\entity\Effect;
use pocketmine\entity\Entity; use pocketmine\entity\Entity;
/**
* Called when an entity takes damage from another entity.
*/
class EntityDamageByEntityEvent extends EntityDamageEvent{ class EntityDamageByEntityEvent extends EntityDamageEvent{
/** @var Entity */ /** @var int */
private $damager; private $damagerEid;
/** @var float */ /** @var float */
private $knockBack; private $knockBack;
@ -39,7 +42,7 @@ class EntityDamageByEntityEvent extends EntityDamageEvent{
* @param float $knockBack * @param float $knockBack
*/ */
public function __construct(Entity $damager, Entity $entity, $cause, $damage, $knockBack = 0.4){ public function __construct(Entity $damager, Entity $entity, $cause, $damage, $knockBack = 0.4){
$this->damager = $damager; $this->damagerEid = $damager->getId();
$this->knockBack = $knockBack; $this->knockBack = $knockBack;
parent::__construct($entity, $cause, $damage); parent::__construct($entity, $cause, $damage);
$this->addAttackerModifiers($damager); $this->addAttackerModifiers($damager);
@ -56,10 +59,12 @@ class EntityDamageByEntityEvent extends EntityDamageEvent{
} }
/** /**
* @return Entity * Returns the attacking entity, or null if the attacker has been killed or closed.
*
* @return Entity|null
*/ */
public function getDamager(){ public function getDamager(){
return $this->damager; return $this->getEntity()->getLevel()->getServer()->findEntity($this->damagerEid, $this->getEntity()->getLevel());
} }
/** /**

View File

@ -25,6 +25,9 @@ use pocketmine\entity\Effect;
use pocketmine\entity\Entity; use pocketmine\entity\Entity;
use pocketmine\event\Cancellable; use pocketmine\event\Cancellable;
/**
* Called when an entity takes damage.
*/
class EntityDamageEvent extends EntityEvent implements Cancellable{ class EntityDamageEvent extends EntityEvent implements Cancellable{
public static $handlerList = null; public static $handlerList = null;