Consumables refactor (#1796)

* Removed broken EntityEatEvents - these don't fit the pattern since they only apply to Human entities anyway. PlayerItemConsumeEvent and PlayerInteractEvent can be used for cancellation purposes, and plugins can do custom stuff without mess.

* Restrict item consuming to Living entities only

* Added FoodSource->requiresHunger()

* Only items implementing the Consumable interface can now be consumed.

* The effects from consuming items are now generic-ized by way of the Living->consume() function. This is overridden in Human to allow applying food and hunger.

* Fixed the hardcoded mess for buckets
This commit is contained in:
Dylan K. Taylor
2017-12-23 13:03:41 +00:00
committed by GitHub
parent 329fe7d844
commit 6e1df36188
14 changed files with 113 additions and 306 deletions

View File

@ -27,13 +27,14 @@ use pocketmine\block\Air;
use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
use pocketmine\block\Liquid;
use pocketmine\entity\Living;
use pocketmine\event\player\PlayerBucketEmptyEvent;
use pocketmine\event\player\PlayerBucketFillEvent;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
use pocketmine\Player;
class Bucket extends Item{
class Bucket extends Item implements Consumable{
public function __construct(int $meta = 0){
parent::__construct(self::BUCKET, $meta, "Bucket");
}
@ -85,4 +86,20 @@ class Bucket extends Item{
return false;
}
public function getResidue(){
return ItemFactory::get(Item::BUCKET, 0, 1);
}
public function getAdditionalEffects() : array{
return [];
}
public function canBeConsumed() : bool{
return $this->meta === 1; //Milk
}
public function onConsume(Living $consumer){
$consumer->removeAllEffects();
}
}

View File

@ -23,14 +23,32 @@ declare(strict_types=1);
namespace pocketmine\item;
use pocketmine\block\Block;
use pocketmine\entity\Effect;
use pocketmine\entity\Living;
/**
* Interface implemented by objects that can be consumed by mobs.
*/
interface Consumable{
/**
* Returns the leftover that this Consumable produces when it is consumed. For Items, this is usually air, but could
* be an Item to add to a Player's inventory afterwards (such as a bowl).
*
* @return Item|Block|mixed
*/
public function getResidue();
/**
* @return Effect[]
*/
public function getAdditionalEffects() : array;
/**
* Called when this Consumable is consumed by mob, after standard resulting effects have been applied.
*
* @param Living $consumer
*/
public function onConsume(Living $consumer);
}

View File

@ -23,42 +23,25 @@ declare(strict_types=1);
namespace pocketmine\item;
use pocketmine\entity\Entity;
use pocketmine\entity\Human;
use pocketmine\event\entity\EntityEatItemEvent;
use pocketmine\entity\Living;
abstract class Food extends Item implements FoodSource{
public function canBeConsumed() : bool{
public function requiresHunger() : bool{
return true;
}
public function canBeConsumedBy(Entity $entity) : bool{
return $entity instanceof Human and $entity->getFood() < $entity->getMaxFood();
}
/**
* @return Item
*/
public function getResidue(){
if($this->getCount() === 1){
return ItemFactory::get(0);
}else{
$new = clone $this;
$new->count--;
return $new;
}
return ItemFactory::get(Item::AIR, 0, 0);
}
public function getAdditionalEffects() : array{
return [];
}
public function onConsume(Entity $human){
$ev = new EntityEatItemEvent($human, $this);
public function onConsume(Living $consumer){
$human->addSaturation($ev->getSaturationRestore());
$human->addFood($ev->getFoodRestore());
foreach($ev->getAdditionalEffects() as $effect){
$human->addEffect($effect);
}
$human->getInventory()->setItemInHand($ev->getResidue());
}
}

View File

@ -23,9 +23,18 @@ declare(strict_types=1);
namespace pocketmine\item;
/**
* Interface implemented by objects that can be consumed by players, giving them food and saturation.
*/
interface FoodSource extends Consumable{
public function getFoodRestore() : int;
public function getSaturationRestore() : float;
/**
* Returns whether a Human eating this FoodSource must have a non-full hunger bar.
* @return bool
*/
public function requiresHunger() : bool;
}

View File

@ -24,8 +24,6 @@ declare(strict_types=1);
namespace pocketmine\item;
use pocketmine\entity\Effect;
use pocketmine\entity\Entity;
use pocketmine\entity\Human;
class GoldenApple extends Food{
@ -33,8 +31,8 @@ class GoldenApple extends Food{
parent::__construct(self::GOLDEN_APPLE, $meta, "Golden Apple");
}
public function canBeConsumedBy(Entity $entity) : bool{
return $entity instanceof Human;
public function requiresHunger() : bool{
return false;
}
public function getFoodRestore() : int{

View File

@ -621,32 +621,6 @@ class Item implements ItemIds, \JsonSerializable{
return $this->block !== null and $this->block->canBePlaced();
}
/**
* Returns whether an entity can eat or drink this item.
* @return bool
*/
public function canBeConsumed() : bool{
return false;
}
/**
* Returns whether this item can be consumed by the supplied Entity.
* @param Entity $entity
*
* @return bool
*/
public function canBeConsumedBy(Entity $entity) : bool{
return $this->canBeConsumed();
}
/**
* Called when the item is consumed by an Entity.
* @param Entity $entity
*/
public function onConsume(Entity $entity){
}
/**
* Returns the block corresponding to this Item.
* @return Block

View File

@ -23,7 +23,7 @@ declare(strict_types=1);
namespace pocketmine\item;
use pocketmine\entity\Entity;
use pocketmine\entity\Living;
class Potion extends Item{
public function __construct(int $meta = 0){
@ -38,7 +38,7 @@ class Potion extends Item{
return 1;
}
public function onConsume(Entity $entity){
public function onConsume(Living $consumer){
// TODO: Implement potions
}
}