diff --git a/src/world/World.php b/src/world/World.php index b1f11fe7d10..1b90a130e01 100644 --- a/src/world/World.php +++ b/src/world/World.php @@ -259,10 +259,15 @@ class World implements ChunkManager{ private array $playerChunkListeners = []; /** - * @var ClientboundPacket[][] chunkHash => [typeConverterHash => ClientboundPacket[]] - * @phpstan-var array>> + * @var ClientboundPacket[][] chunkHash => ClientboundPacket[] + * @phpstan-var array> */ private array $packetBuffersByChunk = []; + /** + * @var \Closure[][] chunkHash => Closure[] + * @phpstan-var array> + */ + private array $packetBuffersByChunkTypeConverter = []; /** * @var float[] chunkHash => timestamp of request @@ -835,25 +840,18 @@ public function broadcastPacketToViewersByTypeConverter(Vector3 $pos, \Closure $ new ParameterType('typeConverter', TypeConverter::class), ), $closure); - [$typeConverters, ] = TypeConverter::sortByConverter($this->getViewersForPosition($pos)); - - foreach($typeConverters as $typeConverter){ - /** @var ClientboundPacket[] $packets */ - $packets = $closure($typeConverter); - foreach($packets as $packet){ - $this->broadcastPacketToPlayersUsingChunk($pos->getFloorX() >> Chunk::COORD_BIT_SIZE, $pos->getFloorZ() >> Chunk::COORD_BIT_SIZE, $packet, $typeConverter); - } + if(!isset($this->packetBuffersByChunkTypeConverter[$index = World::chunkHash($pos->getFloorX() >> Chunk::COORD_BIT_SIZE, $pos->getFloorZ() >> Chunk::COORD_BIT_SIZE)])){ + $this->packetBuffersByChunkTypeConverter[$index] = [$closure]; + }else{ + $this->packetBuffersByChunkTypeConverter[$index][] = $closure; } } - private function broadcastPacketToPlayersUsingChunk(int $chunkX, int $chunkZ, ClientboundPacket $packet, ?TypeConverter $typeConverter = null) : void{ - /** @phpstan-var int|null $typeConverterId */ - $typeConverterId = $typeConverter === null ? null : spl_object_id($typeConverter); - - if(!isset($this->packetBuffersByChunk[$index = World::chunkHash($chunkX, $chunkZ)][$typeConverterId])){ - $this->packetBuffersByChunk[$index][$typeConverterId] = [$packet]; + private function broadcastPacketToPlayersUsingChunk(int $chunkX, int $chunkZ, ClientboundPacket $packet) : void{ + if(!isset($this->packetBuffersByChunk[$index = World::chunkHash($chunkX, $chunkZ)])){ + $this->packetBuffersByChunk[$index] = [$packet]; }else{ - $this->packetBuffersByChunk[$index][$typeConverterId][] = $packet; + $this->packetBuffersByChunk[$index][] = $packet; } } @@ -1093,21 +1091,31 @@ protected function actuallyDoTick(int $currentTick) : void{ $this->checkSleep(); } - foreach($this->packetBuffersByChunk as $index => $entries){ + foreach($this->packetBuffersByChunkTypeConverter as $index => $entries){ World::getXZ($index, $chunkX, $chunkZ); - $universalPackets = $entries[null] ?? []; [$typeConverters, $converterRecipients] = TypeConverter::sortByConverter($this->getChunkPlayers($chunkX, $chunkZ)); foreach($typeConverters as $key => $typeConverter){ - $packets = ($entries[$key] ?? []) + $universalPackets; + $packets = (array_map(fn(\Closure $closure) => $closure($typeConverter), $entries[$key] ?? [])) + ($this->packetBuffersByChunk[$index] ?? []); if(count($packets) > 0){ NetworkBroadcastUtils::broadcastPackets($converterRecipients[$key], $packets); } } + + unset($this->packetBuffersByChunk[$index]); + } + + foreach($this->packetBuffersByChunk as $index => $entries){ + World::getXZ($index, $chunkX, $chunkZ); + $chunkPlayers = $this->getChunkPlayers($chunkX, $chunkZ); + if(count($chunkPlayers) > 0){ + NetworkBroadcastUtils::broadcastPackets($chunkPlayers, $entries); + } } $this->packetBuffersByChunk = []; + $this->packetBuffersByChunkTypeConverter = []; } public function checkSleep() : void{