From b4b888b0d8e478cbc2dd1a7dac620fd51190da87 Mon Sep 17 00:00:00 2001 From: dearminder Date: Fri, 26 Jul 2019 13:09:41 +0200 Subject: [PATCH 01/22] Changed Blaze Power Changed CaveSpider name to Cave Spider Added ZombiePigman Added ZombieVillager Added rest Chicken tempt seeds Added Ocelot Changed Tempted Pig items Added PolarBear Added Rabbit Added Skeleton Horse Added Zombie Horse Added Tempted Wolf Behaviour Changed Default gamerule for spawningmobs to true Changed Creative Inventory Egg for Zombie VIllager to Correct one --- src/pocketmine/entity/Entity.php | 14 ++ src/pocketmine/entity/hostile/Blaze.php | 2 +- src/pocketmine/entity/hostile/CaveSpider.php | 2 +- .../entity/hostile/ZombiePigman.php | 111 +++++++++++ .../entity/hostile/ZombieVillager.php | 105 ++++++++++ src/pocketmine/entity/passive/Chicken.php | 2 +- src/pocketmine/entity/passive/Ocelot.php | 125 ++++++++++++ src/pocketmine/entity/passive/Pig.php | 2 +- src/pocketmine/entity/passive/PolarBear.php | 105 ++++++++++ src/pocketmine/entity/passive/Rabbit.php | 79 ++++++++ .../entity/passive/SkeletonHorse.php | 181 ++++++++++++++++++ src/pocketmine/entity/passive/Wolf.php | 10 +- src/pocketmine/entity/passive/ZombieHorse.php | 178 +++++++++++++++++ src/pocketmine/level/GameRules.php | 2 +- 14 files changed, 909 insertions(+), 9 deletions(-) create mode 100644 src/pocketmine/entity/hostile/ZombiePigman.php create mode 100644 src/pocketmine/entity/hostile/ZombieVillager.php create mode 100644 src/pocketmine/entity/passive/Ocelot.php create mode 100644 src/pocketmine/entity/passive/PolarBear.php create mode 100644 src/pocketmine/entity/passive/Rabbit.php create mode 100644 src/pocketmine/entity/passive/SkeletonHorse.php create mode 100644 src/pocketmine/entity/passive/ZombieHorse.php diff --git a/src/pocketmine/entity/Entity.php b/src/pocketmine/entity/Entity.php index 87023f31001..a78002a44e4 100644 --- a/src/pocketmine/entity/Entity.php +++ b/src/pocketmine/entity/Entity.php @@ -40,6 +40,8 @@ use pocketmine\entity\hostile\Spider; use pocketmine\entity\hostile\Stray; use pocketmine\entity\hostile\Zombie; +use pocketmine\entity\hostile\ZombiePigman; +use pocketmine\entity\hostile\ZombieVillager; use pocketmine\entity\object\ArmorStand; use pocketmine\entity\object\ExperienceOrb; use pocketmine\entity\object\FallingBlock; @@ -54,11 +56,16 @@ use pocketmine\entity\passive\Cow; use pocketmine\entity\passive\Horse; use pocketmine\entity\passive\Mooshroom; +use pocketmine\entity\passive\Ocelot; use pocketmine\entity\passive\Pig; +use pocketmine\entity\passive\PolarBear; +use pocketmine\entity\passive\Rabbit; use pocketmine\entity\passive\Sheep; +use pocketmine\entity\passive\SkeletonHorse; use pocketmine\entity\passive\Squid; use pocketmine\entity\passive\Villager; use pocketmine\entity\passive\Wolf; +use pocketmine\entity\passive\ZombieHorse; use pocketmine\entity\projectile\Arrow; use pocketmine\entity\projectile\Egg; use pocketmine\entity\projectile\EnderPearl; @@ -382,12 +389,19 @@ public static function init() : void{ Entity::registerEntity(Villager::class, false, ['Villager', 'minecraft:villager']); Entity::registerEntity(Wolf::class, false, ['Wolf', 'minecraft:wolf']); Entity::registerEntity(Zombie::class, false, ['Zombie', 'minecraft:zombie']); + Entity::registerEntity(ZombieHorse::class, false, ['ZombieHorse', 'minecraft:zombiehorse']); Entity::registerEntity(Cow::class, false, ['Cow', 'minecraft:cow']); Entity::registerEntity(Sheep::class, false, ['Sheep', 'minecraft:sheep']); Entity::registerEntity(Mooshroom::class, false, ['Mooshroom', 'minecraft:mooshroom']); + Entity::registerEntity(Ocelot::class, false, ['Ocelot', 'minecraft:ocelot']); Entity::registerEntity(Pig::class, false, ['Pig', 'minecraft:pig']); + Entity::registerEntity(ZombiePigman::class, false, ['ZombiePigman', 'minecraft:zombiepigman']); + Entity::registerEntity(ZombieVillager::class, false, ['ZombieVillager', 'minecraft:zombievillager']); + Entity::registerEntity(PolarBear::class, false, ['PolarBear', 'minecraft:polarbear']); + Entity::registerEntity(Rabbit::class, false, ['Rabbit', 'minecraft:rabbit']); Entity::registerEntity(Cat::class, false, ['Cat', 'minecraft:cat']); Entity::registerEntity(Skeleton::class, false, ['Skeleton', 'minecraft:skeleton']); + Entity::registerEntity(SkeletonHorse::class, false, ['SkeletonHorse', 'minecraft:skeletonhorse']); Entity::registerEntity(Stray::class, false, ['Stray', 'minecraft:stray']); Entity::registerEntity(Husk::class, false, ['Husk', 'minecraft:husk']); Entity::registerEntity(Chicken::class, false, ['Chicken', 'minecraft:chicken']); diff --git a/src/pocketmine/entity/hostile/Blaze.php b/src/pocketmine/entity/hostile/Blaze.php index 507702994a8..af88dc08386 100644 --- a/src/pocketmine/entity/hostile/Blaze.php +++ b/src/pocketmine/entity/hostile/Blaze.php @@ -95,7 +95,7 @@ public function onBehaviorUpdate() : void{ public function onRangedAttackToTarget(Entity $target, float $power) : void{ $dv = $target->subtract($this)->normalize(); $fireball = new SmallFireball($this->level, Entity::createBaseNBT($this->add($this->random->nextFloat() * $power, $this->getEyeHeight(), $this->random->nextFloat() * $power), $dv), $this); - $fireball->setMotion($dv->multiply($power)); + $fireball->setMotion($dv->multiply(2)); $fireball->spawnToAll(); } diff --git a/src/pocketmine/entity/hostile/CaveSpider.php b/src/pocketmine/entity/hostile/CaveSpider.php index fca33e8f798..9761e663887 100644 --- a/src/pocketmine/entity/hostile/CaveSpider.php +++ b/src/pocketmine/entity/hostile/CaveSpider.php @@ -44,7 +44,7 @@ protected function initEntity() : void{ } public function getName() : string{ - return "CaveSpider"; + return "Cave Spider"; } public function onCollideWithEntity(Entity $entity) : void{ diff --git a/src/pocketmine/entity/hostile/ZombiePigman.php b/src/pocketmine/entity/hostile/ZombiePigman.php new file mode 100644 index 00000000000..24698975e0a --- /dev/null +++ b/src/pocketmine/entity/hostile/ZombiePigman.php @@ -0,0 +1,111 @@ +setMovementSpeed($this->isBaby() ? 0.35 : 0.23); + $this->setFollowRange(35); + $this->setAttackDamage(3); + + parent::initEntity(); + + $this->equipment = new AltayEntityEquipment($this); + + $this->equipment->setItemInHand(ItemFactory::get(Item::GOLDEN_SWORD)); + } + + public function getName() : string{ + return "Zombie Pigman"; + } + + public function getDrops() : array{ + $drops = [ + ItemFactory::get(Item::ROTTEN_FLESH, 0, mt_rand(0, 1)) + ]; + + if(mt_rand(0, 199) < 5){ + switch(mt_rand(0, 2)){ + case 0: + $drops[] = ItemFactory::get(Item::IRON_INGOT, 0, 1); + break; + case 1: + $drops[] = ItemFactory::get(Item::CARROT, 0, 1); + break; + case 2: + $drops[] = ItemFactory::get(Item::POTATO, 0, 1); + break; + } + } + + return $drops; + } + + public function getXpDropAmount() : int{ + //TODO: check for equipment + return $this->isBaby() ? 12 : 5; + } + + protected function addBehaviors() : void{ + $this->behaviorPool->setBehavior(0, new FloatBehavior($this)); + $this->behaviorPool->setBehavior(1, new MeleeAttackBehavior($this, 1.0)); + $this->behaviorPool->setBehavior(2, new WanderBehavior($this, 1.0)); + $this->behaviorPool->setBehavior(3, new LookAtPlayerBehavior($this, 8.0)); + $this->behaviorPool->setBehavior(4, new RandomLookAroundBehavior($this)); + + $this->targetBehaviorPool->setBehavior(1, new FindAttackableTargetBehavior($this, Player::class)); + $this->targetBehaviorPool->setBehavior(2, new FindAttackableTargetBehavior($this, Villager::class)); + } + + + public function sendSpawnPacket(Player $player) : void{ + parent::sendSpawnPacket($player); + + $this->equipment->sendContents([$player]); + } +} \ No newline at end of file diff --git a/src/pocketmine/entity/hostile/ZombieVillager.php b/src/pocketmine/entity/hostile/ZombieVillager.php new file mode 100644 index 00000000000..7f274bbe69d --- /dev/null +++ b/src/pocketmine/entity/hostile/ZombieVillager.php @@ -0,0 +1,105 @@ +setMovementSpeed($this->isBaby() ? 0.35 : 0.23); + $this->setFollowRange(35); + $this->setAttackDamage(3); + + parent::initEntity(); + } + + public function getName() : string{ + return "Zombie Villager"; + } + + public function getDrops() : array{ + $drops = [ + ItemFactory::get(Item::ROTTEN_FLESH, 0, mt_rand(0, 2)) + ]; + + if(mt_rand(0, 199) < 5){ + switch(mt_rand(0, 2)){ + case 0: + $drops[] = ItemFactory::get(Item::IRON_INGOT, 0, 1); + break; + case 1: + $drops[] = ItemFactory::get(Item::CARROT, 0, 1); + break; + case 2: + $drops[] = ItemFactory::get(Item::POTATO, 0, 1); + break; + } + } + + return $drops; + } + + public function getXpDropAmount() : int{ + //TODO: check for equipment + return $this->isBaby() ? 12 : 5; + } + + protected function addBehaviors() : void{ + $this->behaviorPool->setBehavior(0, new FloatBehavior($this)); + $this->behaviorPool->setBehavior(1, new MeleeAttackBehavior($this, 1.0)); + $this->behaviorPool->setBehavior(2, new WanderBehavior($this, 1.0)); + $this->behaviorPool->setBehavior(3, new LookAtPlayerBehavior($this, 8.0)); + $this->behaviorPool->setBehavior(4, new RandomLookAroundBehavior($this)); + + $this->targetBehaviorPool->setBehavior(1, new FindAttackableTargetBehavior($this, Player::class)); + $this->targetBehaviorPool->setBehavior(2, new FindAttackableTargetBehavior($this, Villager::class)); + } + + public function entityBaseTick(int $diff = 1) : bool{ + if(!$this->isOnFire() and $this->level->isDayTime() and !$this->isImmobile()){ + if(!$this->isInsideOfWater() and $this->level->canSeeSky($this)){ + $this->setOnFire(5); + } + } + return parent::entityBaseTick($diff); + } +} \ No newline at end of file diff --git a/src/pocketmine/entity/passive/Chicken.php b/src/pocketmine/entity/passive/Chicken.php index 25972f3835a..4b33f9540e3 100644 --- a/src/pocketmine/entity/passive/Chicken.php +++ b/src/pocketmine/entity/passive/Chicken.php @@ -68,7 +68,7 @@ protected function addBehaviors() : void{ $this->behaviorPool->setBehavior(0, new FloatBehavior($this)); $this->behaviorPool->setBehavior(1, new PanicBehavior($this, 1.4)); $this->behaviorPool->setBehavior(2, new MateBehavior($this, 1.0)); - $this->behaviorPool->setBehavior(3, new TemptedBehavior($this, [Item::WHEAT_SEEDS], 1.0)); + $this->behaviorPool->setBehavior(3, new TemptedBehavior($this, [Item::WHEAT_SEEDS, Item::PUMPKIN_SEEDS, Item::MELON_SEEDS, Item::BEETROOT_SEEDS], 1.0)); $this->behaviorPool->setBehavior(4, new FollowParentBehavior($this, 1.1)); $this->behaviorPool->setBehavior(5, new WanderBehavior($this, 1.0)); $this->behaviorPool->setBehavior(6, new LookAtPlayerBehavior($this, 6.0)); diff --git a/src/pocketmine/entity/passive/Ocelot.php b/src/pocketmine/entity/passive/Ocelot.php new file mode 100644 index 00000000000..b37ac557787 --- /dev/null +++ b/src/pocketmine/entity/passive/Ocelot.php @@ -0,0 +1,125 @@ +behaviorPool->setBehavior(0, new FloatBehavior($this)); + $this->behaviorPool->setBehavior(1, new MateBehavior($this, 2.0)); + $this->behaviorPool->setBehavior(2, new FollowOwnerBehavior($this, 1.0)); + $this->behaviorPool->setBehavior(3, new PanicBehavior($this, 2.0)); + $this->behaviorPool->setBehavior(4, new LookAtPlayerBehavior($this, 14.0)); + $this->behaviorPool->setBehavior(5, new RandomLookAroundBehavior($this)); + $this->behaviorPool->setBehavior(6, new TemptedBehavior($this, [Item::RAW_SALMON, Item::RAW_FISH], 1.0)); + $this->behaviorPool->setBehavior(7, new SittingBehavior($this)); + // TODO: attack turtle and rabbit + } + + protected function initEntity() : void{ + $this->setMaxHealth(10); + $this->setMovementSpeed(0.3); + $this->setFollowRange(16); + $this->setAttackDamage(3); + $this->propertyManager->setInt(self::DATA_VARIANT, intval($this->namedtag->getInt("CatType", 0))); + $this->propertyManager->setInt(self::DATA_COLOR, intval($this->namedtag->getInt("CollarColor", mt_rand(0, 15)))); + parent::initEntity(); + } + + public function getName() : string{ + return "Ocelot"; + } + + public function onInteract(Player $player, Item $item, Vector3 $clickPos) : bool{ + if(!$this->isImmobile()){ + if($item->getId() == Item::RAW_SALMON || $item->getId() == Item::RAW_FISH){ + if($player->isSurvival()){ + $item->pop(); + } + if($this->isTamed()){ + $this->setInLove(true); + $this->setHealth(min($this->getMaxHealth(), $this->getHealth() + 2)); + }elseif(mt_rand(0, 2) == 0){ + $this->setOwningEntity($player); + $this->setTamed(); + $this->setSitting(); + $this->broadcastEntityEvent(ActorEventPacket::TAME_SUCCESS); + }else{ + $this->broadcastEntityEvent(ActorEventPacket::TAME_FAIL); + } + return true; + }else{ + if($this->isTamed()){ + $this->setSitting(!$this->isSitting()); + } + } + } + return parent::onInteract($player, $item, $clickPos); + } + + public function getXpDropAmount() : int{ + $damage = $this->getLastDamageCause(); + if($damage instanceof EntityDamageByEntityEvent){ + $damager = $damage->getDamager(); + if($damager instanceof Player || ($damager instanceof Wolf && $damager->isTamed())){ + return rand(1, ($this->isInLove() ? 7 : 3)); + } + } + return 0; + } + + public function getDrops() : array{ + return [ + ItemFactory::get(Item::STRING, 0, rand(0, 2)), + ]; + } + + public function attack(EntityDamageEvent $source) : void{ + if($source->getCause() !== EntityDamageEvent::CAUSE_FALL){ + parent::attack($source); + } + } +} \ No newline at end of file diff --git a/src/pocketmine/entity/passive/Pig.php b/src/pocketmine/entity/passive/Pig.php index 5e685b7f692..f783215f570 100644 --- a/src/pocketmine/entity/passive/Pig.php +++ b/src/pocketmine/entity/passive/Pig.php @@ -52,7 +52,7 @@ protected function addBehaviors() : void{ $this->behaviorPool->setBehavior(0, new FloatBehavior($this)); $this->behaviorPool->setBehavior(1, new PanicBehavior($this, 1.25)); $this->behaviorPool->setBehavior(2, new MateBehavior($this, 1.0)); - $this->behaviorPool->setBehavior(3, new TemptedBehavior($this, [Item::WHEAT], 1.2)); + $this->behaviorPool->setBehavior(3, new TemptedBehavior($this, [Item::CARROT, Item::CARROT_ON_A_STICK, Item::POTATO, Item::BEETROOT], 1.2)); // TODO: Add ControlledByPlayerBehavior $this->behaviorPool->setBehavior(4, new FollowParentBehavior($this, 1.1)); $this->behaviorPool->setBehavior(5, new WanderBehavior($this, 1.0)); diff --git a/src/pocketmine/entity/passive/PolarBear.php b/src/pocketmine/entity/passive/PolarBear.php new file mode 100644 index 00000000000..d8e684c1a67 --- /dev/null +++ b/src/pocketmine/entity/passive/PolarBear.php @@ -0,0 +1,105 @@ +behaviorPool->setBehavior(0, new FloatBehavior($this)); + $this->behaviorPool->setBehavior(1, new MateBehavior($this, 1.0)); + $this->behaviorPool->setBehavior(2, new MeleeAttackBehavior($this, 1.0)); + $this->behaviorPool->setBehavior(3, new FollowParentBehavior($this, 1.1)); + $this->behaviorPool->setBehavior(4, new WanderBehavior($this, 1.0)); + $this->behaviorPool->setBehavior(5, new LookAtPlayerBehavior($this, 16.0)); + $this->behaviorPool->setBehavior(6, new RandomLookAroundBehavior($this)); + + $this->targetBehaviorPool->setBehavior(0, new HurtByTargetBehavior($this)); + } + public + function initEntity(): void + { + $this->setMaxHealth(30); + $this->setMovementSpeed(0.30); + $this->setAttackDamage(4); + $this->setFollowRange(16); + parent::initEntity(); + } + //TODO: atack foxes + public + function getName(): string + { + return "Polar Bear"; + } + + public function setTargetEntity(?Entity $target) : void{ + parent::setTargetEntity($target); + if($target == null){ + $this->setAngry(false); + } + } + public function isAngry() : bool{ + return $this->getGenericFlag(self::DATA_FLAG_ANGRY); + } + + public function setAngry(bool $angry = true) : void{ + $this->setGenericFlag(self::DATA_FLAG_ANGRY, $angry); + } + + private function generateRandomDirection(): Vector3 + { + return new Vector3(mt_rand(-1000, 1000) / 1000, mt_rand(-500, 500) / 1000, mt_rand(-1000, 1000) / 1000); + } + + public function getXpDropAmount() : int{ + return rand(1, 3); + } + + public + function getDrops(): array + { + return [ + ItemFactory::get(Item::RAW_SALMON, 0, mt_rand(0, 2)) + ]; + } + } \ No newline at end of file diff --git a/src/pocketmine/entity/passive/Rabbit.php b/src/pocketmine/entity/passive/Rabbit.php new file mode 100644 index 00000000000..f1e20d5a5a1 --- /dev/null +++ b/src/pocketmine/entity/passive/Rabbit.php @@ -0,0 +1,79 @@ +behaviorPool->setBehavior(0, new FloatBehavior($this)); + $this->behaviorPool->setBehavior(1, new MateBehavior($this, 2.0)); + $this->behaviorPool->setBehavior(3, new PanicBehavior($this, 2.0)); + $this->behaviorPool->setBehavior(4, new LookAtPlayerBehavior($this, 14.0)); + $this->behaviorPool->setBehavior(5, new RandomLookAroundBehavior($this)); + $this->behaviorPool->setBehavior(6, new TemptedBehavior($this, [Item::CARROT], 1.0)); + // TODO: running away from player + } + + protected function initEntity() : void{ + $this->setMaxHealth(3); + $this->setMovementSpeed(0.3); + $this->setFollowRange(16); + $this->propertyManager->setInt(self::DATA_VARIANT, intval($this->namedtag->getInt("RabbitType", mt_rand(1, 6)))); + + parent::initEntity(); + } + + public function getName() : string{ + return "Rabbit"; + } + + + + public function getXpDropAmount() : int{ + return rand(1, 3); + } + + public function getDrops() : array{ + return [ + ItemFactory::get(Item::RABBIT_HIDE, 0, rand(0, 1)), + ($this->isOnFire() ? ItemFactory::get(Item::COOKED_RABBIT, 0, rand(0, 1)) : ItemFactory::get(Item::RAW_RABBIT, 0, rand(0, 1))) + ]; + } +} \ No newline at end of file diff --git a/src/pocketmine/entity/passive/SkeletonHorse.php b/src/pocketmine/entity/passive/SkeletonHorse.php new file mode 100644 index 00000000000..d2897ad117d --- /dev/null +++ b/src/pocketmine/entity/passive/SkeletonHorse.php @@ -0,0 +1,181 @@ +inventory; + } + + protected function addBehaviors() : void{ + $this->behaviorPool->setBehavior(0, new HorseRiddenBehavior($this)); + $this->behaviorPool->setBehavior(1, new FloatBehavior($this)); + $this->behaviorPool->setBehavior(2, new PanicBehavior($this, 1.25)); + $this->behaviorPool->setBehavior(3, new MateBehavior($this, 1.0)); + $this->behaviorPool->setBehavior(5, new FollowParentBehavior($this, 1.1)); + $this->behaviorPool->setBehavior(6, new WanderBehavior($this, 1.0)); + $this->behaviorPool->setBehavior(7, new LookAtPlayerBehavior($this, 6.0)); + $this->behaviorPool->setBehavior(8, new RandomLookAroundBehavior($this)); + } + + protected function initEntity() : void{ + $this->setMaxHealth(15); + $this->setMovementSpeed($this->getModifiedMovementSpeed()); + $this->setJumpStrength($this->getModifiedJumpStrength()); + $this->setFollowRange(35); + + if($this->namedtag->hasTag("Variant", IntTag::class) and $this->namedtag->hasTag("MarkVariant", IntTag::class)){ + $this->setVariant($this->namedtag->getInt("Variant")); + $this->setMarkVariant($this->namedtag->getInt("MarkVariant")); + }else{ + $this->setVariant($this->random->nextBoundedInt(7)); + $this->setMarkVariant($this->random->nextBoundedInt(5)); + } + + $this->inventory = new HorseInventory($this); + + if($this->namedtag->hasTag("ArmorItem", CompoundTag::class)){ + $this->inventory->setArmor(Item::nbtDeserialize($this->namedtag->getCompoundTag("ArmorItem"))); + } + + if($this->namedtag->hasTag("SaddleItem", CompoundTag::class)){ + $this->inventory->setSaddle(Item::nbtDeserialize($this->namedtag->getCompoundTag("SaddleItem"))); + } + + parent::initEntity(); + } + + public function addAttributes() : void{ + parent::addAttributes(); + + $this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::HORSE_JUMP_STRENGTH)); + } + + public function getRiderSeatPosition(int $seatNumber = 0) : Vector3{ + return new Vector3(0, 1.1, -0.2); + } + + public function setSaddled(bool $value = true) : void{ + parent::setSaddled($value); + + $this->setGenericFlag(self::DATA_FLAG_CAN_POWER_JUMP, $value); + } + + public function onInteract(Player $player, Item $item, Vector3 $clickPos) : bool{ + if(!$this->isImmobile()){ + // TODO: feeding + + if($player->isSneaking()){ + if($this->isTamed()){ + $player->addWindow($this->inventory); + }else{ + $this->rearUp(); + } + + return true; + } + } + return parent::onInteract($player, $item, $clickPos); + } + + public function sendSpawnPacket(Player $player) : void{ + parent::sendSpawnPacket($player); + + $this->inventory->sendArmor($player); + } + + public function doHitAnimation() : void{ + parent::doHitAnimation(); + + foreach($this->getViewers() as $player){ // WTF + $this->inventory->sendArmor($player); + } + } + + public function saveNBT() : void{ + parent::saveNBT(); + + if($this->inventory !== null){ + $this->namedtag->setTag($this->inventory->getSaddle()->nbtSerialize(-1, "SaddleItem")); + $this->namedtag->setTag($this->inventory->getArmor()->nbtSerialize(-1, "ArmorItem")); + } + } + public + function getDrops(): array + { + return [ + ItemFactory::get(Item::BONE, 0, mt_rand(0, 2)) + ]; + } + //TODO: add changing normal horse to skeleton by lightning +} \ No newline at end of file diff --git a/src/pocketmine/entity/passive/Wolf.php b/src/pocketmine/entity/passive/Wolf.php index 84697b635fb..1b4e1abfcaa 100644 --- a/src/pocketmine/entity/passive/Wolf.php +++ b/src/pocketmine/entity/passive/Wolf.php @@ -34,6 +34,7 @@ use pocketmine\entity\behavior\OwnerHurtTargetBehavior; use pocketmine\entity\behavior\RandomLookAroundBehavior; use pocketmine\entity\behavior\SittingBehavior; +use pocketmine\entity\behavior\TemptedBehavior; use pocketmine\entity\behavior\WanderBehavior; use pocketmine\entity\Entity; use pocketmine\entity\Tamable; @@ -54,10 +55,11 @@ protected function addBehaviors() : void{ $this->behaviorPool->setBehavior(1, new SittingBehavior($this)); $this->behaviorPool->setBehavior(2, new JumpAttackBehavior($this, 1.0)); $this->behaviorPool->setBehavior(3, new MeleeAttackBehavior($this, 2.0)); - $this->behaviorPool->setBehavior(4, new FollowOwnerBehavior($this, 2.0)); - $this->behaviorPool->setBehavior(5, new WanderBehavior($this, 1.0)); - $this->behaviorPool->setBehavior(6, new LookAtPlayerBehavior($this, 8.0)); - $this->behaviorPool->setBehavior(7, new RandomLookAroundBehavior($this)); + $this->behaviorPool->setBehavior(4, new TemptedBehavior($this, [Item::BONE], 0.8)); + $this->behaviorPool->setBehavior(5, new FollowOwnerBehavior($this, 1.0)); + $this->behaviorPool->setBehavior(6, new WanderBehavior($this, 1.0)); + $this->behaviorPool->setBehavior(7, new LookAtPlayerBehavior($this, 8.0)); + $this->behaviorPool->setBehavior(8, new RandomLookAroundBehavior($this)); $this->targetBehaviorPool->setBehavior(0, new HurtByTargetBehavior($this)); $this->targetBehaviorPool->setBehavior(1, new OwnerHurtByTargetBehavior($this)); diff --git a/src/pocketmine/entity/passive/ZombieHorse.php b/src/pocketmine/entity/passive/ZombieHorse.php new file mode 100644 index 00000000000..361897bd494 --- /dev/null +++ b/src/pocketmine/entity/passive/ZombieHorse.php @@ -0,0 +1,178 @@ +inventory; + } + + protected function addBehaviors() : void{ + $this->behaviorPool->setBehavior(1, new FloatBehavior($this)); + $this->behaviorPool->setBehavior(2, new PanicBehavior($this, 1.25)); + $this->behaviorPool->setBehavior(3, new MateBehavior($this, 1.0)); + $this->behaviorPool->setBehavior(5, new FollowParentBehavior($this, 1.1)); + $this->behaviorPool->setBehavior(6, new WanderBehavior($this, 1.0)); + $this->behaviorPool->setBehavior(7, new LookAtPlayerBehavior($this, 6.0)); + $this->behaviorPool->setBehavior(8, new RandomLookAroundBehavior($this)); + } + + protected function initEntity() : void{ + $this->setMaxHealth(15); + $this->setMovementSpeed($this->getModifiedMovementSpeed()); + $this->setJumpStrength($this->getModifiedJumpStrength()); + $this->setFollowRange(35); + + if($this->namedtag->hasTag("Variant", IntTag::class) and $this->namedtag->hasTag("MarkVariant", IntTag::class)){ + $this->setVariant($this->namedtag->getInt("Variant")); + $this->setMarkVariant($this->namedtag->getInt("MarkVariant")); + }else{ + $this->setVariant($this->random->nextBoundedInt(7)); + $this->setMarkVariant($this->random->nextBoundedInt(5)); + } + + $this->inventory = new HorseInventory($this); + + if($this->namedtag->hasTag("ArmorItem", CompoundTag::class)){ + $this->inventory->setArmor(Item::nbtDeserialize($this->namedtag->getCompoundTag("ArmorItem"))); + } + + if($this->namedtag->hasTag("SaddleItem", CompoundTag::class)){ + $this->inventory->setSaddle(Item::nbtDeserialize($this->namedtag->getCompoundTag("SaddleItem"))); + } + + parent::initEntity(); + } + + public function addAttributes() : void{ + parent::addAttributes(); + + $this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::HORSE_JUMP_STRENGTH)); + } + + public function getRiderSeatPosition(int $seatNumber = 0) : Vector3{ + return new Vector3(0, 1.1, -0.2); + } + + public function setSaddled(bool $value = true) : void{ + parent::setSaddled($value); + + $this->setGenericFlag(self::DATA_FLAG_CAN_POWER_JUMP, $value); + } + + public function onInteract(Player $player, Item $item, Vector3 $clickPos) : bool{ + if(!$this->isImmobile()){ + // TODO: feeding + + if($player->isSneaking()){ + if($this->isTamed()){ + $player->addWindow($this->inventory); + }else{ + $this->rearUp(); + } + + return true; + } + } + return parent::onInteract($player, $item, $clickPos); + } + + public function sendSpawnPacket(Player $player) : void{ + parent::sendSpawnPacket($player); + + $this->inventory->sendArmor($player); + } + + public function doHitAnimation() : void{ + parent::doHitAnimation(); + + foreach($this->getViewers() as $player){ // WTF + $this->inventory->sendArmor($player); + } + } + + public function saveNBT() : void{ + parent::saveNBT(); + + if($this->inventory !== null){ + $this->namedtag->setTag($this->inventory->getSaddle()->nbtSerialize(-1, "SaddleItem")); + $this->namedtag->setTag($this->inventory->getArmor()->nbtSerialize(-1, "ArmorItem")); + } + } + public + function getDrops(): array + { + return [ + ItemFactory::get(Item::ROTTEN_FLESH, 0, mt_rand(0, 2)) + ]; + } +} \ No newline at end of file diff --git a/src/pocketmine/level/GameRules.php b/src/pocketmine/level/GameRules.php index c3ed40f4037..1e78eeecfad 100644 --- a/src/pocketmine/level/GameRules.php +++ b/src/pocketmine/level/GameRules.php @@ -71,7 +71,7 @@ public function __construct(){ $this->setBool(self::RULE_DO_FIRE_TICK, true); $this->setBool(self::RULE_DO_INSOMNIA, true); $this->setBool(self::RULE_DO_MOB_LOOT, true); - $this->setBool(self::RULE_DO_MOB_SPAWNING, false); + $this->setBool(self::RULE_DO_MOB_SPAWNING, true); $this->setBool(self::RULE_DO_TILE_DROPS, true); $this->setBool(self::RULE_DO_WEATHER_CYCLE, true); $this->setBool(self::RULE_DROWNING_DAMAGE, true); From d4024fa4e3487e03ba33709569d8de09a1d455a7 Mon Sep 17 00:00:00 2001 From: dearminder Date: Fri, 26 Jul 2019 19:50:06 +0200 Subject: [PATCH 02/22] Added Cod and Tropical Fish --- src/pocketmine/entity/Entity.php | 4 + src/pocketmine/entity/passive/Cod.php | 134 ++++++++++++++++++ .../entity/passive/TropicalFish.php | 134 ++++++++++++++++++ 3 files changed, 272 insertions(+) create mode 100644 src/pocketmine/entity/passive/Cod.php create mode 100644 src/pocketmine/entity/passive/TropicalFish.php diff --git a/src/pocketmine/entity/Entity.php b/src/pocketmine/entity/Entity.php index a78002a44e4..e4fa7d8b946 100644 --- a/src/pocketmine/entity/Entity.php +++ b/src/pocketmine/entity/Entity.php @@ -53,6 +53,7 @@ use pocketmine\entity\object\ItemEntity; use pocketmine\entity\passive\Cat; use pocketmine\entity\passive\Chicken; +use pocketmine\entity\passive\Cod; use pocketmine\entity\passive\Cow; use pocketmine\entity\passive\Horse; use pocketmine\entity\passive\Mooshroom; @@ -63,6 +64,7 @@ use pocketmine\entity\passive\Sheep; use pocketmine\entity\passive\SkeletonHorse; use pocketmine\entity\passive\Squid; +use pocketmine\entity\passive\TropicalFish; use pocketmine\entity\passive\Villager; use pocketmine\entity\passive\Wolf; use pocketmine\entity\passive\ZombieHorse; @@ -386,6 +388,8 @@ public static function init() : void{ Entity::registerEntity(Snowball::class, false, ['Snowball', 'minecraft:snowball']); Entity::registerEntity(SplashPotion::class, false, ['ThrownPotion', 'minecraft:potion', 'thrownpotion']); Entity::registerEntity(Squid::class, false, ['Squid', 'minecraft:squid']); + Entity::registerEntity(TropicalFish::class, false, ['TropicalFish', 'minecraft:tropicalfish']); + Entity::registerEntity(Cod::class, false, ['Cod', 'minecraft:cod']); Entity::registerEntity(Villager::class, false, ['Villager', 'minecraft:villager']); Entity::registerEntity(Wolf::class, false, ['Wolf', 'minecraft:wolf']); Entity::registerEntity(Zombie::class, false, ['Zombie', 'minecraft:zombie']); diff --git a/src/pocketmine/entity/passive/Cod.php b/src/pocketmine/entity/passive/Cod.php new file mode 100644 index 00000000000..6db4ea624f0 --- /dev/null +++ b/src/pocketmine/entity/passive/Cod.php @@ -0,0 +1,134 @@ +setMaxHealth(3); + + parent::initEntity(); + } + + public function getName() : string{ + return "Tropical Fish"; + } + + public function attack(EntityDamageEvent $source) : void{ + parent::attack($source); + if($source->isCancelled()){ + return; + } + + if($source instanceof EntityDamageByEntityEvent){ + $this->swimSpeed = mt_rand(150, 350) / 2000; + $e = $source->getDamager(); + if($e !== null){ + $this->swimDirection = (new Vector3($this->x - $e->x, $this->y - $e->y, $this->z - $e->z))->normalize(); + } + + $this->broadcastEntityEvent(ActorEventPacket::SQUID_INK_CLOUD); + } + } + + private function generateRandomDirection() : Vector3{ + return new Vector3(mt_rand(-1000, 1000) / 1000, mt_rand(-500, 500) / 1000, mt_rand(-1000, 1000) / 1000); + } + + + public function entityBaseTick(int $tickDiff = 1) : bool{ + if($this->closed){ + return false; + } + + if(++$this->switchDirectionTicker === 100 or $this->isCollided){ + $this->switchDirectionTicker = 0; + if(mt_rand(0, 100) < 50){ + $this->swimDirection = null; + } + } + + $hasUpdate = parent::entityBaseTick($tickDiff); + + if($this->isAlive()){ + + if($this->y > 62 and $this->swimDirection !== null){ + $this->swimDirection->y = -0.5; + } + + $inWater = $this->isUnderwater(); + if(!$inWater){ + $this->swimDirection = null; + }elseif($this->swimDirection !== null){ + if($this->motion->lengthSquared() <= $this->swimDirection->lengthSquared()){ + $this->motion = $this->swimDirection->multiply($this->swimSpeed); + } + }else{ + $this->swimDirection = $this->generateRandomDirection(); + $this->swimSpeed = mt_rand(50, 100) / 2000; + } + + $f = sqrt(($this->motion->x ** 2) + ($this->motion->z ** 2)); + $this->yaw = (-atan2($this->motion->x, $this->motion->z) * 180 / M_PI); + $this->pitch = (-atan2($f, $this->motion->y) * 180 / M_PI); + } + + return $hasUpdate; + } + + public function getDrops() : array{ + return [ + ItemFactory::get(Item::RAW_FISH, 0, 1), + //TODO: Add percentage drop for bone + ]; + } + + protected function applyGravity() : void{ + if(!$this->isUnderwater()){ + parent::applyGravity(); + } + } +} \ No newline at end of file diff --git a/src/pocketmine/entity/passive/TropicalFish.php b/src/pocketmine/entity/passive/TropicalFish.php new file mode 100644 index 00000000000..f82081aefce --- /dev/null +++ b/src/pocketmine/entity/passive/TropicalFish.php @@ -0,0 +1,134 @@ +setMaxHealth(3); + //TODO: Add diffrent styles of fish + parent::initEntity(); + } + + public function getName() : string{ + return "Tropical Fish"; + } + + public function attack(EntityDamageEvent $source) : void{ + parent::attack($source); + if($source->isCancelled()){ + return; + } + + if($source instanceof EntityDamageByEntityEvent){ + $this->swimSpeed = mt_rand(150, 350) / 2000; + $e = $source->getDamager(); + if($e !== null){ + $this->swimDirection = (new Vector3($this->x - $e->x, $this->y - $e->y, $this->z - $e->z))->normalize(); + } + + $this->broadcastEntityEvent(ActorEventPacket::SQUID_INK_CLOUD); + } + } + + private function generateRandomDirection() : Vector3{ + return new Vector3(mt_rand(-1000, 1000) / 1000, mt_rand(-500, 500) / 1000, mt_rand(-1000, 1000) / 1000); + } + + + public function entityBaseTick(int $tickDiff = 1) : bool{ + if($this->closed){ + return false; + } + + if(++$this->switchDirectionTicker === 100 or $this->isCollided){ + $this->switchDirectionTicker = 0; + if(mt_rand(0, 100) < 50){ + $this->swimDirection = null; + } + } + + $hasUpdate = parent::entityBaseTick($tickDiff); + + if($this->isAlive()){ + + if($this->y > 62 and $this->swimDirection !== null){ + $this->swimDirection->y = -0.5; + } + + $inWater = $this->isUnderwater(); + if(!$inWater){ + $this->swimDirection = null; + }elseif($this->swimDirection !== null){ + if($this->motion->lengthSquared() <= $this->swimDirection->lengthSquared()){ + $this->motion = $this->swimDirection->multiply($this->swimSpeed); + } + }else{ + $this->swimDirection = $this->generateRandomDirection(); + $this->swimSpeed = mt_rand(50, 100) / 2000; + } + + $f = sqrt(($this->motion->x ** 2) + ($this->motion->z ** 2)); + $this->yaw = (-atan2($this->motion->x, $this->motion->z) * 180 / M_PI); + $this->pitch = (-atan2($f, $this->motion->y) * 180 / M_PI); + } + + return $hasUpdate; + } + + public function getDrops() : array{ + return [ + ItemFactory::get(Item::CLOWNFISH, 0, 1), + //TODO: Add percentage drop for bone + ]; + } + + protected function applyGravity() : void{ + if(!$this->isUnderwater()){ + parent::applyGravity(); + } + } +} \ No newline at end of file From a5962621f90584789a95e98d11734613c680acd1 Mon Sep 17 00:00:00 2001 From: dearminder Date: Sat, 27 Jul 2019 14:44:09 +0200 Subject: [PATCH 03/22] Added WitherSkeleton, Dolphin, Pufferfish, Salmon Added percentage drop for Cod, TropicalFish, PolarBear --- src/pocketmine/entity/Entity.php | 8 + .../entity/hostile/WitherSkeleton.php | 116 +++++++++++++ src/pocketmine/entity/passive/Cod.php | 9 +- src/pocketmine/entity/passive/Dolphin.php | 139 ++++++++++++++++ src/pocketmine/entity/passive/PolarBear.php | 11 +- src/pocketmine/entity/passive/Pufferfish.php | 152 ++++++++++++++++++ src/pocketmine/entity/passive/Salmon.php | 137 ++++++++++++++++ .../entity/passive/TropicalFish.php | 9 +- 8 files changed, 572 insertions(+), 9 deletions(-) create mode 100644 src/pocketmine/entity/hostile/WitherSkeleton.php create mode 100644 src/pocketmine/entity/passive/Dolphin.php create mode 100644 src/pocketmine/entity/passive/Pufferfish.php create mode 100644 src/pocketmine/entity/passive/Salmon.php diff --git a/src/pocketmine/entity/Entity.php b/src/pocketmine/entity/Entity.php index e4fa7d8b946..a1d1ece4c8a 100644 --- a/src/pocketmine/entity/Entity.php +++ b/src/pocketmine/entity/Entity.php @@ -39,6 +39,7 @@ use pocketmine\entity\hostile\Skeleton; use pocketmine\entity\hostile\Spider; use pocketmine\entity\hostile\Stray; +use pocketmine\entity\hostile\WitherSkeleton; use pocketmine\entity\hostile\Zombie; use pocketmine\entity\hostile\ZombiePigman; use pocketmine\entity\hostile\ZombieVillager; @@ -54,6 +55,9 @@ use pocketmine\entity\passive\Cat; use pocketmine\entity\passive\Chicken; use pocketmine\entity\passive\Cod; +use pocketmine\entity\passive\Dolphin; +use pocketmine\entity\passive\Pufferfish; +use pocketmine\entity\passive\Salmon; use pocketmine\entity\passive\Cow; use pocketmine\entity\passive\Horse; use pocketmine\entity\passive\Mooshroom; @@ -390,6 +394,9 @@ public static function init() : void{ Entity::registerEntity(Squid::class, false, ['Squid', 'minecraft:squid']); Entity::registerEntity(TropicalFish::class, false, ['TropicalFish', 'minecraft:tropicalfish']); Entity::registerEntity(Cod::class, false, ['Cod', 'minecraft:cod']); + Entity::registerEntity(Pufferfish::class, false, ['Pufferfish', 'minecraft:pufferfish']); + Entity::registerEntity(Dolphin::class, false, ['Dolphin', 'minecraft:dolphin']); + Entity::registerEntity(Salmon::class, false, ['Salmon', 'minecraft:salmon']); Entity::registerEntity(Villager::class, false, ['Villager', 'minecraft:villager']); Entity::registerEntity(Wolf::class, false, ['Wolf', 'minecraft:wolf']); Entity::registerEntity(Zombie::class, false, ['Zombie', 'minecraft:zombie']); @@ -401,6 +408,7 @@ public static function init() : void{ Entity::registerEntity(Pig::class, false, ['Pig', 'minecraft:pig']); Entity::registerEntity(ZombiePigman::class, false, ['ZombiePigman', 'minecraft:zombiepigman']); Entity::registerEntity(ZombieVillager::class, false, ['ZombieVillager', 'minecraft:zombievillager']); + Entity::registerEntity(WitherSkeleton::class, false, ['WitherSkeleton', 'minecraft:witherskeleon']); Entity::registerEntity(PolarBear::class, false, ['PolarBear', 'minecraft:polarbear']); Entity::registerEntity(Rabbit::class, false, ['Rabbit', 'minecraft:rabbit']); Entity::registerEntity(Cat::class, false, ['Cat', 'minecraft:cat']); diff --git a/src/pocketmine/entity/hostile/WitherSkeleton.php b/src/pocketmine/entity/hostile/WitherSkeleton.php new file mode 100644 index 00000000000..43432f11b6d --- /dev/null +++ b/src/pocketmine/entity/hostile/WitherSkeleton.php @@ -0,0 +1,116 @@ +setMovementSpeed(0.3); + $this->setFollowRange(35); + $this->setAttackDamage(3); + + parent::initEntity(); + + $this->equipment = new AltayEntityEquipment($this); + + $this->equipment->setItemInHand(ItemFactory::get(Item::STONE_SWORD)); + } + + public function getName() : string{ + return "Wither Skeleton"; + } + + public function getDrops() : array{ + $drops = [ + ItemFactory::get(Item::BONE, 0, mt_rand(0, 1)) + ]; + + if(mt_rand(0, 2) < 1){ + $drops[] = ItemFactory::get(Item::COAL, 0, 1); + } + if(mt_rand(1, 40) ===1){ + $drops[] = ItemFactory::get(Item::MOB_HEAD, 1, 1); + } + return $drops; +} + + public function onCollideWithEntity(Entity $entity) : void{ + parent::onCollideWithEntity($entity); + + if($entity instanceof Player){ + if($this->getTargetEntity() === $entity){ + $entity->addEffect(new EffectInstance(Effect::getEffect(Effect::WITHER), 200, 1)); + } + } + } + + + + + public function getXpDropAmount() : int{ + //TODO: check for equipment + return 5; + } + + protected function addBehaviors() : void{ + $this->behaviorPool->setBehavior(0, new FloatBehavior($this)); + $this->behaviorPool->setBehavior(1, new MeleeAttackBehavior($this, 1.0)); + $this->behaviorPool->setBehavior(2, new WanderBehavior($this, 1.0)); + $this->behaviorPool->setBehavior(3, new LookAtPlayerBehavior($this, 8.0)); + $this->behaviorPool->setBehavior(4, new RandomLookAroundBehavior($this)); + + $this->targetBehaviorPool->setBehavior(1, new FindAttackableTargetBehavior($this, Player::class)); + } + + + public function sendSpawnPacket(Player $player) : void{ + parent::sendSpawnPacket($player); + + $this->equipment->sendContents([$player]); + } +} \ No newline at end of file diff --git a/src/pocketmine/entity/passive/Cod.php b/src/pocketmine/entity/passive/Cod.php index 6db4ea624f0..c8405f45e8d 100644 --- a/src/pocketmine/entity/passive/Cod.php +++ b/src/pocketmine/entity/passive/Cod.php @@ -70,7 +70,7 @@ public function attack(EntityDamageEvent $source) : void{ $this->swimDirection = (new Vector3($this->x - $e->x, $this->y - $e->y, $this->z - $e->z))->normalize(); } - $this->broadcastEntityEvent(ActorEventPacket::SQUID_INK_CLOUD); + } } @@ -120,10 +120,13 @@ public function entityBaseTick(int $tickDiff = 1) : bool{ } public function getDrops() : array{ - return [ + $drops = [ ItemFactory::get(Item::RAW_FISH, 0, 1), - //TODO: Add percentage drop for bone ]; + if(mt_rand(1, 4) ===1){ + $drops[] = ItemFactory::get(Item::BONE, 1, mt_rand(1, 2)); + } + return $drops; } protected function applyGravity() : void{ diff --git a/src/pocketmine/entity/passive/Dolphin.php b/src/pocketmine/entity/passive/Dolphin.php new file mode 100644 index 00000000000..d84cd9a894f --- /dev/null +++ b/src/pocketmine/entity/passive/Dolphin.php @@ -0,0 +1,139 @@ +setMaxHealth(10); + + parent::initEntity(); + } + + public function getName() : string{ + return "Salmon"; + } + + public function attack(EntityDamageEvent $source) : void{ + parent::attack($source); + if($source->isCancelled()){ + return; + } + + if($source instanceof EntityDamageByEntityEvent){ + $this->swimSpeed = mt_rand(150, 350) / 2000; + $e = $source->getDamager(); + if($e !== null){ + $this->swimDirection = (new Vector3($this->x - $e->x, $this->y - $e->y, $this->z - $e->z))->normalize(); + } + + } + } + + private function generateRandomDirection() : Vector3{ + return new Vector3(mt_rand(-1000, 1000) / 1000, mt_rand(-500, 500) / 1000, mt_rand(-1000, 1000) / 1000); + } + + + public function entityBaseTick(int $tickDiff = 1) : bool{ + if($this->closed){ + return false; + } + + if(++$this->switchDirectionTicker === 100 or $this->isCollided){ + $this->switchDirectionTicker = 0; + if(mt_rand(0, 100) < 50){ + $this->swimDirection = null; + } + } + + $hasUpdate = parent::entityBaseTick($tickDiff); + + if($this->isAlive()){ + + if($this->y > 62 and $this->swimDirection !== null){ + $this->swimDirection->y = -0.5; + } + + $inWater = $this->isUnderwater(); + if(!$inWater){ + $this->swimDirection = null; + }elseif($this->swimDirection !== null){ + if($this->motion->lengthSquared() <= $this->swimDirection->lengthSquared()){ + $this->motion = $this->swimDirection->multiply($this->swimSpeed); + } + }else{ + $this->swimDirection = $this->generateRandomDirection(); + $this->swimSpeed = mt_rand(50, 100) / 2000; + } + + $f = sqrt(($this->motion->x ** 2) + ($this->motion->z ** 2)); + $this->yaw = (-atan2($this->motion->x, $this->motion->z) * 180 / M_PI); + $this->pitch = (-atan2($f, $this->motion->y) * 1 / M_PI); + } + + return $hasUpdate; + } + + public function getDrops() : array{ + return [ + ItemFactory::get(Item::RAW_SALMON, 0, 1), + //TODO: Add percentage drop for bone + ]; + } + + protected function applyGravity() : void{ + if(!$this->isUnderwater()){ + parent::applyGravity(); + } + } + + +} \ No newline at end of file diff --git a/src/pocketmine/entity/passive/PolarBear.php b/src/pocketmine/entity/passive/PolarBear.php index d8e684c1a67..7446a46030f 100644 --- a/src/pocketmine/entity/passive/PolarBear.php +++ b/src/pocketmine/entity/passive/PolarBear.php @@ -98,8 +98,13 @@ public function getXpDropAmount() : int{ public function getDrops(): array { - return [ - ItemFactory::get(Item::RAW_SALMON, 0, mt_rand(0, 2)) - ]; + $drops = []; + if(mt_rand(1, 4) >1){ + $drops[] = ItemFactory::get(Item::RAW_FISH, 1, mt_rand(0, 2)); + return $drops; + } + else{ + $drops[] = ItemFactory::get(Item::RAW_SALMON, 1, mt_rand(0, 2)); + return $drops;} } } \ No newline at end of file diff --git a/src/pocketmine/entity/passive/Pufferfish.php b/src/pocketmine/entity/passive/Pufferfish.php new file mode 100644 index 00000000000..6cc6859f5f4 --- /dev/null +++ b/src/pocketmine/entity/passive/Pufferfish.php @@ -0,0 +1,152 @@ +setMaxHealth(3); + + parent::initEntity(); + } + + public function getName() : string{ + return "Pufferfish"; + } + + public function attack(EntityDamageEvent $source) : void{ + parent::attack($source); + if($source->isCancelled()){ + return; + } + + if($source instanceof EntityDamageByEntityEvent){ + $this->swimSpeed = mt_rand(150, 350) / 2000; + $e = $source->getDamager(); + if($e !== null){ + $this->swimDirection = (new Vector3($this->x - $e->x, $this->y - $e->y, $this->z - $e->z))->normalize(); + } + + } + } + + private function generateRandomDirection() : Vector3{ + return new Vector3(mt_rand(-1000, 1000) / 1000, mt_rand(-500, 500) / 1000, mt_rand(-1000, 1000) / 1000); + } + + + public function entityBaseTick(int $tickDiff = 1) : bool{ + if($this->closed){ + return false; + } + + if(++$this->switchDirectionTicker === 100 or $this->isCollided){ + $this->switchDirectionTicker = 0; + if(mt_rand(0, 100) < 50){ + $this->swimDirection = null; + } + } + + $hasUpdate = parent::entityBaseTick($tickDiff); + + if($this->isAlive()){ + + if($this->y > 62 and $this->swimDirection !== null){ + $this->swimDirection->y = -0.5; + } + + $inWater = $this->isUnderwater(); + if(!$inWater){ + $this->swimDirection = null; + }elseif($this->swimDirection !== null){ + if($this->motion->lengthSquared() <= $this->swimDirection->lengthSquared()){ + $this->motion = $this->swimDirection->multiply($this->swimSpeed); + } + }else{ + $this->swimDirection = $this->generateRandomDirection(); + $this->swimSpeed = mt_rand(50, 100) / 2000; + } + + $f = sqrt(($this->motion->x ** 2) + ($this->motion->z ** 2)); + $this->yaw = (-atan2($this->motion->x, $this->motion->z) * 180 / M_PI); + $this->pitch = (-atan2($f, $this->motion->y) * 180 / M_PI); + } + + return $hasUpdate; + } + + public function onCollideWithEntity(Entity $entity) : void{ + parent::onCollideWithEntity($entity); + + if($entity instanceof Player){ + if($this->getTargetEntity() === $entity){ + $entity->addEffect(new EffectInstance(Effect::getEffect(Effect::POISON), 7 * 20, 1)); + } + } + } + + + + + public function getDrops() : array{ + $drops = [ + ItemFactory::get(Item::PUFFERFISH, 0, 1), + ]; + if(mt_rand(1, 4) ===1){ + $drops[] = ItemFactory::get(Item::BONE, 1, mt_rand(1, 2)); + } + return $drops; + } + + protected function applyGravity() : void{ + if(!$this->isUnderwater()){ + parent::applyGravity(); + } + } +} \ No newline at end of file diff --git a/src/pocketmine/entity/passive/Salmon.php b/src/pocketmine/entity/passive/Salmon.php new file mode 100644 index 00000000000..ebc41ceb2f9 --- /dev/null +++ b/src/pocketmine/entity/passive/Salmon.php @@ -0,0 +1,137 @@ +setMaxHealth(3); + + parent::initEntity(); + } + + public function getName() : string{ + return "Salmon"; + } + + public function attack(EntityDamageEvent $source) : void{ + parent::attack($source); + if($source->isCancelled()){ + return; + } + + if($source instanceof EntityDamageByEntityEvent){ + $this->swimSpeed = mt_rand(150, 350) / 2000; + $e = $source->getDamager(); + if($e !== null){ + $this->swimDirection = (new Vector3($this->x - $e->x, $this->y - $e->y, $this->z - $e->z))->normalize(); + } + + + } + } + + private function generateRandomDirection() : Vector3{ + return new Vector3(mt_rand(-1000, 1000) / 1000, mt_rand(-500, 500) / 1000, mt_rand(-1000, 1000) / 1000); + } + + + public function entityBaseTick(int $tickDiff = 1) : bool{ + if($this->closed){ + return false; + } + + if(++$this->switchDirectionTicker === 100 or $this->isCollided){ + $this->switchDirectionTicker = 0; + if(mt_rand(0, 100) < 50){ + $this->swimDirection = null; + } + } + + $hasUpdate = parent::entityBaseTick($tickDiff); + + if($this->isAlive()){ + + if($this->y > 62 and $this->swimDirection !== null){ + $this->swimDirection->y = -0.5; + } + + $inWater = $this->isUnderwater(); + if(!$inWater){ + $this->swimDirection = null; + }elseif($this->swimDirection !== null){ + if($this->motion->lengthSquared() <= $this->swimDirection->lengthSquared()){ + $this->motion = $this->swimDirection->multiply($this->swimSpeed); + } + }else{ + $this->swimDirection = $this->generateRandomDirection(); + $this->swimSpeed = mt_rand(50, 100) / 2000; + } + + $f = sqrt(($this->motion->x ** 2) + ($this->motion->z ** 2)); + $this->yaw = (-atan2($this->motion->x, $this->motion->z) * 180 / M_PI); + $this->pitch = (-atan2($f, $this->motion->y) * 180 / M_PI); + } + + return $hasUpdate; + } + + public function getDrops() : array{ + $drops = [ + ItemFactory::get(Item::RAW_SALMON, 0, 1), + ]; + if(mt_rand(1, 4) ===1){ + $drops[] = ItemFactory::get(Item::BONE, 1, mt_rand(1, 2)); + } + return $drops; + } + + protected function applyGravity() : void{ + if(!$this->isUnderwater()){ + parent::applyGravity(); + } + } +} \ No newline at end of file diff --git a/src/pocketmine/entity/passive/TropicalFish.php b/src/pocketmine/entity/passive/TropicalFish.php index f82081aefce..d1ebd0e8568 100644 --- a/src/pocketmine/entity/passive/TropicalFish.php +++ b/src/pocketmine/entity/passive/TropicalFish.php @@ -70,7 +70,7 @@ public function attack(EntityDamageEvent $source) : void{ $this->swimDirection = (new Vector3($this->x - $e->x, $this->y - $e->y, $this->z - $e->z))->normalize(); } - $this->broadcastEntityEvent(ActorEventPacket::SQUID_INK_CLOUD); + } } @@ -120,10 +120,13 @@ public function entityBaseTick(int $tickDiff = 1) : bool{ } public function getDrops() : array{ - return [ + $drops = [ ItemFactory::get(Item::CLOWNFISH, 0, 1), - //TODO: Add percentage drop for bone ]; + if(mt_rand(1, 4) ===1){ + $drops[] = ItemFactory::get(Item::BONE, 1, mt_rand(1, 2)); + } + return $drops; } protected function applyGravity() : void{ From c0006eef645898036e7cda71d4af303584f56f6b Mon Sep 17 00:00:00 2001 From: dearminder Date: Wed, 31 Jul 2019 11:17:21 +0200 Subject: [PATCH 04/22] Tempt Fix --- src/pocketmine/entity/passive/Ocelot.php | 4 ++-- src/pocketmine/entity/passive/Rabbit.php | 4 ++-- src/pocketmine/entity/passive/Wolf.php | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/pocketmine/entity/passive/Ocelot.php b/src/pocketmine/entity/passive/Ocelot.php index b37ac557787..eab4af7ca54 100644 --- a/src/pocketmine/entity/passive/Ocelot.php +++ b/src/pocketmine/entity/passive/Ocelot.php @@ -30,7 +30,7 @@ use pocketmine\entity\behavior\PanicBehavior; use pocketmine\entity\behavior\RandomLookAroundBehavior; use pocketmine\entity\behavior\SittingBehavior; -use pocketmine\entity\behavior\TemptedBehavior; +use pocketmine\entity\behavior\TemptBehavior; use pocketmine\entity\Tamable; use pocketmine\event\entity\EntityDamageByEntityEvent; use pocketmine\event\entity\EntityDamageEvent; @@ -54,7 +54,7 @@ protected function addBehaviors() : void{ $this->behaviorPool->setBehavior(3, new PanicBehavior($this, 2.0)); $this->behaviorPool->setBehavior(4, new LookAtPlayerBehavior($this, 14.0)); $this->behaviorPool->setBehavior(5, new RandomLookAroundBehavior($this)); - $this->behaviorPool->setBehavior(6, new TemptedBehavior($this, [Item::RAW_SALMON, Item::RAW_FISH], 1.0)); + $this->behaviorPool->setBehavior(6, new TemptBehavior($this, [Item::RAW_SALMON, Item::RAW_FISH], 1.0)); $this->behaviorPool->setBehavior(7, new SittingBehavior($this)); // TODO: attack turtle and rabbit } diff --git a/src/pocketmine/entity/passive/Rabbit.php b/src/pocketmine/entity/passive/Rabbit.php index f1e20d5a5a1..c940025a270 100644 --- a/src/pocketmine/entity/passive/Rabbit.php +++ b/src/pocketmine/entity/passive/Rabbit.php @@ -28,7 +28,7 @@ use pocketmine\entity\behavior\MateBehavior; use pocketmine\entity\behavior\PanicBehavior; use pocketmine\entity\behavior\RandomLookAroundBehavior; -use pocketmine\entity\behavior\TemptedBehavior; +use pocketmine\entity\behavior\TemptBehavior; use pocketmine\entity\Tamable; use pocketmine\item\Item; use pocketmine\item\ItemFactory; @@ -47,7 +47,7 @@ protected function addBehaviors() : void $this->behaviorPool->setBehavior(3, new PanicBehavior($this, 2.0)); $this->behaviorPool->setBehavior(4, new LookAtPlayerBehavior($this, 14.0)); $this->behaviorPool->setBehavior(5, new RandomLookAroundBehavior($this)); - $this->behaviorPool->setBehavior(6, new TemptedBehavior($this, [Item::CARROT], 1.0)); + $this->behaviorPool->setBehavior(6, new TemptBehavior($this, [Item::CARROT], 1.0)); // TODO: running away from player } diff --git a/src/pocketmine/entity/passive/Wolf.php b/src/pocketmine/entity/passive/Wolf.php index 5b13f9b2d28..b0c9e0a8fbe 100644 --- a/src/pocketmine/entity/passive/Wolf.php +++ b/src/pocketmine/entity/passive/Wolf.php @@ -61,7 +61,7 @@ protected function addBehaviors() : void{ $this->behaviorPool->setBehavior(5, new RandomStrollBehavior($this, 1.0)); $this->behaviorPool->setBehavior(6, new LookAtPlayerBehavior($this, 8.0)); $this->behaviorPool->setBehavior(7, new RandomLookAroundBehavior($this)); - $this->behaviorPool->setBehavior(4, new TemptedBehavior($this, [Item::BONE], 0.8)); + $this->behaviorPool->setBehavior(4, new TemptBehavior($this, [Item::BONE], 0.8)); $this->targetBehaviorPool->setBehavior(0, new HurtByTargetBehavior($this, true)); $this->targetBehaviorPool->setBehavior(1, new OwnerHurtByTargetBehavior($this)); From 160e771128424a5162ec9cd7b14a1a81e45d0410 Mon Sep 17 00:00:00 2001 From: dearminder Date: Fri, 2 Aug 2019 12:10:40 +0200 Subject: [PATCH 05/22] . --- src/pocketmine/entity/Entity.php | 2 +- src/pocketmine/entity/hostile/Blaze.php | 2 +- src/pocketmine/entity/{passive => hostile}/Dolphin.php | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) rename src/pocketmine/entity/{passive => hostile}/Dolphin.php (97%) diff --git a/src/pocketmine/entity/Entity.php b/src/pocketmine/entity/Entity.php index 83793c1a670..07331102287 100644 --- a/src/pocketmine/entity/Entity.php +++ b/src/pocketmine/entity/Entity.php @@ -45,6 +45,7 @@ use pocketmine\entity\hostile\Zombie; use pocketmine\entity\hostile\ZombiePigman; use pocketmine\entity\hostile\ZombieVillager; +use pocketmine\entity\hostile\Dolphin; use pocketmine\entity\object\ArmorStand; use pocketmine\entity\object\ExperienceOrb; use pocketmine\entity\object\FallingBlock; @@ -57,7 +58,6 @@ use pocketmine\entity\passive\Cat; use pocketmine\entity\passive\Chicken; use pocketmine\entity\passive\Cod; -use pocketmine\entity\passive\Dolphin; use pocketmine\entity\passive\Pufferfish; use pocketmine\entity\passive\Salmon; use pocketmine\entity\passive\Cow; diff --git a/src/pocketmine/entity/hostile/Blaze.php b/src/pocketmine/entity/hostile/Blaze.php index 06260c92d58..e45f87e0fd9 100644 --- a/src/pocketmine/entity/hostile/Blaze.php +++ b/src/pocketmine/entity/hostile/Blaze.php @@ -95,7 +95,7 @@ public function onBehaviorUpdate() : void{ public function onRangedAttackToTarget(Entity $target, float $power) : void{ $dv = $target->subtract($this)->normalize(); $fireball = new SmallFireball($this->level, Entity::createBaseNBT($this->add($this->random->nextFloat() * $power, $this->getEyeHeight(), $this->random->nextFloat() * $power), $dv), $this); - $fireball->setMotion($dv->multiply(2)); + $fireball->setMotion($dv->multiply($power)); $fireball->spawnToAll(); } diff --git a/src/pocketmine/entity/passive/Dolphin.php b/src/pocketmine/entity/hostile/Dolphin.php similarity index 97% rename from src/pocketmine/entity/passive/Dolphin.php rename to src/pocketmine/entity/hostile/Dolphin.php index d84cd9a894f..134398f5fd4 100644 --- a/src/pocketmine/entity/passive/Dolphin.php +++ b/src/pocketmine/entity/hostile/Dolphin.php @@ -21,7 +21,7 @@ declare(strict_types=1); -namespace pocketmine\entity\passive; +namespace pocketmine\entity\hostile; use pocketmine\entity\behavior\JumpAttackBehavior; use pocketmine\entity\behavior\MeleeAttackBehavior; @@ -58,7 +58,7 @@ public function initEntity() : void{ } public function getName() : string{ - return "Salmon"; + return "Dolphin"; } public function attack(EntityDamageEvent $source) : void{ @@ -68,7 +68,7 @@ public function attack(EntityDamageEvent $source) : void{ } if($source instanceof EntityDamageByEntityEvent){ - $this->swimSpeed = mt_rand(150, 350) / 2000; + $this->swimSpeed = mt_rand(350, 650) / 2000; $e = $source->getDamager(); if($e !== null){ $this->swimDirection = (new Vector3($this->x - $e->x, $this->y - $e->y, $this->z - $e->z))->normalize(); From 91915acf40493a6b1b662318315ad69faad9a252 Mon Sep 17 00:00:00 2001 From: dearminder Date: Fri, 2 Aug 2019 12:27:35 +0200 Subject: [PATCH 06/22] Updated To latest Behaviours --- .../entity/hostile/WitherSkeleton.php | 4 +- .../entity/hostile/ZombiePigman.php | 4 +- .../entity/hostile/ZombieVillager.php | 4 +- src/pocketmine/entity/passive/Cat.php | 2 +- src/pocketmine/entity/passive/Ocelot.php | 32 ++- src/pocketmine/entity/passive/PolarBear.php | 4 +- .../entity/passive/SkeletonHorse.php | 254 +++++++++--------- src/pocketmine/entity/passive/ZombieHorse.php | 4 +- 8 files changed, 159 insertions(+), 149 deletions(-) diff --git a/src/pocketmine/entity/hostile/WitherSkeleton.php b/src/pocketmine/entity/hostile/WitherSkeleton.php index 43432f11b6d..1f4b69f27f6 100644 --- a/src/pocketmine/entity/hostile/WitherSkeleton.php +++ b/src/pocketmine/entity/hostile/WitherSkeleton.php @@ -29,7 +29,7 @@ use pocketmine\entity\behavior\LookAtPlayerBehavior; use pocketmine\entity\behavior\MeleeAttackBehavior; use pocketmine\entity\behavior\RandomLookAroundBehavior; -use pocketmine\entity\behavior\WanderBehavior; +use pocketmine\entity\behavior\RandomStrollBehavior; use pocketmine\entity\Effect; use pocketmine\entity\EffectInstance; use pocketmine\entity\Entity; @@ -100,7 +100,7 @@ public function getXpDropAmount() : int{ protected function addBehaviors() : void{ $this->behaviorPool->setBehavior(0, new FloatBehavior($this)); $this->behaviorPool->setBehavior(1, new MeleeAttackBehavior($this, 1.0)); - $this->behaviorPool->setBehavior(2, new WanderBehavior($this, 1.0)); + $this->behaviorPool->setBehavior(2, new RandomStrollBehavior($this, 1.0)); $this->behaviorPool->setBehavior(3, new LookAtPlayerBehavior($this, 8.0)); $this->behaviorPool->setBehavior(4, new RandomLookAroundBehavior($this)); diff --git a/src/pocketmine/entity/hostile/ZombiePigman.php b/src/pocketmine/entity/hostile/ZombiePigman.php index 24698975e0a..199bc079747 100644 --- a/src/pocketmine/entity/hostile/ZombiePigman.php +++ b/src/pocketmine/entity/hostile/ZombiePigman.php @@ -30,7 +30,7 @@ use pocketmine\entity\behavior\LookAtPlayerBehavior; use pocketmine\entity\behavior\MeleeAttackBehavior; use pocketmine\entity\behavior\RandomLookAroundBehavior; -use pocketmine\entity\behavior\WanderBehavior; +use pocketmine\entity\behavior\RandomStrollBehavior; use pocketmine\entity\Monster; use pocketmine\entity\passive\Villager; use pocketmine\inventory\AltayEntityEquipment; @@ -94,7 +94,7 @@ public function getXpDropAmount() : int{ protected function addBehaviors() : void{ $this->behaviorPool->setBehavior(0, new FloatBehavior($this)); $this->behaviorPool->setBehavior(1, new MeleeAttackBehavior($this, 1.0)); - $this->behaviorPool->setBehavior(2, new WanderBehavior($this, 1.0)); + $this->behaviorPool->setBehavior(2, new RandomStrollBehavior($this, 1.0)); $this->behaviorPool->setBehavior(3, new LookAtPlayerBehavior($this, 8.0)); $this->behaviorPool->setBehavior(4, new RandomLookAroundBehavior($this)); diff --git a/src/pocketmine/entity/hostile/ZombieVillager.php b/src/pocketmine/entity/hostile/ZombieVillager.php index 7f274bbe69d..0aa9100bf89 100644 --- a/src/pocketmine/entity/hostile/ZombieVillager.php +++ b/src/pocketmine/entity/hostile/ZombieVillager.php @@ -30,7 +30,7 @@ use pocketmine\entity\behavior\LookAtPlayerBehavior; use pocketmine\entity\behavior\MeleeAttackBehavior; use pocketmine\entity\behavior\RandomLookAroundBehavior; -use pocketmine\entity\behavior\WanderBehavior; +use pocketmine\entity\behavior\RandomStrollBehavior; use pocketmine\entity\Monster; use pocketmine\entity\passive\Villager; use pocketmine\item\Item; @@ -86,7 +86,7 @@ public function getXpDropAmount() : int{ protected function addBehaviors() : void{ $this->behaviorPool->setBehavior(0, new FloatBehavior($this)); $this->behaviorPool->setBehavior(1, new MeleeAttackBehavior($this, 1.0)); - $this->behaviorPool->setBehavior(2, new WanderBehavior($this, 1.0)); + $this->behaviorPool->setBehavior(2, new RandomStrollBehavior($this, 1.0)); $this->behaviorPool->setBehavior(3, new LookAtPlayerBehavior($this, 8.0)); $this->behaviorPool->setBehavior(4, new RandomLookAroundBehavior($this)); diff --git a/src/pocketmine/entity/passive/Cat.php b/src/pocketmine/entity/passive/Cat.php index 29b353fef65..045e8d57ddb 100644 --- a/src/pocketmine/entity/passive/Cat.php +++ b/src/pocketmine/entity/passive/Cat.php @@ -71,7 +71,7 @@ protected function initEntity() : void{ $this->setMovementSpeed(0.3); $this->setFollowRange(16); $this->setAttackDamage(3); - $this->propertyManager->setInt(self::DATA_VARIANT, intval($this->namedtag->getInt("CatType", mt_rand(0, 10)))); + $this->propertyManager->setInt(self::DATA_VARIANT, intval($this->namedtag->getInt("CatType", mt_rand(1, 10)))); $this->propertyManager->setInt(self::DATA_COLOR, intval($this->namedtag->getInt("CollarColor", mt_rand(0, 15)))); parent::initEntity(); diff --git a/src/pocketmine/entity/passive/Ocelot.php b/src/pocketmine/entity/passive/Ocelot.php index eab4af7ca54..9b1fc751728 100644 --- a/src/pocketmine/entity/passive/Ocelot.php +++ b/src/pocketmine/entity/passive/Ocelot.php @@ -29,7 +29,7 @@ use pocketmine\entity\behavior\MateBehavior; use pocketmine\entity\behavior\PanicBehavior; use pocketmine\entity\behavior\RandomLookAroundBehavior; -use pocketmine\entity\behavior\SittingBehavior; +use pocketmine\entity\behavior\StayWhileSittingBehavior; use pocketmine\entity\behavior\TemptBehavior; use pocketmine\entity\Tamable; use pocketmine\event\entity\EntityDamageByEntityEvent; @@ -46,16 +46,23 @@ class Ocelot extends Tamable{ public $width = 0.6; public $height = 0.7; + /** @var StayWhileSittingBehavior */ + protected $behaviorSitting; protected function addBehaviors() : void{ $this->behaviorPool->setBehavior(0, new FloatBehavior($this)); - $this->behaviorPool->setBehavior(1, new MateBehavior($this, 2.0)); - $this->behaviorPool->setBehavior(2, new FollowOwnerBehavior($this, 1.0)); - $this->behaviorPool->setBehavior(3, new PanicBehavior($this, 2.0)); - $this->behaviorPool->setBehavior(4, new LookAtPlayerBehavior($this, 14.0)); - $this->behaviorPool->setBehavior(5, new RandomLookAroundBehavior($this)); - $this->behaviorPool->setBehavior(6, new TemptBehavior($this, [Item::RAW_SALMON, Item::RAW_FISH], 1.0)); - $this->behaviorPool->setBehavior(7, new SittingBehavior($this)); + $this->behaviorPool->setBehavior(1, new PanicBehavior($this, 2.0)); + $this->behaviorPool->setBehavior(2, $this->behaviorSitting = new StayWhileSittingBehavior($this)); + $this->behaviorPool->setBehavior(3, new MateBehavior($this, 2.0)); + $this->behaviorPool->setBehavior(4, new TemptBehavior($this, [ + Item::RAW_SALMON, + Item::RAW_FISH + ], 1.0)); + $this->behaviorPool->setBehavior(5, new FollowOwnerBehavior($this, 1.0)); + $this->behaviorPool->setBehavior(6, new LookAtPlayerBehavior($this, 14.0)); + $this->behaviorPool->setBehavior(7, new RandomLookAroundBehavior($this)); + + // TODO: attack turtle and rabbit } @@ -66,6 +73,7 @@ protected function initEntity() : void{ $this->setAttackDamage(3); $this->propertyManager->setInt(self::DATA_VARIANT, intval($this->namedtag->getInt("CatType", 0))); $this->propertyManager->setInt(self::DATA_COLOR, intval($this->namedtag->getInt("CollarColor", mt_rand(0, 15)))); + parent::initEntity(); } @@ -85,7 +93,7 @@ public function onInteract(Player $player, Item $item, Vector3 $clickPos) : bool }elseif(mt_rand(0, 2) == 0){ $this->setOwningEntity($player); $this->setTamed(); - $this->setSitting(); + $this->setSittingFromBehavior(true); $this->broadcastEntityEvent(ActorEventPacket::TAME_SUCCESS); }else{ $this->broadcastEntityEvent(ActorEventPacket::TAME_FAIL); @@ -93,7 +101,7 @@ public function onInteract(Player $player, Item $item, Vector3 $clickPos) : bool return true; }else{ if($this->isTamed()){ - $this->setSitting(!$this->isSitting()); + $this->setSittingFromBehavior(!$this->isSitting()); } } } @@ -117,6 +125,10 @@ public function getDrops() : array{ ]; } + public function setSittingFromBehavior(bool $value) : void{ + $this->behaviorSitting->setSitting($value); + } + public function attack(EntityDamageEvent $source) : void{ if($source->getCause() !== EntityDamageEvent::CAUSE_FALL){ parent::attack($source); diff --git a/src/pocketmine/entity/passive/PolarBear.php b/src/pocketmine/entity/passive/PolarBear.php index 7446a46030f..c2f95de0f92 100644 --- a/src/pocketmine/entity/passive/PolarBear.php +++ b/src/pocketmine/entity/passive/PolarBear.php @@ -31,7 +31,7 @@ use pocketmine\entity\behavior\MateBehavior; use pocketmine\entity\behavior\MeleeAttackBehavior; use pocketmine\entity\behavior\RandomLookAroundBehavior; -use pocketmine\entity\behavior\WanderBehavior; +use pocketmine\entity\behavior\RandomStrollBehavior; use pocketmine\entity\Entity; use pocketmine\item\Item; use pocketmine\item\ItemFactory; @@ -50,7 +50,7 @@ protected function addBehaviors(): void $this->behaviorPool->setBehavior(1, new MateBehavior($this, 1.0)); $this->behaviorPool->setBehavior(2, new MeleeAttackBehavior($this, 1.0)); $this->behaviorPool->setBehavior(3, new FollowParentBehavior($this, 1.1)); - $this->behaviorPool->setBehavior(4, new WanderBehavior($this, 1.0)); + $this->behaviorPool->setBehavior(4, new RandomStrollBehavior($this, 1.0)); $this->behaviorPool->setBehavior(5, new LookAtPlayerBehavior($this, 16.0)); $this->behaviorPool->setBehavior(6, new RandomLookAroundBehavior($this)); diff --git a/src/pocketmine/entity/passive/SkeletonHorse.php b/src/pocketmine/entity/passive/SkeletonHorse.php index d2897ad117d..c9555cadfdc 100644 --- a/src/pocketmine/entity/passive/SkeletonHorse.php +++ b/src/pocketmine/entity/passive/SkeletonHorse.php @@ -27,16 +27,15 @@ use pocketmine\entity\Attribute; use pocketmine\entity\behavior\FloatBehavior; use pocketmine\entity\behavior\FollowParentBehavior; -use pocketmine\entity\behavior\HorseRiddenBehavior; +use pocketmine\entity\behavior\MountPathingBehavior; use pocketmine\entity\behavior\LookAtPlayerBehavior; use pocketmine\entity\behavior\MateBehavior; use pocketmine\entity\behavior\PanicBehavior; use pocketmine\entity\behavior\RandomLookAroundBehavior; -use pocketmine\entity\behavior\WanderBehavior; +use pocketmine\entity\behavior\RandomStrollBehavior; use pocketmine\inventory\HorseInventory; use pocketmine\inventory\InventoryHolder; use pocketmine\item\Item; -use pocketmine\item\ItemFactory; use pocketmine\math\Vector3; use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\IntTag; @@ -44,132 +43,131 @@ class SkeletonHorse extends AbstractHorse implements InventoryHolder{ - public const NETWORK_ID = self::SKELETON_HORSE; - - public const HORSE_VARIANT_WHITE = 0; - public const HORSE_VARIANT_CREAMY = 1; - public const HORSE_VARIANT_CHESTNUT = 2; - public const HORSE_VARIANT_BROWN = 3; - public const HORSE_VARIANT_BLACK = 4; - public const HORSE_VARIANT_GRAY = 5; - public const HORSE_VARIANT_DARK_BROWN = 6; - - public const HORSE_MARK_VARIANT_NONE = 0; - public const HORSE_MARK_VARIANT_WHITE = 1; - public const HORSE_MARK_VARIANT_WHITE_FIELD = 2; - public const HORSE_MARK_VARIANT_WHITE_DOTS = 3; - public const HORSE_MARK_VARIANT_BLACK_DOTS = 4; - - public $width = 1.4; - public $height = 1.6; - - /** @var HorseInventory */ - protected $inventory; - - public function getName() : string{ - return "Skeleton Horse"; - } - - /** - * @return HorseInventory - */ - public function getInventory() : HorseInventory{ - return $this->inventory; - } - - protected function addBehaviors() : void{ - $this->behaviorPool->setBehavior(0, new HorseRiddenBehavior($this)); - $this->behaviorPool->setBehavior(1, new FloatBehavior($this)); - $this->behaviorPool->setBehavior(2, new PanicBehavior($this, 1.25)); - $this->behaviorPool->setBehavior(3, new MateBehavior($this, 1.0)); - $this->behaviorPool->setBehavior(5, new FollowParentBehavior($this, 1.1)); - $this->behaviorPool->setBehavior(6, new WanderBehavior($this, 1.0)); - $this->behaviorPool->setBehavior(7, new LookAtPlayerBehavior($this, 6.0)); - $this->behaviorPool->setBehavior(8, new RandomLookAroundBehavior($this)); - } - - protected function initEntity() : void{ + public const NETWORK_ID = self::SKELETON_HORSE; + + public const HORSE_VARIANT_WHITE = 0; + public const HORSE_VARIANT_CREAMY = 1; + public const HORSE_VARIANT_CHESTNUT = 2; + public const HORSE_VARIANT_BROWN = 3; + public const HORSE_VARIANT_BLACK = 4; + public const HORSE_VARIANT_GRAY = 5; + public const HORSE_VARIANT_DARK_BROWN = 6; + + public const HORSE_MARK_VARIANT_NONE = 0; + public const HORSE_MARK_VARIANT_WHITE = 1; + public const HORSE_MARK_VARIANT_WHITE_FIELD = 2; + public const HORSE_MARK_VARIANT_WHITE_DOTS = 3; + public const HORSE_MARK_VARIANT_BLACK_DOTS = 4; + + public $width = 1.4; + public $height = 1.6; + + /** @var HorseInventory */ + protected $inventory; + + public function getName() : string{ + return "Skeleton Horse"; + } + + /** + * @return HorseInventory + */ + public function getInventory() : HorseInventory{ + return $this->inventory; + } + + protected function addBehaviors() : void{ + $this->behaviorPool->setBehavior(0, new MountPathingBehavior($this)); + $this->behaviorPool->setBehavior(1, new FloatBehavior($this)); + $this->behaviorPool->setBehavior(2, new PanicBehavior($this, 1.25)); + $this->behaviorPool->setBehavior(3, new MateBehavior($this, 1.0)); + $this->behaviorPool->setBehavior(5, new FollowParentBehavior($this, 1.1)); + $this->behaviorPool->setBehavior(6, new RandomStrollBehavior($this, 1.0)); + $this->behaviorPool->setBehavior(7, new LookAtPlayerBehavior($this, 6.0)); + $this->behaviorPool->setBehavior(8, new RandomLookAroundBehavior($this)); + } + + protected function initEntity() : void{ $this->setMaxHealth(15); - $this->setMovementSpeed($this->getModifiedMovementSpeed()); - $this->setJumpStrength($this->getModifiedJumpStrength()); - $this->setFollowRange(35); - - if($this->namedtag->hasTag("Variant", IntTag::class) and $this->namedtag->hasTag("MarkVariant", IntTag::class)){ - $this->setVariant($this->namedtag->getInt("Variant")); - $this->setMarkVariant($this->namedtag->getInt("MarkVariant")); - }else{ - $this->setVariant($this->random->nextBoundedInt(7)); - $this->setMarkVariant($this->random->nextBoundedInt(5)); - } - - $this->inventory = new HorseInventory($this); - - if($this->namedtag->hasTag("ArmorItem", CompoundTag::class)){ - $this->inventory->setArmor(Item::nbtDeserialize($this->namedtag->getCompoundTag("ArmorItem"))); - } - - if($this->namedtag->hasTag("SaddleItem", CompoundTag::class)){ - $this->inventory->setSaddle(Item::nbtDeserialize($this->namedtag->getCompoundTag("SaddleItem"))); - } - - parent::initEntity(); - } - - public function addAttributes() : void{ - parent::addAttributes(); - - $this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::HORSE_JUMP_STRENGTH)); - } - - public function getRiderSeatPosition(int $seatNumber = 0) : Vector3{ - return new Vector3(0, 1.1, -0.2); - } - - public function setSaddled(bool $value = true) : void{ - parent::setSaddled($value); - - $this->setGenericFlag(self::DATA_FLAG_CAN_POWER_JUMP, $value); - } - - public function onInteract(Player $player, Item $item, Vector3 $clickPos) : bool{ - if(!$this->isImmobile()){ - // TODO: feeding - - if($player->isSneaking()){ - if($this->isTamed()){ - $player->addWindow($this->inventory); - }else{ - $this->rearUp(); - } - - return true; - } - } - return parent::onInteract($player, $item, $clickPos); - } - - public function sendSpawnPacket(Player $player) : void{ - parent::sendSpawnPacket($player); - - $this->inventory->sendArmor($player); - } - - public function doHitAnimation() : void{ - parent::doHitAnimation(); - - foreach($this->getViewers() as $player){ // WTF - $this->inventory->sendArmor($player); - } - } - - public function saveNBT() : void{ - parent::saveNBT(); - - if($this->inventory !== null){ - $this->namedtag->setTag($this->inventory->getSaddle()->nbtSerialize(-1, "SaddleItem")); - $this->namedtag->setTag($this->inventory->getArmor()->nbtSerialize(-1, "ArmorItem")); - } - } + $this->setMovementSpeed($this->getModifiedMovementSpeed()); + $this->setJumpStrength($this->getModifiedJumpStrength()); + $this->setFollowRange(35); + + if($this->namedtag->hasTag("Variant", IntTag::class) and $this->namedtag->hasTag("MarkVariant", IntTag::class)){ + $this->setVariant($this->namedtag->getInt("Variant")); + $this->setMarkVariant($this->namedtag->getInt("MarkVariant")); + }else{ + $this->setVariant($this->random->nextBoundedInt(7)); + $this->setMarkVariant($this->random->nextBoundedInt(5)); + } + $this->inventory = new HorseInventory($this); + + if($this->namedtag->hasTag("ArmorItem", CompoundTag::class)){ + $this->inventory->setArmor(Item::nbtDeserialize($this->namedtag->getCompoundTag("ArmorItem"))); + } + + if($this->namedtag->hasTag("SaddleItem", CompoundTag::class)){ + $this->inventory->setSaddle(Item::nbtDeserialize($this->namedtag->getCompoundTag("SaddleItem"))); + } + + parent::initEntity(); + } + + public function addAttributes() : void{ + parent::addAttributes(); + + $this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::HORSE_JUMP_STRENGTH)); + } + + public function getRiderSeatPosition(int $seatNumber = 0) : Vector3{ + return new Vector3(0, 1.1, -0.2); + } + + public function setSaddled(bool $value = true) : void{ + parent::setSaddled($value); + + $this->setGenericFlag(self::DATA_FLAG_CAN_POWER_JUMP, $value); + } + + public function onInteract(Player $player, Item $item, Vector3 $clickPos) : bool{ + if(!$this->isImmobile()){ + // TODO: feeding + + if($player->isSneaking()){ + if($this->isTamed()){ + $player->addWindow($this->inventory); + }else{ + $this->rearUp(); + } + + return true; + } + } + return parent::onInteract($player, $item, $clickPos); + } + + public function sendSpawnPacket(Player $player) : void{ + parent::sendSpawnPacket($player); + + $this->inventory->sendArmor($player); + } + + public function doHitAnimation() : void{ + parent::doHitAnimation(); + + foreach($this->getViewers() as $player){ // WTF + $this->inventory->sendArmor($player); + } + } + + public function saveNBT() : void{ + parent::saveNBT(); + + if($this->inventory !== null){ + $this->namedtag->setTag($this->inventory->getSaddle()->nbtSerialize(-1, "SaddleItem")); + $this->namedtag->setTag($this->inventory->getArmor()->nbtSerialize(-1, "ArmorItem")); + } + } public function getDrops(): array { diff --git a/src/pocketmine/entity/passive/ZombieHorse.php b/src/pocketmine/entity/passive/ZombieHorse.php index 361897bd494..8f56ca81c76 100644 --- a/src/pocketmine/entity/passive/ZombieHorse.php +++ b/src/pocketmine/entity/passive/ZombieHorse.php @@ -31,7 +31,7 @@ use pocketmine\entity\behavior\MateBehavior; use pocketmine\entity\behavior\PanicBehavior; use pocketmine\entity\behavior\RandomLookAroundBehavior; -use pocketmine\entity\behavior\WanderBehavior; +use pocketmine\entity\behavior\RandomStrollBehavior; use pocketmine\inventory\HorseInventory; use pocketmine\inventory\InventoryHolder; use pocketmine\item\Item; @@ -81,7 +81,7 @@ protected function addBehaviors() : void{ $this->behaviorPool->setBehavior(2, new PanicBehavior($this, 1.25)); $this->behaviorPool->setBehavior(3, new MateBehavior($this, 1.0)); $this->behaviorPool->setBehavior(5, new FollowParentBehavior($this, 1.1)); - $this->behaviorPool->setBehavior(6, new WanderBehavior($this, 1.0)); + $this->behaviorPool->setBehavior(6, new RandomStrollBehavior($this, 1.0)); $this->behaviorPool->setBehavior(7, new LookAtPlayerBehavior($this, 6.0)); $this->behaviorPool->setBehavior(8, new RandomLookAroundBehavior($this)); } From 69abb598898faed9d0c57c2f95edd609f8977815 Mon Sep 17 00:00:00 2001 From: dearminder Date: Fri, 2 Aug 2019 12:32:24 +0200 Subject: [PATCH 07/22] fix --- src/pocketmine/entity/passive/SkeletonHorse.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pocketmine/entity/passive/SkeletonHorse.php b/src/pocketmine/entity/passive/SkeletonHorse.php index c9555cadfdc..30458e4228e 100644 --- a/src/pocketmine/entity/passive/SkeletonHorse.php +++ b/src/pocketmine/entity/passive/SkeletonHorse.php @@ -34,6 +34,7 @@ use pocketmine\entity\behavior\RandomLookAroundBehavior; use pocketmine\entity\behavior\RandomStrollBehavior; use pocketmine\inventory\HorseInventory; +use pocketmine\item\ItemFactory; use pocketmine\inventory\InventoryHolder; use pocketmine\item\Item; use pocketmine\math\Vector3; From fabb3a11ea7dff9f6749dbaca12ff1417f856474 Mon Sep 17 00:00:00 2001 From: dearminder Date: Sat, 3 Aug 2019 12:17:05 +0200 Subject: [PATCH 08/22] Creeper runawawy from ocelots Cat And Ocelot walks randomly Rabbits avoid Player (but now dont come for carrot) --- src/pocketmine/entity/hostile/Creeper.php | 2 ++ src/pocketmine/entity/passive/Cat.php | 6 ++++-- src/pocketmine/entity/passive/Ocelot.php | 22 +++++++++++----------- src/pocketmine/entity/passive/Rabbit.php | 13 ++++++++----- 4 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/pocketmine/entity/hostile/Creeper.php b/src/pocketmine/entity/hostile/Creeper.php index 0478f403be4..8f0d8e981f9 100644 --- a/src/pocketmine/entity/hostile/Creeper.php +++ b/src/pocketmine/entity/hostile/Creeper.php @@ -37,6 +37,7 @@ use pocketmine\entity\behavior\RandomStrollBehavior; use pocketmine\entity\Monster; use pocketmine\entity\passive\Cat; +use pocketmine\entity\passive\Ocelot; use pocketmine\item\FlintSteel; use pocketmine\item\Item; use pocketmine\item\ItemFactory; @@ -96,6 +97,7 @@ protected function addBehaviors() : void{ $this->behaviorPool->setBehavior(1, new CreeperSwellBehavior($this)); // TODO: Avoid from ocelot $this->behaviorPool->setBehavior(2, new AvoidMobTypeBehavior($this, Cat::class, null, 6, 1, 1.2)); + $this->behaviorPool->setBehavior(2, new AvoidMobTypeBehavior($this, Ocelot::class, null, 6, 1, 1.2)); $this->behaviorPool->setBehavior(3, new MeleeAttackBehavior($this, 1.0)); $this->behaviorPool->setBehavior(4, new RandomStrollBehavior($this, 0.8)); $this->behaviorPool->setBehavior(5, new LookAtPlayerBehavior($this, 8.0)); diff --git a/src/pocketmine/entity/passive/Cat.php b/src/pocketmine/entity/passive/Cat.php index e9aa587a53d..032e3c89a3f 100644 --- a/src/pocketmine/entity/passive/Cat.php +++ b/src/pocketmine/entity/passive/Cat.php @@ -29,6 +29,7 @@ use pocketmine\entity\behavior\MateBehavior; use pocketmine\entity\behavior\PanicBehavior; use pocketmine\entity\behavior\RandomLookAroundBehavior; +use pocketmine\entity\behavior\RandomStrollBehavior; use pocketmine\entity\behavior\StayWhileSittingBehavior; use pocketmine\entity\behavior\TemptBehavior; use pocketmine\entity\Tamable; @@ -60,7 +61,8 @@ protected function addBehaviors() : void{ ], 1.0)); $this->behaviorPool->setBehavior(5, new FollowOwnerBehavior($this, 1, 10, 2)); $this->behaviorPool->setBehavior(6, new LookAtPlayerBehavior($this, 14.0)); - $this->behaviorPool->setBehavior(7, new RandomLookAroundBehavior($this)); + $this->behaviorPool->setBehavior(7, new RandomStrollBehavior($this, 1)); + $this->behaviorPool->setBehavior(8, new RandomLookAroundBehavior($this)); // TODO: attack turtle and rabbit @@ -83,7 +85,7 @@ public function getName() : string{ public function onInteract(Player $player, Item $item, Vector3 $clickPos) : bool{ if(!$this->isImmobile()){ - if($item->getId() == Item::RAW_SALMON || $item->getId() == Item::RAW_FISH){ + if($item->getId() == Item::RAW_SALMON || $item->getId() == Item::RAW_FISH || $item->getId() == Item::CLOWNFISH){ if($player->isSurvival()){ $item->pop(); } diff --git a/src/pocketmine/entity/passive/Ocelot.php b/src/pocketmine/entity/passive/Ocelot.php index 9b1fc751728..4139eb7e1e2 100644 --- a/src/pocketmine/entity/passive/Ocelot.php +++ b/src/pocketmine/entity/passive/Ocelot.php @@ -27,10 +27,14 @@ use pocketmine\entity\behavior\FollowOwnerBehavior; use pocketmine\entity\behavior\LookAtPlayerBehavior; use pocketmine\entity\behavior\MateBehavior; +use pocketmine\entity\behavior\MeleeAttackBehavior; +use pocketmine\entity\behavior\NearestAttackableTargetBehavior; use pocketmine\entity\behavior\PanicBehavior; use pocketmine\entity\behavior\RandomLookAroundBehavior; +use pocketmine\entity\behavior\RandomStrollBehavior; use pocketmine\entity\behavior\StayWhileSittingBehavior; use pocketmine\entity\behavior\TemptBehavior; +use pocketmine\entity\passive\Chicken; use pocketmine\entity\Tamable; use pocketmine\event\entity\EntityDamageByEntityEvent; use pocketmine\event\entity\EntityDamageEvent; @@ -58,12 +62,15 @@ protected function addBehaviors() : void{ Item::RAW_SALMON, Item::RAW_FISH ], 1.0)); - $this->behaviorPool->setBehavior(5, new FollowOwnerBehavior($this, 1.0)); + $this->behaviorPool->setBehavior(5, new FollowOwnerBehavior($this, 1, 10, 2)); $this->behaviorPool->setBehavior(6, new LookAtPlayerBehavior($this, 14.0)); $this->behaviorPool->setBehavior(7, new RandomLookAroundBehavior($this)); + $this->behaviorPool->setBehavior(8, new RandomStrollBehavior($this, 0.8)); + $this->behaviorPool->setBehavior(9, new MeleeAttackBehavior($this, 1.0)); - - // TODO: attack turtle and rabbit + $this->targetBehaviorPool->setBehavior(1, new NearestAttackableTargetBehavior($this, Chicken::class, false)); + //$this->targetBehaviorPool->setBehavior(9, new NearestAttackableTargetBehavior($this, SeaTurtle::class, false)); + //Also i have no idea why attack dont works } protected function initEntity() : void{ @@ -88,21 +95,17 @@ public function onInteract(Player $player, Item $item, Vector3 $clickPos) : bool $item->pop(); } if($this->isTamed()){ + $this->setTargetEntity(null); $this->setInLove(true); $this->setHealth(min($this->getMaxHealth(), $this->getHealth() + 2)); }elseif(mt_rand(0, 2) == 0){ $this->setOwningEntity($player); $this->setTamed(); - $this->setSittingFromBehavior(true); $this->broadcastEntityEvent(ActorEventPacket::TAME_SUCCESS); }else{ $this->broadcastEntityEvent(ActorEventPacket::TAME_FAIL); } return true; - }else{ - if($this->isTamed()){ - $this->setSittingFromBehavior(!$this->isSitting()); - } } } return parent::onInteract($player, $item, $clickPos); @@ -125,9 +128,6 @@ public function getDrops() : array{ ]; } - public function setSittingFromBehavior(bool $value) : void{ - $this->behaviorSitting->setSitting($value); - } public function attack(EntityDamageEvent $source) : void{ if($source->getCause() !== EntityDamageEvent::CAUSE_FALL){ diff --git a/src/pocketmine/entity/passive/Rabbit.php b/src/pocketmine/entity/passive/Rabbit.php index c940025a270..e88c9ab8e7c 100644 --- a/src/pocketmine/entity/passive/Rabbit.php +++ b/src/pocketmine/entity/passive/Rabbit.php @@ -23,6 +23,7 @@ namespace pocketmine\entity\passive; +use pocketmine\entity\behavior\AvoidMobTypeBehavior; use pocketmine\entity\behavior\FloatBehavior; use pocketmine\entity\behavior\LookAtPlayerBehavior; use pocketmine\entity\behavior\MateBehavior; @@ -32,6 +33,7 @@ use pocketmine\entity\Tamable; use pocketmine\item\Item; use pocketmine\item\ItemFactory; +use pocketmine\Player; use function mt_rand; class Rabbit extends Tamable{ @@ -44,11 +46,12 @@ protected function addBehaviors() : void { $this->behaviorPool->setBehavior(0, new FloatBehavior($this)); $this->behaviorPool->setBehavior(1, new MateBehavior($this, 2.0)); - $this->behaviorPool->setBehavior(3, new PanicBehavior($this, 2.0)); - $this->behaviorPool->setBehavior(4, new LookAtPlayerBehavior($this, 14.0)); - $this->behaviorPool->setBehavior(5, new RandomLookAroundBehavior($this)); - $this->behaviorPool->setBehavior(6, new TemptBehavior($this, [Item::CARROT], 1.0)); - // TODO: running away from player + $this->behaviorPool->setBehavior(2, new PanicBehavior($this, 2.0)); + $this->behaviorPool->setBehavior(3, new LookAtPlayerBehavior($this, 14.0)); + $this->behaviorPool->setBehavior(4, new RandomLookAroundBehavior($this)); + $this->behaviorPool->setBehavior(5, new TemptBehavior($this, [Item::CARROT], 1.0)); + $this->behaviorPool->setBehavior(6, new AvoidMobTypeBehavior($this, Player::class, null, 8, 1, 1)); + // TODO: going back to player when they see carrot, and movement fix so they dont SLIDE On ground } protected function initEntity() : void{ From f5cec61fbe2394a41fae81631576e1e221a024ea Mon Sep 17 00:00:00 2001 From: dearminder Date: Sat, 3 Aug 2019 12:17:05 +0200 Subject: [PATCH 09/22] Creeper runaway from ocelots Cat And Ocelot walks randomly Rabbits avoid Player (but now dont come for carrot) --- src/pocketmine/entity/hostile/Creeper.php | 2 ++ src/pocketmine/entity/passive/Cat.php | 6 ++++-- src/pocketmine/entity/passive/Ocelot.php | 22 +++++++++++----------- src/pocketmine/entity/passive/Rabbit.php | 13 ++++++++----- 4 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/pocketmine/entity/hostile/Creeper.php b/src/pocketmine/entity/hostile/Creeper.php index 0478f403be4..8f0d8e981f9 100644 --- a/src/pocketmine/entity/hostile/Creeper.php +++ b/src/pocketmine/entity/hostile/Creeper.php @@ -37,6 +37,7 @@ use pocketmine\entity\behavior\RandomStrollBehavior; use pocketmine\entity\Monster; use pocketmine\entity\passive\Cat; +use pocketmine\entity\passive\Ocelot; use pocketmine\item\FlintSteel; use pocketmine\item\Item; use pocketmine\item\ItemFactory; @@ -96,6 +97,7 @@ protected function addBehaviors() : void{ $this->behaviorPool->setBehavior(1, new CreeperSwellBehavior($this)); // TODO: Avoid from ocelot $this->behaviorPool->setBehavior(2, new AvoidMobTypeBehavior($this, Cat::class, null, 6, 1, 1.2)); + $this->behaviorPool->setBehavior(2, new AvoidMobTypeBehavior($this, Ocelot::class, null, 6, 1, 1.2)); $this->behaviorPool->setBehavior(3, new MeleeAttackBehavior($this, 1.0)); $this->behaviorPool->setBehavior(4, new RandomStrollBehavior($this, 0.8)); $this->behaviorPool->setBehavior(5, new LookAtPlayerBehavior($this, 8.0)); diff --git a/src/pocketmine/entity/passive/Cat.php b/src/pocketmine/entity/passive/Cat.php index e9aa587a53d..032e3c89a3f 100644 --- a/src/pocketmine/entity/passive/Cat.php +++ b/src/pocketmine/entity/passive/Cat.php @@ -29,6 +29,7 @@ use pocketmine\entity\behavior\MateBehavior; use pocketmine\entity\behavior\PanicBehavior; use pocketmine\entity\behavior\RandomLookAroundBehavior; +use pocketmine\entity\behavior\RandomStrollBehavior; use pocketmine\entity\behavior\StayWhileSittingBehavior; use pocketmine\entity\behavior\TemptBehavior; use pocketmine\entity\Tamable; @@ -60,7 +61,8 @@ protected function addBehaviors() : void{ ], 1.0)); $this->behaviorPool->setBehavior(5, new FollowOwnerBehavior($this, 1, 10, 2)); $this->behaviorPool->setBehavior(6, new LookAtPlayerBehavior($this, 14.0)); - $this->behaviorPool->setBehavior(7, new RandomLookAroundBehavior($this)); + $this->behaviorPool->setBehavior(7, new RandomStrollBehavior($this, 1)); + $this->behaviorPool->setBehavior(8, new RandomLookAroundBehavior($this)); // TODO: attack turtle and rabbit @@ -83,7 +85,7 @@ public function getName() : string{ public function onInteract(Player $player, Item $item, Vector3 $clickPos) : bool{ if(!$this->isImmobile()){ - if($item->getId() == Item::RAW_SALMON || $item->getId() == Item::RAW_FISH){ + if($item->getId() == Item::RAW_SALMON || $item->getId() == Item::RAW_FISH || $item->getId() == Item::CLOWNFISH){ if($player->isSurvival()){ $item->pop(); } diff --git a/src/pocketmine/entity/passive/Ocelot.php b/src/pocketmine/entity/passive/Ocelot.php index 9b1fc751728..4139eb7e1e2 100644 --- a/src/pocketmine/entity/passive/Ocelot.php +++ b/src/pocketmine/entity/passive/Ocelot.php @@ -27,10 +27,14 @@ use pocketmine\entity\behavior\FollowOwnerBehavior; use pocketmine\entity\behavior\LookAtPlayerBehavior; use pocketmine\entity\behavior\MateBehavior; +use pocketmine\entity\behavior\MeleeAttackBehavior; +use pocketmine\entity\behavior\NearestAttackableTargetBehavior; use pocketmine\entity\behavior\PanicBehavior; use pocketmine\entity\behavior\RandomLookAroundBehavior; +use pocketmine\entity\behavior\RandomStrollBehavior; use pocketmine\entity\behavior\StayWhileSittingBehavior; use pocketmine\entity\behavior\TemptBehavior; +use pocketmine\entity\passive\Chicken; use pocketmine\entity\Tamable; use pocketmine\event\entity\EntityDamageByEntityEvent; use pocketmine\event\entity\EntityDamageEvent; @@ -58,12 +62,15 @@ protected function addBehaviors() : void{ Item::RAW_SALMON, Item::RAW_FISH ], 1.0)); - $this->behaviorPool->setBehavior(5, new FollowOwnerBehavior($this, 1.0)); + $this->behaviorPool->setBehavior(5, new FollowOwnerBehavior($this, 1, 10, 2)); $this->behaviorPool->setBehavior(6, new LookAtPlayerBehavior($this, 14.0)); $this->behaviorPool->setBehavior(7, new RandomLookAroundBehavior($this)); + $this->behaviorPool->setBehavior(8, new RandomStrollBehavior($this, 0.8)); + $this->behaviorPool->setBehavior(9, new MeleeAttackBehavior($this, 1.0)); - - // TODO: attack turtle and rabbit + $this->targetBehaviorPool->setBehavior(1, new NearestAttackableTargetBehavior($this, Chicken::class, false)); + //$this->targetBehaviorPool->setBehavior(9, new NearestAttackableTargetBehavior($this, SeaTurtle::class, false)); + //Also i have no idea why attack dont works } protected function initEntity() : void{ @@ -88,21 +95,17 @@ public function onInteract(Player $player, Item $item, Vector3 $clickPos) : bool $item->pop(); } if($this->isTamed()){ + $this->setTargetEntity(null); $this->setInLove(true); $this->setHealth(min($this->getMaxHealth(), $this->getHealth() + 2)); }elseif(mt_rand(0, 2) == 0){ $this->setOwningEntity($player); $this->setTamed(); - $this->setSittingFromBehavior(true); $this->broadcastEntityEvent(ActorEventPacket::TAME_SUCCESS); }else{ $this->broadcastEntityEvent(ActorEventPacket::TAME_FAIL); } return true; - }else{ - if($this->isTamed()){ - $this->setSittingFromBehavior(!$this->isSitting()); - } } } return parent::onInteract($player, $item, $clickPos); @@ -125,9 +128,6 @@ public function getDrops() : array{ ]; } - public function setSittingFromBehavior(bool $value) : void{ - $this->behaviorSitting->setSitting($value); - } public function attack(EntityDamageEvent $source) : void{ if($source->getCause() !== EntityDamageEvent::CAUSE_FALL){ diff --git a/src/pocketmine/entity/passive/Rabbit.php b/src/pocketmine/entity/passive/Rabbit.php index c940025a270..e88c9ab8e7c 100644 --- a/src/pocketmine/entity/passive/Rabbit.php +++ b/src/pocketmine/entity/passive/Rabbit.php @@ -23,6 +23,7 @@ namespace pocketmine\entity\passive; +use pocketmine\entity\behavior\AvoidMobTypeBehavior; use pocketmine\entity\behavior\FloatBehavior; use pocketmine\entity\behavior\LookAtPlayerBehavior; use pocketmine\entity\behavior\MateBehavior; @@ -32,6 +33,7 @@ use pocketmine\entity\Tamable; use pocketmine\item\Item; use pocketmine\item\ItemFactory; +use pocketmine\Player; use function mt_rand; class Rabbit extends Tamable{ @@ -44,11 +46,12 @@ protected function addBehaviors() : void { $this->behaviorPool->setBehavior(0, new FloatBehavior($this)); $this->behaviorPool->setBehavior(1, new MateBehavior($this, 2.0)); - $this->behaviorPool->setBehavior(3, new PanicBehavior($this, 2.0)); - $this->behaviorPool->setBehavior(4, new LookAtPlayerBehavior($this, 14.0)); - $this->behaviorPool->setBehavior(5, new RandomLookAroundBehavior($this)); - $this->behaviorPool->setBehavior(6, new TemptBehavior($this, [Item::CARROT], 1.0)); - // TODO: running away from player + $this->behaviorPool->setBehavior(2, new PanicBehavior($this, 2.0)); + $this->behaviorPool->setBehavior(3, new LookAtPlayerBehavior($this, 14.0)); + $this->behaviorPool->setBehavior(4, new RandomLookAroundBehavior($this)); + $this->behaviorPool->setBehavior(5, new TemptBehavior($this, [Item::CARROT], 1.0)); + $this->behaviorPool->setBehavior(6, new AvoidMobTypeBehavior($this, Player::class, null, 8, 1, 1)); + // TODO: going back to player when they see carrot, and movement fix so they dont SLIDE On ground } protected function initEntity() : void{ From fa5d87e4eb21b05b26283f670f50d83669fbe612 Mon Sep 17 00:00:00 2001 From: dearminder Date: Sat, 3 Aug 2019 16:41:42 +0200 Subject: [PATCH 10/22] CTRL + ALT + L --- src/pocketmine/entity/passive/PolarBear.php | 136 ++++++++++---------- 1 file changed, 65 insertions(+), 71 deletions(-) diff --git a/src/pocketmine/entity/passive/PolarBear.php b/src/pocketmine/entity/passive/PolarBear.php index c2f95de0f92..06cc1fa49f6 100644 --- a/src/pocketmine/entity/passive/PolarBear.php +++ b/src/pocketmine/entity/passive/PolarBear.php @@ -37,74 +37,68 @@ use pocketmine\item\ItemFactory; use pocketmine\math\Vector3; -class PolarBear extends Animal -{ - public const NETWORK_ID = self::POLAR_BEAR; - - public $width = 1.3; - public $height = 1.4; - - protected function addBehaviors(): void - { - $this->behaviorPool->setBehavior(0, new FloatBehavior($this)); - $this->behaviorPool->setBehavior(1, new MateBehavior($this, 1.0)); - $this->behaviorPool->setBehavior(2, new MeleeAttackBehavior($this, 1.0)); - $this->behaviorPool->setBehavior(3, new FollowParentBehavior($this, 1.1)); - $this->behaviorPool->setBehavior(4, new RandomStrollBehavior($this, 1.0)); - $this->behaviorPool->setBehavior(5, new LookAtPlayerBehavior($this, 16.0)); - $this->behaviorPool->setBehavior(6, new RandomLookAroundBehavior($this)); - - $this->targetBehaviorPool->setBehavior(0, new HurtByTargetBehavior($this)); - } - public - function initEntity(): void - { - $this->setMaxHealth(30); - $this->setMovementSpeed(0.30); - $this->setAttackDamage(4); - $this->setFollowRange(16); - parent::initEntity(); - } - //TODO: atack foxes - public - function getName(): string - { - return "Polar Bear"; - } - - public function setTargetEntity(?Entity $target) : void{ - parent::setTargetEntity($target); - if($target == null){ - $this->setAngry(false); - } - } - public function isAngry() : bool{ - return $this->getGenericFlag(self::DATA_FLAG_ANGRY); - } - - public function setAngry(bool $angry = true) : void{ - $this->setGenericFlag(self::DATA_FLAG_ANGRY, $angry); - } - - private function generateRandomDirection(): Vector3 - { - return new Vector3(mt_rand(-1000, 1000) / 1000, mt_rand(-500, 500) / 1000, mt_rand(-1000, 1000) / 1000); - } - - public function getXpDropAmount() : int{ - return rand(1, 3); - } - - public - function getDrops(): array - { - $drops = []; - if(mt_rand(1, 4) >1){ - $drops[] = ItemFactory::get(Item::RAW_FISH, 1, mt_rand(0, 2)); - return $drops; - } - else{ - $drops[] = ItemFactory::get(Item::RAW_SALMON, 1, mt_rand(0, 2)); - return $drops;} - } - } \ No newline at end of file +class PolarBear extends Animal{ + public const NETWORK_ID = self::POLAR_BEAR; + + public $width = 1.3; + public $height = 1.4; + + protected function addBehaviors() : void{ + $this->behaviorPool->setBehavior(0, new FloatBehavior($this)); + $this->behaviorPool->setBehavior(1, new MateBehavior($this, 1.0)); + $this->behaviorPool->setBehavior(2, new MeleeAttackBehavior($this, 1.0)); + $this->behaviorPool->setBehavior(3, new FollowParentBehavior($this, 1.1)); + $this->behaviorPool->setBehavior(4, new RandomStrollBehavior($this, 1.0)); + $this->behaviorPool->setBehavior(5, new LookAtPlayerBehavior($this, 16.0)); + $this->behaviorPool->setBehavior(6, new RandomLookAroundBehavior($this)); + + $this->targetBehaviorPool->setBehavior(0, new HurtByTargetBehavior($this)); + } + + public function initEntity() : void{ + $this->setMaxHealth(30); + $this->setMovementSpeed(0.30); + $this->setAttackDamage(4); + $this->setFollowRange(16); + parent::initEntity(); + } + + //TODO: atack foxes + public function getName() : string{ + return "Polar Bear"; + } + + public function setTargetEntity(?Entity $target) : void{ + parent::setTargetEntity($target); + if($target == null){ + $this->setAngry(false); + } + } + + public function isAngry() : bool{ + return $this->getGenericFlag(self::DATA_FLAG_ANGRY); + } + + public function setAngry(bool $angry = true) : void{ + $this->setGenericFlag(self::DATA_FLAG_ANGRY, $angry); + } + + private function generateRandomDirection() : Vector3{ + return new Vector3(mt_rand(-1000, 1000) / 1000, mt_rand(-500, 500) / 1000, mt_rand(-1000, 1000) / 1000); + } + + public function getXpDropAmount() : int{ + return rand(1, 3); + } + + public function getDrops() : array{ + $drops = []; + if(mt_rand(1, 4) > 1){ + $drops[] = ItemFactory::get(Item::RAW_FISH, 1, mt_rand(0, 2)); + return $drops; + }else{ + $drops[] = ItemFactory::get(Item::RAW_SALMON, 1, mt_rand(0, 2)); + return $drops; + } + } +} \ No newline at end of file From d502eabd3beddf322ee4533dc950907dc7cc1329 Mon Sep 17 00:00:00 2001 From: dearminder Date: Sat, 3 Aug 2019 16:44:55 +0200 Subject: [PATCH 11/22] CTRL + ALT + L --- src/pocketmine/entity/passive/Rabbit.php | 40 +++++++++++------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/src/pocketmine/entity/passive/Rabbit.php b/src/pocketmine/entity/passive/Rabbit.php index e88c9ab8e7c..1c4d45a20c8 100644 --- a/src/pocketmine/entity/passive/Rabbit.php +++ b/src/pocketmine/entity/passive/Rabbit.php @@ -39,20 +39,19 @@ class Rabbit extends Tamable{ public const NETWORK_ID = self::RABBIT; - public $width = 0.4; + public $width = 0.4; public $height = 0.5; - protected function addBehaviors() : void - { - $this->behaviorPool->setBehavior(0, new FloatBehavior($this)); - $this->behaviorPool->setBehavior(1, new MateBehavior($this, 2.0)); - $this->behaviorPool->setBehavior(2, new PanicBehavior($this, 2.0)); - $this->behaviorPool->setBehavior(3, new LookAtPlayerBehavior($this, 14.0)); - $this->behaviorPool->setBehavior(4, new RandomLookAroundBehavior($this)); - $this->behaviorPool->setBehavior(5, new TemptBehavior($this, [Item::CARROT], 1.0)); - $this->behaviorPool->setBehavior(6, new AvoidMobTypeBehavior($this, Player::class, null, 8, 1, 1)); - // TODO: going back to player when they see carrot, and movement fix so they dont SLIDE On ground - } + protected function addBehaviors() : void{ + $this->behaviorPool->setBehavior(0, new FloatBehavior($this)); + $this->behaviorPool->setBehavior(1, new MateBehavior($this, 2.0)); + $this->behaviorPool->setBehavior(2, new PanicBehavior($this, 2.0)); + $this->behaviorPool->setBehavior(3, new LookAtPlayerBehavior($this, 14.0)); + $this->behaviorPool->setBehavior(4, new RandomLookAroundBehavior($this)); + $this->behaviorPool->setBehavior(5, new TemptBehavior($this, [Item::CARROT], 1.0)); + $this->behaviorPool->setBehavior(6, new AvoidMobTypeBehavior($this, Player::class, null, 8, 1, 1)); + // TODO: going back to player when they see carrot, and movement fix so they dont SLIDE On ground + } protected function initEntity() : void{ $this->setMaxHealth(3); @@ -68,15 +67,14 @@ public function getName() : string{ } + public function getXpDropAmount() : int{ + return rand(1, 3); + } - public function getXpDropAmount() : int{ - return rand(1, 3); - } - - public function getDrops() : array{ - return [ - ItemFactory::get(Item::RABBIT_HIDE, 0, rand(0, 1)), - ($this->isOnFire() ? ItemFactory::get(Item::COOKED_RABBIT, 0, rand(0, 1)) : ItemFactory::get(Item::RAW_RABBIT, 0, rand(0, 1))) - ]; + public function getDrops() : array{ + return [ + ItemFactory::get(Item::RABBIT_HIDE, 0, rand(0, 1)), + ($this->isOnFire() ? ItemFactory::get(Item::COOKED_RABBIT, 0, rand(0, 1)) : ItemFactory::get(Item::RAW_RABBIT, 0, rand(0, 1))) + ]; } } \ No newline at end of file From 0ad56d9df6adb1a40d0458a042a51b8c975251d9 Mon Sep 17 00:00:00 2001 From: dearminder Date: Sat, 3 Aug 2019 16:55:46 +0200 Subject: [PATCH 12/22] Revert it --- src/pocketmine/level/GameRules.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pocketmine/level/GameRules.php b/src/pocketmine/level/GameRules.php index 1e78eeecfad..c3ed40f4037 100644 --- a/src/pocketmine/level/GameRules.php +++ b/src/pocketmine/level/GameRules.php @@ -71,7 +71,7 @@ public function __construct(){ $this->setBool(self::RULE_DO_FIRE_TICK, true); $this->setBool(self::RULE_DO_INSOMNIA, true); $this->setBool(self::RULE_DO_MOB_LOOT, true); - $this->setBool(self::RULE_DO_MOB_SPAWNING, true); + $this->setBool(self::RULE_DO_MOB_SPAWNING, false); $this->setBool(self::RULE_DO_TILE_DROPS, true); $this->setBool(self::RULE_DO_WEATHER_CYCLE, true); $this->setBool(self::RULE_DROWNING_DAMAGE, true); From b37df0ba51df447c14353d053821325e5b0f399b Mon Sep 17 00:00:00 2001 From: dearminder Date: Mon, 5 Aug 2019 14:36:25 +0200 Subject: [PATCH 13/22] Better Effect --- src/pocketmine/entity/hostile/WitherSkeleton.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/pocketmine/entity/hostile/WitherSkeleton.php b/src/pocketmine/entity/hostile/WitherSkeleton.php index 1f4b69f27f6..a97e5264624 100644 --- a/src/pocketmine/entity/hostile/WitherSkeleton.php +++ b/src/pocketmine/entity/hostile/WitherSkeleton.php @@ -33,6 +33,7 @@ use pocketmine\entity\Effect; use pocketmine\entity\EffectInstance; use pocketmine\entity\Entity; +use pocketmine\entity\Living; use pocketmine\entity\Monster; use pocketmine\inventory\AltayEntityEquipment; use pocketmine\item\Item; @@ -82,12 +83,10 @@ public function getDrops() : array{ public function onCollideWithEntity(Entity $entity) : void{ parent::onCollideWithEntity($entity); - if($entity instanceof Player){ - if($this->getTargetEntity() === $entity){ + if($this->getTargetEntityId() === $entity->getId() and $entity instanceof Living){ $entity->addEffect(new EffectInstance(Effect::getEffect(Effect::WITHER), 200, 1)); } } - } From 66a44434fd756e62c5415daccb0a7de61b42bb66 Mon Sep 17 00:00:00 2001 From: EmreTr1 Date: Sun, 20 Oct 2019 18:30:20 +0300 Subject: [PATCH 14/22] Updates from me --- src/pocketmine/entity/passive/Cat.php | 1 - .../entity/passive/TropicalFish.php | 64 +++++++++++++++++-- 2 files changed, 58 insertions(+), 7 deletions(-) diff --git a/src/pocketmine/entity/passive/Cat.php b/src/pocketmine/entity/passive/Cat.php index 032e3c89a3f..f403bfa6517 100644 --- a/src/pocketmine/entity/passive/Cat.php +++ b/src/pocketmine/entity/passive/Cat.php @@ -64,7 +64,6 @@ protected function addBehaviors() : void{ $this->behaviorPool->setBehavior(7, new RandomStrollBehavior($this, 1)); $this->behaviorPool->setBehavior(8, new RandomLookAroundBehavior($this)); - // TODO: attack turtle and rabbit } diff --git a/src/pocketmine/entity/passive/TropicalFish.php b/src/pocketmine/entity/passive/TropicalFish.php index d1ebd0e8568..1808dd558ae 100644 --- a/src/pocketmine/entity/passive/TropicalFish.php +++ b/src/pocketmine/entity/passive/TropicalFish.php @@ -29,6 +29,8 @@ use pocketmine\item\Item; use pocketmine\item\ItemFactory; use pocketmine\math\Vector3; +use pocketmine\nbt\tag\ByteTag; +use pocketmine\nbt\tag\IntTag; use pocketmine\network\mcpe\protocol\ActorEventPacket; use function atan2; use function mt_rand; @@ -38,7 +40,33 @@ class TropicalFish extends WaterAnimal{ public const NETWORK_ID = self::TROPICAL_FISH; - public $width = 0.5; + public const SHAPE_A = 0; + public const SHAPE_B = 1; + + public const PATTERN_1 = 0; + public const PATTERN_2 = 1; + public const PATTERN_3 = 2; + public const PATTERN_4 = 3; + public const PATTERN_5 = 4; + public const PATTERN_6 = 5; + + public const COLOR_WHITE = 0; + public const COLOR_ORANGE = 1; + public const COLOR_MAGENTA = 2; + public const COLOR_LIGHTBLUE = 3; + public const COLOR_YELLOW = 4; + public const COLOR_LIGHTGREEN = 5; + public const COLOR_PINK = 6; + public const COLOR_GRAY = 7; + public const COLOR_SILVER = 8; + public const COLOR_CYAN = 9; + public const COLOR_PURPLE = 10; + public const COLOR_BLUE = 11; + public const COLOR_BROWN = 12; + public const COLOR_GREEN = 13; + public const COLOR_RED = 14; + + public $width = 0.4; public $height = 0.4; /** @var Vector3 */ @@ -48,8 +76,35 @@ class TropicalFish extends WaterAnimal{ private $switchDirectionTicker = 0; public function initEntity() : void{ - $this->setMaxHealth(3); - //TODO: Add diffrent styles of fish + $this->setMaxHealth(6); + + if($this->namedtag->hasTag("Variant", IntTag::class)){ + $this->propertyManager->setInt(self::DATA_VARIANT, $this->namedtag->getInt("Variant")); + }else{ + $this->propertyManager->setInt(self::DATA_VARIANT, mt_rand(0, 1)); + } + + if($this->namedtag->hasTag("MarkVariant", IntTag::class)){ + $this->propertyManager->setInt(self::DATA_MARK_VARIANT, $this->namedtag->getInt("MarkVariant")); + }else{ + $this->propertyManager->setInt(self::DATA_MARK_VARIANT, mt_rand(0, 5)); + } + + if($this->namedtag->hasTag("Color", ByteTag::class)){ + $this->propertyManager->setByte(self::DATA_COLOR, $this->namedtag->getByte("Color")); + }else{ + $this->propertyManager->setByte(self::DATA_COLOR, mt_rand(0, 14)); + } + + if($this->namedtag->hasTag("Color2", ByteTag::class)){ + $this->propertyManager->setByte(self::DATA_COLOR_2, $this->namedtag->getByte("Color2")); + }else{ + $this->propertyManager->setByte(self::DATA_COLOR_2, mt_rand(0, 14)); + } + + $this->setMovementSpeed(0.12); + $this->swimSpeed = 0.12; + parent::initEntity(); } @@ -69,8 +124,6 @@ public function attack(EntityDamageEvent $source) : void{ if($e !== null){ $this->swimDirection = (new Vector3($this->x - $e->x, $this->y - $e->y, $this->z - $e->z))->normalize(); } - - } } @@ -108,7 +161,6 @@ public function entityBaseTick(int $tickDiff = 1) : bool{ } }else{ $this->swimDirection = $this->generateRandomDirection(); - $this->swimSpeed = mt_rand(50, 100) / 2000; } $f = sqrt(($this->motion->x ** 2) + ($this->motion->z ** 2)); From f2b4769576c236d66a0eb9e04fc54af2ff772745 Mon Sep 17 00:00:00 2001 From: EmreTr1 Date: Mon, 21 Oct 2019 20:54:33 +0300 Subject: [PATCH 15/22] Updates from me 2 --- src/pocketmine/entity/hostile/Blaze.php | 3 +- src/pocketmine/entity/hostile/Dolphin.php | 2 +- src/pocketmine/entity/hostile/Skeleton.php | 3 +- .../entity/hostile/WitherSkeleton.php | 10 +- .../entity/hostile/ZombiePigman.php | 16 +- src/pocketmine/entity/passive/Chicken.php | 7 +- src/pocketmine/entity/passive/Cod.php | 7 +- src/pocketmine/entity/passive/Horse.php | 10 +- src/pocketmine/entity/passive/PolarBear.php | 6 +- src/pocketmine/entity/passive/Pufferfish.php | 9 +- src/pocketmine/entity/passive/Rabbit.php | 1 - src/pocketmine/entity/passive/Salmon.php | 7 +- .../entity/passive/SkeletonHorse.php | 38 +-- .../entity/passive/TropicalFish.php | 2 +- src/pocketmine/entity/passive/ZombieHorse.php | 237 ++++++++---------- 15 files changed, 154 insertions(+), 204 deletions(-) diff --git a/src/pocketmine/entity/hostile/Blaze.php b/src/pocketmine/entity/hostile/Blaze.php index e45f87e0fd9..05c4e47c7d3 100644 --- a/src/pocketmine/entity/hostile/Blaze.php +++ b/src/pocketmine/entity/hostile/Blaze.php @@ -75,7 +75,8 @@ public function getXpDropAmount() : int{ public function getDrops() : array{ return [ - ItemFactory::get(Item::BLAZE_ROD, 0, rand(0, 1)), ItemFactory::get(Item::GLOWSTONE_DUST, 0, rand(0, 2)) + ItemFactory::get(Item::BLAZE_ROD, 0, rand(0, 1)), + ItemFactory::get(Item::GLOWSTONE_DUST, 0, rand(0, 2)) ]; } diff --git a/src/pocketmine/entity/hostile/Dolphin.php b/src/pocketmine/entity/hostile/Dolphin.php index 134398f5fd4..66e41200b3d 100644 --- a/src/pocketmine/entity/hostile/Dolphin.php +++ b/src/pocketmine/entity/hostile/Dolphin.php @@ -53,6 +53,7 @@ class Dolphin extends WaterAnimal{ public function initEntity() : void{ $this->setMaxHealth(10); + $this->swimSpeed = 0.12; parent::initEntity(); } @@ -111,7 +112,6 @@ public function entityBaseTick(int $tickDiff = 1) : bool{ } }else{ $this->swimDirection = $this->generateRandomDirection(); - $this->swimSpeed = mt_rand(50, 100) / 2000; } $f = sqrt(($this->motion->x ** 2) + ($this->motion->z ** 2)); diff --git a/src/pocketmine/entity/hostile/Skeleton.php b/src/pocketmine/entity/hostile/Skeleton.php index b0a1d66362f..5f7045c624d 100644 --- a/src/pocketmine/entity/hostile/Skeleton.php +++ b/src/pocketmine/entity/hostile/Skeleton.php @@ -76,7 +76,8 @@ public function getName() : string{ public function getDrops() : array{ return [ - ItemFactory::get(Item::BONE, 0, rand(0, 2)), ItemFactory::get(Item::ARROW, 0, rand(0, 2)) + ItemFactory::get(Item::BONE, 0, rand(0, 2)), + ItemFactory::get(Item::ARROW, 0, rand(0, 2)) ]; } diff --git a/src/pocketmine/entity/hostile/WitherSkeleton.php b/src/pocketmine/entity/hostile/WitherSkeleton.php index a97e5264624..42eeff86670 100644 --- a/src/pocketmine/entity/hostile/WitherSkeleton.php +++ b/src/pocketmine/entity/hostile/WitherSkeleton.php @@ -74,21 +74,19 @@ public function getDrops() : array{ if(mt_rand(0, 2) < 1){ $drops[] = ItemFactory::get(Item::COAL, 0, 1); } - if(mt_rand(1, 40) ===1){ + if(mt_rand(1, 40) === 1){ $drops[] = ItemFactory::get(Item::MOB_HEAD, 1, 1); } return $drops; -} + } public function onCollideWithEntity(Entity $entity) : void{ parent::onCollideWithEntity($entity); if($this->getTargetEntityId() === $entity->getId() and $entity instanceof Living){ - $entity->addEffect(new EffectInstance(Effect::getEffect(Effect::WITHER), 200, 1)); - } + $entity->addEffect(new EffectInstance(Effect::getEffect(Effect::WITHER), 200, 1)); } - - + } public function getXpDropAmount() : int{ diff --git a/src/pocketmine/entity/hostile/ZombiePigman.php b/src/pocketmine/entity/hostile/ZombiePigman.php index 199bc079747..9b11dea8945 100644 --- a/src/pocketmine/entity/hostile/ZombiePigman.php +++ b/src/pocketmine/entity/hostile/ZombiePigman.php @@ -45,8 +45,8 @@ class ZombiePigman extends Monster implements Ageable{ public $width = 0.6; public $height = 1.95; - /** @var AltayEntityEquipment */ - protected $equipment; + /** @var AltayEntityEquipment */ + protected $equipment; protected function initEntity() : void{ $this->setMovementSpeed($this->isBaby() ? 0.35 : 0.23); @@ -55,9 +55,9 @@ protected function initEntity() : void{ parent::initEntity(); - $this->equipment = new AltayEntityEquipment($this); + $this->equipment = new AltayEntityEquipment($this); - $this->equipment->setItemInHand(ItemFactory::get(Item::GOLDEN_SWORD)); + $this->equipment->setItemInHand(ItemFactory::get(Item::GOLDEN_SWORD)); } public function getName() : string{ @@ -103,9 +103,9 @@ protected function addBehaviors() : void{ } - public function sendSpawnPacket(Player $player) : void{ - parent::sendSpawnPacket($player); + public function sendSpawnPacket(Player $player) : void{ + parent::sendSpawnPacket($player); - $this->equipment->sendContents([$player]); - } + $this->equipment->sendContents([$player]); + } } \ No newline at end of file diff --git a/src/pocketmine/entity/passive/Chicken.php b/src/pocketmine/entity/passive/Chicken.php index b843f677ecd..942ba87ed0e 100644 --- a/src/pocketmine/entity/passive/Chicken.php +++ b/src/pocketmine/entity/passive/Chicken.php @@ -68,7 +68,12 @@ protected function addBehaviors() : void{ $this->behaviorPool->setBehavior(0, new FloatBehavior($this)); $this->behaviorPool->setBehavior(1, new PanicBehavior($this, 1.4)); $this->behaviorPool->setBehavior(2, new MateBehavior($this, 1.0)); - $this->behaviorPool->setBehavior(3, new TemptBehavior($this, [Item::WHEAT_SEEDS, Item::PUMPKIN_SEEDS, Item::MELON_SEEDS, Item::BEETROOT_SEEDS], 1.0)); + $this->behaviorPool->setBehavior(3, new TemptBehavior($this, [ + Item::WHEAT_SEEDS, + Item::PUMPKIN_SEEDS, + Item::MELON_SEEDS, + Item::BEETROOT_SEEDS + ], 1.0)); $this->behaviorPool->setBehavior(4, new FollowParentBehavior($this, 1.1)); $this->behaviorPool->setBehavior(5, new RandomStrollBehavior($this, 1.0)); $this->behaviorPool->setBehavior(6, new LookAtPlayerBehavior($this, 6.0)); diff --git a/src/pocketmine/entity/passive/Cod.php b/src/pocketmine/entity/passive/Cod.php index c8405f45e8d..2ac8a80cb67 100644 --- a/src/pocketmine/entity/passive/Cod.php +++ b/src/pocketmine/entity/passive/Cod.php @@ -69,8 +69,6 @@ public function attack(EntityDamageEvent $source) : void{ if($e !== null){ $this->swimDirection = (new Vector3($this->x - $e->x, $this->y - $e->y, $this->z - $e->z))->normalize(); } - - } } @@ -94,7 +92,6 @@ public function entityBaseTick(int $tickDiff = 1) : bool{ $hasUpdate = parent::entityBaseTick($tickDiff); if($this->isAlive()){ - if($this->y > 62 and $this->swimDirection !== null){ $this->swimDirection->y = -0.5; } @@ -108,7 +105,7 @@ public function entityBaseTick(int $tickDiff = 1) : bool{ } }else{ $this->swimDirection = $this->generateRandomDirection(); - $this->swimSpeed = mt_rand(50, 100) / 2000; + $this->swimSpeed = 0.05; } $f = sqrt(($this->motion->x ** 2) + ($this->motion->z ** 2)); @@ -123,7 +120,7 @@ public function getDrops() : array{ $drops = [ ItemFactory::get(Item::RAW_FISH, 0, 1), ]; - if(mt_rand(1, 4) ===1){ + if(mt_rand(1, 4) === 1){ $drops[] = ItemFactory::get(Item::BONE, 1, mt_rand(1, 2)); } return $drops; diff --git a/src/pocketmine/entity/passive/Horse.php b/src/pocketmine/entity/passive/Horse.php index fe18c8cd590..5780b9e1d70 100644 --- a/src/pocketmine/entity/passive/Horse.php +++ b/src/pocketmine/entity/passive/Horse.php @@ -82,7 +82,15 @@ protected function addBehaviors() : void{ $this->behaviorPool->setBehavior(1, new FloatBehavior($this)); $this->behaviorPool->setBehavior(2, new PanicBehavior($this, 1.25)); $this->behaviorPool->setBehavior(3, new MateBehavior($this, 1.0)); - $this->behaviorPool->setBehavior(4, new TemptBehavior($this, [Item::WHEAT, Item::APPLE, Item::WHEAT_BLOCK, Item::GOLDEN_APPLE, Item::ENCHANTED_GOLDEN_APPLE, Item::GOLDEN_CARROT, Item::SUGAR], 1.2)); + $this->behaviorPool->setBehavior(4, new TemptBehavior($this, [ + Item::WHEAT, + Item::APPLE, + Item::WHEAT_BLOCK, + Item::GOLDEN_APPLE, + Item::ENCHANTED_GOLDEN_APPLE, + Item::GOLDEN_CARROT, + Item::SUGAR + ], 1.2)); $this->behaviorPool->setBehavior(5, new FollowParentBehavior($this, 1.1)); $this->behaviorPool->setBehavior(6, new RandomStrollBehavior($this, 1.0)); $this->behaviorPool->setBehavior(7, new LookAtPlayerBehavior($this, 6.0)); diff --git a/src/pocketmine/entity/passive/PolarBear.php b/src/pocketmine/entity/passive/PolarBear.php index 06cc1fa49f6..0cb1c4b8e27 100644 --- a/src/pocketmine/entity/passive/PolarBear.php +++ b/src/pocketmine/entity/passive/PolarBear.php @@ -63,7 +63,7 @@ public function initEntity() : void{ parent::initEntity(); } - //TODO: atack foxes + //TODO: attack fixes public function getName() : string{ return "Polar Bear"; } @@ -83,10 +83,6 @@ public function setAngry(bool $angry = true) : void{ $this->setGenericFlag(self::DATA_FLAG_ANGRY, $angry); } - private function generateRandomDirection() : Vector3{ - return new Vector3(mt_rand(-1000, 1000) / 1000, mt_rand(-500, 500) / 1000, mt_rand(-1000, 1000) / 1000); - } - public function getXpDropAmount() : int{ return rand(1, 3); } diff --git a/src/pocketmine/entity/passive/Pufferfish.php b/src/pocketmine/entity/passive/Pufferfish.php index 6cc6859f5f4..f6465f81874 100644 --- a/src/pocketmine/entity/passive/Pufferfish.php +++ b/src/pocketmine/entity/passive/Pufferfish.php @@ -33,6 +33,7 @@ use pocketmine\item\ItemFactory; use pocketmine\math\Vector3; use pocketmine\network\mcpe\protocol\ActorEventPacket; +use pocketmine\Player; use function atan2; use function mt_rand; use function sqrt; @@ -72,7 +73,6 @@ public function attack(EntityDamageEvent $source) : void{ if($e !== null){ $this->swimDirection = (new Vector3($this->x - $e->x, $this->y - $e->y, $this->z - $e->z))->normalize(); } - } } @@ -80,7 +80,6 @@ private function generateRandomDirection() : Vector3{ return new Vector3(mt_rand(-1000, 1000) / 1000, mt_rand(-500, 500) / 1000, mt_rand(-1000, 1000) / 1000); } - public function entityBaseTick(int $tickDiff = 1) : bool{ if($this->closed){ return false; @@ -110,7 +109,7 @@ public function entityBaseTick(int $tickDiff = 1) : bool{ } }else{ $this->swimDirection = $this->generateRandomDirection(); - $this->swimSpeed = mt_rand(50, 100) / 2000; + $this->swimSpeed = 0.05; } $f = sqrt(($this->motion->x ** 2) + ($this->motion->z ** 2)); @@ -132,13 +131,11 @@ public function onCollideWithEntity(Entity $entity) : void{ } - - public function getDrops() : array{ $drops = [ ItemFactory::get(Item::PUFFERFISH, 0, 1), ]; - if(mt_rand(1, 4) ===1){ + if(mt_rand(1, 4) === 1){ $drops[] = ItemFactory::get(Item::BONE, 1, mt_rand(1, 2)); } return $drops; diff --git a/src/pocketmine/entity/passive/Rabbit.php b/src/pocketmine/entity/passive/Rabbit.php index 1c4d45a20c8..d4a9a68d116 100644 --- a/src/pocketmine/entity/passive/Rabbit.php +++ b/src/pocketmine/entity/passive/Rabbit.php @@ -66,7 +66,6 @@ public function getName() : string{ return "Rabbit"; } - public function getXpDropAmount() : int{ return rand(1, 3); } diff --git a/src/pocketmine/entity/passive/Salmon.php b/src/pocketmine/entity/passive/Salmon.php index ebc41ceb2f9..4d5c96111eb 100644 --- a/src/pocketmine/entity/passive/Salmon.php +++ b/src/pocketmine/entity/passive/Salmon.php @@ -69,8 +69,6 @@ public function attack(EntityDamageEvent $source) : void{ if($e !== null){ $this->swimDirection = (new Vector3($this->x - $e->x, $this->y - $e->y, $this->z - $e->z))->normalize(); } - - } } @@ -78,7 +76,6 @@ private function generateRandomDirection() : Vector3{ return new Vector3(mt_rand(-1000, 1000) / 1000, mt_rand(-500, 500) / 1000, mt_rand(-1000, 1000) / 1000); } - public function entityBaseTick(int $tickDiff = 1) : bool{ if($this->closed){ return false; @@ -108,7 +105,7 @@ public function entityBaseTick(int $tickDiff = 1) : bool{ } }else{ $this->swimDirection = $this->generateRandomDirection(); - $this->swimSpeed = mt_rand(50, 100) / 2000; + $this->swimSpeed = 0.05; } $f = sqrt(($this->motion->x ** 2) + ($this->motion->z ** 2)); @@ -123,7 +120,7 @@ public function getDrops() : array{ $drops = [ ItemFactory::get(Item::RAW_SALMON, 0, 1), ]; - if(mt_rand(1, 4) ===1){ + if(mt_rand(1, 4) === 1){ $drops[] = ItemFactory::get(Item::BONE, 1, mt_rand(1, 2)); } return $drops; diff --git a/src/pocketmine/entity/passive/SkeletonHorse.php b/src/pocketmine/entity/passive/SkeletonHorse.php index 30458e4228e..bba85372233 100644 --- a/src/pocketmine/entity/passive/SkeletonHorse.php +++ b/src/pocketmine/entity/passive/SkeletonHorse.php @@ -46,20 +46,6 @@ class SkeletonHorse extends AbstractHorse implements InventoryHolder{ public const NETWORK_ID = self::SKELETON_HORSE; - public const HORSE_VARIANT_WHITE = 0; - public const HORSE_VARIANT_CREAMY = 1; - public const HORSE_VARIANT_CHESTNUT = 2; - public const HORSE_VARIANT_BROWN = 3; - public const HORSE_VARIANT_BLACK = 4; - public const HORSE_VARIANT_GRAY = 5; - public const HORSE_VARIANT_DARK_BROWN = 6; - - public const HORSE_MARK_VARIANT_NONE = 0; - public const HORSE_MARK_VARIANT_WHITE = 1; - public const HORSE_MARK_VARIANT_WHITE_FIELD = 2; - public const HORSE_MARK_VARIANT_WHITE_DOTS = 3; - public const HORSE_MARK_VARIANT_BLACK_DOTS = 4; - public $width = 1.4; public $height = 1.6; @@ -89,18 +75,11 @@ protected function addBehaviors() : void{ } protected function initEntity() : void{ - $this->setMaxHealth(15); + $this->setMaxHealth(15); $this->setMovementSpeed($this->getModifiedMovementSpeed()); $this->setJumpStrength($this->getModifiedJumpStrength()); $this->setFollowRange(35); - if($this->namedtag->hasTag("Variant", IntTag::class) and $this->namedtag->hasTag("MarkVariant", IntTag::class)){ - $this->setVariant($this->namedtag->getInt("Variant")); - $this->setMarkVariant($this->namedtag->getInt("MarkVariant")); - }else{ - $this->setVariant($this->random->nextBoundedInt(7)); - $this->setMarkVariant($this->random->nextBoundedInt(5)); - } $this->inventory = new HorseInventory($this); if($this->namedtag->hasTag("ArmorItem", CompoundTag::class)){ @@ -169,12 +148,11 @@ public function saveNBT() : void{ $this->namedtag->setTag($this->inventory->getArmor()->nbtSerialize(-1, "ArmorItem")); } } - public - function getDrops(): array - { - return [ - ItemFactory::get(Item::BONE, 0, mt_rand(0, 2)) - ]; - } - //TODO: add changing normal horse to skeleton by lightning + + public function getDrops() : array{ + return [ + ItemFactory::get(Item::BONE, 0, mt_rand(0, 2)) + ]; + } + //TODO: add changing normal horse to skeleton by lightning } \ No newline at end of file diff --git a/src/pocketmine/entity/passive/TropicalFish.php b/src/pocketmine/entity/passive/TropicalFish.php index 1808dd558ae..4f518fca403 100644 --- a/src/pocketmine/entity/passive/TropicalFish.php +++ b/src/pocketmine/entity/passive/TropicalFish.php @@ -103,7 +103,6 @@ public function initEntity() : void{ } $this->setMovementSpeed(0.12); - $this->swimSpeed = 0.12; parent::initEntity(); } @@ -161,6 +160,7 @@ public function entityBaseTick(int $tickDiff = 1) : bool{ } }else{ $this->swimDirection = $this->generateRandomDirection(); + $this->swimSpeed = 0.05; } $f = sqrt(($this->motion->x ** 2) + ($this->motion->z ** 2)); diff --git a/src/pocketmine/entity/passive/ZombieHorse.php b/src/pocketmine/entity/passive/ZombieHorse.php index 8f56ca81c76..bbc004ddbf0 100644 --- a/src/pocketmine/entity/passive/ZombieHorse.php +++ b/src/pocketmine/entity/passive/ZombieHorse.php @@ -43,136 +43,109 @@ class ZombieHorse extends AbstractHorse implements InventoryHolder{ - public const NETWORK_ID = self::ZOMBIE_HORSE; - - public const HORSE_VARIANT_WHITE = 0; - public const HORSE_VARIANT_CREAMY = 1; - public const HORSE_VARIANT_CHESTNUT = 2; - public const HORSE_VARIANT_BROWN = 3; - public const HORSE_VARIANT_BLACK = 4; - public const HORSE_VARIANT_GRAY = 5; - public const HORSE_VARIANT_DARK_BROWN = 6; - - public const HORSE_MARK_VARIANT_NONE = 0; - public const HORSE_MARK_VARIANT_WHITE = 1; - public const HORSE_MARK_VARIANT_WHITE_FIELD = 2; - public const HORSE_MARK_VARIANT_WHITE_DOTS = 3; - public const HORSE_MARK_VARIANT_BLACK_DOTS = 4; - - public $width = 1.4; - public $height = 1.6; - - /** @var HorseInventory */ - protected $inventory; - - public function getName() : string{ - return "Zombie Horse"; - } - - /** - * @return HorseInventory - */ - public function getInventory() : HorseInventory{ - return $this->inventory; - } - - protected function addBehaviors() : void{ - $this->behaviorPool->setBehavior(1, new FloatBehavior($this)); - $this->behaviorPool->setBehavior(2, new PanicBehavior($this, 1.25)); - $this->behaviorPool->setBehavior(3, new MateBehavior($this, 1.0)); - $this->behaviorPool->setBehavior(5, new FollowParentBehavior($this, 1.1)); - $this->behaviorPool->setBehavior(6, new RandomStrollBehavior($this, 1.0)); - $this->behaviorPool->setBehavior(7, new LookAtPlayerBehavior($this, 6.0)); - $this->behaviorPool->setBehavior(8, new RandomLookAroundBehavior($this)); - } - - protected function initEntity() : void{ - $this->setMaxHealth(15); - $this->setMovementSpeed($this->getModifiedMovementSpeed()); - $this->setJumpStrength($this->getModifiedJumpStrength()); - $this->setFollowRange(35); - - if($this->namedtag->hasTag("Variant", IntTag::class) and $this->namedtag->hasTag("MarkVariant", IntTag::class)){ - $this->setVariant($this->namedtag->getInt("Variant")); - $this->setMarkVariant($this->namedtag->getInt("MarkVariant")); - }else{ - $this->setVariant($this->random->nextBoundedInt(7)); - $this->setMarkVariant($this->random->nextBoundedInt(5)); - } - - $this->inventory = new HorseInventory($this); - - if($this->namedtag->hasTag("ArmorItem", CompoundTag::class)){ - $this->inventory->setArmor(Item::nbtDeserialize($this->namedtag->getCompoundTag("ArmorItem"))); - } - - if($this->namedtag->hasTag("SaddleItem", CompoundTag::class)){ - $this->inventory->setSaddle(Item::nbtDeserialize($this->namedtag->getCompoundTag("SaddleItem"))); - } - - parent::initEntity(); - } - - public function addAttributes() : void{ - parent::addAttributes(); - - $this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::HORSE_JUMP_STRENGTH)); - } - - public function getRiderSeatPosition(int $seatNumber = 0) : Vector3{ - return new Vector3(0, 1.1, -0.2); - } - - public function setSaddled(bool $value = true) : void{ - parent::setSaddled($value); - - $this->setGenericFlag(self::DATA_FLAG_CAN_POWER_JUMP, $value); - } - - public function onInteract(Player $player, Item $item, Vector3 $clickPos) : bool{ - if(!$this->isImmobile()){ - // TODO: feeding - - if($player->isSneaking()){ - if($this->isTamed()){ - $player->addWindow($this->inventory); - }else{ - $this->rearUp(); - } - - return true; - } - } - return parent::onInteract($player, $item, $clickPos); - } - - public function sendSpawnPacket(Player $player) : void{ - parent::sendSpawnPacket($player); - - $this->inventory->sendArmor($player); - } - - public function doHitAnimation() : void{ - parent::doHitAnimation(); - - foreach($this->getViewers() as $player){ // WTF - $this->inventory->sendArmor($player); - } - } - - public function saveNBT() : void{ - parent::saveNBT(); - - if($this->inventory !== null){ - $this->namedtag->setTag($this->inventory->getSaddle()->nbtSerialize(-1, "SaddleItem")); - $this->namedtag->setTag($this->inventory->getArmor()->nbtSerialize(-1, "ArmorItem")); - } - } - public - function getDrops(): array - { - return [ - ItemFactory::get(Item::ROTTEN_FLESH, 0, mt_rand(0, 2)) - ]; - } + public const NETWORK_ID = self::ZOMBIE_HORSE; + + public $width = 1.4; + public $height = 1.6; + + /** @var HorseInventory */ + protected $inventory; + + public function getName() : string{ + return "Zombie Horse"; + } + + /** + * @return HorseInventory + */ + public function getInventory() : HorseInventory{ + return $this->inventory; + } + + protected function addBehaviors() : void{ + $this->behaviorPool->setBehavior(1, new FloatBehavior($this)); + $this->behaviorPool->setBehavior(2, new PanicBehavior($this, 1.25)); + $this->behaviorPool->setBehavior(3, new MateBehavior($this, 1.0)); + $this->behaviorPool->setBehavior(5, new FollowParentBehavior($this, 1.1)); + $this->behaviorPool->setBehavior(6, new RandomStrollBehavior($this, 1.0)); + $this->behaviorPool->setBehavior(7, new LookAtPlayerBehavior($this, 6.0)); + $this->behaviorPool->setBehavior(8, new RandomLookAroundBehavior($this)); + } + + protected function initEntity() : void{ + $this->setMaxHealth(15); + $this->setMovementSpeed($this->getModifiedMovementSpeed()); + $this->setJumpStrength($this->getModifiedJumpStrength()); + $this->setFollowRange(35); + + $this->inventory = new HorseInventory($this); + + if($this->namedtag->hasTag("SaddleItem", CompoundTag::class)){ + $this->inventory->setSaddle(Item::nbtDeserialize($this->namedtag->getCompoundTag("SaddleItem"))); + } + + parent::initEntity(); + } + + public function addAttributes() : void{ + parent::addAttributes(); + + $this->attributeMap->addAttribute(Attribute::getAttribute(Attribute::HORSE_JUMP_STRENGTH)); + } + + public function getRiderSeatPosition(int $seatNumber = 0) : Vector3{ + return new Vector3(0, 1.1, -0.2); + } + + public function setSaddled(bool $value = true) : void{ + parent::setSaddled($value); + + $this->setGenericFlag(self::DATA_FLAG_CAN_POWER_JUMP, $value); + } + + public function onInteract(Player $player, Item $item, Vector3 $clickPos) : bool{ + if(!$this->isImmobile()){ + // TODO: feeding + + if($player->isSneaking()){ + if($this->isTamed()){ + $player->addWindow($this->inventory); + }else{ + $this->rearUp(); + } + + return true; + } + } + return parent::onInteract($player, $item, $clickPos); + } + + public function sendSpawnPacket(Player $player) : void{ + parent::sendSpawnPacket($player); + + $this->inventory->sendArmor($player); + } + + public function doHitAnimation() : void{ + parent::doHitAnimation(); + + foreach($this->getViewers() as $player){ // WTF + $this->inventory->sendArmor($player); + } + } + + public function saveNBT() : void{ + parent::saveNBT(); + + if($this->inventory !== null){ + $this->namedtag->setTag($this->inventory->getSaddle()->nbtSerialize(-1, "SaddleItem")); + $this->namedtag->setTag($this->inventory->getArmor()->nbtSerialize(-1, "ArmorItem")); + } + } + + public function getDrops() : array{ + return [ + ItemFactory::get(Item::ROTTEN_FLESH, 0, mt_rand(0, 2)) + ]; + } } \ No newline at end of file From f6aae91f46d255ea7225e498bd23b611a8c30443 Mon Sep 17 00:00:00 2001 From: EmreTr1 Date: Thu, 24 Oct 2019 20:23:48 +0300 Subject: [PATCH 16/22] New Mob AI Navigation system (not finished yet) --- src/pocketmine/entity/Mob.php | 24 +- .../entity/behavior/AvoidMobTypeBehavior.php | 11 +- .../entity/behavior/EatBlockBehavior.php | 2 +- .../entity/behavior/FleeSunBehavior.php | 4 +- .../entity/behavior/FloatBehavior.php | 1 - .../entity/behavior/FollowOwnerBehavior.php | 22 +- .../entity/behavior/FollowParentBehavior.php | 2 +- .../entity/behavior/MateBehavior.php | 2 +- .../entity/behavior/MeleeAttackBehavior.php | 11 +- .../entity/behavior/MountPathingBehavior.php | 2 +- .../entity/behavior/RandomStrollBehavior.php | 10 +- .../entity/behavior/RandomSwimBehavior.php | 79 ++ .../entity/behavior/RangedAttackBehavior.php | 6 +- .../entity/behavior/RestrictSunBehavior.php | 12 +- .../entity/behavior/SwimWanderBehavior.php | 70 ++ .../entity/behavior/TargetBehavior.php | 2 +- .../entity/behavior/TemptBehavior.php | 6 +- .../entity/helper/EntityLookHelper.php | 2 +- src/pocketmine/entity/hostile/Spider.php | 6 + .../entity/passive/TropicalFish.php | 83 +-- .../entity/pathfinder/EntityNavigator.php | 693 ------------------ src/pocketmine/entity/pathfinder/Path.php | 88 --- .../entity/pathfinder/PathPoint.php | 41 -- src/pocketmine/entity/pathfinding/Path.php | 82 +++ .../entity/pathfinding/PathEntity.php | 105 +++ .../entity/pathfinding/PathFinder.php | 131 ++++ .../entity/pathfinding/PathPoint.php | 66 ++ .../pathfinding/navigate/PathNavigate.php | 230 ++++++ .../navigate/PathNavigateClimber.php | 77 ++ .../navigate/PathNavigateGround.php | 258 +++++++ .../pathfinding/processor/NodeProcessor.php | 68 ++ .../processor/WalkNodeProcessor.php | 247 +++++++ 32 files changed, 1495 insertions(+), 948 deletions(-) create mode 100644 src/pocketmine/entity/behavior/RandomSwimBehavior.php create mode 100644 src/pocketmine/entity/behavior/SwimWanderBehavior.php delete mode 100644 src/pocketmine/entity/pathfinder/EntityNavigator.php delete mode 100644 src/pocketmine/entity/pathfinder/Path.php delete mode 100644 src/pocketmine/entity/pathfinder/PathPoint.php create mode 100644 src/pocketmine/entity/pathfinding/Path.php create mode 100644 src/pocketmine/entity/pathfinding/PathEntity.php create mode 100644 src/pocketmine/entity/pathfinding/PathFinder.php create mode 100644 src/pocketmine/entity/pathfinding/PathPoint.php create mode 100644 src/pocketmine/entity/pathfinding/navigate/PathNavigate.php create mode 100644 src/pocketmine/entity/pathfinding/navigate/PathNavigateClimber.php create mode 100644 src/pocketmine/entity/pathfinding/navigate/PathNavigateGround.php create mode 100644 src/pocketmine/entity/pathfinding/processor/NodeProcessor.php create mode 100644 src/pocketmine/entity/pathfinding/processor/WalkNodeProcessor.php diff --git a/src/pocketmine/entity/Mob.php b/src/pocketmine/entity/Mob.php index 0efdd188284..1d2e3d175ca 100644 --- a/src/pocketmine/entity/Mob.php +++ b/src/pocketmine/entity/Mob.php @@ -31,9 +31,9 @@ use pocketmine\entity\helper\EntityJumpHelper; use pocketmine\entity\helper\EntityLookHelper; use pocketmine\entity\helper\EntityMoveHelper; -use pocketmine\entity\pathfinder\EntityNavigator; +use pocketmine\entity\pathfinding\navigate\PathNavigate; +use pocketmine\entity\pathfinding\navigate\PathNavigateGround; use pocketmine\math\Vector3; -use pocketmine\nbt\tag\CompoundTag; use pocketmine\timings\Timings; use function abs; use function boolval; @@ -46,7 +46,7 @@ abstract class Mob extends Living{ protected $behaviorPool; /** @var BehaviorPool */ protected $targetBehaviorPool; - /** @var EntityNavigator */ + /** @var PathNavigate */ protected $navigator; /** @var Entity[] */ protected $seenEntities = []; @@ -154,7 +154,7 @@ protected function initEntity() : void{ $this->targetBehaviorPool = new BehaviorPool(); $this->behaviorPool = new BehaviorPool(); - $this->navigator = new EntityNavigator($this); + $this->navigator = $this->createNavigator(); $this->moveHelper = new EntityMoveHelper($this); $this->jumpHelper = new EntityJumpHelper($this); $this->lookHelper = new EntityLookHelper($this); @@ -191,7 +191,7 @@ protected function onBehaviorUpdate() : void{ Timings::$mobBehaviorUpdateTimer->stopTiming(); Timings::$mobNavigationUpdateTimer->startTiming(); - $this->navigator->onNavigateUpdate(); + $this->navigator->tick(); Timings::$mobNavigationUpdateTimer->stopTiming(); $this->moveHelper->onUpdate(); @@ -220,6 +220,10 @@ protected function onBehaviorUpdate() : void{ $this->bodyHelper->onUpdate(); } + protected function createNavigator() : PathNavigate{ + return new PathNavigateGround($this); + } + /** * @param Entity $target * @@ -231,8 +235,7 @@ public function canSeeEntity(Entity $target) : bool{ }elseif(in_array($target->getId(), $this->seenEntities)){ return true; }else{ - // TODO: Fix seen from corners - $canSee = $this->getNavigator()->isClearBetweenPoints($this, $target); + $canSee = $this->getNavigator()->isDirectPathBetweenPoints($this, $target, new Vector3($i = ceil($this->width + 0.25), $this->height + 1, $i)); if($canSee){ $this->seenEntities[] = $target->getId(); @@ -275,10 +278,7 @@ public function handleLavaJump() : void{ $this->motion->y += 0.04; } - /** - * @return EntityNavigator - */ - public function getNavigator() : EntityNavigator{ + public function getNavigator() : PathNavigate{ return $this->navigator; } @@ -308,7 +308,7 @@ public function updateLeashedState() : void{ } if($f > 4){ - $this->navigator->tryMoveTo($entity, 1.0); + $this->navigator->tryMoveToEntity($entity, 1.0); } if($f > 6){ diff --git a/src/pocketmine/entity/behavior/AvoidMobTypeBehavior.php b/src/pocketmine/entity/behavior/AvoidMobTypeBehavior.php index 4610e281b72..aaf3f69e7c6 100644 --- a/src/pocketmine/entity/behavior/AvoidMobTypeBehavior.php +++ b/src/pocketmine/entity/behavior/AvoidMobTypeBehavior.php @@ -67,7 +67,7 @@ public function canStart() : bool{ $vec = RandomPositionGenerator::findRandomTargetBlockAwayFrom($this->mob, 16, 7, $nearest); if($vec !== null and $nearest->distanceSquared($vec) >= $nearest->distanceSquared($this->mob)){ - $this->path = $this->mob->getNavigator()->findPath($vec); + $this->path = $this->mob->getNavigator()->getPathToPos($vec); return $this->path !== null; } @@ -77,19 +77,18 @@ public function canStart() : bool{ } public function canContinue() : bool{ - return $this->mob->getNavigator()->isBusy(); + return !$this->mob->getNavigator()->noPath(); } public function onStart() : void{ - $this->mob->getNavigator()->setPath($this->path); - $this->mob->getNavigator()->setSpeedMultiplier($this->farSpeed); + $this->mob->getNavigator()->setPath($this->path, $this->farSpeed); } public function onTick() : void{ if($this->mob->distanceSquared($this->nearestEntity) < 49){ - $this->mob->getNavigator()->setSpeedMultiplier($this->nearSpeed); + $this->mob->getNavigator()->setSpeed($this->nearSpeed); }else{ - $this->mob->getNavigator()->setSpeedMultiplier($this->farSpeed); + $this->mob->getNavigator()->setSpeed($this->farSpeed); } } diff --git a/src/pocketmine/entity/behavior/EatBlockBehavior.php b/src/pocketmine/entity/behavior/EatBlockBehavior.php index 008de8082d9..8bfe3805afe 100644 --- a/src/pocketmine/entity/behavior/EatBlockBehavior.php +++ b/src/pocketmine/entity/behavior/EatBlockBehavior.php @@ -51,7 +51,7 @@ public function canStart() : bool{ public function onStart() : void{ $this->mob->broadcastEntityEvent(ActorEventPacket::EAT_GRASS_ANIMATION); $this->duration = 40; - $this->mob->getNavigator()->clearPath(); + $this->mob->getNavigator()->clearPathEntity(); } public function canContinue() : bool{ diff --git a/src/pocketmine/entity/behavior/FleeSunBehavior.php b/src/pocketmine/entity/behavior/FleeSunBehavior.php index 6ab20ec9bf9..279a05b8365 100644 --- a/src/pocketmine/entity/behavior/FleeSunBehavior.php +++ b/src/pocketmine/entity/behavior/FleeSunBehavior.php @@ -54,11 +54,11 @@ public function canStart() : bool{ } public function onStart() : void{ - $this->mob->getNavigator()->tryMoveTo($this->shelter, $this->speedMultiplier); + $this->mob->getNavigator()->tryMoveToPos($this->shelter, $this->speedMultiplier); } public function canContinue() : bool{ - return $this->mob->getNavigator()->isBusy(); + return !$this->mob->getNavigator()->noPath(); } public function findPossibleShelter() : ?Block{ diff --git a/src/pocketmine/entity/behavior/FloatBehavior.php b/src/pocketmine/entity/behavior/FloatBehavior.php index 3147562cc8a..b7083d88d61 100644 --- a/src/pocketmine/entity/behavior/FloatBehavior.php +++ b/src/pocketmine/entity/behavior/FloatBehavior.php @@ -25,7 +25,6 @@ namespace pocketmine\entity\behavior; use pocketmine\entity\Mob; -use pocketmine\math\Vector3; class FloatBehavior extends Behavior{ diff --git a/src/pocketmine/entity/behavior/FollowOwnerBehavior.php b/src/pocketmine/entity/behavior/FollowOwnerBehavior.php index 260c5d9fdb8..75797279bb5 100644 --- a/src/pocketmine/entity/behavior/FollowOwnerBehavior.php +++ b/src/pocketmine/entity/behavior/FollowOwnerBehavior.php @@ -25,10 +25,10 @@ namespace pocketmine\entity\behavior; use pocketmine\entity\Entity; +use pocketmine\entity\pathfinding\navigate\PathNavigateGround; use pocketmine\entity\Tamable; use pocketmine\Player; - class FollowOwnerBehavior extends Behavior{ /** @var float */ @@ -66,11 +66,15 @@ public function canStart() : bool{ public function onStart() : void{ $this->followDelay = 0; - $this->mob->getNavigator()->setAvoidsWater(false); + + $navigator = $this->mob->getNavigator(); + if($navigator instanceof PathNavigateGround){ + $navigator->setAvoidsWater(true); + } } public function canContinue() : bool{ - return $this->mob->getNavigator()->isBusy() and $this->mob->distanceSquared($this->owner) > ($this->maxDistance ** 2) and !$this->mob->isSitting(); + return !$this->mob->getNavigator()->noPath() and $this->mob->distanceSquared($this->owner) > ($this->maxDistance ** 2) and !$this->mob->isSitting(); } public function onTick() : void{ @@ -80,12 +84,12 @@ public function onTick() : void{ if(--$this->followDelay <= 0){ $this->followDelay = 10; - $this->mob->getNavigator()->tryMoveTo($this->owner, $this->speedMultiplier); + $this->mob->getNavigator()->tryMoveToEntity($this->owner, $this->speedMultiplier); if(!$this->mob->isLeashed()){ if($this->mob->distanceSquared($this->owner) > 144){ $this->mob->teleport($this->owner); - $this->mob->getNavigator()->clearPath(true); + $this->mob->getNavigator()->clearPathEntity(); } } } @@ -93,8 +97,12 @@ public function onTick() : void{ } public function onEnd() : void{ - $this->mob->getNavigator()->clearPath(true); + $this->mob->getNavigator()->clearPathEntity(); $this->owner = null; - $this->mob->getNavigator()->setAvoidsWater(true); + + $navigator = $this->mob->getNavigator(); + if($navigator instanceof PathNavigateGround){ + $navigator->setAvoidsWater(true); + } } } \ No newline at end of file diff --git a/src/pocketmine/entity/behavior/FollowParentBehavior.php b/src/pocketmine/entity/behavior/FollowParentBehavior.php index 03ae9f0f521..0fb6bf56cbb 100644 --- a/src/pocketmine/entity/behavior/FollowParentBehavior.php +++ b/src/pocketmine/entity/behavior/FollowParentBehavior.php @@ -79,7 +79,7 @@ public function onStart() : void{ public function onTick() : void{ if($this->delay-- <= 0){ $this->delay = 10; - $this->mob->getNavigator()->tryMoveTo($this->parentAnimal, $this->speedMultiplier); + $this->mob->getNavigator()->tryMoveToEntity($this->parentAnimal, $this->speedMultiplier); } } diff --git a/src/pocketmine/entity/behavior/MateBehavior.php b/src/pocketmine/entity/behavior/MateBehavior.php index 02392e07f40..696c5c7d17d 100644 --- a/src/pocketmine/entity/behavior/MateBehavior.php +++ b/src/pocketmine/entity/behavior/MateBehavior.php @@ -58,7 +58,7 @@ public function canContinue() : bool{ public function onTick() : void{ $this->mob->getLookHelper()->setLookPositionWithEntity($this->targetMate, 10, $this->mob->getVerticalFaceSpeed()); - $this->mob->getNavigator()->tryMoveTo($this->targetMate, $this->speedMultiplier); + $this->mob->getNavigator()->tryMoveToEntity($this->targetMate, $this->speedMultiplier); $this->spawnBabyDelay++; diff --git a/src/pocketmine/entity/behavior/MeleeAttackBehavior.php b/src/pocketmine/entity/behavior/MeleeAttackBehavior.php index 0f52c0bdb71..85b10dc66b5 100644 --- a/src/pocketmine/entity/behavior/MeleeAttackBehavior.php +++ b/src/pocketmine/entity/behavior/MeleeAttackBehavior.php @@ -57,14 +57,13 @@ public function canStart() : bool{ $this->lastPlayerPos = $target->asVector3(); - $this->path = $this->mob->getNavigator()->findPath($target); - return $this->path->havePath(); + $this->path = $this->mob->getNavigator()->getPathToEntity($target); + return $this->path !== null; } public function onStart() : void{ $this->delay = 0; - $this->mob->getNavigator()->setPath($this->path); - $this->mob->getNavigator()->setSpeedMultiplier($this->speedMultiplier); + $this->mob->getNavigator()->setPath($this->path, $this->speedMultiplier); } public function canContinue() : bool{ @@ -95,7 +94,7 @@ public function onTick() : void{ $this->delay += 5; } - if(!$this->mob->getNavigator()->tryMoveTo($target, $this->speedMultiplier)){ + if(!$this->mob->getNavigator()->tryMoveToEntity($target, $this->speedMultiplier)){ $this->delay += 15; } } @@ -118,7 +117,7 @@ public function onEnd() : void{ $this->mob->pitch = 0; $this->attackCooldown = $this->delay = 0; $this->path = null; - $this->mob->getNavigator()->clearPath(); + $this->mob->getNavigator()->clearPathEntity(); } } diff --git a/src/pocketmine/entity/behavior/MountPathingBehavior.php b/src/pocketmine/entity/behavior/MountPathingBehavior.php index 839b24576f8..99de7f30bc4 100644 --- a/src/pocketmine/entity/behavior/MountPathingBehavior.php +++ b/src/pocketmine/entity/behavior/MountPathingBehavior.php @@ -51,7 +51,7 @@ public function onTick() : void{ $pos = RandomPositionGenerator::findRandomTargetBlock($this->mob, 10, 7); if($pos !== null){ - $this->mob->getNavigator()->tryMoveTo($pos, 1, $this->mob->distanceSquared($pos) + 2); + $this->mob->getNavigator()->tryMoveToPos($pos, 1); } } diff --git a/src/pocketmine/entity/behavior/RandomStrollBehavior.php b/src/pocketmine/entity/behavior/RandomStrollBehavior.php index b87c9703948..2e483c64536 100644 --- a/src/pocketmine/entity/behavior/RandomStrollBehavior.php +++ b/src/pocketmine/entity/behavior/RandomStrollBehavior.php @@ -30,7 +30,7 @@ class RandomStrollBehavior extends Behavior{ /** @var float */ - protected $speedMultiplier = 1.0, $followRange = 16.0; + protected $speedMultiplier = 1.0; /** @var int */ protected $chance = 120; @@ -50,8 +50,6 @@ public function canStart() : bool{ if($pos === null) return false; - $this->followRange = $this->mob->distanceSquared($pos) + 2; - $this->targetPos = $pos; return true; @@ -61,15 +59,15 @@ public function canStart() : bool{ } public function canContinue() : bool{ - return $this->mob->getNavigator()->isBusy(); + return !$this->mob->getNavigator()->noPath(); } public function onStart() : void{ - $this->mob->getNavigator()->tryMoveTo($this->targetPos, $this->speedMultiplier, $this->followRange); + $this->mob->getNavigator()->tryMoveToPos($this->targetPos, $this->speedMultiplier); } public function onEnd() : void{ $this->targetPos = null; - $this->mob->getNavigator()->clearPath(); + $this->mob->getNavigator()->clearPathEntity(); } } \ No newline at end of file diff --git a/src/pocketmine/entity/behavior/RandomSwimBehavior.php b/src/pocketmine/entity/behavior/RandomSwimBehavior.php new file mode 100644 index 00000000000..38870769772 --- /dev/null +++ b/src/pocketmine/entity/behavior/RandomSwimBehavior.php @@ -0,0 +1,79 @@ +speedMultiplier = $speedMultiplier; + $this->interval = $interval; + $this->xzDist = $xzDist; + $this->yDist = $yDist; + + $this->mutexBits = 1; + } + + public function canStart() : bool{ + if($this->interval <= 0 or $this->random->nextBoundedInt($this->interval) === 0){ + $pos = RandomPositionGenerator::findRandomTargetBlock($this->mob, $this->xzDist, $this->yDist); + + if($pos instanceof Water){ + $this->targetPos = $pos; + + return true; + } + } + + return false; + } + + public function canContinue() : bool{ + return !$this->mob->getNavigator()->noPath(); + } + + public function onStart() : void{ + $this->mob->getNavigator()->tryMoveToPos($this->targetPos, $this->speedMultiplier); + } + + public function onEnd() : void{ + $this->targetPos = null; + $this->mob->getNavigator()->clearPathEntity(); + } +} \ No newline at end of file diff --git a/src/pocketmine/entity/behavior/RangedAttackBehavior.php b/src/pocketmine/entity/behavior/RangedAttackBehavior.php index 88de9970b1c..b19d5975aa7 100644 --- a/src/pocketmine/entity/behavior/RangedAttackBehavior.php +++ b/src/pocketmine/entity/behavior/RangedAttackBehavior.php @@ -70,7 +70,7 @@ public function canStart() : bool{ } public function canContinue() : bool{ - return $this->canStart() or $this->mob->getNavigator()->isBusy(); + return $this->canStart() or !$this->mob->getNavigator()->noPath(); } public function onEnd() : void{ @@ -89,9 +89,9 @@ public function onTick() : void{ } if($dist <= $this->maxAttackDistance and $this->targetSeenTicks >= 20){ - $this->mob->getNavigator()->clearPath(); + $this->mob->getNavigator()->clearPathEntity(); }else{ - $this->mob->getNavigator()->tryMoveTo($this->attackTarget, $this->speedMultiplier); + $this->mob->getNavigator()->tryMoveToEntity($this->attackTarget, $this->speedMultiplier); } $this->mob->getLookHelper()->setLookPositionWithEntity($this->attackTarget, 30, 30); diff --git a/src/pocketmine/entity/behavior/RestrictSunBehavior.php b/src/pocketmine/entity/behavior/RestrictSunBehavior.php index e712c462691..140de31da44 100644 --- a/src/pocketmine/entity/behavior/RestrictSunBehavior.php +++ b/src/pocketmine/entity/behavior/RestrictSunBehavior.php @@ -24,6 +24,8 @@ namespace pocketmine\entity\behavior; +use pocketmine\entity\pathfinding\navigate\PathNavigateGround; + class RestrictSunBehavior extends Behavior{ public function canStart() : bool{ @@ -31,10 +33,16 @@ public function canStart() : bool{ } public function onStart() : void{ - $this->mob->getNavigator()->setAvoidsSun(true); + $navigator = $this->mob->getNavigator(); + if($navigator instanceof PathNavigateGround){ + $navigator->setAvoidSun(true); + } } public function onEnd() : void{ - $this->mob->getNavigator()->setAvoidsSun(false); + $navigator = $this->mob->getNavigator(); + if($navigator instanceof PathNavigateGround){ + $navigator->setAvoidSun(false); + } } } \ No newline at end of file diff --git a/src/pocketmine/entity/behavior/SwimWanderBehavior.php b/src/pocketmine/entity/behavior/SwimWanderBehavior.php new file mode 100644 index 00000000000..cd98891a838 --- /dev/null +++ b/src/pocketmine/entity/behavior/SwimWanderBehavior.php @@ -0,0 +1,70 @@ +speedMultiplier = $speedMultiplier; + $this->interval = $interval; + $this->lookAhead = $lookAhead; + + $this->mutexBits = 1; + } + + public function canStart() : bool{ + return $this->random->nextBoundedInt($this->interval) === 0; + } + + public function canContinue() : bool{ + return $this->lookAhead > 0; + } + + public function onStart() : void{ + $this->mob->pitch = 0; + $this->mob->yaw = $this->random->nextFloat() * 360; + $this->mob->setMoveForward($speed = $this->speedMultiplier * $this->mob->getMovementSpeed()); + $this->mob->setAIMoveSpeed($speed); + } + + public function onTick() : void{ + $this->lookAhead -= 0.1; + } + + public function onEnd() : void{ + $this->mob->setMoveForward(0.0); + } +} \ No newline at end of file diff --git a/src/pocketmine/entity/behavior/TargetBehavior.php b/src/pocketmine/entity/behavior/TargetBehavior.php index a8ad42fb3cf..708bc8823a1 100644 --- a/src/pocketmine/entity/behavior/TargetBehavior.php +++ b/src/pocketmine/entity/behavior/TargetBehavior.php @@ -115,7 +115,7 @@ public function isSuitableTargetLocal(Living $target, bool $includeInvisibles) : private function canEasilyReach(Living $entity) : bool{ $this->targetSearchDelay = 10 + $this->mob->random->nextBoundedInt(5); - $path = $this->mob->getNavigator()->findPath($entity); + $path = $this->mob->getNavigator()->getPathToEntity($entity); if($path == null){ return false; diff --git a/src/pocketmine/entity/behavior/TemptBehavior.php b/src/pocketmine/entity/behavior/TemptBehavior.php index bc315730517..101a981a176 100644 --- a/src/pocketmine/entity/behavior/TemptBehavior.php +++ b/src/pocketmine/entity/behavior/TemptBehavior.php @@ -83,9 +83,9 @@ public function onTick() : void{ $this->mob->getLookHelper()->setLookPositionWithEntity($this->temptingPlayer, 30, $this->mob->getVerticalFaceSpeed()); if($this->temptingPlayer->distanceSquared($this->mob) < 6.25){ - $this->mob->getNavigator()->clearPath(); + $this->mob->getNavigator()->clearPathEntity(); }else{ - $this->mob->getNavigator()->tryMoveTo($this->temptingPlayer, $this->speedMultiplier); + $this->mob->getNavigator()->tryMoveToEntity($this->temptingPlayer, $this->speedMultiplier); } } @@ -93,6 +93,6 @@ public function onEnd() : void{ $this->delayTemptCounter = 100; $this->temptingPlayer = null; $this->mob->pitch = 0; - $this->mob->getNavigator()->clearPath(); + $this->mob->getNavigator()->clearPathEntity(); } } \ No newline at end of file diff --git a/src/pocketmine/entity/helper/EntityLookHelper.php b/src/pocketmine/entity/helper/EntityLookHelper.php index 16564235708..4663f681c55 100644 --- a/src/pocketmine/entity/helper/EntityLookHelper.php +++ b/src/pocketmine/entity/helper/EntityLookHelper.php @@ -74,7 +74,7 @@ public function onUpdate() : void{ $this->entity->headYaw = $this->updateRotation($this->entity->headYaw, $this->entity->yawOffset, 10); } $f2 = self::wrapAngleTo180($this->entity->headYaw - $this->entity->yawOffset); - if($this->entity->getNavigator()->isBusy()){ + if(!$this->entity->getNavigator()->noPath()){ if($f2 < -75){ $this->entity->headYaw = $this->entity->yawOffset - 75; } diff --git a/src/pocketmine/entity/hostile/Spider.php b/src/pocketmine/entity/hostile/Spider.php index 4cd0fb4ba9e..5faa425dfff 100644 --- a/src/pocketmine/entity/hostile/Spider.php +++ b/src/pocketmine/entity/hostile/Spider.php @@ -33,6 +33,8 @@ use pocketmine\entity\behavior\RandomLookAroundBehavior; use pocketmine\entity\behavior\RandomStrollBehavior; use pocketmine\entity\Monster; +use pocketmine\entity\pathfinding\navigate\PathNavigate; +use pocketmine\entity\pathfinding\navigate\PathNavigateClimber; use pocketmine\item\Item; use pocketmine\item\ItemFactory; use pocketmine\Player; @@ -56,6 +58,10 @@ protected function initEntity() : void{ parent::initEntity(); } + protected function createNavigator() : PathNavigate{ + return new PathNavigateClimber($this); + } + public function getName() : string{ return "Spider"; } diff --git a/src/pocketmine/entity/passive/TropicalFish.php b/src/pocketmine/entity/passive/TropicalFish.php index 4f518fca403..135610dd7ba 100644 --- a/src/pocketmine/entity/passive/TropicalFish.php +++ b/src/pocketmine/entity/passive/TropicalFish.php @@ -23,19 +23,16 @@ namespace pocketmine\entity\passive; +use pocketmine\entity\behavior\AvoidMobTypeBehavior; +use pocketmine\entity\behavior\RandomSwimBehavior; +use pocketmine\entity\behavior\SwimWanderBehavior; use pocketmine\entity\WaterAnimal; -use pocketmine\event\entity\EntityDamageByEntityEvent; -use pocketmine\event\entity\EntityDamageEvent; use pocketmine\item\Item; use pocketmine\item\ItemFactory; -use pocketmine\math\Vector3; use pocketmine\nbt\tag\ByteTag; use pocketmine\nbt\tag\IntTag; -use pocketmine\network\mcpe\protocol\ActorEventPacket; -use function atan2; +use pocketmine\Player; use function mt_rand; -use function sqrt; -use const M_PI; class TropicalFish extends WaterAnimal{ public const NETWORK_ID = self::TROPICAL_FISH; @@ -69,12 +66,6 @@ class TropicalFish extends WaterAnimal{ public $width = 0.4; public $height = 0.4; - /** @var Vector3 */ - public $swimDirection = null; - public $swimSpeed = 0.1; - - private $switchDirectionTicker = 0; - public function initEntity() : void{ $this->setMaxHealth(6); @@ -105,70 +96,18 @@ public function initEntity() : void{ $this->setMovementSpeed(0.12); parent::initEntity(); - } - - public function getName() : string{ - return "Tropical Fish"; - } - public function attack(EntityDamageEvent $source) : void{ - parent::attack($source); - if($source->isCancelled()){ - return; - } - - if($source instanceof EntityDamageByEntityEvent){ - $this->swimSpeed = mt_rand(150, 350) / 2000; - $e = $source->getDamager(); - if($e !== null){ - $this->swimDirection = (new Vector3($this->x - $e->x, $this->y - $e->y, $this->z - $e->z))->normalize(); - } - } + $this->navigator->setAvoidsWater(false); } - private function generateRandomDirection() : Vector3{ - return new Vector3(mt_rand(-1000, 1000) / 1000, mt_rand(-500, 500) / 1000, mt_rand(-1000, 1000) / 1000); + protected function addBehaviors() : void{ + $this->behaviorPool->setBehavior(1, new AvoidMobTypeBehavior($this, Player::class, null, 6, 1.5, 2.0)); + $this->behaviorPool->setBehavior(3, new RandomSwimBehavior($this, 1.0, 16, 4, 0)); + $this->behaviorPool->setBehavior(4, new SwimWanderBehavior($this, 1.0)); } - - public function entityBaseTick(int $tickDiff = 1) : bool{ - if($this->closed){ - return false; - } - - if(++$this->switchDirectionTicker === 100 or $this->isCollided){ - $this->switchDirectionTicker = 0; - if(mt_rand(0, 100) < 50){ - $this->swimDirection = null; - } - } - - $hasUpdate = parent::entityBaseTick($tickDiff); - - if($this->isAlive()){ - - if($this->y > 62 and $this->swimDirection !== null){ - $this->swimDirection->y = -0.5; - } - - $inWater = $this->isUnderwater(); - if(!$inWater){ - $this->swimDirection = null; - }elseif($this->swimDirection !== null){ - if($this->motion->lengthSquared() <= $this->swimDirection->lengthSquared()){ - $this->motion = $this->swimDirection->multiply($this->swimSpeed); - } - }else{ - $this->swimDirection = $this->generateRandomDirection(); - $this->swimSpeed = 0.05; - } - - $f = sqrt(($this->motion->x ** 2) + ($this->motion->z ** 2)); - $this->yaw = (-atan2($this->motion->x, $this->motion->z) * 180 / M_PI); - $this->pitch = (-atan2($f, $this->motion->y) * 180 / M_PI); - } - - return $hasUpdate; + public function getName() : string{ + return "Tropical Fish"; } public function getDrops() : array{ diff --git a/src/pocketmine/entity/pathfinder/EntityNavigator.php b/src/pocketmine/entity/pathfinder/EntityNavigator.php deleted file mode 100644 index fd434b35928..00000000000 --- a/src/pocketmine/entity/pathfinder/EntityNavigator.php +++ /dev/null @@ -1,693 +0,0 @@ -mob = $mob; - } - - /** - * @param PathPoint $from - * @param PathPoint $to - * @param float|null $followRange - * - * @return array - */ - public function navigate(PathPoint $from, PathPoint $to, ?float $followRange = null) : array{ - Timings::$mobPathFindingTimer->startTiming(); - - if($followRange === null){ - $followRange = $this->mob->getFollowRange(); - } - if($followRange <= 0){ - $followRange = 20; //base - } - $blockCache = []; - $ticks = 0; - $from->fScore = $this->calculateGridDistance($from, $to); - $last = $from; - $path = []; - $open = [$from->getHashCode() => $from]; - $currentY = $this->getUsableYCoordinate(); - $closed = []; - $highScore = $from; - - while(!empty($open)){ - $current = $last; - if($last !== $highScore){ - uasort($open, function($a, $b){ - if($a->fScore == $b->fScore) return 0; - - return $a->fScore > $b->fScore ? 1 : -1; - }); - $current = reset($open); - $currentY = $this->getBlockByPoint($current, $blockCache)->y; - } - - $last = null; - - if($current->equals($to)){ - return $this->initPath($path, $current); - } - if($ticks++ > $followRange * 2){ - return $this->initPath($path, $highScore); - } - - unset($open[$current->getHashCode()]); - $closed[$current->getHashCode()] = $current; - - foreach($this->getNeighbors($current, $blockCache, $currentY) as $n){ - if(!isset($closed[$n->getHashCode()])){ - $g = $current->gScore + $this->calculateBlockDistance($current, $n, $blockCache); - if($g >= $followRange){ - return $this->initPath($path, $highScore); - } - - if(isset($open[$n->getHashCode()])){ - $og = $open[$n->getHashCode()]; - if($g >= $og->gScore) continue; - } - $open[$n->getHashCode()] = $n; - $path[$n->getHashCode()] = $current; - - $n->gScore = $g; - $n->fScore = $g + $this->calculateGridDistance($n, $to); - - if($n->fScore <= $highScore->fScore){ - $highScore = $n; - $last = $n; - } - } - } - if($last !== null){ - $currentY = $this->getBlockByPoint($last, $blockCache)->y; - } - } - - Timings::$mobPathFindingTimer->stopTiming(); - - return []; - } - - /** - * @return int - */ - public function getUsableYCoordinate() : int{ - switch($this->processorType){ - case self::PROCESSOR_TYPE_WALK: - $y = $this->mob->getFloorY(); - - if($this->mob->isSwimmer()){ - $currentBlock = $this->mob->level->getBlock($this->mob); - $attempts = 0; - while($currentBlock instanceof Water and $attempts++ < 10){ - $currentBlock = $currentBlock->getSide(Vector3::SIDE_UP); - $y++; - } - } - - return $y; - default: - return $this->mob->getFloorY(); - } - } - - /** - * @param array $path - * @param PathPoint $current - * - * @return array - */ - public function initPath(array $path, PathPoint $current){ - $totalPath = [$current]; - while(isset($path[$current->getHashCode()])){ - $current = $path[$current->getHashCode()]; - array_unshift($totalPath, $current); - } - unset($totalPath[0]); - - Timings::$mobPathFindingTimer->stopTiming(); - - return array_values($totalPath); - } - - /** - * @param PathPoint $from - * @param PathPoint $to - * - * @return float - */ - public function calculateGridDistance(PathPoint $from, PathPoint $to) : float{ - return abs($from->x - $to->x) + abs($from->y - $to->y); - } - - /** - * @param PathPoint $from - * @param PathPoint $to - * @param array $cache - * - * @return float - */ - public function calculateBlockDistance(PathPoint $from, PathPoint $to, array $cache) : float{ - $block1 = $this->getBlockByPoint($from, $cache); - $block2 = $this->getBlockByPoint($to, $cache); - - if($block1 === null or $block2 === null){ - return 0; - }else{ - $block1 = $block1->asVector3(); - $block2 = $block2->asVector3(); - } - - if($this->mob->canClimb()){ - $block1->y = $block2->y = 0; - } - - return $block1->distanceSquared($block2); - } - - /** - * @param PathPoint $tile - * @param array $cache - * - * @return null|Block - */ - public function getBlockByPoint(PathPoint $tile, array $cache) : ?Block{ - return $cache[$tile->getHashCode()] ?? null; - } - - /** - * @param PathPoint $tile - * @param array $cache - * @param int $startY - * - * @return Vector2[] - */ - public function getNeighbors(PathPoint $tile, array &$cache, int $startY) : array{ - $block = $this->mob->level->getBlock(new Vector3($tile->x, $startY, $tile->y)); - - if(!isset($cache[$tile->getHashCode()])){ - $cache[$tile->getHashCode()] = $block; - } - - $list = []; - for($index = 0; $index < count($this->neighbors); ++$index){ - $item = new PathPoint($tile->x + $this->neighbors[$index][0], $tile->y + $this->neighbors[$index][1]); - // Check for too high steps - - $coord = new Vector3((int) $item->x, $block->y, (int) $item->y); - $tb = $this->mob->level->getBlock($coord); - if(!$tb->isPassable()){ - if(!$this->canJumpAt($block)){ - continue; // can't jump because top block is solid - } - - if($this->mob->canClimb() or $this->mob->isSwimmer() or $this->mob->canFly()){ - $blockUp = $this->mob->level->getBlock($coord->getSide(Vector3::SIDE_UP)); - $canMove = false; - for($i = 0; $i < 10; $i++){ - if($this->isBlocked($blockUp->asVector3())){ - $blockUp = $this->mob->level->getBlock($blockUp->getSide(Vector3::SIDE_UP)); - continue; - } - - $canMove = true; - break; - } - - if(!$canMove or $this->isObstructed($blockUp)) continue; - - $cache[$item->getHashCode()] = $blockUp; - }else{ - $blockUp = $this->mob->level->getBlock($coord->getSide(Vector3::SIDE_UP)); - if(!$blockUp->isPassable()){ - // Can't jump - continue; - } - - if($this->isObstructed($blockUp)) continue; - - $cache[$item->getHashCode()] = $blockUp; - } - }else{ - $blockDown = $this->mob->level->getBlock($coord->down()); - if(!$blockDown->isSolid() and !$this->mob->isSwimmer() and !($blockDown instanceof Liquid) and !$this->mob->canFly()){ // TODO: bug? - if($this->mob->canClimb()){ - $canClimb = false; - $blockDown = $this->mob->level->getBlock($blockDown->getSide(Vector3::SIDE_DOWN)); - for($i = 0; $i < 10; $i++){ - if(!$blockDown->isSolid()){ - $blockDown = $this->mob->level->getBlock($blockDown->add(0, -1, 0)); - continue; - } - - $canClimb = true; - break; - } - - if(!$canClimb) continue; - - $blockDown = $this->mob->level->getBlock($blockDown->getSide(Vector3::SIDE_UP)); - - if($this->isObstructed($blockDown)) continue; - - $cache[$item->getHashCode()] = $blockDown; - }else{ - if(!$this->mob->level->getBlock($coord->getSide(Vector3::SIDE_DOWN, 2))->isSolid()){ - // Will fall - continue; - } - - if($this->isObstructed($blockDown)) continue; - - $cache[$item->getHashCode()] = $blockDown; - } - }else{ - if($this->isObstructed($coord) or (!$this->mob->isSwimmer() and $this->avoidsWater and $blockDown instanceof Liquid)) continue; - - $cache[$item->getHashCode()] = $block; - } - } - $item->height = $cache[$item->getHashCode()]->y; - $list[$index] = $item; - } - - $this->checkDiagonals($list); - - return $list; - } - - /** - * @param array $list - */ - public function checkDiagonals(array &$list) : void{ - $checkDiagonals = [ - 0 => [ - 4, 5 - ], 1 => [ - 5, 6 - ], 2 => [ - 6, 7 - ], 3 => [ - 4, 7 - ] - ]; - - foreach($checkDiagonals as $index => $diagonal){ - if(!isset($list[$index])){ - foreach($diagonal as $dia){ - unset($list[$dia]); - } - } - } - } - - /** - * @param Vector3 $coord - * - * @return bool - */ - public function isObstructed(Vector3 $coord) : bool{ - for($i = 1; $i < $this->mob->height; $i++) if($this->isBlocked($coord->add(0, $i, 0))) return true; - - return false; - } - - /** - * @param Vector3 $pos - * - * @return bool - */ - public function canJumpAt(Vector3 $pos) : bool{ - for($i = 1; $i < $this->mob->height + 1; $i++){ - if($this->isBlocked($pos->add(0, $i, 0))) return false; - } - return true; - } - - /** - * @param Vector3 $coord - * - * @return bool - */ - public function isBlocked(Vector3 $coord) : bool{ - $block = $this->mob->level->getBlock($coord); - return !$block->isPassable(); - } - - /** - * Removes sunny path from current path - */ - public function removeSunnyPath() : void{ - if($this->avoidsSun and $this->mob->level->isDayTime()){ - if($this->mob->level->canSeeSky($this->mob)){ - return; - } - - $temp = new Vector3(); - foreach($this->currentPath->getPoints() as $i => $point){ - if($this->mob->level->canSeeSky($temp->setComponents($point->x, $point->height, $point->y))){ - $this->currentPath->limitPath($i - 1); - return; - } - } - } - } - - /** - * Follows current path by index - */ - public function pathFollow() : void{ - if($this->currentPath !== null){ - $length = count($this->currentPath->getPoints()) - 1; - - for($i = $this->currentPath->getCurrentIndex(); $i < count($this->currentPath->getPoints()); ++$i){ - if($this->currentPath->getPointByIndex($i)->height != (int) floor($this->mob->y)){ - $length = $i; - break; - } - } - - $currentPoint = $this->currentPath->getPointByIndex($this->currentPath->getCurrentIndex()); - if(floor($this->mob->x) == $currentPoint->x and floor($this->mob->z) == $currentPoint->y){ - $this->currentPath->setCurrentIndex($this->currentPath->getCurrentIndex() + 1); - } - - for($a = $length; $a >= $this->currentPath->getCurrentIndex(); --$a){ - $vec = $this->currentPath->getVectorByIndex($a); - $vec->y = floor($this->mob->y); - if($this->isClearBetweenPoints($this->mob->floor(), $vec)){ - $this->currentPath->setCurrentIndex($a); - break; - } - } - } - } - - /** - * @param Vector3 $from - * @param Vector3 $to - * @param bool $onlySee - * - * @return bool - */ - public function isClearBetweenPoints(Vector3 $from, Vector3 $to, bool $onlySee = false) : bool{ - $entityPos = $from; - $targetPos = $to; - $distance = $entityPos->distance($targetPos); - $rayPos = $entityPos; - $direction = $targetPos->subtract($entityPos)->normalize(); - - if($distance < $direction->length()){ - return true; - } - - do{ - if(!$this->isSafeToStandAt($rayPos->floor(), $onlySee)){ - return false; - } - $rayPos = $rayPos->add($direction); - }while($distance > $entityPos->distance($rayPos)); - - return true; - } - - /** - * @param Vector3 $pos - * @param bool $onlySee - * - * @return bool - */ - public function isSafeToStandAt(Vector3 $pos, bool $onlySee = false) : bool{ - if($this->isObstructed($pos) and !$onlySee){ - return false; - }elseif($this->isBlocked($pos)){ - return false; - }elseif(!$onlySee){ - $block = $this->mob->level->getBlockAt($pos->x, $pos->y - 1, $pos->z); - if(($block instanceof Water and !$this->mob->isSwimmer() and !$this->mob->canFly() and $this->avoidsWater) or $block instanceof Lava){ // TODO: Implement this for ZombiePigman and LavaSlime - return false; - }else{ - return true; - } - } - return true; - } - - /** - * @param Path $path - */ - public function setPath(Path $path) : void{ - $this->currentPath = $path; - $this->removeSunnyPath(); - } - - /** - * @return null|Path - */ - public function getPath() : ?Path{ - return $this->currentPath; - } - - /** - * @return bool - */ - public function havePath() : bool{ - return $this->currentPath !== null and $this->currentPath->havePath(); - } - - /** - * @return bool - */ - public function isBusy() : bool{ - return $this->havePath() or $this->movePoint !== null; - } - - /** - * @param bool $all - */ - public function clearPath(bool $all = true) : void{ - $this->currentPath = null; - $this->lastPoint = null; - $this->stuckTick = 0; - if($all){ - $this->movePoint = null; - } - } - - /** - * @param bool $value - */ - public function setAvoidsWater(bool $value) : void{ - $this->avoidsWater = $value; - } - - /** - * @param bool $value - */ - public function setAvoidsSun(bool $value) : void{ - $this->avoidsSun = $value; - } - - /** - * @return bool - */ - public function getAvoidsWater() : bool{ - return $this->avoidsWater; - } - - /** - * @return bool - */ - public function getAvoidsSun() : bool{ - return $this->avoidsSun; - } - - /** - * @param Vector3 $point - * - * @return bool - */ - public function isSameDestination(Vector3 $point) : bool{ - return !$this->havePath() ? false : $this->currentPath->getVectorByIndex(count($this->currentPath->getPoints()) - 1)->equals($point); - } - - /** - * @param Vector3 $pos - * @param float $speed - * @param float|null $followRange - * - * @return bool - */ - public function tryMoveTo(Vector3 $pos, float $speed, ?float $followRange = null) : bool{ - if(!$this->isSameDestination($pos->floor())){ - $this->setSpeedMultiplier($speed); - $this->setPath($this->findPath($pos, $followRange)); - return true; - } - return false; - } - - /** - * @param Vector3 $pos - * @param float|null $followRange - * - * @return Path - */ - public function findPath(Vector3 $pos, ?float $followRange = null) : Path{ - return new Path($this->navigate(new PathPoint(floor($this->mob->x), floor($this->mob->z)), new PathPoint(floor($pos->x), floor($pos->z)), $followRange * 2)); - } - - /** - * Update for navigation movement - */ - public function onNavigateUpdate() : void{ - if($this->currentPath !== null){ - if($this->havePath()){ - $this->pathFollow(); - $next = $this->currentPath->getPointByIndex($this->currentPath->getCurrentIndex()); - if($next !== null){ - $this->movePoint = $next; - }else{ - $this->clearPath(false); - } - }else{ - $this->clearPath(false); - } - } - - if($this->movePoint !== null){ - $f = floor($this->mob->width + 1) / 2; - $this->mob->getMoveHelper()->moveTo($this->movePoint->x + $f, $this->movePoint->height, $this->movePoint->y + $f, $this->speedMultiplier); - - $currentPos = $this->mob->floor(); - - if($currentPos->x == $this->movePoint->x and $currentPos->z == $this->movePoint->y){ - $this->movePoint = null; - } - - if($this->lastPoint !== null and $currentPos->x == $this->lastPoint->x and $currentPos->z == $this->lastPoint->z){ - $this->stuckTick++; - - if($this->stuckTick > 100){ - $this->clearPath(); - } - }else{ - $this->lastPoint = $currentPos; - $this->stuckTick = 0; - } - } - } - - /** - * @return float - */ - public function getSpeedMultiplier() : float{ - return $this->speedMultiplier; - } - - /** - * @param float $speedMultiplier - */ - public function setSpeedMultiplier(float $speedMultiplier) : void{ - $this->speedMultiplier = $speedMultiplier; - } - - /** - * @return int - */ - public function getProcessorType() : int{ - return $this->processorType; - } - - /** - * @param int $processorType - */ - public function setProcessorType(int $processorType) : void{ - $this->processorType = $processorType; - } - -} \ No newline at end of file diff --git a/src/pocketmine/entity/pathfinder/Path.php b/src/pocketmine/entity/pathfinder/Path.php deleted file mode 100644 index 8944cb2c9fc..00000000000 --- a/src/pocketmine/entity/pathfinder/Path.php +++ /dev/null @@ -1,88 +0,0 @@ -points = $points; - } - - public function havePath() : bool{ - return !empty($this->points) and $this->currentIndex < count($this->points) - 1; - } - - public function getVectorByIndex(int $index) : ?Vector3{ - $point = $this->getPointByIndex($index); - if($point === null) return null; - - return new Vector3($point->x, $point->height, $point->y); - } - - public function getFinalPathPoint() : ?PathPoint{ - return end($this->points); - } - - public function getPointByIndex(int $index) : ?PathPoint{ - return $this->points[$index] ?? null; - } - - public function removePoint(int $index) : void{ - unset($this->points[$index]); - } - - /** - * @return PathPoint[] - */ - public function getPoints() : array{ - return $this->points; - } - - /** - * @return int - */ - public function getCurrentIndex() : int{ - return $this->currentIndex; - } - - /** - * @param int $currentIndex - */ - public function setCurrentIndex(int $currentIndex) : void{ - $this->currentIndex = $currentIndex; - } - - public function limitPath(int $maxLength) : void{ - $this->points = array_slice($this->points, 0, $maxLength + 1); - } -} \ No newline at end of file diff --git a/src/pocketmine/entity/pathfinder/PathPoint.php b/src/pocketmine/entity/pathfinder/PathPoint.php deleted file mode 100644 index 6e088271f63..00000000000 --- a/src/pocketmine/entity/pathfinder/PathPoint.php +++ /dev/null @@ -1,41 +0,0 @@ -x * 397) ^ $this->y; - } - - public function equals(Vector2 $v) : bool{ - return $this->x == $v->x and $this->y == $v->y; - } -} \ No newline at end of file diff --git a/src/pocketmine/entity/pathfinding/Path.php b/src/pocketmine/entity/pathfinding/Path.php new file mode 100644 index 00000000000..98e20237f9b --- /dev/null +++ b/src/pocketmine/entity/pathfinding/Path.php @@ -0,0 +1,82 @@ +index === -1){ + $this->pathPoints[] = $point; + $point->index = $this->count++; + + $this->sortByDistance(); + } + + return $point; + } + + public function clearPath() : void{ + $this->count = 0; + $this->pathPoints = []; + } + + public function dequeue() : ?PathPoint{ + $point = array_shift($this->pathPoints); + + if($point !== null){ + $point = clone $point; + $point->index = -1; + } + + return $point; + } + + public function changeDistance(PathPoint $point, float $distance) : void{ + if(isset($this->pathPoints[$point->index])){ + $this->pathPoints[$point->index]->distanceToTarget = $distance; + + $this->sortByDistance(); + } + } + + protected function sortByDistance() : void{ + uasort($this->pathPoints, function(PathPoint $point1, PathPoint $point2) : int{ + if($point1->distanceToTarget === $point2->distanceToTarget){ + return 0; + } + + return $point1->distanceToTarget > $point2->distanceToTarget ? -1 : 1; + }); + + $this->pathPoints = array_values($this->pathPoints); // resort indexes + } + + public function isEmpty() : bool{ + return $this->count === 0; + } +} \ No newline at end of file diff --git a/src/pocketmine/entity/pathfinding/PathEntity.php b/src/pocketmine/entity/pathfinding/PathEntity.php new file mode 100644 index 00000000000..09940835928 --- /dev/null +++ b/src/pocketmine/entity/pathfinding/PathEntity.php @@ -0,0 +1,105 @@ +points = $points; + $this->pathLength = count($points); + } + + public function incrementPathIndex() : void{ + ++$this->currentPathIndex; + } + + public function isFinished() : bool{ + return $this->currentPathIndex >= $this->pathLength; + } + + public function getFinalPathPoint() : ?PathPoint{ + return $this->pathLength > 0 ? $this->points[$this->pathLength - 1] : null; + } + + public function getPathPointFromIndex(int $index) : ?PathPoint{ + return $this->points[$index] ?? null; + } + + public function getCurrentPathLength() : int{ + return $this->pathLength; + } + + public function setCurrentPathLength(int $length) : void{ + $this->pathLength = $length; + } + + public function getCurrentPathIndex() : int{ + return $this->currentPathIndex; + } + + public function setCurrentPathIndex(int $index) : void{ + $this->currentPathIndex = $index; + } + + public function getVectorFromIndex(int $index) : ?Vector3{ + return ($point = $this->getPathPointFromIndex($index)) !== null ? $point->add(0.5, 0, 0.5) : null; + } + + public function getPosition() : ?Vector3{ + return $this->getVectorFromIndex($this->currentPathIndex); + } + + public function isSamePath(PathEntity $pathEntity) : bool{ + if(count($pathEntity->points) !== count($this->points)){ + return false; + }else{ + foreach($this->points as $point){ + foreach($pathEntity->points as $point2){ + if(!$point->equals($point2)){ + return false; + } + } + } + + return true; + } + } + + public function isDestinationSame(Vector3 $vec) : bool{ + $point = $this->getFinalPathPoint(); + return $point == null ? false : $point->x == $vec->x and $point->z == $vec->z; + } +} \ No newline at end of file diff --git a/src/pocketmine/entity/pathfinding/PathFinder.php b/src/pocketmine/entity/pathfinding/PathFinder.php new file mode 100644 index 00000000000..e925a341e30 --- /dev/null +++ b/src/pocketmine/entity/pathfinding/PathFinder.php @@ -0,0 +1,131 @@ +path = new Path(); + $this->nodeProcessor = $nodeProcessor; + } + + public function findPathToEntity(Level $level, Entity $entity, Entity $targetEntity, float $maxDist){ + return $this->findPathToXYZ($level, $entity, $targetEntity->x, $targetEntity->getBoundingBox()->minY, $targetEntity->z, $maxDist); + } + + public function findPathToPosition(Level $level, Entity $entity, Vector3 $targetPos, float $maxDist){ + return $this->findPathToXYZ($level, $entity, $targetPos->getX() + 0.5, $targetPos->getY() + 0.5, $targetPos->getZ() + 0.5, $maxDist); + } + + protected function findPathToXYZ(Level $level, Entity $entity, float $x, float $y, float $z, float $maxDist){ + $this->path->clearPath(); + + $this->nodeProcessor->initProcessor($level, $entity); + + $startPoint = $this->nodeProcessor->getPathPointTo($entity); + $endPoint = $this->nodeProcessor->getPathPointToCoords($entity, $x, $y, $z); + $pathEntity = $this->addToPath($entity, $startPoint, $endPoint, $maxDist); + + $this->nodeProcessor->postProcess(); + + return $pathEntity; + } + + private function addToPath(Entity $entity, PathPoint $startPoint, PathPoint $endPoint, float $maxDistance){ + $startPoint->totalPathDistance = 0.0; + $startPoint->distanceToNext = $startPoint->distanceSquared($endPoint); + $startPoint->distanceToTarget = $startPoint->distanceToNext; + + $this->path->clearPath(); + $this->path->addPoint($startPoint); + + $currentPoint = $startPoint; + var_dump("geldi"); + + while(!$this->path->isEmpty()){ + $point = $this->path->dequeue(); + if($point === null){ + return null; + } + + if($point->equals($endPoint)){ + return $this->createPathEntity($endPoint); + } + + if($point->distanceSquared($endPoint) < $currentPoint->distanceSquared($endPoint)){ + $currentPoint = $point; + } + + $point->visited = true; + + $i = $this->nodeProcessor->findPathOptions($this->pathOptions, $entity, $point, $endPoint, $maxDistance); + var_dump($i); + for($j = 0; $j < $i; ++$j){ + $point2 = $this->pathOptions[$j]; + $f = $point->totalPathDistance + $point->distanceSquared($point2); + + if($f < ($maxDistance * 2) and (!$point2->isAssigned() or $f < $point2->totalPathDistance)){ + $point2->previous = $point; + $point2->totalPathDistance = $f; + $point2->distanceToNext = $point2->distanceToSquared($endPoint); + + if($point2->isAssigned()){ + $this->path->changeDistance($point2, $point2->totalPathDistance + $point2->distanceToNext); + }else{ + $point2->distanceToTarget = $point2->totalPathDistance + $point2->distanceToNext; + $this->path->addPoint($point2); + } + } + } + } + + if($currentPoint === $startPoint){ + return null; + }else{ + return $this->createPathEntity($currentPoint); + } + } + + protected function createPathEntity(PathPoint $current) : PathEntity{ + $points = []; + + for($point = $current; $point->previous !== null; $point = $point->previous){ + array_unshift($points, $point); + } + unset($points[0]); + + return new PathEntity($points); + } +} \ No newline at end of file diff --git a/src/pocketmine/entity/pathfinding/PathPoint.php b/src/pocketmine/entity/pathfinding/PathPoint.php new file mode 100644 index 00000000000..7ce22a009b1 --- /dev/null +++ b/src/pocketmine/entity/pathfinding/PathPoint.php @@ -0,0 +1,66 @@ +hash = PathPoint::makeHash($x, $y, $z); + } + + public static function makeHash($x, $y, $z){ + return $y & 255 | ($x & 32767) << 8 | ($z & 32767) << 24 | ($x < 0 ? -2147483648 : 0) | ($z < 0 ? 32768 : 0); + } + + public function equals(Vector3 $point) : bool{ + if (!($point instanceof PathPoint)){ + return false; + }else{ + return $this->hash == $point->hash; + } + } + + public function hashCode() : int{ + return $this->hash; + } + + public function isAssigned() : bool{ + return $this->index >= 0; + } +} \ No newline at end of file diff --git a/src/pocketmine/entity/pathfinding/navigate/PathNavigate.php b/src/pocketmine/entity/pathfinding/navigate/PathNavigate.php new file mode 100644 index 00000000000..b940d213b9d --- /dev/null +++ b/src/pocketmine/entity/pathfinding/navigate/PathNavigate.php @@ -0,0 +1,230 @@ +theEntity = $entity; + $this->level = $entity->getLevel(); + $this->pathSearchRange = 16; + $this->pathFinder = $this->getPathFinder(); + $this->lastPosCheck = new Vector3(); + } + + protected abstract function getPathFinder() : PathFinder; + + public function setSpeed(float $speedIn) : void{ + $this->speed = $speedIn; + } + + public function getPathSearchRange() : int{ + return $this->pathSearchRange; + } + + public function getPathToPos(Vector3 $pos) : ?PathEntity{ + if(!$this->canNavigate()){ + return null; + }else{ + return $this->pathFinder->findPathToPosition($this->level, $this->theEntity, $pos, $this->getPathSearchRange()); + } + } + + public function tryMoveToPos(Vector3 $pos, float $speed) : bool{ + return $this->setPath($this->getPathToPos($pos), $speed); + } + + public function setHeightRequirement(float $jumpHeight) : void{ + $this->heightRequirement = $jumpHeight; + } + + public function getPathToEntity(Entity $entity){ + if(!$this->canNavigate()){ + return null; + }else{ + return $this->pathFinder->findPathToEntity($this->level, $this->theEntity, $entity, $this->getPathSearchRange()); + } + } + + public function tryMoveToEntity(Entity $entity, float $speed) : bool{ + $v = $this->setPath($path = $this->getPathToEntity($entity), $speed); + + return $v; + } + + public function setPath(?PathEntity $pathEntity, float $speed) : bool{ + if($pathEntity === null){ + $this->currentPath = null; + return false; + }else{ + if(!$pathEntity->isSamePath($this->currentPath)){ + $this->currentPath = $pathEntity; + } + + $this->removeSunnyPath(); + + if($this->currentPath->getCurrentPathLength() === 0){ + return false; + }else{ + $this->speed = $speed; + $this->ticksAtLastPos = $this->totalTicks; + $this->lastPosCheck = $this->getEntityPosition(); + + return true; + } + } + } + + public function getPath() : ?PathEntity{ + return $this->currentPath; + } + + public function tick() : void{ + ++$this->totalTicks; + + if(!$this->noPath()){ + if($this->canNavigate()){ + $this->pathFollow(); + }elseif($this->currentPath != null and $this->currentPath->getCurrentPathIndex() < $this->currentPath->getCurrentPathLength()){ + $pos1 = $this->getEntityPosition(); + $pos2 = $this->currentPath->getVectorFromIndex($this->currentPath->getCurrentPathIndex()); + + if($pos1->y > $pos2->y and !$this->theEntity->onGround and floor($pos1->x) == floor($pos2->x) and floor($pos1->z) == floor($pos2->z)){ + $this->currentPath->setCurrentPathIndex($this->currentPath->getCurrentPathIndex() + 1); + } + } + + if(!$this->noPath()){ + $pos = $this->currentPath->getPosition(); + if($pos != null){ + $bb = (new AxisAlignedBB($pos->x, $pos->y, $pos->z, $pos->x, $pos->y, $pos->z))->expand(0.5, 0.5, 0.5); + $list = $this->level->getCollidingEntities($bb->addCoord(0.0, -1.0, 0.0), $this->theEntity); + $bb = $bb->offset(0.0, 1.0, 0.0); + + $yOffset = -1.0; + foreach($list as $entity){ + $yOffset = $entity->getBoundingBox()->calculateYOffset($bb, $yOffset); + } + + $this->theEntity->getMoveHelper()->moveTo($pos->x, $pos->y + $yOffset, $pos->z, $this->speed); + } + } + } + } + + protected function pathFollow() : void{ + $vec3 = $this->getEntityPosition(); + $i = $this->currentPath->getCurrentPathLength(); + + for($j = $this->currentPath->getCurrentPathIndex(); $j < $this->currentPath->getCurrentPathLength(); ++$j){ + if($this->currentPath->getPathPointFromIndex($j)->y != $vec3->y){ + $i = $j; + break; + } + } + + $f = $this->theEntity->width * $this->theEntity->width * $this->heightRequirement; + + for($k = $this->currentPath->getCurrentPathIndex(); $k < $i; ++$k){ + $vec31 = $this->currentPath->getVectorFromIndex($k); + + if($vec3->distanceSquared($vec31) < $f){ + $this->currentPath->setCurrentPathIndex($k + 1); + } + } + + $j1 = ceil($this->theEntity->width + 0.25); + $k1 = $this->theEntity->height + 1; + $l = $j1; + + for($i1 = $i - 1; $i1 >= $this->currentPath->getCurrentPathIndex(); --$i1){ + if($this->isDirectPathBetweenPoints($vec3, $this->currentPath->getVectorFromIndex($i1), new Vector3($j1, $k1, $l))){ + $this->currentPath->setCurrentPathIndex($i1); + $this->checkForStuck($vec3); + return; + } + } + + $this->checkForStuck($vec3); + } + + protected function checkForStuck(Vector3 $pos) : void{ + if($this->totalTicks - $this->ticksAtLastPos > 100){ + if($pos->distanceSquared($this->lastPosCheck) < 2.25){ + $this->clearPathEntity(); + } + + $this->ticksAtLastPos = $this->totalTicks; + $this->lastPosCheck = $pos; + } + } + + public function noPath() : bool{ + return $this->currentPath === null or $this->currentPath->isFinished(); + } + + public function clearPathEntity() : void{ + $this->currentPath = null; + } + + protected abstract function getEntityPosition() : Vector3; + + protected abstract function canNavigate() : bool; + + protected function isInLiquid() : bool{ + return $this->theEntity->isInsideOfWater() or $this->theEntity->isInsideOfLava(); + } + + protected function removeSunnyPath() : void{ + // NOOP + } + + public abstract function isDirectPathBetweenPoints(Vector3 $from, Vector3 $to, Vector3 $size) : bool; +} \ No newline at end of file diff --git a/src/pocketmine/entity/pathfinding/navigate/PathNavigateClimber.php b/src/pocketmine/entity/pathfinding/navigate/PathNavigateClimber.php new file mode 100644 index 00000000000..cb7f24406af --- /dev/null +++ b/src/pocketmine/entity/pathfinding/navigate/PathNavigateClimber.php @@ -0,0 +1,77 @@ +targetPos = $pos; + return parent::getPathToPos($pos); + } + + public function getPathToEntity(Entity $entity){ + $this->targetPos = $entity->asVector3(); + return parent::getPathToEntity($entity); + } + + public function tryMoveToEntity(Entity $entity, float $speed) : bool{ + $path = $this->getPathToEntity($entity); + + if($path !== null){ + return $this->setPath($path, $speed); + }else{ + $this->targetPos = $entity->asVector3(); + $this->setSpeed($speed); + + return true; + } + } + + public function tick() : void{ + if(!$this->noPath()){ + parent::tick(); + }elseif($this->targetPos !== null){ + $f = $this->theEntity->width ** 2; + + if($this->theEntity->distanceSquared($this->targetPos->add(0.5, 0.5, 0.5)) >= $f and + ($this->theEntity->y <= $this->targetPos->y or + $this->theEntity->distanceSquared(new Vector3($this->targetPos->x + 0.5, floor($this->theEntity->y) + 0.5, $this->targetPos->z)) >= $f)){ + $this->theEntity->getMoveHelper()->moveTo($this->targetPos->x, $this->targetPos->y, $this->targetPos->z, $this->speed); + }else{ + $this->targetPos = null; + } + } + } +} \ No newline at end of file diff --git a/src/pocketmine/entity/pathfinding/navigate/PathNavigateGround.php b/src/pocketmine/entity/pathfinding/navigate/PathNavigateGround.php new file mode 100644 index 00000000000..8f090f3bb29 --- /dev/null +++ b/src/pocketmine/entity/pathfinding/navigate/PathNavigateGround.php @@ -0,0 +1,258 @@ +nodeProcessor = new WalkNodeProcessor(); + $this->nodeProcessor->setEnterDoors(true); + + parent::__construct($entity); + } + + protected function getPathFinder() : PathFinder{ + return new PathFinder($this->nodeProcessor); + } + + protected function canNavigate() : bool{ + return $this->theEntity->onGround or ($this->getCanSwim() and $this->isInLiquid()); + } + + protected function getEntityPosition() : Vector3{ + return new Vector3($this->theEntity->x, $this->getPathablePosY(), $this->theEntity->z); + } + + protected function getPathablePosY() : int{ + if($this->theEntity->isInsideOfWater() && $this->getCanSwim()){ + $i = $this->theEntity->getBoundingBox()->minY - 1; + $block = $this->level->getBlock(new Vector3(floor($this->theEntity->x), $i, floor($this->theEntity->z))); + $j = 0; + + while($block->getId() === Block::WATER or $block->getId() === Block::STILL_WATER){ + ++$i; + $block = $this->level->getBlock(new Vector3(floor($this->theEntity->x), $i, floor($this->theEntity->z))); + ++$j; + + if($j > 16){ + return (int) $this->theEntity->getBoundingBox()->minY; + } + } + + return $i; + }else{ + return (int) $this->theEntity->getBoundingBox()->minY; + } + } + + protected function removeSunnyPath() : void{ + if($this->shouldAvoidSun){ + if($this->level->canSeeSky(new Vector3(floor($this->theEntity->x), $this->theEntity->getBoundingBox()->minY + 0.5, floor($this->theEntity->z)))){ + return; + } + + for($i = 0; $i < $this->currentPath->getCurrentPathLength(); ++$i){ + $point = $this->currentPath->getPathPointFromIndex($i); + + if($this->level->canSeeSky(new Vector3($point->x, $point->y, $point->z))){ + $this->currentPath->setCurrentPathLength($i - 1); + return; + } + } + } + } + + /** + * @param Vector3 $from + * @param Vector3 $to + * @param Vector3 $size + * + * @return bool + */ + public function isDirectPathBetweenPoints(Vector3 $from, Vector3 $to, Vector3 $size) : bool{ + $currentX = $from->getFloorX(); + $currentZ = $from->getFloorZ(); + $dX = $to->x - $from->x; + $dZ = $to->z - $from->z; + $distNormal = 1 / sqrt($dX ** 2 + $dZ ** 2); + $dX *= $distNormal; + $dZ *= $distNormal; + + if(!$this->isSafeToStandAt($from->floor(), $size->add(2, 0, 2), $from, $dX, $dZ)){ + return false; + }else{ + $dX = max($dX, 0.0001); + $dZ = max($dZ, 0.0001); + $dXN = 1 / abs($dX); + $dZN = 1 / abs($dZ); + $xDiff = $currentX - $from->x; + $zDiff = $currentZ - $from->z; + + if($dX >= 0){ + $xDiff++; + } + + if($dZ >= 0){ + $zDiff++; + } + + $xDiff /= $dX; + $zDiff /= $dZ; + + $pX = $dX < 0 ? -1 : 1; + $pZ = $dZ < 0 ? -1 : 1; + + $rX = $to->getFloorX() - $currentX; + $rZ = $to->getFloorZ() - $currentZ; + + while($rX * $pX > 0 or $rZ * $pZ > 0){ + if($xDiff < $zDiff){ + $zDiff += $dXN; + $currentX += $pX; + $rX = $to->getFloorX() - $currentX; + }else{ + $zDiff += $dZN; + $currentZ += $pZ; + $rZ = $to->getFloorZ() - $currentZ; + } + + if(!$this->isSafeToStandAt(new Vector3($currentX, round($from->y), $currentZ), $size, $from, $dX, $dZ)){ + return false; + } + } + + return true; + } + } + + protected function isSafeToStandAt(Vector3 $current, Vector3 $size, Vector3 $base, float $distX, float $distZ) : bool{ + $a = $current->x - $size->x / 2; + $c = $current->z - $size->z / 2; + + if(!$this->isPositionClear($current->asVector3()->setComponents($a, $current->y, $c), $size, $base, $distX, $distZ)){ + return false; + }else{ + for($x = $a; $x < $a + $size->x; ++$x){ + for($z = $c; $z < $c + $size->z; ++$z){ + $x2 = $x + 0.5 - $base->x; + $z2 = $z + 0.5 - $base->z; + + if($x2 * $distX + $z2 * $distZ >= 0){ + $block = $this->level->getBlock(new Vector3($x, $current->y - 1, $z)); + + if($block->getId() === Block::AIR){ + return false; + } + + if($block->getId() === Block::WATER and !$this->theEntity->isInsideOfWater()){ + return false; + } + + if($block->getId() === Block::LAVA){ + return false; + } + } + } + } + + return true; + } + } + + /** + * @param Vector3 $pos + * @param Vector3 $size + * @param Vector3 $point + * @param float $distX + * @param float $distZ + * + * @return bool + */ + protected function isPositionClear(Vector3 $pos, Vector3 $size, Vector3 $point, float $distX, float $distZ) : bool{ + $tempVector = new Vector3(); + + for($x1 = min($pos->x, $pos->x + $size->x - 1); $x1 <= max($pos->x, $pos->x + $size->x - 1); $x1++){ + for($y1 = min($pos->y, $pos->y + $size->y - 1); $y1 <= max($pos->y, $pos->y + $size->y - 1); $y1++){ + for($z1 = min($pos->z, $pos->z + $size->z - 1); $z1 <= max($pos->z, $pos->z + $size->z - 1); $z1++){ + $tempVector->setComponents($x1, $y1, $z1); + + $d0 = $tempVector->getX() + 0.5 - $point->x; + $d1 = $tempVector->getZ() + 0.5 - $point->z; + + if($d0 * $distX + $d1 * $distZ >= 0){ + $block = $this->level->getBlock($tempVector); + + if(!$block->isPassable()){ + return false; + } + } + } + } + } + + return true; + } + + public function setAvoidsWater(bool $value) : void{ + $this->nodeProcessor->setAvoidsWater($value); + } + + public function getAvoidsWater() : bool{ + return $this->nodeProcessor->getAvoidsWater(); + } + + public function setBreakDoors(bool $value) : void{ + $this->nodeProcessor->setBreakDoors($value); + } + + public function setEnterDoors(bool $value) : void{ + $this->nodeProcessor->setEnterDoors($value); + } + + public function getEnterDoors() : bool{ + return $this->nodeProcessor->getEnterDoors(); + } + + public function setCanSwim(bool $value) : void{ + $this->nodeProcessor->setCanSwim($value); + } + + public function getCanSwim() : bool{ + return $this->nodeProcessor->getCanSwim(); + } + + public function setAvoidSun(bool $value) : void{ + $this->shouldAvoidSun = $value; + } +} \ No newline at end of file diff --git a/src/pocketmine/entity/pathfinding/processor/NodeProcessor.php b/src/pocketmine/entity/pathfinding/processor/NodeProcessor.php new file mode 100644 index 00000000000..2bdd39ff782 --- /dev/null +++ b/src/pocketmine/entity/pathfinding/processor/NodeProcessor.php @@ -0,0 +1,68 @@ +level = $level; + $this->pointMap = []; + + $this->entityBlockBox = new AxisAlignedBB(0, 0, 0, floor($entity->width + 1), floor($entity->height + 1), floor($entity->width + 1)); + } + + public function postProcess() : void{ + // NOOP + } + + protected function openPoint(float $x, float $y, float $z) : PathPoint{ + $i = PathPoint::makeHash($x, $y, $z); + + if (empty($this->pointMap[$i])){ + $point = new PathPoint($x, $y, $z); + $this->pointMap[$i] = $point; + }else{ + $point = $this->pointMap[$i]; + } + + return $point; + } + + public abstract function getPathPointTo(Entity $entity) : PathPoint; + + public abstract function getPathPointToCoords(Entity $entity, float $x, float $y, float $z) : PathPoint; + + public abstract function findPathOptions(array &$pathOptions, Entity $entity, PathPoint $currentPoint, PathPoint $targetPoint, float $maxDistance) : int; +} \ No newline at end of file diff --git a/src/pocketmine/entity/pathfinding/processor/WalkNodeProcessor.php b/src/pocketmine/entity/pathfinding/processor/WalkNodeProcessor.php new file mode 100644 index 00000000000..ce05f629f42 --- /dev/null +++ b/src/pocketmine/entity/pathfinding/processor/WalkNodeProcessor.php @@ -0,0 +1,247 @@ +shouldAvoidWater = $this->avoidsWater; + } + + public function postProcess() : void{ + $this->avoidsWater = $this->shouldAvoidWater; + } + + public function getPathPointTo(Entity $entity) : PathPoint{ + if($this->canSwim and $entity->isInsideOfWater()){ + $i = $entity->getBoundingBox()->minY; + $mutablePos = new Vector3(floor($entity->x), $i, floor($entity->z)); + + for($block = $this->level->getBlock($mutablePos); $block->getId() == Block::STILL_WATER or $block->getId() == Block::WATER; $block = $this->level->getBlock($mutablePos)){ + ++$i; + $mutablePos->setComponents(floor($entity->x), $i, floor($entity->z)); + } + + $this->avoidsWater = false; + }else{ + $i = floor($entity->getBoundingBox()->minY + 0.5); + } + + return $this->openPoint(floor($entity->getBoundingBox()->minX), $i, floor($entity->getBoundingBox()->minZ)); + } + + public function getPathPointToCoords(Entity $entity, float $x, float $y, float $z) : PathPoint{ + return $this->openPoint(floor($x - ($entity->width / 2.0)), floor($y), floor($z - ($entity->width / 2.0))); + } + + public function findPathOptions(array &$pathOptions, Entity $entity, PathPoint $currentPoint, PathPoint $targetPoint, float $maxDistance) : int{ + $i = 0; + $j = 0; + + if($this->getState($entity, $currentPoint->add(0, 1, 0)) === 1){ + $j = 1; + } + + $point = $this->getSafePoint($entity, $currentPoint->x, $currentPoint->y + 1, $currentPoint->z + 1, $j); + $point1 = $this->getSafePoint($entity, $currentPoint->x - 1, $currentPoint->y + 1, $currentPoint->z, $j); + $point2 = $this->getSafePoint($entity, $currentPoint->x + 1, $currentPoint->y + 1, $currentPoint->z, $j); + $point3 = $this->getSafePoint($entity, $currentPoint->x, $currentPoint->y + 1, $currentPoint->z - 1, $j); + + if($point !== null and !$point->visited and $point->distance($targetPoint) < $maxDistance){ + $pathOptions[$i++] = $point; + } + + if($point1 !== null and !$point1->visited and $point1->distance($targetPoint) < $maxDistance){ + $pathOptions[$i++] = $point1; + } + + if($point2 !== null and !$point2->visited and $point2->distance($targetPoint) < $maxDistance){ + $pathOptions[$i++] = $point2; + } + + if($point3 !== null and !$point3->visited and $point3->distance($targetPoint) < $maxDistance){ + $pathOptions[$i++] = $point3; + } + + return $i; + } + + protected function getSafePoint(Entity $entity, float $x, float $y, float $z, int $yOffset) : ?PathPoint{ + $point = null; + $i = $this->getState($entity, $pos = new Vector3($x, $y, $z)); + + if($i === 2){ + return $this->openPoint($x, $y, $z); + }else{ + if($i === 1){ + $point = $this->openPoint($x, $y, $z); + } + + if($point === null and $yOffset > 0 and $i !== -3 and $i !== -4 and $this->getState($entity, $pos->add(0 , $yOffset, 0)) === 1){ + $point = $this->openPoint($x, $y + $yOffset, $z); + $y += $yOffset; + } + + if($point !== null){ + $j = 0; + + for($k = 0; $y > 0; $point = $this->openPoint($x, $y, $z)){ + $k = $this->getState($entity, $pos->add(0, -1, 0)); + + if($this->avoidsWater and $k === -1){ + return null; + } + + if($k !== 1){ + break; + } + + if($j++ >= 3){ // TODO: add a function for this + return null; + } + + --$y; + + if($y <= 0){ + return null; + } + } + + if($k === -2){ + return null; + } + } + + return $point; + } + } + + protected function getState(Entity $entity, Vector3 $pos) : int{ + return self::getPositionState($entity, $this->entityBlockBox->offsetCopy($pos->x, $pos->y, $pos->z), $this->avoidsWater, $this->canBreakDoors, $this->canEnterDoors); + } + + public static function getPositionState(Entity $entity, AxisAlignedBB $bb, bool $avoidWater, bool $breakDoors, bool $enterDoors) : int{ + $flag = false; + $mutablePos = new Vector3(); + + for($x = $bb->minX; $x < $bb->maxX; ++$x){ + for($y = $bb->minY; $y < $bb->maxY; ++$y){ + for($z = $bb->minZ; $z < $bb->maxZ; ++$z){ + $mutablePos->setComponents($x, $y, $z); + $block = $entity->level->getBlock($mutablePos); + + if($block->getId() !== Block::AIR){ + if($block->getId() !== Block::TRAPDOOR and $block->getId() !== Block::IRON_TRAPDOOR){ + if($block->getId() != Block::STILL_WATER and $block->getId() != Block::WATER){ + if(!$enterDoors and $block instanceof Door){ + return 0; + } + }else{ + if($avoidWater){ + return -1; + } + + $flag = true; + } + }else{ + $flag = true; + } + + if($entity->level->getBlock($mutablePos) instanceof Rail){ + if(!($entity->level->getBlock($entity) instanceof Rail) and !($entity->level->getBlock($entity->getSide(Vector3::SIDE_DOWN)) instanceof Rail)){ + return -3; + } + }elseif(!$block->isTransparent() and (!$breakDoors or !($block instanceof Door))){ + if($block instanceof Fence or $block instanceof FenceGate or $block->isSolid()){ + return -3; + } + + if($block->getId() !== Block::TRAPDOOR and $block->getId() !== Block::IRON_TRAPDOOR){ + return -4; + } + + if($block->getId() === Block::LAVA){ + return 0; + } + + if(!$entity->isInsideOfLava()){ + return -2; + } + } + } + } + } + } + + return $flag ? 2 : 1; + } + + public function setEnterDoors(bool $value) : void{ + $this->canEnterDoors = $value; + } + + public function setBreakDoors(bool $value) : void{ + $this->canBreakDoors = $value; + } + + public function setAvoidsWater(bool $value) : void{ + $this->avoidsWater = $value; + } + + public function setCanSwim(bool $value) : void{ + $this->canSwim = $value; + } + + public function getEnterDoors() : bool{ + return $this->canEnterDoors; + } + + public function getCanSwim() : bool{ + return $this->canSwim; + } + + public function getAvoidsWater() : bool{ + return $this->avoidsWater; + } +} \ No newline at end of file From 208ca8fd457dc5671e0300240e7ff3ac2559247c Mon Sep 17 00:00:00 2001 From: EmreTr1 Date: Fri, 25 Oct 2019 19:22:51 +0300 Subject: [PATCH 17/22] Optimization & bug fixes (its working now) --- src/pocketmine/entity/Animal.php | 4 ++-- src/pocketmine/entity/pathfinding/PathFinder.php | 16 +++++++++------- .../entity/pathfinding/navigate/PathNavigate.php | 2 +- .../pathfinding/processor/WalkNodeProcessor.php | 9 ++++----- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/pocketmine/entity/Animal.php b/src/pocketmine/entity/Animal.php index 5f705da4f36..aab3511b01a 100644 --- a/src/pocketmine/entity/Animal.php +++ b/src/pocketmine/entity/Animal.php @@ -112,7 +112,7 @@ public function saveNBT() : void{ } public function getVariant() : int{ - return $this->propertyManager->getInt(self::DATA_VARIANT); + return $this->propertyManager->getInt(self::DATA_VARIANT) ?? 0; } public function setVariant(int $variant) : void{ @@ -120,7 +120,7 @@ public function setVariant(int $variant) : void{ } public function getMarkVariant() : int{ - return $this->propertyManager->getInt(self::DATA_MARK_VARIANT); + return $this->propertyManager->getInt(self::DATA_MARK_VARIANT) ?? 0; } public function setMarkVariant(int $markVariant) : void{ diff --git a/src/pocketmine/entity/pathfinding/PathFinder.php b/src/pocketmine/entity/pathfinding/PathFinder.php index e925a341e30..486c07179a6 100644 --- a/src/pocketmine/entity/pathfinding/PathFinder.php +++ b/src/pocketmine/entity/pathfinding/PathFinder.php @@ -32,6 +32,7 @@ class PathFinder{ /** @var Path */ protected $path; + /** @var PathPoint[] */ protected $pathOptions = []; /** @var NodeProcessor */ protected $nodeProcessor; @@ -63,8 +64,8 @@ protected function findPathToXYZ(Level $level, Entity $entity, float $x, float $ return $pathEntity; } - private function addToPath(Entity $entity, PathPoint $startPoint, PathPoint $endPoint, float $maxDistance){ - $startPoint->totalPathDistance = 0.0; + protected function addToPath(Entity $entity, PathPoint $startPoint, PathPoint $endPoint, float $maxDistance){ + $startPoint->totalPathDistance = 0; $startPoint->distanceToNext = $startPoint->distanceSquared($endPoint); $startPoint->distanceToTarget = $startPoint->distanceToNext; @@ -72,9 +73,9 @@ private function addToPath(Entity $entity, PathPoint $startPoint, PathPoint $end $this->path->addPoint($startPoint); $currentPoint = $startPoint; - var_dump("geldi"); - + $attempt = 0; while(!$this->path->isEmpty()){ + $attempt++; $point = $this->path->dequeue(); if($point === null){ return null; @@ -82,6 +83,8 @@ private function addToPath(Entity $entity, PathPoint $startPoint, PathPoint $end if($point->equals($endPoint)){ return $this->createPathEntity($endPoint); + }elseif($attempt - $this->path->getCount() >= $maxDistance / 2){ + return $this->createPathEntity($currentPoint); } if($point->distanceSquared($endPoint) < $currentPoint->distanceSquared($endPoint)){ @@ -91,7 +94,6 @@ private function addToPath(Entity $entity, PathPoint $startPoint, PathPoint $end $point->visited = true; $i = $this->nodeProcessor->findPathOptions($this->pathOptions, $entity, $point, $endPoint, $maxDistance); - var_dump($i); for($j = 0; $j < $i; ++$j){ $point2 = $this->pathOptions[$j]; $f = $point->totalPathDistance + $point->distanceSquared($point2); @@ -99,7 +101,7 @@ private function addToPath(Entity $entity, PathPoint $startPoint, PathPoint $end if($f < ($maxDistance * 2) and (!$point2->isAssigned() or $f < $point2->totalPathDistance)){ $point2->previous = $point; $point2->totalPathDistance = $f; - $point2->distanceToNext = $point2->distanceToSquared($endPoint); + $point2->distanceToNext = $point2->distanceSquared($endPoint); if($point2->isAssigned()){ $this->path->changeDistance($point2, $point2->totalPathDistance + $point2->distanceToNext); @@ -126,6 +128,6 @@ protected function createPathEntity(PathPoint $current) : PathEntity{ } unset($points[0]); - return new PathEntity($points); + return new PathEntity(array_values($points)); } } \ No newline at end of file diff --git a/src/pocketmine/entity/pathfinding/navigate/PathNavigate.php b/src/pocketmine/entity/pathfinding/navigate/PathNavigate.php index b940d213b9d..52081c40312 100644 --- a/src/pocketmine/entity/pathfinding/navigate/PathNavigate.php +++ b/src/pocketmine/entity/pathfinding/navigate/PathNavigate.php @@ -104,7 +104,7 @@ public function setPath(?PathEntity $pathEntity, float $speed) : bool{ $this->currentPath = null; return false; }else{ - if(!$pathEntity->isSamePath($this->currentPath)){ + if($this->currentPath === null or !$pathEntity->isSamePath($this->currentPath)){ $this->currentPath = $pathEntity; } diff --git a/src/pocketmine/entity/pathfinding/processor/WalkNodeProcessor.php b/src/pocketmine/entity/pathfinding/processor/WalkNodeProcessor.php index ce05f629f42..3af2f75de8e 100644 --- a/src/pocketmine/entity/pathfinding/processor/WalkNodeProcessor.php +++ b/src/pocketmine/entity/pathfinding/processor/WalkNodeProcessor.php @@ -127,7 +127,7 @@ protected function getSafePoint(Entity $entity, float $x, float $y, float $z, in $j = 0; for($k = 0; $y > 0; $point = $this->openPoint($x, $y, $z)){ - $k = $this->getState($entity, $pos->add(0, -1, 0)); + $k = $this->getState($entity, new Vector3($x, $y - 1, $z)); if($this->avoidsWater and $k === -1){ return null; @@ -168,12 +168,11 @@ public static function getPositionState(Entity $entity, AxisAlignedBB $bb, bool for($x = $bb->minX; $x < $bb->maxX; ++$x){ for($y = $bb->minY; $y < $bb->maxY; ++$y){ for($z = $bb->minZ; $z < $bb->maxZ; ++$z){ - $mutablePos->setComponents($x, $y, $z); - $block = $entity->level->getBlock($mutablePos); + $block = $entity->level->getBlock($mutablePos->setComponents($x, $y, $z)); if($block->getId() !== Block::AIR){ if($block->getId() !== Block::TRAPDOOR and $block->getId() !== Block::IRON_TRAPDOOR){ - if($block->getId() != Block::STILL_WATER and $block->getId() != Block::WATER){ + if($block->getId() !== Block::STILL_WATER and $block->getId() !== Block::WATER){ if(!$enterDoors and $block instanceof Door){ return 0; } @@ -188,7 +187,7 @@ public static function getPositionState(Entity $entity, AxisAlignedBB $bb, bool $flag = true; } - if($entity->level->getBlock($mutablePos) instanceof Rail){ + if($block instanceof Rail){ if(!($entity->level->getBlock($entity) instanceof Rail) and !($entity->level->getBlock($entity->getSide(Vector3::SIDE_DOWN)) instanceof Rail)){ return -3; } From 9687c9d7ec98a3c2a88a6dd7b076cd55666ee039 Mon Sep 17 00:00:00 2001 From: EmreTr1 Date: Fri, 25 Oct 2019 19:23:07 +0300 Subject: [PATCH 18/22] fixes --- src/pocketmine/entity/behavior/FloatBehavior.php | 6 ++++++ src/pocketmine/entity/behavior/PanicBehavior.php | 1 - .../entity/pathfinding/navigate/PathNavigate.php | 13 ++----------- .../pathfinding/navigate/PathNavigateGround.php | 2 +- .../pathfinding/processor/WalkNodeProcessor.php | 3 ++- 5 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/pocketmine/entity/behavior/FloatBehavior.php b/src/pocketmine/entity/behavior/FloatBehavior.php index b7083d88d61..54d3c2eca31 100644 --- a/src/pocketmine/entity/behavior/FloatBehavior.php +++ b/src/pocketmine/entity/behavior/FloatBehavior.php @@ -25,12 +25,18 @@ namespace pocketmine\entity\behavior; use pocketmine\entity\Mob; +use pocketmine\entity\pathfinding\navigate\PathNavigateGround; class FloatBehavior extends Behavior{ public function __construct(Mob $mob){ parent::__construct($mob); $this->mutexBits = 4; + + $navigator = $this->mob->getNavigator(); + if($navigator instanceof PathNavigateGround){ + $navigator->setCanSwim(true); + } } public function canStart() : bool{ diff --git a/src/pocketmine/entity/behavior/PanicBehavior.php b/src/pocketmine/entity/behavior/PanicBehavior.php index 4aef5d2e909..f24da085e5a 100644 --- a/src/pocketmine/entity/behavior/PanicBehavior.php +++ b/src/pocketmine/entity/behavior/PanicBehavior.php @@ -38,7 +38,6 @@ public function canStart() : bool{ $this->targetPos = RandomPositionGenerator::findRandomTargetBlock($this->mob, 5, 4); if($this->targetPos !== null){ - $this->followRange = $this->mob->distanceSquared($this->targetPos) + 2; return true; } } diff --git a/src/pocketmine/entity/pathfinding/navigate/PathNavigate.php b/src/pocketmine/entity/pathfinding/navigate/PathNavigate.php index 52081c40312..81e8d750be8 100644 --- a/src/pocketmine/entity/pathfinding/navigate/PathNavigate.php +++ b/src/pocketmine/entity/pathfinding/navigate/PathNavigate.php @@ -143,17 +143,8 @@ public function tick() : void{ if(!$this->noPath()){ $pos = $this->currentPath->getPosition(); - if($pos != null){ - $bb = (new AxisAlignedBB($pos->x, $pos->y, $pos->z, $pos->x, $pos->y, $pos->z))->expand(0.5, 0.5, 0.5); - $list = $this->level->getCollidingEntities($bb->addCoord(0.0, -1.0, 0.0), $this->theEntity); - $bb = $bb->offset(0.0, 1.0, 0.0); - - $yOffset = -1.0; - foreach($list as $entity){ - $yOffset = $entity->getBoundingBox()->calculateYOffset($bb, $yOffset); - } - - $this->theEntity->getMoveHelper()->moveTo($pos->x, $pos->y + $yOffset, $pos->z, $this->speed); + if($pos !== null){ + $this->theEntity->getMoveHelper()->moveTo($pos->x, $pos->y + 0, $pos->z, $this->speed); } } } diff --git a/src/pocketmine/entity/pathfinding/navigate/PathNavigateGround.php b/src/pocketmine/entity/pathfinding/navigate/PathNavigateGround.php index 8f090f3bb29..e3cb3f75138 100644 --- a/src/pocketmine/entity/pathfinding/navigate/PathNavigateGround.php +++ b/src/pocketmine/entity/pathfinding/navigate/PathNavigateGround.php @@ -70,7 +70,7 @@ protected function getPathablePosY() : int{ } } - return $i; + return (int) $i; }else{ return (int) $this->theEntity->getBoundingBox()->minY; } diff --git a/src/pocketmine/entity/pathfinding/processor/WalkNodeProcessor.php b/src/pocketmine/entity/pathfinding/processor/WalkNodeProcessor.php index 3af2f75de8e..3736db6f94b 100644 --- a/src/pocketmine/entity/pathfinding/processor/WalkNodeProcessor.php +++ b/src/pocketmine/entity/pathfinding/processor/WalkNodeProcessor.php @@ -29,6 +29,7 @@ use pocketmine\block\Fence; use pocketmine\block\FenceGate; use pocketmine\block\Rail; +use pocketmine\block\StoneBricks; use pocketmine\entity\Entity; use pocketmine\entity\pathfinding\PathPoint; use pocketmine\level\Level; @@ -192,7 +193,7 @@ public static function getPositionState(Entity $entity, AxisAlignedBB $bb, bool return -3; } }elseif(!$block->isTransparent() and (!$breakDoors or !($block instanceof Door))){ - if($block instanceof Fence or $block instanceof FenceGate or $block->isSolid()){ + if($block instanceof Fence or $block instanceof FenceGate or $block instanceof StoneBricks){ return -3; } From 0ec1ae768b716317328ae2b70589aad4d351ba3c Mon Sep 17 00:00:00 2001 From: EmreTr1 Date: Sun, 27 Oct 2019 14:10:04 +0300 Subject: [PATCH 19/22] uh? --- src/pocketmine/entity/pathfinding/Path.php | 115 +++++++++++++++++---- 1 file changed, 93 insertions(+), 22 deletions(-) diff --git a/src/pocketmine/entity/pathfinding/Path.php b/src/pocketmine/entity/pathfinding/Path.php index 98e20237f9b..d2ec228e343 100644 --- a/src/pocketmine/entity/pathfinding/Path.php +++ b/src/pocketmine/entity/pathfinding/Path.php @@ -30,26 +30,26 @@ class Path{ protected $count = 0; public function addPoint(PathPoint $point) : PathPoint{ - if ($point->index === -1){ - $this->pathPoints[] = $point; - $point->index = $this->count++; - - $this->sortByDistance(); + if($point->index === -1){ + $this->pathPoints[$this->count] = $point; + $point->index = $this->count; + $this->sortBack($this->count++); } return $point; } - public function clearPath() : void{ - $this->count = 0; - $this->pathPoints = []; - } - public function dequeue() : ?PathPoint{ - $point = array_shift($this->pathPoints); + $point = $this->pathPoints[0] ?? null; if($point !== null){ - $point = clone $point; + $this->pathPoints[0] = $this->pathPoints[--$this->count]; + unset($this->pathPoints[$this->count]); + + if($this->count > 0){ + $this->sortForward(0); + } + $point->index = -1; } @@ -57,26 +57,97 @@ public function dequeue() : ?PathPoint{ } public function changeDistance(PathPoint $point, float $distance) : void{ - if(isset($this->pathPoints[$point->index])){ - $this->pathPoints[$point->index]->distanceToTarget = $distance; + $f = $point->distanceToTarget; + $point->distanceToTarget = $distance; - $this->sortByDistance(); + if($distance < $f){ + $this->sortBack($point->index); + }else{ + $this->sortForward($point->index); } } - protected function sortByDistance() : void{ - uasort($this->pathPoints, function(PathPoint $point1, PathPoint $point2) : int{ - if($point1->distanceToTarget === $point2->distanceToTarget){ - return 0; + protected function sortBack(int $index) : void{ + $point = $this->pathPoints[$index] ?? null; + if($point !== null){ + $point1 = null; + + for($f = $point->distanceToTarget; $index > 0; $index = $i){ + $i = $index - 1 >> 1; + $point1 = $this->pathPoints[$i] ?? null; + + if($point1 === null or $f >= $point1->distanceToTarget){ + break; + } + + $this->pathPoints[$index] = $point1; + $point1->index = $index; } - return $point1->distanceToTarget > $point2->distanceToTarget ? -1 : 1; - }); + if($point1 !== null){ + $this->pathPoints[$index] = $point; + $point->index = $index; + } + } + } + + protected function sortForward(int $index) : void{ + $point = $this->pathPoints[$index] ?? null; + if($point !== null){ + $f = $point->distanceToTarget; + + while(true){ + $i = 1 + ($index << 1); + $j = $i + 1; + + if($i >= $this->count){ + break; + } + + $point1 = $this->pathPoints[$i]; + $f1 = $point1->distanceToTarget; + + if($j >= $this->count){ + $point2 = null; + $f2 = PHP_INT_MAX; + }else{ + $point2 = $this->pathPoints[$j]; + $f2 = $point2->distanceToTarget; + } + + if($f1 < $f2){ + if($f1 >= $f){ + break; + } + + $this->pathPoints[$index] = $point1; + $point1->index = $index; + $index = $i; + }else{ + if($f2 >= $f){ + break; + } + + $this->pathPoints[$index] = $point2; + $point2->index = $index; + $index = $j; + } + } + + $this->pathPoints[$index] = $point; + $point->index = $index; + } + } - $this->pathPoints = array_values($this->pathPoints); // resort indexes + public function clearPath() : void{ + $this->count = 0; } public function isEmpty() : bool{ return $this->count === 0; } + + public function getCount() : int{ + return $this->count; + } } \ No newline at end of file From 133ea44d1758975ef6166184690a52b0c9368784 Mon Sep 17 00:00:00 2001 From: EmreTr1 Date: Wed, 13 Nov 2019 21:48:34 +0300 Subject: [PATCH 20/22] composer --- composer.lock | 54 ++++++++++++++++++-------------------- src/pocketmine/lang/locale | 2 +- 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/composer.lock b/composer.lock index 1aa6687668e..5fe5669b07e 100644 --- a/composer.lock +++ b/composer.lock @@ -92,16 +92,16 @@ }, { "name": "pocketmine/binaryutils", - "version": "0.1.9", + "version": "0.1.10", "source": { "type": "git", "url": "https://github.com/pmmp/BinaryUtils.git", - "reference": "8b3b1160679398387cb896fd5d06018413437dfa" + "reference": "435f2ee265bce75ef1aa9563f9b60ff36d705e80" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pmmp/BinaryUtils/zipball/8b3b1160679398387cb896fd5d06018413437dfa", - "reference": "8b3b1160679398387cb896fd5d06018413437dfa", + "url": "https://api.github.com/repos/pmmp/BinaryUtils/zipball/435f2ee265bce75ef1aa9563f9b60ff36d705e80", + "reference": "435f2ee265bce75ef1aa9563f9b60ff36d705e80", "shasum": "" }, "require": { @@ -119,23 +119,23 @@ ], "description": "Classes and methods for conveniently handling binary data", "support": { - "source": "https://github.com/pmmp/BinaryUtils/tree/0.1.9", + "source": "https://github.com/pmmp/BinaryUtils/tree/0.1", "issues": "https://github.com/pmmp/BinaryUtils/issues" }, - "time": "2019-07-22T13:15:53+00:00" + "time": "2019-10-21T14:40:32+00:00" }, { "name": "pocketmine/math", - "version": "0.2.2", + "version": "0.2.3", "source": { "type": "git", "url": "https://github.com/pmmp/Math.git", - "reference": "b755d3fb7025c4ddb7d9d6df0ba7e0b65125e51c" + "reference": "68be8a79fd0169043ef514797c304517cb8a6071" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pmmp/Math/zipball/b755d3fb7025c4ddb7d9d6df0ba7e0b65125e51c", - "reference": "b755d3fb7025c4ddb7d9d6df0ba7e0b65125e51c", + "url": "https://api.github.com/repos/pmmp/Math/zipball/68be8a79fd0169043ef514797c304517cb8a6071", + "reference": "68be8a79fd0169043ef514797c304517cb8a6071", "shasum": "" }, "require": { @@ -153,23 +153,23 @@ ], "description": "PHP library containing math related code used in PocketMine-MP", "support": { - "source": "https://github.com/pmmp/Math/tree/0.2.2", + "source": "https://github.com/pmmp/Math/tree/0.2", "issues": "https://github.com/pmmp/Math/issues" }, - "time": "2019-01-04T15:42:36+00:00" + "time": "2019-10-21T14:35:10+00:00" }, { "name": "pocketmine/nbt", - "version": "0.2.10", + "version": "0.2.11", "source": { "type": "git", "url": "https://github.com/pmmp/NBT.git", - "reference": "2db27aebe7dc89772aaa8df53361eef801f60063" + "reference": "78784b93632c51f0fad0719b2d6ffe072529db6d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pmmp/NBT/zipball/2db27aebe7dc89772aaa8df53361eef801f60063", - "reference": "2db27aebe7dc89772aaa8df53361eef801f60063", + "url": "https://api.github.com/repos/pmmp/NBT/zipball/78784b93632c51f0fad0719b2d6ffe072529db6d", + "reference": "78784b93632c51f0fad0719b2d6ffe072529db6d", "shasum": "" }, "require": { @@ -194,10 +194,10 @@ ], "description": "PHP library for working with Named Binary Tags", "support": { - "source": "https://github.com/pmmp/NBT/tree/0.2.10", + "source": "https://github.com/pmmp/NBT/tree/0.2", "issues": "https://github.com/pmmp/NBT/issues" }, - "time": "2019-07-22T15:22:23+00:00" + "time": "2019-10-21T14:50:43+00:00" }, { "name": "pocketmine/raklib", @@ -235,7 +235,7 @@ ], "description": "A RakNet server implementation written in PHP", "support": { - "source": "https://github.com/pmmp/RakLib/tree/0.12", + "source": "https://github.com/pmmp/RakLib/tree/0.12.5", "issues": "https://github.com/pmmp/RakLib/issues" }, "time": "2019-07-22T14:38:20+00:00" @@ -276,23 +276,20 @@ }, { "name": "pocketmine/spl", - "version": "0.3.2", + "version": "0.3.3", "source": { "type": "git", "url": "https://github.com/pmmp/SPL.git", - "reference": "7fd53857cd000491ba69e8db865792a024dd2c49" + "reference": "94d4df142fe837ba836e9348dd00209e4bdcc307" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pmmp/SPL/zipball/7fd53857cd000491ba69e8db865792a024dd2c49", - "reference": "7fd53857cd000491ba69e8db865792a024dd2c49", + "url": "https://api.github.com/repos/pmmp/SPL/zipball/94d4df142fe837ba836e9348dd00209e4bdcc307", + "reference": "94d4df142fe837ba836e9348dd00209e4bdcc307", "shasum": "" }, "type": "library", "autoload": { - "exclude-from-classmap": [ - "stubs" - ], "classmap": [ "./" ] @@ -302,9 +299,10 @@ ], "description": "Standard library files required by PocketMine-MP and related projects", "support": { - "source": "https://github.com/pmmp/SPL/tree/master" + "source": "https://github.com/pmmp/SPL/tree/0.3.3", + "issues": "https://github.com/pmmp/SPL/issues" }, - "time": "2018-08-12T15:17:39+00:00" + "time": "2019-10-28T11:41:20+00:00" } ], "packages-dev": [], diff --git a/src/pocketmine/lang/locale b/src/pocketmine/lang/locale index 73ed1ab3e1f..85343cfb7f7 160000 --- a/src/pocketmine/lang/locale +++ b/src/pocketmine/lang/locale @@ -1 +1 @@ -Subproject commit 73ed1ab3e1f2a1644fe908b439f8cf8ed6c12ab5 +Subproject commit 85343cfb7f7892bcb42ae7b7f594199cebca7d03 From c10ac35b6d75eb4844b9f28fb84677d6a179aa1b Mon Sep 17 00:00:00 2001 From: EmreTr1 Date: Wed, 13 Nov 2019 22:46:30 +0300 Subject: [PATCH 21/22] SwimNodeProcessor --- src/pocketmine/entity/object/ItemEntity.php | 2 +- .../pathfinding/navigate/PathNavigate.php | 2 +- .../processor/SwimNodeProcessor.php | 103 ++++++++++++++++++ .../entity/projectile/FishingHook.php | 2 +- src/pocketmine/entity/vehicle/Boat.php | 2 +- src/pocketmine/level/Level.php | 8 +- 6 files changed, 112 insertions(+), 7 deletions(-) create mode 100644 src/pocketmine/entity/pathfinding/processor/SwimNodeProcessor.php diff --git a/src/pocketmine/entity/object/ItemEntity.php b/src/pocketmine/entity/object/ItemEntity.php index 10351b24b7f..4be28d1bd10 100644 --- a/src/pocketmine/entity/object/ItemEntity.php +++ b/src/pocketmine/entity/object/ItemEntity.php @@ -163,7 +163,7 @@ protected function applyGravity() : void{ $bb2 = new AxisAlignedBB($bb->minX, $d1, $bb->minZ, $bb->maxX, $d3, $bb->maxZ); - if($this->level->isLiquidInBoundingBox($bb2, new Water())){ + if($this->level->isLiquidInBoundingBox($bb2)){ $waterCount += 0.2; } } diff --git a/src/pocketmine/entity/pathfinding/navigate/PathNavigate.php b/src/pocketmine/entity/pathfinding/navigate/PathNavigate.php index 81e8d750be8..c339d7c6f90 100644 --- a/src/pocketmine/entity/pathfinding/navigate/PathNavigate.php +++ b/src/pocketmine/entity/pathfinding/navigate/PathNavigate.php @@ -144,7 +144,7 @@ public function tick() : void{ if(!$this->noPath()){ $pos = $this->currentPath->getPosition(); if($pos !== null){ - $this->theEntity->getMoveHelper()->moveTo($pos->x, $pos->y + 0, $pos->z, $this->speed); + $this->theEntity->getMoveHelper()->moveTo($pos->x + 0.5, $pos->y, $pos->z + 0.5, $this->speed); } } } diff --git a/src/pocketmine/entity/pathfinding/processor/SwimNodeProcessor.php b/src/pocketmine/entity/pathfinding/processor/SwimNodeProcessor.php new file mode 100644 index 00000000000..f9dbf1f7449 --- /dev/null +++ b/src/pocketmine/entity/pathfinding/processor/SwimNodeProcessor.php @@ -0,0 +1,103 @@ +shouldAvoidWater = $this->avoidsWater; + } + + public function postProcess() : void{ + $this->avoidsWater = $this->shouldAvoidWater; + } + + public function getPathPointTo(Entity $entity) : PathPoint{ + return $this->openPoint(floor($entity->getBoundingBox()->minX), floor($entity->getBoundingBox()->minX + 0.5), floor($entity->getBoundingBox()->minZ)); + } + + public function getPathPointToCoords(Entity $entity, float $x, float $y, float $z) : PathPoint{ + return $this->openPoint(floor($x - ($entity->width / 2)), floor($y + 0.5), floor($z - ($entity->width / 2))); + } + + public function findPathOptions(array &$pathOptions, Entity $entity, PathPoint $currentPoint, PathPoint $targetPoint, float $maxDistance) : int{ + $i = 0; + + foreach([Vector3::SIDE_DOWN, Vector3::SIDE_UP, Vector3::SIDE_EAST, Vector3::SIDE_SOUTH, Vector3::SIDE_WEST, Vector3::SIDE_NORTH] as $side){ + $vec = $currentPoint->getSide($side); + $point = $this->getSafePoint($entity, $vec->x, $vec->y, $vec->z); + + if($point !== null and !$point->visited and $point->distanceSquared($targetPoint) < $maxDistance){ + $pathOptions[$i++] = $point; + } + } + + return $i; + } + + protected function getSafePoint(Entity $entity, float $x, float $y, float $z) : ?PathPoint{ + return $this->isFullyWater($x, $y, $z) ? $this->openPoint($x, $y, $z) : null; + } + + protected function isFullyWater(float $x, float $y, float $z) : bool{ + $tempVector = new Vector3(); + + for($x1 = $x; $x1 < $x + $this->entityBlockBox->maxX; $x1++){ + for($y1 = $y; $y1 < $y + $this->entityBlockBox->maxY; $y1++){ + for($z1 = $z; $z1 < $z + $this->entityBlockBox->maxZ; $z1++){ + $block = $this->level->getBlock($tempVector->setComponents($x1, $y1, $z1)); + + if(!($block instanceof Water)){ + return false; + } + } + } + } + + return true; + } +} \ No newline at end of file diff --git a/src/pocketmine/entity/projectile/FishingHook.php b/src/pocketmine/entity/projectile/FishingHook.php index 1665f314959..82610f78de8 100644 --- a/src/pocketmine/entity/projectile/FishingHook.php +++ b/src/pocketmine/entity/projectile/FishingHook.php @@ -170,7 +170,7 @@ public function onUpdate(int $currentTick) : bool{ $bb2 = new AxisAlignedBB($bb->minX, $d1, $bb->minZ, $bb->maxX, $d3, $bb->maxZ); - if($this->level->isLiquidInBoundingBox($bb2, new Water())){ + if($this->level->isLiquidInBoundingBox($bb2)){ $d10 += 0.2; } } diff --git a/src/pocketmine/entity/vehicle/Boat.php b/src/pocketmine/entity/vehicle/Boat.php index 2828a050d8a..8851ccdf448 100644 --- a/src/pocketmine/entity/vehicle/Boat.php +++ b/src/pocketmine/entity/vehicle/Boat.php @@ -175,7 +175,7 @@ public function onUpdate(int $currentTick) : bool{ $bb2 = new AxisAlignedBB($bb->minX, $d1, $bb->minZ, $bb->maxX, $d3, $bb->maxZ); - if($this->level->isLiquidInBoundingBox($bb2, new Water())){ + if($this->level->isLiquidInBoundingBox($bb2)){ $waterCount += 0.2; } } diff --git a/src/pocketmine/level/Level.php b/src/pocketmine/level/Level.php index e43bbe04d31..f47f700b384 100644 --- a/src/pocketmine/level/Level.php +++ b/src/pocketmine/level/Level.php @@ -29,7 +29,9 @@ use pocketmine\block\Air; use pocketmine\block\Block; use pocketmine\block\BlockFactory; +use pocketmine\block\Lava; use pocketmine\block\Liquid; +use pocketmine\block\Water; use pocketmine\entity\CreatureType; use pocketmine\entity\Entity; use pocketmine\entity\object\ExperienceOrb; @@ -1341,11 +1343,11 @@ public function getCollisionBlocks(AxisAlignedBB $bb, bool $targetFirst = false) /** * @param AxisAlignedBB $bb - * @param Liquid $material + * @param bool $isLava * * @return bool */ - public function isLiquidInBoundingBox(AxisAlignedBB $bb, Liquid $material) : bool{ + public function isLiquidInBoundingBox(AxisAlignedBB $bb, bool $isLava = false) : bool{ $minX = (int) floor($bb->minX); $minY = (int) floor($bb->minY); $minZ = (int) floor($bb->minZ); @@ -1358,7 +1360,7 @@ public function isLiquidInBoundingBox(AxisAlignedBB $bb, Liquid $material) : boo for($z = $minZ; $z < $maxZ; ++$z){ $block = $this->getBlockAt($x, $y, $z); - if($block instanceof $material){ + if(($isLava and $block instanceof Lava) or (!$isLava and $block instanceof Water)){ $j2 = $block->getDamage(); $d0 = $y + 1; From ee47c526b926a5d220a53974715bd62500a89e81 Mon Sep 17 00:00:00 2001 From: EmreTr1 Date: Sun, 23 Aug 2020 00:20:07 +0300 Subject: [PATCH 22/22] Some fixes --- src/pocketmine/entity/Entity.php | 10 ++++---- src/pocketmine/entity/WaterAnimal.php | 6 +++++ .../entity/behavior/SwimWanderBehavior.php | 4 +++- src/pocketmine/entity/hostile/Dolphin.php | 1 - .../entity/hostile/ZombieVillager.php | 6 ++--- src/pocketmine/entity/passive/PolarBear.php | 2 +- .../entity/passive/TropicalFish.php | 23 +++++++++++++++++++ .../pathfinding/navigate/PathNavigate.php | 5 ++-- .../navigate/PathNavigateGround.php | 4 ++-- src/pocketmine/resources/vanilla | 2 +- 10 files changed, 46 insertions(+), 17 deletions(-) diff --git a/src/pocketmine/entity/Entity.php b/src/pocketmine/entity/Entity.php index 7d53d5f85bf..537265e63f1 100644 --- a/src/pocketmine/entity/Entity.php +++ b/src/pocketmine/entity/Entity.php @@ -419,20 +419,20 @@ public static function init() : void{ Entity::registerEntity(Villager::class, false, ['Villager', 'minecraft:villager']); Entity::registerEntity(Wolf::class, false, ['Wolf', 'minecraft:wolf']); Entity::registerEntity(Zombie::class, false, ['Zombie', 'minecraft:zombie']); - Entity::registerEntity(ZombieHorse::class, false, ['ZombieHorse', 'minecraft:zombiehorse']); + Entity::registerEntity(ZombieHorse::class, false, ['ZombieHorse', 'minecraft:zombie_horse']); Entity::registerEntity(Cow::class, false, ['Cow', 'minecraft:cow']); Entity::registerEntity(Sheep::class, false, ['Sheep', 'minecraft:sheep']); Entity::registerEntity(Mooshroom::class, false, ['Mooshroom', 'minecraft:mooshroom']); Entity::registerEntity(Ocelot::class, false, ['Ocelot', 'minecraft:ocelot']); Entity::registerEntity(Pig::class, false, ['Pig', 'minecraft:pig']); - Entity::registerEntity(ZombiePigman::class, false, ['ZombiePigman', 'minecraft:zombiepigman']); - Entity::registerEntity(ZombieVillager::class, false, ['ZombieVillager', 'minecraft:zombievillager']); - Entity::registerEntity(WitherSkeleton::class, false, ['WitherSkeleton', 'minecraft:witherskeleon']); + Entity::registerEntity(ZombiePigman::class, false, ['ZombiePigman', 'minecraft:zombie_pigman']); + Entity::registerEntity(ZombieVillager::class, false, ['ZombieVillager', 'minecraft:zombie_villager']); + Entity::registerEntity(WitherSkeleton::class, false, ['WitherSkeleton', 'minecraft:wither_skeleon']); Entity::registerEntity(PolarBear::class, false, ['PolarBear', 'minecraft:polarbear']); Entity::registerEntity(Rabbit::class, false, ['Rabbit', 'minecraft:rabbit']); Entity::registerEntity(Cat::class, false, ['Cat', 'minecraft:cat']); Entity::registerEntity(Skeleton::class, false, ['Skeleton', 'minecraft:skeleton']); - Entity::registerEntity(SkeletonHorse::class, false, ['SkeletonHorse', 'minecraft:skeletonhorse']); + Entity::registerEntity(SkeletonHorse::class, false, ['SkeletonHorse', 'minecraft:skeleton_horse']); Entity::registerEntity(Stray::class, false, ['Stray', 'minecraft:stray']); Entity::registerEntity(Husk::class, false, ['Husk', 'minecraft:husk']); Entity::registerEntity(Chicken::class, false, ['Chicken', 'minecraft:chicken']); diff --git a/src/pocketmine/entity/WaterAnimal.php b/src/pocketmine/entity/WaterAnimal.php index d21792af9a7..5f77f929ebb 100644 --- a/src/pocketmine/entity/WaterAnimal.php +++ b/src/pocketmine/entity/WaterAnimal.php @@ -23,7 +23,9 @@ namespace pocketmine\entity; +use pocketmine\block\Water; use pocketmine\event\entity\EntityDamageEvent; +use pocketmine\math\Vector3; abstract class WaterAnimal extends Mob implements Ageable{ @@ -41,6 +43,10 @@ public function canSpawnHere() : bool{ return true; } + public function getBlockPathWeight(Vector3 $pos) : float{ + return $this->level->getBlock($pos) instanceof Water ? 10 : 0; + } + public function onAirExpired() : void{ $ev = new EntityDamageEvent($this, EntityDamageEvent::CAUSE_SUFFOCATION, 2); $this->attack($ev); diff --git a/src/pocketmine/entity/behavior/SwimWanderBehavior.php b/src/pocketmine/entity/behavior/SwimWanderBehavior.php index cd98891a838..2bd50a71ae1 100644 --- a/src/pocketmine/entity/behavior/SwimWanderBehavior.php +++ b/src/pocketmine/entity/behavior/SwimWanderBehavior.php @@ -55,7 +55,9 @@ public function canContinue() : bool{ public function onStart() : void{ $this->mob->pitch = 0; - $this->mob->yaw = $this->random->nextFloat() * 360; + $this->mob->yaw = $this->random->nextBoundedInt(360); + $this->mob->headYaw = $this->mob->yaw; + $this->mob->yawOffset = $this->mob->yaw; $this->mob->setMoveForward($speed = $this->speedMultiplier * $this->mob->getMovementSpeed()); $this->mob->setAIMoveSpeed($speed); } diff --git a/src/pocketmine/entity/hostile/Dolphin.php b/src/pocketmine/entity/hostile/Dolphin.php index 66e41200b3d..767a08fd460 100644 --- a/src/pocketmine/entity/hostile/Dolphin.php +++ b/src/pocketmine/entity/hostile/Dolphin.php @@ -82,7 +82,6 @@ private function generateRandomDirection() : Vector3{ return new Vector3(mt_rand(-1000, 1000) / 1000, mt_rand(-500, 500) / 1000, mt_rand(-1000, 1000) / 1000); } - public function entityBaseTick(int $tickDiff = 1) : bool{ if($this->closed){ return false; diff --git a/src/pocketmine/entity/hostile/ZombieVillager.php b/src/pocketmine/entity/hostile/ZombieVillager.php index 0aa9100bf89..2300b23e016 100644 --- a/src/pocketmine/entity/hostile/ZombieVillager.php +++ b/src/pocketmine/entity/hostile/ZombieVillager.php @@ -25,10 +25,10 @@ namespace pocketmine\entity\hostile; use pocketmine\entity\Ageable; -use pocketmine\entity\behavior\FindAttackableTargetBehavior; use pocketmine\entity\behavior\FloatBehavior; use pocketmine\entity\behavior\LookAtPlayerBehavior; use pocketmine\entity\behavior\MeleeAttackBehavior; +use pocketmine\entity\behavior\NearestAttackableTargetBehavior; use pocketmine\entity\behavior\RandomLookAroundBehavior; use pocketmine\entity\behavior\RandomStrollBehavior; use pocketmine\entity\Monster; @@ -90,8 +90,8 @@ protected function addBehaviors() : void{ $this->behaviorPool->setBehavior(3, new LookAtPlayerBehavior($this, 8.0)); $this->behaviorPool->setBehavior(4, new RandomLookAroundBehavior($this)); - $this->targetBehaviorPool->setBehavior(1, new FindAttackableTargetBehavior($this, Player::class)); - $this->targetBehaviorPool->setBehavior(2, new FindAttackableTargetBehavior($this, Villager::class)); + $this->targetBehaviorPool->setBehavior(1, new NearestAttackableTargetBehavior($this, Player::class)); + $this->targetBehaviorPool->setBehavior(2, new NearestAttackableTargetBehavior($this, Villager::class)); } public function entityBaseTick(int $diff = 1) : bool{ diff --git a/src/pocketmine/entity/passive/PolarBear.php b/src/pocketmine/entity/passive/PolarBear.php index 0cb1c4b8e27..1ac9344066d 100644 --- a/src/pocketmine/entity/passive/PolarBear.php +++ b/src/pocketmine/entity/passive/PolarBear.php @@ -52,6 +52,7 @@ protected function addBehaviors() : void{ $this->behaviorPool->setBehavior(5, new LookAtPlayerBehavior($this, 16.0)); $this->behaviorPool->setBehavior(6, new RandomLookAroundBehavior($this)); + //TODO: attack to foxes $this->targetBehaviorPool->setBehavior(0, new HurtByTargetBehavior($this)); } @@ -63,7 +64,6 @@ public function initEntity() : void{ parent::initEntity(); } - //TODO: attack fixes public function getName() : string{ return "Polar Bear"; } diff --git a/src/pocketmine/entity/passive/TropicalFish.php b/src/pocketmine/entity/passive/TropicalFish.php index 135610dd7ba..2e21b1ae465 100644 --- a/src/pocketmine/entity/passive/TropicalFish.php +++ b/src/pocketmine/entity/passive/TropicalFish.php @@ -26,11 +26,13 @@ use pocketmine\entity\behavior\AvoidMobTypeBehavior; use pocketmine\entity\behavior\RandomSwimBehavior; use pocketmine\entity\behavior\SwimWanderBehavior; +use pocketmine\entity\helper\EntityLookHelper; use pocketmine\entity\WaterAnimal; use pocketmine\item\Item; use pocketmine\item\ItemFactory; use pocketmine\nbt\tag\ByteTag; use pocketmine\nbt\tag\IntTag; +use pocketmine\network\mcpe\protocol\LevelSoundEventPacket; use pocketmine\Player; use function mt_rand; @@ -120,6 +122,27 @@ public function getDrops() : array{ return $drops; } + public function entityBaseTick(int $tickDiff = 1) : bool{ + if(!$this->isInsideOfWater()){ + $this->jumpHelper->setJumping(true); + } + + return parent::entityBaseTick($tickDiff); + } + + public function jump() : void{ + parent::jump(); + + $this->yaw = $this->random->nextBoundedInt(360); + $this->headYaw = $this->yaw; + $this->yawOffset = $this->yaw; + + $this->setAIMoveSpeed($speed = $this->getMovementSpeed() * 2); + $this->setMoveForward($speed); + + $this->level->broadcastLevelSoundEvent($this, LevelSoundEventPacket::SOUND_JUMP, -1, self::TROPICAL_FISH); + } + protected function applyGravity() : void{ if(!$this->isUnderwater()){ parent::applyGravity(); diff --git a/src/pocketmine/entity/pathfinding/navigate/PathNavigate.php b/src/pocketmine/entity/pathfinding/navigate/PathNavigate.php index c339d7c6f90..63a8adf3316 100644 --- a/src/pocketmine/entity/pathfinding/navigate/PathNavigate.php +++ b/src/pocketmine/entity/pathfinding/navigate/PathNavigate.php @@ -41,9 +41,9 @@ abstract class PathNavigate{ /** @var PathEntity|null */ protected $currentPath; /** @var float */ - protected $speed; + protected $speed = 1.0; - private $pathSearchRange = 0; + private $pathSearchRange = 16; private $totalTicks = 0; private $ticksAtLastPos = 0; private $lastPosCheck; @@ -54,7 +54,6 @@ abstract class PathNavigate{ public function __construct(Mob $entity){ $this->theEntity = $entity; $this->level = $entity->getLevel(); - $this->pathSearchRange = 16; $this->pathFinder = $this->getPathFinder(); $this->lastPosCheck = new Vector3(); } diff --git a/src/pocketmine/entity/pathfinding/navigate/PathNavigateGround.php b/src/pocketmine/entity/pathfinding/navigate/PathNavigateGround.php index e3cb3f75138..d7f9cafd0dd 100644 --- a/src/pocketmine/entity/pathfinding/navigate/PathNavigateGround.php +++ b/src/pocketmine/entity/pathfinding/navigate/PathNavigateGround.php @@ -103,8 +103,8 @@ protected function removeSunnyPath() : void{ public function isDirectPathBetweenPoints(Vector3 $from, Vector3 $to, Vector3 $size) : bool{ $currentX = $from->getFloorX(); $currentZ = $from->getFloorZ(); - $dX = $to->x - $from->x; - $dZ = $to->z - $from->z; + $dX = $to->x - $from->x + 0.001; + $dZ = $to->z - $from->z + 0.001; $distNormal = 1 / sqrt($dX ** 2 + $dZ ** 2); $dX *= $distNormal; $dZ *= $distNormal; diff --git a/src/pocketmine/resources/vanilla b/src/pocketmine/resources/vanilla index afc885cccae..fcd3a215633 160000 --- a/src/pocketmine/resources/vanilla +++ b/src/pocketmine/resources/vanilla @@ -1 +1 @@ -Subproject commit afc885cccae38048d309911f2c5ddcdcb6af8152 +Subproject commit fcd3a2156331d80591aa374677dad5238ea14054