Ejemplo n.º 1
0
 /**
  * @param Vector3 $pos1
  * @param Vector3 $pos2
  *
  * @return MovingObjectPosition
  */
 public function calculateIntercept(Vector3 $pos1, Vector3 $pos2)
 {
     $bb = $this->getBoundingBox();
     if ($bb === null) {
         return null;
     }
     $v1 = $pos1->getIntermediateWithXValue($pos2, $bb->minX);
     $v2 = $pos1->getIntermediateWithXValue($pos2, $bb->maxX);
     $v3 = $pos1->getIntermediateWithYValue($pos2, $bb->minY);
     $v4 = $pos1->getIntermediateWithYValue($pos2, $bb->maxY);
     $v5 = $pos1->getIntermediateWithZValue($pos2, $bb->minZ);
     $v6 = $pos1->getIntermediateWithZValue($pos2, $bb->maxZ);
     if ($v1 !== null and !$bb->isVectorInYZ($v1)) {
         $v1 = null;
     }
     if ($v2 !== null and !$bb->isVectorInYZ($v2)) {
         $v2 = null;
     }
     if ($v3 !== null and !$bb->isVectorInXZ($v3)) {
         $v3 = null;
     }
     if ($v4 !== null and !$bb->isVectorInXZ($v4)) {
         $v4 = null;
     }
     if ($v5 !== null and !$bb->isVectorInXY($v5)) {
         $v5 = null;
     }
     if ($v6 !== null and !$bb->isVectorInXY($v6)) {
         $v6 = null;
     }
     $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($this->x, $this->y, $this->z, $f, $vector->add($this->x, $this->y, $this->z));
 }
Ejemplo n.º 2
0
 public function onUpdate()
 {
     $this->entityBaseTick();
     if ($this->closed !== false) {
         return false;
     }
     $movingObjectPosition = null;
     $this->motionY -= $this->gravity;
     $this->inBlock = $this->checkObstruction($this->x, ($this->boundingBox->minY + $this->boundingBox->maxY) / 2, $this->z);
     $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->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) {
             $motion = sqrt($this->motionX ** 2 + $this->motionY ** 2 + $this->motionZ ** 2);
             $damage = ceil($motion * $this->damage);
             $ev = new EntityDamageByEntityEvent($this->shootingEntity === null ? $this : $this->shootingEntity, $movingObjectPosition->entityHit, EntityDamageEvent::CAUSE_PROJECTILE, $damage);
             $this->server->getPluginManager()->callEvent($ev);
             if (!$ev->isCancelled()) {
                 $movingObjectPosition->entityHit->attack($damage, $ev);
                 if ($this->fireTicks > 0) {
                     $movingObjectPosition->entityHit->setOnFire(5);
                 }
                 $this->kill();
             }
         }
     }
     $this->move($this->motionX, $this->motionY, $this->motionZ);
     $friction = 1 - $this->drag;
     if ($this->onGround) {
         $friction = $this->getLevel()->getBlock(new Vector3($this->getFloorX(), $this->getFloorY() - 1, $this->getFloorZ()))->frictionFactor * $friction;
     }
     $this->motionX *= $friction;
     $this->motionY *= 1 - $this->drag;
     $this->motionZ *= $friction;
     if ($this->onGround) {
         $this->motionX = 0;
         $this->motionY = 0;
         $this->motionZ = 0;
     }
     if ($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;
     }
     if ($this->age > 1200) {
         $this->kill();
     }
     $this->updateMovement();
     return !$this->onGround or $this->motionX == 0 and $this->motionY == 0 and $this->motionZ == 0;
 }
Ejemplo n.º 3
0
 public function calculateIntercept(Vector3 $pos1, Vector3 $pos2)
 {
     $intermediateVectors = $this->getIntermediateVectorsArray($pos1, $pos2);
     $vector = $this->calculateInterceptVector($pos1, $intermediateVectors);
     if ($vector === null) {
         return null;
     }
     $f = $this->calculateInterceptSide($vector, $intermediateVectors);
     return MovingObjectPosition::fromBlock(0, 0, 0, $f, $vector);
 }
Ejemplo n.º 4
0
 public function onUpdate($currentTick)
 {
     if ($this->closed) {
         return false;
     }
     $tickDiff = max(1, $currentTick - $this->lastUpdate);
     $this->lastUpdate = $currentTick;
     $hasUpdate = $this->entityBaseTick($tickDiff);
     if (!$this->dead) {
         $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 $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;
         }
         $this->updateMovement();
     }
     return $hasUpdate;
 }
Ejemplo n.º 5
0
 /**
  * @param Vector3 $pos1
  * @param Vector3 $pos2
  *
  * @return MovingObjectPosition
  */
 public function calculateIntercept(Vector3 $pos1, Vector3 $pos2)
 {
     $bb = $this->getBoundingBox();
     if ($bb === null) {
         return null;
     }
     $intermediateVectors = $bb->getIntermediateVectorsArray($pos1, $pos2);
     $vector = $bb->calculateInterceptVector($pos1, $intermediateVectors);
     if ($vector === null) {
         return null;
     }
     $f = $bb->calculateInterceptSide($vector, $intermediateVectors);
     return MovingObjectPosition::fromBlock($this->x, $this->y, $this->z, $f, $vector->add($this->x, $this->y, $this->z));
 }