protected function readPacket()
{
if (strlen($packet = $this->thread->readMainToThreadPacket()) > 0) {
$pid = ord($packet[0]);
$offset = 1;
if ($pid === self::PACKET_REQUEST_CHUNK) {
$levelID = Binary::readInt(substr($packet, $offset, 4));
$offset += 4;
$chunkX = Binary::readInt(substr($packet, $offset, 4));
$offset += 4;
$chunkZ = Binary::readInt(substr($packet, $offset, 4));
$this->enqueueChunk($levelID, $chunkX, $chunkZ);
} elseif ($pid === self::PACKET_SEND_CHUNK) {
$levelID = Binary::readInt(substr($packet, $offset, 4));
$offset += 4;
$len = ord($packet[$offset++]);
/** @var FullChunk $class */
$class = substr($packet, $offset, $len);
$offset += $len;
$chunk = $class::fromBinary(substr($packet, $offset));
$this->receiveChunk($levelID, $chunk);
} elseif ($pid === self::PACKET_OPEN_LEVEL) {
$levelID = Binary::readInt(substr($packet, $offset, 4));
$offset += 4;
$seed = Binary::readInt(substr($packet, $offset, 4));
$offset += 4;
$len = Binary::readShort(substr($packet, $offset, 2));
$offset += 2;
$class = substr($packet, $offset, $len);
$offset += $len;
$options = unserialize(substr($packet, $offset));
$this->openLevel($levelID, $seed, $class, $options);
} elseif ($pid === self::PACKET_CLOSE_LEVEL) {
$levelID = Binary::readInt(substr($packet, $offset, 4));
$this->closeLevel($levelID);
} elseif ($pid === self::PACKET_ADD_NAMESPACE) {
$len = Binary::readShort(substr($packet, $offset, 2));
$offset += 2;
$namespace = substr($packet, $offset, $len);
$offset += $len;
$path = substr($packet, $offset);
$this->loader->addPath($path);
} elseif ($pid === self::PACKET_SHUTDOWN) {
foreach ($this->levels as $level) {
$level->shutdown();
}
$this->levels = [];
$this->shutdown = true;
}
} elseif (count($this->thread->getInternalQueue()) === 0) {
$this->thread->synchronized(function () {
$this->thread->wait(50000);
});
}
}