diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index 4031877b9..9658ff18d 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -2807,7 +2807,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade $t = $this->level->getTile($pos); if($t instanceof Sign){ $nbt = new NBT(NBT::LITTLE_ENDIAN); - $nbt->read($packet->namedtag); + $nbt->read($packet->namedtag, false, true); $nbt = $nbt->getData(); if($nbt["id"] !== Tile::SIGN){ $t->spawnTo($this); diff --git a/src/pocketmine/level/format/anvil/Anvil.php b/src/pocketmine/level/format/anvil/Anvil.php index 303f7cacf..b48a5ec2f 100644 --- a/src/pocketmine/level/format/anvil/Anvil.php +++ b/src/pocketmine/level/format/anvil/Anvil.php @@ -86,7 +86,7 @@ class Anvil extends McRegion{ } } $nbt->setData($list); - $tiles = $nbt->write(); + $tiles = $nbt->write(true); } $extraData = new BinaryStream(); diff --git a/src/pocketmine/level/format/anvil/ChunkRequestTask.php b/src/pocketmine/level/format/anvil/ChunkRequestTask.php index 8649f74f1..f86f36fbb 100644 --- a/src/pocketmine/level/format/anvil/ChunkRequestTask.php +++ b/src/pocketmine/level/format/anvil/ChunkRequestTask.php @@ -49,7 +49,7 @@ class ChunkRequestTask extends AsyncTask{ foreach($chunk->getTiles() as $tile){ if($tile instanceof Spawnable){ $nbt->setData($tile->getSpawnCompound()); - $tiles .= $nbt->write(); + $tiles .= $nbt->write(true); } } diff --git a/src/pocketmine/level/format/mcregion/McRegion.php b/src/pocketmine/level/format/mcregion/McRegion.php index c89c079ba..93d3a76cf 100644 --- a/src/pocketmine/level/format/mcregion/McRegion.php +++ b/src/pocketmine/level/format/mcregion/McRegion.php @@ -129,7 +129,7 @@ class McRegion extends BaseLevelProvider{ } } $nbt->setData($list); - $tiles = $nbt->write(); + $tiles = $nbt->write(true); } $extraData = new BinaryStream(); diff --git a/src/pocketmine/nbt/NBT.php b/src/pocketmine/nbt/NBT.php index 68e15d642..510a04767 100644 --- a/src/pocketmine/nbt/NBT.php +++ b/src/pocketmine/nbt/NBT.php @@ -463,14 +463,14 @@ class NBT{ $this->endianness = $endianness & 0x01; } - public function read($buffer, $doMultiple = false){ + public function read($buffer, $doMultiple = false, bool $network = false){ $this->offset = 0; $this->buffer = $buffer; - $this->data = $this->readTag(); + $this->data = $this->readTag($network); if($doMultiple and $this->offset < strlen($this->buffer)){ $this->data = [$this->data]; do{ - $this->data[] = $this->readTag(); + $this->data[] = $this->readTag($network); }while($this->offset < strlen($this->buffer)); } $this->buffer = ""; @@ -480,20 +480,25 @@ class NBT{ $this->read(zlib_decode($buffer)); } + public function readNetworkCompressed($buffer, $compression = ZLIB_ENCODING_GZIP){ + $this->read(zlib_decode($buffer), false, true); + } + + /** * @return string|bool */ - public function write(){ + public function write(bool $network = false){ $this->offset = 0; $this->buffer = ""; if($this->data instanceof CompoundTag){ - $this->writeTag($this->data); + $this->writeTag($this->data, $network); return $this->buffer; }elseif(is_array($this->data)){ foreach($this->data as $tag){ - $this->writeTag($tag); + $this->writeTag($tag, $network); } return $this->buffer; } @@ -509,51 +514,64 @@ class NBT{ return false; } - public function readTag(){ - switch($this->getByte()){ + public function writeNetworkCompressed($compression = ZLIB_ENCODING_GZIP, $level = 7){ + if(($write = $this->write(true)) !== false){ + return zlib_encode($write, $compression, $level); + } + + return false; + } + + public function readTag(bool $network = false){ + if($this->feof()){ + $tagType = -1; //prevent crashes for empty tags + }else{ + $tagType = $this->getByte(); + } + switch($tagType){ case NBT::TAG_Byte: - $tag = new ByteTag($this->getString()); - $tag->read($this); + $tag = new ByteTag($this->getString($network)); + $tag->read($this, $network); break; case NBT::TAG_Short: - $tag = new ShortTag($this->getString()); - $tag->read($this); + $tag = new ShortTag($this->getString($network)); + $tag->read($this, $network); break; case NBT::TAG_Int: - $tag = new IntTag($this->getString()); - $tag->read($this); + $tag = new IntTag($this->getString($network)); + $tag->read($this, $network); break; case NBT::TAG_Long: - $tag = new LongTag($this->getString()); - $tag->read($this); + $tag = new LongTag($this->getString($network)); + $tag->read($this, $network); break; case NBT::TAG_Float: - $tag = new FloatTag($this->getString()); - $tag->read($this); + $tag = new FloatTag($this->getString($network)); + $tag->read($this, $network); break; case NBT::TAG_Double: - $tag = new DoubleTag($this->getString()); - $tag->read($this); + $tag = new DoubleTag($this->getString($network)); + $tag->read($this, $network); break; case NBT::TAG_ByteArray: - $tag = new ByteArrayTag($this->getString()); - $tag->read($this); + $tag = new ByteArrayTag($this->getString($network)); + $tag->read($this, $network); break; case NBT::TAG_String: - $tag = new StringTag($this->getString()); - $tag->read($this); + $tag = new StringTag($this->getString($network)); + $tag->read($this, $network); break; case NBT::TAG_List: - $tag = new ListTag($this->getString()); - $tag->read($this); + $tag = new ListTag($this->getString($network)); + $tag->read($this, $network); break; case NBT::TAG_Compound: - $tag = new CompoundTag($this->getString()); - $tag->read($this); + $tag = new CompoundTag($this->getString($network)); + $tag->read($this, $network); break; case NBT::TAG_IntArray: - $tag = new IntArrayTag($this->getString()); - $tag->read($this); + $tag = new IntArrayTag($this->getString($network)); + $tag->read($this, $network); break; case NBT::TAG_End: //No named tag @@ -564,12 +582,12 @@ class NBT{ return $tag; } - public function writeTag(Tag $tag){ + public function writeTag(Tag $tag, bool $network = false){ $this->putByte($tag->getType()); if($tag instanceof NamedTAG){ - $this->putString($tag->getName()); + $this->putString($tag->getName(), $network); } - $tag->write($this); + $tag->write($this, $network); } public function getByte(){ @@ -588,12 +606,19 @@ class NBT{ $this->buffer .= $this->endianness === self::BIG_ENDIAN ? Binary::writeShort($v) : Binary::writeLShort($v); } - public function getInt(){ + public function getInt(bool $network = false){ + if($network === true){ + return Binary::readVarInt($this); + } return $this->endianness === self::BIG_ENDIAN ? Binary::readInt($this->get(4)) : Binary::readLInt($this->get(4)); } - public function putInt($v){ - $this->buffer .= $this->endianness === self::BIG_ENDIAN ? Binary::writeInt($v) : Binary::writeLInt($v); + public function putInt($v, bool $network = false){ + if($network === true){ + $this->buffer .= Binary::writeVarInt($v); + }else{ + $this->buffer .= $this->endianness === self::BIG_ENDIAN ? Binary::writeInt($v) : Binary::writeLInt($v); + } } public function getLong(){ @@ -620,12 +645,17 @@ class NBT{ $this->buffer .= $this->endianness === self::BIG_ENDIAN ? Binary::writeDouble($v) : Binary::writeLDouble($v); } - public function getString(){ - return $this->get($this->getShort()); + public function getString(bool $network = false){ + $len = $network ? $this->getByte() : $this->getShort(); + return $this->get($len); } - public function putString($v){ - $this->putShort(strlen($v)); + public function putString($v, bool $network = false){ + if($network === true){ + $this->putByte(strlen($v)); + }else{ + $this->putShort(strlen($v)); + } $this->buffer .= $v; } diff --git a/src/pocketmine/nbt/tag/ByteArrayTag.php b/src/pocketmine/nbt/tag/ByteArrayTag.php index 9bfdf7559..7a8200396 100644 --- a/src/pocketmine/nbt/tag/ByteArrayTag.php +++ b/src/pocketmine/nbt/tag/ByteArrayTag.php @@ -31,12 +31,12 @@ class ByteArrayTag extends NamedTag{ return NBT::TAG_ByteArray; } - public function read(NBT $nbt){ - $this->value = $nbt->get($nbt->getInt()); + public function read(NBT $nbt, bool $network = false){ + $this->value = $nbt->get($nbt->getInt($network)); } - public function write(NBT $nbt){ - $nbt->putInt(strlen($this->value)); + public function write(NBT $nbt, bool $network = false){ + $nbt->putInt(strlen($this->value), $network); $nbt->put($this->value); } } \ No newline at end of file diff --git a/src/pocketmine/nbt/tag/ByteTag.php b/src/pocketmine/nbt/tag/ByteTag.php index 46caa2798..80aeb55fd 100644 --- a/src/pocketmine/nbt/tag/ByteTag.php +++ b/src/pocketmine/nbt/tag/ByteTag.php @@ -31,11 +31,11 @@ class ByteTag extends NamedTag{ return NBT::TAG_Byte; } - public function read(NBT $nbt){ + public function read(NBT $nbt, bool $network = false){ $this->value = $nbt->getByte(); } - public function write(NBT $nbt){ + public function write(NBT $nbt, bool $network = false){ $nbt->putByte($this->value); } } \ No newline at end of file diff --git a/src/pocketmine/nbt/tag/CompoundTag.php b/src/pocketmine/nbt/tag/CompoundTag.php index ebef4fadd..0fceae172 100644 --- a/src/pocketmine/nbt/tag/CompoundTag.php +++ b/src/pocketmine/nbt/tag/CompoundTag.php @@ -83,23 +83,23 @@ class CompoundTag extends NamedTag implements \ArrayAccess{ return NBT::TAG_Compound; } - public function read(NBT $nbt){ + public function read(NBT $nbt, bool $network = false){ $this->value = []; do{ - $tag = $nbt->readTag(); + $tag = $nbt->readTag($network); if($tag instanceof NamedTag and $tag->getName() !== ""){ $this->{$tag->getName()} = $tag; } }while(!($tag instanceof EndTag) and !$nbt->feof()); } - public function write(NBT $nbt){ + public function write(NBT $nbt, bool $network = false){ foreach($this as $tag){ if($tag instanceof Tag and !($tag instanceof EndTag)){ - $nbt->writeTag($tag); + $nbt->writeTag($tag, $network); } } - $nbt->writeTag(new EndTag); + $nbt->writeTag(new EndTag, $network); } public function __toString(){ diff --git a/src/pocketmine/nbt/tag/DoubleTag.php b/src/pocketmine/nbt/tag/DoubleTag.php index f25379248..c64b647a0 100644 --- a/src/pocketmine/nbt/tag/DoubleTag.php +++ b/src/pocketmine/nbt/tag/DoubleTag.php @@ -31,11 +31,11 @@ class DoubleTag extends NamedTag{ return NBT::TAG_Double; } - public function read(NBT $nbt){ + public function read(NBT $nbt, bool $network = false){ $this->value = $nbt->getDouble(); } - public function write(NBT $nbt){ + public function write(NBT $nbt, bool $network = false){ $nbt->putDouble($this->value); } } \ No newline at end of file diff --git a/src/pocketmine/nbt/tag/EndTag.php b/src/pocketmine/nbt/tag/EndTag.php index 0a9af721b..30c8a1641 100644 --- a/src/pocketmine/nbt/tag/EndTag.php +++ b/src/pocketmine/nbt/tag/EndTag.php @@ -29,11 +29,11 @@ class EndTag extends Tag{ return NBT::TAG_End; } - public function read(NBT $nbt){ + public function read(NBT $nbt, bool $network = false){ } - public function write(NBT $nbt){ + public function write(NBT $nbt, bool $network = false){ } } \ No newline at end of file diff --git a/src/pocketmine/nbt/tag/FloatTag.php b/src/pocketmine/nbt/tag/FloatTag.php index 3e80ff6c5..65d595c8a 100644 --- a/src/pocketmine/nbt/tag/FloatTag.php +++ b/src/pocketmine/nbt/tag/FloatTag.php @@ -31,11 +31,11 @@ class FloatTag extends NamedTag{ return NBT::TAG_Float; } - public function read(NBT $nbt){ + public function read(NBT $nbt, bool $network = false){ $this->value = $nbt->getFloat(); } - public function write(NBT $nbt){ + public function write(NBT $nbt, bool $network = false){ $nbt->putFloat($this->value); } } \ No newline at end of file diff --git a/src/pocketmine/nbt/tag/IntArrayTag.php b/src/pocketmine/nbt/tag/IntArrayTag.php index a9f2bf5ae..2c6df4446 100644 --- a/src/pocketmine/nbt/tag/IntArrayTag.php +++ b/src/pocketmine/nbt/tag/IntArrayTag.php @@ -31,13 +31,13 @@ class IntArrayTag extends NamedTag{ return NBT::TAG_IntArray; } - public function read(NBT $nbt){ - $size = $nbt->getInt(); + public function read(NBT $nbt, bool $network = false){ + $size = $nbt->getInt($network); $this->value = array_values(unpack($nbt->endianness === NBT::LITTLE_ENDIAN ? "V*" : "N*", $nbt->get($size * 4))); } - public function write(NBT $nbt){ - $nbt->putInt(count($this->value)); + public function write(NBT $nbt, bool $network = false){ + $nbt->putInt(count($this->value), $network); $nbt->put(pack($nbt->endianness === NBT::LITTLE_ENDIAN ? "V*" : "N*", ...$this->value)); } diff --git a/src/pocketmine/nbt/tag/IntTag.php b/src/pocketmine/nbt/tag/IntTag.php index db5643bec..48974ba76 100644 --- a/src/pocketmine/nbt/tag/IntTag.php +++ b/src/pocketmine/nbt/tag/IntTag.php @@ -31,11 +31,11 @@ class IntTag extends NamedTag{ return NBT::TAG_Int; } - public function read(NBT $nbt){ - $this->value = $nbt->getInt(); + public function read(NBT $nbt, bool $network = false){ + $this->value = $nbt->getInt($network); } - public function write(NBT $nbt){ - $nbt->putInt($this->value); + public function write(NBT $nbt, bool $network = false){ + $nbt->putInt($this->value, $network); } } \ No newline at end of file diff --git a/src/pocketmine/nbt/tag/ListTag.php b/src/pocketmine/nbt/tag/ListTag.php index d60b44209..02aaedf57 100644 --- a/src/pocketmine/nbt/tag/ListTag.php +++ b/src/pocketmine/nbt/tag/ListTag.php @@ -114,72 +114,72 @@ class ListTag extends NamedTag implements \ArrayAccess, \Countable{ return $this->tagType; } - public function read(NBT $nbt){ + public function read(NBT $nbt, bool $network = false){ $this->value = []; $this->tagType = $nbt->getByte(); - $size = $nbt->getInt(); + $size = $nbt->getInt($network); for($i = 0; $i < $size and !$nbt->feof(); ++$i){ switch($this->tagType){ case NBT::TAG_Byte: $tag = new ByteTag(""); - $tag->read($nbt); + $tag->read($nbt, $network); $this->{$i} = $tag; break; case NBT::TAG_Short: $tag = new ShortTag(""); - $tag->read($nbt); + $tag->read($nbt, $network); $this->{$i} = $tag; break; case NBT::TAG_Int: $tag = new IntTag(""); - $tag->read($nbt); + $tag->read($nbt, $network); $this->{$i} = $tag; break; case NBT::TAG_Long: $tag = new LongTag(""); - $tag->read($nbt); + $tag->read($nbt, $network); $this->{$i} = $tag; break; case NBT::TAG_Float: $tag = new FloatTag(""); - $tag->read($nbt); + $tag->read($nbt, $network); $this->{$i} = $tag; break; case NBT::TAG_Double: $tag = new DoubleTag(""); - $tag->read($nbt); + $tag->read($nbt, $network); $this->{$i} = $tag; break; case NBT::TAG_ByteArray: $tag = new ByteArrayTag(""); - $tag->read($nbt); + $tag->read($nbt, $network); $this->{$i} = $tag; break; case NBT::TAG_String: $tag = new StringTag(""); - $tag->read($nbt); + $tag->read($nbt, $network); $this->{$i} = $tag; break; case NBT::TAG_List: $tag = new TagEnum(""); - $tag->read($nbt); + $tag->read($nbt, $network); $this->{$i} = $tag; break; case NBT::TAG_Compound: $tag = new CompoundTag(""); - $tag->read($nbt); + $tag->read($nbt, $network); $this->{$i} = $tag; break; case NBT::TAG_IntArray: $tag = new IntArrayTag(""); - $tag->read($nbt); + $tag->read($nbt, $network); $this->{$i} = $tag; break; } } } - public function write(NBT $nbt){ + public function write(NBT $nbt, bool $network = false){ if(!isset($this->tagType)){ $id = null; foreach($this as $tag){ @@ -205,7 +205,7 @@ class ListTag extends NamedTag implements \ArrayAccess, \Countable{ } $nbt->putInt(count($tags)); foreach($tags as $tag){ - $tag->write($nbt); + $tag->write($nbt, $network); } } diff --git a/src/pocketmine/nbt/tag/LongTag.php b/src/pocketmine/nbt/tag/LongTag.php index ca822905b..7abc82a6d 100644 --- a/src/pocketmine/nbt/tag/LongTag.php +++ b/src/pocketmine/nbt/tag/LongTag.php @@ -31,11 +31,13 @@ class LongTag extends NamedTag{ return NBT::TAG_Long; } - public function read(NBT $nbt){ + //TODO: check if this also changed to varint + + public function read(NBT $nbt, bool $network = false){ $this->value = $nbt->getLong(); } - public function write(NBT $nbt){ + public function write(NBT $nbt, bool $network = false){ $nbt->putLong($this->value); } } \ No newline at end of file diff --git a/src/pocketmine/nbt/tag/ShortTag.php b/src/pocketmine/nbt/tag/ShortTag.php index b35cdbbad..a7b53f913 100644 --- a/src/pocketmine/nbt/tag/ShortTag.php +++ b/src/pocketmine/nbt/tag/ShortTag.php @@ -31,11 +31,11 @@ class ShortTag extends NamedTag{ return NBT::TAG_Short; } - public function read(NBT $nbt){ + public function read(NBT $nbt, bool $network = false){ $this->value = $nbt->getShort(); } - public function write(NBT $nbt){ + public function write(NBT $nbt, bool $network = false){ $nbt->putShort($this->value); } } \ No newline at end of file diff --git a/src/pocketmine/nbt/tag/StringTag.php b/src/pocketmine/nbt/tag/StringTag.php index 11350649c..f53473f8f 100644 --- a/src/pocketmine/nbt/tag/StringTag.php +++ b/src/pocketmine/nbt/tag/StringTag.php @@ -31,12 +31,11 @@ class StringTag extends NamedTag{ return NBT::TAG_String; } - public function read(NBT $nbt){ - $this->value = $nbt->get($nbt->getShort()); + public function read(NBT $nbt, bool $network = false){ + $this->value = $nbt->getString($network); } - public function write(NBT $nbt){ - $nbt->putShort(strlen($this->value)); - $nbt->put($this->value); + public function write(NBT $nbt, bool $network = false){ + $nbt->putString($this->value, $network); } } \ No newline at end of file diff --git a/src/pocketmine/nbt/tag/Tag.php b/src/pocketmine/nbt/tag/Tag.php index e085f55d3..be2b0b31b 100644 --- a/src/pocketmine/nbt/tag/Tag.php +++ b/src/pocketmine/nbt/tag/Tag.php @@ -40,9 +40,9 @@ abstract class Tag extends \stdClass{ $this->value = $value; } - abstract public function write(NBT $nbt); + abstract public function write(NBT $nbt, bool $network = false); - abstract public function read(NBT $nbt); + abstract public function read(NBT $nbt, bool $network = false); public function __toString(){ return (string) $this->value; diff --git a/src/pocketmine/tile/Spawnable.php b/src/pocketmine/tile/Spawnable.php index 6cf3346a6..f9fb98956 100644 --- a/src/pocketmine/tile/Spawnable.php +++ b/src/pocketmine/tile/Spawnable.php @@ -40,7 +40,7 @@ abstract class Spawnable extends Tile{ $pk->x = $this->x; $pk->y = $this->y; $pk->z = $this->z; - $pk->namedtag = $nbt->write(); + $pk->namedtag = $nbt->write(true); $player->dataPacket($pk); return true; diff --git a/src/pocketmine/utils/BinaryStream.php b/src/pocketmine/utils/BinaryStream.php index cf0c2231d..3896a4a4c 100644 --- a/src/pocketmine/utils/BinaryStream.php +++ b/src/pocketmine/utils/BinaryStream.php @@ -58,7 +58,9 @@ class BinaryStream extends \stdClass{ $this->offset = strlen($this->buffer) - 1; return ""; }elseif($len === true){ - return substr($this->buffer, $this->offset); + $str = substr($this->buffer, $this->offset); + $this->offset = strlen($this->buffer); + return $str; } return $len === 1 ? $this->buffer{$this->offset++} : substr($this->buffer, ($this->offset += $len) - $len, $len);