mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-07-24 03:44:08 +00:00
Merge PR #1775: NBT streams refactor
This commit is contained in:
commit
3ea72a0bf9
@ -91,7 +91,7 @@ use pocketmine\level\WeakPosition;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\metadata\MetadataValue;
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\NetworkLittleEndianNBTStream;
|
||||
use pocketmine\nbt\tag\ByteTag;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\DoubleTag;
|
||||
@ -2834,8 +2834,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
|
||||
$t = $this->level->getTile($pos);
|
||||
if($t instanceof Spawnable){
|
||||
$nbt = new NBT(NBT::LITTLE_ENDIAN);
|
||||
$nbt->read($packet->namedtag, false, true);
|
||||
$nbt = new NetworkLittleEndianNBTStream();
|
||||
$nbt->read($packet->namedtag);
|
||||
$nbt = $nbt->getData();
|
||||
if(!$t->updateCompoundTag($nbt, $this)){
|
||||
$t->spawnTo($this);
|
||||
|
@ -67,6 +67,7 @@ use pocketmine\level\LevelException;
|
||||
use pocketmine\metadata\EntityMetadataStore;
|
||||
use pocketmine\metadata\LevelMetadataStore;
|
||||
use pocketmine\metadata\PlayerMetadataStore;
|
||||
use pocketmine\nbt\BigEndianNBTStream;
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\tag\ByteTag;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
@ -749,7 +750,7 @@ class Server{
|
||||
if($this->shouldSavePlayerData()){
|
||||
if(file_exists($path . "$name.dat")){
|
||||
try{
|
||||
$nbt = new NBT(NBT::BIG_ENDIAN);
|
||||
$nbt = new BigEndianNBTStream();
|
||||
$nbt->readCompressed(file_get_contents($path . "$name.dat"));
|
||||
|
||||
return $nbt->getData();
|
||||
@ -815,7 +816,7 @@ class Server{
|
||||
$this->pluginManager->callEvent($ev);
|
||||
|
||||
if(!$ev->isCancelled()){
|
||||
$nbt = new NBT(NBT::BIG_ENDIAN);
|
||||
$nbt = new BigEndianNBTStream();
|
||||
try{
|
||||
$nbt->setData($ev->getSaveData());
|
||||
|
||||
|
@ -34,6 +34,7 @@ use pocketmine\item\enchantment\Enchantment;
|
||||
use pocketmine\item\enchantment\EnchantmentInstance;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\LittleEndianNBTStream;
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\tag\ByteTag;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
@ -64,7 +65,7 @@ class Item implements ItemIds, \JsonSerializable{
|
||||
}
|
||||
|
||||
if(self::$cachedParser === null){
|
||||
self::$cachedParser = new NBT(NBT::LITTLE_ENDIAN);
|
||||
self::$cachedParser = new LittleEndianNBTStream();
|
||||
}
|
||||
|
||||
self::$cachedParser->read($tag);
|
||||
@ -79,7 +80,7 @@ class Item implements ItemIds, \JsonSerializable{
|
||||
|
||||
private static function writeCompoundTag(CompoundTag $tag) : string{
|
||||
if(self::$cachedParser === null){
|
||||
self::$cachedParser = new NBT(NBT::LITTLE_ENDIAN);
|
||||
self::$cachedParser = new LittleEndianNBTStream();
|
||||
}
|
||||
|
||||
self::$cachedParser->setData($tag);
|
||||
|
@ -29,7 +29,7 @@ use pocketmine\level\generator\Generator;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\level\LevelException;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\BigEndianNBTStream;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\StringTag;
|
||||
use pocketmine\scheduler\AsyncTask;
|
||||
@ -48,7 +48,7 @@ abstract class BaseLevelProvider implements LevelProvider{
|
||||
if(!file_exists($this->path)){
|
||||
mkdir($this->path, 0777, true);
|
||||
}
|
||||
$nbt = new NBT(NBT::BIG_ENDIAN);
|
||||
$nbt = new BigEndianNBTStream();
|
||||
$nbt->readCompressed(file_get_contents($this->getPath() . "level.dat"));
|
||||
$levelData = $nbt->getData()->getCompoundTag("Data");
|
||||
if($levelData !== null){
|
||||
@ -120,7 +120,7 @@ abstract class BaseLevelProvider implements LevelProvider{
|
||||
}
|
||||
|
||||
public function saveLevelData(){
|
||||
$nbt = new NBT(NBT::BIG_ENDIAN);
|
||||
$nbt = new BigEndianNBTStream();
|
||||
$nbt->setData(new CompoundTag("", [
|
||||
$this->levelData
|
||||
]));
|
||||
|
@ -32,7 +32,7 @@ use pocketmine\level\generator\Flat;
|
||||
use pocketmine\level\generator\Generator;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\level\LevelException;
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\LittleEndianNBTStream;
|
||||
use pocketmine\nbt\tag\{
|
||||
ByteTag, CompoundTag, FloatTag, IntTag, LongTag, StringTag
|
||||
};
|
||||
@ -94,7 +94,7 @@ class LevelDB extends BaseLevelProvider{
|
||||
if(!file_exists($this->path)){
|
||||
mkdir($this->path, 0777, true);
|
||||
}
|
||||
$nbt = new NBT(NBT::LITTLE_ENDIAN);
|
||||
$nbt = new LittleEndianNBTStream();
|
||||
$nbt->read(substr(file_get_contents($this->getPath() . "level.dat"), 8));
|
||||
$levelData = $nbt->getData();
|
||||
if($levelData instanceof CompoundTag){
|
||||
@ -217,7 +217,7 @@ class LevelDB extends BaseLevelProvider{
|
||||
new StringTag("generatorOptions", $options["preset"] ?? "")
|
||||
]);
|
||||
|
||||
$nbt = new NBT(NBT::LITTLE_ENDIAN);
|
||||
$nbt = new LittleEndianNBTStream();
|
||||
$nbt->setData($levelData);
|
||||
$buffer = $nbt->write();
|
||||
file_put_contents($path . "level.dat", Binary::writeLInt(self::CURRENT_STORAGE_VERSION) . Binary::writeLInt(strlen($buffer)) . $buffer);
|
||||
@ -247,7 +247,7 @@ class LevelDB extends BaseLevelProvider{
|
||||
$this->levelData->setInt("NetworkVersion", ProtocolInfo::CURRENT_PROTOCOL);
|
||||
$this->levelData->setInt("StorageVersion", self::CURRENT_STORAGE_VERSION);
|
||||
|
||||
$nbt = new NBT(NBT::LITTLE_ENDIAN);
|
||||
$nbt = new LittleEndianNBTStream();
|
||||
$nbt->setData($this->levelData);
|
||||
$buffer = $nbt->write();
|
||||
file_put_contents($this->getPath() . "level.dat", Binary::writeLInt(self::CURRENT_STORAGE_VERSION) . Binary::writeLInt(strlen($buffer)) . $buffer);
|
||||
@ -416,7 +416,7 @@ class LevelDB extends BaseLevelProvider{
|
||||
throw new UnsupportedChunkFormatException("don't know how to decode chunk format version $chunkVersion");
|
||||
}
|
||||
|
||||
$nbt = new NBT(NBT::LITTLE_ENDIAN);
|
||||
$nbt = new LittleEndianNBTStream();
|
||||
|
||||
$entities = [];
|
||||
if(($entityData = $this->db->get($index . self::TAG_ENTITY)) !== false and strlen($entityData) > 0){
|
||||
@ -553,7 +553,7 @@ class LevelDB extends BaseLevelProvider{
|
||||
*/
|
||||
private function writeTags(array $targets, string $index){
|
||||
if(!empty($targets)){
|
||||
$nbt = new NBT(NBT::LITTLE_ENDIAN);
|
||||
$nbt = new LittleEndianNBTStream();
|
||||
$nbt->setData($targets);
|
||||
$this->db->put($index, $nbt->write());
|
||||
}else{
|
||||
|
@ -27,6 +27,7 @@ use pocketmine\level\format\Chunk;
|
||||
use pocketmine\level\format\ChunkException;
|
||||
use pocketmine\level\format\io\ChunkUtils;
|
||||
use pocketmine\level\format\SubChunk;
|
||||
use pocketmine\nbt\BigEndianNBTStream;
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\tag\ByteArrayTag;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
@ -83,7 +84,7 @@ class Anvil extends McRegion{
|
||||
|
||||
//TODO: TileTicks
|
||||
|
||||
$writer = new NBT(NBT::BIG_ENDIAN);
|
||||
$writer = new BigEndianNBTStream();
|
||||
$nbt->setName("Level");
|
||||
$writer->setData(new CompoundTag("", [$nbt]));
|
||||
|
||||
@ -100,7 +101,7 @@ class Anvil extends McRegion{
|
||||
}
|
||||
|
||||
public function nbtDeserialize(string $data){
|
||||
$nbt = new NBT(NBT::BIG_ENDIAN);
|
||||
$nbt = new BigEndianNBTStream();
|
||||
try{
|
||||
$nbt->readCompressed($data);
|
||||
|
||||
|
@ -30,6 +30,7 @@ use pocketmine\level\format\io\ChunkUtils;
|
||||
use pocketmine\level\format\SubChunk;
|
||||
use pocketmine\level\generator\Generator;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\nbt\BigEndianNBTStream;
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\tag\{
|
||||
ByteArrayTag, ByteTag, CompoundTag, IntArrayTag, IntTag, ListTag, LongTag, StringTag
|
||||
@ -102,7 +103,7 @@ class McRegion extends BaseLevelProvider{
|
||||
|
||||
$nbt->setTag(new ListTag("TileEntities", $tiles, NBT::TAG_Compound));
|
||||
|
||||
$writer = new NBT(NBT::BIG_ENDIAN);
|
||||
$writer = new BigEndianNBTStream();
|
||||
$nbt->setName("Level");
|
||||
$writer->setData(new CompoundTag("", [$nbt]));
|
||||
|
||||
@ -115,7 +116,7 @@ class McRegion extends BaseLevelProvider{
|
||||
* @return Chunk|null
|
||||
*/
|
||||
public function nbtDeserialize(string $data){
|
||||
$nbt = new NBT(NBT::BIG_ENDIAN);
|
||||
$nbt = new BigEndianNBTStream();
|
||||
try{
|
||||
$nbt->readCompressed($data);
|
||||
|
||||
@ -258,7 +259,7 @@ class McRegion extends BaseLevelProvider{
|
||||
new StringTag("LevelName", $name),
|
||||
new CompoundTag("GameRules", [])
|
||||
]);
|
||||
$nbt = new NBT(NBT::BIG_ENDIAN);
|
||||
$nbt = new BigEndianNBTStream();
|
||||
$nbt->setData(new CompoundTag("", [
|
||||
$levelData
|
||||
]));
|
||||
|
87
src/pocketmine/nbt/BigEndianNBTStream.php
Normal file
87
src/pocketmine/nbt/BigEndianNBTStream.php
Normal file
@ -0,0 +1,87 @@
|
||||
<?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));
|
||||
}
|
||||
}
|
87
src/pocketmine/nbt/LittleEndianNBTStream.php
Normal file
87
src/pocketmine/nbt/LittleEndianNBTStream.php
Normal file
@ -0,0 +1,87 @@
|
||||
<?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));
|
||||
}
|
||||
}
|
@ -36,22 +36,11 @@ use pocketmine\nbt\tag\IntArrayTag;
|
||||
use pocketmine\nbt\tag\IntTag;
|
||||
use pocketmine\nbt\tag\ListTag;
|
||||
use pocketmine\nbt\tag\LongTag;
|
||||
use pocketmine\nbt\tag\NamedTag;
|
||||
use pocketmine\nbt\tag\ShortTag;
|
||||
use pocketmine\nbt\tag\StringTag;
|
||||
use pocketmine\nbt\tag\Tag;
|
||||
|
||||
#ifndef COMPILE
|
||||
use pocketmine\utils\Binary;
|
||||
#endif
|
||||
|
||||
|
||||
#include <rules/NBT.h>
|
||||
|
||||
/**
|
||||
* Named Binary Tag encoder/decoder
|
||||
*/
|
||||
class NBT{
|
||||
abstract class NBT{
|
||||
|
||||
public const LITTLE_ENDIAN = 0;
|
||||
public const BIG_ENDIAN = 1;
|
||||
@ -68,17 +57,12 @@ class NBT{
|
||||
public const TAG_Compound = 10;
|
||||
public const TAG_IntArray = 11;
|
||||
|
||||
public $buffer;
|
||||
public $offset;
|
||||
public $endianness;
|
||||
private $data;
|
||||
|
||||
/**
|
||||
* @param int $type
|
||||
*
|
||||
* @return Tag
|
||||
*/
|
||||
public static function createTag(int $type){
|
||||
public static function createTag(int $type) : Tag{
|
||||
switch($type){
|
||||
case self::TAG_End:
|
||||
return new EndTag();
|
||||
@ -172,260 +156,4 @@ class NBT{
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function get($len){
|
||||
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($v){
|
||||
$this->buffer .= $v;
|
||||
}
|
||||
|
||||
public function feof() : bool{
|
||||
return !isset($this->buffer{$this->offset});
|
||||
}
|
||||
|
||||
public function __construct($endianness = self::LITTLE_ENDIAN){
|
||||
$this->offset = 0;
|
||||
$this->endianness = $endianness & 0x01;
|
||||
}
|
||||
|
||||
public function read($buffer, $doMultiple = false, bool $network = false){
|
||||
$this->offset = 0;
|
||||
$this->buffer = $buffer;
|
||||
$this->data = $this->readTag($network);
|
||||
if($doMultiple and $this->offset < strlen($this->buffer)){
|
||||
$this->data = [$this->data];
|
||||
do{
|
||||
$this->data[] = $this->readTag($network);
|
||||
}while($this->offset < strlen($this->buffer));
|
||||
}
|
||||
$this->buffer = "";
|
||||
}
|
||||
|
||||
public function readCompressed($buffer){
|
||||
$this->read(zlib_decode($buffer));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $network
|
||||
*
|
||||
* @return string|bool
|
||||
*/
|
||||
public function write(bool $network = false){
|
||||
$this->offset = 0;
|
||||
$this->buffer = "";
|
||||
|
||||
if($this->data instanceof CompoundTag){
|
||||
$this->writeTag($this->data, $network);
|
||||
|
||||
return $this->buffer;
|
||||
}elseif(is_array($this->data)){
|
||||
foreach($this->data as $tag){
|
||||
$this->writeTag($tag, $network);
|
||||
}
|
||||
return $this->buffer;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function writeCompressed($compression = ZLIB_ENCODING_GZIP, $level = 7){
|
||||
if(($write = $this->write()) !== false){
|
||||
return zlib_encode($write, $compression, $level);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function readTag(bool $network = false){
|
||||
if($this->feof()){
|
||||
return new EndTag();
|
||||
}
|
||||
|
||||
$tagType = $this->getByte();
|
||||
$tag = self::createTag($tagType);
|
||||
|
||||
if($tag instanceof NamedTag){
|
||||
$tag->setName($this->getString($network));
|
||||
$tag->read($this, $network);
|
||||
}
|
||||
|
||||
return $tag;
|
||||
}
|
||||
|
||||
public function writeTag(Tag $tag, bool $network = false){
|
||||
$this->putByte($tag->getType());
|
||||
if($tag instanceof NamedTag){
|
||||
$this->putString($tag->getName(), $network);
|
||||
}
|
||||
$tag->write($this, $network);
|
||||
}
|
||||
|
||||
public function getByte() : int{
|
||||
return Binary::readByte($this->get(1));
|
||||
}
|
||||
|
||||
public function getSignedByte() : int{
|
||||
return Binary::readSignedByte($this->get(1));
|
||||
}
|
||||
|
||||
public function putByte($v){
|
||||
$this->buffer .= Binary::writeByte($v);
|
||||
}
|
||||
|
||||
public function getShort() : int{
|
||||
return $this->endianness === self::BIG_ENDIAN ? Binary::readShort($this->get(2)) : Binary::readLShort($this->get(2));
|
||||
}
|
||||
|
||||
public function getSignedShort() : int{
|
||||
return $this->endianness === self::BIG_ENDIAN ? Binary::readSignedShort($this->get(2)) : Binary::readSignedLShort($this->get(2));
|
||||
}
|
||||
|
||||
public function putShort($v){
|
||||
$this->buffer .= $this->endianness === self::BIG_ENDIAN ? Binary::writeShort($v) : Binary::writeLShort($v);
|
||||
}
|
||||
|
||||
public function getInt(bool $network = false) : int{
|
||||
if($network === true){
|
||||
return Binary::readVarInt($this->buffer, $this->offset);
|
||||
}
|
||||
return $this->endianness === self::BIG_ENDIAN ? Binary::readInt($this->get(4)) : Binary::readLInt($this->get(4));
|
||||
}
|
||||
|
||||
public function putInt($v, bool $network = false){
|
||||
if($network === true){
|
||||
$this->buffer .= Binary::writeVarInt($v);
|
||||
}else{
|
||||
$this->buffer .= $this->endianness === self::BIG_ENDIAN ? Binary::writeInt($v) : Binary::writeLInt($v);
|
||||
}
|
||||
}
|
||||
|
||||
public function getLong(bool $network = false) : int{
|
||||
if($network){
|
||||
return Binary::readVarLong($this->buffer, $this->offset);
|
||||
}
|
||||
return $this->endianness === self::BIG_ENDIAN ? Binary::readLong($this->get(8)) : Binary::readLLong($this->get(8));
|
||||
}
|
||||
|
||||
public function putLong($v, bool $network = false){
|
||||
if($network){
|
||||
$this->buffer .= Binary::writeVarLong($v);
|
||||
}else{
|
||||
$this->buffer .= $this->endianness === self::BIG_ENDIAN ? Binary::writeLong($v) : Binary::writeLLong($v);
|
||||
}
|
||||
}
|
||||
|
||||
public function getFloat() : float{
|
||||
return $this->endianness === self::BIG_ENDIAN ? Binary::readFloat($this->get(4)) : Binary::readLFloat($this->get(4));
|
||||
}
|
||||
|
||||
public function putFloat($v){
|
||||
$this->buffer .= $this->endianness === self::BIG_ENDIAN ? Binary::writeFloat($v) : Binary::writeLFloat($v);
|
||||
}
|
||||
|
||||
public function getDouble() : float{
|
||||
return $this->endianness === self::BIG_ENDIAN ? Binary::readDouble($this->get(8)) : Binary::readLDouble($this->get(8));
|
||||
}
|
||||
|
||||
public function putDouble($v){
|
||||
$this->buffer .= $this->endianness === self::BIG_ENDIAN ? Binary::writeDouble($v) : Binary::writeLDouble($v);
|
||||
}
|
||||
|
||||
public function getString(bool $network = false){
|
||||
$len = $network ? Binary::readUnsignedVarInt($this->buffer, $this->offset) : $this->getShort();
|
||||
return $this->get($len);
|
||||
}
|
||||
|
||||
public function putString($v, bool $network = false){
|
||||
if($network === true){
|
||||
$this->put(Binary::writeUnsignedVarInt(strlen($v)));
|
||||
}else{
|
||||
$this->putShort(strlen($v));
|
||||
}
|
||||
$this->buffer .= $v;
|
||||
}
|
||||
|
||||
public function getArray() : array{
|
||||
$data = [];
|
||||
self::toArray($data, $this->data);
|
||||
return $data;
|
||||
}
|
||||
|
||||
private static function toArray(array &$data, Tag $tag){
|
||||
/** @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($key, $value){
|
||||
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){
|
||||
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){
|
||||
$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){
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
}
|
||||
|
271
src/pocketmine/nbt/NBTStream.php
Normal file
271
src/pocketmine/nbt/NBTStream.php
Normal file
@ -0,0 +1,271 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
74
src/pocketmine/nbt/NetworkLittleEndianNBTStream.php
Normal file
74
src/pocketmine/nbt/NetworkLittleEndianNBTStream.php
Normal file
@ -0,0 +1,74 @@
|
||||
<?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
|
||||
}
|
||||
}
|
||||
}
|
@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine\nbt\tag;
|
||||
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\NBTStream;
|
||||
|
||||
#include <rules/NBT.h>
|
||||
|
||||
@ -43,12 +44,12 @@ class ByteArrayTag extends NamedTag{
|
||||
return NBT::TAG_ByteArray;
|
||||
}
|
||||
|
||||
public function read(NBT $nbt, bool $network = false) : void{
|
||||
$this->value = $nbt->get($nbt->getInt($network));
|
||||
public function read(NBTStream $nbt) : void{
|
||||
$this->value = $nbt->get($nbt->getInt());
|
||||
}
|
||||
|
||||
public function write(NBT $nbt, bool $network = false) : void{
|
||||
$nbt->putInt(strlen($this->value), $network);
|
||||
public function write(NBTStream $nbt) : void{
|
||||
$nbt->putInt(strlen($this->value));
|
||||
$nbt->put($this->value);
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine\nbt\tag;
|
||||
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\NBTStream;
|
||||
|
||||
#include <rules/NBT.h>
|
||||
|
||||
@ -43,11 +44,11 @@ class ByteTag extends NamedTag{
|
||||
return NBT::TAG_Byte;
|
||||
}
|
||||
|
||||
public function read(NBT $nbt, bool $network = false) : void{
|
||||
public function read(NBTStream $nbt) : void{
|
||||
$this->value = $nbt->getSignedByte();
|
||||
}
|
||||
|
||||
public function write(NBT $nbt, bool $network = false) : void{
|
||||
public function write(NBTStream $nbt) : void{
|
||||
$nbt->putByte($this->value);
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine\nbt\tag;
|
||||
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\NBTStream;
|
||||
|
||||
#include <rules/NBT.h>
|
||||
|
||||
@ -427,23 +428,23 @@ class CompoundTag extends NamedTag implements \ArrayAccess{
|
||||
return NBT::TAG_Compound;
|
||||
}
|
||||
|
||||
public function read(NBT $nbt, bool $network = false) : void{
|
||||
public function read(NBTStream $nbt) : void{
|
||||
$this->value = [];
|
||||
do{
|
||||
$tag = $nbt->readTag($network);
|
||||
$tag = $nbt->readTag();
|
||||
if($tag instanceof NamedTag and $tag->__name !== ""){
|
||||
$this->{$tag->__name} = $tag;
|
||||
}
|
||||
}while(!($tag instanceof EndTag) and !$nbt->feof());
|
||||
}
|
||||
|
||||
public function write(NBT $nbt, bool $network = false) : void{
|
||||
public function write(NBTStream $nbt) : void{
|
||||
foreach($this as $tag){
|
||||
if($tag instanceof Tag and !($tag instanceof EndTag)){
|
||||
$nbt->writeTag($tag, $network);
|
||||
$nbt->writeTag($tag);
|
||||
}
|
||||
}
|
||||
$nbt->writeTag(new EndTag, $network);
|
||||
$nbt->writeTag(new EndTag);
|
||||
}
|
||||
|
||||
public function __toString(){
|
||||
|
@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine\nbt\tag;
|
||||
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\NBTStream;
|
||||
|
||||
#include <rules/NBT.h>
|
||||
|
||||
@ -43,11 +44,11 @@ class DoubleTag extends NamedTag{
|
||||
return NBT::TAG_Double;
|
||||
}
|
||||
|
||||
public function read(NBT $nbt, bool $network = false) : void{
|
||||
public function read(NBTStream $nbt) : void{
|
||||
$this->value = $nbt->getDouble();
|
||||
}
|
||||
|
||||
public function write(NBT $nbt, bool $network = false) : void{
|
||||
public function write(NBTStream $nbt) : void{
|
||||
$nbt->putDouble($this->value);
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine\nbt\tag;
|
||||
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\NBTStream;
|
||||
|
||||
class EndTag extends Tag{
|
||||
|
||||
@ -31,11 +32,11 @@ class EndTag extends Tag{
|
||||
return NBT::TAG_End;
|
||||
}
|
||||
|
||||
public function read(NBT $nbt, bool $network = false) : void{
|
||||
public function read(NBTStream $nbt) : void{
|
||||
|
||||
}
|
||||
|
||||
public function write(NBT $nbt, bool $network = false) : void{
|
||||
public function write(NBTStream $nbt) : void{
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine\nbt\tag;
|
||||
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\NBTStream;
|
||||
|
||||
#include <rules/NBT.h>
|
||||
|
||||
@ -43,11 +44,11 @@ class FloatTag extends NamedTag{
|
||||
return NBT::TAG_Float;
|
||||
}
|
||||
|
||||
public function read(NBT $nbt, bool $network = false) : void{
|
||||
public function read(NBTStream $nbt) : void{
|
||||
$this->value = $nbt->getFloat();
|
||||
}
|
||||
|
||||
public function write(NBT $nbt, bool $network = false) : void{
|
||||
public function write(NBTStream $nbt) : void{
|
||||
$nbt->putFloat($this->value);
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine\nbt\tag;
|
||||
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\NBTStream;
|
||||
|
||||
#include <rules/NBT.h>
|
||||
|
||||
@ -43,14 +44,12 @@ class IntArrayTag extends NamedTag{
|
||||
return NBT::TAG_IntArray;
|
||||
}
|
||||
|
||||
public function read(NBT $nbt, bool $network = false) : void{
|
||||
$size = $nbt->getInt($network);
|
||||
$this->value = array_values(unpack($nbt->endianness === NBT::LITTLE_ENDIAN ? "V*" : "N*", $nbt->get($size * 4)));
|
||||
public function read(NBTStream $nbt) : void{
|
||||
$this->value = $nbt->getIntArray();
|
||||
}
|
||||
|
||||
public function write(NBT $nbt, bool $network = false) : void{
|
||||
$nbt->putInt(count($this->value), $network);
|
||||
$nbt->put(pack($nbt->endianness === NBT::LITTLE_ENDIAN ? "V*" : "N*", ...$this->value));
|
||||
public function write(NBTStream $nbt) : void{
|
||||
$nbt->putIntArray($this->value);
|
||||
}
|
||||
|
||||
public function __toString(){
|
||||
|
@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine\nbt\tag;
|
||||
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\NBTStream;
|
||||
|
||||
#include <rules/NBT.h>
|
||||
|
||||
@ -41,12 +42,12 @@ class IntTag extends NamedTag{
|
||||
return NBT::TAG_Int;
|
||||
}
|
||||
|
||||
public function read(NBT $nbt, bool $network = false) : void{
|
||||
$this->value = $nbt->getInt($network);
|
||||
public function read(NBTStream $nbt) : void{
|
||||
$this->value = $nbt->getInt();
|
||||
}
|
||||
|
||||
public function write(NBT $nbt, bool $network = false) : void{
|
||||
$nbt->putInt($this->value, $network);
|
||||
public function write(NBTStream $nbt) : void{
|
||||
$nbt->putInt($this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine\nbt\tag;
|
||||
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\NBTStream;
|
||||
|
||||
#include <rules/NBT.h>
|
||||
|
||||
@ -163,20 +164,20 @@ class ListTag extends NamedTag implements \ArrayAccess, \Countable{
|
||||
return $this->tagType;
|
||||
}
|
||||
|
||||
public function read(NBT $nbt, bool $network = false) : void{
|
||||
public function read(NBTStream $nbt) : void{
|
||||
$this->value = [];
|
||||
$this->tagType = $nbt->getByte();
|
||||
$size = $nbt->getInt($network);
|
||||
$size = $nbt->getInt();
|
||||
|
||||
$tagBase = NBT::createTag($this->tagType);
|
||||
for($i = 0; $i < $size and !$nbt->feof(); ++$i){
|
||||
$tag = clone $tagBase;
|
||||
$tag->read($nbt, $network);
|
||||
$tag->read($nbt);
|
||||
$this->{$i} = $tag;
|
||||
}
|
||||
}
|
||||
|
||||
public function write(NBT $nbt, bool $network = false) : void{
|
||||
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){
|
||||
@ -200,9 +201,9 @@ class ListTag extends NamedTag implements \ArrayAccess, \Countable{
|
||||
$tags[] = $tag;
|
||||
}
|
||||
}
|
||||
$nbt->putInt(count($tags), $network);
|
||||
$nbt->putInt(count($tags));
|
||||
foreach($tags as $tag){
|
||||
$tag->write($nbt, $network);
|
||||
$tag->write($nbt);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine\nbt\tag;
|
||||
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\NBTStream;
|
||||
|
||||
#include <rules/NBT.h>
|
||||
|
||||
@ -43,12 +44,12 @@ class LongTag extends NamedTag{
|
||||
return NBT::TAG_Long;
|
||||
}
|
||||
|
||||
public function read(NBT $nbt, bool $network = false) : void{
|
||||
$this->value = $nbt->getLong($network);
|
||||
public function read(NBTStream $nbt) : void{
|
||||
$this->value = $nbt->getLong();
|
||||
}
|
||||
|
||||
public function write(NBT $nbt, bool $network = false) : void{
|
||||
$nbt->putLong($this->value, $network);
|
||||
public function write(NBTStream $nbt) : void{
|
||||
$nbt->putLong($this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine\nbt\tag;
|
||||
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\NBTStream;
|
||||
|
||||
#include <rules/NBT.h>
|
||||
|
||||
@ -43,11 +44,11 @@ class ShortTag extends NamedTag{
|
||||
return NBT::TAG_Short;
|
||||
}
|
||||
|
||||
public function read(NBT $nbt, bool $network = false) : void{
|
||||
public function read(NBTStream $nbt) : void{
|
||||
$this->value = $nbt->getSignedShort();
|
||||
}
|
||||
|
||||
public function write(NBT $nbt, bool $network = false) : void{
|
||||
public function write(NBTStream $nbt) : void{
|
||||
$nbt->putShort($this->value);
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine\nbt\tag;
|
||||
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\NBTStream;
|
||||
|
||||
#include <rules/NBT.h>
|
||||
|
||||
@ -43,12 +44,12 @@ class StringTag extends NamedTag{
|
||||
return NBT::TAG_String;
|
||||
}
|
||||
|
||||
public function read(NBT $nbt, bool $network = false) : void{
|
||||
$this->value = $nbt->getString($network);
|
||||
public function read(NBTStream $nbt) : void{
|
||||
$this->value = $nbt->getString();
|
||||
}
|
||||
|
||||
public function write(NBT $nbt, bool $network = false) : void{
|
||||
$nbt->putString($this->value, $network);
|
||||
public function write(NBTStream $nbt) : void{
|
||||
$nbt->putString($this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -26,7 +26,7 @@ declare(strict_types=1);
|
||||
*/
|
||||
namespace pocketmine\nbt\tag;
|
||||
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\NBTStream;
|
||||
|
||||
abstract class Tag extends \stdClass{
|
||||
|
||||
@ -42,9 +42,9 @@ abstract class Tag extends \stdClass{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
abstract public function write(NBT $nbt, bool $network = false) : void;
|
||||
abstract public function write(NBTStream $nbt) : void;
|
||||
|
||||
abstract public function read(NBT $nbt, bool $network = false) : void;
|
||||
abstract public function read(NBTStream $nbt) : void;
|
||||
|
||||
public function __toString(){
|
||||
return (string) $this->value;
|
||||
|
@ -25,6 +25,7 @@ namespace pocketmine\tile;
|
||||
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\NetworkLittleEndianNBTStream;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\network\mcpe\protocol\BlockEntityDataPacket;
|
||||
use pocketmine\Player;
|
||||
@ -92,11 +93,11 @@ abstract class Spawnable extends Tile{
|
||||
final public function getSerializedSpawnCompound() : string{
|
||||
if($this->spawnCompoundCache === null){
|
||||
if(self::$nbtWriter === null){
|
||||
self::$nbtWriter = new NBT(NBT::LITTLE_ENDIAN);
|
||||
self::$nbtWriter = new NetworkLittleEndianNBTStream();
|
||||
}
|
||||
|
||||
self::$nbtWriter->setData($this->getSpawnCompound());
|
||||
$this->spawnCompoundCache = self::$nbtWriter->write(true);
|
||||
$this->spawnCompoundCache = self::$nbtWriter->write();
|
||||
}
|
||||
|
||||
return $this->spawnCompoundCache;
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 86961f81970a49f8c25e18d0d414961d7142a84d
|
||||
Subproject commit 316fd5606fef1191e7f228d3156dd1518c33aba4
|
Loading…
x
Reference in New Issue
Block a user