From f6f1d31112f55606b666b700238dc40b7771d849 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 29 Apr 2020 11:34:25 +0100 Subject: [PATCH] do not mess with cached data directly in packets --- src/network/mcpe/StaticPacketCache.php | 69 +++++++++++++++++++ .../mcpe/handler/PreSpawnPacketHandler.php | 7 +- .../AvailableActorIdentifiersPacket.php | 35 +++++++--- .../protocol/BiomeDefinitionListPacket.php | 35 +++++++--- 4 files changed, 120 insertions(+), 26 deletions(-) create mode 100644 src/network/mcpe/StaticPacketCache.php diff --git a/src/network/mcpe/StaticPacketCache.php b/src/network/mcpe/StaticPacketCache.php new file mode 100644 index 000000000..6ef7e8aed --- /dev/null +++ b/src/network/mcpe/StaticPacketCache.php @@ -0,0 +1,69 @@ + + */ + private static function loadCompoundFromFile(string $filePath) : CacheableNbt{ + $rawNbt = @file_get_contents($filePath); + if($rawNbt === false) throw new \RuntimeException("Failed to read file"); + return new CacheableNbt((new NetworkNbtSerializer())->read($rawNbt)->mustGetCompoundTag()); + } + + private static function make() : self{ + return new self( + BiomeDefinitionListPacket::create(self::loadCompoundFromFile(\pocketmine\RESOURCE_PATH . '/vanilla/biome_definitions.nbt')), + AvailableActorIdentifiersPacket::create(self::loadCompoundFromFile(\pocketmine\RESOURCE_PATH . '/vanilla/entity_identifiers.nbt')) + ); + } + + public function __construct(BiomeDefinitionListPacket $biomeDefs, AvailableActorIdentifiersPacket $availableActorIdentifiers){ + $this->biomeDefs = $biomeDefs; + $this->availableActorIdentifiers = $availableActorIdentifiers; + } + + public function getBiomeDefs() : BiomeDefinitionListPacket{ + return $this->biomeDefs; + } + + public function getAvailableActorIdentifiers() : AvailableActorIdentifiersPacket{ + return $this->availableActorIdentifiers; + } +} \ No newline at end of file diff --git a/src/network/mcpe/handler/PreSpawnPacketHandler.php b/src/network/mcpe/handler/PreSpawnPacketHandler.php index b25ad0267..1407c727d 100644 --- a/src/network/mcpe/handler/PreSpawnPacketHandler.php +++ b/src/network/mcpe/handler/PreSpawnPacketHandler.php @@ -25,12 +25,11 @@ namespace pocketmine\network\mcpe\handler; use pocketmine\network\mcpe\convert\RuntimeBlockMapping; use pocketmine\network\mcpe\NetworkSession; -use pocketmine\network\mcpe\protocol\AvailableActorIdentifiersPacket; -use pocketmine\network\mcpe\protocol\BiomeDefinitionListPacket; use pocketmine\network\mcpe\protocol\RequestChunkRadiusPacket; use pocketmine\network\mcpe\protocol\SetLocalPlayerAsInitializedPacket; use pocketmine\network\mcpe\protocol\StartGamePacket; use pocketmine\network\mcpe\protocol\types\DimensionIds; +use pocketmine\network\mcpe\StaticPacketCache; use pocketmine\player\Player; use pocketmine\Server; @@ -82,8 +81,8 @@ class PreSpawnPacketHandler extends PacketHandler{ $this->session->sendDataPacket($pk); - $this->session->sendDataPacket(new AvailableActorIdentifiersPacket()); - $this->session->sendDataPacket(new BiomeDefinitionListPacket()); + $this->session->sendDataPacket(StaticPacketCache::getInstance()->getAvailableActorIdentifiers()); + $this->session->sendDataPacket(StaticPacketCache::getInstance()->getBiomeDefs()); $this->player->setImmobile(); //HACK: fix client-side falling pre-spawn diff --git a/src/network/mcpe/protocol/AvailableActorIdentifiersPacket.php b/src/network/mcpe/protocol/AvailableActorIdentifiersPacket.php index c3990e3aa..4d2a1cade 100644 --- a/src/network/mcpe/protocol/AvailableActorIdentifiersPacket.php +++ b/src/network/mcpe/protocol/AvailableActorIdentifiersPacket.php @@ -25,28 +25,41 @@ namespace pocketmine\network\mcpe\protocol; #include +use pocketmine\nbt\NbtDataException; use pocketmine\network\mcpe\protocol\serializer\NetworkBinaryStream; -use function file_get_contents; +use pocketmine\network\mcpe\protocol\serializer\NetworkNbtSerializer; +use pocketmine\network\mcpe\protocol\types\CacheableNbt; class AvailableActorIdentifiersPacket extends DataPacket implements ClientboundPacket{ public const NETWORK_ID = ProtocolInfo::AVAILABLE_ACTOR_IDENTIFIERS_PACKET; - /** @var string|null */ - private static $DEFAULT_NBT_CACHE = null; + /** + * @var CacheableNbt + * @phpstan-var CacheableNbt<\pocketmine\nbt\tag\CompoundTag> + */ + public $identifiers; - /** @var string */ - public $namedtag; + /** + * @phpstan-param CacheableNbt<\pocketmine\nbt\tag\CompoundTag> $nbt + */ + public static function create(CacheableNbt $nbt) : self{ + $result = new self; + $result->identifiers = $nbt; + return $result; + } protected function decodePayload(NetworkBinaryStream $in) : void{ - $this->namedtag = $in->getRemaining(); + $offset = $in->getOffset(); + try{ + $this->identifiers = new CacheableNbt((new NetworkNbtSerializer())->read($in->getBuffer(), $offset)->mustGetCompoundTag()); + }catch(NbtDataException $e){ + throw PacketDecodeException::wrap($e, "Failed decoding actor identifiers"); + } + $in->setOffset($offset); } protected function encodePayload(NetworkBinaryStream $out) : void{ - $out->put( - $this->namedtag ?? - self::$DEFAULT_NBT_CACHE ?? - (self::$DEFAULT_NBT_CACHE = file_get_contents(\pocketmine\RESOURCE_PATH . '/vanilla/entity_identifiers.nbt')) - ); + $out->put($this->identifiers->getEncodedNbt()); } public function handle(PacketHandlerInterface $handler) : bool{ diff --git a/src/network/mcpe/protocol/BiomeDefinitionListPacket.php b/src/network/mcpe/protocol/BiomeDefinitionListPacket.php index 8229843e2..0388c1109 100644 --- a/src/network/mcpe/protocol/BiomeDefinitionListPacket.php +++ b/src/network/mcpe/protocol/BiomeDefinitionListPacket.php @@ -25,28 +25,41 @@ namespace pocketmine\network\mcpe\protocol; #include +use pocketmine\nbt\NbtDataException; use pocketmine\network\mcpe\protocol\serializer\NetworkBinaryStream; -use function file_get_contents; +use pocketmine\network\mcpe\protocol\serializer\NetworkNbtSerializer; +use pocketmine\network\mcpe\protocol\types\CacheableNbt; class BiomeDefinitionListPacket extends DataPacket implements ClientboundPacket{ public const NETWORK_ID = ProtocolInfo::BIOME_DEFINITION_LIST_PACKET; - /** @var string|null */ - private static $DEFAULT_NBT_CACHE = null; + /** + * @var CacheableNbt + * @phpstan-var CacheableNbt<\pocketmine\nbt\tag\CompoundTag> + */ + public $defs; - /** @var string */ - public $namedtag; + /** + * @phpstan-param CacheableNbt<\pocketmine\nbt\tag\CompoundTag> $nbt + */ + public static function create(CacheableNbt $nbt) : self{ + $result = new self; + $result->defs = $nbt; + return $result; + } protected function decodePayload(NetworkBinaryStream $in) : void{ - $this->namedtag = $in->getRemaining(); + $offset = $in->getOffset(); + try{ + $this->defs = new CacheableNbt((new NetworkNbtSerializer())->read($in->getBuffer(), $offset)->mustGetCompoundTag()); + }catch(NbtDataException $e){ + throw PacketDecodeException::wrap($e, "Failed decoding biome definitions"); + } + $in->setOffset($offset); } protected function encodePayload(NetworkBinaryStream $out) : void{ - $out->put( - $this->namedtag ?? - self::$DEFAULT_NBT_CACHE ?? - (self::$DEFAULT_NBT_CACHE = file_get_contents(\pocketmine\RESOURCE_PATH . '/vanilla/biome_definitions.nbt')) - ); + $out->put($this->defs->getEncodedNbt()); } public function handle(PacketHandlerInterface $handler) : bool{