diff --git a/composer.json b/composer.json index e5f7b00d6..833ab5d8f 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,8 @@ "ext-zlib": ">=1.2.11", "pocketmine/raklib": "^0.10.0", "pocketmine/pocketmine-spl": "^0.2.0", - "pocketmine/pocketmine-binaryutils": "dev-master#4795001f4444725f97b3c14c1e295635ff0a98a4" + "pocketmine/pocketmine-binaryutils": "dev-master#4795001f4444725f97b3c14c1e295635ff0a98a4", + "pocketmine/pocketmine-nbt": "dev-master#f8934c0aed90d1f55452588f7ebef7c4519518a5" }, "autoload": { "psr-0": { @@ -42,6 +43,10 @@ { "type": "vcs", "url": "https://github.com/pmmp/PocketMine-BinaryUtils" + }, + { + "type": "vcs", + "url": "https://github.com/pmmp/PocketMine-NBT" } ] } diff --git a/composer.lock b/composer.lock index 938135ccd..c1933436a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "13a106ee8e33d29b4fc1d9edf2828b7d", + "content-hash": "f77760ebc72a115643865a02056f39cc", "packages": [ { "name": "pocketmine/pocketmine-binaryutils", @@ -20,6 +20,9 @@ "reference": "4795001f4444725f97b3c14c1e295635ff0a98a4", "shasum": "" }, + "require": { + "php": ">=7.2" + }, "type": "library", "autoload": { "psr-4": { @@ -36,6 +39,40 @@ }, "time": "2018-01-11T12:51:47+00:00" }, + { + "name": "pocketmine/pocketmine-nbt", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/pmmp/PocketMine-NBT.git", + "reference": "f8934c0aed90d1f55452588f7ebef7c4519518a5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pmmp/PocketMine-NBT/zipball/f8934c0aed90d1f55452588f7ebef7c4519518a5", + "reference": "f8934c0aed90d1f55452588f7ebef7c4519518a5", + "shasum": "" + }, + "require": { + "php": ">=7.2.0", + "pocketmine/pocketmine-binaryutils": "dev-master#8bb34e771fee69abcc5482d17d2fa0b4f0e15a5e" + }, + "type": "library", + "autoload": { + "psr-4": { + "pocketmine\\nbt\\": "src/" + } + }, + "license": [ + "LGPL-3.0" + ], + "description": "PHP library for working with Named Binary Tags", + "support": { + "source": "https://github.com/pmmp/PocketMine-NBT/tree/master", + "issues": "https://github.com/pmmp/PocketMine-NBT/issues" + }, + "time": "2018-01-11T13:51:50+00:00" + }, { "name": "pocketmine/pocketmine-spl", "version": "0.2.0", @@ -112,7 +149,8 @@ "stability-flags": { "php": 5, "ext-pthreads": 20, - "pocketmine/pocketmine-binaryutils": 20 + "pocketmine/pocketmine-binaryutils": 20, + "pocketmine/pocketmine-nbt": 20 }, "prefer-stable": false, "prefer-lowest": false, diff --git a/src/pocketmine/nbt/BigEndianNBTStream.php b/src/pocketmine/nbt/BigEndianNBTStream.php deleted file mode 100644 index d86d850d8..000000000 --- a/src/pocketmine/nbt/BigEndianNBTStream.php +++ /dev/null @@ -1,87 +0,0 @@ - - -class BigEndianNBTStream extends NBTStream{ - - public function getShort() : int{ - return Binary::readShort($this->get(2)); - } - - public function getSignedShort() : int{ - return Binary::readSignedShort($this->get(2)); - } - - public function putShort(int $v) : void{ - $this->buffer .= Binary::writeShort($v); - } - - public function getInt() : int{ - return Binary::readInt($this->get(4)); - } - - public function putInt(int $v) : void{ - $this->buffer .= Binary::writeInt($v); - } - - public function getLong() : int{ - return Binary::readLong($this->get(8)); - } - - public function putLong(int $v) : void{ - $this->buffer .= Binary::writeLong($v); - } - - public function getFloat() : float{ - return Binary::readFloat($this->get(4)); - } - - public function putFloat(float $v) : void{ - $this->buffer .= Binary::writeFloat($v); - } - - public function getDouble() : float{ - return Binary::readDouble($this->get(8)); - } - - public function putDouble(float $v) : void{ - $this->buffer .= Binary::writeDouble($v); - } - - public function getIntArray() : array{ - $len = $this->getInt(); - return array_values(unpack("N*", $this->get($len * 4))); - } - - public function putIntArray(array $array) : void{ - $this->putInt(count($array)); - $this->put(pack("N*", ...$array)); - } -} diff --git a/src/pocketmine/nbt/JsonNBTParser.php b/src/pocketmine/nbt/JsonNBTParser.php deleted file mode 100644 index 34bdff16c..000000000 --- a/src/pocketmine/nbt/JsonNBTParser.php +++ /dev/null @@ -1,260 +0,0 @@ -setValue($value); - $data[$key] = $tag; - } - - $key++; - } - - return $data; - } - - /** - * @param string $str - * @param int $offset - * - * @return NamedTag[] - */ - private static function parseCompound(string $str, int &$offset = 0) : array{ - $len = strlen($str); - - $data = []; - - for(; $offset < $len; ++$offset){ - if($str{$offset - 1} === "}"){ - break; - }elseif($str{$offset} === "}"){ - ++$offset; - break; - } - - $key = self::readKey($str, $offset); - $value = self::readValue($str, $offset, $type); - - $tag = NBT::createTag($type); - if($tag instanceof NamedTag){ - $tag->setName($key); - $tag->setValue($value); - $data[$key] = $tag; - } - } - - return $data; - } - - /** - * @param string $data - * @param int $offset - * @param int|null $type - * - * @return mixed - * @throws \Exception - */ - private static function readValue(string $data, int &$offset, &$type = null){ - $value = ""; - $type = null; - $inQuotes = false; - - $len = strlen($data); - for(; $offset < $len; ++$offset){ - $c = $data{$offset}; - - if(!$inQuotes and ($c === " " or $c === "\r" or $c === "\n" or $c === "\t" or $c === "," or $c === "}" or $c === "]")){ - if($c === "," or $c === "}" or $c === "]"){ - break; - } - }elseif($c === '"'){ - $inQuotes = !$inQuotes; - if($type === null){ - $type = NBT::TAG_String; - }elseif($inQuotes){ - throw new \Exception("Syntax error: invalid quote at offset $offset"); - } - }elseif($c === "\\"){ - $value .= $data{$offset + 1} ?? ""; - ++$offset; - }elseif($c === "{" and !$inQuotes){ - if($value !== ""){ - throw new \Exception("Syntax error: invalid compound start at offset $offset"); - } - ++$offset; - $value = self::parseCompound($data, $offset); - $type = NBT::TAG_Compound; - break; - }elseif($c === "[" and !$inQuotes){ - if($value !== ""){ - throw new \Exception("Syntax error: invalid list start at offset $offset"); - } - ++$offset; - $value = self::parseList($data, $offset); - $type = NBT::TAG_List; - break; - }else{ - $value .= $c; - } - } - - if($value === ""){ - throw new \Exception("Syntax error: invalid empty value at offset $offset"); - } - - if($type === null and strlen($value) > 0){ - $value = trim($value); - $last = strtolower(substr($value, -1)); - $part = substr($value, 0, -1); - - if($last !== "b" and $last !== "s" and $last !== "l" and $last !== "f" and $last !== "d"){ - $part = $value; - $last = null; - } - - if($last !== "f" and $last !== "d" and ((string) ((int) $part)) === $part){ - if($last === "b"){ - $type = NBT::TAG_Byte; - }elseif($last === "s"){ - $type = NBT::TAG_Short; - }elseif($last === "l"){ - $type = NBT::TAG_Long; - }else{ - $type = NBT::TAG_Int; - } - $value = (int) $part; - }elseif(is_numeric($part)){ - if($last === "f" or $last === "d" or strpos($part, ".") !== false){ - if($last === "f"){ - $type = NBT::TAG_Float; - }elseif($last === "d"){ - $type = NBT::TAG_Double; - }else{ - $type = NBT::TAG_Float; - } - $value = (float) $part; - }else{ - if($last === "l"){ - $type = NBT::TAG_Long; - }else{ - $type = NBT::TAG_Int; - } - - $value = $part; - } - }else{ - $type = NBT::TAG_String; - } - } - - return $value; - } - - /** - * @param string $data - * @param int $offset - * - * @return string - * @throws \Exception - */ - private static function readKey(string $data, int &$offset) : string{ - $key = ""; - - $len = strlen($data); - for(; $offset < $len; ++$offset){ - $c = $data{$offset}; - - if($c === ":"){ - ++$offset; - break; - }elseif($c !== " " and $c !== "\r" and $c !== "\n" and $c !== "\t" and $c !== "\""){ - $key .= $c; - } - } - - if($key === ""){ - throw new \Exception("Syntax error: invalid empty key at offset $offset"); - } - - return $key; - } -} diff --git a/src/pocketmine/nbt/LittleEndianNBTStream.php b/src/pocketmine/nbt/LittleEndianNBTStream.php deleted file mode 100644 index c51c85ce1..000000000 --- a/src/pocketmine/nbt/LittleEndianNBTStream.php +++ /dev/null @@ -1,87 +0,0 @@ - - -class LittleEndianNBTStream extends NBTStream{ - - public function getShort() : int{ - return Binary::readLShort($this->get(2)); - } - - public function getSignedShort() : int{ - return Binary::readSignedLShort($this->get(2)); - } - - public function putShort(int $v) : void{ - $this->put(Binary::writeLShort($v)); - } - - public function getInt() : int{ - return Binary::readLInt($this->get(4)); - } - - public function putInt(int $v) : void{ - $this->put(Binary::writeLInt($v)); - } - - public function getLong() : int{ - return Binary::readLLong($this->get(8)); - } - - public function putLong(int $v) : void{ - $this->put(Binary::writeLLong($v)); - } - - public function getFloat() : float{ - return Binary::readLFloat($this->get(4)); - } - - public function putFloat(float $v) : void{ - $this->put(Binary::writeLFloat($v)); - } - - public function getDouble() : float{ - return Binary::readLDouble($this->get(8)); - } - - public function putDouble(float $v) : void{ - $this->put(Binary::writeLDouble($v)); - } - - public function getIntArray() : array{ - $len = $this->getInt(); - return array_values(unpack("V*", $this->get($len * 4))); - } - - public function putIntArray(array $array) : void{ - $this->putInt(count($array)); - $this->put(pack("V*", ...$array)); - } -} diff --git a/src/pocketmine/nbt/NBT.php b/src/pocketmine/nbt/NBT.php deleted file mode 100644 index 3827884e6..000000000 --- a/src/pocketmine/nbt/NBT.php +++ /dev/null @@ -1,159 +0,0 @@ -getName() !== $tag2->getName() or $tag1->getCount() !== $tag2->getCount()){ - return false; - } - - foreach($tag1 as $k => $v){ - if(!($v instanceof Tag)){ - continue; - } - - if(!isset($tag2->{$k}) or !($tag2->{$k} instanceof $v)){ - return false; - } - - if($v instanceof CompoundTag){ - if(!self::matchTree($v, $tag2->{$k})){ - return false; - } - }elseif($v instanceof ListTag){ - if(!self::matchList($v, $tag2->{$k})){ - return false; - } - }else{ - if($v->getValue() !== $tag2->{$k}->getValue()){ - return false; - } - } - } - - return true; - } - - public static function matchTree(CompoundTag $tag1, CompoundTag $tag2) : bool{ - if($tag1->getName() !== $tag2->getName() or $tag1->getCount() !== $tag2->getCount()){ - return false; - } - - foreach($tag1 as $k => $v){ - if(!($v instanceof Tag)){ - continue; - } - - if(!isset($tag2->{$k}) or !($tag2->{$k} instanceof $v)){ - return false; - } - - if($v instanceof CompoundTag){ - if(!self::matchTree($v, $tag2->{$k})){ - return false; - } - }elseif($v instanceof ListTag){ - if(!self::matchList($v, $tag2->{$k})){ - return false; - } - }else{ - if($v->getValue() !== $tag2->{$k}->getValue()){ - return false; - } - } - } - - return true; - } -} diff --git a/src/pocketmine/nbt/NBTStream.php b/src/pocketmine/nbt/NBTStream.php deleted file mode 100644 index 8531fb34e..000000000 --- a/src/pocketmine/nbt/NBTStream.php +++ /dev/null @@ -1,271 +0,0 @@ - - -/** - * Base Named Binary Tag encoder/decoder - */ -abstract class NBTStream{ - - public $buffer; - public $offset; - private $data; - - public function get($len) : string{ - if($len < 0){ - $this->offset = strlen($this->buffer) - 1; - return ""; - }elseif($len === true){ - return substr($this->buffer, $this->offset); - } - - return $len === 1 ? $this->buffer{$this->offset++} : substr($this->buffer, ($this->offset += $len) - $len, $len); - } - - public function put(string $v) : void{ - $this->buffer .= $v; - } - - public function feof() : bool{ - return !isset($this->buffer{$this->offset}); - } - - public function __construct(){ - $this->offset = 0; - $this->buffer = ""; - } - - public function read(string $buffer, bool $doMultiple = false) : void{ - $this->offset = 0; - $this->buffer = $buffer; - $this->data = $this->readTag(); - if($doMultiple and $this->offset < strlen($this->buffer)){ - $this->data = [$this->data]; - do{ - $this->data[] = $this->readTag(); - }while($this->offset < strlen($this->buffer)); - } - $this->buffer = ""; - } - - public function readCompressed(string $buffer) : void{ - $this->read(zlib_decode($buffer)); - } - - /** - * @return bool|string - */ - public function write(){ - $this->offset = 0; - $this->buffer = ""; - - if($this->data instanceof CompoundTag){ - $this->writeTag($this->data); - - return $this->buffer; - }elseif(is_array($this->data)){ - foreach($this->data as $tag){ - $this->writeTag($tag); - } - return $this->buffer; - } - - return false; - } - - public function writeCompressed(int $compression = ZLIB_ENCODING_GZIP, int $level = 7){ - if(($write = $this->write()) !== false){ - return zlib_encode($write, $compression, $level); - } - - return false; - } - - public function readTag() : Tag{ - if($this->feof()){ - return new EndTag(); - } - - $tagType = $this->getByte(); - $tag = NBT::createTag($tagType); - - if($tag instanceof NamedTag){ - $tag->setName($this->getString()); - $tag->read($this); - } - - return $tag; - } - - public function writeTag(Tag $tag) : void{ - $this->putByte($tag->getType()); - if($tag instanceof NamedTag){ - $this->putString($tag->getName()); - } - $tag->write($this); - } - - public function getByte() : int{ - return Binary::readByte($this->get(1)); - } - - public function getSignedByte() : int{ - return Binary::readSignedByte($this->get(1)); - } - - public function putByte(int $v) : void{ - $this->buffer .= Binary::writeByte($v); - } - - abstract public function getShort() : int; - - abstract public function getSignedShort() : int; - - abstract public function putShort(int $v) : void; - - - abstract public function getInt() : int; - - abstract public function putInt(int $v) : void; - - abstract public function getLong() : int; - - abstract public function putLong(int $v) : void; - - - abstract public function getFloat() : float; - - abstract public function putFloat(float $v) : void; - - - abstract public function getDouble() : float; - - abstract public function putDouble(float $v) : void; - - public function getString() : string{ - return $this->get($this->getShort()); - } - - public function putString(string $v) : void{ - $this->putShort(strlen($v)); - $this->put($v); - } - - abstract public function getIntArray() : array; - - abstract public function putIntArray(array $array) : void; - - - - public function getArray() : array{ - $data = []; - self::toArray($data, $this->data); - return $data; - } - - private static function toArray(array &$data, Tag $tag) : void{ - /** @var CompoundTag[]|ListTag[]|IntArrayTag[] $tag */ - foreach($tag as $key => $value){ - if($value instanceof CompoundTag or $value instanceof ListTag or $value instanceof IntArrayTag){ - $data[$key] = []; - self::toArray($data[$key], $value); - }else{ - $data[$key] = $value->getValue(); - } - } - } - - public static function fromArrayGuesser(string $key, $value) : ?NamedTag{ - if(is_int($value)){ - return new IntTag($key, $value); - }elseif(is_float($value)){ - return new FloatTag($key, $value); - }elseif(is_string($value)){ - return new StringTag($key, $value); - }elseif(is_bool($value)){ - return new ByteTag($key, $value ? 1 : 0); - } - - return null; - } - - private static function fromArray(Tag $tag, array $data, callable $guesser) : void{ - foreach($data as $key => $value){ - if(is_array($value)){ - $isNumeric = true; - $isIntArray = true; - foreach($value as $k => $v){ - if(!is_numeric($k)){ - $isNumeric = false; - break; - }elseif(!is_int($v)){ - $isIntArray = false; - } - } - $tag{$key} = $isNumeric ? ($isIntArray ? new IntArrayTag($key, []) : new ListTag($key, [])) : new CompoundTag($key, []); - self::fromArray($tag->{$key}, $value, $guesser); - }else{ - $v = call_user_func($guesser, $key, $value); - if($v instanceof Tag){ - $tag{$key} = $v; - } - } - } - } - - public function setArray(array $data, callable $guesser = null) : void{ - $this->data = new CompoundTag("", []); - self::fromArray($this->data, $data, $guesser ?? [self::class, "fromArrayGuesser"]); - } - - /** - * @return CompoundTag|array - */ - public function getData(){ - return $this->data; - } - - /** - * @param CompoundTag|array $data - */ - public function setData($data) : void{ - $this->data = $data; - } -} diff --git a/src/pocketmine/nbt/NetworkLittleEndianNBTStream.php b/src/pocketmine/nbt/NetworkLittleEndianNBTStream.php deleted file mode 100644 index 4bb583783..000000000 --- a/src/pocketmine/nbt/NetworkLittleEndianNBTStream.php +++ /dev/null @@ -1,74 +0,0 @@ - - -class NetworkLittleEndianNBTStream extends LittleEndianNBTStream{ - - public function getInt() : int{ - return Binary::readVarInt($this->buffer, $this->offset); - } - - public function putInt(int $v) : void{ - $this->put(Binary::writeVarInt($v)); - } - - public function getLong() : int{ - return Binary::readVarLong($this->buffer, $this->offset); - } - - public function putLong(int $v) : void{ - $this->put(Binary::writeVarLong($v)); - } - - public function getString() : string{ - return $this->get(Binary::readUnsignedVarInt($this->buffer, $this->offset)); - } - - public function putString(string $v) : void{ - $this->put(Binary::writeUnsignedVarInt(strlen($v)) . $v); - } - - public function getIntArray() : array{ - $len = $this->getInt(); //varint - $ret = []; - for($i = 0; $i < $len; ++$i){ - $ret[] = $this->getInt(); //varint - } - - return $ret; - } - - public function putIntArray(array $array) : void{ - $this->putInt(count($array)); //varint - foreach($array as $v){ - $this->putInt($v); //varint - } - } -} diff --git a/src/pocketmine/nbt/tag/ByteArrayTag.php b/src/pocketmine/nbt/tag/ByteArrayTag.php deleted file mode 100644 index 0023958c7..000000000 --- a/src/pocketmine/nbt/tag/ByteArrayTag.php +++ /dev/null @@ -1,74 +0,0 @@ - - -class ByteArrayTag extends NamedTag{ - - /** - * ByteArrayTag constructor. - * - * @param string $name - * @param string $value - */ - public function __construct(string $name = "", string $value = ""){ - parent::__construct($name, $value); - } - - public function getType() : int{ - return NBT::TAG_ByteArray; - } - - public function read(NBTStream $nbt) : void{ - $this->value = $nbt->get($nbt->getInt()); - } - - public function write(NBTStream $nbt) : void{ - $nbt->putInt(strlen($this->value)); - $nbt->put($this->value); - } - - /** - * @return string - */ - public function &getValue() : string{ - return parent::getValue(); - } - - /** - * @param string $value - * - * @throws \TypeError - */ - public function setValue($value) : void{ - if(!is_string($value)){ - throw new \TypeError("ByteArrayTag value must be of type string, " . gettype($value) . " given"); - } - parent::setValue($value); - } -} diff --git a/src/pocketmine/nbt/tag/ByteTag.php b/src/pocketmine/nbt/tag/ByteTag.php deleted file mode 100644 index dd93a7864..000000000 --- a/src/pocketmine/nbt/tag/ByteTag.php +++ /dev/null @@ -1,75 +0,0 @@ - - -class ByteTag extends NamedTag{ - - /** - * ByteTag constructor. - * - * @param string $name - * @param int $value - */ - public function __construct(string $name = "", int $value = 0){ - parent::__construct($name, $value); - } - - public function getType() : int{ - return NBT::TAG_Byte; - } - - public function read(NBTStream $nbt) : void{ - $this->value = $nbt->getSignedByte(); - } - - public function write(NBTStream $nbt) : void{ - $nbt->putByte($this->value); - } - - /** - * @return int - */ - public function &getValue() : int{ - return parent::getValue(); - } - - /** - * @param int $value - * - * @throws \TypeError - */ - public function setValue($value) : void{ - if(!is_int($value)){ - throw new \TypeError("ByteTag value must be of type int, " . gettype($value) . " given"); - }elseif($value < -(2 ** 7) or $value > ((2 ** 7) - 1)){ - throw new \InvalidArgumentException("Value $value is too large!"); - } - parent::setValue($value); - } -} diff --git a/src/pocketmine/nbt/tag/CompoundTag.php b/src/pocketmine/nbt/tag/CompoundTag.php deleted file mode 100644 index e17f1f495..000000000 --- a/src/pocketmine/nbt/tag/CompoundTag.php +++ /dev/null @@ -1,467 +0,0 @@ - - -class CompoundTag extends NamedTag implements \ArrayAccess{ - - /** - * CompoundTag constructor. - * - * @param string $name - * @param NamedTag[] $value - */ - public function __construct(string $name = "", array $value = []){ - parent::__construct($name, $value); - } - - /** - * @return int - */ - public function getCount(){ - return count($this->getValue()); - } - - /** - * @return NamedTag[] - */ - public function &getValue(){ - $result = []; - foreach($this as $tag){ - if($tag instanceof NamedTag){ - $result[$tag->getName()] = $tag; - } - } - - return $result; - } - - /** - * @param NamedTag[] $value - * - * @throws \TypeError - */ - public function setValue($value) : void{ - if(is_array($value)){ - foreach($value as $name => $tag){ - if($tag instanceof NamedTag){ - $this->{$tag->__name} = $tag; - }else{ - throw new \TypeError("CompoundTag members must be NamedTags, got " . gettype($tag) . " in given array"); - } - } - }else{ - throw new \TypeError("CompoundTag value must be NamedTag[], " . gettype($value) . " given"); - } - } - - /* - * Here follows many functions of misery for the sake of type safety. We really needs generics in PHP :( - */ - - /** - * Returns the tag with the specified name, or null if it does not exist. - * - * @param string $name - * @param string|null $expectedClass Class that extends NamedTag - * - * @return NamedTag|null - * @throws \RuntimeException if the tag exists and is not of the expected type (if specified) - */ - public function getTag(string $name, string $expectedClass = NamedTag::class) : ?NamedTag{ - assert(is_a($expectedClass, NamedTag::class, true)); - $tag = $this->{$name} ?? null; - if($tag !== null and !($tag instanceof $expectedClass)){ - throw new \RuntimeException("Expected a tag of type $expectedClass, got " . get_class($tag)); - } - - return $tag; - } - - /** - * Returns the ListTag with the specified name, or null if it does not exist. Triggers an exception if a tag exists - * with that name and the tag is not a ListTag. - * - * @param string $name - * @return ListTag|null - */ - public function getListTag(string $name) : ?ListTag{ - return $this->getTag($name, ListTag::class); - } - - /** - * Returns the CompoundTag with the specified name, or null if it does not exist. Triggers an exception if a tag - * exists with that name and the tag is not a CompoundTag. - * - * @param string $name - * @return CompoundTag|null - */ - public function getCompoundTag(string $name) : ?CompoundTag{ - return $this->getTag($name, CompoundTag::class); - } - - /** - * Sets the specified NamedTag as a child tag of the CompoundTag at the offset specified by the tag's name. If a tag - * already exists at the offset, it will be overwritten with the new one. - * - * @param NamedTag $tag - */ - public function setTag(NamedTag $tag) : void{ - $this->{$tag->__name} = $tag; - } - - /** - * Removes the child tags with the specified names from the CompoundTag. This function accepts a variadic list of - * strings. - * - * @param string[] ...$names - */ - public function removeTag(string ...$names) : void{ - foreach($names as $name){ - unset($this->{$name}); - } - } - - /** - * Returns whether the CompoundTag contains a child tag with the specified name. - * - * @param string $name - * @param string $expectedClass - * - * @return bool - */ - public function hasTag(string $name, string $expectedClass = NamedTag::class) : bool{ - assert(is_a($expectedClass, NamedTag::class, true)); - return ($this->{$name} ?? null) instanceof $expectedClass; - } - - /** - * Returns the value of the child tag with the specified name, or $default if the tag doesn't exist. If the child - * tag is not of type $expectedType, an exception will be thrown, unless a default is given and $badTagDefault is - * true. - * - * @param string $name - * @param string $expectedClass - * @param mixed $default - * @param bool $badTagDefault Return the specified default if the tag is not of the expected type. - * - * @return mixed - */ - public function getTagValue(string $name, string $expectedClass, $default = null, bool $badTagDefault = false){ - $tag = $this->getTag($name, $badTagDefault ? NamedTag::class : $expectedClass); - if($tag instanceof $expectedClass){ - return $tag->getValue(); - } - - if($default === null){ - throw new \RuntimeException("Tag with name \"$name\" " . ($tag !== null ? "not of expected type" : "not found") . " and no valid default value given"); - } - - return $default; - } - - /* - * The following methods are wrappers around getTagValue() with type safety. - */ - - /** - * @param string $name - * @param int|null $default - * @param bool $badTagDefault - * - * @return int - */ - public function getByte(string $name, ?int $default = null, bool $badTagDefault = false) : int{ - return $this->getTagValue($name, ByteTag::class, $default, $badTagDefault); - } - - /** - * @param string $name - * @param int|null $default - * @param bool $badTagDefault - * - * @return int - */ - public function getShort(string $name, ?int $default = null, bool $badTagDefault = false) : int{ - return $this->getTagValue($name, ShortTag::class, $default, $badTagDefault); - } - - /** - * @param string $name - * @param int|null $default - * @param bool $badTagDefault - * - * @return int - */ - public function getInt(string $name, ?int $default = null, bool $badTagDefault = false) : int{ - return $this->getTagValue($name, IntTag::class, $default, $badTagDefault); - } - - /** - * @param string $name - * @param int|null $default - * @param bool $badTagDefault - * - * @return int - */ - public function getLong(string $name, ?int $default = null, bool $badTagDefault = false) : int{ - return $this->getTagValue($name, LongTag::class, $default, $badTagDefault); - } - - /** - * @param string $name - * @param float|null $default - * @param bool $badTagDefault - * - * @return float - */ - public function getFloat(string $name, ?float $default = null, bool $badTagDefault = false) : float{ - return $this->getTagValue($name, FloatTag::class, $default, $badTagDefault); - } - - /** - * @param string $name - * @param float|null $default - * @param bool $badTagDefault - * - * @return float - */ - public function getDouble(string $name, ?float $default = null, bool $badTagDefault = false) : float{ - return $this->getTagValue($name, DoubleTag::class, $default, $badTagDefault); - } - - /** - * @param string $name - * @param string|null $default - * @param bool $badTagDefault - * - * @return string - */ - public function getByteArray(string $name, ?string $default = null, bool $badTagDefault = false) : string{ - return $this->getTagValue($name, ByteArrayTag::class, $default, $badTagDefault); - } - - /** - * @param string $name - * @param string|null $default - * @param bool $badTagDefault - * - * @return string - */ - public function getString(string $name, ?string $default = null, bool $badTagDefault = false) : string{ - return $this->getTagValue($name, StringTag::class, $default, $badTagDefault); - } - - /** - * @param string $name - * @param int[]|null $default - * @param bool $badTagDefault - * - * @return int[] - */ - public function getIntArray(string $name, ?array $default = null, bool $badTagDefault = false) : array{ - return $this->getTagValue($name, IntArrayTag::class, $default, $badTagDefault); - } - - /** - * Sets the value of the child tag at the specified offset, creating it if it does not exist. If the child tag - * exists and the value is of the wrong type, an exception will be thrown. - * - * @param string $name Name of the tag to set - * @param string $tagClass Class that extends NamedTag - * @param mixed $value Value to set. This should be compatible with the specified tag type. - * @param bool $force Force set the value even if the existing tag is not the correct type (overwrite the old tag) - */ - public function setTagValue(string $name, string $tagClass, $value, bool $force) : void{ - assert(is_a($tagClass, NamedTag::class, true)); - $tag = $this->getTag($name, $force ? NamedTag::class : $tagClass); - if($tag instanceof $tagClass){ - $tag->setValue($value); - }else{ - $this->setTag(new $tagClass($name, $value)); - } - } - - /* - * The following methods are wrappers around setTagValue() with type safety. - */ - - /** - * @param string $name - * @param int $value - * @param bool $force - */ - public function setByte(string $name, int $value, bool $force = false) : void{ - $this->setTagValue($name, ByteTag::class, $value, $force); - } - - /** - * @param string $name - * @param int $value - * @param bool $force - */ - public function setShort(string $name, int $value, bool $force = false) : void{ - $this->setTagValue($name, ShortTag::class, $value, $force); - } - - /** - * @param string $name - * @param int $value - * @param bool $force - */ - public function setInt(string $name, int $value, bool $force = false) : void{ - $this->setTagValue($name, IntTag::class, $value, $force); - } - - /** - * @param string $name - * @param int $value - * @param bool $force - */ - public function setLong(string $name, int $value, bool $force = false) : void{ - $this->setTagValue($name, LongTag::class, $value, $force); - } - - /** - * @param string $name - * @param float $value - * @param bool $force - */ - public function setFloat(string $name, float $value, bool $force = false) : void{ - $this->setTagValue($name, FloatTag::class, $value, $force); - } - - /** - * @param string $name - * @param float $value - * @param bool $force - */ - public function setDouble(string $name, float $value, bool $force = false) : void{ - $this->setTagValue($name, DoubleTag::class, $value, $force); - } - - /** - * @param string $name - * @param string $value - * @param bool $force - */ - public function setByteArray(string $name, string $value, bool $force = false) : void{ - $this->setTagValue($name, ByteArrayTag::class, $value, $force); - } - - /** - * @param string $name - * @param string $value - * @param bool $force - */ - public function setString(string $name, string $value, bool $force = false) : void{ - $this->setTagValue($name, StringTag::class, $value, $force); - } - - /** - * @param string $name - * @param int[] $value - * @param bool $force - */ - public function setIntArray(string $name, array $value, bool $force = false) : void{ - $this->setTagValue($name, IntArrayTag::class, $value, $force); - } - - - - public function offsetExists($offset){ - return isset($this->{$offset}) and $this->{$offset} instanceof Tag; - } - - public function offsetGet($offset){ - if(isset($this->{$offset}) and $this->{$offset} instanceof Tag){ - if($this->{$offset} instanceof \ArrayAccess){ - return $this->{$offset}; - }else{ - return $this->{$offset}->getValue(); - } - } - - assert(false, "Offset $offset not found"); - - return null; - } - - public function offsetSet($offset, $value){ - if($value instanceof Tag){ - $this->{$offset} = $value; - }elseif(isset($this->{$offset}) and $this->{$offset} instanceof Tag){ - $this->{$offset}->setValue($value); - } - } - - public function offsetUnset($offset){ - unset($this->{$offset}); - } - - public function getType() : int{ - return NBT::TAG_Compound; - } - - public function read(NBTStream $nbt) : void{ - $this->value = []; - do{ - $tag = $nbt->readTag(); - if($tag instanceof NamedTag and $tag->__name !== ""){ - $this->{$tag->__name} = $tag; - } - }while(!($tag instanceof EndTag) and !$nbt->feof()); - } - - public function write(NBTStream $nbt) : void{ - foreach($this as $tag){ - if($tag instanceof Tag and !($tag instanceof EndTag)){ - $nbt->writeTag($tag); - } - } - $nbt->writeTag(new EndTag); - } - - public function __toString(){ - $str = get_class($this) . "{\n"; - foreach($this as $tag){ - if($tag instanceof Tag){ - $str .= get_class($tag) . ":" . $tag->__toString() . "\n"; - } - } - return $str . "}"; - } - - public function __clone(){ - foreach($this as $key => $tag){ - if($tag instanceof Tag){ - $this->{$key} = clone $tag; - } - } - } -} diff --git a/src/pocketmine/nbt/tag/DoubleTag.php b/src/pocketmine/nbt/tag/DoubleTag.php deleted file mode 100644 index 1ce8f91d5..000000000 --- a/src/pocketmine/nbt/tag/DoubleTag.php +++ /dev/null @@ -1,73 +0,0 @@ - - -class DoubleTag extends NamedTag{ - - /** - * DoubleTag constructor. - * - * @param string $name - * @param float $value - */ - public function __construct(string $name = "", float $value = 0.0){ - parent::__construct($name, $value); - } - - public function getType() : int{ - return NBT::TAG_Double; - } - - public function read(NBTStream $nbt) : void{ - $this->value = $nbt->getDouble(); - } - - public function write(NBTStream $nbt) : void{ - $nbt->putDouble($this->value); - } - - /** - * @return float - */ - public function &getValue() : float{ - return parent::getValue(); - } - - /** - * @param float $value - * - * @throws \TypeError - */ - public function setValue($value) : void{ - if(!is_float($value) and !is_int($value)){ - throw new \TypeError("DoubleTag value must be of type double, " . gettype($value) . " given"); - } - parent::setValue((float) $value); - } -} diff --git a/src/pocketmine/nbt/tag/EndTag.php b/src/pocketmine/nbt/tag/EndTag.php deleted file mode 100644 index 11d692131..000000000 --- a/src/pocketmine/nbt/tag/EndTag.php +++ /dev/null @@ -1,42 +0,0 @@ - - -class FloatTag extends NamedTag{ - - /** - * FloatTag constructor. - * - * @param string $name - * @param float $value - */ - public function __construct(string $name = "", float $value = 0.0){ - parent::__construct($name, $value); - } - - public function getType() : int{ - return NBT::TAG_Float; - } - - public function read(NBTStream $nbt) : void{ - $this->value = $nbt->getFloat(); - } - - public function write(NBTStream $nbt) : void{ - $nbt->putFloat($this->value); - } - - /** - * @return float - */ - public function &getValue() : float{ - return parent::getValue(); - } - - public function setValue($value) : void{ - if(!is_float($value) and !is_int($value)){ - throw new \TypeError("FloatTag value must be of type float, " . gettype($value) . " given"); - } - parent::setValue((float) $value); - } -} diff --git a/src/pocketmine/nbt/tag/IntArrayTag.php b/src/pocketmine/nbt/tag/IntArrayTag.php deleted file mode 100644 index 30c61d4f9..000000000 --- a/src/pocketmine/nbt/tag/IntArrayTag.php +++ /dev/null @@ -1,83 +0,0 @@ - - -class IntArrayTag extends NamedTag{ - - /** - * IntArrayTag constructor. - * - * @param string $name - * @param int[] $value - */ - public function __construct(string $name = "", array $value = []){ - parent::__construct($name, $value); - } - - public function getType() : int{ - return NBT::TAG_IntArray; - } - - public function read(NBTStream $nbt) : void{ - $this->value = $nbt->getIntArray(); - } - - public function write(NBTStream $nbt) : void{ - $nbt->putIntArray($this->value); - } - - public function __toString(){ - $str = get_class($this) . "{\n"; - $str .= implode(", ", $this->value); - return $str . "}"; - } - - /** - * @return int[] - */ - public function &getValue() : array{ - return parent::getValue(); - } - - /** - * @param int[] $value - * - * @throws \TypeError - */ - public function setValue($value) : void{ - if(!is_array($value)){ - throw new \TypeError("IntArrayTag value must be of type int[], " . gettype($value) . " given"); - } - assert(count(array_filter($value, function($v){ - return !is_int($v); - })) === 0); - - parent::setValue($value); - } -} diff --git a/src/pocketmine/nbt/tag/IntTag.php b/src/pocketmine/nbt/tag/IntTag.php deleted file mode 100644 index ed38d756a..000000000 --- a/src/pocketmine/nbt/tag/IntTag.php +++ /dev/null @@ -1,73 +0,0 @@ - - -class IntTag extends NamedTag{ - - /** - * @param string $name - * @param int $value - */ - public function __construct(string $name = "", int $value = 0){ - parent::__construct($name, $value); - } - - public function getType() : int{ - return NBT::TAG_Int; - } - - public function read(NBTStream $nbt) : void{ - $this->value = $nbt->getInt(); - } - - public function write(NBTStream $nbt) : void{ - $nbt->putInt($this->value); - } - - /** - * @return int - */ - public function &getValue() : int{ - return parent::getValue(); - } - - /** - * @param int $value - * - * @throws \TypeError - */ - public function setValue($value) : void{ - if(!is_int($value)){ - throw new \TypeError("IntTag value must be of type int, " . gettype($value) . " given"); - }elseif($value < -(2 ** 31) or $value > ((2 ** 31) - 1)){ - throw new \InvalidArgumentException("Value $value is too large!"); - } - parent::setValue($value); - } -} diff --git a/src/pocketmine/nbt/tag/ListTag.php b/src/pocketmine/nbt/tag/ListTag.php deleted file mode 100644 index b7f723c88..000000000 --- a/src/pocketmine/nbt/tag/ListTag.php +++ /dev/null @@ -1,227 +0,0 @@ - - -class ListTag extends NamedTag implements \ArrayAccess, \Countable{ - - /** @var int */ - private $tagType; - - /** - * ListTag constructor. - * - * @param string $name - * @param NamedTag[] $value - * @param int $tagType - */ - public function __construct(string $name = "", array $value = [], int $tagType = NBT::TAG_End){ - parent::__construct($name, $value); - $this->tagType = $tagType; - } - - /** - * @return NamedTag[] - */ - public function &getValue() : array{ - $value = []; - foreach($this as $k => $v){ - if($v instanceof Tag){ - $value[$k] = $v; - } - } - - return $value; - } - - /** - * @param NamedTag[] $value - * - * @throws \TypeError - */ - public function setValue($value) : void{ - if(is_array($value)){ - foreach($value as $name => $tag){ - if($tag instanceof NamedTag){ - $this->{$name} = $tag; - }else{ - throw new \TypeError("ListTag members must be NamedTags, got " . gettype($tag) . " in given array"); - } - } - }else{ - throw new \TypeError("ListTag value must be NamedTag[], " . gettype($value) . " given"); - } - } - - public function getCount(){ - $count = 0; - foreach($this as $tag){ - if($tag instanceof Tag){ - ++$count; - } - } - - return $count; - } - - public function getAllValues() : array{ - $result = []; - foreach($this as $tag){ - if(!($tag instanceof NamedTag)){ - continue; - } - - if($tag instanceof \ArrayAccess){ - $result[] = $tag; - }else{ - $result[] = $tag->getValue(); - } - } - - return $result; - } - - public function offsetExists($offset){ - return isset($this->{$offset}); - } - - /** - * @param int $offset - * - * @return CompoundTag|ListTag|mixed - */ - public function offsetGet($offset){ - if(isset($this->{$offset}) and $this->{$offset} instanceof Tag){ - if($this->{$offset} instanceof \ArrayAccess){ - return $this->{$offset}; - }else{ - return $this->{$offset}->getValue(); - } - } - - return null; - } - - public function offsetSet($offset, $value){ - if($value instanceof Tag){ - $this->{$offset} = $value; - }elseif($this->{$offset} instanceof Tag){ - $this->{$offset}->setValue($value); - } - } - - public function offsetUnset($offset){ - unset($this->{$offset}); - } - - public function count($mode = COUNT_NORMAL){ - $count = 0; - for($i = 0; isset($this->{$i}); $i++){ - if($mode === COUNT_RECURSIVE and $this->{$i} instanceof \Countable){ - $count += count($this->{$i}); - }else{ - $count++; - } - } - - return $count; - } - - public function getType() : int{ - return NBT::TAG_List; - } - - public function setTagType(int $type){ - $this->tagType = $type; - } - - public function getTagType() : int{ - return $this->tagType; - } - - public function read(NBTStream $nbt) : void{ - $this->value = []; - $this->tagType = $nbt->getByte(); - $size = $nbt->getInt(); - - $tagBase = NBT::createTag($this->tagType); - for($i = 0; $i < $size and !$nbt->feof(); ++$i){ - $tag = clone $tagBase; - $tag->read($nbt); - $this->{$i} = $tag; - } - } - - public function write(NBTStream $nbt) : void{ - if($this->tagType === NBT::TAG_End){ //previously empty list, try detecting type from tag children - $id = NBT::TAG_End; - foreach($this as $tag){ - if($tag instanceof Tag and !($tag instanceof EndTag)){ - if($id === NBT::TAG_End){ - $id = $tag->getType(); - }elseif($id !== $tag->getType()){ - return; //TODO: throw exception? - } - } - } - $this->tagType = $id; - } - - $nbt->putByte($this->tagType); - - /** @var Tag[] $tags */ - $tags = []; - foreach($this as $tag){ - if($tag instanceof Tag){ - $tags[] = $tag; - } - } - $nbt->putInt(count($tags)); - foreach($tags as $tag){ - $tag->write($nbt); - } - } - - public function __toString(){ - $str = get_class($this) . "{\n"; - foreach($this as $tag){ - if($tag instanceof Tag){ - $str .= get_class($tag) . ":" . $tag->__toString() . "\n"; - } - } - return $str . "}"; - } - - public function __clone(){ - foreach($this as $key => $tag){ - if($tag instanceof Tag){ - $this->{$key} = clone $tag; - } - } - } -} diff --git a/src/pocketmine/nbt/tag/LongTag.php b/src/pocketmine/nbt/tag/LongTag.php deleted file mode 100644 index e435afefc..000000000 --- a/src/pocketmine/nbt/tag/LongTag.php +++ /dev/null @@ -1,73 +0,0 @@ - - -class LongTag extends NamedTag{ - - /** - * LongTag constructor. - * - * @param string $name - * @param int $value - */ - public function __construct(string $name = "", int $value = 0){ - parent::__construct($name, $value); - } - - public function getType() : int{ - return NBT::TAG_Long; - } - - public function read(NBTStream $nbt) : void{ - $this->value = $nbt->getLong(); - } - - public function write(NBTStream $nbt) : void{ - $nbt->putLong($this->value); - } - - /** - * @return int - */ - public function &getValue() : int{ - return parent::getValue(); - } - - /** - * @param int $value - * - * @throws \TypeError - */ - public function setValue($value) : void{ - if(!is_int($value)){ - throw new \TypeError("LongTag value must be of type int, " . gettype($value) . " given"); - } - parent::setValue($value); - } -} diff --git a/src/pocketmine/nbt/tag/NamedTag.php b/src/pocketmine/nbt/tag/NamedTag.php deleted file mode 100644 index a3a22fb01..000000000 --- a/src/pocketmine/nbt/tag/NamedTag.php +++ /dev/null @@ -1,55 +0,0 @@ -__name = ($name === null or $name === false) ? "" : $name; - if($value !== null){ - $this->setValue($value); - } - } - - /** - * @return string - */ - public function getName() : string{ - return $this->__name; - } - - /** - * @param string $name - */ - public function setName(string $name) : void{ - $this->__name = $name; - } -} diff --git a/src/pocketmine/nbt/tag/ShortTag.php b/src/pocketmine/nbt/tag/ShortTag.php deleted file mode 100644 index 6eabeb222..000000000 --- a/src/pocketmine/nbt/tag/ShortTag.php +++ /dev/null @@ -1,75 +0,0 @@ - - -class ShortTag extends NamedTag{ - - /** - * ShortTag constructor. - * - * @param string $name - * @param int $value - */ - public function __construct(string $name = "", int $value = 0){ - parent::__construct($name, $value); - } - - public function getType() : int{ - return NBT::TAG_Short; - } - - public function read(NBTStream $nbt) : void{ - $this->value = $nbt->getSignedShort(); - } - - public function write(NBTStream $nbt) : void{ - $nbt->putShort($this->value); - } - - /** - * @return int - */ - public function &getValue() : int{ - return parent::getValue(); - } - - /** - * @param int $value - * - * @throws \TypeError - */ - public function setValue($value) : void{ - if(!is_int($value)){ - throw new \TypeError("ShortTag value must be of type int, " . gettype($value) . " given"); - }elseif($value < -(2 ** 15) or $value > ((2 ** 15) - 1)){ - throw new \InvalidArgumentException("Value $value is too large!"); - } - parent::setValue($value); - } -} diff --git a/src/pocketmine/nbt/tag/StringTag.php b/src/pocketmine/nbt/tag/StringTag.php deleted file mode 100644 index 53deb5d87..000000000 --- a/src/pocketmine/nbt/tag/StringTag.php +++ /dev/null @@ -1,73 +0,0 @@ - - -class StringTag extends NamedTag{ - - /** - * StringTag constructor. - * - * @param string $name - * @param string $value - */ - public function __construct(string $name = "", string $value = ""){ - parent::__construct($name, $value); - } - - public function getType() : int{ - return NBT::TAG_String; - } - - public function read(NBTStream $nbt) : void{ - $this->value = $nbt->getString(); - } - - public function write(NBTStream $nbt) : void{ - $nbt->putString($this->value); - } - - /** - * @return string - */ - public function &getValue() : string{ - return parent::getValue(); - } - - /** - * @param string $value - * - * @throws \TypeError - */ - public function setValue($value) : void{ - if(!is_string($value)){ - throw new \TypeError("StringTag value must be of type string, " . gettype($value) . " given"); - } - parent::setValue($value); - } -} diff --git a/src/pocketmine/nbt/tag/Tag.php b/src/pocketmine/nbt/tag/Tag.php deleted file mode 100644 index f4233378e..000000000 --- a/src/pocketmine/nbt/tag/Tag.php +++ /dev/null @@ -1,52 +0,0 @@ -value; - } - - abstract public function getType() : int; - - public function setValue($value) : void{ - $this->value = $value; - } - - abstract public function write(NBTStream $nbt) : void; - - abstract public function read(NBTStream $nbt) : void; - - public function __toString(){ - return (string) $this->value; - } -}