Skip to content

Commit 55c2c31

Browse files
committed
BaseNbtSerializer: added support for reading and writing headless tags
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.
1 parent 5c3307f commit 55c2c31

File tree

2 files changed

+43
-0
lines changed

2 files changed

+43
-0
lines changed

src/BaseNbtSerializer.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
namespace pocketmine\nbt;
2525

26+
use pocketmine\nbt\tag\Tag;
2627
use pocketmine\utils\Binary;
2728
use pocketmine\utils\BinaryDataException;
2829
use pocketmine\utils\BinaryStream;
@@ -73,6 +74,24 @@ public function read(string $buffer, int &$offset = 0, int $maxDepth = 0) : Tree
7374
return $data;
7475
}
7576

77+
/**
78+
* Reads a tag without a header from the buffer and returns it. The tag does not have a name, and the type is not
79+
* specified by the binary data. Only the tag's raw binary value is present.
80+
*
81+
* This could be used if the expected root type is always the same, but it's not usually seen in the wild.
82+
* However, this is used in some places in the Minecraft: Bedrock network protocol.
83+
*
84+
* @throws NbtDataException
85+
*/
86+
public function readHeadless(string $buffer, int $rootType, int &$offset = 0, int $maxDepth = 0) : Tag{
87+
$this->buffer = new BinaryStream($buffer, $offset);
88+
89+
$data = NBT::createTag($rootType, $this, new ReaderTracker($maxDepth));
90+
$offset = $this->buffer->getOffset();
91+
92+
return $data;
93+
}
94+
7695
/**
7796
* Decodes a list of NBT tags into objects and returns them.
7897
*
@@ -111,6 +130,18 @@ public function write(TreeRoot $data) : string{
111130
return $this->buffer->getBuffer();
112131
}
113132

133+
/**
134+
* Writes a nameless tag without any header information. The reader of the data must know what type to expect, as
135+
* it is not specified in the data.
136+
*
137+
* @see BaseNbtSerializer::readHeadless()
138+
*/
139+
public function writeHeadless(Tag $data) : string{
140+
$this->buffer = new BinaryStream();
141+
$data->write($this);
142+
return $this->buffer->getBuffer();
143+
}
144+
114145
/**
115146
* @param TreeRoot[] $data
116147
*/

tests/phpunit/NbtSerializerTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@
2525

2626
use PHPUnit\Framework\TestCase;
2727
use pocketmine\nbt\tag\CompoundTag;
28+
use pocketmine\nbt\tag\IntTag;
2829
use pocketmine\nbt\tag\ListTag;
30+
use pocketmine\utils\Binary;
2931

3032
class NbtSerializerTest extends TestCase{
3133

@@ -73,4 +75,14 @@ public function testCompoundTagIntKeysEncode() : void{
7375
$data->setInt("1", 1);
7476
(new BigEndianNbtSerializer())->write(new TreeRoot($data));
7577
}
78+
79+
public function testHeadlessDecodeEncode() : void{
80+
$tag = new IntTag(123);
81+
$serializer = new BigEndianNbtSerializer();
82+
$raw = $serializer->writeHeadless($tag);
83+
self::assertSame($raw, Binary::writeInt(123));
84+
85+
$tag2 = $serializer->readHeadless($raw, NBT::TAG_Int);
86+
self::assertEquals($tag, $tag2);
87+
}
7688
}

0 commit comments

Comments
 (0)