mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-20 16:00:20 +00:00
Workaround items in blockentity NBT not being processed correctly in 1.19.10
closes #5154 this hack sends only the bare essential data to create the tiles in LevelChunkPacket, and then separately sending the full tile data using BlockActorDataPacket afterwards. This is necessary because the client doesn't handle items correctly in NBT when chunks are sent without using the SubChunkRequest system. In 4.6 this is observed with incorrect items shown in item frames; in 5.0 it's seen with items simply not showing up at all (difference due to modernization of the serialization format in 5.0).
This commit is contained in:
parent
c7133bc2e6
commit
2b61c025c2
@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\network\mcpe;
|
||||
|
||||
use pocketmine\block\tile\Spawnable;
|
||||
use pocketmine\data\bedrock\EffectIdMap;
|
||||
use pocketmine\entity\Attribute;
|
||||
use pocketmine\entity\effect\EffectInstance;
|
||||
@ -58,6 +59,7 @@ use pocketmine\network\mcpe\handler\PreSpawnPacketHandler;
|
||||
use pocketmine\network\mcpe\handler\ResourcePacksPacketHandler;
|
||||
use pocketmine\network\mcpe\handler\SpawnResponsePacketHandler;
|
||||
use pocketmine\network\mcpe\protocol\AvailableCommandsPacket;
|
||||
use pocketmine\network\mcpe\protocol\BlockActorDataPacket;
|
||||
use pocketmine\network\mcpe\protocol\ChunkRadiusUpdatedPacket;
|
||||
use pocketmine\network\mcpe\protocol\ClientboundPacket;
|
||||
use pocketmine\network\mcpe\protocol\DisconnectPacket;
|
||||
@ -959,6 +961,22 @@ class NetworkSession{
|
||||
try{
|
||||
$this->queueCompressed($promise);
|
||||
$onCompletion();
|
||||
|
||||
//TODO: HACK! we send the full tile data here, due to a bug in 1.19.10 which causes items in tiles
|
||||
//(item frames, lecterns) to not load properly when they are sent in a chunk via the classic chunk
|
||||
//sending mechanism. We workaround this bug by sending only bare essential data in LevelChunkPacket
|
||||
//(enough to create the tiles, since BlockActorDataPacket can't create tiles by itself) and then
|
||||
//send the actual tile properties here.
|
||||
//TODO: maybe we can stuff these packets inside the cached batch alongside LevelChunkPacket?
|
||||
$chunk = $currentWorld->getChunk($chunkX, $chunkZ);
|
||||
if($chunk !== null){
|
||||
foreach($chunk->getTiles() as $tile){
|
||||
if(!($tile instanceof Spawnable)){
|
||||
continue;
|
||||
}
|
||||
$this->sendDataPacket(BlockActorDataPacket::create(BlockPosition::fromVector3($tile->getPosition()), $tile->getSerializedSpawnCompound()));
|
||||
}
|
||||
}
|
||||
}finally{
|
||||
$world->timings->syncChunkSend->stopTiming();
|
||||
}
|
||||
|
@ -24,8 +24,11 @@ declare(strict_types=1);
|
||||
namespace pocketmine\network\mcpe\serializer;
|
||||
|
||||
use pocketmine\block\tile\Spawnable;
|
||||
use pocketmine\block\tile\Tile;
|
||||
use pocketmine\block\tile\TileFactory;
|
||||
use pocketmine\data\bedrock\BiomeIds;
|
||||
use pocketmine\data\bedrock\LegacyBiomeIdToStringIdMap;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\TreeRoot;
|
||||
use pocketmine\network\mcpe\convert\RuntimeBlockMapping;
|
||||
use pocketmine\network\mcpe\protocol\serializer\NetworkNbtSerializer;
|
||||
@ -38,6 +41,7 @@ use pocketmine\world\format\PalettedBlockArray;
|
||||
use pocketmine\world\format\SubChunk;
|
||||
use function chr;
|
||||
use function count;
|
||||
use function get_class;
|
||||
use function str_repeat;
|
||||
|
||||
final class ChunkSerializer{
|
||||
@ -125,9 +129,19 @@ final class ChunkSerializer{
|
||||
|
||||
public static function serializeTiles(Chunk $chunk) : string{
|
||||
$stream = new BinaryStream();
|
||||
$nbtSerializer = new NetworkNbtSerializer();
|
||||
foreach($chunk->getTiles() as $tile){
|
||||
if($tile instanceof Spawnable){
|
||||
$stream->put($tile->getSerializedSpawnCompound()->getEncodedNbt());
|
||||
//TODO: HACK! we send only the bare essentials to create a tile in the chunk itself, due to a bug in
|
||||
//1.19.10 which causes items in tiles (item frames, lecterns) to not load properly when they are sent in
|
||||
//a chunk via the classic chunk sending mechanism. We workaround this bug by sendingBlockActorDataPacket
|
||||
//in NetworkSession to set the actual tile properties after sending the LevelChunkPacket.
|
||||
$nbt = CompoundTag::create()
|
||||
->setString(Tile::TAG_ID, TileFactory::getInstance()->getSaveId(get_class($tile)))
|
||||
->setInt(Tile::TAG_X, $tile->getPosition()->getFloorX())
|
||||
->setInt(Tile::TAG_Y, $tile->getPosition()->getFloorY())
|
||||
->setInt(Tile::TAG_Z, $tile->getPosition()->getFloorZ());
|
||||
$stream->put($nbtSerializer->write(new TreeRoot($nbt)));
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user