Skip to content

Commit

Permalink
BaseNbtSerializer: added support for reading and writing headless tags
Browse files Browse the repository at this point in the history
in the future it might be nice to make this generic, but it's not worth the effort and BC breaks right now, since we only need this in one place anyway.
  • Loading branch information
dktapps committed Jul 14, 2023
1 parent 5c3307f commit 55c2c31
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 0 deletions.
31 changes: 31 additions & 0 deletions src/BaseNbtSerializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

namespace pocketmine\nbt;

use pocketmine\nbt\tag\Tag;
use pocketmine\utils\Binary;
use pocketmine\utils\BinaryDataException;
use pocketmine\utils\BinaryStream;
Expand Down Expand Up @@ -73,6 +74,24 @@ public function read(string $buffer, int &$offset = 0, int $maxDepth = 0) : Tree
return $data;
}

/**
* Reads a tag without a header from the buffer and returns it. The tag does not have a name, and the type is not
* specified by the binary data. Only the tag's raw binary value is present.
*
* This could be used if the expected root type is always the same, but it's not usually seen in the wild.
* However, this is used in some places in the Minecraft: Bedrock network protocol.
*
* @throws NbtDataException
*/
public function readHeadless(string $buffer, int $rootType, int &$offset = 0, int $maxDepth = 0) : Tag{
$this->buffer = new BinaryStream($buffer, $offset);

$data = NBT::createTag($rootType, $this, new ReaderTracker($maxDepth));
$offset = $this->buffer->getOffset();

return $data;
}

/**
* Decodes a list of NBT tags into objects and returns them.
*
Expand Down Expand Up @@ -111,6 +130,18 @@ public function write(TreeRoot $data) : string{
return $this->buffer->getBuffer();
}

/**
* Writes a nameless tag without any header information. The reader of the data must know what type to expect, as
* it is not specified in the data.
*
* @see BaseNbtSerializer::readHeadless()
*/
public function writeHeadless(Tag $data) : string{
$this->buffer = new BinaryStream();
$data->write($this);
return $this->buffer->getBuffer();
}

/**
* @param TreeRoot[] $data
*/
Expand Down
12 changes: 12 additions & 0 deletions tests/phpunit/NbtSerializerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@

use PHPUnit\Framework\TestCase;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\ListTag;
use pocketmine\utils\Binary;

class NbtSerializerTest extends TestCase{

Expand Down Expand Up @@ -73,4 +75,14 @@ public function testCompoundTagIntKeysEncode() : void{
$data->setInt("1", 1);
(new BigEndianNbtSerializer())->write(new TreeRoot($data));
}

public function testHeadlessDecodeEncode() : void{
$tag = new IntTag(123);
$serializer = new BigEndianNbtSerializer();
$raw = $serializer->writeHeadless($tag);
self::assertSame($raw, Binary::writeInt(123));

$tag2 = $serializer->readHeadless($raw, NBT::TAG_Int);
self::assertEquals($tag, $tag2);
}
}

0 comments on commit 55c2c31

Please sign in to comment.