Skip to content

Commit 44f524d

Browse files
committed
automatically convert strings in Java Edition nbt to utf-8
1 parent 4639486 commit 44f524d

10 files changed

+109
-44
lines changed

src/Deserializer/BedrockEditionNbtDeserializer.php

+15
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Aternos\Nbt\MachineByteOrder;
66
use Aternos\Nbt\NbtFormat;
7+
use Aternos\Nbt\String\StringDataFormatException;
78
use pocketmine\utils\Binary;
89

910
class BedrockEditionNbtDeserializer extends NbtDeserializer
@@ -88,4 +89,18 @@ public function readDouble(): DeserializerFloatReadResult
8889
$raw = $this->getReader()->read(8);
8990
return new DeserializerFloatReadResult(Binary::readLDouble($raw), $raw);
9091
}
92+
93+
/**
94+
* @inheritDoc
95+
* @throws StringDataFormatException
96+
*/
97+
public function readString(): DeserializerStringReadResult
98+
{
99+
$length = $this->readStringLengthPrefix();
100+
$val = $this->getReader()->read($length->getValue());
101+
if(strlen($val) !== $length->getValue()){
102+
throw new StringDataFormatException("Failed to read string: expected length " . $length->getValue() . ", got " . strlen($val));
103+
}
104+
return new DeserializerStringReadResult($val, $length->getRawData() . $val);
105+
}
91106
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
namespace Aternos\Nbt\Deserializer;
4+
5+
class DeserializerStringReadResult extends DeserializerReadResult
6+
{
7+
public function __construct(protected string $value, string $rawData)
8+
{
9+
parent::__construct($rawData);
10+
}
11+
12+
/**
13+
* @return string
14+
*/
15+
public function getValue(): string
16+
{
17+
return $this->value;
18+
}
19+
20+
/**
21+
* @return int
22+
*/
23+
public function getRawLength(): int
24+
{
25+
return strlen($this->getRawData());
26+
}
27+
28+
/**
29+
* @return int
30+
*/
31+
public function getLength(): int
32+
{
33+
return strlen($this->value);
34+
}
35+
}

src/Deserializer/JavaEditionNbtDeserializer.php

+16
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
use Aternos\Nbt\MachineByteOrder;
66
use Aternos\Nbt\NbtFormat;
7+
use Aternos\Nbt\String\JavaEncoding;
8+
use Aternos\Nbt\String\StringDataFormatException;
79
use pocketmine\utils\Binary;
810

911
class JavaEditionNbtDeserializer extends NbtDeserializer
@@ -88,4 +90,18 @@ public function readDouble(): DeserializerFloatReadResult
8890
$raw = $this->getReader()->read(8);
8991
return new DeserializerFloatReadResult(Binary::readDouble($raw), $raw);
9092
}
93+
94+
/**
95+
* @inheritDoc
96+
* @throws StringDataFormatException
97+
*/
98+
public function readString(): DeserializerStringReadResult
99+
{
100+
$length = $this->readStringLengthPrefix();
101+
$val = $this->getReader()->read($length->getValue());
102+
if(strlen($val) !== $length->getValue()){
103+
throw new StringDataFormatException("Failed to read string: expected length " . $length->getValue() . ", got " . strlen($val));
104+
}
105+
return new DeserializerStringReadResult(JavaEncoding::getInstance()->decode($val), $length->getRawData() . $val);
106+
}
91107
}

src/Deserializer/NbtDeserializer.php

+5
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ abstract public function readFloat(): DeserializerFloatReadResult;
5454
*/
5555
abstract public function readDouble(): DeserializerFloatReadResult;
5656

57+
/**
58+
* @return DeserializerStringReadResult
59+
*/
60+
abstract public function readString(): DeserializerStringReadResult;
61+
5762
/**
5863
* @return int
5964
*/

src/Serializer/BedrockEditionNbtSerializer.php

+11-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,17 @@ public function writeFloat(float $value): static
8585
*/
8686
public function writeDouble(float $value): static
8787
{
88-
$this->writer->write(Binary::writeLDouble($value));
88+
$this->getWriter()->write(Binary::writeLDouble($value));
89+
return $this;
90+
}
91+
92+
/**
93+
* @inheritDoc
94+
*/
95+
public function writeString(string $value): static
96+
{
97+
$this->writeStringLengthPrefix(strlen($value));
98+
$this->getWriter()->write($value);
8999
return $this;
90100
}
91101
}

src/Serializer/JavaEditionNbtSerializer.php

+13-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Aternos\Nbt\MachineByteOrder;
66
use Aternos\Nbt\NbtFormat;
7+
use Aternos\Nbt\String\JavaEncoding;
78
use pocketmine\utils\Binary;
89

910
class JavaEditionNbtSerializer extends NbtSerializer
@@ -85,7 +86,18 @@ public function writeFloat(float $value): static
8586
*/
8687
public function writeDouble(float $value): static
8788
{
88-
$this->writer->write(Binary::writeDouble($value));
89+
$this->getWriter()->write(Binary::writeDouble($value));
90+
return $this;
91+
}
92+
93+
/**
94+
* @inheritDoc
95+
*/
96+
public function writeString(string $value): static
97+
{
98+
$encoded = JavaEncoding::getInstance()->encode($value);
99+
$this->writeStringLengthPrefix(strlen($encoded));
100+
$this->getWriter()->write($encoded);
89101
return $this;
90102
}
91103
}

src/Serializer/NbtSerializer.php

+6
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ abstract public function writeFloat(float $value): static;
6262
*/
6363
abstract public function writeDouble(float $value): static;
6464

65+
/**
66+
* @param string $value
67+
* @return $this
68+
*/
69+
abstract public function writeString(string $value): static;
70+
6571
/**
6672
* @return int
6773
*/

src/String/JavaEncoding.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public function encode(string $string, string $sourceEncoding = "UTF-8"): string
6060
}
6161

6262
$result .= chr(0xED);
63-
$result .= chr(0xA0 | (($c >> 0x10) & 0x0F));
63+
$result .= chr(0xA0 | ((($c >> 0x10) & 0x0F) - 1));
6464
$result .= chr(0x80 | (($c >> 0x0A) & 0x3f));
6565
$result .= chr(0xED);
6666
$result .= chr(0xb0 | (($c >> 0x06) & 0x0f));

src/Tag/StringTag.php

+2-27
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44

55
use Aternos\Nbt\IO\Reader\Reader;
66
use Aternos\Nbt\IO\Writer\Writer;
7-
use Aternos\Nbt\String\JavaEncoding;
8-
use Aternos\Nbt\String\StringDataFormatException;
97
use Exception;
108

119
class StringTag extends Tag
@@ -22,16 +20,6 @@ public function getValue(): string
2220
return $this->value;
2321
}
2422

25-
/**
26-
* @param string $encoding
27-
* @return string
28-
* @throws StringDataFormatException
29-
*/
30-
public function getDecodedValue(string $encoding = "UTF-8"): string
31-
{
32-
return JavaEncoding::getInstance()->decode($this->value, $encoding);
33-
}
34-
3523
/**
3624
* @param string $value
3725
* @return StringTag
@@ -42,17 +30,6 @@ public function setValue(string $value): StringTag
4230
return $this;
4331
}
4432

45-
/**
46-
* @param string $value
47-
* @param string $encoding
48-
* @return StringTag
49-
*/
50-
public function setDecodedValue(string $value, string $encoding = "UTF-8"): StringTag
51-
{
52-
$this->value = JavaEncoding::getInstance()->encode($value, $encoding);
53-
return $this;
54-
}
55-
5633
/**
5734
* @return int
5835
*/
@@ -71,8 +48,7 @@ public function writeContent(Writer $writer): static
7148
if ($length > 0xffff) {
7249
throw new Exception("String exceeds maximum length of " . 0xffff . " characters");
7350
}
74-
$writer->getSerializer()->writeStringLengthPrefix($length);
75-
$writer->write($this->value);
51+
$writer->getSerializer()->writeString($this->value);
7652
return $this;
7753
}
7854

@@ -81,8 +57,7 @@ public function writeContent(Writer $writer): static
8157
*/
8258
protected function readContent(Reader $reader): static
8359
{
84-
$length = $reader->getDeserializer()->readStringLengthPrefix()->getValue();
85-
$this->value = $reader->read($length);
60+
$this->value = $reader->getDeserializer()->readString()->getValue();
8661
return $this;
8762
}
8863

src/Tag/Tag.php

+5-14
Original file line numberDiff line numberDiff line change
@@ -159,12 +159,8 @@ public function getType(): int
159159
public function read(Reader $reader, bool $named = true): static
160160
{
161161
if ($named && static::canBeNamed()) {
162-
$nameLength = $reader->getDeserializer()->readStringLengthPrefix()->getValue();
163-
$name = $reader->read($nameLength);
164-
if (strlen($name) !== $nameLength) {
165-
throw new Exception("Failed to read name of " . static::class);
166-
}
167-
$this->setName($name);
162+
$name = $reader->getDeserializer()->readString();
163+
$this->setName($name->getValue());
168164
}
169165
return $this->readContent($reader);
170166
}
@@ -180,12 +176,8 @@ public static function readRaw(Reader $reader, TagOptions $options, bool $named
180176
{
181177
$result = "";
182178
if ($named && static::canBeNamed()) {
183-
$nameLength = $reader->getDeserializer()->readStringLengthPrefix();
184-
$name = $reader->read($nameLength->getValue());
185-
if (strlen($name) !== $nameLength->getValue()) {
186-
throw new Exception("Failed to read name of " . static::class);
187-
}
188-
$result .= $nameLength->getRawData() . $name;
179+
$name = $reader->getDeserializer()->readString();
180+
$result .= $name->getRawData();
189181
}
190182
$result .= static::readContentRaw($reader, $options);
191183
return $result;
@@ -210,8 +202,7 @@ public function writeData(Writer $writer, bool $named = true): static
210202
if (is_null($name)) {
211203
throw new Exception("Cannot write named tag, because tag does not have a name value");
212204
}
213-
$serializer->writeStringLengthPrefix(strlen($this->getName()));
214-
$writer->write($this->getName());
205+
$serializer->writeString($this->getName());
215206
}
216207
$this->writeContent($writer);
217208
$this->isBeingSerialized = false;

0 commit comments

Comments
 (0)