Minor improvements to Batch encoding

This commit is contained in:
Dylan K. Taylor 2017-04-15 19:40:06 +01:00
parent b55929b382
commit c5eccc8e1c
3 changed files with 39 additions and 18 deletions

View File

@ -1771,17 +1771,11 @@ class Server{
*/ */
public function batchPackets(array $players, array $packets, $forceSync = false){ public function batchPackets(array $players, array $packets, $forceSync = false){
Timings::$playerNetworkTimer->startTiming(); Timings::$playerNetworkTimer->startTiming();
$str = "";
$pk = new BatchPacket();
foreach($packets as $p){ foreach($packets as $p){
if($p instanceof DataPacket){ $pk->addPacket($p);
if(!$p->isEncoded){
$p->encode();
}
$str .= Binary::writeUnsignedVarInt(strlen($p->buffer)) . $p->buffer;
}else{
$str .= Binary::writeUnsignedVarInt(strlen($p)) . $p;
}
} }
$targets = []; $targets = [];
@ -1792,18 +1786,17 @@ class Server{
} }
if(!$forceSync and $this->networkCompressionAsync){ if(!$forceSync and $this->networkCompressionAsync){
$task = new CompressBatchedTask($str, $targets, $this->networkCompressionLevel); $task = new CompressBatchedTask($pk, $targets, $this->networkCompressionLevel);
$this->getScheduler()->scheduleAsyncTask($task); $this->getScheduler()->scheduleAsyncTask($task);
}else{ }else{
$this->broadcastPacketsCallback(zlib_encode($str, ZLIB_ENCODING_DEFLATE, $this->networkCompressionLevel), $targets); $pk->compress($this->networkCompressionLevel);
$this->broadcastPacketsCallback($pk, $targets);
} }
Timings::$playerNetworkTimer->stopTiming(); Timings::$playerNetworkTimer->stopTiming();
} }
public function broadcastPacketsCallback($data, array $identifiers){ public function broadcastPacketsCallback(BatchPacket $pk, array $identifiers){
$pk = new BatchPacket();
$pk->payload = $data;
$pk->encode(); $pk->encode();
$pk->isEncoded = true; $pk->isEncoded = true;

View File

@ -21,6 +21,7 @@
namespace pocketmine\network; namespace pocketmine\network;
use pocketmine\network\mcpe\protocol\BatchPacket;
use pocketmine\scheduler\AsyncTask; use pocketmine\scheduler\AsyncTask;
use pocketmine\Server; use pocketmine\Server;
@ -31,15 +32,18 @@ class CompressBatchedTask extends AsyncTask{
public $final; public $final;
public $targets; public $targets;
public function __construct($data, array $targets, $level = 7){ public function __construct(BatchPacket $data, array $targets, $level = 7){
$this->data = $data; $this->data = serialize($data);
$this->targets = $targets; $this->targets = $targets;
$this->level = $level; $this->level = $level;
} }
public function onRun(){ public function onRun(){
try{ try{
$this->final = zlib_encode($this->data, ZLIB_ENCODING_DEFLATE, $this->level); /** @var BatchPacket $pk */
$pk = unserialize($this->data);
$pk->compress($this->level);
$this->final = serialize($pk);
$this->data = null; $this->data = null;
}catch(\Throwable $e){ }catch(\Throwable $e){
@ -47,6 +51,6 @@ class CompressBatchedTask extends AsyncTask{
} }
public function onCompletion(Server $server){ public function onCompletion(Server $server){
$server->broadcastPacketsCallback($this->final, (array) $this->targets); $server->broadcastPacketsCallback(unserialize($this->final), (array) $this->targets);
} }
} }

View File

@ -25,11 +25,14 @@ namespace pocketmine\network\mcpe\protocol;
use pocketmine\network\mcpe\NetworkSession; use pocketmine\network\mcpe\NetworkSession;
use pocketmine\utils\Binary;
use pocketmine\utils\BinaryStream;
class BatchPacket extends DataPacket{ class BatchPacket extends DataPacket{
const NETWORK_ID = 0xfe; const NETWORK_ID = 0xfe;
public $payload; public $payload;
public $compressed = false;
public function canBeBatched() : bool{ public function canBeBatched() : bool{
return false; return false;
@ -45,9 +48,30 @@ class BatchPacket extends DataPacket{
public function encode(){ public function encode(){
$this->reset(); $this->reset();
assert($this->compressed);
$this->put($this->payload); $this->put($this->payload);
} }
/**
* @param DataPacket|string $packet
*/
public function addPacket($packet){
if($packet instanceof DataPacket){
if(!$packet->isEncoded){
$packet->encode();
}
$packet = $packet->buffer;
}
$this->payload .= Binary::writeUnsignedVarInt(strlen($packet)) . $packet;
}
public function compress(int $level = 7){
assert(!$this->compressed);
$this->payload = zlib_encode($this->payload, ZLIB_ENCODING_DEFLATE, $level);
$this->compressed = true;
}
public function handle(NetworkSession $session) : bool{ public function handle(NetworkSession $session) : bool{
if(strlen($this->payload) < 2){ if(strlen($this->payload) < 2){
throw new \InvalidStateException("Not enough bytes in payload, expected zlib header"); throw new \InvalidStateException("Not enough bytes in payload, expected zlib header");