public function processBatch(BatchPacket $packet, Player $p) { try { if (strlen($packet->payload) === 0) { //prevent zlib_decode errors for incorrectly-decoded packets throw new \InvalidArgumentException("BatchPacket payload is empty or packet decode error"); } $str = zlib_decode($packet->payload, 1024 * 1024 * 64); //Max 64MB $len = strlen($str); if ($len === 0) { throw new \InvalidStateException("Decoded BatchPacket payload is empty"); } $stream = new BinaryStream($str); while ($stream->offset < $len) { $buf = $stream->getString(); if (($pk = $this->getPacket(ord($buf[0]))) !== null) { if ($pk::NETWORK_ID === Info::BATCH_PACKET) { throw new \InvalidStateException("Invalid BatchPacket inside BatchPacket"); } $pk->setBuffer($buf, 1); $pk->decode(); assert($pk->feof(), "Still " . strlen(substr($pk->buffer, $pk->offset)) . " bytes unread in " . get_class($pk)); $p->handleDataPacket($pk); } } } catch (\Throwable $e) { if (\pocketmine\DEBUG > 1) { $logger = $this->server->getLogger(); $logger->debug("BatchPacket " . " 0x" . bin2hex($packet->payload)); $logger->logException($e); } } }
/** * Reads a metadata coded string * * @param $value * @param bool $types * * @return array */ public static function readMetadata($value, $types = false) { $stream = new BinaryStream(); $stream->setBuffer($value); $count = $stream->getUnsignedVarInt(); $data = []; for ($i = 0; $i < $count; ++$i) { $key = $stream->getUnsignedVarInt(); $type = $stream->getUnsignedVarInt(); $value = null; switch ($type) { case Entity::DATA_TYPE_BYTE: $value = $stream->getByte(); break; case Entity::DATA_TYPE_SHORT: $value = $stream->getLShort(true); //signed break; case Entity::DATA_TYPE_INT: $value = $stream->getVarInt(); break; case Entity::DATA_TYPE_FLOAT: $value = $stream->getLFloat(); break; case Entity::DATA_TYPE_STRING: $value = $stream->getString(); break; case Entity::DATA_TYPE_SLOT: //TODO: use objects directly $item = $stream->getSlot(); $value[0] = $item->getId(); $value[1] = $item->getCount(); $value[2] = $item->getDamage(); break; case Entity::DATA_TYPE_POS: $value = [0, 0, 0]; $stream->getBlockCoords($value[0], $value[1], $value[2]); break; case Entity::DATA_TYPE_LONG: $value = $stream->getVarInt(); //TODO: varint64 proper support break; case Entity::DATA_TYPE_VECTOR3F: $value = [0.0, 0.0, 0.0]; $stream->getVector3f($value[0], $value[1], $value[2]); break; default: $value = []; } if ($types === true) { $data[$key] = [$value, $type]; } else { $data[$key] = $value; } } return $data; }