From 9cdb6419367d41f46bc51aabeb75c93ae5b0cd27 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sun, 19 Feb 2023 16:47:20 +0000 Subject: [PATCH] Added encode packet timings these changes required some new APIs in BedrockProtocol. --- composer.json | 2 +- composer.lock | 14 +++++----- src/network/mcpe/NetworkSession.php | 28 ++++++++++++++++--- .../mcpe/StandardPacketBroadcaster.php | 9 ++++-- src/timings/Timings.php | 11 ++++++++ 5 files changed, 49 insertions(+), 15 deletions(-) diff --git a/composer.json b/composer.json index 0b5a1b69f..6c0641918 100644 --- a/composer.json +++ b/composer.json @@ -37,7 +37,7 @@ "pocketmine/bedrock-block-upgrade-schema": "^1.0.0", "pocketmine/bedrock-data": "~1.14.0+bedrock-1.19.60", "pocketmine/bedrock-item-upgrade-schema": "^1.0.0", - "pocketmine/bedrock-protocol": "~19.2.0+bedrock-1.19.62", + "pocketmine/bedrock-protocol": "~19.3.0+bedrock-1.19.62", "pocketmine/binaryutils": "^0.2.1", "pocketmine/callback-validator": "^1.0.2", "pocketmine/classloader": "^0.2.0", diff --git a/composer.lock b/composer.lock index 99ef44d62..b070d7fc0 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "4c3c6f98f5d9eb34c3c5dab3a2f59282", + "content-hash": "7e0991461c05ed03067e19ed52f4579b", "packages": [ { "name": "adhocore/json-comment", @@ -328,16 +328,16 @@ }, { "name": "pocketmine/bedrock-protocol", - "version": "19.2.0+bedrock-1.19.62", + "version": "19.3.0+bedrock-1.19.62", "source": { "type": "git", "url": "https://github.com/pmmp/BedrockProtocol.git", - "reference": "a156db582d0b1a6c20c9d9cc9b1df7ef907efd0b" + "reference": "a5bf4753c7f30f781c4541918e238f5bb637e7ad" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/a156db582d0b1a6c20c9d9cc9b1df7ef907efd0b", - "reference": "a156db582d0b1a6c20c9d9cc9b1df7ef907efd0b", + "url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/a5bf4753c7f30f781c4541918e238f5bb637e7ad", + "reference": "a5bf4753c7f30f781c4541918e238f5bb637e7ad", "shasum": "" }, "require": { @@ -369,9 +369,9 @@ "description": "An implementation of the Minecraft: Bedrock Edition protocol in PHP", "support": { "issues": "https://github.com/pmmp/BedrockProtocol/issues", - "source": "https://github.com/pmmp/BedrockProtocol/tree/19.2.0+bedrock-1.19.62" + "source": "https://github.com/pmmp/BedrockProtocol/tree/19.3.0+bedrock-1.19.62" }, - "time": "2023-02-17T16:32:49+00:00" + "time": "2023-02-19T16:11:03+00:00" }, { "name": "pocketmine/binaryutils", diff --git a/src/network/mcpe/NetworkSession.php b/src/network/mcpe/NetworkSession.php index ebc943960..7dc9680f2 100644 --- a/src/network/mcpe/NetworkSession.php +++ b/src/network/mcpe/NetworkSession.php @@ -120,6 +120,7 @@ use pocketmine\player\XboxLivePlayerInfo; use pocketmine\Server; use pocketmine\timings\Timings; use pocketmine\utils\AssumptionFailedError; +use pocketmine\utils\BinaryStream; use pocketmine\utils\ObjectSet; use pocketmine\utils\TextFormat; use pocketmine\utils\Utils; @@ -176,7 +177,7 @@ class NetworkSession{ private ?EncryptionContext $cipher = null; - /** @var Packet[] */ + /** @var ClientboundPacket[] */ private array $sendBuffer = []; /** @@ -263,6 +264,23 @@ 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($this->packetSerializerContext); + $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 @@ -502,12 +520,14 @@ class NetworkSession{ $syncMode = false; } - $batch = PacketBatch::fromPackets($this->packetSerializerContext, ...$this->sendBuffer); + $stream = new BinaryStream(); + self::encodePacketBatchTimed($stream, $this->packetSerializerContext, $this->sendBuffer); + if($this->enableCompression){ - $promise = $this->server->prepareBatch($batch, $this->compressor, $syncMode); + $promise = $this->server->prepareBatch(new PacketBatch($stream->getBuffer()), $this->compressor, $syncMode); }else{ $promise = new CompressBatchPromise(); - $promise->resolve($batch->getBuffer()); + $promise->resolve($stream->getBuffer()); } $this->sendBuffer = []; $this->queueCompressedNoBufferFlush($promise, $immediate); diff --git a/src/network/mcpe/StandardPacketBroadcaster.php b/src/network/mcpe/StandardPacketBroadcaster.php index 9cba70739..73848ccae 100644 --- a/src/network/mcpe/StandardPacketBroadcaster.php +++ b/src/network/mcpe/StandardPacketBroadcaster.php @@ -25,6 +25,7 @@ namespace pocketmine\network\mcpe; use pocketmine\network\mcpe\protocol\serializer\PacketBatch; use pocketmine\Server; +use pocketmine\utils\BinaryStream; use function spl_object_id; final class StandardPacketBroadcaster implements PacketBroadcaster{ @@ -38,7 +39,9 @@ final class StandardPacketBroadcaster implements PacketBroadcaster{ $serializerContext = $recipient->getPacketSerializerContext(); $bufferId = spl_object_id($serializerContext); if(!isset($buffers[$bufferId])){ - $buffers[$bufferId] = PacketBatch::fromPackets($serializerContext, ...$packets); + $stream = new BinaryStream(); + NetworkSession::encodePacketBatchTimed($stream, $serializerContext, $packets); + $buffers[$bufferId] = $stream->getBuffer(); } //TODO: different compressors might be compatible, it might not be necessary to split them up by object @@ -52,14 +55,14 @@ final class StandardPacketBroadcaster implements PacketBroadcaster{ $buffer = $buffers[$bufferId]; foreach($compressorMap as $compressorId => $compressorTargets){ $compressor = $compressors[$compressorId]; - if(!$compressor->willCompress($buffer->getBuffer())){ + if(!$compressor->willCompress($buffer)){ foreach($compressorTargets as $target){ foreach($packets as $pk){ $target->addToSendBuffer($pk); } } }else{ - $promise = $this->server->prepareBatch($buffer, $compressor); + $promise = $this->server->prepareBatch(new PacketBatch($buffer), $compressor); foreach($compressorTargets as $target){ $target->queueCompressed($promise); } diff --git a/src/timings/Timings.php b/src/timings/Timings.php index 1f8426969..426e9ab61 100644 --- a/src/timings/Timings.php +++ b/src/timings/Timings.php @@ -127,6 +127,9 @@ abstract class Timings{ /** @var TimingsHandler[] */ private static array $packetHandleTimingMap = []; + /** @var TimingsHandler[] */ + private static array $packetEncodeTimingMap = []; + /** @var TimingsHandler[] */ public static $packetSendTimingMap = []; /** @var TimingsHandler[] */ @@ -254,6 +257,14 @@ abstract class Timings{ ); } + public static function getEncodeDataPacketTimings(ClientboundPacket $pk) : TimingsHandler{ + $pid = $pk->pid(); + return self::$packetEncodeTimingMap[$pid] ??= new TimingsHandler( + self::INCLUDED_BY_OTHER_TIMINGS_PREFIX . "Encode - " . $pk->getName() . " [0x" . dechex($pid) . "]", + self::getSendDataPacketTimings($pk) + ); + } + public static function getSendDataPacketTimings(ClientboundPacket $pk) : TimingsHandler{ $pid = $pk->pid(); if(!isset(self::$packetSendTimingMap[$pid])){