Merge pull request #3978 from PEMapModder/attr

Implemented attributes
This commit is contained in:
PEMapModder 2016-03-07 18:15:15 +08:00
commit fc08759199
54 changed files with 1344 additions and 350 deletions

View File

@ -35,7 +35,6 @@ use pocketmine\event\block\SignChangeEvent;
use pocketmine\event\entity\EntityDamageByBlockEvent;
use pocketmine\event\entity\EntityDamageByEntityEvent;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\event\entity\EntityRegainHealthEvent;
use pocketmine\event\entity\EntityShootBowEvent;
use pocketmine\event\entity\ProjectileLaunchEvent;
use pocketmine\event\inventory\CraftItemEvent;
@ -50,6 +49,7 @@ use pocketmine\event\player\PlayerChatEvent;
use pocketmine\event\player\PlayerCommandPreprocessEvent;
use pocketmine\event\player\PlayerDeathEvent;
use pocketmine\event\player\PlayerDropItemEvent;
use pocketmine\event\player\PlayerExhaustEvent;
use pocketmine\event\player\PlayerGameModeChangeEvent;
use pocketmine\event\player\PlayerInteractEvent;
use pocketmine\event\player\PlayerItemConsumeEvent;
@ -123,6 +123,7 @@ use pocketmine\network\protocol\SetTimePacket;
use pocketmine\network\protocol\StartGamePacket;
use pocketmine\network\protocol\TakeItemEntityPacket;
use pocketmine\network\protocol\TextPacket;
use pocketmine\network\protocol\UpdateAttributesPacket;
use pocketmine\network\protocol\UpdateBlockPacket;
use pocketmine\network\SourceInterface;
use pocketmine\permission\PermissibleBase;
@ -245,7 +246,8 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
/**
* This might disappear in the future.
* Please use getUniqueId() instead (IP + clientId + name combo, in the future it'll change to real UUID for online auth)
* Please use getUniqueId() instead (IP + clientId + name combo, in the future it'll change to real UUID for online
* auth)
*
* @deprecated
*
@ -484,7 +486,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
return $this->perm->getEffectivePermissions();
}
/**
* @param SourceInterface $interface
* @param null $clientID
@ -855,7 +856,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->loadQueue = $newOrder;
Timings::$playerChunkOrderTimer->stopTiming();
return true;
@ -986,12 +986,12 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->level->sleepTicks = 60;
return true;
}
/**
* Sets the spawnpoint of the player (and the compass direction) to a Vector3, or set it on another world with a Position object
* Sets the spawnpoint of the player (and the compass direction) to a Vector3, or set it on another world with a
* Position object
*
* @param Vector3|Position $pos
*/
@ -1017,7 +1017,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->setDataProperty(self::DATA_PLAYER_BED_POSITION, self::DATA_TYPE_POS, [0, 0, 0]);
$this->setDataFlag(self::DATA_PLAYER_FLAGS, self::DATA_PLAYER_FLAG_SLEEP, false);
$this->level->sleepTicks = 0;
$pk = new AnimatePacket();
@ -1025,7 +1024,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$pk->action = 3; //Wake up
$this->dataPacket($pk);
}
}
/**
@ -1213,6 +1211,23 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
return false;
}
public function entityBaseTick($tickDiff = 1){
$hasUpdate = parent::entityBaseTick($tickDiff);
$entries = $this->attributeMap->needSend();
if(count($entries) > 0){
$pk = new UpdateAttributesPacket();
$pk->entityId = 0;
$pk->entries = $entries;
$this->dataPacket($pk);
foreach($entries as $entry){
$entry->markSynchronized();
}
}
return $hasUpdate;
}
protected function checkGroundState($movX, $movY, $movZ, $dx, $dy, $dz){
if(!$this->onGround or $movY != 0){
$bb = clone $this->boundingBox;
@ -1448,7 +1463,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}
protected function updateMovement(){
}
public function onUpdate($currentTick){
@ -1531,7 +1545,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->server->batchPackets([$this], $this->batchedPackets, false);
$this->batchedPackets = [];
}
}
public function canInteract(Vector3 $pos, $maxDistance, $maxDiff = 0.5){
@ -1612,7 +1625,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->allowFlight = $this->isCreative();
if(($level = $this->server->getLevelByName($nbt["Level"])) === null){
$this->setLevel($this->server->getDefaultLevel());
$nbt["Level"] = $this->level->getName();
@ -1631,7 +1643,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->achievements = [];
/** @var Byte $achievement */
/** @var ByteTag $achievement */
foreach($nbt->Achievements as $achievement){
$this->achievements[$achievement->getName()] = $achievement->getValue() > 0 ? true : false;
}
@ -1752,7 +1764,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
return;
}
$timings = Timings::getReceiveDataPacketTimings($packet);
$timings->startTiming();
@ -1950,7 +1961,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ACTION, false);
if(!$this->canInteract($blockVector->add(0.5, 0.5, 0.5), 13) or $this->isSpectator()){
}elseif($this->isCreative()){
$item = $this->inventory->getItemInHand();
if($this->level->useItemOn($blockVector, $item, $packet->face, $packet->fx, $packet->fy, $packet->fz, $this) === true){
@ -2082,7 +2092,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
break;
}
$nbt = new CompoundTag("", [
"Pos" => new ListTag("Pos", [
new DoubleTag("", $this->x),
@ -2255,7 +2264,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$vector = new Vector3($packet->x, $packet->y, $packet->z);
if($this->isCreative()){
$item = $this->inventory->getItemInHand();
}else{
@ -2270,6 +2278,8 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->inventory->setItemInHand($item);
$this->inventory->sendHeldItem($this->hasSpawned);
}
$this->exhaust(0.025, PlayerExhaustEvent::CAUSE_MINING);
}
break;
}
@ -2309,7 +2319,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
if(
$target instanceof Player and
$this->server->getConfigBoolean("pvp", true) === false
){
$cancelled = true;
}
@ -2407,16 +2416,19 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
break;
}
if($item->isTool() and $this->isSurvival()){
if($item->useOn($target) and $item->getDamage() >= $item->getMaxDurability()){
$this->inventory->setItemInHand(Item::get(Item::AIR, 0, 1));
}else{
$this->inventory->setItemInHand($item);
if($this->isSurvival()){
if($item->isTool()){
if($item->useOn($target) and $item->getDamage() >= $item->getMaxDurability()){
$this->inventory->setItemInHand(Item::get(Item::AIR, 0, 1));
}else{
$this->inventory->setItemInHand($item);
}
}
$this->exhaust(0.3, PlayerExhaustEvent::CAUSE_ATTACK);
}
}
break;
case ProtocolInfo::ANIMATE_PACKET:
if($this->spawned === false or !$this->isAlive()){
@ -2444,65 +2456,19 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ACTION, false); //TODO: check if this should be true
switch($packet->event){
case 9: //Eating
$items = [ //TODO: move this to item classes
Item::APPLE => 4,
Item::MUSHROOM_STEW => 10,
Item::BEETROOT_SOUP => 10,
Item::BREAD => 5,
Item::RAW_PORKCHOP => 3,
Item::COOKED_PORKCHOP => 8,
Item::RAW_BEEF => 3,
Item::STEAK => 8,
Item::COOKED_CHICKEN => 6,
Item::RAW_CHICKEN => 2,
Item::MELON_SLICE => 2,
Item::GOLDEN_APPLE => 10,
Item::PUMPKIN_PIE => 8,
Item::CARROT => 4,
Item::POTATO => 1,
Item::BAKED_POTATO => 6,
Item::COOKIE => 2,
Item::COOKED_FISH => [
0 => 5,
1 => 6
],
Item::RAW_FISH => [
0 => 2,
1 => 2,
2 => 1,
3 => 1
],
];
case EntityEventPacket::USE_ITEM: //Eating
$slot = $this->inventory->getItemInHand();
if($this->getHealth() < $this->getMaxHealth() and isset($items[$slot->getId()])){
$this->server->getPluginManager()->callEvent($ev = new PlayerItemConsumeEvent($this, $slot));
if($ev->isCancelled()){
if($slot->canBeConsumed()){
$ev = new PlayerItemConsumeEvent($this, $slot);
if(!$slot->canBeConsumedBy($this)){
$ev->setCancelled();
}
$this->server->getPluginManager()->callEvent($ev);
if(!$ev->isCancelled()){
$slot->onConsume($this);
}else{
$this->inventory->sendContents($this);
break;
}
$pk = new EntityEventPacket();
$pk->eid = $this->getId();
$pk->event = EntityEventPacket::USE_ITEM;
$this->dataPacket($pk);
Server::broadcastPacket($this->getViewers(), $pk);
$amount = $items[$slot->getId()];
if(is_array($amount)){
$amount = isset($amount[$slot->getDamage()]) ? $amount[$slot->getDamage()] : 0;
}
$ev = new EntityRegainHealthEvent($this, $amount, EntityRegainHealthEvent::CAUSE_EATING);
$this->heal($ev->getAmount(), $ev);
--$slot->count;
$this->inventory->setItemInHand($slot);
if($slot->getId() === Item::MUSHROOM_STEW or $slot->getId() === Item::BEETROOT_SOUP){
$this->inventory->addItem(Item::get(Item::BOWL, 0, 1));
}elseif($slot->getId() === Item::RAW_FISH and $slot->getDamage() === 3){ //Pufferfish
//$this->addEffect(Effect::getEffect(Effect::HUNGER)->setAmplifier(2)->setDuration(15 * 20));
$this->addEffect(Effect::getEffect(Effect::NAUSEA)->setAmplifier(1)->setDuration(15 * 20));
$this->addEffect(Effect::getEffect(Effect::POISON)->setAmplifier(3)->setDuration(60 * 20));
}
}
break;
@ -2604,7 +2570,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$canCraft = true;
if($recipe instanceof ShapedRecipe){
for($x = 0; $x < 3 and $canCraft; ++$x){
for($y = 0; $y < 3; ++$y){
@ -2792,7 +2757,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
break;
}
if($this->currentTransaction === null or $this->currentTransaction->getCreationTime() < (microtime(true) - 8)){
if($this->currentTransaction !== null){
foreach($this->currentTransaction->getInventories() as $inventory){
@ -2934,7 +2898,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
return;
}
$message = $message->getText();
}
$mes = explode("\n", $this->server->getLanguage()->translateString($message));
@ -3225,7 +3188,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
break;
default:
}
Entity::kill();
@ -3246,7 +3208,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->server->broadcast($ev->getDeathMessage(), Server::BROADCAST_CHANNEL_USERS);
}
$pk = new RespawnPacket();
$pos = $this->getSpawn();
$pk->x = $pos->x;
@ -3288,6 +3249,10 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$pk->eid = 0;
$pk->event = EntityEventPacket::HURT_ANIMATION;
$this->dataPacket($pk);
if($this->isSurvival()){
$this->exhaust(0.3, PlayerExhaustEvent::CAUSE_DAMAGE);
}
}
}
@ -3431,7 +3396,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->forceMovement = new Vector3($this->x, $this->y, $this->z);
$this->sendPosition($this, $this->yaw, $this->pitch, 1);
$this->resetFallDistance();
$this->orderChunks();
$this->nextChunkOrderRun = 0;
@ -3439,7 +3403,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}
}
/**
* @param Inventory $inventory
*
@ -3507,25 +3470,20 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->server->getPlayerMetadata()->removeMetadata($this, $metadataKey, $plugin);
}
public function onChunkChanged(FullChunk $chunk){
$this->loadQueue[Level::chunkHash($chunk->getX(), $chunk->getZ())] = abs(($this->x >> 4) - $chunk->getX()) + abs(($this->z >> 4) - $chunk->getZ());
}
public function onChunkLoaded(FullChunk $chunk){
}
public function onChunkPopulated(FullChunk $chunk){
}
public function onChunkUnloaded(FullChunk $chunk){
}
public function onBlockChanged(Vector3 $block){
}
public function getLoaderId(){
@ -3537,9 +3495,10 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}
/**
* @param $chunkX
* @param $chunkZ
* @param $payload
* @param int $chunkX
* @param int $chunkZ
* @param string $payload
* @param int $ordering
*
* @return DataPacket
*/

View File

@ -21,14 +21,15 @@
namespace pocketmine\block;
use pocketmine\event\entity\EntityRegainHealthEvent;
use pocketmine\entity\Effect;
use pocketmine\event\entity\EntityEatBlockEvent;
use pocketmine\item\FoodSource;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\AxisAlignedBB;
use pocketmine\Player;
class Cake extends Transparent{
class Cake extends Transparent implements FoodSource{
protected $id = self::CAKE_BLOCK;
@ -91,18 +92,10 @@ class Cake extends Transparent{
public function onActivate(Item $item, Player $player = null){
if($player instanceof Player and $player->getHealth() < $player->getMaxHealth()){
++$this->meta;
$ev = new EntityRegainHealthEvent($player, 3, EntityRegainHealthEvent::CAUSE_EATING);
$player->heal($ev->getAmount(), $ev);
$ev = new EntityEatBlockEvent($player, $this);
if(!$ev->isCancelled()){
if($this->meta >= 0x06){
$this->getLevel()->setBlock($this, new Air(), true);
}else{
$this->getLevel()->setBlock($this, $this, true);
}
$this->getLevel()->setBlock($this, $ev->getResidue());
return true;
}
}
@ -110,4 +103,27 @@ class Cake extends Transparent{
return false;
}
public function getFoodRestore() : int{
return 2;
}
public function getSaturationRestore() : float{
return 0.4;
}
public function getResidue(){
$clone = clone $this;
$clone->meta++;
if($clone->meta >= 0x06){
$clone = new Air();
}
return $clone;
}
/**
* @return Effect[]
*/
public function getAdditionalEffects() : array{
return [];
}
}

View File

@ -21,20 +21,20 @@
namespace pocketmine\entity;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\event\entity\EntityRegainHealthEvent;
use pocketmine\network\Network;
use pocketmine\network\protocol\MobEffectPacket;
use pocketmine\Player;
class Attribute{
const MAX_HEALTH = 0;
const EXPERIENCE = 1;
const EXPERIENCE_LEVEL = 2;
const ABSORPTION = 0;
const SATURATION = 1;
const EXHAUSTION = 2;
const KNOCKBACK_RESISTANCE = 3;
const HEALTH = 4;
const MOVEMENT_SPEED = 5;
const FOLLOW_RANGE = 6;
const HUNGER = 7;
const FOOD = 7;
const ATTACK_DAMAGE = 8;
const EXPERIENCE_LEVEL = 9;
const EXPERIENCE = 10;
private $id;
protected $minValue;
@ -44,13 +44,23 @@ class Attribute{
protected $name;
protected $shouldSend;
protected $desynchronized = true;
/** @var Attribute[] */
protected static $attributes = [];
public static function init(){
self::addAttribute(self::MAX_HEALTH, "generic.health", 0, 0x7fffffff, 20, true);
self::addAttribute(self::EXPERIENCE, "player.experience", 0, 1, 0, true);
self::addAttribute(self::EXPERIENCE_LEVEL, "player.level", 0, 24791, 0, true);
self::addAttribute(self::ABSORPTION, "generic.absorption", 0.00, 340282346638528859811704183484516925440.00, 0.00);
self::addAttribute(self::SATURATION, "player.saturation", 0.00, 20.00, 5.00);
self::addAttribute(self::EXHAUSTION, "player.exhaustion", 0.00, 5.00, 0.41);
self::addAttribute(self::KNOCKBACK_RESISTANCE, "generic.knockbackResistance", 0.00, 1.00, 0.00);
self::addAttribute(self::HEALTH, "generic.health", 0.00, 20.00, 20.00);
self::addAttribute(self::MOVEMENT_SPEED, "generic.movementSpeed", 0.00, 340282346638528859811704183484516925440.00, 0.10);
self::addAttribute(self::FOLLOW_RANGE, "generic.followRange", 0.00, 2048.00, 16.00, false);
self::addAttribute(self::HUNGER, "player.hunger", 0.00, 20.00, 20.00);
self::addAttribute(self::ATTACK_DAMAGE, "generic.attackDamage", 0.00, 340282346638528859811704183484516925440.00, 1.00, false);
self::addAttribute(self::EXPERIENCE_LEVEL, "player.level", 0.00, 24791.00, 0.00);
self::addAttribute(self::EXPERIENCE, "player.experience", 0.00, 1.00, 0.00);
}
/**
@ -60,9 +70,10 @@ class Attribute{
* @param float $maxValue
* @param float $defaultValue
* @param bool $shouldSend
*
* @return Attribute
*/
public static function addAttribute($id, $name, $minValue, $maxValue, $defaultValue, $shouldSend = false){
public static function addAttribute($id, $name, $minValue, $maxValue, $defaultValue, $shouldSend = true){
if($minValue > $maxValue or $defaultValue > $maxValue or $defaultValue < $minValue){
throw new \InvalidArgumentException("Invalid ranges: min value: $minValue, max value: $maxValue, $defaultValue: $defaultValue");
}
@ -72,6 +83,7 @@ class Attribute{
/**
* @param $id
*
* @return null|Attribute
*/
public static function getAttribute($id){
@ -80,6 +92,7 @@ class Attribute{
/**
* @param $name
*
* @return null|Attribute
*/
public static function getAttributeByName($name){
@ -92,13 +105,13 @@ class Attribute{
return null;
}
private function __construct($id, $name, $minValue, $maxValue, $defaultValue, $shouldSend = false){
private function __construct($id, $name, $minValue, $maxValue, $defaultValue, $shouldSend = true){
$this->id = (int) $id;
$this->name = (string) $name;
$this->minValue = (float) $minValue;
$this->maxValue = (float) $maxValue;
$this->defaultValue = (float) $defaultValue;
$this->shouldSend = (float) $shouldSend;
$this->shouldSend = (bool) $shouldSend;
$this->currentValue = $this->defaultValue;
}
@ -112,7 +125,10 @@ class Attribute{
throw new \InvalidArgumentException("Value $minValue is bigger than the maxValue!");
}
$this->minValue = $minValue;
if($this->minValue != $minValue){
$this->desynchronized = true;
$this->minValue = $minValue;
}
return $this;
}
@ -125,7 +141,10 @@ class Attribute{
throw new \InvalidArgumentException("Value $maxValue is bigger than the minValue!");
}
$this->maxValue = $maxValue;
if($this->maxValue != $maxValue){
$this->desynchronized = true;
$this->maxValue = $maxValue;
}
return $this;
}
@ -138,7 +157,10 @@ class Attribute{
throw new \InvalidArgumentException("Value $defaultValue exceeds the range!");
}
$this->defaultValue = $defaultValue;
if($this->defaultValue !== $defaultValue){
$this->desynchronized = true;
$this->defaultValue = $defaultValue;
}
return $this;
}
@ -146,13 +168,18 @@ class Attribute{
return $this->currentValue;
}
public function setValue($value){
public function setValue($value, $fit = false){
if($value > $this->getMaxValue() or $value < $this->getMinValue()){
throw new \InvalidArgumentException("Value $value exceeds the range!");
if(!$fit){
throw new \InvalidArgumentException("Value $value exceeds the range!");
}
$value = min(max($value, $this->getMinValue()), $this->getMaxValue());
}
$this->currentValue = $value;
if($this->currentValue != $value){
$this->desynchronized = true;
$this->currentValue = $value;
}
return $this;
}
@ -168,4 +195,11 @@ class Attribute{
return $this->shouldSend;
}
public function isDesynchronized() : bool{
return $this->shouldSend and $this->desynchronized;
}
public function markSynchronized(bool $synced = true){
$this->desynchronized = !$synced;
}
}

View File

@ -0,0 +1,65 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\entity;
class AttributeMap implements \ArrayAccess{
/** @var Attribute[] */
private $attributes = [];
public function addAttribute(Attribute $attribute){
$this->attributes[$attribute->getId()] = $attribute;
}
/**
* @param int $id
*
* @return Attribute|null
*/
public function getAttribute(int $id){
return $this->attributes[$id] ?? null;
}
/**
* @return Attribute[]
*/
public function needSend() : array{
return array_filter($this->attributes, function (Attribute $attribute){
return $attribute->isSyncable() and $attribute->isDesynchronized();
});
}
public function offsetExists($offset){
return isset($this->attributes[$offset]);
}
public function offsetGet($offset){
return $this->attributes[$offset]->getValue();
}
public function offsetSet($offset, $value){
$this->attributes[$offset]->setValue($value);
}
public function offsetUnset($offset){
throw new \RuntimeException("Could not unset an attribute from an attribute map");
}
}

View File

@ -23,11 +23,10 @@ namespace pocketmine\entity;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\event\entity\EntityRegainHealthEvent;
use pocketmine\network\Network;
use pocketmine\event\player\PlayerExhaustEvent;
use pocketmine\network\protocol\MobEffectPacket;
use pocketmine\Player;
class Effect{
const SPEED = 1;
const SLOWNESS = 2;
@ -36,8 +35,8 @@ class Effect{
const FATIGUE = 4;
const MINING_FATIGUE = 4;
const STRENGTH = 5;
//TODO: const HEALING = 6;
//TODO: const HARMING = 7;
// TODO: const HEALING = 6;
// TODO: const HARMING = 7;
const JUMP = 8;
const NAUSEA = 9;
const CONFUSION = 9;
@ -46,15 +45,15 @@ class Effect{
const FIRE_RESISTANCE = 12;
const WATER_BREATHING = 13;
const INVISIBILITY = 14;
//const BLINDNESS = 15;
//const NIGHT_VISION = 16;
//const HUNGER = 17;
const BLINDNESS = 15;
const NIGHT_VISION = 16;
const HUNGER = 17;
const WEAKNESS = 18;
const POISON = 19;
const WITHER = 20;
const HEALTH_BOOST = 21;
//const ABSORPTION = 22;
//const SATURATION = 23;
const ABSORPTION = 22; // TODO implement
const SATURATION = 23;
/** @var Effect[] */
protected static $effects;
@ -76,17 +75,20 @@ class Effect{
self::$effects[Effect::FIRE_RESISTANCE] = new Effect(Effect::FIRE_RESISTANCE, "%potion.fireResistance", 228, 154, 58);
self::$effects[Effect::WATER_BREATHING] = new Effect(Effect::WATER_BREATHING, "%potion.waterBreathing", 46, 82, 153);
self::$effects[Effect::INVISIBILITY] = new Effect(Effect::INVISIBILITY, "%potion.invisibility", 127, 131, 146);
//Hunger
self::$effects[Effect::WEAKNESS] = new Effect(Effect::WEAKNESS, "%potion.weakness", 72, 77, 72 , true);
self::$effects[Effect::BLINDNESS] = new Effect(Effect::BLINDNESS, "%potion.blindness", 191, 192, 192);
self::$effects[Effect::NIGHT_VISION] = new Effect(Effect::NIGHT_VISION, "%potion.nightVision", 0, 0, 139);
self::$effects[Effect::HUNGER] = new Effect(Effect::HUNGER, "%potion.hunger", 46, 139, 87);
self::$effects[Effect::WEAKNESS] = new Effect(Effect::WEAKNESS, "%potion.weakness", 72, 77, 72, true);
self::$effects[Effect::POISON] = new Effect(Effect::POISON, "%potion.poison", 78, 147, 49, true);
self::$effects[Effect::WITHER] = new Effect(Effect::WITHER, "%potion.wither", 53, 42, 39, true);
self::$effects[Effect::HEALTH_BOOST] = new Effect(Effect::HEALTH_BOOST, "%potion.healthBoost", 248, 125, 35);
//Absorption
//Saturation
self::$effects[Effect::ABSORPTION] = new Effect(Effect::ABSORPTION, "%potion.absorption", 36, 107, 251);
self::$effects[Effect::SATURATION] = new Effect(Effect::SATURATION, "%potion.saturation", 255, 0, 255);
}
/**
* @param int $id
*
* @return $this
*/
public static function getEffect($id){
@ -200,6 +202,14 @@ class Effect{
return ($this->duration % $interval) === 0;
}
return true;
case Effect::HUNGER:
if($this->amplifier < 0){ // prevents hacking with amplifier -1
return false;
}
if(($interval = 20) > 0){
return ($this->duration % $interval) === 0;
}
return true;
}
return false;
}
@ -224,6 +234,11 @@ class Effect{
$entity->heal($ev->getAmount(), $ev);
}
break;
case Effect::HUNGER:
if($entity instanceof Human){
$entity->exhaust(0.5 * $this->amplifier, PlayerExhaustEvent::CAUSE_POTION);
}
}
}
@ -235,7 +250,7 @@ class Effect{
$this->color = (($r & 0xff) << 16) + (($g & 0xff) << 8) + ($b & 0xff);
}
public function add(Entity $entity, $modify = false){
public function add(Entity $entity, $modify = false, Effect $oldEffect = null){
if($entity instanceof Player){
$pk = new MobEffectPacket();
$pk->eid = 0;
@ -255,6 +270,24 @@ class Effect{
if($this->id === Effect::INVISIBILITY){
$entity->setDataFlag(Entity::DATA_FLAGS, Entity::DATA_FLAG_INVISIBLE, true);
$entity->setDataProperty(Entity::DATA_SHOW_NAMETAG, Entity::DATA_TYPE_BYTE, 0);
}elseif($this->id === Effect::SPEED){
$attr = $entity->getAttributeMap()->getAttribute(Attribute::MOVEMENT_SPEED);
if($modify and $oldEffect !== null){
$speed = $attr->getValue() / (1 + 0.2 * $oldEffect->getAmplifier());
}else{
$speed = $attr->getValue();
}
$speed *= (1 + 0.2 * $this->amplifier);
$attr->setValue($speed);
}elseif($this->id === Effect::SLOWNESS){
$attr = $entity->getAttributeMap()->getAttribute(Attribute::MOVEMENT_SPEED);
if($modify and $oldEffect !== null){
$speed = $attr->getValue() / (1 - 0.15 * $oldEffect->getAmplifier());
}else{
$speed = $attr->getValue();
}
$speed *= (1 - 0.15 * $this->amplifier);
$attr->setValue($speed);
}
}
@ -271,6 +304,12 @@ class Effect{
if($this->id === Effect::INVISIBILITY){
$entity->setDataFlag(Entity::DATA_FLAGS, Entity::DATA_FLAG_INVISIBLE, false);
$entity->setDataProperty(Entity::DATA_SHOW_NAMETAG, Entity::DATA_TYPE_BYTE, 1);
}elseif($this->id === Effect::SPEED){
$attr = $entity->getAttributeMap()->getAttribute(Attribute::MOVEMENT_SPEED);
$attr->setValue($attr->getValue() / (1 + 0.2 * $this->amplifier));
}elseif($this->id === Effect::SLOWNESS){
$attr = $entity->getAttributeMap()->getAttribute(Attribute::MOVEMENT_SPEED);
$attr->setValue($attr->getValue() / (1 - 0.15 * $this->amplifier));
}
}
}

View File

@ -48,19 +48,17 @@ use pocketmine\metadata\MetadataValue;
use pocketmine\nbt\tag\ByteTag;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\DoubleTag;
use pocketmine\nbt\tag\ListTag;
use pocketmine\nbt\tag\FloatTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\ListTag;
use pocketmine\nbt\tag\ShortTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\network\Network;
use pocketmine\network\protocol\MobEffectPacket;
use pocketmine\network\protocol\RemoveEntityPacket;
use pocketmine\network\protocol\SetEntityDataPacket;
use pocketmine\Player;
use pocketmine\plugin\Plugin;
use pocketmine\Server;
use pocketmine\utils\ChunkException;
abstract class Entity extends Location implements Metadatable{
@ -191,6 +189,9 @@ abstract class Entity extends Location implements Metadatable{
protected $fireProof;
private $invulnerable;
/** @var AttributeMap */
protected $attributeMap;
protected $gravity;
protected $drag;
@ -265,6 +266,8 @@ abstract class Entity extends Location implements Metadatable{
}
$this->invulnerable = $this->namedtag["Invulnerable"] > 0 ? true : false;
$this->attributeMap = new AttributeMap();
$this->chunk->addEntity($this);
$this->level->addEntity($this);
$this->initEntity();
@ -316,7 +319,11 @@ abstract class Entity extends Location implements Metadatable{
}
public function setSprinting($value = true){
$this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_SPRINTING, (bool) $value);
if($value !== $this->isSprinting()){
$this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_SPRINTING, (bool) $value);
$attr = $this->attributeMap->getAttribute(Attribute::MOVEMENT_SPEED);
$attr->setValue($value ? ($attr->getValue() * 1.3) : ($attr->getValue() / 1.3));
}
}
/**
@ -360,7 +367,7 @@ abstract class Entity extends Location implements Metadatable{
){
return;
}
$effect->add($this, true);
$effect->add($this, true, $oldEffect);
}else{
$effect->add($this, false);
}
@ -405,10 +412,10 @@ abstract class Entity extends Location implements Metadatable{
}
/**
* @param int|string $type
* @param FullChunk $chunk
* @param CompoundTag $nbt
* @param $args
* @param int|string $type
* @param FullChunk $chunk
* @param CompoundTag $nbt
* @param $args
*
* @return Entity
*/
@ -503,6 +510,17 @@ abstract class Entity extends Location implements Metadatable{
protected function initEntity(){
assert($this->namedtag instanceof CompoundTag);
if(isset($this->namedtag->CustomName)){
$this->setNameTag($this->namedtag["CustomName"]);
if(isset($this->namedtag->CustomNameVisible)){
$this->setNameTagVisible($this->namedtag["CustomNameVisible"] > 0);
}
}
$this->scheduleUpdate();
$this->addAttributes();
if(isset($this->namedtag->ActiveEffects)){
foreach($this->namedtag->ActiveEffects->getValue() as $e){
$effect = Effect::getEffect($e["Id"]);
@ -515,16 +533,9 @@ abstract class Entity extends Location implements Metadatable{
$this->addEffect($effect);
}
}
}
if(isset($this->namedtag->CustomName)){
$this->setNameTag($this->namedtag["CustomName"]);
if(isset($this->namedtag->CustomNameVisible)){
$this->setNameTagVisible($this->namedtag["CustomNameVisible"] > 0);
}
}
$this->scheduleUpdate();
protected function addAttributes(){
}
/**
@ -670,6 +681,10 @@ abstract class Entity extends Location implements Metadatable{
return $this->lastDamageCause;
}
public function getAttributeMap(){
return $this->attributeMap;
}
/**
* @return int
*/
@ -1547,6 +1562,7 @@ abstract class Entity extends Location implements Metadatable{
* @param int $propertyId
* @param int $id
* @param bool $value
* @param int $type
*/
public function setDataFlag($propertyId, $id, $value = true, $type = self::DATA_TYPE_BYTE){
if($this->getDataFlag($propertyId, $id) !== $value){

View File

@ -21,20 +21,24 @@
namespace pocketmine\entity;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\event\entity\EntityRegainHealthEvent;
use pocketmine\event\player\PlayerExhaustEvent;
use pocketmine\inventory\InventoryHolder;
use pocketmine\inventory\PlayerInventory;
use pocketmine\item\Item as ItemItem;
use pocketmine\utils\UUID;
use pocketmine\nbt\NBT;
use pocketmine\nbt\tag\ByteTag;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\FloatTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\ListTag;
use pocketmine\nbt\tag\ShortTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\network\Network;
use pocketmine\network\protocol\AddPlayerPacket;
use pocketmine\network\protocol\RemovePlayerPacket;
use pocketmine\Player;
use pocketmine\utils\UUID;
class Human extends Creature implements ProjectileSource, InventoryHolder{
@ -47,7 +51,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
/** @var PlayerInventory */
protected $inventory;
/** @var UUID */
protected $uuid;
protected $rawUUID;
@ -60,6 +63,11 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
protected $skinName;
protected $skin;
protected $foodTickTimer = 0;
protected $totalXp = 0;
protected $xpSeed;
public function getSkinData(){
return $this->skin;
}
@ -91,6 +99,153 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
$this->skinName = $skinName;
}
public function getFood() : float{
return $this->attributeMap->getAttribute(Attribute::HUNGER)->getValue();
}
/**
* WARNING: This method does not check if full and may throw an exception if out of bounds.
* Use {@link Human::addFood()} for this purpose
*
* @param float $new
*
* @throws \InvalidArgumentException
*/
public function setFood(float $new){
$attr = $this->attributeMap->getAttribute(Attribute::HUNGER);
$old = $attr->getValue();
$attr->setValue($new);
// ranges: 18-20 (regen), 7-17 (none), 1-6 (no sprint), 0 (health depletion)
foreach([17, 6, 0] as $bound){
if(($old > $bound) !== ($new > $bound)){
$reset = true;
}
}
if(isset($reset)){
$this->foodTickTimer = 0;
}
}
public function getMaxFood() : float{
return $this->attributeMap->getAttribute(Attribute::HUNGER)->getMaxValue();
}
public function addFood(float $amount){
$attr = $this->attributeMap->getAttribute(Attribute::HUNGER);
$amount += $attr->getValue();
$amount = max(min($amount, $attr->getMaxValue()), $attr->getMinValue());
$this->setFood($amount);
}
public function getSaturation() : float{
return $this->attributeMap->getAttribute(Attribute::HUNGER)->getValue();
}
/**
* WARNING: This method does not check if saturated and may throw an exception if out of bounds.
* Use {@link Human::addSaturation()} for this purpose
*
* @param float $saturation
*
* @throws \InvalidArgumentException
*/
public function setSaturation(float $saturation){
$this->attributeMap->getAttribute(Attribute::HUNGER)->setValue($saturation);
}
public function addSaturation(float $amount){
$attr = $this->attributeMap->getAttribute(Attribute::SATURATION);
$attr->setValue($attr->getValue() + $amount, true);
}
public function getExhaustion() : float{
return $this->attributeMap->getAttribute(Attribute::EXHAUSTION)->getValue();
}
/**
* WARNING: This method does not check if exhausted and does not consume saturation/food.
* Use {@link Human::exhaust()} for this purpose.
*
* @param float $exhaustion
*/
public function setExhaustion(float $exhaustion){
$this->attributeMap->getAttribute(Attribute::EXHAUSTION)->setValue($exhaustion);
}
/**
* Increases a human's exhaustion level.
*
* @param float $amount
* @param int $cause
*
* @return float the amount of exhaustion level increased
*/
public function exhaust(float $amount, int $cause = PlayerExhaustEvent::CAUSE_CUSTOM) : float{
$this->server->getPluginManager()->callEvent($ev = new PlayerExhaustEvent($this, $amount, $cause));
if($ev->isCancelled()){
return 0.0;
}
$exhaustion = $this->getExhaustion();
$exhaustion += $ev->getAmount();
while($exhaustion >= 4.0){
$exhaustion -= 4.0;
$saturation = $this->getSaturation();
if($saturation > 0){
$saturation = max(0, $saturation - 1.0);
$this->setSaturation($saturation);
}else{
$food = $this->getFood();
if($food > 0){
$food--;
$this->setFood($food);
}
}
}
$this->setExhaustion($exhaustion);
return $ev->getAmount();
}
public function getXpLevel() : int{
return (int) $this->attributeMap->getAttribute(Attribute::EXPERIENCE_LEVEL)->getValue();
}
public function setXpLevel(int $level){
$this->attributeMap->getAttribute(Attribute::EXPERIENCE_LEVEL)->setValue($level);
}
public function getXpProgress() : float{
return $this->attributeMap->getAttribute(Attribute::EXPERIENCE)->getValue();
}
public function setXpProgress(float $progress){
$this->attributeMap->getAttribute(Attribute::EXPERIENCE)->setValue($progress);
}
public function getTotalXp() : float{
return $this->totalXp;
}
public function getRemainderXp() : int{
return $this->getTotalXp() - self::getTotalXpForLevel($this->getXpLevel());
}
public function recalculateXpProgress() : float{
$this->setXpProgress($this->getRemainderXp() / self::getTotalXpForLevel($this->getXpLevel()));
}
public static function getTotalXpForLevel(int $level) : int{
if($level <= 16){
return $level ** 2 + $level * 6;
}elseif($level < 32){
return $level ** 2 * 2.5 - 40.5 * $level + 360;
}
return $level ** 2 * 4.5 - 162.5 * $level + 2220;
}
public function getInventory(){
return $this->inventory;
}
@ -103,10 +258,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
$this->inventory = new PlayerInventory($this);
if($this instanceof Player){
$this->addWindow($this->inventory, 0);
}
if(!($this instanceof Player)){
}else{
if(isset($this->namedtag->NameTag)){
$this->setNameTag($this->namedtag["NameTag"]);
}
@ -131,6 +283,101 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
}
parent::initEntity();
if(!isset($this->namedtag->foodLevel) or !($this->namedtag->foodLevel instanceof IntTag)){
$this->namedtag->foodLevel = new IntTag("foodLevel", $this->getFood());
}else{
$this->setFood($this->namedtag["foodLevel"]);
}
if(!isset($this->namedtag->foodExhaustionLevel) or !($this->namedtag->foodExhaustionLevel instanceof IntTag)){
$this->namedtag->foodExhaustionLevel = new FloatTag("foodExhaustionLevel", $this->getExhaustion());
}else{
$this->setExhaustion($this->namedtag["foodExhaustionLevel"]);
}
if(!isset($this->namedtag->foodSaturationLevel) or !($this->namedtag->foodSaturationLevel instanceof IntTag)){
$this->namedtag->foodSaturationLevel = new FloatTag("foodSaturationLevel", $this->getSaturation());
}else{
$this->setSaturation($this->namedtag["foodSaturationLevel"]);
}
if(!isset($this->namedtag->foodTickTimer) or !($this->namedtag->foodTickTimer instanceof IntTag)){
$this->namedtag->foodTickTimer = new IntTag("foodTickTimer", $this->foodTickTimer);
}else{
$this->foodTickTimer = $this->namedtag["foodTickTimer"];
}
if(!isset($this->namedtag->XpLevel) or !($this->namedtag->XpLevel instanceof IntTag)){
$this->namedtag->XpLevel = new IntTag("XpLevel", $this->getXpLevel());
}else{
$this->setXpLevel($this->namedtag["XpLevel"]);
}
if(!isset($this->namedtag->XpP) or !($this->namedtag->XpP instanceof FloatTag)){
$this->namedtag->XpP = new FloatTag("XpP", $this->getXpProgress());
}
if(!isset($this->namedtag->XpTotal) or !($this->namedtag->XpTotal instanceof IntTag)){
$this->namedtag->XpTotal = new IntTag("XpTotal", $this->totalXp);
}else{
$this->totalXp = $this->namedtag["XpTotal"];
}
if(!isset($this->namedtag->XpSeed) or !($this->namedtag->XpSeed instanceof IntTag)){
$this->namedtag->XpSeed = new IntTag("XpSeed", $this->xpSeed ?? ($this->xpSeed = mt_rand(PHP_INT_MIN, PHP_INT_MAX)));
}else{
$this->xpSeed = $this->namedtag["XpSeed"];
}
}
protected function addAttributes(){
parent::addAttributes();
$this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::SATURATION));
$this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::EXHAUSTION));
$this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::HUNGER));
$this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::EXPERIENCE_LEVEL));
$this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::EXPERIENCE));
}
public function entityBaseTick($tickDiff = 1){
$hasUpdate = parent::entityBaseTick($tickDiff);
$food = $this->getFood();
$health = $this->getHealth();
if($food >= 18){
$this->foodTickTimer++;
if($this->foodTickTimer >= 80 and $health < $this->getMaxHealth()){
$this->heal(1, new EntityRegainHealthEvent($this, 1, EntityRegainHealthEvent::CAUSE_SATURATION));
$this->exhaust(3.0, PlayerExhaustEvent::CAUSE_HEALTH_REGEN);
$this->foodTickTimer = 0;
}
}elseif($food === 0){
$this->foodTickTimer++;
if($this->foodTickTimer >= 80){
$diff = $this->server->getDifficulty();
$can = false;
if($diff === 1){
$can = $health > 10;
}elseif($diff === 2){
$can = $health > 1;
}elseif($diff === 3){
$can = true;
}
if($can){
$this->attack(1, new EntityDamageEvent($this, EntityDamageEvent::CAUSE_STARVATION, 1));
}
}
}
if($food <= 6){
if($this->isSprinting()){
$this->setSprinting(false);
}
}
return $hasUpdate;
}
public function getName(){
@ -208,7 +455,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
throw new \InvalidStateException((new \ReflectionClass($this))->getShortName() . " must have a valid skin set");
}
if(!($this instanceof Player)){
$this->server->updatePlayerListData($this->getUniqueId(), $this->getId(), $this->getName(), $this->skinName, $this->skin, [$player]);
}
@ -258,5 +504,4 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
parent::close();
}
}
}

View File

@ -21,7 +21,6 @@
namespace pocketmine\entity;
use pocketmine\block\Block;
use pocketmine\event\entity\EntityDamageByChildEntityEvent;
use pocketmine\event\entity\EntityDamageByEntityEvent;
@ -32,9 +31,7 @@ use pocketmine\event\Timings;
use pocketmine\item\Item as ItemItem;
use pocketmine\math\Vector3;
use pocketmine\nbt\tag\ShortTag;
use pocketmine\network\Network;
use pocketmine\network\protocol\EntityEventPacket;
use pocketmine\Server;
use pocketmine\utils\BlockIterator;
@ -53,18 +50,26 @@ abstract class Living extends Entity implements Damageable{
if(isset($this->namedtag->HealF)){
$this->namedtag->Health = new ShortTag("Health", (int) $this->namedtag["HealF"]);
unset($this->namedtag->HealF);
}
if(!isset($this->namedtag->Health) or !($this->namedtag->Health instanceof ShortTag)){
}elseif(!isset($this->namedtag->Health) or !($this->namedtag->Health instanceof ShortTag)){
$this->namedtag->Health = new ShortTag("Health", $this->getMaxHealth());
}
$this->setHealth($this->namedtag["Health"]);
}
protected function addAttributes(){
$this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::HEALTH));
$this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::FOLLOW_RANGE));
$this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::KNOCKBACK_RESISTANCE));
$this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::MOVEMENT_SPEED));
$this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::ATTACK_DAMAGE));
$this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::ABSORPTION));
}
public function setHealth($amount){
$wasAlive = $this->isAlive();
parent::setHealth($amount);
$this->attributeMap->getAttribute(Attribute::HEALTH)->setValue($this->getHealth());
if($this->isAlive() and !$wasAlive){
$pk = new EntityEventPacket();
$pk->eid = $this->getId();
@ -73,6 +78,10 @@ abstract class Living extends Entity implements Damageable{
}
}
public function setMaxHealth($amount){
$this->attributeMap->getAttribute(Attribute::HEALTH)->setMaxValue($amount);
}
public function saveNBT(){
parent::saveNBT();
$this->namedtag->Health = new ShortTag("Health", $this->getHealth());
@ -99,15 +108,15 @@ abstract class Living extends Entity implements Damageable{
if($this->attackTime > 0 or $this->noDamageTicks > 0){
$lastCause = $this->getLastDamageCause();
if($lastCause !== null and $lastCause->getDamage() >= $damage){
$source->setCancelled();
$source->setCancelled();
}
}
parent::attack($damage, $source);
parent::attack($damage, $source);
if($source->isCancelled()){
return;
}
if($source->isCancelled()){
return;
}
if($source instanceof EntityDamageByEntityEvent){
$e = $source->getDamager();
@ -285,8 +294,7 @@ abstract class Living extends Entity implements Damageable{
if($block instanceof Block){
return $block;
}
}catch (\ArrayOutOfBoundsException $e){
}catch(\ArrayOutOfBoundsException $e){
}
return null;

View File

@ -49,6 +49,7 @@ class EntityDamageEvent extends EntityEvent implements Cancellable{
const CAUSE_SUICIDE = 12;
const CAUSE_MAGIC = 13;
const CAUSE_CUSTOM = 14;
const CAUSE_STARVATION = 15;
private $cause;

View File

@ -0,0 +1,49 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\event\entity;
use pocketmine\block\Block;
use pocketmine\entity\Entity;
use pocketmine\item\FoodSource;
class EntityEatBlockEvent extends EntityEatEvent{
public function __construct(Entity $entity, FoodSource $foodSource){
if(!($foodSource instanceof Block)){
throw new \InvalidArgumentException("Food source must be a block");
}
parent::__construct($entity, $foodSource);
}
/**
* @return Block
*/
public function getResidue(){
return parent::getResidue();
}
public function setResidue($residue){
if(!($residue instanceof Block)){
throw new \InvalidArgumentException("Eating a Block can only result in a Block residue");
}
parent::setResidue($residue);
}
}

View File

@ -0,0 +1,99 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\event\entity;
use pocketmine\entity\Effect;
use pocketmine\entity\Entity;
use pocketmine\event\Cancellable;
use pocketmine\item\FoodSource;
class EntityEatEvent extends EntityEvent implements Cancellable{
public static $handlerList = null;
/** @var FoodSource */
private $foodSource;
/** @var int */
private $foodRestore;
/** @var float */
private $saturationRestore;
private $residue;
/** @var Effect[] */
private $additionalEffects;
public function __construct(Entity $entity, FoodSource $foodSource){
$this->entity = $entity;
$this->foodSource = $foodSource;
$this->foodRestore = $foodSource->getFoodRestore();
$this->saturationRestore = $foodSource->getSaturationRestore();
$this->residue = $foodSource->getResidue();
$this->additionalEffects = $foodSource->getAdditionalEffects();
}
public function getFoodSource(){
return $this->foodSource;
}
public function getFoodRestore() : int{
return $this->foodRestore;
}
public function setFoodRestore(int $foodRestore){
$this->foodRestore = $foodRestore;
}
public function getSaturationRestore() : float{
return $this->saturationRestore;
}
public function setSaturationRestore(float $saturationRestore){
$this->saturationRestore = $saturationRestore;
}
public function getResidue(){
return $this->residue;
}
public function setResidue($residue){
$this->residue = $residue;
}
/**
* @return Effect[]
*/
public function getAdditionalEffects(){
return $this->additionalEffects;
}
/**
* @param Effect[] $additionalEffects
*
* @throws \TypeError
*/
public function setAdditionalEffects(array $additionalEffects){
foreach($additionalEffects as $effect){
if(!($effect instanceof Effect)){
throw new \TypeError("Argument 1 passed to EntityEatEvent::setAdditionalEffects() must be an Effect array");
}
}
$this->additionalEffects = $additionalEffects;
}
}

View File

@ -0,0 +1,46 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\event\entity;
use pocketmine\entity\Entity;
use pocketmine\item\Food;
use pocketmine\item\Item;
class EntityEatItemEvent extends EntityEatEvent{
public function __construct(Entity $entity, Food $foodSource){
parent::__construct($entity, $foodSource);
}
/**
* @return Item
*/
public function getResidue(){
return parent::getResidue();
}
public function setResidue($residue){
if(!($residue instanceof Item)){
throw new \InvalidArgumentException("Eating an Item can only result in an Item residue");
}
parent::setResidue($residue);
}
}

View File

@ -31,6 +31,7 @@ class EntityRegainHealthEvent extends EntityEvent implements Cancellable{
const CAUSE_EATING = 1;
const CAUSE_MAGIC = 2;
const CAUSE_CUSTOM = 3;
const CAUSE_SATURATION = 4;
private $amount;
private $reason;

View File

@ -0,0 +1,66 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\event\player;
use pocketmine\entity\Human;
use pocketmine\event\Cancellable;
use pocketmine\Player;
class PlayerExhaustEvent extends PlayerEvent implements Cancellable{
public static $handlerList = null;
const CAUSE_ATTACK = 1;
const CAUSE_DAMAGE = 2;
const CAUSE_MINING = 3;
const CAUSE_HEALTH_REGEN = 4;
const CAUSE_POTION = 5;
const CAUSE_WALKING = 6;
const CAUSE_SNEAKING = 7;
const CAUSE_SWIMMING = 8;
const CAUSE_JUMPING = 10;
const CAUSE_CUSTOM = 11;
const CAUSE_FLAG_SPRINT = 0x10000;
/** @var float */
private $amount;
public function __construct(Human $human, float $amount, int $cause){
$this->player = $human;
$this->amount = $amount;
}
/**
* @return Human|Player
*/
public function getPlayer(){
return $this->player;
}
public function getAmount() : float{
return $this->amount;
}
public function setAmount(float $amount){
$this->amount = $amount;
}
}

View File

@ -22,9 +22,16 @@
namespace pocketmine\item;
class Apple extends Item{
class Apple extends Food{
public function __construct($meta = 0, $count = 1){
parent::__construct(self::APPLE, 0, $count, "Apple");
}
public function getFoodRestore() : int{
return 4;
}
public function getSaturationRestore() : float{
return 2.4;
}
}

View File

@ -21,10 +21,17 @@
namespace pocketmine\item;
class BakedPotato extends Item{
class BakedPotato extends Food{
public function __construct($meta = 0, $count = 1){
parent::__construct(self::BAKED_POTATO, $meta, $count, "Baked Potato");
}
public function getFoodRestore() : int{
return 5;
}
public function getSaturationRestore() : float{
return 7.2;
}
}

View File

@ -21,10 +21,17 @@
namespace pocketmine\item;
class Beetroot extends Item{
class Beetroot extends Food{
public function __construct($meta = 0, $count = 1){
parent::__construct(self::BEETROOT, $meta, $count, "Beetroot");
}
public function getFoodRestore() : int{
return 1;
}
public function getSaturationRestore() : float{
return 1.2;
}
}

View File

@ -22,7 +22,7 @@
namespace pocketmine\item;
class BeetrootSoup extends Item{
class BeetrootSoup extends Food{
public function __construct($meta = 0, $count = 1){
parent::__construct(self::BEETROOT_SOUP, 0, $count, "Beetroot Soup");
}
@ -30,4 +30,16 @@ class BeetrootSoup extends Item{
public function getMaxStackSize(){
return 1;
}
public function getFoodRestore() : int{
return 6;
}
public function getSaturationRestore() : float{
return 7.2;
}
public function getResidue(){
return Item::get(Item::BOWL);
}
}

View File

@ -21,8 +21,8 @@
namespace pocketmine\item;
class BlazePowder extends Item {
public function __construct($meta = 0, $count =1){
parent::__construct(self::BLAZE_POWDER, $meta, $count, "Blaze Powder");
}
class BlazePowder extends Item{
public function __construct($meta = 0, $count = 1){
parent::__construct(self::BLAZE_POWDER, $meta, $count, "Blaze Powder");
}
}

View File

@ -21,8 +21,8 @@
namespace pocketmine\item;
class Boat extends Item {
public function __construct($meta = 0, $count =1){
parent::__construct(self::BOAT, $meta, $count, "Boat");
}
class Boat extends Item{
public function __construct($meta = 0, $count = 1){
parent::__construct(self::BOAT, $meta, $count, "Boat");
}
}

View File

@ -21,10 +21,17 @@
namespace pocketmine\item;
class Bread extends Item{
class Bread extends Food{
public function __construct($meta = 0, $count = 1){
parent::__construct(self::BREAD, $meta, $count, "Bread");
}
public function getFoodRestore() : int{
return 5;
}
public function getSaturationRestore() : float{
return 6;
}
}

View File

@ -21,8 +21,8 @@
namespace pocketmine\item;
class BrewingStand extends Item {
public function __construct($meta = 0, $count =1){
parent::__construct(self::BREWING_STAND, $meta, $count, "Brewing Stand");
}
class BrewingStand extends Item{
public function __construct($meta = 0, $count = 1){
parent::__construct(self::BREWING_STAND, $meta, $count, "Brewing Stand");
}
}

View File

@ -23,9 +23,17 @@ namespace pocketmine\item;
use pocketmine\block\Block;
class Carrot extends Item{
class Carrot extends Food{
public function __construct($meta = 0, $count = 1){
$this->block = Block::get(Item::CARROT_BLOCK);
parent::__construct(self::CARROT, 0, $count, "Carrot");
}
public function getFoodRestore() : int{
return 3;
}
public function getSaturationRestore() : float{
return 4.8;
}
}

View File

@ -21,10 +21,17 @@
namespace pocketmine\item;
class CookedChicken extends Item{
class CookedChicken extends Food{
public function __construct($meta = 0, $count = 1){
parent::__construct(self::COOKED_CHICKEN, $meta, $count, "Cooked Chicken");
}
public function getFoodRestore() : int{
return 6;
}
public function getSaturationRestore() : float{
return 7.2;
}
}

View File

@ -21,13 +21,16 @@
namespace pocketmine\item;
class CookedFish extends Item{
class CookedFish extends Fish{
public function __construct($meta = 0, $count = 1){
parent::__construct(self::COOKED_FISH, $meta, $count, "Cooked Fish");
if($this->meta === 1){
$this->name = "Cooked Salmon";
}
Food::__construct(self::COOKED_FISH, $meta, $count, $meta === self::FISH_SALMON ? "Cooked Salmon" : "Cooked Fish");
}
public function getFoodRestore() : int{
return $this->meta === self::FISH_SALMON ? 6 : 5;
}
public function getSaturationRestore() : float{
return $this->meta === self::FISH_SALMON ? 9.6 : 6;
}
}

View File

@ -21,10 +21,17 @@
namespace pocketmine\item;
class CookedPorkchop extends Item{
class CookedPorkchop extends Food{
public function __construct($meta = 0, $count = 1){
parent::__construct(self::COOKED_PORKCHOP, $meta, $count, "Cooked Porkchop");
}
public function getFoodRestore() : int{
return 8;
}
public function getSaturationRestore() : float{
return 12.8;
}
}

View File

@ -21,8 +21,16 @@
namespace pocketmine\item;
class CookedRabbit extends Item {
public function __construct($meta = 0, $count =1){
parent::__construct(self::COOKED_RABBIT, $meta, $count, "Cooked Rabbit");
}
class CookedRabbit extends Food{
public function __construct($meta = 0, $count = 1){
parent::__construct(self::COOKED_RABBIT, $meta, $count, "Cooked Rabbit");
}
public function getFoodRestore() : int{
return 5;
}
public function getSaturationRestore() : float{
return 6;
}
}

View File

@ -21,10 +21,17 @@
namespace pocketmine\item;
class Cookie extends Item{
class Cookie extends Food{
public function __construct($meta = 0, $count = 1){
parent::__construct(self::COOKIE, $meta, $count, "Cookie");
}
public function getFoodRestore() : int{
return 2;
}
public function getSaturationRestore() : float{
return 0.4;
}
}

View File

@ -21,8 +21,8 @@
namespace pocketmine\item;
class FermentedSpiderEye extends Item {
public function __construct($meta = 0, $count =1){
class FermentedSpiderEye extends Item{
public function __construct($meta = 0, $count = 1){
parent::__construct(self::FERMENTED_SPIDER_EYE, $meta, $count, "Fermented Spider Eye");
}
}
}

View File

@ -21,17 +21,57 @@
namespace pocketmine\item;
use pocketmine\entity\Effect;
class Fish extends Food{
const FISH_FISH = 0;
const FISH_SALMON = 1;
const FISH_CLOWNFISH = 2;
const FISH_PUFFERFISH = 3;
class Fish extends Item{
public function __construct($meta = 0, $count = 1){
parent::__construct(self::RAW_FISH, $meta, $count, "Raw Fish");
if($this->meta === 1){
$this->name = "Raw Salmon";
}elseif($this->meta === 2){
$this->name = "Clownfish";
}elseif($this->meta === 3){
$this->name = "Pufferfish";
$name = "Raw Fish";
if($this->meta === self::FISH_SALMON){
$name = "Raw Salmon";
}elseif($this->meta === self::FISH_CLOWNFISH){
$name = "Clownfish";
}elseif($this->meta === self::FISH_PUFFERFISH){
$name = "Pufferfish";
}
parent::__construct(self::RAW_FISH, $meta, $count, $name);
}
public function getFoodRestore() : int{
if($this->meta === self::FISH_FISH){
return 2;
}elseif($this->meta === self::FISH_SALMON){
return 2;
}elseif($this->meta === self::FISH_CLOWNFISH){
return 1;
}elseif($this->meta === self::FISH_PUFFERFISH){
return 1.2;
}
return 0;
}
public function getSaturationRestore() : float{
if($this->meta === self::FISH_FISH){
return 0.4;
}elseif($this->meta === self::FISH_SALMON){
return 0.4;
}elseif($this->meta === self::FISH_CLOWNFISH){
return 0.2;
}elseif($this->meta === self::FISH_PUFFERFISH){
return 0.2;
}
return 0;
}
public function getAdditionalEffects() : array{
return $this->meta === self::FISH_PUFFERFISH ? [
Effect::getEffect(Effect::HUNGER)->setDuration(300)->setAmplifier(2),
Effect::getEffect(Effect::NAUSEA)->setDuration(300)->setAmplifier(1),
Effect::getEffect(Effect::POISON)->setDuration(1200)->setAmplifier(3),
] : [];
}
}

View File

@ -21,8 +21,6 @@
namespace pocketmine\item;
use pocketmine\block\Block;
class FishingRod extends Item{
public function __construct($meta = 0, $count = 1){
parent::__construct(self::FISHING_ROD, 0, $count, "Fishing Rod");

View File

@ -0,0 +1,73 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\item;
use pocketmine\entity\Entity;
use pocketmine\entity\Human;
use pocketmine\event\entity\EntityEatItemEvent;
use pocketmine\network\protocol\EntityEventPacket;
use pocketmine\Player;
use pocketmine\Server;
abstract class Food extends Item implements FoodSource{
public function canBeConsumed() : bool{
return true;
}
public function canBeConsumedBy(Entity $entity) : bool{
return $entity instanceof Human and $entity->getFood() < $entity->getMaxFood();
}
public function getResidue(){
if($this->getCount() === 1){
return Item::get(0);
}else{
$new = clone $this;
$new->count--;
return $new;
}
}
public function getAdditionalEffects() : array{
return [];
}
public function onConsume(Entity $human){
$pk = new EntityEventPacket();
$pk->eid = $human->getId();
$pk->event = EntityEventPacket::USE_ITEM;
if($human instanceof Player){
$human->dataPacket($pk);
}
Server::broadcastPacket($human->getViewers(), $pk);
$ev = new EntityEatItemEvent($human, $this);
$human->addSaturation($ev->getSaturationRestore());
$human->addFood($ev->getFoodRestore());
foreach($ev->getAdditionalEffects() as $effect){
$human->addEffect($effect);
}
$human->getInventory()->setItemInHand($ev->getResidue());
}
}

View File

@ -0,0 +1,37 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\item;
use pocketmine\entity\Effect;
interface FoodSource{
public function getFoodRestore() : int;
public function getSaturationRestore() : float;
public function getResidue();
/**
* @return Effect[]
*/
public function getAdditionalEffects() : array;
}

View File

@ -21,8 +21,8 @@
namespace pocketmine\item;
class GlassBottle extends Item {
public function __construct($meta = 0, $count =1){
parent::__construct(self::GLASS_BOTTLE, $meta, $count, "Glass Bottle");
}
class GlassBottle extends Item{
public function __construct($meta = 0, $count = 1){
parent::__construct(self::GLASS_BOTTLE, $meta, $count, "Glass Bottle");
}
}

View File

@ -21,8 +21,8 @@
namespace pocketmine\item;
class GlisteringMelon extends Item {
public function __construct($meta = 0, $count =1){
parent::__construct(self::GLISTERING_MELON, $meta, $count, "Glistering Melon");
}
class GlisteringMelon extends Item{
public function __construct($meta = 0, $count = 1){
parent::__construct(self::GLISTERING_MELON, $meta, $count, "Glistering Melon");
}
}

View File

@ -21,10 +21,31 @@
namespace pocketmine\item;
class GoldenApple extends Item{
use pocketmine\entity\Effect;
class GoldenApple extends Food{
public function __construct($meta = 0, $count = 1){
parent::__construct(self::GOLDEN_APPLE, $meta, $count, "Golden Apple");
parent::__construct(self::GOLDEN_APPLE, $meta, $count, ($meta === 1 ? "Enchanted " : "") . "Golden Apple");
}
public function getFoodRestore() : int{
return 4;
}
public function getSaturationRestore() : float{
return 9.6;
}
public function getAdditionalEffects() : array{
return $this->meta === 1 ? [
Effect::getEffect(Effect::REGENERATION)->setDuration(600)->setAmplifier(4),
Effect::getEffect(Effect::ABSORPTION)->setDuration(2400),
Effect::getEffect(Effect::DAMAGE_RESISTANCE)->setDuration(6000),
Effect::getEffect(Effect::FIRE_RESISTANCE)->setDuration(6000),
] : [
Effect::getEffect(Effect::REGENERATION)->setDuration(100)->setAmplifier(1),
Effect::getEffect(Effect::ABSORPTION)->setDuration(2400)
];
}
}

View File

@ -21,8 +21,16 @@
namespace pocketmine\item;
class GoldenCarrot extends Item {
public function __construct($meta = 0, $count =1){
parent::__construct(self::GOLDEN_CARROT, $meta, $count, "Golden Carrot");
}
class GoldenCarrot extends Food{
public function __construct($meta = 0, $count = 1){
parent::__construct(self::GOLDEN_CARROT, $meta, $count, "Golden Carrot");
}
public function getFoodRestore() : int{
return 6;
}
public function getSaturationRestore() : float{
return 14.4;
}
}

View File

@ -296,7 +296,6 @@ class Item{
const STONECUTTER = 245;
const GLOWING_OBSIDIAN = 246;
//Normal Item IDs
const IRON_SHOVEL = 256;
const IRON_PICKAXE = 257;
@ -408,7 +407,6 @@ class Item{
const CAKE = 354;
const BED = 355;
const COOKIE = 357;
const SHEARS = 359;
@ -472,7 +470,6 @@ class Item{
const BEETROOT_SEED = 458;
const BEETROOT_SOUP = 459;
/** @var \SplFixedArray */
public static $list = null;
protected $block;
@ -1049,6 +1046,17 @@ class Item{
return $this->block !== null and $this->block->canBePlaced();
}
public function canBeConsumed() : bool{
return false;
}
public function canBeConsumedBy(Entity $entity) : bool{
return $this->canBeConsumed();
}
public function onConsume(Entity $entity){
}
public function getBlock() : Block{
if($this->block instanceof Block){
return clone $this->block;

View File

@ -21,8 +21,8 @@
namespace pocketmine\item;
class MagmaCream extends Item {
public function __construct($meta = 0, $count =1){
parent::__construct(self::MAGMA_CREAM, $meta, $count, "Magma Cream");
}
class MagmaCream extends Item{
public function __construct($meta = 0, $count = 1){
parent::__construct(self::MAGMA_CREAM, $meta, $count, "Magma Cream");
}
}

View File

@ -21,10 +21,17 @@
namespace pocketmine\item;
class Melon extends Item{
class Melon extends Food{
public function __construct($meta = 0, $count = 1){
parent::__construct(self::MELON, $meta, $count, "Melon");
}
public function getFoodRestore() : int{
return 2;
}
public function getSaturationRestore() : float{
return 1.2;
}
}

View File

@ -21,8 +21,7 @@
namespace pocketmine\item;
class MushroomStew extends Item{
class MushroomStew extends Food{
public function __construct($meta = 0, $count = 1){
parent::__construct(self::MUSHROOM_STEW, 0, $count, "Mushroom Stew");
}
@ -30,4 +29,16 @@ class MushroomStew extends Item{
public function getMaxStackSize(){
return 1;
}
public function getFoodRestore() : int{
return 6;
}
public function getSaturationRestore() : float{
return 7.2;
}
public function getResidue(){
return Item::get(Item::BOWL);
}
}

View File

@ -21,8 +21,8 @@
namespace pocketmine\item;
class NetherWart extends Item {
public function __construct($meta = 0, $count =1){
parent::__construct(self::NETHER_WART, $meta, $count, "Nether Wart");
}
class NetherWart extends Item{
public function __construct($meta = 0, $count = 1){
parent::__construct(self::NETHER_WART, $meta, $count, "Nether Wart");
}
}

View File

@ -23,9 +23,17 @@ namespace pocketmine\item;
use pocketmine\block\Block;
class Potato extends Item{
class Potato extends Food{
public function __construct($meta = 0, $count = 1){
$this->block = Block::get(Item::POTATO_BLOCK);
parent::__construct(self::POTATO, 0, $count, "Potato");
}
public function getFoodRestore() : int{
return 1;
}
public function getSaturationRestore() : float{
return 0.6;
}
}

View File

@ -21,8 +21,18 @@
namespace pocketmine\item;
class Potion extends Item {
public function __construct($meta = 0, $count =1){
parent::__construct(self::POTION, $meta, $count, "Potion");
}
use pocketmine\entity\Entity;
class Potion extends Item{
public function __construct($meta = 0, $count = 1){
parent::__construct(self::POTION, $meta, $count, "Potion");
}
public function canBeConsumed() : bool{
return true;
}
public function onConsume(Entity $entity){
// TODO: Implement potions
}
}

View File

@ -21,10 +21,17 @@
namespace pocketmine\item;
class PumpkinPie extends Item{
class PumpkinPie extends Food{
public function __construct($meta = 0, $count = 1){
parent::__construct(self::PUMPKIN_PIE, $meta, $count, "Pumpkin Pie");
}
public function getFoodRestore() : int{
return 8;
}
public function getSaturationRestore() : float{
return 4.8;
}
}

View File

@ -21,10 +21,17 @@
namespace pocketmine\item;
class RawBeef extends Item{
class RawBeef extends Food{
public function __construct($meta = 0, $count = 1){
parent::__construct(self::RAW_BEEF, $meta, $count, "Raw Beef");
}
public function getFoodRestore() : int{
return 3;
}
public function getSaturationRestore() : float{
return 1.8;
}
}

View File

@ -21,10 +21,25 @@
namespace pocketmine\item;
class RawChicken extends Item{
use pocketmine\entity\Effect;
class RawChicken extends Food{
public function __construct($meta = 0, $count = 1){
parent::__construct(self::RAW_CHICKEN, $meta, $count, "Raw Chicken");
}
public function getFoodRestore() : int{
return 2;
}
public function getSaturationRestore() : float{
return 1.2;
}
public function getAdditionalEffects() : array{
if(mt_rand(0, 9) < 3){
return Effect::getEffect(Effect::HUNGER)->setDuration(600);
}
}
}

View File

@ -3,6 +3,7 @@
/*
*
* ____ _ _ __ __ _ __ __ ____
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
@ -27,8 +28,8 @@ use pocketmine\level\format\FullChunk;
use pocketmine\level\Level;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\DoubleTag;
use pocketmine\nbt\tag\ListTag;
use pocketmine\nbt\tag\FloatTag;
use pocketmine\nbt\tag\ListTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\Player;

View File

@ -21,8 +21,22 @@
namespace pocketmine\item;
class SpiderEye extends Item {
public function __construct($meta = 0, $count =1){
use pocketmine\entity\Effect;
class SpiderEye extends Food{
public function __construct($meta = 0, $count = 1){
parent::__construct(self::SPIDER_EYE, $meta, $count, "Spider Eye");
}
}
public function getFoodRestore() : int{
return 2;
}
public function getSaturationRestore() : float{
return 3.2;
}
public function getAdditionalEffects() : array{
return [Effect::getEffect(Effect::POISON)->setDuration(80)];
}
}

View File

@ -21,10 +21,17 @@
namespace pocketmine\item;
class Steak extends Item{
class Steak extends Food{
public function __construct($meta = 0, $count = 1){
parent::__construct(self::STEAK, $meta, $count, "Steak");
}
public function getFoodRestore() : int{
return 8;
}
public function getSaturationRestore() : float{
return 12.8;
}
}

View File

@ -19,12 +19,10 @@
*
*/
namespace pocketmine\item;
use pocketmine\block\Block;
use pocketmine\entity\Entity;
use pocketmine\nbt\tag\ByteTag;
abstract class Tool extends Item{
const TIER_WOODEN = 1;

View File

@ -31,8 +31,8 @@ class EnchantmentEntry{
/**
* @param Enchantment[] $enchantments
* @param $cost
* @param $randomName
* @param number $cost
* @param string $randomName
*/
public function __construct(array $enchantments, $cost, $randomName){
$this->enchantments = $enchantments;

View File

@ -32,7 +32,7 @@ class EnchantmentList{
}
/**
* @param $slot
* @param $slot
* @param EnchantmentEntry $entry
*/
public function setSlot($slot, EnchantmentEntry $entry){