├── plugin.yml ├── resources └── auto-update.yml └── src └── onebone └── artificialintelligent ├── ArtificialIntelligent.php ├── TickTask.php └── entity ├── BaseEntity.php ├── Cow.php ├── MovingEntity.php ├── Pig.php └── Sheep.php /plugin.yml: -------------------------------------------------------------------------------- 1 | name: ArtificialIntelligent 2 | version: "0.1" 3 | author: onebone 4 | main: onebone\artificialintelligent\ArtificialIntelligent 5 | api: [1.12.0] 6 | -------------------------------------------------------------------------------- /resources/auto-update.yml: -------------------------------------------------------------------------------- 1 | enabled: true 2 | force-update: true 3 | -------------------------------------------------------------------------------- /src/onebone/artificialintelligent/ArtificialIntelligent.php: -------------------------------------------------------------------------------- 1 | saveResource("auto-update.yml"); 43 | 44 | $update = new Config($this->getDataFolder()."auto-update.yml", Config::YAML); 45 | if($update->get("enabled")){ 46 | try{ 47 | $url = "http://onebone.me/plugins/artificialintelligent/api/?version=".$this->getDescription()->getVersion(); 48 | $content = Utils::getUrl($url); 49 | 50 | $data = json_decode($content, true); 51 | if($data["update-available"] === true){ 52 | $this->getLogger()->notice("New version of ArtificialIntelligent was released. Version : ".$data["new-version"]); 53 | if($update->get("force-update") and $this->isPhar()){ 54 | $address = file_get_contents($data["download-address"]); 55 | $e = explode("/", $data["download-address"]); 56 | $filename = end($e); 57 | file_put_contents($this->getDataFolder()."../".$filename, $address); 58 | if($this->isPhar()){ 59 | $file = substr($this->getFile(), 7, -1); 60 | @unlink($file); 61 | } 62 | 63 | $this->getLogger()->notice("ArtificialIntelligent was updated automatically to version ".$data["new-version"]); 64 | $this->getServer()->shutdown(); 65 | return; 66 | } 67 | }else{ 68 | $this->getLogger()->notice("ArtificialIntelligent is currently up-to-date."); 69 | } 70 | if($data["notice"] !== ""){ 71 | $this->getLogger()->notice($data["notice"]); 72 | } 73 | }catch(\Exception $e){ 74 | $this->getLogger()->error("Error while retrieving data from server : \n".$e); 75 | } 76 | } 77 | 78 | $this->getServer()->getScheduler()->scheduleDelayedRepeatingTask(new TickTask($this), 240, 240); 79 | 80 | $this->getServer()->getPluginManager()->registerEvents($this, $this); 81 | } 82 | 83 | public function onSpawn(EntitySpawnEvent $event){ 84 | $entity = $event->getEntity(); 85 | 86 | if($entity instanceof Sheep or $entity instanceof Cow or $entity instanceof Pig){ 87 | $this->entities[$entity->getId()] = $entity; 88 | } 89 | } 90 | 91 | public function onUpdate($currentTick){ 92 | $spawnLimit = $this->getServer()->getProperty("spawn-limits", ["animals" => 15])["animals"]; 93 | 94 | if($spawnLimit >= count($this->entities)){ 95 | $players = $this->getServer()->getOnlinePlayers(); 96 | if(count($players) <= 0) return; 97 | $player = $players[array_rand($players)]; 98 | 99 | $x = $player->getX() + mt_rand(-50, 50); 100 | $z = $player->getZ() + mt_rand(-50, 50); 101 | 102 | $y = $player->getLevel()->getHighestBlockAt($x, $z) + 1; 103 | Entity::createEntity(self::$registered[array_rand(self::$registered)], $player->getLevel()->getChunk($x >> 4, $z >> 4), new Compound("", [ 104 | "Pos" => new Enum("Pos", [ 105 | new Double("", $x), 106 | new Double("", $y), 107 | new Double("", $z) 108 | ]), 109 | "Motion" => new Enum("Motion", [ 110 | new Double("", 0), 111 | new Double("", 0), 112 | new Double("", 0) 113 | ]), 114 | "Rotation" => new Enum("Rotation", [ 115 | new Float("", 0), 116 | new Float("", 0) 117 | ]), 118 | ])); 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/onebone/artificialintelligent/TickTask.php: -------------------------------------------------------------------------------- 1 | getOwner()->onUpdate($currentTick); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/onebone/artificialintelligent/entity/BaseEntity.php: -------------------------------------------------------------------------------- 1 | processMove(); 26 | } 27 | } 28 | 29 | public function processMove(){ 30 | if($this->target instanceof Vector3){ 31 | $xDiff = $this->target->x - $this->x; 32 | $zDiff = $this->target->z - $this->z; 33 | if($xDiff ** 2 + $zDiff ** 2 < 2){ 34 | $this->target = null; 35 | return; 36 | } 37 | $diff = abs($xDiff) + abs($zDiff); 38 | $speed = 0.1; 39 | $this->motionX = $speed * (($this->target->x - $this->x) / $diff); 40 | $this->motionZ = $speed * (($this->target->z - $this->z) / $diff); 41 | 42 | $radius = $this->width / 2; 43 | 44 | $boundingBox = new AxisAlignedBB(round($this->x - $radius + ($this->motionX * 10)), $this->y, round($this->z - $radius + ($this->motionZ * 10)), round($this->x + $radius + ($this->motionX * 10)), ceil($this->y + $this->height), round($this->z + $radius + ($this->motionZ * 10))); 45 | 46 | $block = $this->getLevel()->getBlock($this->getSide(0)); 47 | 48 | if(!$block->isSolid()){ 49 | $this->motionY -= $this->gravity; 50 | }else{ 51 | $this->motionY = 0; 52 | } 53 | 54 | $collision = $this->getLevel()->getCollisionCubes($this, $boundingBox, false); 55 | $height = 0; 56 | foreach($collision as $block){ 57 | $height += ($block->maxY - $block->minY); 58 | } 59 | 60 | if($height > 1){ 61 | $this->motionX = 0; 62 | $this->motionZ = 0; 63 | $this->target = null; 64 | return; 65 | }elseif($height > 0){ 66 | $this->motionY = 0.25; 67 | } 68 | 69 | $angle = atan2($this->target->z - $this->z, $this->target->x - $this->x); 70 | $this->yaw = (($angle * 180) / M_PI) - 90; 71 | 72 | $this->move($this->motionX, $this->motionY, $this->motionZ); 73 | 74 | $this->getLevel()->addEntityMovement($this->chunk->getX(), $this->chunk->getZ(), $this->id, $this->x, $this->y, $this->z, $this->yaw, $this->pitch); 75 | }else{ 76 | $this->motionX = 0; 77 | $this->motionZ = 0; 78 | $rand = mt_rand(1, 150); 79 | if($rand === 1){ 80 | $this->target = new Vector3($this->x + rand(-8, 8), $this->y, $this->z + rand(-8, 8)); 81 | }elseif($rand > 1 and $rand < 5){ 82 | $this->yaw = max(-180, min(180, ($this->yaw + rand(-90, 90)))); 83 | $this->getLevel()->addEntityMovement($this->chunk->getX(), $this->chunk->getZ(), $this->id, $this->x, $this->y, $this->z, $this->yaw, $this->pitch); 84 | } 85 | if(!$this->getLevel()->getBlock($this->round())->isSolid()){ 86 | $this->motionY -= $this->gravity; 87 | }else{ 88 | $this->motionY = 0; 89 | } 90 | $this->move($this->motionX, $this->motionY, $this->motionZ); 91 | } 92 | } 93 | 94 | public function kill(){ 95 | if(!$this->isAlive() or $this->closed){ 96 | return; 97 | } 98 | 99 | $pk = new EntityEventPacket(); 100 | $pk->eid = $this->id; 101 | $pk->event = EntityEventPacket::DEATH_ANIMATION; 102 | foreach($this->getLevel()->getPlayers() as $player){ 103 | $player->dataPacket($pk->setChannel(Network::CHANNEL_WORLD_EVENTS)); 104 | } 105 | 106 | parent::kill(); 107 | } 108 | 109 | public function attack($damage, EntityDamageEvent $source){ 110 | parent::attack($damage, $source); 111 | 112 | if(!$source->isCancelled()){ 113 | $pk = new EntityEventPacket(); 114 | $pk->eid = $this->id; 115 | $pk->event = EntityEventPacket::HURT_ANIMATION; 116 | foreach($this->getLevel()->getPlayers() as $player){ 117 | $player->dataPacket($pk->setChannel(Network::CHANNEL_WORLD_EVENTS)); 118 | } 119 | /* if($source instanceof EntityDamageByEntityEvent){ 120 | $e = $source->getDamager(); 121 | if($source instanceof EntityDamageByChildEntityEvent){ 122 | $e = $source->getChild(); 123 | } 124 | 125 | $deltaX = $this->x - $e->x; 126 | $deltaZ = $this->z - $e->z; 127 | $this->knockBack($e, $damage, $deltaX, $deltaZ, $source->getKnockBack()); 128 | }*/ 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/onebone/artificialintelligent/entity/Cow.php: -------------------------------------------------------------------------------- 1 | width = 1; 18 | $this->height = 1; 19 | } 20 | 21 | public function getName(){ 22 | return "Cow"; 23 | } 24 | 25 | public function spawnTo(Player $player){ 26 | $pk = new AddEntityPacket(); 27 | $pk->eid = $this->getId(); 28 | $pk->type = self::NETWORK_ID; 29 | $pk->x = $this->x; 30 | $pk->y = $this->y; 31 | $pk->z = $this->z; 32 | $pk->speedX = $this->motionX; 33 | $pk->speedY = $this->motionY; 34 | $pk->speedZ = $this->motionZ; 35 | $pk->yaw = $this->yaw; 36 | $pk->pitch = $this->pitch; 37 | $pk->metadata = $this->dataProperties; 38 | $player->dataPacket($pk); 39 | 40 | parent::spawnTo($player); 41 | } 42 | 43 | public function processMove(){ 44 | $targetSet = false; 45 | $entities = $this->getLevel()->getNearbyEntities(new AxisAlignedBB($this->x - 7, $this->y - 3, $this->z - 7, $this->x + 7, $this->y + 3, $this->z + 7)); 46 | foreach($entities as $entity){ 47 | if($entity instanceof Player){ 48 | if($entity->getInventory()->getItemInHand()->getId() === 296){ 49 | $this->target = $entity; 50 | $targetSet = true; 51 | break; 52 | } 53 | } 54 | } 55 | if($targetSet === false){ 56 | if($this->target instanceof Player){ 57 | $this->target = null; 58 | } 59 | } 60 | parent::processMove(); 61 | } 62 | 63 | public function getDrops(){ 64 | return [ 65 | Item::get(Item::LEATHER, 0, mt_rand(0, 2)), 66 | Item::get(Item::RAW_BEEF, 0, mt_rand(1, 3)) 67 | ]; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/onebone/artificialintelligent/entity/MovingEntity.php: -------------------------------------------------------------------------------- 1 | width = 1; 18 | $this->height = 1; 19 | } 20 | 21 | public function getName(){ 22 | return "Pig"; 23 | } 24 | 25 | public function spawnTo(Player $player){ 26 | $pk = new AddEntityPacket(); 27 | $pk->eid = $this->getId(); 28 | $pk->type = self::NETWORK_ID; 29 | $pk->x = $this->x; 30 | $pk->y = $this->y; 31 | $pk->z = $this->z; 32 | $pk->speedX = $this->motionX; 33 | $pk->speedY = $this->motionY; 34 | $pk->speedZ = $this->motionZ; 35 | $pk->yaw = $this->yaw; 36 | $pk->pitch = $this->pitch; 37 | $pk->metadata = $this->dataProperties; 38 | $player->dataPacket($pk); 39 | 40 | parent::spawnTo($player); 41 | } 42 | 43 | public function processMove(){ 44 | $targetSet = false; 45 | $entities = $this->getLevel()->getNearbyEntities(new AxisAlignedBB($this->x - 7, $this->y - 3, $this->z - 7, $this->x + 7, $this->y + 3, $this->z + 7)); 46 | foreach($entities as $entity){ 47 | if($entity instanceof Player){ 48 | if($entity->getInventory()->getItemInHand()->getId() === 391){ 49 | $this->target = $entity; 50 | $targetSet = true; 51 | break; 52 | } 53 | } 54 | } 55 | if($targetSet === false){ 56 | if($this->target instanceof Player){ 57 | $this->target = null; 58 | } 59 | } 60 | parent::processMove(); 61 | } 62 | 63 | public function getDrops(){ 64 | return [ 65 | Item::get(Item::RAW_PORKCHOP, 0, mt_rand(1, 3)) 66 | ]; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/onebone/artificialintelligent/entity/Sheep.php: -------------------------------------------------------------------------------- 1 | width = 1; 20 | $this->height = 1; 21 | } 22 | 23 | public function getName(){ 24 | return "Sheep"; 25 | } 26 | 27 | public function spawnTo(Player $player){ 28 | $pk = new AddEntityPacket(); 29 | $pk->eid = $this->getId(); 30 | $pk->type = self::NETWORK_ID; 31 | $pk->x = $this->x; 32 | $pk->y = $this->y; 33 | $pk->z = $this->z; 34 | $pk->speedX = $this->motionX; 35 | $pk->speedY = $this->motionY; 36 | $pk->speedZ = $this->motionZ; 37 | $pk->yaw = $this->yaw; 38 | $pk->pitch = $this->pitch; 39 | $pk->metadata = $this->dataProperties; 40 | $player->dataPacket($pk); 41 | 42 | parent::spawnTo($player); 43 | } 44 | 45 | public function processMove(){ 46 | $targetSet = false; 47 | 48 | $entities = $this->getLevel()->getNearbyEntities(new AxisAlignedBB($this->x - 7, $this->y - 3, $this->z - 7, $this->x + 7, $this->y + 3, $this->z + 7)); 49 | foreach($entities as $entity){ 50 | if($entity instanceof Player){ 51 | if($entity->getInventory()->getItemInHand()->getId() === 296){ 52 | $this->target = $entity; 53 | $targetSet = true; 54 | break; 55 | } 56 | } 57 | } 58 | if($targetSet === false){ 59 | if($this->target instanceof Player){ 60 | $this->target = null; 61 | } 62 | } 63 | 64 | if($this->motionX === 0 and $this->motionZ === 0){ 65 | $rand = mt_rand(1, 1000); 66 | if($rand < 10 and $this->getLevel()->getBlock(($pos = $this->subtract(0, 1, 0)))->getId() === 2){ 67 | $pk = new EntityEventPacket(); 68 | $pk->eid = $this->id; 69 | $pk->event = $rand === 1 ? EntityEventPacket::EAT_GRASS_ANIMATION : EntityEventPacket::AMBIENT_SOUND; 70 | foreach($this->getLevel()->getPlayers() as $player){ 71 | $player->dataPacket($pk->setChannel(Network::CHANNEL_WORLD_EVENTS)); 72 | } 73 | 74 | if($rand === 1) 75 | $this->getLevel()->setBlock($pos, Block::get(Block::DIRT)); 76 | } 77 | } 78 | parent::processMove(); 79 | } 80 | 81 | public function getDrops(){ 82 | return [ 83 | Item::get(Item::WOOL, 0, 1) 84 | ]; 85 | } 86 | } 87 | --------------------------------------------------------------------------------