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": {
"type": "git",
"url": "https://github.com/pmmp/NBT.git",
"reference": "cb170cf827e265cfb492de2af684cba23574dfec"
"reference": "772f627884c92beb750cc1c50a8d25f155a9c006"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/NBT/zipball/cb170cf827e265cfb492de2af684cba23574dfec",
"reference": "cb170cf827e265cfb492de2af684cba23574dfec",
"url": "https://api.github.com/repos/pmmp/NBT/zipball/772f627884c92beb750cc1c50a8d25f155a9c006",
"reference": "772f627884c92beb750cc1c50a8d25f155a9c006",
"shasum": ""
},
"require": {
@ -405,7 +405,7 @@
"source": "https://github.com/pmmp/NBT/tree/master",
"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",

View File

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

View File

@ -61,6 +61,7 @@ use pocketmine\metadata\PlayerMetadataStore;
use pocketmine\nbt\BigEndianNbtSerializer;
use pocketmine\nbt\NbtDataException;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\TreeRoot;
use pocketmine\network\AdvancedNetworkInterface;
use pocketmine\network\mcpe\CompressBatchPromise;
use pocketmine\network\mcpe\CompressBatchTask;
@ -645,7 +646,7 @@ class Server{
if(file_exists($path . "$name.dat")){
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
rename($path . "$name.dat", $path . "$name.dat.bak");
$this->logger->error($this->getLanguage()->translateString("pocketmine.data.playerCorrupted", [$name]));
@ -667,7 +668,7 @@ class Server{
if(!$ev->isCancelled()){
$nbt = new BigEndianNbtSerializer();
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){
$this->logger->critical($this->getLanguage()->translateString("pocketmine.data.saveError", [$name, $e->getMessage()]));
$this->logger->logException($e);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -26,7 +26,6 @@ namespace pocketmine\item;
use pocketmine\nbt\NBT;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\ListTag;
use pocketmine\nbt\tag\StringTag;
class WritableBook extends Item{
@ -91,7 +90,7 @@ class WritableBook extends Item{
$page = $pagesTag->get($pageId);
$page->setString(self::TAG_PAGE_TEXT, $pageText);
$this->getNamedTag()->setTag($pagesTag);
$this->getNamedTag()->setTag(self::TAG_PAGES, $pagesTag);
return $created;
}
@ -110,13 +109,13 @@ class WritableBook extends Item{
$pagesTag = $this->getPagesTag();
for($current = $pagesTag->count(); $current <= $pageId; $current++){
$pagesTag->push(new CompoundTag("", [
new StringTag(self::TAG_PAGE_TEXT, ""),
new StringTag(self::TAG_PAGE_PHOTONAME, "")
]));
$pagesTag->push(CompoundTag::create()
->setString(self::TAG_PAGE_TEXT, "")
->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{
$pagesTag = $this->getPagesTag();
$pagesTag->insert($pageId, new CompoundTag("", [
new StringTag(self::TAG_PAGE_TEXT, $pageText),
new StringTag(self::TAG_PAGE_PHOTONAME, "")
]));
$pagesTag->insert($pageId, CompoundTag::create()
->setString(self::TAG_PAGE_TEXT, $pageText)
->setString(self::TAG_PAGE_PHOTONAME, "")
);
$this->getNamedTag()->setTag($pagesTag);
$this->getNamedTag()->setTag(self::TAG_PAGES, $pagesTag);
return true;
}
@ -194,7 +193,7 @@ class WritableBook extends Item{
}
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{
$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);
}
}

View File

@ -1630,22 +1630,21 @@ class Level implements ChunkManager, Metadatable{
* @return ItemEntity|null
*/
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);
$itemTag = $item->nbtSerialize();
$itemTag->setName("Item");
if(!$item->isNull()){
$nbt = EntityFactory::createBaseNBT($source, $motion, lcg_value() * 360, 0);
$nbt->setShort("Health", 5);
$nbt->setShort("PickupDelay", $delay);
$nbt->setTag($itemTag);
/** @var ItemEntity $itemEntity */
$itemEntity = EntityFactory::create(ItemEntity::class, $this, $nbt);
$itemEntity->spawnToAll();
return $itemEntity;
if($item->isNull()){
return null;
}
return null;
$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->setShort("Health", 5);
$nbt->setShort("PickupDelay", $delay);
$nbt->setTag("Item", $item->nbtSerialize());
/** @var ItemEntity $itemEntity */
$itemEntity = EntityFactory::create(ItemEntity::class, $this, $nbt);
$itemEntity->spawnToAll();
return $itemEntity;
}
/**

View File

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

View File

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

View File

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

View File

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

View File

@ -56,7 +56,7 @@ class McRegion extends RegionLevelProvider{
protected function deserializeChunk(string $data) : Chunk{
$nbt = new BigEndianNbtSerializer();
try{
$chunk = $nbt->readCompressed($data);
$chunk = $nbt->readCompressed($data)->getTag();
}catch(NbtDataException $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\ItemIds;
use pocketmine\math\Vector3;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\TreeRoot;
use pocketmine\network\BadPacketException;
use pocketmine\network\mcpe\protocol\types\CommandOriginData;
use pocketmine\network\mcpe\protocol\types\EntityLink;
@ -96,13 +98,14 @@ class NetworkBinaryStream extends BinaryStream{
$cnt = $auxValue & 0xff;
$nbtLen = $this->getLShort();
/** @var CompoundTag|null $compound */
$compound = null;
if($nbtLen === 0xffff){
$c = $this->getByte();
if($c !== 1){
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){
throw new BadPacketException("Unexpected fake NBT length $nbtLen");
}
@ -143,7 +146,7 @@ class NetworkBinaryStream extends BinaryStream{
if($item->hasNamedTag()){
$this->putLShort(0xffff);
$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{
$this->putLShort(0);
}

View File

@ -398,7 +398,7 @@ class SimpleSessionHandler extends SessionHandler{
$block = $this->player->getLevel()->getBlock($pos);
try{
$nbt = (new NetworkNbtSerializer())->read($packet->namedtag);
$nbt = (new NetworkNbtSerializer())->read($packet->namedtag)->getTag();
}catch(NbtDataException $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\IntTag;
use pocketmine\nbt\tag\ListTag;
use pocketmine\nbt\tag\StringTag;
/**
* @deprecated
@ -72,26 +71,26 @@ class Banner extends Spawnable{
protected function writeSaveData(CompoundTag $nbt) : void{
$nbt->setInt(self::TAG_BASE, $this->baseColor->getInvertedMagicNumber());
$patterns = new ListTag(self::TAG_PATTERNS);
$patterns = new ListTag();
foreach($this->patterns as $pattern){
$patterns->push(new CompoundTag("", [
new StringTag(self::TAG_PATTERN_NAME, $pattern->getId()),
new IntTag(self::TAG_PATTERN_COLOR, $pattern->getColor()->getInvertedMagicNumber())
]));
$patterns->push(CompoundTag::create()
->setString(self::TAG_PATTERN_NAME, $pattern->getId())
->setInt(self::TAG_PATTERN_COLOR, $pattern->getColor()->getInvertedMagicNumber())
);
}
$nbt->setTag($patterns);
$nbt->setTag(self::TAG_PATTERNS, $patterns);
}
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
$nbt->setInt(self::TAG_BASE, $this->baseColor->getInvertedMagicNumber());
$patterns = new ListTag(self::TAG_PATTERNS);
$patterns = new ListTag();
foreach($this->patterns as $pattern){
$patterns->push(new CompoundTag("", [
new StringTag(self::TAG_PATTERN_NAME, $pattern->getId()),
new IntTag(self::TAG_PATTERN_COLOR, $pattern->getColor()->getInvertedMagicNumber())
]));
$patterns->push(CompoundTag::create()
->setString(self::TAG_PATTERN_NAME, $pattern->getId())
->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);
}
$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){
$tag->setString(Container::TAG_LOCK, $this->lock);

View File

@ -61,7 +61,7 @@ class ItemFrame extends Spawnable{
protected function writeSaveData(CompoundTag $nbt) : void{
$nbt->setFloat(self::TAG_ITEM_DROP_CHANCE, $this->itemDropChance);
$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{
@ -102,6 +102,6 @@ class ItemFrame extends Spawnable{
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
$nbt->setFloat(self::TAG_ITEM_DROP_CHANCE, $this->itemDropChance);
$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;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\nbt\TreeRoot;
use pocketmine\network\mcpe\NetworkNbtSerializer;
use function get_class;
@ -76,7 +75,7 @@ abstract class Spawnable extends Tile{
self::$nbtWriter = new NetworkNbtSerializer();
}
$this->spawnCompoundCache = self::$nbtWriter->write($this->getSpawnCompound());
$this->spawnCompoundCache = self::$nbtWriter->write(new TreeRoot($this->getSpawnCompound()));
}
return $this->spawnCompoundCache;
@ -86,12 +85,11 @@ abstract class Spawnable extends Tile{
* @return CompoundTag
*/
final public function getSpawnCompound() : CompoundTag{
$nbt = new CompoundTag("", [
new StringTag(self::TAG_ID, TileFactory::getSaveId(get_class($this))), //TODO: disassociate network ID from save ID
new IntTag(self::TAG_X, $this->x),
new IntTag(self::TAG_Y, $this->y),
new IntTag(self::TAG_Z, $this->z)
]);
$nbt = CompoundTag::create()
->setString(self::TAG_ID, TileFactory::getSaveId(get_class($this))) //TODO: disassociate network ID from save ID
->setInt(self::TAG_X, $this->x)
->setInt(self::TAG_Y, $this->y)
->setInt(self::TAG_Z, $this->z);
$this->addAdditionalSpawnData($nbt);
return $nbt;
}

View File

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