shootingEntity = $shootingEntity; parent::__construct($chunk, $nbt); } protected function initEntity(){ $this->namedtag->id = new String("id", "Arrow"); $this->setMaxHealth(1); $this->setHealth(1); if(isset($this->namedtag->Age)){ $this->age = $this->namedtag["Age"]; } } public function onUpdate($currentTick){ if($this->closed){ return false; } $this->timings->startTiming(); $tickDiff = max(1, $currentTick - $this->lastUpdate); $this->lastUpdate = $currentTick; $hasUpdate = $this->entityBaseTick($tickDiff); if(!$this->dead){ $movingObjectPosition = null; $this->motionY -= $this->gravity; $this->keepMovement = $this->checkObstruction($this->x, ($this->boundingBox->minY + $this->boundingBox->maxY) / 2, $this->z); $moveVector = Vector3::createVector($this->x + $this->motionX, $this->y + $this->motionY, $this->z + $this->motionZ); $list = $this->getLevel()->getCollidingEntities($this->boundingBox->addCoord($this->motionX, $this->motionY, $this->motionZ)->expand(1, 1, 1), $this); $nearDistance = PHP_INT_MAX; $nearEntity = null; foreach($list as $entity){ if(/*!$entity->canCollideWith($this) or */ ($entity === $this->shootingEntity and $this->ticksLived < 5) ){ continue; } $axisalignedbb = $entity->boundingBox->grow(0.3, 0.3, 0.3); $ob = $axisalignedbb->calculateIntercept($this, $moveVector); if($ob === null){ continue; } $distance = $this->distance($ob->hitVector); if($distance < $nearDistance){ $nearDistance = $distance; $nearEntity = $entity; } } if($nearEntity !== null){ $movingObjectPosition = MovingObjectPosition::fromEntity($nearEntity); } if($movingObjectPosition !== null){ if($movingObjectPosition->entityHit !== null){ $this->server->getPluginManager()->callEvent(ProjectileHitEvent::createEvent($this)); $motion = sqrt($this->motionX ** 2 + $this->motionY ** 2 + $this->motionZ ** 2); $damage = ceil($motion * $this->damage); $ev = EntityDamageByEntityEvent::createEvent($this->shootingEntity === null ? $this : $this->shootingEntity, $movingObjectPosition->entityHit, EntityDamageEvent::CAUSE_PROJECTILE, $damage); $this->server->getPluginManager()->callEvent($ev); if(!$ev->isCancelled()){ $movingObjectPosition->entityHit->attack($ev->getFinalDamage(), $ev); } if($this->fireTicks > 0){ $ev = EntityCombustByEntityEvent::createEvent($this, $movingObjectPosition->entityHit, 5); $this->server->getPluginManager()->callEvent($ev); if(!$ev->isCancelled()){ $movingObjectPosition->entityHit->setOnFire($ev->getDuration()); } } $this->kill(); return true; } } $this->move($this->motionX, $this->motionY, $this->motionZ); if($this->onGround and ($this->motionX != 0 or $this->motionY != 0 or $this->motionZ != 0)){ $this->motionX = 0; $this->motionY = 0; $this->motionZ = 0; $this->server->getPluginManager()->callEvent(ProjectileHitEvent::createEvent($this)); } if(!$this->onGround or $this->motionX != 0 or $this->motionY != 0 or $this->motionZ != 0){ $f = sqrt(($this->motionX ** 2) + ($this->motionZ ** 2)); $this->yaw = (atan2($this->motionX, $this->motionZ) * 180 / M_PI); $this->pitch = (atan2($this->motionY, $f) * 180 / M_PI); $hasUpdate = true; } if($this->age > 1200){ $this->kill(); $hasUpdate = true; } $this->updateMovement(); } $this->timings->stopTiming(); return $hasUpdate; } public function attack($damage, $source = EntityDamageEvent::CAUSE_MAGIC){ } public function heal($amount, $source = EntityRegainHealthEvent::CAUSE_MAGIC){ } public function saveNBT(){ parent::saveNBT(); $this->namedtag->Age = new Short("Age", $this->age); } public function getData(){ $flags = 0; $flags |= $this->fireTicks > 0 ? 1 : 0; return [ 0 => ["type" => 0, "value" => $flags], 1 => ["type" => 1, "value" => $this->airTicks], 16 => ["type" => 0, "value" => 0] //Is critical ]; } public function canCollideWith(Entity $entity){ return $entity instanceof Living and !$this->onGround; } public function spawnTo(Player $player){ $pk = AddEntityPacket::getFromPool(); $pk->type = Arrow::NETWORK_ID; $pk->eid = $this->getID(); $pk->x = $this->x; $pk->y = $this->y; $pk->z = $this->z; $pk->did = 0; //TODO: send motion here $player->dataPacket($pk); $pk = SetEntityMotionPacket::getFromPool(); $pk->entities = [ [$this->getID(), $this->motionX, $this->motionY, $this->motionZ] ]; $player->dataPacket($pk); parent::spawnTo($player); } }