add a more flexible hook system to EffectManager

This commit is contained in:
Dylan K. Taylor 2019-08-01 19:36:13 +01:00
parent d09e79e682
commit 7e4236a3ec
4 changed files with 32 additions and 29 deletions

View File

@ -212,24 +212,6 @@ abstract class Living extends Entity{
return $this->effectManager;
}
/**
* @internal
*
* @param EffectInstance $effect
* @param bool $replacesOldEffect
*/
public function onEffectAdded(EffectInstance $effect, bool $replacesOldEffect) : void{
}
/**
* @internal
* @param EffectInstance $effect
*/
public function onEffectRemoved(EffectInstance $effect) : void{
}
/**
* Causes the mob to consume the given Consumable object, applying applicable effects, health bonuses, food bonuses,
* etc.

View File

@ -27,7 +27,9 @@ use pocketmine\entity\Living;
use pocketmine\event\entity\EntityEffectAddEvent;
use pocketmine\event\entity\EntityEffectRemoveEvent;
use pocketmine\utils\Color;
use pocketmine\utils\Utils;
use function abs;
use function spl_object_id;
class EffectManager{
@ -42,6 +44,11 @@ class EffectManager{
/** @var bool */
protected $onlyAmbientEffects = false;
/** @var \Closure[] */
protected $effectAddHooks = [];
/** @var \Closure[] */
protected $effectRemoveHooks = [];
public function __construct(Living $entity){
$this->entity = $entity;
$this->bubbleColor = new Color(0, 0, 0, 0);
@ -78,14 +85,18 @@ class EffectManager{
$ev->call();
if($ev->isCancelled()){
if($hasExpired and !$ev->getEffect()->hasExpired()){ //altered duration of an expired effect to make it not get removed
$this->entity->onEffectAdded($ev->getEffect(), true);
foreach($this->effectAddHooks as $hook){
$hook($ev->getEffect(), true);
}
}
return;
}
unset($this->effects[$index]);
$effect->getType()->remove($this->entity, $effect);
$this->entity->onEffectRemoved($effect);
foreach($this->effectRemoveHooks as $hook){
$hook($effect);
}
$this->recalculateEffectColor();
}
@ -151,7 +162,9 @@ class EffectManager{
}
$effect->getType()->add($this->entity, $effect);
$this->entity->onEffectAdded($effect, $oldEffect !== null);
foreach($this->effectAddHooks as $hook){
$hook($effect, $oldEffect !== null);
}
$this->effects[$index] = $effect;
@ -218,4 +231,14 @@ class EffectManager{
return !empty($this->effects);
}
public function onEffectAdd(\Closure $closure) : void{
Utils::validateCallableSignature(function(EffectInstance $effect, bool $replacesOldEffect) : void{}, $closure);
$this->effectAddHooks[spl_object_id($closure)] = $closure;
}
public function onEffectRemove(\Closure $closure) : void{
Utils::validateCallableSignature(function(EffectInstance $effect) : void{}, $closure);
$this->effectRemoveHooks[spl_object_id($closure)] = $closure;
}
}

View File

@ -184,6 +184,12 @@ class NetworkSession{
$this->player = new $class($this->server, $this, $this->info, $this->authenticated);
$this->invManager = new InventoryManager($this->player, $this);
$this->player->getEffects()->onEffectAdd(function(EffectInstance $effect, bool $replacesOldEffect) : void{
$this->onEntityEffectAdded($this->player, $effect, $replacesOldEffect);
});
$this->player->getEffects()->onEffectRemove(function(EffectInstance $effect) : void{
$this->onEntityEffectRemoved($this->player, $effect);
});
}
public function getPlayer() : ?Player{

View File

@ -1453,14 +1453,6 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener,
return $this->isCreative() or parent::canBreathe();
}
public function onEffectAdded(EffectInstance $effect, bool $replacesOldEffect) : void{
$this->networkSession->onEntityEffectAdded($this, $effect, $replacesOldEffect);
}
public function onEffectRemoved(EffectInstance $effect) : void{
$this->networkSession->onEntityEffectRemoved($this, $effect);
}
/**
* Returns whether the player can interact with the specified position. This checks distance and direction.
*