Skip to content

Commit

Permalink
Remove clientside chunk caching
Browse files Browse the repository at this point in the history
  • Loading branch information
dries-c committed Jan 23, 2025
1 parent 68ace67 commit 0e32816
Show file tree
Hide file tree
Showing 14 changed files with 135 additions and 87 deletions.
3 changes: 0 additions & 3 deletions src/block/MossCarpet.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,6 @@ public function isSolid() : bool{
return true;
}

/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{
return [AxisAlignedBB::one()->trim(Facing::UP, 15 / 16)];
}
Expand Down
54 changes: 19 additions & 35 deletions src/network/mcpe/ChunkRequestTask.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,21 @@

namespace pocketmine\network\mcpe;

use pocketmine\network\mcpe\compression\CompressBatchPromise;
use pocketmine\network\mcpe\compression\Compressor;
use pocketmine\network\mcpe\convert\TypeConverter;
use pocketmine\network\mcpe\protocol\serializer\PacketSerializer;
use pocketmine\network\mcpe\protocol\LevelChunkPacket;
use pocketmine\network\mcpe\protocol\ProtocolInfo;
use pocketmine\network\mcpe\protocol\serializer\PacketBatch;
use pocketmine\network\mcpe\protocol\types\ChunkPosition;
use pocketmine\network\mcpe\protocol\types\DimensionIds;
use pocketmine\network\mcpe\serializer\ChunkSerializer;
use pocketmine\scheduler\AsyncTask;
use pocketmine\thread\NonThreadSafeValue;
use pocketmine\utils\Binary;
use pocketmine\utils\BinaryStream;
use pocketmine\world\format\Chunk;
use pocketmine\world\format\io\FastChunkSerializer;
/** @phpstan-ignore-next-line */
use function xxhash64;
use function chr;

class ChunkRequestTask extends AsyncTask{
private const TLS_KEY_PROMISE = "promise";
Expand All @@ -52,7 +55,7 @@ class ChunkRequestTask extends AsyncTask{
/**
* @phpstan-param DimensionIds::* $dimensionId
*/
public function __construct(int $chunkX, int $chunkZ, int $dimensionId, Chunk $chunk, TypeConverter $typeConverter, CachedChunkPromise $promise, Compressor $compressor){
public function __construct(int $chunkX, int $chunkZ, int $dimensionId, Chunk $chunk, TypeConverter $typeConverter, CompressBatchPromise $promise, Compressor $compressor){
$this->compressor = new NonThreadSafeValue($compressor);
$this->mappingProtocol = $typeConverter->getProtocolId();

Expand All @@ -67,42 +70,23 @@ public function __construct(int $chunkX, int $chunkZ, int $dimensionId, Chunk $c

public function onRun() : void{
$chunk = FastChunkSerializer::deserializeTerrain($this->chunk);
$dimensionId = $this->dimensionId;

$cache = new CachedChunk();
$subCount = ChunkSerializer::getSubChunkCount($chunk, $dimensionId);
$converter = TypeConverter::getInstance();
$payload = ChunkSerializer::serializeFullChunk($chunk, $dimensionId, $converter, $this->tiles);

$converter = TypeConverter::getInstance($this->mappingProtocol);
foreach(ChunkSerializer::serializeSubChunks($chunk, $this->dimensionId, $converter->getBlockTranslator(), $this->mappingProtocol) as $subChunk){
/** @phpstan-ignore-next-line */
$cache->addSubChunk(Binary::readLong(xxhash64($subChunk)), $subChunk);
}
$stream = new BinaryStream();
PacketBatch::encodePackets($stream, $this->mappingProtocol, [LevelChunkPacket::create(new ChunkPosition($this->chunkX, $this->chunkZ), $dimensionId, $subCount, false, null, $payload)]);

$encoder = PacketSerializer::encoder($this->mappingProtocol);
$biomeEncoder = clone $encoder;
ChunkSerializer::serializeBiomes($chunk, $this->dimensionId, $biomeEncoder);
/** @phpstan-ignore-next-line */
$cache->setBiomes(Binary::readLong(xxhash64($chunkBuffer = $biomeEncoder->getBuffer())), $chunkBuffer);

$chunkDataEncoder = clone $encoder;
ChunkSerializer::serializeChunkData($chunk, $chunkDataEncoder, $converter, $this->tiles);

$cache->compressPackets(
$this->chunkX,
$this->chunkZ,
$this->dimensionId,
$chunkDataEncoder->getBuffer(),
$this->compressor->deserialize(),
$this->mappingProtocol
);

$this->setResult($cache);
$compressor = $this->compressor->deserialize();
$protocolAddition = $this->mappingProtocol >= ProtocolInfo::PROTOCOL_1_20_60 ? chr($compressor->getNetworkId()) : '';
$this->setResult($protocolAddition . $compressor->compress($stream->getBuffer()));
}

public function onCompletion() : void{
/** @var CachedChunk $result */
$result = $this->getResult();

/** @var CachedChunkPromise $promise */
/** @var CompressBatchPromise $promise */
$promise = $this->fetchLocal(self::TLS_KEY_PROMISE);
$promise->resolve($result);
$promise->resolve($this->getResult());
}
}
5 changes: 0 additions & 5 deletions src/network/mcpe/NetworkSession.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@
use pocketmine\network\mcpe\protocol\ChunkRadiusUpdatedPacket;
use pocketmine\network\mcpe\protocol\ClientboundCloseFormPacket;
use pocketmine\network\mcpe\protocol\ClientboundPacket;
use pocketmine\network\mcpe\protocol\ClientCacheMissResponsePacket;
use pocketmine\network\mcpe\protocol\DisconnectPacket;
use pocketmine\network\mcpe\protocol\ModalFormRequestPacket;
use pocketmine\network\mcpe\protocol\MovePlayerPacket;
Expand Down Expand Up @@ -86,7 +85,6 @@
use pocketmine\network\mcpe\protocol\types\AbilitiesData;
use pocketmine\network\mcpe\protocol\types\AbilitiesLayer;
use pocketmine\network\mcpe\protocol\types\BlockPosition;
use pocketmine\network\mcpe\protocol\types\ChunkCacheBlob;
use pocketmine\network\mcpe\protocol\types\command\CommandData;
use pocketmine\network\mcpe\protocol\types\command\CommandEnum;
use pocketmine\network\mcpe\protocol\types\command\CommandOverload;
Expand Down Expand Up @@ -120,10 +118,7 @@
use pocketmine\world\Position;
use pocketmine\world\World;
use pocketmine\YmlServerProperties;
use function array_keys;
use function array_map;
use function array_replace;
use function array_values;
use function base64_encode;
use function bin2hex;
use function count;
Expand Down
10 changes: 3 additions & 7 deletions src/network/mcpe/cache/ChunkCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
use function count;
use function is_string;
use function spl_object_id;
use function strlen;

/**
* This class is used by the current MCPE protocol system to store cached chunk packets for fast resending.
Expand Down Expand Up @@ -102,12 +103,7 @@ private function prepareChunkAsync(int $chunkX, int $chunkZ, int $chunkHash, Typ
if($chunk === null){
throw new \InvalidArgumentException("Cannot request an unloaded chunk");
}
$protocolId = $typeConverter->getProtocolId();

if(isset($this->caches[$chunkHash][$protocolId])){
++$this->hits;
return $this->caches[$chunkHash][$protocolId];
}
++$this->misses;

$this->world->timings->syncChunkSendPrepare->startTiming();
try{
Expand All @@ -124,7 +120,7 @@ private function prepareChunkAsync(int $chunkX, int $chunkZ, int $chunkHash, Typ
$this->compressor
)
);
$this->caches[$chunkHash][$protocolId] = $promise;
$this->caches[$chunkHash][$protocolId = $typeConverter->getProtocolId()] = $promise;
$promise->onResolve(function(CompressBatchPromise $promise) use ($chunkHash, $protocolId) : void{
//the promise may have been discarded or replaced if the chunk was unloaded or modified in the meantime
if(($this->caches[$chunkHash][$protocolId] ?? null) === $promise){
Expand Down
8 changes: 3 additions & 5 deletions src/network/mcpe/handler/InGamePacketHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@
/**
* This handler handles packets related to general gameplay.
*/
class InGamePacketHandler extends ChunkRequestPacketHandler{
class InGamePacketHandler extends PacketHandler{
private const MAX_FORM_RESPONSE_DEPTH = 2; //modal/simple will be 1, custom forms 2 - they will never contain anything other than string|int|float|bool|null

protected float $lastRightClickTime = 0.0;
Expand All @@ -145,11 +145,9 @@ class InGamePacketHandler extends ChunkRequestPacketHandler{

public function __construct(
private Player $player,
NetworkSession $session,
private NetworkSession $session,
private InventoryManager $inventoryManager
){
parent::__construct($session);
}
){}

public function handleText(TextPacket $packet) : bool{
if($packet->type === TextPacket::TYPE_CHAT){
Expand Down
8 changes: 3 additions & 5 deletions src/network/mcpe/handler/LoginPacketHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,19 +49,17 @@
/**
* Handles the initial login phase of the session. This handler is used as the initial state.
*/
class LoginPacketHandler extends ChunkRequestPacketHandler{
class LoginPacketHandler extends PacketHandler{
/**
* @phpstan-param \Closure(PlayerInfo) : void $playerInfoConsumer
* @phpstan-param \Closure(bool $isAuthenticated, bool $authRequired, Translatable|string|null $error, ?string $clientPubKey) : void $authCallback
*/
public function __construct(
private Server $server,
NetworkSession $session,
private NetworkSession $session,
private \Closure $playerInfoConsumer,
private \Closure $authCallback
){
parent::__construct($session);
}
){}

public function handleLogin(LoginPacket $packet) : bool{
$protocolVersion = $packet->protocol;
Expand Down
8 changes: 3 additions & 5 deletions src/network/mcpe/handler/PreSpawnPacketHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,13 @@
/**
* Handler used for the pre-spawn phase of the session.
*/
class PreSpawnPacketHandler extends ChunkRequestPacketHandler{
class PreSpawnPacketHandler extends PacketHandler{
public function __construct(
private Server $server,
private Player $player,
NetworkSession $session,
private NetworkSession $session,
private InventoryManager $inventoryManager
){
parent::__construct($session);
}
){}

public function setUp() : void{
Timings::$playerNetworkSendPreSpawnGameData->startTiming();
Expand Down
4 changes: 1 addition & 3 deletions src/network/mcpe/handler/ResourcePacksPacketHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
* Handler used for the resource packs sequence phase of the session. This handler takes care of downloading resource
* packs to the client.
*/
class ResourcePacksPacketHandler extends ChunkRequestPacketHandler{
class ResourcePacksPacketHandler extends PacketHandler{
private const PACK_CHUNK_SIZE = 256 * 1024; //256KB

/**
Expand Down Expand Up @@ -89,8 +89,6 @@ public function __construct(
private bool $mustAccept,
private \Closure $completionCallback
){
parent::__construct($session);

$this->requestQueue = new \SplQueue();
foreach($resourcePackStack as $pack){
$this->resourcePacksById[$pack->getPackId()] = $pack;
Expand Down
7 changes: 2 additions & 5 deletions src/network/mcpe/handler/SpawnResponsePacketHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,15 @@

namespace pocketmine\network\mcpe\handler;

use pocketmine\network\mcpe\NetworkSession;
use pocketmine\network\mcpe\protocol\PlayerAuthInputPacket;
use pocketmine\network\mcpe\protocol\PlayerSkinPacket;
use pocketmine\network\mcpe\protocol\SetLocalPlayerAsInitializedPacket;

final class SpawnResponsePacketHandler extends ChunkRequestPacketHandler{
final class SpawnResponsePacketHandler extends PacketHandler{
/**
* @phpstan-param \Closure() : void $responseCallback
*/
public function __construct(private \Closure $responseCallback, NetworkSession $session){
parent::__construct($session);
}
public function __construct(private \Closure $responseCallback){}

public function handleSetLocalPlayerAsInitialized(SetLocalPlayerAsInitializedPacket $packet) : bool{
($this->responseCallback)();
Expand Down
16 changes: 8 additions & 8 deletions src/network/mcpe/serializer/ChunkSerializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,18 +85,18 @@ public static function getSubChunkCount(Chunk $chunk, int $dimensionId) : int{
* @phpstan-param DimensionIds::* $dimensionId
* @return string[]
*/
public static function serializeSubChunks(Chunk $chunk, int $dimensionId, BlockTranslator $blockTranslator, int $protocolId) : array
public static function serializeSubChunks(Chunk $chunk, int $dimensionId, TypeConverter $typeConverter) : array
{
$stream = PacketSerializer::encoder($protocolId);
$stream = PacketSerializer::encoder($typeConverter->getProtocolId());
$subChunks = [];

$subChunkCount = self::getSubChunkCount($chunk, $dimensionId);
$writtenCount = 0;

[$minSubChunkIndex, $maxSubChunkIndex] = self::getDimensionChunkBounds($dimensionId);
[$minSubChunkIndex, ] = self::getDimensionChunkBounds($dimensionId);
for($y = $minSubChunkIndex; $writtenCount < $subChunkCount; ++$y, ++$writtenCount){
$subChunkStream = clone $stream;
self::serializeSubChunk($chunk->getSubChunk($y), $blockTranslator, $subChunkStream, false);
self::serializeSubChunk($chunk->getSubChunk($y), $typeConverter->getBlockTranslator(), $subChunkStream, false);
$subChunks[] = $subChunkStream->getBuffer();
}

Expand All @@ -106,15 +106,15 @@ public static function serializeSubChunks(Chunk $chunk, int $dimensionId, BlockT
/**
* @phpstan-param DimensionIds::* $dimensionId
*/
public static function serializeFullChunk(Chunk $chunk, int $dimensionId, TypeConverter $converter, int $protocolId, ?string $tiles = null) : string{
$stream = PacketSerializer::encoder($protocolId);
public static function serializeFullChunk(Chunk $chunk, int $dimensionId, TypeConverter $typeConverter, ?string $tiles = null) : string{
$stream = PacketSerializer::encoder($typeConverter->getProtocolId());

foreach(self::serializeSubChunks($chunk, $dimensionId, $converter->getBlockTranslator(), $protocolId) as $subChunk){
foreach(self::serializeSubChunks($chunk, $dimensionId, $typeConverter) as $subChunk){
$stream->put($subChunk);
}

self::serializeBiomes($chunk, $dimensionId, $stream);
self::serializeChunkData($chunk, $stream, $converter, $tiles);
self::serializeChunkData($chunk, $stream, $typeConverter, $tiles);

return $stream->getBuffer();
}
Expand Down
19 changes: 14 additions & 5 deletions src/world/World.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
use pocketmine\world\particle\ProtocolParticle;
use pocketmine\world\sound\BlockPlaceSound;
use pocketmine\world\sound\BlockSound;
use pocketmine\world\sound\ProtocolSound;
use pocketmine\world\sound\Sound;
use pocketmine\world\utils\SubChunkExplorer;
use pocketmine\YmlServerProperties;
Expand Down Expand Up @@ -730,11 +731,19 @@ public function addSound(Vector3 $pos, Sound $sound, ?array $players = null) : v
$players = $ev->getRecipients();
}

if($sound instanceof BlockSound){
$closure = function(TypeConverter $typeConverter) use ($sound, $pos) : array{
$sound->setBlockTranslator($typeConverter->getBlockTranslator());
return $sound->encode($pos);
};
if(($blockSound = ($sound instanceof BlockSound)) || $sound instanceof ProtocolSound){
if($blockSound){
$closure = function(TypeConverter $typeConverter) use ($sound, $pos) : array{
$sound->setBlockTranslator($typeConverter->getBlockTranslator());
return $sound->encode($pos);
};
}else{
/** @var ProtocolSound $sound */
$closure = function(TypeConverter $typeConverter) use ($sound, $pos) : array{
$sound->setProtocolId($typeConverter->getProtocolId());
return $sound->encode($pos);
};
}

if($players === $this->getViewersForPosition($pos)){
$this->broadcastPacketToViewersByTypeConverter($pos, $closure);
Expand Down
12 changes: 11 additions & 1 deletion src/world/sound/NoteSound.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@
use pocketmine\data\bedrock\NoteInstrumentIdMap;
use pocketmine\math\Vector3;
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
use pocketmine\network\mcpe\protocol\ProtocolInfo;
use pocketmine\network\mcpe\protocol\types\LevelSoundEvent;

class NoteSound implements Sound{
class NoteSound extends ProtocolSound{
public function __construct(
private NoteInstrument $instrument,
private int $note
Expand All @@ -40,6 +41,15 @@ public function __construct(

public function encode(Vector3 $pos) : array{
$instrumentId = NoteInstrumentIdMap::getInstance()->toId($this->instrument);

if($this->protocolId < ProtocolInfo::PROTOCOL_1_21_50){
if($instrumentId === 5 || $instrumentId === 7){
$instrumentId++;
}elseif($instrumentId === 6 || $instrumentId === 8){
$instrumentId--;
}
}

return [LevelSoundEventPacket::nonActorSound(LevelSoundEvent::NOTE, $pos, false, ($instrumentId << 8) | $this->note)];
}
}
33 changes: 33 additions & 0 deletions src/world/sound/ProtocolSound.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/

declare(strict_types=1);

namespace pocketmine\world\sound;

abstract class ProtocolSound implements Sound{

protected int $protocolId;

public function setProtocolId(int $protocolId) : void{
$this->protocolId = $protocolId;
}
}
Loading

0 comments on commit 0e32816

Please sign in to comment.