Refactored effects handling, split up concerns of effect types and instances

Removed json insanity for effects

Split up effect types and effect instances

Saturation is an instant effect
This commit is contained in:
Dylan K. Taylor
2018-03-07 12:42:31 +00:00
parent c7f8796136
commit dc3bf8546e
17 changed files with 442 additions and 453 deletions

View File

@ -63,7 +63,7 @@ abstract class Living extends Entity implements Damageable{
protected $jumpVelocity = 0.42;
/** @var Effect[] */
/** @var EffectInstance[] */
protected $effects = [];
/** @var ArmorInventory */
@ -95,16 +95,18 @@ abstract class Living extends Entity implements Damageable{
$activeEffectsTag = $this->namedtag->getListTag("ActiveEffects");
if($activeEffectsTag !== null){
foreach($activeEffectsTag as $e){
$amplifier = Binary::unsignByte($e->getByte("Amplifier")); //0-255 only
$effect = Effect::getEffect($e->getByte("Id"));
if($effect === null){
continue;
}
$effect->setAmplifier($amplifier)->setDuration($e->getInt("Duration"))->setVisible($e->getByte("ShowParticles", 1) > 0)->setAmbient($e->getByte("Ambient", 0) !== 0);
$this->addEffect($effect);
$this->addEffect(new EffectInstance(
$effect,
$e->getInt("Duration"),
Binary::unsignByte($e->getByte("Amplifier")),
$e->getByte("ShowParticles", 1) !== 0,
$e->getByte("Ambient", 0) !== 0
));
}
}
}
@ -174,7 +176,7 @@ abstract class Living extends Entity implements Damageable{
/**
* Returns an array of Effects currently active on the mob.
* @return Effect[]
* @return EffectInstance[]
*/
public function getEffects() : array{
return $this->effects;
@ -203,7 +205,8 @@ abstract class Living extends Entity implements Damageable{
}
unset($this->effects[$effectId]);
$effect->remove($this);
$effect->getType()->remove($this, $effect);
$this->sendEffectRemove($effect);
$this->recalculateEffectColor();
}
@ -215,7 +218,7 @@ abstract class Living extends Entity implements Damageable{
*
* @param int $effectId
*
* @return Effect|null
* @return EffectInstance|null
*/
public function getEffect(int $effectId){
return $this->effects[$effectId] ?? null;
@ -245,11 +248,11 @@ abstract class Living extends Entity implements Damageable{
* If a weaker effect of the same type is already applied, it will be replaced.
* If a weaker or equal-strength effect is already applied but has a shorter duration, it will be replaced.
*
* @param Effect $effect
* @param EffectInstance $effect
*
* @return bool whether the effect has been successfully applied.
*/
public function addEffect(Effect $effect) : bool{
public function addEffect(EffectInstance $effect) : bool{
$oldEffect = null;
$cancelled = false;
@ -271,7 +274,13 @@ abstract class Living extends Entity implements Damageable{
return false;
}
$effect->add($this, $oldEffect);
if($oldEffect !== null){
$oldEffect->getType()->remove($this, $oldEffect);
}
$effect->getType()->add($this, $effect);
$this->sendEffectAdd($effect, $oldEffect !== null);
$this->effects[$effect->getId()] = $effect;
$this->recalculateEffectColor();
@ -287,7 +296,7 @@ abstract class Living extends Entity implements Damageable{
$colors = [];
$ambient = true;
foreach($this->effects as $effect){
if($effect->isVisible() and $effect->hasBubbles()){
if($effect->isVisible() and $effect->getType()->hasBubbles()){
$level = $effect->getEffectLevel();
$color = $effect->getColor();
for($i = 0; $i < $level; ++$i){
@ -327,6 +336,14 @@ abstract class Living extends Entity implements Damageable{
}
}
protected function sendEffectAdd(EffectInstance $effect, bool $replacesOldEffect) : void{
}
protected function sendEffectRemove(EffectInstance $effect) : void{
}
/**
* Causes the mob to consume the given Consumable object, applying applicable effects, health bonuses, food bonuses,
* etc.
@ -609,13 +626,14 @@ abstract class Living extends Entity implements Damageable{
}
protected function doEffectsTick(int $tickDiff = 1){
foreach($this->effects as $effect){
if($effect->canTick()){
$effect->applyEffect($this);
foreach($this->effects as $instance){
$type = $instance->getType();
if($type->canTick($instance)){
$type->applyEffect($this, $instance);
}
$effect->setDuration(max(0, $effect->getDuration() - $tickDiff));
if($effect->getDuration() <= 0){
$this->removeEffect($effect->getId());
$instance->decreaseDuration($tickDiff);
if($instance->hasExpired()){
$this->removeEffect($instance->getId());
}
}
}