Inheritance: extends DataPacket
Esempio n. 1
0
 public function setMotion(Vector3 $mot)
 {
     if (parent::setMotion($mot)) {
         if ($this->chunk !== null) {
             $this->level->addEntityMotion($this->chunk->getX(), $this->chunk->getZ(), $this->getId(), $this->motionX, $this->motionY, $this->motionZ);
             $pk = new SetEntityMotionPacket();
             $pk->entities[] = [0, $mot->x, $mot->y, $mot->z];
             $this->dataPacket($pk->setChannel(Network::CHANNEL_MOVEMENT));
         }
         if ($this->motionY > 0) {
             $this->startAirTicks = -log($this->gravity / ($this->gravity + $this->drag * $this->motionY)) / $this->drag * 2 + 5;
         }
         return true;
     }
     return false;
 }
Esempio n. 2
0
 /**
  * WARNING: Do not use this, it's only for internal use.
  * Changes to this function won't be recorded on the version.
  *
  * @param int $currentTick
  *
  * @return bool
  */
 public function doTick($currentTick)
 {
     $this->timings->doTick->startTiming();
     $this->checkTime();
     if ($currentTick % 200 === 0) {
         $this->sendTime();
     }
     $this->unloadChunks();
     $X = \null;
     $Z = \null;
     //Do block updates
     $this->timings->doTickPending->startTiming();
     while ($this->updateQueue->count() > 0 and $this->updateQueue->current()["priority"] <= $currentTick) {
         $block = $this->getBlock($this->updateQueue->extract()["data"]);
         unset($this->updateQueueIndex[\PHP_INT_SIZE === 8 ? ($block->x & 0xfffffff) << 35 | ($block->y & 0x7f) << 28 | $block->z & 0xfffffff : $block->x . ":" . $block->y . ":" . $block->z]);
         $block->onUpdate(self::BLOCK_UPDATE_SCHEDULED);
     }
     $this->timings->doTickPending->stopTiming();
     $this->timings->entityTick->startTiming();
     //Update entities that need update
     Timings::$tickEntityTimer->startTiming();
     foreach ($this->updateEntities as $id => $entity) {
         if ($entity->closed or !$entity->onUpdate($currentTick)) {
             unset($this->updateEntities[$id]);
         }
     }
     Timings::$tickEntityTimer->stopTiming();
     $this->timings->entityTick->stopTiming();
     $this->timings->tileEntityTick->startTiming();
     //Update tiles that need update
     if (\count($this->updateTiles) > 0) {
         //Timings::$tickTileEntityTimer->startTiming();
         foreach ($this->updateTiles as $id => $tile) {
             if ($tile->onUpdate() !== \true) {
                 unset($this->updateTiles[$id]);
             }
         }
         //Timings::$tickTileEntityTimer->stopTiming();
     }
     $this->timings->tileEntityTick->stopTiming();
     $this->timings->doTickTiles->startTiming();
     $this->tickChunks();
     $this->timings->doTickTiles->stopTiming();
     if (\count($this->changedCount) > 0) {
         if (\count($this->players) > 0) {
             foreach ($this->changedCount as $index => $mini) {
                 for ($Y = 0; $Y < 8; ++$Y) {
                     if (($mini & 1 << $Y) === 0) {
                         continue;
                     }
                     if (\count($this->changedBlocks[$index][$Y]) < 256) {
                         continue;
                     } else {
                         $X = \null;
                         $Z = \null;
                         if (\PHP_INT_SIZE === 8) {
                             $X = $index >> 32 << 32 >> 32;
                             $Z = ($index & 0xffffffff) << 32 >> 32;
                         } else {
                             list($X, $Z) = \explode(":", $index);
                             $X = (int) $X;
                             $Z = (int) $Z;
                         }
                         foreach ($this->getUsingChunk($X, $Z) as $p) {
                             $p->unloadChunk($X, $Z);
                         }
                         unset($this->changedBlocks[$index][$Y]);
                     }
                 }
             }
             $this->changedCount = [];
             if (\count($this->changedBlocks) > 0) {
                 foreach ($this->changedBlocks as $index => $mini) {
                     foreach ($mini as $blocks) {
                         /** @var Block $b */
                         foreach ($blocks as $b) {
                             $pk = new UpdateBlockPacket();
                             $pk->x = $b->x;
                             $pk->y = $b->y;
                             $pk->z = $b->z;
                             $pk->block = $b->getId();
                             $pk->meta = $b->getDamage();
                             Server::broadcastPacket($this->getUsingChunk($b->x >> 4, $b->z >> 4), $pk);
                         }
                     }
                 }
                 $this->changedBlocks = [];
             }
         } else {
             $this->changedCount = [];
             $this->changedBlocks = [];
         }
     }
     $this->processChunkRequest();
     foreach ($this->moveToSend as $index => $entry) {
         Level::getXZ($index, $chunkX, $chunkZ);
         $pk = new MoveEntityPacket();
         $pk->entities = $entry;
         Server::broadcastPacket($this->getChunkPlayers($chunkX, $chunkZ), $pk->setChannel(Network::CHANNEL_MOVEMENT));
     }
     $this->moveToSend = [];
     foreach ($this->motionToSend as $index => $entry) {
         Level::getXZ($index, $chunkX, $chunkZ);
         $pk = new SetEntityMotionPacket();
         $pk->entities = $entry;
         Server::broadcastPacket($this->getChunkPlayers($chunkX, $chunkZ), $pk->setChannel(Network::CHANNEL_MOVEMENT));
     }
     $this->motionToSend = [];
     $this->timings->doTick->stopTiming();
 }
Esempio n. 3
0
 public function onUpdate($currentTick)
 {
     if (!$this->loggedIn) {
         return false;
     }
     $tickDiff = $currentTick - $this->lastUpdate;
     if ($tickDiff <= 0) {
         return true;
     }
     if ($this->dead === true and $this->spawned) {
         ++$this->deadTicks;
         if ($this->deadTicks >= 10) {
             $this->despawnFromAll();
         }
         return true;
     }
     $this->timings->startTiming();
     if ($this->spawned) {
         $this->processMovement($tickDiff);
         $this->entityBaseTick($tickDiff);
         if ($this->onGround) {
             $this->inAirTicks = 0;
         } else {
             if ($this->inAirTicks > 10 and $this->isSurvival() and !$this->isSleeping() and $this->getDataProperty(self::DATA_NO_AI) === 0) {
                 $expectedVelocity = -$this->gravity / $this->drag - -$this->gravity / $this->drag * exp(-$this->drag * ($this->inAirTicks - 5));
                 $diff = sqrt(abs($this->speed->y - $expectedVelocity));
                 if (!$this->hasEffect(Effect::JUMP) and $diff > 0.6 and $expectedVelocity < $this->speed->y and !$this->server->getAllowFlight()) {
                     if ($this->inAirTicks < 100) {
                         $this->setMotion(new Vector3(0, $expectedVelocity, 0));
                     } elseif ($this->kick("Flying is not enabled on this server")) {
                         return false;
                     }
                 }
             }
             ++$this->inAirTicks;
         }
     }
     if ($this->nextChunkOrderRun-- <= 0 or $this->chunk === null) {
         $this->orderChunks();
     }
     if (count($this->loadQueue) > 0 or !$this->spawned) {
         $this->sendNextChunk();
     }
     $this->checkTeleportPosition();
     if (count($this->moveToSend) > 0) {
         $pk = new MoveEntityPacket();
         $pk->entities = $this->moveToSend;
         $this->batchDataPacket($pk->setChannel(Network::CHANNEL_MOVEMENT));
         $this->moveToSend = [];
     }
     if (count($this->motionToSend) > 0) {
         $pk = new SetEntityMotionPacket();
         $pk->entities = $this->motionToSend;
         $this->batchDataPacket($pk->setChannel(Network::CHANNEL_MOVEMENT));
         $this->motionToSend = [];
     }
     if (count($this->batchedPackets) > 0) {
         foreach ($this->batchedPackets as $channel => $list) {
             $this->server->batchPackets([$this], $list, false, $channel);
         }
         $this->batchedPackets = [];
     }
     $this->lastUpdate = $currentTick;
     $this->timings->stopTiming();
     return true;
 }
Esempio n. 4
0
 /**
  * WARNING: Do not use this, it's only for internal use.
  * Changes to this function won't be recorded on the version.
  *
  * @param int $currentTick
  *
  * @return bool
  */
 public function doTick($currentTick)
 {
     $this->timings->doTick->startTiming();
     $this->checkTime();
     if (++$this->sendTimeTicker === 200) {
         $this->sendTime();
         $this->sendTimeTicker = 0;
     }
     $this->unloadChunks();
     //Do block updates
     $this->timings->doTickPending->startTiming();
     while ($this->updateQueue->count() > 0 and $this->updateQueue->current()["priority"] <= $currentTick) {
         $block = $this->getBlock($this->updateQueue->extract()["data"]);
         unset($this->updateQueueIndex[Level::blockHash($block->x, $block->y, $block->z)]);
         $block->onUpdate(self::BLOCK_UPDATE_SCHEDULED);
     }
     $this->timings->doTickPending->stopTiming();
     $this->timings->entityTick->startTiming();
     //Update entities that need update
     Timings::$tickEntityTimer->startTiming();
     foreach ($this->updateEntities as $id => $entity) {
         if ($entity->closed or !$entity->onUpdate($currentTick)) {
             unset($this->updateEntities[$id]);
         }
     }
     Timings::$tickEntityTimer->stopTiming();
     $this->timings->entityTick->stopTiming();
     $this->timings->tileEntityTick->startTiming();
     Timings::$tickTileEntityTimer->startTiming();
     //Update tiles that need update
     if (count($this->updateTiles) > 0) {
         foreach ($this->updateTiles as $id => $tile) {
             if ($tile->onUpdate() !== true) {
                 unset($this->updateTiles[$id]);
             }
         }
     }
     Timings::$tickTileEntityTimer->stopTiming();
     $this->timings->tileEntityTick->stopTiming();
     $this->timings->doTickTiles->startTiming();
     $this->tickChunks();
     $this->timings->doTickTiles->stopTiming();
     if (count($this->changedBlocks) > 0) {
         if (count($this->players) > 0) {
             foreach ($this->changedBlocks as $index => $blocks) {
                 unset($this->chunkCache[$index]);
                 Level::getXZ($index, $chunkX, $chunkZ);
                 if (count($blocks) > 512) {
                     $chunk = $this->getChunk($chunkX, $chunkZ);
                     foreach ($this->getChunkPlayers($chunkX, $chunkZ) as $p) {
                         $p->onChunkChanged($chunk);
                     }
                 } else {
                     $this->sendBlocks($this->getChunkPlayers($chunkX, $chunkZ), $blocks, UpdateBlockPacket::FLAG_ALL);
                 }
             }
         } else {
             $this->chunkCache = [];
         }
         $this->changedBlocks = [];
     }
     $this->processChunkRequest();
     if ($this->sleepTicks > 0 and --$this->sleepTicks <= 0) {
         $this->checkSleep();
     }
     foreach ($this->moveToSend as $index => $entry) {
         Level::getXZ($index, $chunkX, $chunkZ);
         $pk = new MoveEntityPacket();
         $pk->entities = $entry;
         $this->addChunkPacket($chunkX, $chunkZ, $pk->setChannel(Network::CHANNEL_MOVEMENT));
     }
     $this->moveToSend = [];
     foreach ($this->motionToSend as $index => $entry) {
         Level::getXZ($index, $chunkX, $chunkZ);
         $pk = new SetEntityMotionPacket();
         $pk->entities = $entry;
         $this->addChunkPacket($chunkX, $chunkZ, $pk->setChannel(Network::CHANNEL_MOVEMENT));
     }
     $this->motionToSend = [];
     foreach ($this->chunkPackets as $index => $entries) {
         Level::getXZ($index, $chunkX, $chunkZ);
         $chunkPlayers = $this->getChunkPlayers($chunkX, $chunkZ);
         if (count($chunkPlayers) > 0) {
             foreach ($entries as $pk) {
                 Server::broadcastPacket($chunkPlayers, $pk);
             }
         }
     }
     $this->chunkPackets = [];
     $this->timings->doTick->stopTiming();
 }
Esempio n. 5
0
 public function onUpdate($currentTick)
 {
     if (!$this->loggedIn) {
         return \false;
     }
     if ($this->dead === \true and $this->spawned) {
         ++$this->deadTicks;
         if ($this->deadTicks >= 10) {
             $this->despawnFromAll();
         }
         return $this->deadTicks < 10;
     }
     $this->timings->startTiming();
     if ($this->spawned) {
         $this->processMovement($currentTick);
         $this->entityBaseTick(1);
         if ($this->onGround) {
             $this->inAirTicks = 0;
         } else {
             if ($this->inAirTicks > 20 and $this->isSurvival() and !$this->isSleeping() and $this->spawned and !$this->server->getAllowFlight()) {
                 $expectedVelocity = -$this->gravity / $this->drag - -$this->gravity / $this->drag * \exp(-$this->drag * ($this->inAirTicks - 2));
                 $diff = ($this->speed->y - $expectedVelocity) ** 2;
                 if ($diff > 0.6 and $expectedVelocity < $this->speed->y) {
                     $this->kick("Disable fly mods.");
                 }
                 return \false;
             } else {
                 ++$this->inAirTicks;
             }
         }
         foreach ($this->level->getNearbyEntities($this->boundingBox->grow(1, 0.5, 1), $this) as $entity) {
             if ($currentTick - $entity->lastUpdate > 1) {
                 $entity->scheduleUpdate();
             }
             if ($entity instanceof Arrow and $entity->hadCollision) {
                 if ($entity->dead !== \true) {
                     $item = Item::get(Item::ARROW, 0, 1);
                     if ($this->isSurvival() and !$this->inventory->canAddItem($item)) {
                         continue;
                     }
                     $this->server->getPluginManager()->callEvent($ev = new InventoryPickupArrowEvent($this->inventory, $entity));
                     if ($ev->isCancelled()) {
                         continue;
                     }
                     $pk = new TakeItemEntityPacket();
                     $pk->eid = $this->getId();
                     $pk->target = $entity->getId();
                     Server::broadcastPacket($entity->getViewers(), $pk->setChannel(Network::CHANNEL_ENTITY_SPAWNING));
                     $this->inventory->addItem(clone $item);
                     $entity->kill();
                 }
             } elseif ($entity instanceof DroppedItem) {
                 if ($entity->dead !== \true and $entity->getPickupDelay() <= 0) {
                     $item = $entity->getItem();
                     if ($item instanceof Item) {
                         if ($this->isSurvival() and !$this->inventory->canAddItem($item)) {
                             continue;
                         }
                         $this->server->getPluginManager()->callEvent($ev = new InventoryPickupItemEvent($this->inventory, $entity));
                         if ($ev->isCancelled()) {
                             continue;
                         }
                         switch ($item->getId()) {
                             case Item::WOOD:
                                 $this->awardAchievement("mineWood");
                                 break;
                             case Item::DIAMOND:
                                 $this->awardAchievement("diamond");
                                 break;
                         }
                         $pk = new TakeItemEntityPacket();
                         $pk->eid = $this->getId();
                         $pk->target = $entity->getId();
                         Server::broadcastPacket($entity->getViewers(), $pk->setChannel(Network::CHANNEL_ENTITY_SPAWNING));
                         $this->inventory->addItem(clone $item);
                         $entity->kill();
                     }
                 }
             }
         }
     }
     if ($this->nextChunkOrderRun-- <= 0 or $this->chunk === \null) {
         $this->orderChunks();
     }
     if (\count($this->loadQueue) > 0 or !$this->spawned) {
         $this->sendNextChunk();
     }
     if (\count($this->moveToSend) > 0) {
         $pk = new MoveEntityPacket();
         $pk->entities = $this->moveToSend;
         $this->batchDataPacket($pk->setChannel(Network::CHANNEL_MOVEMENT));
         $this->moveToSend = [];
     }
     if (\count($this->motionToSend) > 0) {
         $pk = new SetEntityMotionPacket();
         $pk->entities = $this->motionToSend;
         $this->batchDataPacket($pk->setChannel(Network::CHANNEL_MOVEMENT));
         $this->motionToSend = [];
     }
     if (\count($this->batchedPackets) > 0) {
         foreach ($this->batchedPackets as $channel => $list) {
             $this->server->batchPackets([$this], $list, \false, $channel);
         }
         $this->batchedPackets = [];
     }
     $this->lastUpdate = $currentTick;
     $this->timings->stopTiming();
     return \true;
 }