diff --git a/src/pocketmine/block/EmeraldOre.php b/src/pocketmine/block/EmeraldOre.php index 7e790702a..7dcbcde65 100644 --- a/src/pocketmine/block/EmeraldOre.php +++ b/src/pocketmine/block/EmeraldOre.php @@ -53,7 +53,11 @@ class EmeraldOre extends Solid{ public function getDropsForCompatibleTool(Item $item) : array{ return [ - ItemFactory::get(Item::EMERALD) + ItemFactory::get(Item::EMERALD) ]; } + + protected function getXpDropAmount() : int{ + return mt_rand(3, 7); + } } diff --git a/src/pocketmine/block/TNT.php b/src/pocketmine/block/TNT.php index 7666fd91f..5ebae29cd 100644 --- a/src/pocketmine/block/TNT.php +++ b/src/pocketmine/block/TNT.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace pocketmine\block; use pocketmine\entity\Entity; +use pocketmine\entity\projectile\Arrow; use pocketmine\item\FlintSteel; use pocketmine\item\Item; use pocketmine\math\Vector3; @@ -56,6 +57,16 @@ class TNT extends Solid{ return false; } + public function hasEntityCollision() : bool{ + return true; + } + + public function onEntityCollide(Entity $entity) : void{ + if($entity instanceof Arrow and $entity->isOnFire()){ + $this->ignite(); + } + } + public function ignite(int $fuse = 80){ $this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true); diff --git a/src/pocketmine/entity/projectile/Arrow.php b/src/pocketmine/entity/projectile/Arrow.php index bfe45c412..5842149a9 100644 --- a/src/pocketmine/entity/projectile/Arrow.php +++ b/src/pocketmine/entity/projectile/Arrow.php @@ -52,7 +52,8 @@ class Arrow extends Projectile{ protected $gravity = 0.05; protected $drag = 0.01; - protected $damage = 2; + /** @var float */ + protected $damage = 2.0; /** @var int */ protected $pickupMode = self::PICKUP_ANY; diff --git a/src/pocketmine/entity/projectile/Projectile.php b/src/pocketmine/entity/projectile/Projectile.php index 7cd579690..66c0a1433 100644 --- a/src/pocketmine/entity/projectile/Projectile.php +++ b/src/pocketmine/entity/projectile/Projectile.php @@ -46,7 +46,8 @@ abstract class Projectile extends Entity{ public const DATA_SHOOTER_ID = 17; - protected $damage = 0; + /** @var float */ + protected $damage = 0.0; /** @var Vector3|null */ protected $blockHit; @@ -74,6 +75,7 @@ abstract class Projectile extends Entity{ $this->setMaxHealth(1); $this->setHealth(1); $this->age = $this->namedtag->getShort("Age", $this->age); + $this->damage = $this->namedtag->getDouble("damage", $this->damage); do{ $blockHit = null; @@ -112,6 +114,25 @@ abstract class Projectile extends Entity{ return false; } + /** + * Returns the base damage applied on collision. This is multiplied by the projectile's speed to give a result + * damage. + * + * @return float + */ + public function getBaseDamage() : float{ + return $this->damage; + } + + /** + * Sets the base amount of damage applied by the projectile. + * + * @param float $damage + */ + public function setBaseDamage(float $damage) : void{ + $this->damage = $damage; + } + /** * Returns the amount of damage this projectile will deal to the entity it hits. * @return int @@ -124,6 +145,7 @@ abstract class Projectile extends Entity{ parent::saveNBT(); $this->namedtag->setShort("Age", $this->age); + $this->namedtag->setDouble("damage", $this->damage); if($this->blockHit !== null){ $this->namedtag->setInt("tileX", $this->blockHit->x); @@ -140,17 +162,19 @@ abstract class Projectile extends Entity{ return true; } - public function hasMovementUpdate() : bool{ - $parent = parent::hasMovementUpdate(); - if($parent and $this->blockHit !== null){ + public function onNearbyBlockChange() : void{ + if($this->blockHit !== null){ $blockIn = $this->level->getBlockAt($this->blockHit->x, $this->blockHit->y, $this->blockHit->z); - - if($blockIn->getId() === $this->blockHitId and $blockIn->getDamage() === $this->blockHitData){ - return false; + if($blockIn->getId() !== $this->blockHitId or $blockIn->getDamage() !== $this->blockHitData){ + $this->blockHit = $this->blockHitId = $this->blockHitData = null; } } - return $parent; + parent::onNearbyBlockChange(); + } + + public function hasMovementUpdate() : bool{ + return $this->blockHit === null and parent::hasMovementUpdate(); } public function move(float $dx, float $dy, float $dz) : void{ diff --git a/src/pocketmine/item/Bow.php b/src/pocketmine/item/Bow.php index 5807401ad..39e11a4c1 100644 --- a/src/pocketmine/item/Bow.php +++ b/src/pocketmine/item/Bow.php @@ -24,9 +24,11 @@ declare(strict_types=1); namespace pocketmine\item; use pocketmine\entity\Entity; +use pocketmine\entity\projectile\Arrow as ArrowEntity; use pocketmine\entity\projectile\Projectile; use pocketmine\event\entity\EntityShootBowEvent; use pocketmine\event\entity\ProjectileLaunchEvent; +use pocketmine\item\enchantment\Enchantment; use pocketmine\network\mcpe\protocol\LevelSoundEventPacket; use pocketmine\Player; @@ -64,6 +66,13 @@ class Bow extends Tool{ $entity = Entity::createEntity("Arrow", $player->getLevel(), $nbt, $player, $force == 2); if($entity instanceof Projectile){ + $infinity = $this->hasEnchantment(Enchantment::INFINITY); + if($infinity and $entity instanceof ArrowEntity){ + $entity->setPickupMode(ArrowEntity::PICKUP_CREATIVE); + } + if(($powerLevel = $this->getEnchantmentLevel(Enchantment::POWER)) > 0){ + $entity->setBaseDamage($entity->getBaseDamage() + (($powerLevel + 1) / 2)); + } $ev = new EntityShootBowEvent($player, $this, $entity, $force); if($force < 0.1 or $diff < 5){ @@ -80,7 +89,9 @@ class Bow extends Tool{ }else{ $entity->setMotion($entity->getMotion()->multiply($ev->getForce())); if($player->isSurvival()){ - $player->getInventory()->removeItem(ItemFactory::get(Item::ARROW, 0, 1)); + if(!$infinity){ //TODO: tipped arrows are still consumed when Infinity is applied + $player->getInventory()->removeItem(ItemFactory::get(Item::ARROW, 0, 1)); + } $this->applyDamage(1); } diff --git a/src/pocketmine/item/ItemIds.php b/src/pocketmine/item/ItemIds.php index 2fe989bb2..79cfb00e5 100644 --- a/src/pocketmine/item/ItemIds.php +++ b/src/pocketmine/item/ItemIds.php @@ -193,7 +193,7 @@ interface ItemIds extends BlockIds{ public const LEAD = 420; public const NAMETAG = 421, NAME_TAG = 421; public const PRISMARINE_CRYSTALS = 422; - public const MUTTONRAW = 423, MUTTON_RAW = 423, RAW_MUTTON = 423; + public const MUTTON = 423, MUTTONRAW = 423, MUTTON_RAW = 423, RAW_MUTTON = 423; public const COOKED_MUTTON = 424, MUTTONCOOKED = 424, MUTTON_COOKED = 424; public const ARMOR_STAND = 425; public const END_CRYSTAL = 426; diff --git a/src/pocketmine/item/enchantment/Enchantment.php b/src/pocketmine/item/enchantment/Enchantment.php index 8b4fca982..9d40e7758 100644 --- a/src/pocketmine/item/enchantment/Enchantment.php +++ b/src/pocketmine/item/enchantment/Enchantment.php @@ -121,6 +121,10 @@ class Enchantment{ self::registerEnchantment(new Enchantment(self::SILK_TOUCH, "%enchantment.untouching", self::RARITY_MYTHIC, self::SLOT_DIG, self::SLOT_SHEARS, 1)); self::registerEnchantment(new Enchantment(self::UNBREAKING, "%enchantment.durability", self::RARITY_UNCOMMON, self::SLOT_DIG | self::SLOT_ARMOR | self::SLOT_FISHING_ROD | self::SLOT_BOW, self::SLOT_TOOL | self::SLOT_CARROT_STICK | self::SLOT_ELYTRA, 3)); + self::registerEnchantment(new Enchantment(self::POWER, "%enchantment.arrowDamage", self::RARITY_COMMON, self::SLOT_BOW, self::SLOT_NONE, 5)); + + self::registerEnchantment(new Enchantment(self::INFINITY, "%enchantment.arrowInfinite", self::RARITY_MYTHIC, self::SLOT_BOW, self::SLOT_NONE, 1)); + self::registerEnchantment(new Enchantment(self::VANISHING, "%enchantment.curse.vanishing", self::RARITY_MYTHIC, self::SLOT_NONE, self::SLOT_ALL, 1)); } diff --git a/src/pocketmine/level/Explosion.php b/src/pocketmine/level/Explosion.php index 49300a66f..cc45e2082 100644 --- a/src/pocketmine/level/Explosion.php +++ b/src/pocketmine/level/Explosion.php @@ -236,6 +236,9 @@ class Explosion{ if(!isset($this->affectedBlocks[$index = Level::blockHash($sideBlock->x, $sideBlock->y, $sideBlock->z)]) and !isset($updateBlocks[$index])){ $this->level->getServer()->getPluginManager()->callEvent($ev = new BlockUpdateEvent($this->level->getBlockAt($sideBlock->x, $sideBlock->y, $sideBlock->z))); if(!$ev->isCancelled()){ + foreach($this->level->getNearbyEntities(new AxisAlignedBB($sideBlock->x - 1, $sideBlock->y - 1, $sideBlock->z - 1, $sideBlock->x + 2, $sideBlock->y + 2, $sideBlock->z + 2)) as $entity){ + $entity->onNearbyBlockChange(); + } $ev->getBlock()->onNearbyBlockChange(); } $updateBlocks[$index] = true;