public function onUpdate($currentTick) { if ($this->closed) { return false; } $tickDiff = $currentTick - $this->lastUpdate; if ($tickDiff <= 0 and !$this->justCreated) { return true; } $this->lastUpdate = $currentTick; $hasUpdate = $this->entityBaseTick($tickDiff); if ($this->isAlive()) { $movingObjectPosition = null; if (!$this->isCollided) { $this->motionY -= $this->gravity; } $moveVector = new Vector3($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 === $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->distanceSquared($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(new ProjectileHitEvent($this)); $motion = sqrt($this->motionX ** 2 + $this->motionY ** 2 + $this->motionZ ** 2); $damage = ceil($motion * $this->damage); if ($this instanceof Arrow and $this->isCritical) { $damage += mt_rand(0, (int) ($damage / 2) + 1); } if ($this->shootingEntity === null) { $ev = new EntityDamageByEntityEvent($this, $movingObjectPosition->entityHit, EntityDamageEvent::CAUSE_PROJECTILE, $damage); } else { $ev = new EntityDamageByChildEntityEvent($this->shootingEntity, $this, $movingObjectPosition->entityHit, EntityDamageEvent::CAUSE_PROJECTILE, $damage); } $movingObjectPosition->entityHit->attack($ev->getFinalDamage(), $ev); $this->hadCollision = true; if ($this->fireTicks > 0) { $ev = new EntityCombustByEntityEvent($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->isCollided and !$this->hadCollision) { $this->hadCollision = true; $this->motionX = 0; $this->motionY = 0; $this->motionZ = 0; $this->server->getPluginManager()->callEvent(new ProjectileHitEvent($this)); } elseif (!$this->isCollided and $this->hadCollision) { $this->hadCollision = false; } if (!$this->onGround or abs($this->motionX) > 1.0E-5 or abs($this->motionY) > 1.0E-5 or abs($this->motionZ) > 1.0E-5) { $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; } $this->updateMovement(); } return $hasUpdate; }
public function calculateIntercept(Vector3 $pos1, Vector3 $pos2) { $v1 = $pos1->getIntermediateWithXValue($pos2, $this->minX); $v2 = $pos1->getIntermediateWithXValue($pos2, $this->maxX); $v3 = $pos1->getIntermediateWithYValue($pos2, $this->minY); $v4 = $pos1->getIntermediateWithYValue($pos2, $this->maxY); $v5 = $pos1->getIntermediateWithZValue($pos2, $this->minZ); $v6 = $pos1->getIntermediateWithZValue($pos2, $this->maxZ); if ($v1 !== null and !$this->isVectorInYZ($v1)) { $v1 = null; } if ($v2 !== null and !$this->isVectorInYZ($v2)) { $v2 = null; } if ($v3 !== null and !$this->isVectorInXZ($v3)) { $v3 = null; } if ($v4 !== null and !$this->isVectorInXZ($v4)) { $v4 = null; } if ($v5 !== null and !$this->isVectorInXY($v5)) { $v5 = null; } if ($v6 !== null and !$this->isVectorInXY($v6)) { $v6 = null; } $vector = null; if ($v1 !== null and ($vector === null or $pos1->distanceSquared($v1) < $pos1->distanceSquared($vector))) { $vector = $v1; } if ($v2 !== null and ($vector === null or $pos1->distanceSquared($v2) < $pos1->distanceSquared($vector))) { $vector = $v2; } if ($v3 !== null and ($vector === null or $pos1->distanceSquared($v3) < $pos1->distanceSquared($vector))) { $vector = $v3; } if ($v4 !== null and ($vector === null or $pos1->distanceSquared($v4) < $pos1->distanceSquared($vector))) { $vector = $v4; } if ($v5 !== null and ($vector === null or $pos1->distanceSquared($v5) < $pos1->distanceSquared($vector))) { $vector = $v5; } if ($v6 !== null and ($vector === null or $pos1->distanceSquared($v6) < $pos1->distanceSquared($vector))) { $vector = $v6; } if ($vector === null) { return null; } $f = -1; if ($vector === $v1) { $f = 4; } elseif ($vector === $v2) { $f = 5; } elseif ($vector === $v3) { $f = 0; } elseif ($vector === $v4) { $f = 1; } elseif ($vector === $v5) { $f = 2; } elseif ($vector === $v6) { $f = 3; } return MovingObjectPosition::fromBlock(0, 0, 0, $f, $vector); }