mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-06-03 18:42:37 +00:00
Moved NBT to Composer library
This commit is contained in:
parent
579c508761
commit
c4966404bb
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
42
composer.lock
generated
42
composer.lock
generated
@ -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,
|
||||
|
@ -1,87 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\nbt;
|
||||
|
||||
#ifndef COMPILE
|
||||
use pocketmine\utils\Binary;
|
||||
#endif
|
||||
|
||||
#include <rules/NBT.h>
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
@ -1,260 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\nbt;
|
||||
|
||||
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\NamedTag;
|
||||
|
||||
class JsonNBTParser{
|
||||
|
||||
/**
|
||||
* Parses JSON-formatted NBT into a CompoundTag and returns it. Used for parsing tags supplied with the /give command.
|
||||
*
|
||||
* @param string $data
|
||||
* @param int &$offset
|
||||
*
|
||||
* @return CompoundTag|null
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function parseJSON(string $data, int &$offset = 0){
|
||||
$len = strlen($data);
|
||||
for(; $offset < $len; ++$offset){
|
||||
$c = $data{$offset};
|
||||
if($c === "{"){
|
||||
++$offset;
|
||||
$data = self::parseCompound($data, $offset);
|
||||
|
||||
return new CompoundTag("", $data);
|
||||
}elseif($c !== " " and $c !== "\r" and $c !== "\n" and $c !== "\t"){
|
||||
throw new \Exception("Syntax error: unexpected '$c' at offset $offset");
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**#
|
||||
* @param string $str
|
||||
* @param int &$offset
|
||||
*
|
||||
* @return NamedTag[]
|
||||
*/
|
||||
private static function parseList(string $str, int &$offset = 0) : array{
|
||||
$len = strlen($str);
|
||||
|
||||
$key = 0;
|
||||
$value = null;
|
||||
|
||||
$data = [];
|
||||
|
||||
for(; $offset < $len; ++$offset){
|
||||
if($str{$offset - 1} === "]"){
|
||||
break;
|
||||
}elseif($str{$offset} === "]"){
|
||||
++$offset;
|
||||
break;
|
||||
}
|
||||
|
||||
$value = self::readValue($str, $offset, $type);
|
||||
|
||||
$tag = NBT::createTag($type);
|
||||
if($tag instanceof NamedTag){
|
||||
$tag->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;
|
||||
}
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\nbt;
|
||||
|
||||
#ifndef COMPILE
|
||||
use pocketmine\utils\Binary;
|
||||
#endif
|
||||
|
||||
#include <rules/NBT.h>
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
@ -1,159 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Named Binary Tag handling classes
|
||||
*/
|
||||
namespace pocketmine\nbt;
|
||||
|
||||
use pocketmine\nbt\tag\ByteArrayTag;
|
||||
use pocketmine\nbt\tag\ByteTag;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\DoubleTag;
|
||||
use pocketmine\nbt\tag\EndTag;
|
||||
use pocketmine\nbt\tag\FloatTag;
|
||||
use pocketmine\nbt\tag\IntArrayTag;
|
||||
use pocketmine\nbt\tag\IntTag;
|
||||
use pocketmine\nbt\tag\ListTag;
|
||||
use pocketmine\nbt\tag\LongTag;
|
||||
use pocketmine\nbt\tag\ShortTag;
|
||||
use pocketmine\nbt\tag\StringTag;
|
||||
use pocketmine\nbt\tag\Tag;
|
||||
|
||||
abstract class NBT{
|
||||
|
||||
public const LITTLE_ENDIAN = 0;
|
||||
public const BIG_ENDIAN = 1;
|
||||
public const TAG_End = 0;
|
||||
public const TAG_Byte = 1;
|
||||
public const TAG_Short = 2;
|
||||
public const TAG_Int = 3;
|
||||
public const TAG_Long = 4;
|
||||
public const TAG_Float = 5;
|
||||
public const TAG_Double = 6;
|
||||
public const TAG_ByteArray = 7;
|
||||
public const TAG_String = 8;
|
||||
public const TAG_List = 9;
|
||||
public const TAG_Compound = 10;
|
||||
public const TAG_IntArray = 11;
|
||||
|
||||
/**
|
||||
* @param int $type
|
||||
*
|
||||
* @return Tag
|
||||
*/
|
||||
public static function createTag(int $type) : Tag{
|
||||
switch($type){
|
||||
case self::TAG_End:
|
||||
return new EndTag();
|
||||
case self::TAG_Byte:
|
||||
return new ByteTag();
|
||||
case self::TAG_Short:
|
||||
return new ShortTag();
|
||||
case self::TAG_Int:
|
||||
return new IntTag();
|
||||
case self::TAG_Long:
|
||||
return new LongTag();
|
||||
case self::TAG_Float:
|
||||
return new FloatTag();
|
||||
case self::TAG_Double:
|
||||
return new DoubleTag();
|
||||
case self::TAG_ByteArray:
|
||||
return new ByteArrayTag();
|
||||
case self::TAG_String:
|
||||
return new StringTag();
|
||||
case self::TAG_List:
|
||||
return new ListTag();
|
||||
case self::TAG_Compound:
|
||||
return new CompoundTag();
|
||||
case self::TAG_IntArray:
|
||||
return new IntArrayTag();
|
||||
default:
|
||||
throw new \InvalidArgumentException("Unknown NBT tag type $type");
|
||||
}
|
||||
}
|
||||
|
||||
public static function matchList(ListTag $tag1, ListTag $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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
@ -1,271 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\nbt;
|
||||
|
||||
use pocketmine\nbt\tag\ByteTag;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\EndTag;
|
||||
use pocketmine\nbt\tag\FloatTag;
|
||||
use pocketmine\nbt\tag\IntArrayTag;
|
||||
use pocketmine\nbt\tag\IntTag;
|
||||
use pocketmine\nbt\tag\ListTag;
|
||||
use pocketmine\nbt\tag\NamedTag;
|
||||
use pocketmine\nbt\tag\StringTag;
|
||||
use pocketmine\nbt\tag\Tag;
|
||||
#ifndef COMPILE
|
||||
use pocketmine\utils\Binary;
|
||||
#endif
|
||||
|
||||
#include <rules/NBT.h>
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\nbt;
|
||||
|
||||
#ifndef COMPILE
|
||||
use pocketmine\utils\Binary;
|
||||
#endif
|
||||
|
||||
#include <rules/NBT.h>
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\nbt\tag;
|
||||
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\NBTStream;
|
||||
|
||||
#include <rules/NBT.h>
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\nbt\tag;
|
||||
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\NBTStream;
|
||||
|
||||
#include <rules/NBT.h>
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
@ -1,467 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\nbt\tag;
|
||||
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\NBTStream;
|
||||
|
||||
#include <rules/NBT.h>
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\nbt\tag;
|
||||
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\NBTStream;
|
||||
|
||||
#include <rules/NBT.h>
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\nbt\tag;
|
||||
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\NBTStream;
|
||||
|
||||
class EndTag extends Tag{
|
||||
|
||||
public function getType() : int{
|
||||
return NBT::TAG_End;
|
||||
}
|
||||
|
||||
public function read(NBTStream $nbt) : void{
|
||||
|
||||
}
|
||||
|
||||
public function write(NBTStream $nbt) : void{
|
||||
|
||||
}
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\nbt\tag;
|
||||
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\NBTStream;
|
||||
|
||||
#include <rules/NBT.h>
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\nbt\tag;
|
||||
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\NBTStream;
|
||||
|
||||
#include <rules/NBT.h>
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\nbt\tag;
|
||||
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\NBTStream;
|
||||
|
||||
#include <rules/NBT.h>
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
@ -1,227 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\nbt\tag;
|
||||
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\NBTStream;
|
||||
|
||||
#include <rules/NBT.h>
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\nbt\tag;
|
||||
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\NBTStream;
|
||||
|
||||
#include <rules/NBT.h>
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\nbt\tag;
|
||||
|
||||
|
||||
abstract class NamedTag extends Tag{
|
||||
/** @var string */
|
||||
protected $__name;
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function __construct(string $name = "", $value = null){
|
||||
$this->__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;
|
||||
}
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\nbt\tag;
|
||||
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\NBTStream;
|
||||
|
||||
#include <rules/NBT.h>
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\nbt\tag;
|
||||
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\NBTStream;
|
||||
|
||||
#include <rules/NBT.h>
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* All the NBT Tags
|
||||
*/
|
||||
namespace pocketmine\nbt\tag;
|
||||
|
||||
use pocketmine\nbt\NBTStream;
|
||||
|
||||
abstract class Tag extends \stdClass{
|
||||
|
||||
protected $value;
|
||||
|
||||
public function &getValue(){
|
||||
return $this->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;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user