diff --git a/src/network/mcpe/NetworkSession.php b/src/network/mcpe/NetworkSession.php index 5ff3998a2..fc46f8ae5 100644 --- a/src/network/mcpe/NetworkSession.php +++ b/src/network/mcpe/NetworkSession.php @@ -447,6 +447,8 @@ class NetworkSession{ } } + public function getPacketSerializerContext() : PacketSerializerContext{ return $this->packetSerializerContext; } + public function getBroadcaster() : PacketBroadcaster{ return $this->broadcaster; } public function getCompressor() : Compressor{ diff --git a/src/network/mcpe/StandardPacketBroadcaster.php b/src/network/mcpe/StandardPacketBroadcaster.php index 1442a5bbf..4da9b0951 100644 --- a/src/network/mcpe/StandardPacketBroadcaster.php +++ b/src/network/mcpe/StandardPacketBroadcaster.php @@ -23,10 +23,7 @@ declare(strict_types=1); namespace pocketmine\network\mcpe; -use pocketmine\network\mcpe\compression\Compressor; -use pocketmine\network\mcpe\convert\GlobalItemTypeDictionary; use pocketmine\network\mcpe\protocol\serializer\PacketBatch; -use pocketmine\network\mcpe\protocol\serializer\PacketSerializerContext; use pocketmine\Server; use function spl_object_id; @@ -40,35 +37,40 @@ final class StandardPacketBroadcaster implements PacketBroadcaster{ } public function broadcastPackets(array $recipients, array $packets) : void{ - //TODO: we should be using session-specific serializer contexts for this - $stream = PacketBatch::fromPackets(new PacketSerializerContext(GlobalItemTypeDictionary::getInstance()->getDictionary()), ...$packets); - - /** @var Compressor[] $compressors */ + $buffers = []; $compressors = []; - /** @var NetworkSession[][] $compressorTargets */ - $compressorTargets = []; + $targetMap = []; foreach($recipients as $recipient){ - $compressor = $recipient->getCompressor(); - $compressorId = spl_object_id($compressor); + $serializerContext = $recipient->getPacketSerializerContext(); + $bufferId = spl_object_id($serializerContext); + if(!isset($buffers[$bufferId])){ + $buffers[$bufferId] = PacketBatch::fromPackets($serializerContext, ...$packets); + } + //TODO: different compressors might be compatible, it might not be necessary to split them up by object - $compressors[$compressorId] = $compressor; - $compressorTargets[$compressorId][] = $recipient; + $compressor = $recipient->getCompressor(); + $compressors[spl_object_id($compressor)] = $compressor; + + $targetMap[$bufferId][spl_object_id($compressor)][] = $recipient; } - foreach($compressors as $compressorId => $compressor){ - if(!$compressor->willCompress($stream->getBuffer())){ - foreach($compressorTargets[$compressorId] as $target){ - foreach($packets as $pk){ - $target->addToSendBuffer($pk); + foreach($targetMap as $bufferId => $compressorMap){ + $buffer = $buffers[$bufferId]; + foreach($compressorMap as $compressorId => $compressorTargets){ + $compressor = $compressors[$compressorId]; + if(!$compressor->willCompress($buffer->getBuffer())){ + foreach($compressorTargets as $target){ + foreach($packets as $pk){ + $target->addToSendBuffer($pk); + } + } + }else{ + $promise = $this->server->prepareBatch($buffer, $compressor); + foreach($compressorTargets as $target){ + $target->queueCompressed($promise); } - } - }else{ - $promise = $this->server->prepareBatch($stream, $compressor); - foreach($compressorTargets[$compressorId] as $target){ - $target->queueCompressed($promise); } } } - } }