Implemented food and hunger

This commit is contained in:
PEMapModder 2016-02-10 22:49:48 +08:00
parent 1082e32fd7
commit 329a525ea1
47 changed files with 724 additions and 323 deletions

View File

@ -76,11 +76,9 @@ use pocketmine\inventory\PlayerInventory;
use pocketmine\inventory\ShapedRecipe;
use pocketmine\inventory\ShapelessRecipe;
use pocketmine\inventory\SimpleTransactionGroup;
use pocketmine\item\Item;
use pocketmine\level\ChunkLoader;
use pocketmine\level\format\FullChunk;
use pocketmine\level\format\LevelProvider;
use pocketmine\level\Level;
use pocketmine\level\Location;
use pocketmine\level\Position;
@ -93,13 +91,12 @@ use pocketmine\nbt\NBT;
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\LongTag;
use pocketmine\nbt\tag\ShortTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\network\Network;
use pocketmine\network\protocol\AdventureSettingsPacket;
use pocketmine\network\protocol\AnimatePacket;
use pocketmine\network\protocol\BatchPacket;
@ -110,20 +107,20 @@ use pocketmine\network\protocol\DisconnectPacket;
use pocketmine\network\protocol\EntityEventPacket;
use pocketmine\network\protocol\FullChunkDataPacket;
use pocketmine\network\protocol\Info as ProtocolInfo;
use pocketmine\network\protocol\MovePlayerPacket;
use pocketmine\network\protocol\PlayerActionPacket;
use pocketmine\network\protocol\PlayStatusPacket;
use pocketmine\network\protocol\RespawnPacket;
use pocketmine\network\protocol\SetPlayerGameTypePacket;
use pocketmine\network\protocol\TextPacket;
use pocketmine\network\protocol\MovePlayerPacket;
use pocketmine\network\protocol\SetDifficultyPacket;
use pocketmine\network\protocol\SetEntityMotionPacket;
use pocketmine\network\protocol\SetHealthPacket;
use pocketmine\network\protocol\SetPlayerGameTypePacket;
use pocketmine\network\protocol\SetSpawnPositionPacket;
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;
@ -133,8 +130,6 @@ use pocketmine\tile\Sign;
use pocketmine\tile\Spawnable;
use pocketmine\tile\Tile;
use pocketmine\utils\TextFormat;
use raklib\Binary;
/**
@ -247,7 +242,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
*
@ -486,7 +482,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
return $this->perm->getEffectivePermissions();
}
/**
* @param SourceInterface $interface
* @param null $clientID
@ -853,7 +848,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->loadQueue = $newOrder;
Timings::$playerChunkOrderTimer->stopTiming();
return true;
@ -984,12 +978,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
*/
@ -1015,7 +1009,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();
@ -1023,7 +1016,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$pk->action = 3; //Wake up
$this->dataPacket($pk);
}
}
/**
@ -1211,6 +1203,17 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
return false;
}
public function entityBaseTick($tickDiff = 1){
parent::entityBaseTick($tickDiff);
$entries = $this->attributeMap->needSend();
if(count($entries) > 0){
$pk = new UpdateAttributesPacket();
$pk->entityId = 0;
$pk->entries = $entries;
$this->dataPacket($pk);
}
}
protected function checkGroundState($movX, $movY, $movZ, $dx, $dy, $dz){
if(!$this->onGround or $movY != 0){
$bb = clone $this->boundingBox;
@ -1446,7 +1449,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}
protected function updateMovement(){
}
public function onUpdate($currentTick){
@ -1529,7 +1531,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){
@ -1610,7 +1611,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();
@ -1750,7 +1750,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
return;
}
$timings = Timings::getReceiveDataPacketTimings($packet);
$timings->startTiming();
@ -1948,7 +1947,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){
@ -2076,7 +2074,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
break;
}
$nbt = new CompoundTag("", [
"Pos" => new ListTag("Pos", [
new DoubleTag("", $this->x),
@ -2249,7 +2246,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{
@ -2405,7 +2401,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}
}
break;
case ProtocolInfo::ANIMATE_PACKET:
if($this->spawned === false or !$this->isAlive()){
@ -2434,7 +2429,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
switch($packet->event){
case 9: //Eating
$items = [ //TODO: move this to item classes
$items = [ //TODO: change to hunger; add RabbitStew and RawRabbit and RottenFlesh
Item::APPLE => 4,
Item::MUSHROOM_STEW => 10,
Item::BEETROOT_SOUP => 10,
@ -2593,7 +2588,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){
@ -2781,7 +2775,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){
@ -2915,7 +2908,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
return;
}
$message = $message->getText();
}
$mes = explode("\n", $this->server->getLanguage()->translateString($message));
@ -3206,7 +3198,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
break;
default:
}
Entity::kill();
@ -3227,7 +3218,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;
@ -3412,7 +3402,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;
@ -3420,7 +3409,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}
}
/**
* @param Inventory $inventory
*
@ -3488,25 +3476,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(){

View File

@ -94,7 +94,7 @@ class Cake extends Transparent{
++$this->meta;
$ev = new EntityRegainHealthEvent($player, 3, EntityRegainHealthEvent::CAUSE_EATING);
$player->heal($ev->getAmount(), $ev);
$player->heal($ev->getAmount(), $ev); // TODO hunger
if(!$ev->isCancelled()){
if($this->meta >= 0x06){

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);
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);
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,6 +70,7 @@ class Attribute{
* @param float $maxValue
* @param float $defaultValue
* @param bool $shouldSend
*
* @return Attribute
*/
public static function addAttribute($id, $name, $minValue, $maxValue, $defaultValue, $shouldSend = false){
@ -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){
@ -98,7 +111,7 @@ class Attribute{
$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!");
}
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!");
}
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!");
}
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()){
if(!$fit){
throw new \InvalidArgumentException("Value $value exceeds the range!");
}
$value = min(max($value, $this->getMinValue()), $this->getMaxValue());
}
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(){
$this->desynchronized = false;
}
}

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\entity;
class AttributeMap{
/** @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;
}
public function needSend() : array{
return array_filter($this->attributes, function (Attribute $attribute){
return $attribute->isSyncable() and $attribute->isDesynchronized();
});
}
}

View File

@ -23,11 +23,9 @@ 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 Effect{
const SPEED = 1;
const SLOWNESS = 2;
@ -46,15 +44,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; // TODO implement
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 +74,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
// TODO Blindness %potion.blindness
// TODO Night Vision %potion.nightVision
// TODO Hunger %potion.hunger
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
// TODO Absorption %potion.absorption
// TODO Saturation %potion.saturation
}
/**
* @param int $id
*
* @return $this
*/
public static function getEffect($id){

View File

@ -48,20 +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{
@ -192,6 +189,9 @@ abstract class Entity extends Location implements Metadatable{
protected $fireProof;
private $invulnerable;
/** @var AttributeMap */
protected $attributeMap;
protected $gravity;
protected $drag;
@ -266,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();
@ -526,6 +528,8 @@ abstract class Entity extends Location implements Metadatable{
}
$this->scheduleUpdate();
$this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::KNOCKBACK_RESISTANCE));
}
/**
@ -670,6 +674,10 @@ abstract class Entity extends Location implements Metadatable{
return $this->lastDamageCause;
}
public function getAttributeMap(){
return $this->attributeMap;
}
/**
* @return int
*/

View File

@ -24,17 +24,16 @@ namespace pocketmine\entity;
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\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 +46,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
/** @var PlayerInventory */
protected $inventory;
/** @var UUID */
protected $uuid;
protected $rawUUID;
@ -91,6 +89,60 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
$this->skinName = $skinName;
}
public function getFood() : float{
return (float) $this->attributeMap->getAttribute(Attribute::HUNGER)->getValue();
}
public function setFood(float $food){
$this->attributeMap->getAttribute(Attribute::HUNGER)->setValue($food);
}
public function addFood(float $amount){
$this->attributeMap->getAttribute(Attribute::HUNGER)->setValue($amount, true);
}
public function getSaturation() : float{
return $this->attributeMap->getAttribute(Attribute::HUNGER)->getValue();
}
public function setSaturation(float $saturation){
$this->attributeMap->getAttribute(Attribute::HUNGER)->setValue($saturation);
}
public function addSaturation(float $amount){
$this->attributeMap->getAttribute(Attribute::SATURATION)->setValue($amount, true);
}
public function getExhaustion() : float{
return $this->attributeMap->getAttribute(Attribute::EXHAUSTION)->getValue();
}
public function setExhaustion(float $exhaustion){
$this->attributeMap->getAttribute(Attribute::EXHAUSTION)->setValue($exhaustion);
}
public function exhaust(float $amount){
$exhaustion = $this->getExhaustion();
$exhaustion += $amount;
if($exhaustion >= 4.0){
$exhaustion -= 4.0;
$this->setExhaustion($exhaustion);
$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);
}
}
}
}
public function getInventory(){
return $this->inventory;
}
@ -105,7 +157,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
$this->addWindow($this->inventory, 0);
}
if(!($this instanceof Player)){
if(isset($this->namedtag->NameTag)){
$this->setNameTag($this->namedtag["NameTag"]);
@ -130,6 +181,13 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
}
}
$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::ATTACK_DAMAGE));
$this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::EXPERIENCE_LEVEL));
$this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::EXPERIENCE));
parent::initEntity();
}
@ -208,7 +266,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 +315,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;
@ -60,11 +57,17 @@ abstract class Living extends Entity implements Damageable{
}
$this->setHealth($this->namedtag["Health"]);
$this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::ABSORPTION));
$this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::HEALTH));
$this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::MOVEMENT_SPEED));
$this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::FOLLOW_RANGE));
}
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 +76,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());
@ -286,7 +293,6 @@ abstract class Living extends Entity implements Damageable{
return $block;
}
}catch(\ArrayOutOfBoundsException $e){
}
return null;

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() : Item{
return Item::get(Item::BOWL);
}
}

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

@ -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() : int{
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 {
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,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 getAdditionEffects(){
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,50 @@
<?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;
use pocketmine\Player;
abstract class Food extends Item{
public abstract function getFoodRestore() : int;
public abstract function getSaturationRestore() : float;
public function getResidue() : Item{
if($this->getCount() === 1){
return Item::get(0);
}else{
$this->count--;
return $this;
}
}
/**
* @return Effect[]
*/
public function getAdditionEffects() : array{
return [];
}
public function onEat(Player $player){
}
}

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 getAdditionEffects() : 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 {
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

@ -25,23 +25,18 @@
namespace pocketmine\item;
use pocketmine\block\Block;
use pocketmine\block\Fence;
use pocketmine\block\Flower;
use pocketmine\entity\Entity;
use pocketmine\entity\Squid;
use pocketmine\entity\Villager;
use pocketmine\entity\Zombie;
use pocketmine\inventory\Fuel;
use pocketmine\item\enchantment\Enchantment;
use pocketmine\level\Level;
use pocketmine\nbt\NBT;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\ListTag;
use pocketmine\nbt\tag\ShortTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\Player;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\NBT;
use pocketmine\utils\Config;
use pocketmine\Server;
use pocketmine\utils\Config;
class Item{
@ -301,7 +296,6 @@ class Item{
const STONECUTTER = 245;
const GLOWING_OBSIDIAN = 246;
//Normal Item IDs
const IRON_SHOVEL = 256;
const IRON_PICKAXE = 257;
@ -413,7 +407,6 @@ class Item{
const CAKE = 354;
const BED = 355;
const COOKIE = 357;
const SHEARS = 359;
@ -477,7 +470,6 @@ class Item{
const BEETROOT_SEED = 458;
const BEETROOT_SOUP = 459;
/** @var \SplFixedArray */
public static $list = null;
protected $block;
@ -679,6 +671,7 @@ class Item{
/**
* @param $index
*
* @return Item
*/
public static function getCreativeItem(int $index){
@ -713,6 +706,7 @@ class Item{
/**
* @param string $str
* @param bool $multiple
*
* @return Item[]|Item
*/
public static function fromString(string $str, bool $multiple = false){
@ -851,6 +845,7 @@ class Item{
/**
* @param $id
*
* @return Enchantment|null
*/
public function getEnchantment(int $id){

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() : Item{
return Item::get(Item::BOWL);
}
}

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,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 getAdditionEffects() : 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 {
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 getAdditionEffects() : 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;