From 329a525ea1e07442059431d3195d4d37915fcc1c Mon Sep 17 00:00:00 2001 From: PEMapModder Date: Wed, 10 Feb 2016 22:49:48 +0800 Subject: [PATCH 01/10] Implemented food and hunger --- src/pocketmine/Player.php | 171 ++++++++---------- src/pocketmine/block/Cake.php | 2 +- src/pocketmine/entity/Attribute.php | 84 ++++++--- src/pocketmine/entity/AttributeMap.php | 46 +++++ src/pocketmine/entity/Effect.php | 23 +-- src/pocketmine/entity/Entity.php | 16 +- src/pocketmine/entity/Human.php | 78 ++++++-- src/pocketmine/entity/Living.php | 38 ++-- src/pocketmine/item/Apple.php | 9 +- src/pocketmine/item/BakedPotato.php | 9 +- src/pocketmine/item/Beetroot.php | 9 +- src/pocketmine/item/BeetrootSoup.php | 14 +- src/pocketmine/item/BlazePowder.php | 8 +- src/pocketmine/item/Boat.php | 8 +- src/pocketmine/item/Bowl.php | 10 +- src/pocketmine/item/Bread.php | 9 +- src/pocketmine/item/BrewingStand.php | 8 +- src/pocketmine/item/Carrot.php | 12 +- src/pocketmine/item/CookedChicken.php | 19 +- src/pocketmine/item/CookedFish.php | 25 +-- src/pocketmine/item/CookedPorkchop.php | 19 +- src/pocketmine/item/CookedRabbit.php | 16 +- src/pocketmine/item/Cookie.php | 19 +- src/pocketmine/item/FermentedSpiderEye.php | 6 +- src/pocketmine/item/Fish.php | 68 +++++-- src/pocketmine/item/FishingRod.php | 2 - src/pocketmine/item/Food.php | 50 +++++ src/pocketmine/item/GlassBottle.php | 8 +- src/pocketmine/item/GlisteringMelon.php | 8 +- src/pocketmine/item/GoldenApple.php | 35 +++- src/pocketmine/item/GoldenCarrot.php | 16 +- src/pocketmine/item/Item.php | 25 +-- src/pocketmine/item/MagmaCream.php | 8 +- src/pocketmine/item/Melon.php | 19 +- src/pocketmine/item/MushroomStew.php | 27 ++- src/pocketmine/item/NetherWart.php | 8 +- src/pocketmine/item/Potato.php | 10 +- src/pocketmine/item/Potion.php | 8 +- src/pocketmine/item/PumpkinPie.php | 9 +- src/pocketmine/item/RawBeef.php | 9 +- src/pocketmine/item/RawChicken.php | 17 +- src/pocketmine/item/SpawnEgg.php | 15 +- src/pocketmine/item/SpiderEye.php | 20 +- src/pocketmine/item/Steak.php | 19 +- src/pocketmine/item/Tool.php | 2 - .../item/enchantment/EnchantmentEntry.php | 4 +- .../item/enchantment/EnchantmentList.php | 2 +- 47 files changed, 724 insertions(+), 323 deletions(-) create mode 100644 src/pocketmine/entity/AttributeMap.php create mode 100644 src/pocketmine/item/Food.php diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index 819949329..ff9120364 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -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; /** @@ -221,7 +216,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade protected $viewDistance; protected $chunksPerTick; - protected $spawnThreshold; + protected $spawnThreshold; /** @var null|Position */ private $spawnPosition = null; @@ -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 @@ -505,7 +500,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade $this->clientID = $clientID; $this->loaderId = Level::generateChunkLoaderId($this); $this->chunksPerTick = (int) $this->server->getProperty("chunk-sending.per-tick", 4); - $this->spawnThreshold = (int) $this->server->getProperty("chunk-sending.spawn-threshold", 56); + $this->spawnThreshold = (int) $this->server->getProperty("chunk-sending.spawn-threshold", 56); $this->spawnPosition = null; $this->gamemode = $this->server->getGamemode(); $this->setLevel($this->server->getDefaultLevel()); @@ -559,9 +554,9 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade return $this->displayName; } - /** - * @param string $name - */ + /** + * @param string $name + */ public function setDisplayName($name){ $this->displayName = $name; if($this->spawned){ @@ -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(); @@ -1906,13 +1905,13 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade break; } }else{ - if($packet->selectedSlot >= 0 and $packet->selectedSlot < 9){ - $this->inventory->setHeldItemIndex($packet->selectedSlot); - $this->inventory->setHeldItemSlot($packet->slot); - }else{ - $this->inventory->sendContents($this); - break; - } + if($packet->selectedSlot >= 0 and $packet->selectedSlot < 9){ + $this->inventory->setHeldItemIndex($packet->selectedSlot); + $this->inventory->setHeldItemSlot($packet->slot); + }else{ + $this->inventory->sendContents($this); + break; + } } }elseif($item === null or $slot === -1 or !$item->deepEquals($packet->item)){ // packet error or not implemented $this->inventory->sendContents($this); @@ -1922,13 +1921,13 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade $this->inventory->setItem($packet->selectedSlot, $item); $this->inventory->setHeldItemSlot($packet->selectedSlot); }else{ - if($packet->selectedSlot >= 0 and $packet->selectedSlot < $this->inventory->getHotbarSize()){ - $this->inventory->setHeldItemIndex($packet->selectedSlot); - $this->inventory->setHeldItemSlot($slot); - }else{ - $this->inventory->sendContents($this); - break; - } + if($packet->selectedSlot >= 0 and $packet->selectedSlot < $this->inventory->getHotbarSize()){ + $this->inventory->setHeldItemIndex($packet->selectedSlot); + $this->inventory->setHeldItemSlot($slot); + }else{ + $this->inventory->sendContents($this); + break; + } } $this->inventory->sendHeldItem($this->hasSpawned); @@ -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){ @@ -2069,14 +2067,13 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade break; case PlayerActionPacket::ACTION_RELEASE_ITEM: if($this->startAction > -1 and $this->getDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ACTION)){ - if($this->inventory->getItemInHand()->getId() === Item::BOW) { + if($this->inventory->getItemInHand()->getId() === Item::BOW){ $bow = $this->inventory->getItemInHand(); - if ($this->isSurvival() and !$this->inventory->contains(Item::get(Item::ARROW, 0, 1))) { + if($this->isSurvival() and !$this->inventory->contains(Item::get(Item::ARROW, 0, 1))){ $this->inventory->sendContents($this); break; } - $nbt = new CompoundTag("", [ "Pos" => new ListTag("Pos", [ new DoubleTag("", $this->x), @@ -2100,35 +2097,35 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade $f = min((($p ** 2) + $p * 2) / 3, 1) * 2; $ev = new EntityShootBowEvent($this, $bow, Entity::createEntity("Arrow", $this->chunk, $nbt, $this, $f == 2 ? true : false), $f); - if ($f < 0.1 or $diff < 5) { + if($f < 0.1 or $diff < 5){ $ev->setCancelled(); } $this->server->getPluginManager()->callEvent($ev); - if ($ev->isCancelled()) { + if($ev->isCancelled()){ $ev->getProjectile()->kill(); $this->inventory->sendContents($this); - } else { + }else{ $ev->getProjectile()->setMotion($ev->getProjectile()->getMotion()->multiply($ev->getForce())); if($this->isSurvival()){ $this->inventory->removeItem(Item::get(Item::ARROW, 0, 1)); $bow->setDamage($bow->getDamage() + 1); - if ($bow->getDamage() >= 385) { + if($bow->getDamage() >= 385){ $this->inventory->setItemInHand(Item::get(Item::AIR, 0, 0)); - } else { + }else{ $this->inventory->setItemInHand($bow); } } - if ($ev->getProjectile() instanceof Projectile) { + if($ev->getProjectile() instanceof Projectile){ $this->server->getPluginManager()->callEvent($projectileEv = new ProjectileLaunchEvent($ev->getProjectile())); - if ($projectileEv->isCancelled()) { + if($projectileEv->isCancelled()){ $ev->getProjectile()->kill(); - } else { + }else{ $ev->getProjectile()->spawnToAll(); $this->level->addSound(new LaunchSound($this), $this->getViewers()); } - } else { + }else{ $ev->getProjectile()->spawnToAll(); } } @@ -2146,7 +2143,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade $this->dataPacket($pk); Server::broadcastPacket($this->getViewers(), $pk); - if ($this->isSurvival()) { + if($this->isSurvival()){ $slot = $this->inventory->getItemInHand(); --$slot->count; $this->inventory->setItemInHand($slot); @@ -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{ @@ -2274,7 +2270,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade $this->level->sendBlocks([$this], [$target], UpdateBlockPacket::FLAG_ALL_PRIORITY); - $this->inventory->sendHeldItem($this); + $this->inventory->sendHeldItem($this); if($tile instanceof Spawnable){ $tile->spawnTo($this); @@ -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, @@ -2481,7 +2476,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade if(is_array($amount)){ $amount = isset($amount[$slot->getDamage()]) ? $amount[$slot->getDamage()] : 0; } - $ev = new EntityRegainHealthEvent($this, $amount, EntityRegainHealthEvent::CAUSE_EATING); + $ev = new EntityRegainHealthEvent($this, $amount, EntityRegainHealthEvent::CAUSE_EATING); $this->heal($ev->getAmount(), $ev); --$slot->count; @@ -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){ @@ -2645,7 +2639,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade $result = $packet->output[0]; if(!$canCraft or !$recipe->getResult()->deepEquals($result)){ - $this->server->getLogger()->debug("Unmatched recipe ". $recipe->getId() ." from player ". $this->getName() .": expected " . $recipe->getResult() . ", got ". $result .", using: " . implode(", ", $ingredients)); + $this->server->getLogger()->debug("Unmatched recipe " . $recipe->getId() . " from player " . $this->getName() . ": expected " . $recipe->getResult() . ", got " . $result . ", using: " . implode(", ", $ingredients)); $this->inventory->sendContents($this); break; } @@ -2669,7 +2663,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade } if(!$canCraft){ - $this->server->getLogger()->debug("Unmatched recipe ". $recipe->getId() ." from player ". $this->getName() .": client does not have enough items, using: " . implode(", ", $ingredients)); + $this->server->getLogger()->debug("Unmatched recipe " . $recipe->getId() . " from player " . $this->getName() . ": client does not have enough items, using: " . implode(", ", $ingredients)); $this->inventory->sendContents($this); break; } @@ -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){ @@ -2883,11 +2876,11 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade $this->server->getPluginManager()->callEvent($ev = new PlayerKickEvent($this, $reason, $this->getLeaveMessage())); if(!$ev->isCancelled()){ if($isAdmin){ - if(!$this->isBanned()) { - $message = "Kicked by admin." . ($reason !== "" ? " Reason: " . $reason : ""); - }else{ - $message = $reason; - } + if(!$this->isBanned()){ + $message = "Kicked by admin." . ($reason !== "" ? " Reason: " . $reason : ""); + }else{ + $message = $reason; + } }else{ if($reason === ""){ $message = "disconnectionScreen.noReason"; @@ -2910,12 +2903,11 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade */ public function sendMessage($message){ if($message instanceof TextContainer){ - if ($message instanceof TranslationContainer) { - $this->sendTranslation($message->getText(), $message->getParameters()); - return; - } - $message = $message->getText(); - + if($message instanceof TranslationContainer){ + $this->sendTranslation($message->getText(), $message->getParameters()); + return; + } + $message = $message->getText(); } $mes = explode("\n", $this->server->getLanguage()->translateString($message)); @@ -2966,7 +2958,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade * * @param string $message Message to be broadcasted * @param string $reason Reason showed in console - * @param bool $notify + * @param bool $notify */ public final function close($message = "", $reason = "generic reason", $notify = true){ @@ -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; @@ -3250,13 +3240,13 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade return; } - if($this->isCreative() - and $source->getCause() !== EntityDamageEvent::CAUSE_MAGIC - and $source->getCause() !== EntityDamageEvent::CAUSE_SUICIDE - and $source->getCause() !== EntityDamageEvent::CAUSE_VOID - ){ - $source->setCancelled(); - }elseif($this->allowFlight and $source->getCause() === EntityDamageEvent::CAUSE_FALL){ + if($this->isCreative() + and $source->getCause() !== EntityDamageEvent::CAUSE_MAGIC + and $source->getCause() !== EntityDamageEvent::CAUSE_SUICIDE + and $source->getCause() !== EntityDamageEvent::CAUSE_VOID + ){ + $source->setCancelled(); + }elseif($this->allowFlight and $source->getCause() === EntityDamageEvent::CAUSE_FALL){ $source->setCancelled(); } @@ -3355,11 +3345,11 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade /** * @param Vector3|Position|Location $pos - * @param float $yaw - * @param float $pitch + * @param float $yaw + * @param float $pitch * * @return bool - */ + */ public function teleport(Vector3 $pos, $yaw = null, $pitch = null){ if(!$this->isOnline()){ return false; @@ -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(){ diff --git a/src/pocketmine/block/Cake.php b/src/pocketmine/block/Cake.php index d95b64a7c..90f8efca6 100644 --- a/src/pocketmine/block/Cake.php +++ b/src/pocketmine/block/Cake.php @@ -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){ diff --git a/src/pocketmine/entity/Attribute.php b/src/pocketmine/entity/Attribute.php index a312ed3a7..4e48411bc 100644 --- a/src/pocketmine/entity/Attribute.php +++ b/src/pocketmine/entity/Attribute.php @@ -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){ @@ -88,7 +101,7 @@ class Attribute{ return clone $a; } } - + return null; } @@ -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; } @@ -106,13 +119,16 @@ class Attribute{ public function getMinValue(){ return $this->minValue; } - + public function setMinValue($minValue){ if($minValue > $this->getMaxValue()){ 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(){ + $this->desynchronized = false; + } } diff --git a/src/pocketmine/entity/AttributeMap.php b/src/pocketmine/entity/AttributeMap.php new file mode 100644 index 000000000..fe44474a5 --- /dev/null +++ b/src/pocketmine/entity/AttributeMap.php @@ -0,0 +1,46 @@ +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(); + }); + } +} diff --git a/src/pocketmine/entity/Effect.php b/src/pocketmine/entity/Effect.php index b10dc0d30..0f3d9e066 100644 --- a/src/pocketmine/entity/Effect.php +++ b/src/pocketmine/entity/Effect.php @@ -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 - self::$effects[Effect::WEAKNESS] = new Effect(Effect::WEAKNESS, "%potion.weakness", 72, 77, 72 , true); + // 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){ diff --git a/src/pocketmine/entity/Entity.php b/src/pocketmine/entity/Entity.php index 92527456a..4c286b1d5 100644 --- a/src/pocketmine/entity/Entity.php +++ b/src/pocketmine/entity/Entity.php @@ -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 */ diff --git a/src/pocketmine/entity/Human.php b/src/pocketmine/entity/Human.php index 170e8f0d6..7265c3f51 100644 --- a/src/pocketmine/entity/Human.php +++ b/src/pocketmine/entity/Human.php @@ -2,11 +2,11 @@ /* * - * ____ _ _ __ __ _ __ __ ____ - * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \ + * ____ _ _ __ __ _ __ __ ____ + * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \ * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) | - * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/ - * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_| + * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/ + * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_| * * 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 @@ -15,7 +15,7 @@ * * @author PocketMine Team * @link http://www.pocketmine.net/ - * + * * */ @@ -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(); } } - } diff --git a/src/pocketmine/entity/Living.php b/src/pocketmine/entity/Living.php index c65d0bfa8..ded684ab8 100644 --- a/src/pocketmine/entity/Living.php +++ b/src/pocketmine/entity/Living.php @@ -2,11 +2,11 @@ /* * - * ____ _ _ __ __ _ __ __ ____ - * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \ + * ____ _ _ __ __ _ __ __ ____ + * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \ * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) | - * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/ - * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_| + * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/ + * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_| * * 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 @@ -15,13 +15,12 @@ * * @author PocketMine Team * @link http://www.pocketmine.net/ - * + * * */ 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; @@ -44,7 +41,7 @@ abstract class Living extends Entity implements Damageable{ protected $drag = 0.02; protected $attackTime = 0; - + protected $invisible = false; protected function initEntity(){ @@ -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()); @@ -99,15 +106,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 +292,7 @@ abstract class Living extends Entity implements Damageable{ if($block instanceof Block){ return $block; } - }catch (\ArrayOutOfBoundsException $e){ - + }catch(\ArrayOutOfBoundsException $e){ } return null; diff --git a/src/pocketmine/item/Apple.php b/src/pocketmine/item/Apple.php index d54b34b83..13e6d1785 100644 --- a/src/pocketmine/item/Apple.php +++ b/src/pocketmine/item/Apple.php @@ -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; + } } \ No newline at end of file diff --git a/src/pocketmine/item/BakedPotato.php b/src/pocketmine/item/BakedPotato.php index 34792d715..92d261d96 100644 --- a/src/pocketmine/item/BakedPotato.php +++ b/src/pocketmine/item/BakedPotato.php @@ -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; + } } diff --git a/src/pocketmine/item/Beetroot.php b/src/pocketmine/item/Beetroot.php index 917c989a1..432e0c08d 100644 --- a/src/pocketmine/item/Beetroot.php +++ b/src/pocketmine/item/Beetroot.php @@ -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; + } } diff --git a/src/pocketmine/item/BeetrootSoup.php b/src/pocketmine/item/BeetrootSoup.php index 8a7a2425c..626167e30 100644 --- a/src/pocketmine/item/BeetrootSoup.php +++ b/src/pocketmine/item/BeetrootSoup.php @@ -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); + } } \ No newline at end of file diff --git a/src/pocketmine/item/BlazePowder.php b/src/pocketmine/item/BlazePowder.php index ce4d771cd..ca9276cd0 100644 --- a/src/pocketmine/item/BlazePowder.php +++ b/src/pocketmine/item/BlazePowder.php @@ -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"); + } } diff --git a/src/pocketmine/item/Boat.php b/src/pocketmine/item/Boat.php index e2c36b632..9c695c465 100644 --- a/src/pocketmine/item/Boat.php +++ b/src/pocketmine/item/Boat.php @@ -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"); + } } diff --git a/src/pocketmine/item/Bowl.php b/src/pocketmine/item/Bowl.php index 76f7feb6e..54f74cf2c 100644 --- a/src/pocketmine/item/Bowl.php +++ b/src/pocketmine/item/Bowl.php @@ -2,11 +2,11 @@ /* * - * ____ _ _ __ __ _ __ __ ____ - * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \ + * ____ _ _ __ __ _ __ __ ____ + * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \ * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) | - * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/ - * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_| + * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/ + * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_| * * 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 @@ -15,7 +15,7 @@ * * @author PocketMine Team * @link http://www.pocketmine.net/ - * + * * */ diff --git a/src/pocketmine/item/Bread.php b/src/pocketmine/item/Bread.php index ffadc7fc1..a50d5a0f7 100644 --- a/src/pocketmine/item/Bread.php +++ b/src/pocketmine/item/Bread.php @@ -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; + } } diff --git a/src/pocketmine/item/BrewingStand.php b/src/pocketmine/item/BrewingStand.php index 52dc68134..414b8d74e 100644 --- a/src/pocketmine/item/BrewingStand.php +++ b/src/pocketmine/item/BrewingStand.php @@ -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"); + } } diff --git a/src/pocketmine/item/Carrot.php b/src/pocketmine/item/Carrot.php index 719f3a58c..fa00814a7 100644 --- a/src/pocketmine/item/Carrot.php +++ b/src/pocketmine/item/Carrot.php @@ -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"); } -} \ No newline at end of file + + public function getFoodRestore() : int{ + return 3; + } + + public function getSaturationRestore() : float{ + return 4.8; + } +} diff --git a/src/pocketmine/item/CookedChicken.php b/src/pocketmine/item/CookedChicken.php index 872e92003..f5828e609 100644 --- a/src/pocketmine/item/CookedChicken.php +++ b/src/pocketmine/item/CookedChicken.php @@ -2,11 +2,11 @@ /* * - * ____ _ _ __ __ _ __ __ ____ - * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \ + * ____ _ _ __ __ _ __ __ ____ + * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \ * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) | - * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/ - * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_| + * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/ + * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_| * * 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 @@ -15,16 +15,23 @@ * * @author PocketMine Team * @link http://www.pocketmine.net/ - * + * * */ 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; + } } diff --git a/src/pocketmine/item/CookedFish.php b/src/pocketmine/item/CookedFish.php index 9c7441ea4..62111645a 100644 --- a/src/pocketmine/item/CookedFish.php +++ b/src/pocketmine/item/CookedFish.php @@ -2,11 +2,11 @@ /* * - * ____ _ _ __ __ _ __ __ ____ - * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \ + * ____ _ _ __ __ _ __ __ ____ + * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \ * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) | - * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/ - * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_| + * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/ + * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_| * * 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 @@ -15,19 +15,22 @@ * * @author PocketMine Team * @link http://www.pocketmine.net/ - * + * * */ 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; + } } diff --git a/src/pocketmine/item/CookedPorkchop.php b/src/pocketmine/item/CookedPorkchop.php index 24ecb5e11..0f41f4a84 100644 --- a/src/pocketmine/item/CookedPorkchop.php +++ b/src/pocketmine/item/CookedPorkchop.php @@ -2,11 +2,11 @@ /* * - * ____ _ _ __ __ _ __ __ ____ - * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \ + * ____ _ _ __ __ _ __ __ ____ + * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \ * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) | - * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/ - * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_| + * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/ + * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_| * * 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 @@ -15,16 +15,23 @@ * * @author PocketMine Team * @link http://www.pocketmine.net/ - * + * * */ 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; + } } diff --git a/src/pocketmine/item/CookedRabbit.php b/src/pocketmine/item/CookedRabbit.php index b39f1e745..5544f5bb3 100644 --- a/src/pocketmine/item/CookedRabbit.php +++ b/src/pocketmine/item/CookedRabbit.php @@ -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; + } } diff --git a/src/pocketmine/item/Cookie.php b/src/pocketmine/item/Cookie.php index 3ca0a7132..dc7e35ba2 100644 --- a/src/pocketmine/item/Cookie.php +++ b/src/pocketmine/item/Cookie.php @@ -2,11 +2,11 @@ /* * - * ____ _ _ __ __ _ __ __ ____ - * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \ + * ____ _ _ __ __ _ __ __ ____ + * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \ * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) | - * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/ - * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_| + * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/ + * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_| * * 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 @@ -15,16 +15,23 @@ * * @author PocketMine Team * @link http://www.pocketmine.net/ - * + * * */ 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; + } } diff --git a/src/pocketmine/item/FermentedSpiderEye.php b/src/pocketmine/item/FermentedSpiderEye.php index 7fb9b2950..d00230a1a 100644 --- a/src/pocketmine/item/FermentedSpiderEye.php +++ b/src/pocketmine/item/FermentedSpiderEye.php @@ -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"); - } + } } diff --git a/src/pocketmine/item/Fish.php b/src/pocketmine/item/Fish.php index e56df941c..7a477f5b6 100644 --- a/src/pocketmine/item/Fish.php +++ b/src/pocketmine/item/Fish.php @@ -2,11 +2,11 @@ /* * - * ____ _ _ __ __ _ __ __ ____ - * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \ + * ____ _ _ __ __ _ __ __ ____ + * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \ * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) | - * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/ - * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_| + * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/ + * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_| * * 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 @@ -15,23 +15,63 @@ * * @author PocketMine Team * @link http://www.pocketmine.net/ - * + * * */ 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); } -} \ No newline at end of file + 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), + ] : []; + } +} diff --git a/src/pocketmine/item/FishingRod.php b/src/pocketmine/item/FishingRod.php index 26df171fc..9f5794f56 100644 --- a/src/pocketmine/item/FishingRod.php +++ b/src/pocketmine/item/FishingRod.php @@ -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"); diff --git a/src/pocketmine/item/Food.php b/src/pocketmine/item/Food.php new file mode 100644 index 000000000..a10c85689 --- /dev/null +++ b/src/pocketmine/item/Food.php @@ -0,0 +1,50 @@ +getCount() === 1){ + return Item::get(0); + }else{ + $this->count--; + return $this; + } + } + + /** + * @return Effect[] + */ + public function getAdditionEffects() : array{ + return []; + } + + public function onEat(Player $player){ + } +} diff --git a/src/pocketmine/item/GlassBottle.php b/src/pocketmine/item/GlassBottle.php index f3ea67929..063442511 100644 --- a/src/pocketmine/item/GlassBottle.php +++ b/src/pocketmine/item/GlassBottle.php @@ -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"); + } } diff --git a/src/pocketmine/item/GlisteringMelon.php b/src/pocketmine/item/GlisteringMelon.php index 5c1d331f4..792b1b149 100644 --- a/src/pocketmine/item/GlisteringMelon.php +++ b/src/pocketmine/item/GlisteringMelon.php @@ -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"); + } } diff --git a/src/pocketmine/item/GoldenApple.php b/src/pocketmine/item/GoldenApple.php index 69b381e9d..ede34f43a 100644 --- a/src/pocketmine/item/GoldenApple.php +++ b/src/pocketmine/item/GoldenApple.php @@ -2,11 +2,11 @@ /* * - * ____ _ _ __ __ _ __ __ ____ - * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \ + * ____ _ _ __ __ _ __ __ ____ + * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \ * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) | - * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/ - * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_| + * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/ + * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_| * * 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 @@ -15,16 +15,37 @@ * * @author PocketMine Team * @link http://www.pocketmine.net/ - * + * * */ 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) + ]; + } } diff --git a/src/pocketmine/item/GoldenCarrot.php b/src/pocketmine/item/GoldenCarrot.php index 7a0eec3cf..6cf07b960 100644 --- a/src/pocketmine/item/GoldenCarrot.php +++ b/src/pocketmine/item/GoldenCarrot.php @@ -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; + } } diff --git a/src/pocketmine/item/Item.php b/src/pocketmine/item/Item.php index 32550f385..c631f706b 100644 --- a/src/pocketmine/item/Item.php +++ b/src/pocketmine/item/Item.php @@ -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; @@ -643,7 +635,7 @@ class Item{ $creativeItems = new Config(Server::getInstance()->getFilePath() . "src/pocketmine/resources/creativeitems.json", Config::JSON, []); - foreach($creativeItems->getAll() as $item) { + foreach($creativeItems->getAll() as $item){ self::addCreativeItem(Item::get($item["ID"], $item["Damage"])); } } @@ -679,6 +671,7 @@ class Item{ /** * @param $index + * * @return Item */ public static function getCreativeItem(int $index){ @@ -712,7 +705,8 @@ class Item{ /** * @param string $str - * @param bool $multiple + * @param bool $multiple + * * @return Item[]|Item */ public static function fromString(string $str, bool $multiple = false){ @@ -772,7 +766,7 @@ class Item{ public function getCompoundTag(){ return $this->tags; } - + public function hasCompoundTag() : bool{ return $this->tags !== "" and $this->tags !== null; } @@ -851,6 +845,7 @@ class Item{ /** * @param $id + * * @return Enchantment|null */ public function getEnchantment(int $id){ @@ -1130,7 +1125,7 @@ class Item{ } final public function __toString() : string{ - return "Item " . $this->name . " (" . $this->id . ":" . ($this->meta === null ? "?" : $this->meta) . ")x" . $this->count . ($this->hasCompoundTag() ? " tags:0x".bin2hex($this->getCompoundTag()) : ""); + return "Item " . $this->name . " (" . $this->id . ":" . ($this->meta === null ? "?" : $this->meta) . ")x" . $this->count . ($this->hasCompoundTag() ? " tags:0x" . bin2hex($this->getCompoundTag()) : ""); } public function getDestroySpeed(Block $block, Player $player){ diff --git a/src/pocketmine/item/MagmaCream.php b/src/pocketmine/item/MagmaCream.php index 37e97be92..43c13a918 100644 --- a/src/pocketmine/item/MagmaCream.php +++ b/src/pocketmine/item/MagmaCream.php @@ -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"); + } } diff --git a/src/pocketmine/item/Melon.php b/src/pocketmine/item/Melon.php index 086338915..75cefe875 100644 --- a/src/pocketmine/item/Melon.php +++ b/src/pocketmine/item/Melon.php @@ -2,11 +2,11 @@ /* * - * ____ _ _ __ __ _ __ __ ____ - * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \ + * ____ _ _ __ __ _ __ __ ____ + * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \ * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) | - * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/ - * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_| + * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/ + * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_| * * 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 @@ -15,16 +15,23 @@ * * @author PocketMine Team * @link http://www.pocketmine.net/ - * + * * */ 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; + } } diff --git a/src/pocketmine/item/MushroomStew.php b/src/pocketmine/item/MushroomStew.php index 172852c65..b729bbdc5 100644 --- a/src/pocketmine/item/MushroomStew.php +++ b/src/pocketmine/item/MushroomStew.php @@ -2,11 +2,11 @@ /* * - * ____ _ _ __ __ _ __ __ ____ - * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \ + * ____ _ _ __ __ _ __ __ ____ + * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \ * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) | - * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/ - * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_| + * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/ + * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_| * * 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 @@ -15,14 +15,13 @@ * * @author PocketMine Team * @link http://www.pocketmine.net/ - * + * * */ 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; } -} \ No newline at end of file + + public function getFoodRestore() : int{ + return 6; + } + + public function getSaturationRestore() : float{ + return 7.2; + } + + public function getResidue() : Item{ + return Item::get(Item::BOWL); + } +} diff --git a/src/pocketmine/item/NetherWart.php b/src/pocketmine/item/NetherWart.php index 733fc64af..951b5456d 100644 --- a/src/pocketmine/item/NetherWart.php +++ b/src/pocketmine/item/NetherWart.php @@ -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"); + } } diff --git a/src/pocketmine/item/Potato.php b/src/pocketmine/item/Potato.php index d68f86f9e..f9cea5a27 100644 --- a/src/pocketmine/item/Potato.php +++ b/src/pocketmine/item/Potato.php @@ -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; + } } \ No newline at end of file diff --git a/src/pocketmine/item/Potion.php b/src/pocketmine/item/Potion.php index ec08fed47..8a6bac037 100644 --- a/src/pocketmine/item/Potion.php +++ b/src/pocketmine/item/Potion.php @@ -21,8 +21,8 @@ namespace pocketmine\item; -class Potion extends Item { - public function __construct($meta = 0, $count =1){ - parent::__construct(self::POTION, $meta, $count, "Potion"); - } +class Potion extends Item{ + public function __construct($meta = 0, $count = 1){ + parent::__construct(self::POTION, $meta, $count, "Potion"); + } } diff --git a/src/pocketmine/item/PumpkinPie.php b/src/pocketmine/item/PumpkinPie.php index 6d2a24d51..1805a298b 100644 --- a/src/pocketmine/item/PumpkinPie.php +++ b/src/pocketmine/item/PumpkinPie.php @@ -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; + } } diff --git a/src/pocketmine/item/RawBeef.php b/src/pocketmine/item/RawBeef.php index 612ef9ff9..dde1bd3c3 100644 --- a/src/pocketmine/item/RawBeef.php +++ b/src/pocketmine/item/RawBeef.php @@ -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; + } } diff --git a/src/pocketmine/item/RawChicken.php b/src/pocketmine/item/RawChicken.php index 25121cb26..a7a07a06a 100644 --- a/src/pocketmine/item/RawChicken.php +++ b/src/pocketmine/item/RawChicken.php @@ -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); + } + } } diff --git a/src/pocketmine/item/SpawnEgg.php b/src/pocketmine/item/SpawnEgg.php index 8512d43dd..a8e56b8fb 100644 --- a/src/pocketmine/item/SpawnEgg.php +++ b/src/pocketmine/item/SpawnEgg.php @@ -2,11 +2,12 @@ /* * - * ____ _ _ __ __ _ __ __ ____ - * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \ + * ____ _ _ __ __ _ __ __ ____ + * ____ _ _ __ __ _ __ __ ____ + * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \ * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) | - * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/ - * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_| + * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/ + * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_| * * 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 @@ -15,7 +16,7 @@ * * @author PocketMine Team * @link http://www.pocketmine.net/ - * + * * */ @@ -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; @@ -82,4 +83,4 @@ class SpawnEgg extends Item{ return false; } -} \ No newline at end of file +} diff --git a/src/pocketmine/item/SpiderEye.php b/src/pocketmine/item/SpiderEye.php index b33d7c72a..2644e3cd5 100644 --- a/src/pocketmine/item/SpiderEye.php +++ b/src/pocketmine/item/SpiderEye.php @@ -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 getAdditionEffects() : array{ + return Effect::getEffect(Effect::POISON)->setDuration(80); + } } diff --git a/src/pocketmine/item/Steak.php b/src/pocketmine/item/Steak.php index bc18b0a1a..126795ab4 100644 --- a/src/pocketmine/item/Steak.php +++ b/src/pocketmine/item/Steak.php @@ -2,11 +2,11 @@ /* * - * ____ _ _ __ __ _ __ __ ____ - * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \ + * ____ _ _ __ __ _ __ __ ____ + * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \ * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) | - * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/ - * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_| + * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/ + * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_| * * 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 @@ -15,16 +15,23 @@ * * @author PocketMine Team * @link http://www.pocketmine.net/ - * + * * */ 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; + } } diff --git a/src/pocketmine/item/Tool.php b/src/pocketmine/item/Tool.php index 7f3c0b833..31d7e840c 100644 --- a/src/pocketmine/item/Tool.php +++ b/src/pocketmine/item/Tool.php @@ -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; diff --git a/src/pocketmine/item/enchantment/EnchantmentEntry.php b/src/pocketmine/item/enchantment/EnchantmentEntry.php index e1a40d37c..d6d109f47 100644 --- a/src/pocketmine/item/enchantment/EnchantmentEntry.php +++ b/src/pocketmine/item/enchantment/EnchantmentEntry.php @@ -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; diff --git a/src/pocketmine/item/enchantment/EnchantmentList.php b/src/pocketmine/item/enchantment/EnchantmentList.php index a4fbd09cc..6a8af365a 100644 --- a/src/pocketmine/item/enchantment/EnchantmentList.php +++ b/src/pocketmine/item/enchantment/EnchantmentList.php @@ -32,7 +32,7 @@ class EnchantmentList{ } /** - * @param $slot + * @param $slot * @param EnchantmentEntry $entry */ public function setSlot($slot, EnchantmentEntry $entry){ From 52e8781d36497567920ccb45243b3d42f49a207c Mon Sep 17 00:00:00 2001 From: PEMapModder Date: Thu, 11 Feb 2016 01:53:51 +0800 Subject: [PATCH 02/10] Implemented hunger-related regen and damage --- src/pocketmine/Player.php | 21 ++-- src/pocketmine/entity/Effect.php | 13 +++ src/pocketmine/entity/Human.php | 98 ++++++++++++++++++- .../event/entity/EntityDamageEvent.php | 1 + .../event/entity/EntityRegainHealthEvent.php | 1 + 5 files changed, 123 insertions(+), 11 deletions(-) diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index ff9120364..bfc346e83 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -2260,6 +2260,8 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade $this->inventory->setItemInHand($item); $this->inventory->sendHeldItem($this->hasSpawned); } + + $this->exhaust(0.025); } break; } @@ -2294,7 +2296,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade if( $target instanceof Player and $this->server->getConfigBoolean("pvp", true) === false - ){ $cancelled = true; } @@ -2392,12 +2393,16 @@ 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); } } @@ -3259,6 +3264,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); + } } } diff --git a/src/pocketmine/entity/Effect.php b/src/pocketmine/entity/Effect.php index 0f3d9e066..8ed114a98 100644 --- a/src/pocketmine/entity/Effect.php +++ b/src/pocketmine/entity/Effect.php @@ -201,6 +201,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; } @@ -225,6 +233,11 @@ class Effect{ $entity->heal($ev->getAmount(), $ev); } break; + + case Effect::HUNGER: + if($entity instanceof Human){ + $entity->exhaust(0.5 * $this->amplifier); + } } } diff --git a/src/pocketmine/entity/Human.php b/src/pocketmine/entity/Human.php index 7265c3f51..c8e91909c 100644 --- a/src/pocketmine/entity/Human.php +++ b/src/pocketmine/entity/Human.php @@ -21,6 +21,8 @@ namespace pocketmine\entity; +use pocketmine\event\entity\EntityDamageEvent; +use pocketmine\event\entity\EntityRegainHealthEvent; use pocketmine\inventory\InventoryHolder; use pocketmine\inventory\PlayerInventory; use pocketmine\item\Item as ItemItem; @@ -58,6 +60,8 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ protected $skinName; protected $skin; + protected $foodTickTimer = 0; + public function getSkinData(){ return $this->skin; } @@ -93,18 +97,47 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ return (float) $this->attributeMap->getAttribute(Attribute::HUNGER)->getValue(); } - public function setFood(float $food){ - $this->attributeMap->getAttribute(Attribute::HUNGER)->setValue($food); + /** + * 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 addFood(float $amount){ - $this->attributeMap->getAttribute(Attribute::HUNGER)->setValue($amount, true); + $attr = $this->attributeMap->getAttribute(Attribute::HUNGER); + $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); } @@ -117,15 +150,32 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ 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. + * TODO walk per meter: 0.01 + * TODO sneak per meter: 0.005 + * TODO swim per meter: 0.015 + * TODO sprint per meter: 0.1 + * TODO jump: 0.2 + * TODO regen per halfheart | food >= 18: 4.0 + * + * @param float $amount + */ public function exhaust(float $amount){ $exhaustion = $this->getExhaustion(); $exhaustion += $amount; - if($exhaustion >= 4.0){ + while($exhaustion >= 4.0){ $exhaustion -= 4.0; $this->setExhaustion($exhaustion); @@ -181,14 +231,52 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ } } + parent::initEntity(); + $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(); + public function entityBaseTick($tickDiff = 1){ + $hasUpdate = parent::entityBaseTick($tickDiff); + + $food = $this->getFood(); + $health = $this->getHealth(); + if($food >= 18){ + $this->foodTickTimer++; + if($this->foodTickTimer >= 80){ + $this->heal(1, new EntityRegainHealthEvent($this, 1, EntityRegainHealthEvent::CAUSE_SATURATION)); + $this->exhaust(3.0); + $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(){ diff --git a/src/pocketmine/event/entity/EntityDamageEvent.php b/src/pocketmine/event/entity/EntityDamageEvent.php index f792f6bda..0b681a7c2 100644 --- a/src/pocketmine/event/entity/EntityDamageEvent.php +++ b/src/pocketmine/event/entity/EntityDamageEvent.php @@ -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; diff --git a/src/pocketmine/event/entity/EntityRegainHealthEvent.php b/src/pocketmine/event/entity/EntityRegainHealthEvent.php index 4be1d27da..14bbd80ac 100644 --- a/src/pocketmine/event/entity/EntityRegainHealthEvent.php +++ b/src/pocketmine/event/entity/EntityRegainHealthEvent.php @@ -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; From 28967ca4955a2859d9c724fd5c7163ef6289b25b Mon Sep 17 00:00:00 2001 From: PEMapModder Date: Thu, 11 Feb 2016 15:42:07 +0800 Subject: [PATCH 03/10] Fixed eating --- src/pocketmine/Player.php | 71 ++++++------------------------ src/pocketmine/entity/Human.php | 12 +++-- src/pocketmine/item/CookedFish.php | 2 +- src/pocketmine/item/Fish.php | 2 +- src/pocketmine/item/Food.php | 24 ++++++++-- 5 files changed, 41 insertions(+), 70 deletions(-) diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index bfc346e83..c657cfd0e 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -76,6 +76,7 @@ use pocketmine\inventory\PlayerInventory; use pocketmine\inventory\ShapedRecipe; use pocketmine\inventory\ShapelessRecipe; use pocketmine\inventory\SimpleTransactionGroup; +use pocketmine\item\Food; use pocketmine\item\Item; use pocketmine\level\ChunkLoader; use pocketmine\level\format\FullChunk; @@ -2433,65 +2434,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: change to hunger; add RabbitStew and RawRabbit and RottenFlesh - 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 instanceof Food){ + $ev = new PlayerItemConsumeEvent($this, $slot); + if($this->getFood() >= $this->getMaxFood()){ + $ev->setCancelled(); + } + $this->server->getPluginManager()->callEvent($ev); + if(!$ev->isCancelled()){ + $slot->onEat($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; @@ -3264,7 +3219,7 @@ 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); } diff --git a/src/pocketmine/entity/Human.php b/src/pocketmine/entity/Human.php index c8e91909c..312bf2968 100644 --- a/src/pocketmine/entity/Human.php +++ b/src/pocketmine/entity/Human.php @@ -94,7 +94,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ } public function getFood() : float{ - return (float) $this->attributeMap->getAttribute(Attribute::HUNGER)->getValue(); + return $this->attributeMap->getAttribute(Attribute::HUNGER)->getValue(); } /** @@ -120,6 +120,10 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ } } + public function getMaxFood() : float{ + return $this->attributeMap->getAttribute(Attribute::HUNGER)->getMaxValue(); + } + public function addFood(float $amount){ $attr = $this->attributeMap->getAttribute(Attribute::HUNGER); $amount = max(min($amount, $attr->getMaxValue()), $attr->getMinValue()); @@ -162,12 +166,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ /** * Increases a human's exhaustion level. - * TODO walk per meter: 0.01 - * TODO sneak per meter: 0.005 - * TODO swim per meter: 0.015 - * TODO sprint per meter: 0.1 - * TODO jump: 0.2 - * TODO regen per halfheart | food >= 18: 4.0 * * @param float $amount */ diff --git a/src/pocketmine/item/CookedFish.php b/src/pocketmine/item/CookedFish.php index 62111645a..bc8dceb4c 100644 --- a/src/pocketmine/item/CookedFish.php +++ b/src/pocketmine/item/CookedFish.php @@ -30,7 +30,7 @@ class CookedFish extends Fish{ return $this->meta === self::FISH_SALMON ? 6 : 5; } - public function getSaturationRestore() : int{ + public function getSaturationRestore() : float{ return $this->meta === self::FISH_SALMON ? 9.6 : 6; } } diff --git a/src/pocketmine/item/Fish.php b/src/pocketmine/item/Fish.php index 7a477f5b6..aa6c9e5fc 100644 --- a/src/pocketmine/item/Fish.php +++ b/src/pocketmine/item/Fish.php @@ -67,7 +67,7 @@ class Fish extends Food{ return 0; } - public function getAdditionEffects(){ + public function getAdditionEffects() : array{ return $this->meta === self::FISH_PUFFERFISH ? [ Effect::getEffect(Effect::HUNGER)->setDuration(300)->setAmplifier(2), Effect::getEffect(Effect::NAUSEA)->setDuration(300)->setAmplifier(1), diff --git a/src/pocketmine/item/Food.php b/src/pocketmine/item/Food.php index a10c85689..52ba6bbb1 100644 --- a/src/pocketmine/item/Food.php +++ b/src/pocketmine/item/Food.php @@ -22,7 +22,10 @@ namespace pocketmine\item; use pocketmine\entity\Effect; +use pocketmine\entity\Human; +use pocketmine\network\protocol\EntityEventPacket; use pocketmine\Player; +use pocketmine\Server; abstract class Food extends Item{ public abstract function getFoodRestore() : int; @@ -33,8 +36,9 @@ abstract class Food extends Item{ if($this->getCount() === 1){ return Item::get(0); }else{ - $this->count--; - return $this; + $new = clone $this; + $new->count--; + return $new; } } @@ -45,6 +49,20 @@ abstract class Food extends Item{ return []; } - public function onEat(Player $player){ + public function onEat(Human $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); + + $human->addSaturation($this->getSaturationRestore()); + $human->addFood($this->getFoodRestore()); + foreach($this->getAdditionEffects() as $effect){ + $human->addEffect($effect); + } + $human->getInventory()->setItemInHand($this->getResidue()); } } From 8807617480702b2d27d123d9e430b5d047c9acc6 Mon Sep 17 00:00:00 2001 From: PEMapModder Date: Thu, 11 Feb 2016 18:45:58 +0800 Subject: [PATCH 04/10] Fixed attriutes not sending --- src/pocketmine/Player.php | 15 ++++++++++----- src/pocketmine/entity/Attribute.php | 4 ++-- src/pocketmine/entity/AttributeMap.php | 3 +++ src/pocketmine/entity/Human.php | 10 ++++++++-- src/pocketmine/entity/Living.php | 5 +++++ src/pocketmine/item/SpiderEye.php | 2 +- 6 files changed, 29 insertions(+), 10 deletions(-) diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index c657cfd0e..a1c2f810f 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -34,7 +34,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; @@ -1205,14 +1204,20 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade } public function entityBaseTick($tickDiff = 1){ - parent::entityBaseTick($tickDiff); + $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){ @@ -3189,9 +3194,9 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade public function setHealth($amount){ parent::setHealth($amount); if($this->spawned === true){ - $pk = new SetHealthPacket(); - $pk->health = $this->getHealth(); - $this->dataPacket($pk); +// $pk = new SetHealthPacket(); +// $pk->health = $this->getHealth(); +// $this->dataPacket($pk); } } diff --git a/src/pocketmine/entity/Attribute.php b/src/pocketmine/entity/Attribute.php index 4e48411bc..62b9b6916 100644 --- a/src/pocketmine/entity/Attribute.php +++ b/src/pocketmine/entity/Attribute.php @@ -73,7 +73,7 @@ class Attribute{ * * @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"); } @@ -105,7 +105,7 @@ 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; diff --git a/src/pocketmine/entity/AttributeMap.php b/src/pocketmine/entity/AttributeMap.php index fe44474a5..3e060cc1d 100644 --- a/src/pocketmine/entity/AttributeMap.php +++ b/src/pocketmine/entity/AttributeMap.php @@ -38,6 +38,9 @@ class AttributeMap{ 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(); diff --git a/src/pocketmine/entity/Human.php b/src/pocketmine/entity/Human.php index 312bf2968..4f0471570 100644 --- a/src/pocketmine/entity/Human.php +++ b/src/pocketmine/entity/Human.php @@ -126,6 +126,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ 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); } @@ -147,7 +148,8 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ } public function addSaturation(float $amount){ - $this->attributeMap->getAttribute(Attribute::SATURATION)->setValue($amount, true); + $attr = $this->attributeMap->getAttribute(Attribute::SATURATION); + $attr->setValue($attr->getValue() + $amount, true); } public function getExhaustion() : float{ @@ -175,7 +177,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ while($exhaustion >= 4.0){ $exhaustion -= 4.0; - $this->setExhaustion($exhaustion); $saturation = $this->getSaturation(); if($saturation > 0){ @@ -189,6 +190,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ } } } + $this->setExhaustion($exhaustion); } public function getInventory(){ @@ -230,6 +232,10 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ } parent::initEntity(); + } + + protected function addAttributes(){ + parent::addAttributes(); $this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::SATURATION)); $this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::EXHAUSTION)); diff --git a/src/pocketmine/entity/Living.php b/src/pocketmine/entity/Living.php index ded684ab8..27658e80d 100644 --- a/src/pocketmine/entity/Living.php +++ b/src/pocketmine/entity/Living.php @@ -32,6 +32,7 @@ use pocketmine\item\Item as ItemItem; use pocketmine\math\Vector3; use pocketmine\nbt\tag\ShortTag; use pocketmine\network\protocol\EntityEventPacket; +use pocketmine\Player; use pocketmine\Server; use pocketmine\utils\BlockIterator; @@ -47,6 +48,8 @@ abstract class Living extends Entity implements Damageable{ protected function initEntity(){ parent::initEntity(); + $this->addAttributes(); + if(isset($this->namedtag->HealF)){ $this->namedtag->Health = new ShortTag("Health", (int) $this->namedtag["HealF"]); unset($this->namedtag->HealF); @@ -57,7 +60,9 @@ abstract class Living extends Entity implements Damageable{ } $this->setHealth($this->namedtag["Health"]); + } + protected function addAttributes(){ $this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::ABSORPTION)); $this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::HEALTH)); $this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::MOVEMENT_SPEED)); diff --git a/src/pocketmine/item/SpiderEye.php b/src/pocketmine/item/SpiderEye.php index 2644e3cd5..3d8d67296 100644 --- a/src/pocketmine/item/SpiderEye.php +++ b/src/pocketmine/item/SpiderEye.php @@ -37,6 +37,6 @@ class SpiderEye extends Food{ } public function getAdditionEffects() : array{ - return Effect::getEffect(Effect::POISON)->setDuration(80); + return [Effect::getEffect(Effect::POISON)->setDuration(80)]; } } From e79976bdac4b47ab3358ff9c2dc7a1cc8515f3e7 Mon Sep 17 00:00:00 2001 From: PEMapModder Date: Thu, 11 Feb 2016 22:07:04 +0800 Subject: [PATCH 05/10] Added events --- src/pocketmine/Player.php | 14 +-- src/pocketmine/block/Cake.php | 42 +++++--- src/pocketmine/entity/Effect.php | 19 ++-- src/pocketmine/entity/Human.php | 17 +++- .../event/entity/EntityEatBlockEvent.php | 49 +++++++++ .../event/entity/EntityEatEvent.php | 99 +++++++++++++++++++ .../event/entity/EntityEatItemEvent.php | 47 +++++++++ .../event/player/PlayerExhaustEvent.php | 66 +++++++++++++ src/pocketmine/item/BeetrootSoup.php | 2 +- src/pocketmine/item/Fish.php | 2 +- src/pocketmine/item/Food.php | 35 ++++--- src/pocketmine/item/FoodSource.php | 37 +++++++ src/pocketmine/item/GoldenApple.php | 2 +- src/pocketmine/item/Item.php | 11 +++ src/pocketmine/item/MushroomStew.php | 2 +- src/pocketmine/item/Potion.php | 10 ++ src/pocketmine/item/RawChicken.php | 2 +- src/pocketmine/item/SpiderEye.php | 2 +- 18 files changed, 405 insertions(+), 53 deletions(-) create mode 100644 src/pocketmine/event/entity/EntityEatBlockEvent.php create mode 100644 src/pocketmine/event/entity/EntityEatEvent.php create mode 100644 src/pocketmine/event/entity/EntityEatItemEvent.php create mode 100644 src/pocketmine/event/player/PlayerExhaustEvent.php create mode 100644 src/pocketmine/item/FoodSource.php diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index a1c2f810f..19dd1696b 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -48,6 +48,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; @@ -75,7 +76,6 @@ use pocketmine\inventory\PlayerInventory; use pocketmine\inventory\ShapedRecipe; use pocketmine\inventory\ShapelessRecipe; use pocketmine\inventory\SimpleTransactionGroup; -use pocketmine\item\Food; use pocketmine\item\Item; use pocketmine\level\ChunkLoader; use pocketmine\level\format\FullChunk; @@ -2267,7 +2267,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade $this->inventory->sendHeldItem($this->hasSpawned); } - $this->exhaust(0.025); + $this->exhaust(0.025, PlayerExhaustEvent::CAUSE_MINING); } break; } @@ -2408,7 +2408,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade } } - $this->exhaust(0.3); + $this->exhaust(0.3, PlayerExhaustEvent::CAUSE_ATTACK); } } @@ -2442,14 +2442,14 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade case EntityEventPacket::USE_ITEM: //Eating $slot = $this->inventory->getItemInHand(); - if($slot instanceof Food){ + if($slot->canBeConsumed()){ $ev = new PlayerItemConsumeEvent($this, $slot); - if($this->getFood() >= $this->getMaxFood()){ + if(!$slot->canBeConsumedBy($this)){ $ev->setCancelled(); } $this->server->getPluginManager()->callEvent($ev); if(!$ev->isCancelled()){ - $slot->onEat($this); + $slot->onConsume($this); }else{ $this->inventory->sendContents($this); } @@ -3226,7 +3226,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade $this->dataPacket($pk); if($this->isSurvival()){ - $this->exhaust(0.3); + $this->exhaust(0.3, PlayerExhaustEvent::CAUSE_DAMAGE); } } } diff --git a/src/pocketmine/block/Cake.php b/src/pocketmine/block/Cake.php index 90f8efca6..e9c9a3880 100644 --- a/src/pocketmine/block/Cake.php +++ b/src/pocketmine/block/Cake.php @@ -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); // TODO hunger + $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 []; + } } diff --git a/src/pocketmine/entity/Effect.php b/src/pocketmine/entity/Effect.php index 8ed114a98..56f4ff660 100644 --- a/src/pocketmine/entity/Effect.php +++ b/src/pocketmine/entity/Effect.php @@ -23,6 +23,7 @@ namespace pocketmine\entity; use pocketmine\event\entity\EntityDamageEvent; use pocketmine\event\entity\EntityRegainHealthEvent; +use pocketmine\event\player\PlayerExhaustEvent; use pocketmine\network\protocol\MobEffectPacket; use pocketmine\Player; @@ -34,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,7 +47,7 @@ class Effect{ const INVISIBILITY = 14; const BLINDNESS = 15; const NIGHT_VISION = 16; - const HUNGER = 17; // TODO implement + const HUNGER = 17; const WEAKNESS = 18; const POISON = 19; const WITHER = 20; @@ -74,15 +75,15 @@ 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); - // TODO Blindness %potion.blindness - // TODO Night Vision %potion.nightVision - // TODO Hunger %potion.hunger + 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); - // TODO Absorption %potion.absorption - // TODO Saturation %potion.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); } /** @@ -236,7 +237,7 @@ class Effect{ case Effect::HUNGER: if($entity instanceof Human){ - $entity->exhaust(0.5 * $this->amplifier); + $entity->exhaust(0.5 * $this->amplifier, PlayerExhaustEvent::CAUSE_POTION); } } } diff --git a/src/pocketmine/entity/Human.php b/src/pocketmine/entity/Human.php index 4f0471570..9cba80291 100644 --- a/src/pocketmine/entity/Human.php +++ b/src/pocketmine/entity/Human.php @@ -23,6 +23,7 @@ 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; @@ -170,10 +171,18 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ * 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){ + 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 += $amount; + $exhaustion += $ev->getAmount(); while($exhaustion >= 4.0){ $exhaustion -= 4.0; @@ -191,6 +200,8 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ } } $this->setExhaustion($exhaustion); + + return $ev->getAmount(); } public function getInventory(){ @@ -254,7 +265,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ $this->foodTickTimer++; if($this->foodTickTimer >= 80){ $this->heal(1, new EntityRegainHealthEvent($this, 1, EntityRegainHealthEvent::CAUSE_SATURATION)); - $this->exhaust(3.0); + $this->exhaust(3.0, PlayerExhaustEvent::CAUSE_HEALTH_REGEN); $this->foodTickTimer = 0; } }elseif($food === 0){ diff --git a/src/pocketmine/event/entity/EntityEatBlockEvent.php b/src/pocketmine/event/entity/EntityEatBlockEvent.php new file mode 100644 index 000000000..969dc9a1b --- /dev/null +++ b/src/pocketmine/event/entity/EntityEatBlockEvent.php @@ -0,0 +1,49 @@ +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; + } +} diff --git a/src/pocketmine/event/entity/EntityEatItemEvent.php b/src/pocketmine/event/entity/EntityEatItemEvent.php new file mode 100644 index 000000000..9293f8351 --- /dev/null +++ b/src/pocketmine/event/entity/EntityEatItemEvent.php @@ -0,0 +1,47 @@ +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; + } +} diff --git a/src/pocketmine/item/BeetrootSoup.php b/src/pocketmine/item/BeetrootSoup.php index 626167e30..9f221f1ae 100644 --- a/src/pocketmine/item/BeetrootSoup.php +++ b/src/pocketmine/item/BeetrootSoup.php @@ -39,7 +39,7 @@ class BeetrootSoup extends Food{ return 7.2; } - public function getResidue() : Item{ + public function getResidue(){ return Item::get(Item::BOWL); } } \ No newline at end of file diff --git a/src/pocketmine/item/Fish.php b/src/pocketmine/item/Fish.php index aa6c9e5fc..58e5da42f 100644 --- a/src/pocketmine/item/Fish.php +++ b/src/pocketmine/item/Fish.php @@ -67,7 +67,7 @@ class Fish extends Food{ return 0; } - public function getAdditionEffects() : array{ + 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), diff --git a/src/pocketmine/item/Food.php b/src/pocketmine/item/Food.php index 52ba6bbb1..6fd6bfacf 100644 --- a/src/pocketmine/item/Food.php +++ b/src/pocketmine/item/Food.php @@ -21,18 +21,23 @@ namespace pocketmine\item; -use pocketmine\entity\Effect; +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{ - public abstract function getFoodRestore() : int; +abstract class Food extends Item implements FoodSource{ + public function canBeConsumed() : bool{ + return true; + } - public abstract function getSaturationRestore() : float; + public function canBeConsumedBy(Entity $entity){ + return $entity instanceof Human and $entity->getFood() < $entity->getMaxFood(); + } - public function getResidue() : Item{ + public function getResidue(){ if($this->getCount() === 1){ return Item::get(0); }else{ @@ -42,14 +47,11 @@ abstract class Food extends Item{ } } - /** - * @return Effect[] - */ - public function getAdditionEffects() : array{ + public function getAdditionalEffects() : array{ return []; } - public function onEat(Human $human){ + public function onConsume(Entity $human){ $pk = new EntityEventPacket(); $pk->eid = $human->getId(); $pk->event = EntityEventPacket::USE_ITEM; @@ -57,12 +59,15 @@ abstract class Food extends Item{ $human->dataPacket($pk); } Server::broadcastPacket($human->getViewers(), $pk); - - $human->addSaturation($this->getSaturationRestore()); - $human->addFood($this->getFoodRestore()); - foreach($this->getAdditionEffects() as $effect){ + + $ev = new EntityEatItemEvent($human, $this); + + $human->addSaturation($ev->getSaturationRestore()); + $human->addFood($ev->getFoodRestore()); + foreach($ev->getAdditionalEffects() as $effect){ $human->addEffect($effect); } - $human->getInventory()->setItemInHand($this->getResidue()); + + $human->getInventory()->setItemInHand($ev->getResidue()); } } diff --git a/src/pocketmine/item/FoodSource.php b/src/pocketmine/item/FoodSource.php new file mode 100644 index 000000000..ed3834361 --- /dev/null +++ b/src/pocketmine/item/FoodSource.php @@ -0,0 +1,37 @@ +meta === 1 ? [ Effect::getEffect(Effect::REGENERATION)->setDuration(600)->setAmplifier(4), Effect::getEffect(Effect::ABSORPTION)->setDuration(2400), diff --git a/src/pocketmine/item/Item.php b/src/pocketmine/item/Item.php index c631f706b..8bcb4887b 100644 --- a/src/pocketmine/item/Item.php +++ b/src/pocketmine/item/Item.php @@ -1042,6 +1042,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; diff --git a/src/pocketmine/item/MushroomStew.php b/src/pocketmine/item/MushroomStew.php index b729bbdc5..4c315ab9a 100644 --- a/src/pocketmine/item/MushroomStew.php +++ b/src/pocketmine/item/MushroomStew.php @@ -38,7 +38,7 @@ class MushroomStew extends Food{ return 7.2; } - public function getResidue() : Item{ + public function getResidue(){ return Item::get(Item::BOWL); } } diff --git a/src/pocketmine/item/Potion.php b/src/pocketmine/item/Potion.php index 8a6bac037..af879be24 100644 --- a/src/pocketmine/item/Potion.php +++ b/src/pocketmine/item/Potion.php @@ -21,8 +21,18 @@ namespace pocketmine\item; +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 + } } diff --git a/src/pocketmine/item/RawChicken.php b/src/pocketmine/item/RawChicken.php index a7a07a06a..244191287 100644 --- a/src/pocketmine/item/RawChicken.php +++ b/src/pocketmine/item/RawChicken.php @@ -36,7 +36,7 @@ class RawChicken extends Food{ return 1.2; } - public function getAdditionEffects() : array{ + public function getAdditionalEffects() : array{ if(mt_rand(0, 9) < 3){ return Effect::getEffect(Effect::HUNGER)->setDuration(600); } diff --git a/src/pocketmine/item/SpiderEye.php b/src/pocketmine/item/SpiderEye.php index 3d8d67296..049e4c6f9 100644 --- a/src/pocketmine/item/SpiderEye.php +++ b/src/pocketmine/item/SpiderEye.php @@ -36,7 +36,7 @@ class SpiderEye extends Food{ return 3.2; } - public function getAdditionEffects() : array{ + public function getAdditionalEffects() : array{ return [Effect::getEffect(Effect::POISON)->setDuration(80)]; } } From 54595768334c63dc7be7598c5ec6071f5972029e Mon Sep 17 00:00:00 2001 From: PEMapModder Date: Wed, 17 Feb 2016 19:56:19 +0800 Subject: [PATCH 06/10] Added hunger and experience saving --- src/pocketmine/entity/AttributeMap.php | 18 ++++- src/pocketmine/entity/Entity.php | 5 +- src/pocketmine/entity/Human.php | 93 ++++++++++++++++++++++++-- src/pocketmine/entity/Living.php | 13 ++-- src/pocketmine/item/Food.php | 2 +- 5 files changed, 116 insertions(+), 15 deletions(-) diff --git a/src/pocketmine/entity/AttributeMap.php b/src/pocketmine/entity/AttributeMap.php index 3e060cc1d..0c1960211 100644 --- a/src/pocketmine/entity/AttributeMap.php +++ b/src/pocketmine/entity/AttributeMap.php @@ -21,7 +21,7 @@ namespace pocketmine\entity; -class AttributeMap{ +class AttributeMap implements \ArrayAccess{ /** @var Attribute[] */ private $attributes = []; @@ -46,4 +46,20 @@ class AttributeMap{ 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"); + } } diff --git a/src/pocketmine/entity/Entity.php b/src/pocketmine/entity/Entity.php index 4c286b1d5..7aa462dc1 100644 --- a/src/pocketmine/entity/Entity.php +++ b/src/pocketmine/entity/Entity.php @@ -529,7 +529,10 @@ abstract class Entity extends Location implements Metadatable{ $this->scheduleUpdate(); - $this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::KNOCKBACK_RESISTANCE)); + $this->addAttributes(); + } + + protected function addAttributes(){ } /** diff --git a/src/pocketmine/entity/Human.php b/src/pocketmine/entity/Human.php index 9cba80291..c9568f973 100644 --- a/src/pocketmine/entity/Human.php +++ b/src/pocketmine/entity/Human.php @@ -30,6 +30,8 @@ use pocketmine\item\Item as ItemItem; 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; @@ -63,6 +65,9 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ protected $foodTickTimer = 0; + protected $totalXp = 0; + protected $xpSeed; + public function getSkinData(){ return $this->skin; } @@ -204,6 +209,43 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ 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; } @@ -216,9 +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"]); } @@ -242,6 +282,52 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ } } + 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"]; + } + parent::initEntity(); } @@ -251,7 +337,6 @@ 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)); } diff --git a/src/pocketmine/entity/Living.php b/src/pocketmine/entity/Living.php index 27658e80d..e768ab37d 100644 --- a/src/pocketmine/entity/Living.php +++ b/src/pocketmine/entity/Living.php @@ -32,7 +32,6 @@ use pocketmine\item\Item as ItemItem; use pocketmine\math\Vector3; use pocketmine\nbt\tag\ShortTag; use pocketmine\network\protocol\EntityEventPacket; -use pocketmine\Player; use pocketmine\Server; use pocketmine\utils\BlockIterator; @@ -48,14 +47,10 @@ abstract class Living extends Entity implements Damageable{ protected function initEntity(){ parent::initEntity(); - $this->addAttributes(); - 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()); } @@ -63,10 +58,12 @@ abstract class Living extends Entity implements Damageable{ } protected function addAttributes(){ - $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)); + $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){ diff --git a/src/pocketmine/item/Food.php b/src/pocketmine/item/Food.php index 6fd6bfacf..ffc196b63 100644 --- a/src/pocketmine/item/Food.php +++ b/src/pocketmine/item/Food.php @@ -33,7 +33,7 @@ abstract class Food extends Item implements FoodSource{ return true; } - public function canBeConsumedBy(Entity $entity){ + public function canBeConsumedBy(Entity $entity) : bool{ return $entity instanceof Human and $entity->getFood() < $entity->getMaxFood(); } From 83f29fd871b4b713f9568c71b0c67f8a8618e1a2 Mon Sep 17 00:00:00 2001 From: PEMapModder Date: Mon, 22 Feb 2016 15:06:45 +0800 Subject: [PATCH 07/10] Fixed a crash --- src/pocketmine/entity/Human.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/pocketmine/entity/Human.php b/src/pocketmine/entity/Human.php index c9568f973..36dec8ae8 100644 --- a/src/pocketmine/entity/Human.php +++ b/src/pocketmine/entity/Human.php @@ -282,6 +282,8 @@ 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{ @@ -327,13 +329,12 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ }else{ $this->xpSeed = $this->namedtag["XpSeed"]; } - - parent::initEntity(); } protected function addAttributes(){ parent::addAttributes(); + echo "a", PHP_EOL; $this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::SATURATION)); $this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::EXHAUSTION)); $this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::HUNGER)); @@ -348,10 +349,11 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ $health = $this->getHealth(); if($food >= 18){ $this->foodTickTimer++; - if($this->foodTickTimer >= 80){ + 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++; From 86ec7ed77118fb7c800975cb971f8b8aaec1de09 Mon Sep 17 00:00:00 2001 From: PEMapModder Date: Mon, 22 Feb 2016 18:24:51 +0800 Subject: [PATCH 08/10] Fixed player not dying --- src/pocketmine/Player.php | 6 +++--- src/pocketmine/entity/Human.php | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index 09c293020..77de5256f 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -3204,9 +3204,9 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade public function setHealth($amount){ parent::setHealth($amount); if($this->spawned === true){ -// $pk = new SetHealthPacket(); -// $pk->health = $this->getHealth(); -// $this->dataPacket($pk); + $pk = new SetHealthPacket(); + $pk->health = $this->getHealth(); + $this->dataPacket($pk); } } diff --git a/src/pocketmine/entity/Human.php b/src/pocketmine/entity/Human.php index 36dec8ae8..7c7b1ab64 100644 --- a/src/pocketmine/entity/Human.php +++ b/src/pocketmine/entity/Human.php @@ -334,7 +334,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ protected function addAttributes(){ parent::addAttributes(); - echo "a", PHP_EOL; $this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::SATURATION)); $this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::EXHAUSTION)); $this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::HUNGER)); From d59fd42fc6c1e22c9935c1412431dbcc98197d2a Mon Sep 17 00:00:00 2001 From: PEMapModder Date: Mon, 22 Feb 2016 18:34:11 +0800 Subject: [PATCH 09/10] Fixed EntityEatItemEvent::setResidue() declaration --- src/pocketmine/event/entity/EntityEatItemEvent.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/pocketmine/event/entity/EntityEatItemEvent.php b/src/pocketmine/event/entity/EntityEatItemEvent.php index 9293f8351..fe57ac6c0 100644 --- a/src/pocketmine/event/entity/EntityEatItemEvent.php +++ b/src/pocketmine/event/entity/EntityEatItemEvent.php @@ -23,7 +23,6 @@ namespace pocketmine\event\entity; use pocketmine\entity\Entity; use pocketmine\item\Food; -use pocketmine\item\FoodSource; use pocketmine\item\Item; class EntityEatItemEvent extends EntityEatEvent{ @@ -38,7 +37,7 @@ class EntityEatItemEvent extends EntityEatEvent{ return parent::getResidue(); } - public function setResidue(FoodSource $residue){ + public function setResidue($residue){ if(!($residue instanceof Item)){ throw new \InvalidArgumentException("Eating an Item can only result in an Item residue"); } From 09ce8fab82dfec4298419fba2826e674a5e48687 Mon Sep 17 00:00:00 2001 From: PEMapModder Date: Mon, 7 Mar 2016 18:12:54 +0800 Subject: [PATCH 10/10] Fixed speed and slowness potions --- src/pocketmine/Player.php | 2 +- src/pocketmine/entity/Attribute.php | 8 +++--- src/pocketmine/entity/Effect.php | 26 ++++++++++++++++++- src/pocketmine/entity/Entity.php | 40 ++++++++++++++++------------- 4 files changed, 52 insertions(+), 24 deletions(-) diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index 77de5256f..e2e228c8f 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -1641,7 +1641,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; } diff --git a/src/pocketmine/entity/Attribute.php b/src/pocketmine/entity/Attribute.php index 62b9b6916..f6fb4b238 100644 --- a/src/pocketmine/entity/Attribute.php +++ b/src/pocketmine/entity/Attribute.php @@ -56,9 +56,9 @@ class Attribute{ 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::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); + 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); } @@ -199,7 +199,7 @@ class Attribute{ return $this->shouldSend and $this->desynchronized; } - public function markSynchronized(){ - $this->desynchronized = false; + public function markSynchronized(bool $synced = true){ + $this->desynchronized = !$synced; } } diff --git a/src/pocketmine/entity/Effect.php b/src/pocketmine/entity/Effect.php index 56f4ff660..c6f2e17d3 100644 --- a/src/pocketmine/entity/Effect.php +++ b/src/pocketmine/entity/Effect.php @@ -250,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; @@ -270,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); } } @@ -286,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)); } } } diff --git a/src/pocketmine/entity/Entity.php b/src/pocketmine/entity/Entity.php index eab6b1e49..e386379e6 100644 --- a/src/pocketmine/entity/Entity.php +++ b/src/pocketmine/entity/Entity.php @@ -319,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)); + } } /** @@ -363,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); } @@ -408,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 */ @@ -506,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"]); @@ -518,18 +533,6 @@ 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(); - - $this->addAttributes(); } protected function addAttributes(){ @@ -1559,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){