do not mess with cached data directly in packets

This commit is contained in:
Dylan K. Taylor 2020-04-29 11:34:25 +01:00
parent aa57d05e12
commit f6f1d31112
4 changed files with 120 additions and 26 deletions

View File

@ -0,0 +1,69 @@
<?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\network\mcpe;
use pocketmine\network\mcpe\protocol\AvailableActorIdentifiersPacket;
use pocketmine\network\mcpe\protocol\BiomeDefinitionListPacket;
use pocketmine\network\mcpe\protocol\serializer\NetworkNbtSerializer;
use pocketmine\network\mcpe\protocol\types\CacheableNbt;
use pocketmine\utils\SingletonTrait;
use function file_get_contents;
class StaticPacketCache{
use SingletonTrait;
/** @var BiomeDefinitionListPacket */
private $biomeDefs;
/** @var AvailableActorIdentifiersPacket */
private $availableActorIdentifiers;
/**
* @phpstan-return CacheableNbt<\pocketmine\nbt\tag\CompoundTag>
*/
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;
}
}

View File

@ -25,12 +25,11 @@ namespace pocketmine\network\mcpe\handler;
use pocketmine\network\mcpe\convert\RuntimeBlockMapping; use pocketmine\network\mcpe\convert\RuntimeBlockMapping;
use pocketmine\network\mcpe\NetworkSession; 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\RequestChunkRadiusPacket;
use pocketmine\network\mcpe\protocol\SetLocalPlayerAsInitializedPacket; use pocketmine\network\mcpe\protocol\SetLocalPlayerAsInitializedPacket;
use pocketmine\network\mcpe\protocol\StartGamePacket; use pocketmine\network\mcpe\protocol\StartGamePacket;
use pocketmine\network\mcpe\protocol\types\DimensionIds; use pocketmine\network\mcpe\protocol\types\DimensionIds;
use pocketmine\network\mcpe\StaticPacketCache;
use pocketmine\player\Player; use pocketmine\player\Player;
use pocketmine\Server; use pocketmine\Server;
@ -82,8 +81,8 @@ class PreSpawnPacketHandler extends PacketHandler{
$this->session->sendDataPacket($pk); $this->session->sendDataPacket($pk);
$this->session->sendDataPacket(new AvailableActorIdentifiersPacket()); $this->session->sendDataPacket(StaticPacketCache::getInstance()->getAvailableActorIdentifiers());
$this->session->sendDataPacket(new BiomeDefinitionListPacket()); $this->session->sendDataPacket(StaticPacketCache::getInstance()->getBiomeDefs());
$this->player->setImmobile(); //HACK: fix client-side falling pre-spawn $this->player->setImmobile(); //HACK: fix client-side falling pre-spawn

View File

@ -25,28 +25,41 @@ namespace pocketmine\network\mcpe\protocol;
#include <rules/DataPacket.h> #include <rules/DataPacket.h>
use pocketmine\nbt\NbtDataException;
use pocketmine\network\mcpe\protocol\serializer\NetworkBinaryStream; 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{ class AvailableActorIdentifiersPacket extends DataPacket implements ClientboundPacket{
public const NETWORK_ID = ProtocolInfo::AVAILABLE_ACTOR_IDENTIFIERS_PACKET; 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{ 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{ protected function encodePayload(NetworkBinaryStream $out) : void{
$out->put( $out->put($this->identifiers->getEncodedNbt());
$this->namedtag ??
self::$DEFAULT_NBT_CACHE ??
(self::$DEFAULT_NBT_CACHE = file_get_contents(\pocketmine\RESOURCE_PATH . '/vanilla/entity_identifiers.nbt'))
);
} }
public function handle(PacketHandlerInterface $handler) : bool{ public function handle(PacketHandlerInterface $handler) : bool{

View File

@ -25,28 +25,41 @@ namespace pocketmine\network\mcpe\protocol;
#include <rules/DataPacket.h> #include <rules/DataPacket.h>
use pocketmine\nbt\NbtDataException;
use pocketmine\network\mcpe\protocol\serializer\NetworkBinaryStream; 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{ class BiomeDefinitionListPacket extends DataPacket implements ClientboundPacket{
public const NETWORK_ID = ProtocolInfo::BIOME_DEFINITION_LIST_PACKET; 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{ 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{ protected function encodePayload(NetworkBinaryStream $out) : void{
$out->put( $out->put($this->defs->getEncodedNbt());
$this->namedtag ??
self::$DEFAULT_NBT_CACHE ??
(self::$DEFAULT_NBT_CACHE = file_get_contents(\pocketmine\RESOURCE_PATH . '/vanilla/biome_definitions.nbt'))
);
} }
public function handle(PacketHandlerInterface $handler) : bool{ public function handle(PacketHandlerInterface $handler) : bool{