Skip to content

Commit 071c15d

Browse files
committed
NetworkSession: immediate-send now causes a buffer flush when the packet is ready
instead of skipping queues and forcing sync compression as previously seen. this maintains proper packet order and allows immediate-flush to be used to reduce latency in-game. Small servers won't notice any difference, but for larger ones it may make a difference, since the buffer time effectively depends on the amount of load RakLib is under. closes #3325
1 parent 673b39e commit 071c15d

File tree

1 file changed

+20
-27
lines changed

1 file changed

+20
-27
lines changed

src/network/mcpe/NetworkSession.php

+20-27
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ class NetworkSession{
174174
*/
175175
private array $sendBufferAckPromises = [];
176176

177-
/** @phpstan-var \SplQueue<array{CompressBatchPromise|string, list<PromiseResolver<true>>}> */
177+
/** @phpstan-var \SplQueue<array{CompressBatchPromise|string, list<PromiseResolver<true>>, bool}> */
178178
private \SplQueue $compressedQueue;
179179
private bool $forceAsyncCompression = true;
180180
private bool $enableCompression = false; //disabled until handshake completed
@@ -235,7 +235,7 @@ public function getLogger() : \Logger{
235235

236236
private function onSessionStartSuccess() : void{
237237
$this->logger->debug("Session start handshake completed, awaiting login packet");
238-
$this->flushSendBuffer(true);
238+
$this->flushGamePacketQueue();
239239
$this->enableCompression = true;
240240
$this->setHandler(new LoginPacketHandler(
241241
$this->server,
@@ -529,7 +529,7 @@ private function sendDataPacketInternal(ClientboundPacket $packet, bool $immedia
529529
$this->addToSendBuffer(self::encodePacketTimed(PacketSerializer::encoder(), $evPacket));
530530
}
531531
if($immediate){
532-
$this->flushSendBuffer(true);
532+
$this->flushGamePacketQueue();
533533
}
534534

535535
return true;
@@ -577,14 +577,12 @@ public function addToSendBuffer(string $buffer) : void{
577577
$this->sendBuffer[] = $buffer;
578578
}
579579

580-
private function flushSendBuffer(bool $immediate = false) : void{
580+
private function flushGamePacketQueue() : void{
581581
if(count($this->sendBuffer) > 0){
582582
Timings::$playerNetworkSend->startTiming();
583583
try{
584584
$syncMode = null; //automatic
585-
if($immediate){
586-
$syncMode = true;
587-
}elseif($this->forceAsyncCompression){
585+
if($this->forceAsyncCompression){
588586
$syncMode = false;
589587
}
590588

@@ -599,7 +597,9 @@ private function flushSendBuffer(bool $immediate = false) : void{
599597
$this->sendBuffer = [];
600598
$ackPromises = $this->sendBufferAckPromises;
601599
$this->sendBufferAckPromises = [];
602-
$this->queueCompressedNoBufferFlush($batch, $immediate, $ackPromises);
600+
//these packets were already potentially buffered for up to 50ms - make sure the transport layer doesn't
601+
//delay them any longer
602+
$this->queueCompressedNoGamePacketFlush($batch, networkFlush: true, ackPromises: $ackPromises);
603603
}finally{
604604
Timings::$playerNetworkSend->stopTiming();
605605
}
@@ -619,8 +619,10 @@ public function getTypeConverter() : TypeConverter{ return $this->typeConverter;
619619
public function queueCompressed(CompressBatchPromise|string $payload, bool $immediate = false) : void{
620620
Timings::$playerNetworkSend->startTiming();
621621
try{
622-
$this->flushSendBuffer($immediate); //Maintain ordering if possible
623-
$this->queueCompressedNoBufferFlush($payload, $immediate);
622+
//if the next packet causes a flush, avoid unnecessarily flushing twice
623+
//however, if the next packet does *not* cause a flush, game packets should be flushed to avoid delays
624+
$this->flushGamePacketQueue();
625+
$this->queueCompressedNoGamePacketFlush($payload, $immediate);
624626
}finally{
625627
Timings::$playerNetworkSend->stopTiming();
626628
}
@@ -631,22 +633,13 @@ public function queueCompressed(CompressBatchPromise|string $payload, bool $imme
631633
*
632634
* @phpstan-param list<PromiseResolver<true>> $ackPromises
633635
*/
634-
private function queueCompressedNoBufferFlush(CompressBatchPromise|string $batch, bool $immediate = false, array $ackPromises = []) : void{
636+
private function queueCompressedNoGamePacketFlush(CompressBatchPromise|string $batch, bool $networkFlush = false, array $ackPromises = []) : void{
635637
Timings::$playerNetworkSend->startTiming();
636638
try{
639+
$this->compressedQueue->enqueue([$batch, $ackPromises, $networkFlush]);
637640
if(is_string($batch)){
638-
if($immediate){
639-
//Skips all queues
640-
$this->sendEncoded($batch, true, $ackPromises);
641-
}else{
642-
$this->compressedQueue->enqueue([$batch, $ackPromises]);
643-
$this->flushCompressedQueue();
644-
}
645-
}elseif($immediate){
646-
//Skips all queues
647-
$this->sendEncoded($batch->getResult(), true, $ackPromises);
641+
$this->flushCompressedQueue();
648642
}else{
649-
$this->compressedQueue->enqueue([$batch, $ackPromises]);
650643
$batch->onResolve(function() : void{
651644
if($this->connected){
652645
$this->flushCompressedQueue();
@@ -663,14 +656,14 @@ private function flushCompressedQueue() : void{
663656
try{
664657
while(!$this->compressedQueue->isEmpty()){
665658
/** @var CompressBatchPromise|string $current */
666-
[$current, $ackPromises] = $this->compressedQueue->bottom();
659+
[$current, $ackPromises, $networkFlush] = $this->compressedQueue->bottom();
667660
if(is_string($current)){
668661
$this->compressedQueue->dequeue();
669-
$this->sendEncoded($current, false, $ackPromises);
662+
$this->sendEncoded($current, $networkFlush, $ackPromises);
670663

671664
}elseif($current->hasResult()){
672665
$this->compressedQueue->dequeue();
673-
$this->sendEncoded($current->getResult(), false, $ackPromises);
666+
$this->sendEncoded($current->getResult(), $networkFlush, $ackPromises);
674667

675668
}else{
676669
//can't send any more queued until this one is ready
@@ -710,7 +703,7 @@ private function tryDisconnect(\Closure $func, Translatable|string $reason) : vo
710703
$this->disconnectGuard = true;
711704
$func();
712705
$this->disconnectGuard = false;
713-
$this->flushSendBuffer(true);
706+
$this->flushGamePacketQueue();
714707
$this->sender->close("");
715708
foreach($this->disposeHooks as $callback){
716709
$callback();
@@ -1345,6 +1338,6 @@ public function tick() : void{
13451338
Timings::$playerNetworkSendInventorySync->stopTiming();
13461339
}
13471340

1348-
$this->flushSendBuffer();
1341+
$this->flushGamePacketQueue();
13491342
}
13501343
}

0 commit comments

Comments
 (0)