diff --git a/src/network/mcpe/NetworkSession.php b/src/network/mcpe/NetworkSession.php index 2b995ef8f..8becf1260 100644 --- a/src/network/mcpe/NetworkSession.php +++ b/src/network/mcpe/NetworkSession.php @@ -177,7 +177,7 @@ class NetworkSession{ private ?EncryptionContext $cipher = null; - /** @var ClientboundPacket[] */ + /** @var string[] */ private array $sendBuffer = []; /** @@ -264,23 +264,6 @@ class NetworkSession{ ); } - /** - * @param ClientboundPacket[] $packets - */ - public static function encodePacketBatchTimed(BinaryStream $stream, PacketSerializerContext $context, array $packets) : void{ - PacketBatch::encodeRaw($stream, array_map(function(ClientboundPacket $packet) use ($context) : string{ - $timings = Timings::getEncodeDataPacketTimings($packet); - $timings->startTiming(); - try{ - $stream = PacketSerializer::encoder($context); - $packet->encode($stream); - return $stream->getBuffer(); - }finally{ - $timings->stopTiming(); - } - }, $packets)); - } - private function onPlayerCreated(Player $player) : void{ if(!$this->isConnected()){ //the remote player might have disconnected before spawn terrain generation was finished @@ -498,7 +481,7 @@ class NetworkSession{ return false; } - $this->addToSendBuffer($packet); + $this->addToSendBuffer(self::encodePacketTimed(PacketSerializer::encoder($this->packetSerializerContext), $packet)); if($immediate){ $this->flushSendBuffer(true); } @@ -512,16 +495,24 @@ class NetworkSession{ /** * @internal */ - public function addToSendBuffer(ClientboundPacket $packet) : void{ - $timings = Timings::getSendDataPacketTimings($packet); + public static function encodePacketTimed(PacketSerializer $serializer, ClientboundPacket $packet) : string{ + $timings = Timings::getEncodeDataPacketTimings($packet); $timings->startTiming(); try{ - $this->sendBuffer[] = $packet; + $packet->encode($serializer); + return $serializer->getBuffer(); }finally{ $timings->stopTiming(); } } + /** + * @internal + */ + public function addToSendBuffer(string $buffer) : void{ + $this->sendBuffer[] = $buffer; + } + private function flushSendBuffer(bool $immediate = false) : void{ if(count($this->sendBuffer) > 0){ Timings::$playerNetworkSend->startTiming(); @@ -534,7 +525,7 @@ class NetworkSession{ } $stream = new BinaryStream(); - self::encodePacketBatchTimed($stream, $this->packetSerializerContext, $this->sendBuffer); + PacketBatch::encodeRaw($stream, $this->sendBuffer); if($this->enableCompression){ $promise = $this->server->prepareBatch(new PacketBatch($stream->getBuffer()), $this->compressor, $syncMode); diff --git a/src/network/mcpe/StandardPacketBroadcaster.php b/src/network/mcpe/StandardPacketBroadcaster.php index 73848ccae..c52b8f93d 100644 --- a/src/network/mcpe/StandardPacketBroadcaster.php +++ b/src/network/mcpe/StandardPacketBroadcaster.php @@ -23,25 +23,35 @@ declare(strict_types=1); namespace pocketmine\network\mcpe; +use pocketmine\network\mcpe\protocol\ClientboundPacket; use pocketmine\network\mcpe\protocol\serializer\PacketBatch; +use pocketmine\network\mcpe\protocol\serializer\PacketSerializer; use pocketmine\Server; use pocketmine\utils\BinaryStream; +use function array_map; use function spl_object_id; final class StandardPacketBroadcaster implements PacketBroadcaster{ public function __construct(private Server $server){} public function broadcastPackets(array $recipients, array $packets) : void{ - $buffers = []; + $batchBuffers = []; + + /** @var string[][] $packetBuffers */ + $packetBuffers = []; $compressors = []; + /** @var NetworkSession[][][] $targetMap */ $targetMap = []; foreach($recipients as $recipient){ $serializerContext = $recipient->getPacketSerializerContext(); $bufferId = spl_object_id($serializerContext); - if(!isset($buffers[$bufferId])){ + if(!isset($batchBuffers[$bufferId])){ + $packetBuffers[$bufferId] = array_map(function(ClientboundPacket $packet) use ($serializerContext) : string{ + return NetworkSession::encodePacketTimed(PacketSerializer::encoder($serializerContext), $packet); + }, $packets); $stream = new BinaryStream(); - NetworkSession::encodePacketBatchTimed($stream, $serializerContext, $packets); - $buffers[$bufferId] = $stream->getBuffer(); + PacketBatch::encodeRaw($stream, $packetBuffers[$bufferId]); + $batchBuffers[$bufferId] = $stream->getBuffer(); } //TODO: different compressors might be compatible, it might not be necessary to split them up by object @@ -52,17 +62,17 @@ final class StandardPacketBroadcaster implements PacketBroadcaster{ } foreach($targetMap as $bufferId => $compressorMap){ - $buffer = $buffers[$bufferId]; + $batchBuffer = $batchBuffers[$bufferId]; foreach($compressorMap as $compressorId => $compressorTargets){ $compressor = $compressors[$compressorId]; - if(!$compressor->willCompress($buffer)){ + if(!$compressor->willCompress($batchBuffer)){ foreach($compressorTargets as $target){ - foreach($packets as $pk){ - $target->addToSendBuffer($pk); + foreach($packetBuffers[$bufferId] as $packetBuffer){ + $target->addToSendBuffer($packetBuffer); } } }else{ - $promise = $this->server->prepareBatch(new PacketBatch($buffer), $compressor); + $promise = $this->server->prepareBatch(new PacketBatch($batchBuffer), $compressor); foreach($compressorTargets as $target){ $target->queueCompressed($promise); }