Updating for latest PocketMine-NBT changes

This commit is contained in:
Dylan K. Taylor 2019-03-21 15:58:22 +00:00
parent 1ac255f955
commit 8c536c248d
24 changed files with 237 additions and 266 deletions

8
composer.lock generated
View File

@ -372,12 +372,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/pmmp/NBT.git", "url": "https://github.com/pmmp/NBT.git",
"reference": "cb170cf827e265cfb492de2af684cba23574dfec" "reference": "772f627884c92beb750cc1c50a8d25f155a9c006"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/pmmp/NBT/zipball/cb170cf827e265cfb492de2af684cba23574dfec", "url": "https://api.github.com/repos/pmmp/NBT/zipball/772f627884c92beb750cc1c50a8d25f155a9c006",
"reference": "cb170cf827e265cfb492de2af684cba23574dfec", "reference": "772f627884c92beb750cc1c50a8d25f155a9c006",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -405,7 +405,7 @@
"source": "https://github.com/pmmp/NBT/tree/master", "source": "https://github.com/pmmp/NBT/tree/master",
"issues": "https://github.com/pmmp/NBT/issues" "issues": "https://github.com/pmmp/NBT/issues"
}, },
"time": "2019-03-16T12:12:20+00:00" "time": "2019-03-18T14:38:07+00:00"
}, },
{ {
"name": "pocketmine/raklib", "name": "pocketmine/raklib",

View File

@ -1826,10 +1826,10 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener,
//TODO: old code had a TODO for SpawnForced //TODO: old code had a TODO for SpawnForced
}elseif($spawnReset){ }elseif($spawnReset){
$namedtag->setTag(new ListTag("Pos", [ $namedtag->setTag("Pos", new ListTag([
new DoubleTag("", $spawn->x), new DoubleTag($spawn->x),
new DoubleTag("", $spawn->y), new DoubleTag($spawn->y),
new DoubleTag("", $spawn->z) new DoubleTag($spawn->z)
])); ]));
} }
@ -1882,9 +1882,9 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener,
$this->achievements = []; $this->achievements = [];
$achievements = $nbt->getCompoundTag("Achievements"); $achievements = $nbt->getCompoundTag("Achievements");
if($achievements !== null){ if($achievements !== null){
/** @var ByteTag $achievement */ /** @var ByteTag $tag */
foreach($achievements as $achievement){ foreach($achievements as $name => $tag){
$this->achievements[$achievement->getName()] = $achievement->getValue() !== 0; $this->achievements[$name] = $tag->getValue() !== 0;
} }
} }
@ -2897,19 +2897,19 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener,
if(!$this->isAlive()){ if(!$this->isAlive()){
//hack for respawn after quit //hack for respawn after quit
$nbt->setTag(new ListTag("Pos", [ $nbt->setTag("Pos", new ListTag([
new DoubleTag("", $this->spawnPosition->x), new DoubleTag($this->spawnPosition->x),
new DoubleTag("", $this->spawnPosition->y), new DoubleTag($this->spawnPosition->y),
new DoubleTag("", $this->spawnPosition->z) new DoubleTag($this->spawnPosition->z)
])); ]));
} }
} }
$achievements = new CompoundTag("Achievements"); $achievements = new CompoundTag();
foreach($this->achievements as $achievement => $status){ foreach($this->achievements as $achievement => $status){
$achievements->setByte($achievement, $status ? 1 : 0); $achievements->setByte($achievement, $status ? 1 : 0);
} }
$nbt->setTag($achievements); $nbt->setTag("Achievements", $achievements);
$nbt->setInt("playerGameType", $this->gamemode); $nbt->setInt("playerGameType", $this->gamemode);
$nbt->setLong("firstPlayed", $this->firstPlayed); $nbt->setLong("firstPlayed", $this->firstPlayed);

View File

@ -61,6 +61,7 @@ use pocketmine\metadata\PlayerMetadataStore;
use pocketmine\nbt\BigEndianNbtSerializer; use pocketmine\nbt\BigEndianNbtSerializer;
use pocketmine\nbt\NbtDataException; use pocketmine\nbt\NbtDataException;
use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\TreeRoot;
use pocketmine\network\AdvancedNetworkInterface; use pocketmine\network\AdvancedNetworkInterface;
use pocketmine\network\mcpe\CompressBatchPromise; use pocketmine\network\mcpe\CompressBatchPromise;
use pocketmine\network\mcpe\CompressBatchTask; use pocketmine\network\mcpe\CompressBatchTask;
@ -645,7 +646,7 @@ class Server{
if(file_exists($path . "$name.dat")){ if(file_exists($path . "$name.dat")){
try{ try{
return (new BigEndianNbtSerializer())->readCompressed(file_get_contents($path . "$name.dat")); return (new BigEndianNbtSerializer())->readCompressed(file_get_contents($path . "$name.dat"))->getTag();
}catch(NbtDataException $e){ //zlib decode error / corrupt data }catch(NbtDataException $e){ //zlib decode error / corrupt data
rename($path . "$name.dat", $path . "$name.dat.bak"); rename($path . "$name.dat", $path . "$name.dat.bak");
$this->logger->error($this->getLanguage()->translateString("pocketmine.data.playerCorrupted", [$name])); $this->logger->error($this->getLanguage()->translateString("pocketmine.data.playerCorrupted", [$name]));
@ -667,7 +668,7 @@ class Server{
if(!$ev->isCancelled()){ if(!$ev->isCancelled()){
$nbt = new BigEndianNbtSerializer(); $nbt = new BigEndianNbtSerializer();
try{ try{
file_put_contents($this->getDataPath() . "players/" . strtolower($name) . ".dat", $nbt->writeCompressed($ev->getSaveData())); file_put_contents($this->getDataPath() . "players/" . strtolower($name) . ".dat", $nbt->writeCompressed(new TreeRoot($ev->getSaveData())));
}catch(\ErrorException $e){ }catch(\ErrorException $e){
$this->logger->critical($this->getLanguage()->translateString("pocketmine.data.saveError", [$name, $e->getMessage()])); $this->logger->critical($this->getLanguage()->translateString("pocketmine.data.saveError", [$name, $e->getMessage()]));
$this->logger->logException($e); $this->logger->logException($e);

View File

@ -715,7 +715,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
} }
public function saveNBT() : CompoundTag{ public function saveNBT() : CompoundTag{
$nbt = new CompoundTag(""); $nbt = new CompoundTag();
if(!($this instanceof Player)){ if(!($this instanceof Player)){
$nbt->setString("id", EntityFactory::getSaveId(get_class($this))); $nbt->setString("id", EntityFactory::getSaveId(get_class($this)));
@ -725,21 +725,21 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
} }
} }
$nbt->setTag(new ListTag("Pos", [ $nbt->setTag("Pos", new ListTag([
new DoubleTag("", $this->x), new DoubleTag($this->x),
new DoubleTag("", $this->y), new DoubleTag($this->y),
new DoubleTag("", $this->z) new DoubleTag($this->z)
])); ]));
$nbt->setTag(new ListTag("Motion", [ $nbt->setTag("Motion", new ListTag([
new DoubleTag("", $this->motion->x), new DoubleTag($this->motion->x),
new DoubleTag("", $this->motion->y), new DoubleTag($this->motion->y),
new DoubleTag("", $this->motion->z) new DoubleTag($this->motion->z)
])); ]));
$nbt->setTag(new ListTag("Rotation", [ $nbt->setTag("Rotation", new ListTag([
new FloatTag("", $this->yaw), new FloatTag($this->yaw),
new FloatTag("", $this->pitch) new FloatTag($this->pitch)
])); ]));
$nbt->setFloat("FallDistance", $this->fallDistance); $nbt->setFloat("FallDistance", $this->fallDistance);

View File

@ -246,21 +246,20 @@ final class EntityFactory{
* @return CompoundTag * @return CompoundTag
*/ */
public static function createBaseNBT(Vector3 $pos, ?Vector3 $motion = null, float $yaw = 0.0, float $pitch = 0.0) : CompoundTag{ public static function createBaseNBT(Vector3 $pos, ?Vector3 $motion = null, float $yaw = 0.0, float $pitch = 0.0) : CompoundTag{
return new CompoundTag("", [ return CompoundTag::create()
new ListTag("Pos", [ ->setTag("Pos", new ListTag([
new DoubleTag("", $pos->x), new DoubleTag($pos->x),
new DoubleTag("", $pos->y), new DoubleTag($pos->y),
new DoubleTag("", $pos->z) new DoubleTag($pos->z)
]), ]))
new ListTag("Motion", [ ->setTag("Motion", new ListTag([
new DoubleTag("", $motion ? $motion->x : 0.0), new DoubleTag($motion ? $motion->x : 0.0),
new DoubleTag("", $motion ? $motion->y : 0.0), new DoubleTag($motion ? $motion->y : 0.0),
new DoubleTag("", $motion ? $motion->z : 0.0) new DoubleTag($motion ? $motion->z : 0.0)
]), ]))
new ListTag("Rotation", [ ->setTag("Rotation", new ListTag([
new FloatTag("", $yaw), new FloatTag($yaw),
new FloatTag("", $pitch) new FloatTag($pitch)
]) ]));
]);
} }
} }

View File

@ -800,8 +800,8 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
$nbt->setInt("XpTotal", $this->totalXp); $nbt->setInt("XpTotal", $this->totalXp);
$nbt->setInt("XpSeed", $this->xpSeed); $nbt->setInt("XpSeed", $this->xpSeed);
$inventoryTag = new ListTag("Inventory", [], NBT::TAG_Compound); $inventoryTag = new ListTag([], NBT::TAG_Compound);
$nbt->setTag($inventoryTag); $nbt->setTag("Inventory", $inventoryTag);
if($this->inventory !== null){ if($this->inventory !== null){
//Normal inventory //Normal inventory
$slotCount = $this->inventory->getSize() + $this->inventory->getHotbarSize(); $slotCount = $this->inventory->getSize() + $this->inventory->getHotbarSize();
@ -835,17 +835,17 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
} }
} }
$nbt->setTag(new ListTag("EnderChestInventory", $items, NBT::TAG_Compound)); $nbt->setTag("EnderChestInventory", new ListTag($items, NBT::TAG_Compound));
} }
if($this->skin !== null){ if($this->skin !== null){
$nbt->setTag(new CompoundTag("Skin", [ $nbt->setTag("Skin", CompoundTag::create()
new StringTag("Name", $this->skin->getSkinId()), ->setString("Name", $this->skin->getSkinId())
new ByteArrayTag("Data", $this->skin->getSkinData()), ->setByteArray("Data", $this->skin->getSkinData())
new ByteArrayTag("CapeData", $this->skin->getCapeData()), ->setByteArray("CapeData", $this->skin->getCapeData())
new StringTag("GeometryName", $this->skin->getGeometryName()), ->setString("GeometryName", $this->skin->getGeometryName())
new ByteArrayTag("GeometryData", $this->skin->getGeometryData()) ->setByteArray("GeometryData", $this->skin->getGeometryData())
])); );
} }
return $nbt; return $nbt;

View File

@ -42,10 +42,8 @@ use pocketmine\item\enchantment\Enchantment;
use pocketmine\item\Item; use pocketmine\item\Item;
use pocketmine\math\Vector3; use pocketmine\math\Vector3;
use pocketmine\math\VoxelRayTrace; use pocketmine\math\VoxelRayTrace;
use pocketmine\nbt\tag\ByteTag;
use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\FloatTag; use pocketmine\nbt\tag\FloatTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\ListTag; use pocketmine\nbt\tag\ListTag;
use pocketmine\network\mcpe\protocol\EntityEventPacket; use pocketmine\network\mcpe\protocol\EntityEventPacket;
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket; use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
@ -178,16 +176,15 @@ abstract class Living extends Entity implements Damageable{
if(count($this->effects) > 0){ if(count($this->effects) > 0){
$effects = []; $effects = [];
foreach($this->effects as $effect){ foreach($this->effects as $effect){
$effects[] = new CompoundTag("", [ $effects[] = CompoundTag::create()
new ByteTag("Id", $effect->getId()), ->setByte("Id", $effect->getId())
new ByteTag("Amplifier", Binary::signByte($effect->getAmplifier())), ->setByte("Amplifier", Binary::signByte($effect->getAmplifier()))
new IntTag("Duration", $effect->getDuration()), ->setInt("Duration", $effect->getDuration())
new ByteTag("Ambient", $effect->isAmbient() ? 1 : 0), ->setByte("Ambient", $effect->isAmbient() ? 1 : 0)
new ByteTag("ShowParticles", $effect->isVisible() ? 1 : 0) ->setByte("ShowParticles", $effect->isVisible() ? 1 : 0);
]);
} }
$nbt->setTag(new ListTag("ActiveEffects", $effects)); $nbt->setTag("ActiveEffects", new ListTag($effects));
} }
return $nbt; return $nbt;

View File

@ -134,7 +134,7 @@ class ItemEntity extends Entity{
public function saveNBT() : CompoundTag{ public function saveNBT() : CompoundTag{
$nbt = parent::saveNBT(); $nbt = parent::saveNBT();
$nbt->setTag($this->item->nbtSerialize(-1, "Item")); $nbt->setTag("Item", $this->item->nbtSerialize());
$nbt->setShort("Health", (int) $this->getHealth()); $nbt->setShort("Health", (int) $this->getHealth());
if($this->despawnDelay === self::NEVER_DESPAWN){ if($this->despawnDelay === self::NEVER_DESPAWN){
$age = -32768; $age = -32768;

View File

@ -29,9 +29,7 @@ use pocketmine\block\BlockFactory;
use pocketmine\block\utils\BannerPattern; use pocketmine\block\utils\BannerPattern;
use pocketmine\block\utils\DyeColor; use pocketmine\block\utils\DyeColor;
use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\ListTag; use pocketmine\nbt\tag\ListTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\tile\Banner as TileBanner; use pocketmine\tile\Banner as TileBanner;
class Banner extends Item{ class Banner extends Item{
@ -81,15 +79,15 @@ class Banner extends Item{
* @param Deque|BannerPattern[] $patterns * @param Deque|BannerPattern[] $patterns
*/ */
public function setPatterns(Deque $patterns) : void{ public function setPatterns(Deque $patterns) : void{
$tag = new ListTag(self::TAG_PATTERNS); $tag = new ListTag();
/** @var BannerPattern $pattern */ /** @var BannerPattern $pattern */
foreach($patterns as $pattern){ foreach($patterns as $pattern){
$tag->push(new CompoundTag("", [ $tag->push(CompoundTag::create()
new StringTag(self::TAG_PATTERN_NAME, $pattern->getId()), ->setString(self::TAG_PATTERN_NAME, $pattern->getId())
new IntTag(self::TAG_PATTERN_COLOR, $pattern->getColor()->getInvertedMagicNumber()) ->setInt(self::TAG_PATTERN_COLOR, $pattern->getColor()->getInvertedMagicNumber())
])); );
} }
$this->getNamedTag()->setTag($tag); $this->getNamedTag()->setTag(self::TAG_PATTERNS, $tag);
} }
public function getFuelTime() : int{ public function getFuelTime() : int{

View File

@ -36,11 +36,11 @@ use pocketmine\math\Vector3;
use pocketmine\nbt\LittleEndianNbtSerializer; use pocketmine\nbt\LittleEndianNbtSerializer;
use pocketmine\nbt\NBT; use pocketmine\nbt\NBT;
use pocketmine\nbt\NbtDataException; use pocketmine\nbt\NbtDataException;
use pocketmine\nbt\tag\ByteTag;
use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\ListTag; use pocketmine\nbt\tag\ListTag;
use pocketmine\nbt\tag\ShortTag; use pocketmine\nbt\tag\ShortTag;
use pocketmine\nbt\tag\StringTag; use pocketmine\nbt\tag\StringTag;
use pocketmine\nbt\TreeRoot;
use pocketmine\Player; use pocketmine\Player;
use pocketmine\utils\Binary; use pocketmine\utils\Binary;
use function array_map; use function array_map;
@ -199,10 +199,7 @@ class Item implements ItemIds, \JsonSerializable{
* @return Item * @return Item
*/ */
public function setCustomBlockData(CompoundTag $compound) : Item{ public function setCustomBlockData(CompoundTag $compound) : Item{
$tags = clone $compound; $this->getNamedTag()->setTag(self::TAG_BLOCK_ENTITY_TAG, clone $compound);
$tags->setName(self::TAG_BLOCK_ENTITY_TAG);
$this->getNamedTag()->setTag($tags);
return $this; return $this;
} }
@ -311,15 +308,15 @@ class Item implements ItemIds, \JsonSerializable{
$ench = $this->getNamedTag()->getListTag(self::TAG_ENCH); $ench = $this->getNamedTag()->getListTag(self::TAG_ENCH);
if(!($ench instanceof ListTag)){ if(!($ench instanceof ListTag)){
$ench = new ListTag(self::TAG_ENCH, [], NBT::TAG_Compound); $ench = new ListTag([], NBT::TAG_Compound);
}else{ }else{
/** @var CompoundTag $entry */ /** @var CompoundTag $entry */
foreach($ench as $k => $entry){ foreach($ench as $k => $entry){
if($entry->getShort("id") === $enchantment->getId()){ if($entry->getShort("id") === $enchantment->getId()){
$ench->set($k, new CompoundTag("", [ $ench->set($k, CompoundTag::create()
new ShortTag("id", $enchantment->getId()), ->setShort("id", $enchantment->getId())
new ShortTag("lvl", $enchantment->getLevel()) ->setShort("lvl", $enchantment->getLevel())
])); );
$found = true; $found = true;
break; break;
} }
@ -327,13 +324,13 @@ class Item implements ItemIds, \JsonSerializable{
} }
if(!$found){ if(!$found){
$ench->push(new CompoundTag("", [ $ench->push(CompoundTag::create()
new ShortTag("id", $enchantment->getId()), ->setShort("id", $enchantment->getId())
new ShortTag("lvl", $enchantment->getLevel()) ->setShort("lvl", $enchantment->getLevel())
])); );
} }
$this->getNamedTag()->setTag($ench); $this->getNamedTag()->setTag(self::TAG_ENCH, $ench);
return $this; return $this;
} }
@ -418,12 +415,12 @@ class Item implements ItemIds, \JsonSerializable{
/** @var CompoundTag $display */ /** @var CompoundTag $display */
$display = $this->getNamedTag()->getCompoundTag(self::TAG_DISPLAY); $display = $this->getNamedTag()->getCompoundTag(self::TAG_DISPLAY);
if(!($display instanceof CompoundTag)){ if($display === null){
$display = new CompoundTag(self::TAG_DISPLAY); $display = new CompoundTag();
} }
$display->setString(self::TAG_DISPLAY_NAME, $name); $display->setString(self::TAG_DISPLAY_NAME, $name);
$this->getNamedTag()->setTag($display); $this->getNamedTag()->setTag(self::TAG_DISPLAY, $display);
return $this; return $this;
} }
@ -439,7 +436,7 @@ class Item implements ItemIds, \JsonSerializable{
if($display->getCount() === 0){ if($display->getCount() === 0){
$this->getNamedTag()->removeTag(self::TAG_DISPLAY); $this->getNamedTag()->removeTag(self::TAG_DISPLAY);
}else{ }else{
$this->getNamedTag()->setTag($display); $this->getNamedTag()->setTag(self::TAG_DISPLAY, $display);
} }
} }
@ -466,14 +463,14 @@ class Item implements ItemIds, \JsonSerializable{
public function setLore(array $lines) : Item{ public function setLore(array $lines) : Item{
$display = $this->getNamedTag()->getCompoundTag(self::TAG_DISPLAY); $display = $this->getNamedTag()->getCompoundTag(self::TAG_DISPLAY);
if(!($display instanceof CompoundTag)){ if(!($display instanceof CompoundTag)){
$display = new CompoundTag(self::TAG_DISPLAY, []); $display = new CompoundTag();
} }
$display->setTag(new ListTag(self::TAG_DISPLAY_LORE, array_map(function(string $str) : StringTag{ $display->setTag(self::TAG_DISPLAY_LORE, new ListTag(array_map(function(string $str) : StringTag{
return new StringTag("", $str); return new StringTag($str);
}, $lines), NBT::TAG_String)); }, $lines), NBT::TAG_String));
$this->getNamedTag()->setTag($display); $this->getNamedTag()->setTag(self::TAG_DISPLAY, $display);
return $this; return $this;
} }
@ -493,7 +490,7 @@ class Item implements ItemIds, \JsonSerializable{
* @return CompoundTag * @return CompoundTag
*/ */
public function getNamedTag() : CompoundTag{ public function getNamedTag() : CompoundTag{
return $this->nbt ?? ($this->nbt = new CompoundTag("")); return $this->nbt ?? ($this->nbt = new CompoundTag());
} }
/** /**
@ -790,7 +787,7 @@ class Item implements ItemIds, \JsonSerializable{
* @return string * @return string
*/ */
final public function __toString() : string{ final public function __toString() : string{
return "Item " . $this->name . " (" . $this->id . ":" . ($this->hasAnyDamageValue() ? "?" : $this->getMeta()) . ")x" . $this->count . ($this->hasNamedTag() ? " tags:" . base64_encode((new LittleEndianNbtSerializer())->write($this->nbt)) : ""); return "Item " . $this->name . " (" . $this->id . ":" . ($this->hasAnyDamageValue() ? "?" : $this->getMeta()) . ")x" . $this->count . ($this->hasNamedTag() ? " tags:" . base64_encode((new LittleEndianNbtSerializer())->write(new TreeRoot($this->nbt))) : "");
} }
/** /**
@ -812,7 +809,7 @@ class Item implements ItemIds, \JsonSerializable{
} }
if($this->hasNamedTag()){ if($this->hasNamedTag()){
$data["nbt_b64"] = base64_encode((new LittleEndianNbtSerializer())->write($this->getNamedTag())); $data["nbt_b64"] = base64_encode((new LittleEndianNbtSerializer())->write(new TreeRoot($this->getNamedTag())));
} }
return $data; return $data;
@ -839,7 +836,7 @@ class Item implements ItemIds, \JsonSerializable{
$nbt = base64_decode($data["nbt_b64"], true); $nbt = base64_decode($data["nbt_b64"], true);
} }
return ItemFactory::get( return ItemFactory::get(
(int) $data["id"], (int) ($data["damage"] ?? 0), (int) ($data["count"] ?? 1), $nbt !== "" ? (new LittleEndianNbtSerializer())->read($nbt) : null (int) $data["id"], (int) ($data["damage"] ?? 0), (int) ($data["count"] ?? 1), $nbt !== "" ? (new LittleEndianNbtSerializer())->read($nbt)->getTag() : null
); );
} }
@ -847,21 +844,17 @@ class Item implements ItemIds, \JsonSerializable{
* Serializes the item to an NBT CompoundTag * Serializes the item to an NBT CompoundTag
* *
* @param int $slot optional, the inventory slot of the item * @param int $slot optional, the inventory slot of the item
* @param string $tagName the name to assign to the CompoundTag object
* *
* @return CompoundTag * @return CompoundTag
*/ */
public function nbtSerialize(int $slot = -1, string $tagName = "") : CompoundTag{ public function nbtSerialize(int $slot = -1) : CompoundTag{
$result = new CompoundTag($tagName, [ $result = CompoundTag::create()
new ShortTag("id", $this->id), ->setShort("id", $this->id)
new ByteTag("Count", Binary::signByte($this->count)), ->setByte("Count", Binary::signByte($this->count))
new ShortTag("Damage", $this->getMeta()) ->setShort("Damage", $this->getMeta());
]);
if($this->hasNamedTag()){ if($this->hasNamedTag()){
$itemNBT = clone $this->getNamedTag(); $result->setTag("tag", clone $this->getNamedTag());
$itemNBT->setName("tag");
$result->setTag($itemNBT);
} }
if($slot !== -1){ if($slot !== -1){
@ -902,11 +895,8 @@ class Item implements ItemIds, \JsonSerializable{
} }
$itemNBT = $tag->getCompoundTag("tag"); $itemNBT = $tag->getCompoundTag("tag");
if($itemNBT instanceof CompoundTag){ if($itemNBT !== null){
/** @var CompoundTag $t */ $item->setNamedTag(clone $itemNBT);
$t = clone $itemNBT;
$t->setName("");
$item->setNamedTag($t);
} }
return $item; return $item;

View File

@ -26,7 +26,6 @@ namespace pocketmine\item;
use pocketmine\nbt\NBT; use pocketmine\nbt\NBT;
use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\ListTag; use pocketmine\nbt\tag\ListTag;
use pocketmine\nbt\tag\StringTag;
class WritableBook extends Item{ class WritableBook extends Item{
@ -91,7 +90,7 @@ class WritableBook extends Item{
$page = $pagesTag->get($pageId); $page = $pagesTag->get($pageId);
$page->setString(self::TAG_PAGE_TEXT, $pageText); $page->setString(self::TAG_PAGE_TEXT, $pageText);
$this->getNamedTag()->setTag($pagesTag); $this->getNamedTag()->setTag(self::TAG_PAGES, $pagesTag);
return $created; return $created;
} }
@ -110,13 +109,13 @@ class WritableBook extends Item{
$pagesTag = $this->getPagesTag(); $pagesTag = $this->getPagesTag();
for($current = $pagesTag->count(); $current <= $pageId; $current++){ for($current = $pagesTag->count(); $current <= $pageId; $current++){
$pagesTag->push(new CompoundTag("", [ $pagesTag->push(CompoundTag::create()
new StringTag(self::TAG_PAGE_TEXT, ""), ->setString(self::TAG_PAGE_TEXT, "")
new StringTag(self::TAG_PAGE_PHOTONAME, "") ->setString(self::TAG_PAGE_PHOTONAME, "")
])); );
} }
$this->getNamedTag()->setTag($pagesTag); $this->getNamedTag()->setTag(self::TAG_PAGES, $pagesTag);
} }
/** /**
@ -144,12 +143,12 @@ class WritableBook extends Item{
public function insertPage(int $pageId, string $pageText = "") : bool{ public function insertPage(int $pageId, string $pageText = "") : bool{
$pagesTag = $this->getPagesTag(); $pagesTag = $this->getPagesTag();
$pagesTag->insert($pageId, new CompoundTag("", [ $pagesTag->insert($pageId, CompoundTag::create()
new StringTag(self::TAG_PAGE_TEXT, $pageText), ->setString(self::TAG_PAGE_TEXT, $pageText)
new StringTag(self::TAG_PAGE_PHOTONAME, "") ->setString(self::TAG_PAGE_PHOTONAME, "")
])); );
$this->getNamedTag()->setTag($pagesTag); $this->getNamedTag()->setTag(self::TAG_PAGES, $pagesTag);
return true; return true;
} }
@ -194,7 +193,7 @@ class WritableBook extends Item{
} }
protected function getPagesTag() : ListTag{ protected function getPagesTag() : ListTag{
return $this->getNamedTag()->getListTag(self::TAG_PAGES) ?? new ListTag(self::TAG_PAGES, [], NBT::TAG_Compound); return $this->getNamedTag()->getListTag(self::TAG_PAGES) ?? new ListTag([], NBT::TAG_Compound);
} }
/** /**
@ -203,7 +202,7 @@ class WritableBook extends Item{
*/ */
public function setPages(array $pages) : void{ public function setPages(array $pages) : void{
$nbt = $this->getNamedTag(); $nbt = $this->getNamedTag();
$nbt->setTag(new ListTag(self::TAG_PAGES, $pages, NBT::TAG_Compound)); $nbt->setTag(self::TAG_PAGES, new ListTag($pages, NBT::TAG_Compound));
$this->setNamedTag($nbt); $this->setNamedTag($nbt);
} }
} }

View File

@ -1630,22 +1630,21 @@ class Level implements ChunkManager, Metadatable{
* @return ItemEntity|null * @return ItemEntity|null
*/ */
public function dropItem(Vector3 $source, Item $item, ?Vector3 $motion = null, int $delay = 10) : ?ItemEntity{ public function dropItem(Vector3 $source, Item $item, ?Vector3 $motion = null, int $delay = 10) : ?ItemEntity{
$motion = $motion ?? new Vector3(lcg_value() * 0.2 - 0.1, 0.2, lcg_value() * 0.2 - 0.1); if($item->isNull()){
$itemTag = $item->nbtSerialize(); return null;
$itemTag->setName("Item"); }
if(!$item->isNull()){ $motion = $motion ?? new Vector3(lcg_value() * 0.2 - 0.1, 0.2, lcg_value() * 0.2 - 0.1);
$nbt = EntityFactory::createBaseNBT($source, $motion, lcg_value() * 360, 0); $nbt = EntityFactory::createBaseNBT($source, $motion, lcg_value() * 360, 0);
$nbt->setShort("Health", 5); $nbt->setShort("Health", 5);
$nbt->setShort("PickupDelay", $delay); $nbt->setShort("PickupDelay", $delay);
$nbt->setTag($itemTag); $nbt->setTag("Item", $item->nbtSerialize());
/** @var ItemEntity $itemEntity */ /** @var ItemEntity $itemEntity */
$itemEntity = EntityFactory::create(ItemEntity::class, $this, $nbt); $itemEntity = EntityFactory::create(ItemEntity::class, $this, $nbt);
$itemEntity->spawnToAll(); $itemEntity->spawnToAll();
return $itemEntity; return $itemEntity;
}
return null;
} }
/** /**

View File

@ -29,12 +29,10 @@ use pocketmine\level\generator\Generator;
use pocketmine\level\generator\GeneratorManager; use pocketmine\level\generator\GeneratorManager;
use pocketmine\level\Level; use pocketmine\level\Level;
use pocketmine\nbt\LittleEndianNbtSerializer; use pocketmine\nbt\LittleEndianNbtSerializer;
use pocketmine\nbt\tag\ByteTag;
use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\FloatTag;
use pocketmine\nbt\tag\IntTag; use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\LongTag;
use pocketmine\nbt\tag\StringTag; use pocketmine\nbt\tag\StringTag;
use pocketmine\nbt\TreeRoot;
use pocketmine\network\mcpe\protocol\ProtocolInfo; use pocketmine\network\mcpe\protocol\ProtocolInfo;
use pocketmine\utils\Binary; use pocketmine\utils\Binary;
use pocketmine\utils\Utils; use pocketmine\utils\Utils;
@ -63,51 +61,50 @@ class BedrockLevelData extends BaseNbtLevelData{
//TODO: add support for limited worlds //TODO: add support for limited worlds
} }
$levelData = new CompoundTag("", [ $levelData = CompoundTag::create()
//Vanilla fields //Vanilla fields
new IntTag("DayCycleStopTime", -1), ->setInt("DayCycleStopTime", -1)
new IntTag("Difficulty", Level::getDifficultyFromString((string) ($options["difficulty"] ?? "normal"))), ->setInt("Difficulty", Level::getDifficultyFromString((string) ($options["difficulty"] ?? "normal")))
new ByteTag("ForceGameType", 0), ->setByte("ForceGameType", 0)
new IntTag("GameType", 0), ->setInt("GameType", 0)
new IntTag("Generator", $generatorType), ->setInt("Generator", $generatorType)
new LongTag("LastPlayed", time()), ->setLong("LastPlayed", time())
new StringTag("LevelName", $name), ->setString("LevelName", $name)
new IntTag("NetworkVersion", ProtocolInfo::CURRENT_PROTOCOL), ->setInt("NetworkVersion", ProtocolInfo::CURRENT_PROTOCOL)
//new IntTag("Platform", 2), //TODO: find out what the possible values are for //->setInt("Platform", 2) //TODO: find out what the possible values are for
new LongTag("RandomSeed", $seed), ->setLong("RandomSeed", $seed)
new IntTag("SpawnX", 0), ->setInt("SpawnX", 0)
new IntTag("SpawnY", 32767), ->setInt("SpawnY", 32767)
new IntTag("SpawnZ", 0), ->setInt("SpawnZ", 0)
new IntTag("StorageVersion", self::CURRENT_STORAGE_VERSION), ->setInt("StorageVersion", self::CURRENT_STORAGE_VERSION)
new LongTag("Time", 0), ->setLong("Time", 0)
new ByteTag("eduLevel", 0), ->setByte("eduLevel", 0)
new ByteTag("falldamage", 1), ->setByte("falldamage", 1)
new ByteTag("firedamage", 1), ->setByte("firedamage", 1)
new ByteTag("hasBeenLoadedInCreative", 1), //badly named, this actually determines whether achievements can be earned in this world... ->setByte("hasBeenLoadedInCreative", 1) //badly named, this actually determines whether achievements can be earned in this world...
new ByteTag("immutableWorld", 0), ->setByte("immutableWorld", 0)
new FloatTag("lightningLevel", 0.0), ->setFloat("lightningLevel", 0.0)
new IntTag("lightningTime", 0), ->setInt("lightningTime", 0)
new ByteTag("pvp", 1), ->setByte("pvp", 1)
new FloatTag("rainLevel", 0.0), ->setFloat("rainLevel", 0.0)
new IntTag("rainTime", 0), ->setInt("rainTime", 0)
new ByteTag("spawnMobs", 1), ->setByte("spawnMobs", 1)
new ByteTag("texturePacksRequired", 0), //TODO ->setByte("texturePacksRequired", 0) //TODO
//Additional PocketMine-MP fields //Additional PocketMine-MP fields
new CompoundTag("GameRules", []), ->setTag("GameRules", new CompoundTag())
new ByteTag("hardcore", ($options["hardcore"] ?? false) === true ? 1 : 0), ->setByte("hardcore", ($options["hardcore"] ?? false) === true ? 1 : 0)
new StringTag("generatorName", GeneratorManager::getGeneratorName($generator)), ->setString("generatorName", GeneratorManager::getGeneratorName($generator))
new StringTag("generatorOptions", $options["preset"] ?? "") ->setString("generatorOptions", $options["preset"] ?? "");
]);
$nbt = new LittleEndianNbtSerializer(); $nbt = new LittleEndianNbtSerializer();
$buffer = $nbt->write($levelData); $buffer = $nbt->write(new TreeRoot($levelData));
file_put_contents($path . "level.dat", Binary::writeLInt(self::CURRENT_STORAGE_VERSION) . Binary::writeLInt(strlen($buffer)) . $buffer); file_put_contents($path . "level.dat", Binary::writeLInt(self::CURRENT_STORAGE_VERSION) . Binary::writeLInt(strlen($buffer)) . $buffer);
} }
protected function load() : ?CompoundTag{ protected function load() : ?CompoundTag{
$nbt = new LittleEndianNbtSerializer(); $nbt = new LittleEndianNbtSerializer();
$levelData = $nbt->read(substr(file_get_contents($this->dataPath), 8)); $levelData = $nbt->read(substr(file_get_contents($this->dataPath), 8))->getTag();
$version = $levelData->getInt("StorageVersion", INT32_MAX, true); $version = $levelData->getInt("StorageVersion", INT32_MAX, true);
if($version > self::CURRENT_STORAGE_VERSION){ if($version > self::CURRENT_STORAGE_VERSION){
@ -152,7 +149,7 @@ class BedrockLevelData extends BaseNbtLevelData{
$this->compoundTag->setInt("StorageVersion", self::CURRENT_STORAGE_VERSION); $this->compoundTag->setInt("StorageVersion", self::CURRENT_STORAGE_VERSION);
$nbt = new LittleEndianNbtSerializer(); $nbt = new LittleEndianNbtSerializer();
$buffer = $nbt->write($this->compoundTag); $buffer = $nbt->write(new TreeRoot($this->compoundTag));
file_put_contents($this->dataPath, Binary::writeLInt(self::CURRENT_STORAGE_VERSION) . Binary::writeLInt(strlen($buffer)) . $buffer); file_put_contents($this->dataPath, Binary::writeLInt(self::CURRENT_STORAGE_VERSION) . Binary::writeLInt(strlen($buffer)) . $buffer);
} }

View File

@ -27,12 +27,10 @@ use pocketmine\level\generator\Generator;
use pocketmine\level\generator\GeneratorManager; use pocketmine\level\generator\GeneratorManager;
use pocketmine\level\Level; use pocketmine\level\Level;
use pocketmine\nbt\BigEndianNbtSerializer; use pocketmine\nbt\BigEndianNbtSerializer;
use pocketmine\nbt\tag\ByteTag;
use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\FloatTag; use pocketmine\nbt\tag\FloatTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\LongTag;
use pocketmine\nbt\tag\StringTag; use pocketmine\nbt\tag\StringTag;
use pocketmine\nbt\TreeRoot;
use pocketmine\utils\Utils; use pocketmine\utils\Utils;
use function ceil; use function ceil;
use function file_get_contents; use function file_get_contents;
@ -44,36 +42,34 @@ class JavaLevelData extends BaseNbtLevelData{
public static function generate(string $path, string $name, int $seed, string $generator, array $options = [], int $version = 19133) : void{ public static function generate(string $path, string $name, int $seed, string $generator, array $options = [], int $version = 19133) : void{
Utils::testValidInstance($generator, Generator::class); Utils::testValidInstance($generator, Generator::class);
//TODO, add extra details //TODO, add extra details
$levelData = new CompoundTag("Data", [ $levelData = CompoundTag::create()
new ByteTag("hardcore", ($options["hardcore"] ?? false) === true ? 1 : 0), ->setByte("hardcore", ($options["hardcore"] ?? false) === true ? 1 : 0)
new ByteTag("Difficulty", Level::getDifficultyFromString((string) ($options["difficulty"] ?? "normal"))), ->setByte("Difficulty", Level::getDifficultyFromString((string) ($options["difficulty"] ?? "normal")))
new ByteTag("initialized", 1), ->setByte("initialized", 1)
new IntTag("GameType", 0), ->setInt("GameType", 0)
new IntTag("generatorVersion", 1), //2 in MCPE ->setInt("generatorVersion", 1) //2 in MCPE
new IntTag("SpawnX", 256), ->setInt("SpawnX", 256)
new IntTag("SpawnY", 70), ->setInt("SpawnY", 70)
new IntTag("SpawnZ", 256), ->setInt("SpawnZ", 256)
new IntTag("version", $version), ->setInt("version", $version)
new IntTag("DayTime", 0), ->setInt("DayTime", 0)
new LongTag("LastPlayed", (int) (microtime(true) * 1000)), ->setLong("LastPlayed", (int) (microtime(true) * 1000))
new LongTag("RandomSeed", $seed), ->setLong("RandomSeed", $seed)
new LongTag("SizeOnDisk", 0), ->setLong("SizeOnDisk", 0)
new LongTag("Time", 0), ->setLong("Time", 0)
new StringTag("generatorName", GeneratorManager::getGeneratorName($generator)), ->setString("generatorName", GeneratorManager::getGeneratorName($generator))
new StringTag("generatorOptions", $options["preset"] ?? ""), ->setString("generatorOptions", $options["preset"] ?? "")
new StringTag("LevelName", $name), ->setString("LevelName", $name)
new CompoundTag("GameRules", []) ->setTag("GameRules", new CompoundTag());
]);
$nbt = new BigEndianNbtSerializer(); $nbt = new BigEndianNbtSerializer();
$buffer = $nbt->writeCompressed(new CompoundTag("", [ $buffer = $nbt->writeCompressed(new TreeRoot(CompoundTag::create()->setTag("Data", $levelData)));
$levelData
]));
file_put_contents($path . "level.dat", $buffer); file_put_contents($path . "level.dat", $buffer);
} }
protected function load() : ?CompoundTag{ protected function load() : ?CompoundTag{
$nbt = new BigEndianNbtSerializer(); $nbt = new BigEndianNbtSerializer();
$levelData = $nbt->readCompressed(file_get_contents($this->dataPath)); $levelData = $nbt->readCompressed(file_get_contents($this->dataPath))->getTag();
if($levelData->hasTag("Data", CompoundTag::class)){ if($levelData->hasTag("Data", CompoundTag::class)){
return $levelData->getCompoundTag("Data"); return $levelData->getCompoundTag("Data");
} }
@ -94,10 +90,7 @@ class JavaLevelData extends BaseNbtLevelData{
public function save() : void{ public function save() : void{
$nbt = new BigEndianNbtSerializer(); $nbt = new BigEndianNbtSerializer();
$this->compoundTag->setName("Data"); $buffer = $nbt->writeCompressed(new TreeRoot(CompoundTag::create()->setTag("Data", $this->compoundTag)));
$buffer = $nbt->writeCompressed(new CompoundTag("", [
$this->compoundTag
]));
file_put_contents($this->dataPath, $buffer); file_put_contents($this->dataPath, $buffer);
} }

View File

@ -40,14 +40,13 @@ use pocketmine\level\generator\Generator;
use pocketmine\nbt\LittleEndianNbtSerializer; use pocketmine\nbt\LittleEndianNbtSerializer;
use pocketmine\nbt\NbtDataException; use pocketmine\nbt\NbtDataException;
use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\IntTag; use pocketmine\nbt\TreeRoot;
use pocketmine\nbt\tag\ShortTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\utils\Binary; use pocketmine\utils\Binary;
use pocketmine\utils\BinaryDataException; use pocketmine\utils\BinaryDataException;
use pocketmine\utils\BinaryStream; use pocketmine\utils\BinaryStream;
use pocketmine\utils\Utils; use pocketmine\utils\Utils;
use function array_flip; use function array_flip;
use function array_map;
use function array_values; use function array_values;
use function chr; use function chr;
use function count; use function count;
@ -159,7 +158,7 @@ class LevelDB extends BaseLevelProvider implements WritableLevelProvider{
$palette = []; $palette = [];
for($i = 0, $paletteSize = $stream->getLInt(); $i < $paletteSize; ++$i){ for($i = 0, $paletteSize = $stream->getLInt(); $i < $paletteSize; ++$i){
$offset = $stream->getOffset(); $offset = $stream->getOffset();
$tag = $nbt->read($stream->getBuffer(), $offset); $tag = $nbt->read($stream->getBuffer(), $offset)->getTag();
$stream->setOffset($offset); $stream->setOffset($offset);
$id = $stringToLegacyId[$tag->getString("name")] ?? BlockIds::INFO_UPDATE; $id = $stringToLegacyId[$tag->getString("name")] ?? BlockIds::INFO_UPDATE;
@ -303,7 +302,7 @@ class LevelDB extends BaseLevelProvider implements WritableLevelProvider{
$entities = []; $entities = [];
if(($entityData = $this->db->get($index . self::TAG_ENTITY)) !== false and $entityData !== ""){ if(($entityData = $this->db->get($index . self::TAG_ENTITY)) !== false and $entityData !== ""){
try{ try{
$entities = $nbt->readMultiple($entityData); $entities = array_map(function(TreeRoot $root) : CompoundTag{ return $root->getTag(); }, $nbt->readMultiple($entityData));
}catch(NbtDataException $e){ }catch(NbtDataException $e){
throw new CorruptedChunkException($e->getMessage(), 0, $e); throw new CorruptedChunkException($e->getMessage(), 0, $e);
} }
@ -313,7 +312,7 @@ class LevelDB extends BaseLevelProvider implements WritableLevelProvider{
$tiles = []; $tiles = [];
if(($tileData = $this->db->get($index . self::TAG_BLOCK_ENTITY)) !== false and $tileData !== ""){ if(($tileData = $this->db->get($index . self::TAG_BLOCK_ENTITY)) !== false and $tileData !== ""){
try{ try{
$tiles = $nbt->readMultiple($tileData); $tiles = array_map(function(TreeRoot $root) : CompoundTag{ return $root->getTag(); }, $nbt->readMultiple($tileData));
}catch(NbtDataException $e){ }catch(NbtDataException $e){
throw new CorruptedChunkException($e->getMessage(), 0, $e); throw new CorruptedChunkException($e->getMessage(), 0, $e);
} }
@ -379,11 +378,10 @@ class LevelDB extends BaseLevelProvider implements WritableLevelProvider{
$subStream->putLInt(count($palette)); $subStream->putLInt(count($palette));
$tags = []; $tags = [];
foreach($palette as $p){ foreach($palette as $p){
$tags[] = new CompoundTag("", [ $tags[] = new TreeRoot(CompoundTag::create()
new StringTag("name", $idMap[$p >> 4] ?? "minecraft:info_update"), ->setString("name", $idMap[$p >> 4] ?? "minecraft:info_update")
new IntTag("oldid", $p >> 4), //PM only (debugging), vanilla doesn't have this ->setInt("oldid", $p >> 4) //PM only (debugging), vanilla doesn't have this
new ShortTag("val", $p & 0xf) ->setShort("val", $p & 0xf));
]);
} }
$subStream->put((new LittleEndianNbtSerializer())->writeMultiple($tags)); $subStream->put((new LittleEndianNbtSerializer())->writeMultiple($tags));
@ -415,7 +413,7 @@ class LevelDB extends BaseLevelProvider implements WritableLevelProvider{
private function writeTags(array $targets, string $index, \LevelDBWriteBatch $write) : void{ private function writeTags(array $targets, string $index, \LevelDBWriteBatch $write) : void{
if(!empty($targets)){ if(!empty($targets)){
$nbt = new LittleEndianNbtSerializer(); $nbt = new LittleEndianNbtSerializer();
$write->put($index, $nbt->writeMultiple($targets)); $write->put($index, $nbt->writeMultiple(array_map(function(CompoundTag $tag) : TreeRoot{ return new TreeRoot($tag); }, $targets)));
}else{ }else{
$write->delete($index); $write->delete($index);
} }

View File

@ -59,7 +59,7 @@ trait LegacyAnvilChunkTrait{
protected function deserializeChunk(string $data) : Chunk{ protected function deserializeChunk(string $data) : Chunk{
$nbt = new BigEndianNbtSerializer(); $nbt = new BigEndianNbtSerializer();
try{ try{
$chunk = $nbt->readCompressed($data); $chunk = $nbt->readCompressed($data)->getTag();
}catch(NbtDataException $e){ }catch(NbtDataException $e){
throw new CorruptedChunkException($e->getMessage(), 0, $e); throw new CorruptedChunkException($e->getMessage(), 0, $e);
} }

View File

@ -56,7 +56,7 @@ class McRegion extends RegionLevelProvider{
protected function deserializeChunk(string $data) : Chunk{ protected function deserializeChunk(string $data) : Chunk{
$nbt = new BigEndianNbtSerializer(); $nbt = new BigEndianNbtSerializer();
try{ try{
$chunk = $nbt->readCompressed($data); $chunk = $nbt->readCompressed($data)->getTag();
}catch(NbtDataException $e){ }catch(NbtDataException $e){
throw new CorruptedChunkException($e->getMessage(), 0, $e); throw new CorruptedChunkException($e->getMessage(), 0, $e);
} }

View File

@ -31,6 +31,8 @@ use pocketmine\item\Item;
use pocketmine\item\ItemFactory; use pocketmine\item\ItemFactory;
use pocketmine\item\ItemIds; use pocketmine\item\ItemIds;
use pocketmine\math\Vector3; use pocketmine\math\Vector3;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\TreeRoot;
use pocketmine\network\BadPacketException; use pocketmine\network\BadPacketException;
use pocketmine\network\mcpe\protocol\types\CommandOriginData; use pocketmine\network\mcpe\protocol\types\CommandOriginData;
use pocketmine\network\mcpe\protocol\types\EntityLink; use pocketmine\network\mcpe\protocol\types\EntityLink;
@ -96,13 +98,14 @@ class NetworkBinaryStream extends BinaryStream{
$cnt = $auxValue & 0xff; $cnt = $auxValue & 0xff;
$nbtLen = $this->getLShort(); $nbtLen = $this->getLShort();
/** @var CompoundTag|null $compound */
$compound = null; $compound = null;
if($nbtLen === 0xffff){ if($nbtLen === 0xffff){
$c = $this->getByte(); $c = $this->getByte();
if($c !== 1){ if($c !== 1){
throw new BadPacketException("Unexpected NBT count $c"); throw new BadPacketException("Unexpected NBT count $c");
} }
$compound = (new NetworkNbtSerializer())->read($this->buffer, $this->offset); $compound = (new NetworkNbtSerializer())->read($this->buffer, $this->offset)->getTag();
}elseif($nbtLen !== 0){ }elseif($nbtLen !== 0){
throw new BadPacketException("Unexpected fake NBT length $nbtLen"); throw new BadPacketException("Unexpected fake NBT length $nbtLen");
} }
@ -143,7 +146,7 @@ class NetworkBinaryStream extends BinaryStream{
if($item->hasNamedTag()){ if($item->hasNamedTag()){
$this->putLShort(0xffff); $this->putLShort(0xffff);
$this->putByte(1); //TODO: some kind of count field? always 1 as of 1.9.0 $this->putByte(1); //TODO: some kind of count field? always 1 as of 1.9.0
$this->put((new NetworkNbtSerializer())->write($item->getNamedTag())); $this->put((new NetworkNbtSerializer())->write(new TreeRoot($item->getNamedTag())));
}else{ }else{
$this->putLShort(0); $this->putLShort(0);
} }

View File

@ -398,7 +398,7 @@ class SimpleSessionHandler extends SessionHandler{
$block = $this->player->getLevel()->getBlock($pos); $block = $this->player->getLevel()->getBlock($pos);
try{ try{
$nbt = (new NetworkNbtSerializer())->read($packet->namedtag); $nbt = (new NetworkNbtSerializer())->read($packet->namedtag)->getTag();
}catch(NbtDataException $e){ }catch(NbtDataException $e){
throw new BadPacketException($e->getMessage(), 0, $e); throw new BadPacketException($e->getMessage(), 0, $e);
} }

View File

@ -31,7 +31,6 @@ use pocketmine\math\Vector3;
use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\IntTag; use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\ListTag; use pocketmine\nbt\tag\ListTag;
use pocketmine\nbt\tag\StringTag;
/** /**
* @deprecated * @deprecated
@ -72,26 +71,26 @@ class Banner extends Spawnable{
protected function writeSaveData(CompoundTag $nbt) : void{ protected function writeSaveData(CompoundTag $nbt) : void{
$nbt->setInt(self::TAG_BASE, $this->baseColor->getInvertedMagicNumber()); $nbt->setInt(self::TAG_BASE, $this->baseColor->getInvertedMagicNumber());
$patterns = new ListTag(self::TAG_PATTERNS); $patterns = new ListTag();
foreach($this->patterns as $pattern){ foreach($this->patterns as $pattern){
$patterns->push(new CompoundTag("", [ $patterns->push(CompoundTag::create()
new StringTag(self::TAG_PATTERN_NAME, $pattern->getId()), ->setString(self::TAG_PATTERN_NAME, $pattern->getId())
new IntTag(self::TAG_PATTERN_COLOR, $pattern->getColor()->getInvertedMagicNumber()) ->setInt(self::TAG_PATTERN_COLOR, $pattern->getColor()->getInvertedMagicNumber())
])); );
} }
$nbt->setTag($patterns); $nbt->setTag(self::TAG_PATTERNS, $patterns);
} }
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{ protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
$nbt->setInt(self::TAG_BASE, $this->baseColor->getInvertedMagicNumber()); $nbt->setInt(self::TAG_BASE, $this->baseColor->getInvertedMagicNumber());
$patterns = new ListTag(self::TAG_PATTERNS); $patterns = new ListTag();
foreach($this->patterns as $pattern){ foreach($this->patterns as $pattern){
$patterns->push(new CompoundTag("", [ $patterns->push(CompoundTag::create()
new StringTag(self::TAG_PATTERN_NAME, $pattern->getId()), ->setString(self::TAG_PATTERN_NAME, $pattern->getId())
new IntTag(self::TAG_PATTERN_COLOR, $pattern->getColor()->getInvertedMagicNumber()) ->setInt(self::TAG_PATTERN_COLOR, $pattern->getColor()->getInvertedMagicNumber())
])); );
} }
$nbt->setTag($patterns); $nbt->setTag(self::TAG_PATTERNS, $patterns);
} }
/** /**

View File

@ -69,7 +69,7 @@ trait ContainerTrait{
$items[] = $item->nbtSerialize($slot); $items[] = $item->nbtSerialize($slot);
} }
$tag->setTag(new ListTag(Container::TAG_ITEMS, $items, NBT::TAG_Compound)); $tag->setTag(Container::TAG_ITEMS, new ListTag($items, NBT::TAG_Compound));
if($this->lock !== null){ if($this->lock !== null){
$tag->setString(Container::TAG_LOCK, $this->lock); $tag->setString(Container::TAG_LOCK, $this->lock);

View File

@ -61,7 +61,7 @@ class ItemFrame extends Spawnable{
protected function writeSaveData(CompoundTag $nbt) : void{ protected function writeSaveData(CompoundTag $nbt) : void{
$nbt->setFloat(self::TAG_ITEM_DROP_CHANCE, $this->itemDropChance); $nbt->setFloat(self::TAG_ITEM_DROP_CHANCE, $this->itemDropChance);
$nbt->setByte(self::TAG_ITEM_ROTATION, $this->itemRotation); $nbt->setByte(self::TAG_ITEM_ROTATION, $this->itemRotation);
$nbt->setTag($this->item->nbtSerialize(-1, self::TAG_ITEM)); $nbt->setTag(self::TAG_ITEM, $this->item->nbtSerialize());
} }
public function hasItem() : bool{ public function hasItem() : bool{
@ -102,6 +102,6 @@ class ItemFrame extends Spawnable{
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{ protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
$nbt->setFloat(self::TAG_ITEM_DROP_CHANCE, $this->itemDropChance); $nbt->setFloat(self::TAG_ITEM_DROP_CHANCE, $this->itemDropChance);
$nbt->setByte(self::TAG_ITEM_ROTATION, $this->itemRotation); $nbt->setByte(self::TAG_ITEM_ROTATION, $this->itemRotation);
$nbt->setTag($this->item->nbtSerialize(-1, self::TAG_ITEM)); $nbt->setTag(self::TAG_ITEM, $this->item->nbtSerialize());
} }
} }

View File

@ -24,8 +24,7 @@ declare(strict_types=1);
namespace pocketmine\tile; namespace pocketmine\tile;
use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\IntTag; use pocketmine\nbt\TreeRoot;
use pocketmine\nbt\tag\StringTag;
use pocketmine\network\mcpe\NetworkNbtSerializer; use pocketmine\network\mcpe\NetworkNbtSerializer;
use function get_class; use function get_class;
@ -76,7 +75,7 @@ abstract class Spawnable extends Tile{
self::$nbtWriter = new NetworkNbtSerializer(); self::$nbtWriter = new NetworkNbtSerializer();
} }
$this->spawnCompoundCache = self::$nbtWriter->write($this->getSpawnCompound()); $this->spawnCompoundCache = self::$nbtWriter->write(new TreeRoot($this->getSpawnCompound()));
} }
return $this->spawnCompoundCache; return $this->spawnCompoundCache;
@ -86,12 +85,11 @@ abstract class Spawnable extends Tile{
* @return CompoundTag * @return CompoundTag
*/ */
final public function getSpawnCompound() : CompoundTag{ final public function getSpawnCompound() : CompoundTag{
$nbt = new CompoundTag("", [ $nbt = CompoundTag::create()
new StringTag(self::TAG_ID, TileFactory::getSaveId(get_class($this))), //TODO: disassociate network ID from save ID ->setString(self::TAG_ID, TileFactory::getSaveId(get_class($this))) //TODO: disassociate network ID from save ID
new IntTag(self::TAG_X, $this->x), ->setInt(self::TAG_X, $this->x)
new IntTag(self::TAG_Y, $this->y), ->setInt(self::TAG_Y, $this->y)
new IntTag(self::TAG_Z, $this->z) ->setInt(self::TAG_Z, $this->z);
]);
$this->addAdditionalSpawnData($nbt); $this->addAdditionalSpawnData($nbt);
return $nbt; return $nbt;
} }

View File

@ -72,18 +72,18 @@ abstract class Tile extends Position{
abstract protected function writeSaveData(CompoundTag $nbt) : void; abstract protected function writeSaveData(CompoundTag $nbt) : void;
public function saveNBT() : CompoundTag{ public function saveNBT() : CompoundTag{
$nbt = new CompoundTag(""); $nbt = CompoundTag::create()
$nbt->setString(self::TAG_ID, TileFactory::getSaveId(get_class($this))); ->setString(self::TAG_ID, TileFactory::getSaveId(get_class($this)))
$nbt->setInt(self::TAG_X, $this->x); ->setInt(self::TAG_X, $this->x)
$nbt->setInt(self::TAG_Y, $this->y); ->setInt(self::TAG_Y, $this->y)
$nbt->setInt(self::TAG_Z, $this->z); ->setInt(self::TAG_Z, $this->z);
$this->writeSaveData($nbt); $this->writeSaveData($nbt);
return $nbt; return $nbt;
} }
public function getCleanedNBT() : ?CompoundTag{ public function getCleanedNBT() : ?CompoundTag{
$this->writeSaveData($tag = new CompoundTag("")); $this->writeSaveData($tag = new CompoundTag());
return $tag->getCount() > 0 ? $tag : null; return $tag->getCount() > 0 ? $tag : null;
} }