From fa21cd96c570a19dd4db3204779e24a163652f28 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sun, 3 Jun 2018 18:29:08 +0100 Subject: [PATCH] Tiles no longer store their NBT at runtime This is a significant breaking change for anything utilizing Tiles as they now do not store their NBT at runtime anymore. This is another step in the process of ridding PocketMine-MP of runtime NBT. It can be noticed that all tiles are now using class fields to store properties instead of NBT, which is much faster, uses less memory and is also more concise when written in code. Highlights: - Tile->namedtag has been removed. - Tile->saveNBT() now accepts a CompoundTag() parameter. Typically it's expected that this will be fed a newly-created CompoundTag (this part may be improved in the future). - New internal methods Tile->readSaveData() and Tile->writeSaveData() have been added. Instead of overriding __construct() and saveNBT() to load and save properties from NBT, you should now implement these methods instead. This is not final and will see further changes before it's done. --- .../level/format/io/leveldb/LevelDB.php | 4 +- .../level/format/io/region/Anvil.php | 4 +- .../level/format/io/region/McRegion.php | 4 +- src/pocketmine/tile/Banner.php | 14 +++--- src/pocketmine/tile/Bed.php | 19 +++----- src/pocketmine/tile/Chest.php | 30 +++++-------- src/pocketmine/tile/EnchantTable.php | 16 ++----- src/pocketmine/tile/EnderChest.php | 8 ++++ src/pocketmine/tile/FlowerPot.php | 13 ++---- src/pocketmine/tile/Furnace.php | 31 +++++++------ src/pocketmine/tile/ItemFrame.php | 15 +++---- src/pocketmine/tile/Sign.php | 12 ++--- src/pocketmine/tile/Skull.php | 12 ++--- src/pocketmine/tile/Tile.php | 45 ++++++++++--------- 14 files changed, 96 insertions(+), 131 deletions(-) diff --git a/src/pocketmine/level/format/io/leveldb/LevelDB.php b/src/pocketmine/level/format/io/leveldb/LevelDB.php index a63f58a43..53dd2af77 100644 --- a/src/pocketmine/level/format/io/leveldb/LevelDB.php +++ b/src/pocketmine/level/format/io/leveldb/LevelDB.php @@ -456,8 +456,8 @@ class LevelDB extends BaseLevelProvider{ $tiles = []; foreach($chunk->getTiles() as $tile){ if(!$tile->isClosed()){ - $tile->saveNBT(); - $tiles[] = $tile->namedtag; + $tile->saveNBT($tileTag = new CompoundTag()); + $tiles[] = $tileTag; } } $this->writeTags($tiles, $index . self::TAG_BLOCK_ENTITY); diff --git a/src/pocketmine/level/format/io/region/Anvil.php b/src/pocketmine/level/format/io/region/Anvil.php index 7f9bc3208..5a7a63c1d 100644 --- a/src/pocketmine/level/format/io/region/Anvil.php +++ b/src/pocketmine/level/format/io/region/Anvil.php @@ -75,8 +75,8 @@ class Anvil extends McRegion{ $tiles = []; foreach($chunk->getTiles() as $tile){ - $tile->saveNBT(); - $tiles[] = $tile->namedtag; + $tile->saveNBT($tileTag = new CompoundTag()); + $tiles[] = $tileTag; } $nbt->setTag(new ListTag("TileEntities", $tiles, NBT::TAG_Compound)); diff --git a/src/pocketmine/level/format/io/region/McRegion.php b/src/pocketmine/level/format/io/region/McRegion.php index b83124ede..6c98dc67d 100644 --- a/src/pocketmine/level/format/io/region/McRegion.php +++ b/src/pocketmine/level/format/io/region/McRegion.php @@ -94,8 +94,8 @@ class McRegion extends BaseLevelProvider{ $tiles = []; foreach($chunk->getTiles() as $tile){ - $tile->saveNBT(); - $tiles[] = $tile->namedtag; + $tile->saveNBT($tileTag = new CompoundTag()); + $tiles[] = $tileTag; } $nbt->setTag(new ListTag("TileEntities", $tiles, NBT::TAG_Compound)); diff --git a/src/pocketmine/tile/Banner.php b/src/pocketmine/tile/Banner.php index 0bf7fdb50..9cdf3a30c 100644 --- a/src/pocketmine/tile/Banner.php +++ b/src/pocketmine/tile/Banner.php @@ -24,7 +24,6 @@ declare(strict_types=1); namespace pocketmine\tile; use pocketmine\item\Item; -use pocketmine\level\Level; use pocketmine\math\Vector3; use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\IntTag; @@ -107,19 +106,16 @@ class Banner extends Spawnable implements Nameable{ */ private $patterns; - public function __construct(Level $level, CompoundTag $nbt){ + protected function readSaveData(CompoundTag $nbt) : void{ $this->baseColor = $nbt->getInt(self::TAG_BASE, self::COLOR_BLACK, true); $this->patterns = $nbt->getListTag(self::TAG_PATTERNS) ?? new ListTag(self::TAG_PATTERNS); - $nbt->removeTag(self::TAG_BASE, self::TAG_PATTERNS); $this->loadName($nbt); - parent::__construct($level, $nbt); } - public function saveNBT() : void{ - parent::saveNBT(); - $this->namedtag->setInt(self::TAG_BASE, $this->baseColor); - $this->namedtag->setTag($this->patterns); - $this->saveName($this->namedtag); + protected function writeSaveData(CompoundTag $nbt) : void{ + $nbt->setInt(self::TAG_BASE, $this->baseColor); + $nbt->setTag($this->patterns); + $this->saveName($nbt); } public function addAdditionalSpawnData(CompoundTag $nbt) : void{ diff --git a/src/pocketmine/tile/Bed.php b/src/pocketmine/tile/Bed.php index ad7694b02..322e42d62 100644 --- a/src/pocketmine/tile/Bed.php +++ b/src/pocketmine/tile/Bed.php @@ -25,7 +25,6 @@ namespace pocketmine\tile; use pocketmine\item\Item; -use pocketmine\level\Level; use pocketmine\math\Vector3; use pocketmine\nbt\tag\CompoundTag; use pocketmine\Player; @@ -35,13 +34,6 @@ class Bed extends Spawnable{ /** @var int */ private $color = 14; //default to old red - public function __construct(Level $level, CompoundTag $nbt){ - $this->color = $nbt->getByte(self::TAG_COLOR, 14, true); - $nbt->removeTag(self::TAG_COLOR); - - parent::__construct($level, $nbt); - } - public function getColor() : int{ return $this->color; } @@ -51,13 +43,16 @@ class Bed extends Spawnable{ $this->onChanged(); } - public function addAdditionalSpawnData(CompoundTag $nbt) : void{ + protected function readSaveData(CompoundTag $nbt) : void{ + $this->color = $nbt->getByte(self::TAG_COLOR, 14, true); + } + + protected function writeSaveData(CompoundTag $nbt) : void{ $nbt->setByte(self::TAG_COLOR, $this->color); } - public function saveNBT() : void{ - parent::saveNBT(); - $this->namedtag->setByte(self::TAG_COLOR, $this->color); + public function addAdditionalSpawnData(CompoundTag $nbt) : void{ + $nbt->setByte(self::TAG_COLOR, $this->color); } protected static function createAdditionalNBT(CompoundTag $nbt, Vector3 $pos, ?int $face = null, ?Item $item = null, ?Player $player = null) : void{ diff --git a/src/pocketmine/tile/Chest.php b/src/pocketmine/tile/Chest.php index 9d14dbf4c..74c51f900 100644 --- a/src/pocketmine/tile/Chest.php +++ b/src/pocketmine/tile/Chest.php @@ -26,7 +26,6 @@ namespace pocketmine\tile; use pocketmine\inventory\ChestInventory; use pocketmine\inventory\DoubleChestInventory; use pocketmine\inventory\InventoryHolder; -use pocketmine\level\Level; use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\IntTag; @@ -50,19 +49,26 @@ class Chest extends Spawnable implements InventoryHolder, Container, Nameable{ /** @var int|null */ private $pairZ; - public function __construct(Level $level, CompoundTag $nbt){ + protected function readSaveData(CompoundTag $nbt) : void{ if($nbt->hasTag(self::TAG_PAIRX, IntTag::class) and $nbt->hasTag(self::TAG_PAIRZ, IntTag::class)){ $this->pairX = $nbt->getInt(self::TAG_PAIRX); $this->pairZ = $nbt->getInt(self::TAG_PAIRZ); } - $nbt->removeTag(self::TAG_PAIRX, self::TAG_PAIRZ); $this->loadName($nbt); - parent::__construct($level, $nbt); - $this->inventory = new ChestInventory($this); - $this->loadItems($this->namedtag); + $this->loadItems($nbt); + } + protected function writeSaveData(CompoundTag $nbt) : void{ + if($this->isPaired()){ + $nbt->setInt(self::TAG_PAIRX, $this->pairX); + $nbt->setInt(self::TAG_PAIRZ, $this->pairZ); + }else{ + $nbt->removeTag(self::TAG_PAIRX, self::TAG_PAIRZ); + } + $this->saveName($nbt); + $this->saveItems($nbt); } public function close() : void{ @@ -81,18 +87,6 @@ class Chest extends Spawnable implements InventoryHolder, Container, Nameable{ } } - public function saveNBT() : void{ - parent::saveNBT(); - if($this->isPaired()){ - $this->namedtag->setInt(self::TAG_PAIRX, $this->pairX); - $this->namedtag->setInt(self::TAG_PAIRZ, $this->pairZ); - }else{ - $this->namedtag->removeTag(self::TAG_PAIRX, self::TAG_PAIRZ); - } - $this->saveItems($this->namedtag); - $this->saveName($this->namedtag); - } - /** * @return ChestInventory|DoubleChestInventory */ diff --git a/src/pocketmine/tile/EnchantTable.php b/src/pocketmine/tile/EnchantTable.php index d31491ce2..e2618a8ff 100644 --- a/src/pocketmine/tile/EnchantTable.php +++ b/src/pocketmine/tile/EnchantTable.php @@ -23,20 +23,10 @@ declare(strict_types=1); namespace pocketmine\tile; -use pocketmine\level\Level; -use pocketmine\nbt\tag\CompoundTag; - class EnchantTable extends Spawnable implements Nameable{ - use NameableTrait; - - public function __construct(Level $level, CompoundTag $nbt){ - $this->loadName($nbt); - parent::__construct($level, $nbt); - } - - public function saveNBT() : void{ - parent::saveNBT(); - $this->saveName($this->namedtag); + use NameableTrait{ + loadName as readSaveData; + saveName as writeSaveData; } /** diff --git a/src/pocketmine/tile/EnderChest.php b/src/pocketmine/tile/EnderChest.php index 1895c1c10..822c4c01a 100644 --- a/src/pocketmine/tile/EnderChest.php +++ b/src/pocketmine/tile/EnderChest.php @@ -27,6 +27,14 @@ use pocketmine\nbt\tag\CompoundTag; class EnderChest extends Spawnable{ + protected function readSaveData(CompoundTag $nbt) : void{ + + } + + protected function writeSaveData(CompoundTag $nbt) : void{ + + } + public function addAdditionalSpawnData(CompoundTag $nbt) : void{ } diff --git a/src/pocketmine/tile/FlowerPot.php b/src/pocketmine/tile/FlowerPot.php index e4c7eb734..84de9f06c 100644 --- a/src/pocketmine/tile/FlowerPot.php +++ b/src/pocketmine/tile/FlowerPot.php @@ -25,7 +25,6 @@ namespace pocketmine\tile; use pocketmine\item\Item; use pocketmine\item\ItemFactory; -use pocketmine\level\Level; use pocketmine\nbt\tag\CompoundTag; class FlowerPot extends Spawnable{ @@ -35,17 +34,13 @@ class FlowerPot extends Spawnable{ /** @var Item */ private $item; - public function __construct(Level $level, CompoundTag $nbt){ - //TODO: check PC format + protected function readSaveData(CompoundTag $nbt) : void{ $this->item = ItemFactory::get($nbt->getShort(self::TAG_ITEM, 0, true), $nbt->getInt(self::TAG_ITEM_DATA, 0, true), 1); - $nbt->removeTag(self::TAG_ITEM, self::TAG_ITEM_DATA); - - parent::__construct($level, $nbt); } - public function saveNBT() : void{ - $this->namedtag->setShort(self::TAG_ITEM, $this->item->getId()); - $this->namedtag->setInt(self::TAG_ITEM_DATA, $this->item->getDamage()); + protected function writeSaveData(CompoundTag $nbt) : void{ + $nbt->setShort(self::TAG_ITEM, $this->item->getId()); + $nbt->setInt(self::TAG_ITEM_DATA, $this->item->getDamage()); } public function canAddItem(Item $item) : bool{ diff --git a/src/pocketmine/tile/Furnace.php b/src/pocketmine/tile/Furnace.php index cd70d3aac..a952d0daf 100644 --- a/src/pocketmine/tile/Furnace.php +++ b/src/pocketmine/tile/Furnace.php @@ -56,6 +56,13 @@ class Furnace extends Spawnable implements InventoryHolder, Container, Nameable{ private $maxTime; public function __construct(Level $level, CompoundTag $nbt){ + parent::__construct($level, $nbt); + if($this->burnTime > 0){ + $this->scheduleUpdate(); + } + } + + protected function readSaveData(CompoundTag $nbt) : void{ $this->burnTime = max(0, $nbt->getShort(self::TAG_BURN_TIME, 0, true)); $this->cookTime = $nbt->getShort(self::TAG_COOK_TIME, 0, true); @@ -70,14 +77,16 @@ class Furnace extends Spawnable implements InventoryHolder, Container, Nameable{ $this->loadName($nbt); - parent::__construct($level, $nbt); $this->inventory = new FurnaceInventory($this); - $this->loadItems($this->namedtag); + $this->loadItems($nbt); + } - - if($this->burnTime > 0){ - $this->scheduleUpdate(); - } + protected function writeSaveData(CompoundTag $nbt) : void{ + $nbt->setShort(self::TAG_BURN_TIME, $this->burnTime); + $nbt->setShort(self::TAG_COOK_TIME, $this->cookTime); + $nbt->setShort(self::TAG_MAX_TIME, $this->maxTime); + $this->saveName($nbt); + $this->saveItems($nbt); } /** @@ -96,16 +105,6 @@ class Furnace extends Spawnable implements InventoryHolder, Container, Nameable{ } } - public function saveNBT() : void{ - parent::saveNBT(); - $this->namedtag->setShort(self::TAG_BURN_TIME, $this->burnTime); - $this->namedtag->setShort(self::TAG_COOK_TIME, $this->cookTime); - $this->namedtag->setShort(self::TAG_MAX_TIME, $this->maxTime); - - $this->saveItems($this->namedtag); - $this->saveName($this->namedtag); - } - /** * @return FurnaceInventory */ diff --git a/src/pocketmine/tile/ItemFrame.php b/src/pocketmine/tile/ItemFrame.php index 39f715121..56ab6b7f2 100644 --- a/src/pocketmine/tile/ItemFrame.php +++ b/src/pocketmine/tile/ItemFrame.php @@ -25,7 +25,6 @@ namespace pocketmine\tile; use pocketmine\item\Item; use pocketmine\item\ItemFactory; -use pocketmine\level\Level; use pocketmine\nbt\tag\CompoundTag; class ItemFrame extends Spawnable{ @@ -40,7 +39,7 @@ class ItemFrame extends Spawnable{ /** @var float */ private $itemDropChance; - public function __construct(Level $level, CompoundTag $nbt){ + protected function readSaveData(CompoundTag $nbt) : void{ if(($itemTag = $nbt->getCompoundTag(self::TAG_ITEM)) !== null){ $this->item = Item::nbtDeserialize($itemTag); }else{ @@ -48,16 +47,12 @@ class ItemFrame extends Spawnable{ } $this->itemRotation = $nbt->getByte(self::TAG_ITEM_ROTATION, 0, true); $this->itemDropChance = $nbt->getFloat(self::TAG_ITEM_DROP_CHANCE, 1.0, true); - $nbt->removeTag(self::TAG_ITEM, self::TAG_ITEM_ROTATION, self::TAG_ITEM_DROP_CHANCE); - - parent::__construct($level, $nbt); } - public function saveNBT() : void{ - parent::saveNBT(); - $this->namedtag->setFloat(self::TAG_ITEM_DROP_CHANCE, $this->itemDropChance); - $this->namedtag->setByte(self::TAG_ITEM_ROTATION, $this->itemRotation); - $this->namedtag->setTag($this->item->nbtSerialize(-1, self::TAG_ITEM)); + 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)); } public function hasItem() : bool{ diff --git a/src/pocketmine/tile/Sign.php b/src/pocketmine/tile/Sign.php index 72974affb..1be69c42f 100644 --- a/src/pocketmine/tile/Sign.php +++ b/src/pocketmine/tile/Sign.php @@ -24,7 +24,6 @@ declare(strict_types=1); namespace pocketmine\tile; use pocketmine\event\block\SignChangeEvent; -use pocketmine\level\Level; use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\StringTag; use pocketmine\Player; @@ -37,7 +36,7 @@ class Sign extends Spawnable{ /** @var string[] */ protected $text = ["", "", "", ""]; - public function __construct(Level $level, CompoundTag $nbt){ + protected function readSaveData(CompoundTag $nbt) : void{ if($nbt->hasTag(self::TAG_TEXT_BLOB, StringTag::class)){ //MCPE 1.2 save format $this->text = array_pad(explode("\n", $nbt->getString(self::TAG_TEXT_BLOB)), 4, ""); assert(count($this->text) === 4, "Too many lines!"); @@ -51,17 +50,14 @@ class Sign extends Spawnable{ } } } - - parent::__construct($level, $nbt); } - public function saveNBT() : void{ - parent::saveNBT(); - $this->namedtag->setString(self::TAG_TEXT_BLOB, implode("\n", $this->text)); + protected function writeSaveData(CompoundTag $nbt) : void{ + $nbt->setString(self::TAG_TEXT_BLOB, implode("\n", $this->text)); for($i = 1; $i <= 4; ++$i){ //Backwards-compatibility $textKey = sprintf(self::TAG_TEXT_LINE, $i); - $this->namedtag->setString($textKey, $this->getLine($i - 1)); + $nbt->setString($textKey, $this->getLine($i - 1)); } } diff --git a/src/pocketmine/tile/Skull.php b/src/pocketmine/tile/Skull.php index 1b24eb534..828c67d1a 100644 --- a/src/pocketmine/tile/Skull.php +++ b/src/pocketmine/tile/Skull.php @@ -24,7 +24,6 @@ declare(strict_types=1); namespace pocketmine\tile; use pocketmine\item\Item; -use pocketmine\level\Level; use pocketmine\math\Vector3; use pocketmine\nbt\tag\CompoundTag; use pocketmine\Player; @@ -47,17 +46,14 @@ class Skull extends Spawnable{ /** @var int */ private $skullRotation; - public function __construct(Level $level, CompoundTag $nbt){ + protected function readSaveData(CompoundTag $nbt) : void{ $this->skullType = $nbt->getByte(self::TAG_SKULL_TYPE, self::TYPE_SKELETON, true); $this->skullRotation = $nbt->getByte(self::TAG_ROT, 0, true); - $nbt->removeTag(self::TAG_SKULL_TYPE, self::TAG_ROT); - parent::__construct($level, $nbt); } - public function saveNBT() : void{ - parent::saveNBT(); - $this->namedtag->setByte(self::TAG_SKULL_TYPE, $this->skullType); - $this->namedtag->setByte(self::TAG_ROT, $this->skullRotation); + protected function writeSaveData(CompoundTag $nbt) : void{ + $nbt->setByte(self::TAG_SKULL_TYPE, $this->skullType); + $nbt->setByte(self::TAG_ROT, $this->skullRotation); } public function setType(int $type){ diff --git a/src/pocketmine/tile/Tile.php b/src/pocketmine/tile/Tile.php index 876b186d7..e87979c68 100644 --- a/src/pocketmine/tile/Tile.php +++ b/src/pocketmine/tile/Tile.php @@ -74,8 +74,6 @@ abstract class Tile extends Position{ public $id; /** @var bool */ public $closed = false; - /** @var CompoundTag */ - public $namedtag; /** @var Server */ protected $server; /** @var TimingsHandler */ @@ -155,12 +153,12 @@ abstract class Tile extends Position{ public function __construct(Level $level, CompoundTag $nbt){ $this->timings = Timings::getTileEntityTimings($this); - $this->namedtag = $nbt; $this->server = $level->getServer(); $this->name = ""; $this->id = Tile::$tileCount++; - parent::__construct($this->namedtag->getInt(self::TAG_X), $this->namedtag->getInt(self::TAG_Y), $this->namedtag->getInt(self::TAG_Z), $level); + parent::__construct($nbt->getInt(self::TAG_X), $nbt->getInt(self::TAG_Y), $nbt->getInt(self::TAG_Z), $level); + $this->readSaveData($nbt); $this->getLevel()->addTile($this); } @@ -169,26 +167,31 @@ abstract class Tile extends Position{ return $this->id; } - public function saveNBT() : void{ - $this->namedtag->setString(self::TAG_ID, static::getSaveId()); - $this->namedtag->setInt(self::TAG_X, $this->x); - $this->namedtag->setInt(self::TAG_Y, $this->y); - $this->namedtag->setInt(self::TAG_Z, $this->z); - } + /** + * Reads additional data from the CompoundTag on tile creation. + * + * @param CompoundTag $nbt + */ + abstract protected function readSaveData(CompoundTag $nbt) : void; - public function getNBT() : CompoundTag{ - return $this->namedtag; + /** + * Writes additional save data to a CompoundTag, not including generic things like ID and coordinates. + * + * @param CompoundTag $nbt + */ + abstract protected function writeSaveData(CompoundTag $nbt) : void; + + public function saveNBT(CompoundTag $nbt) : void{ + $nbt->setString(self::TAG_ID, static::getSaveId()); + $nbt->setInt(self::TAG_X, $this->x); + $nbt->setInt(self::TAG_Y, $this->y); + $nbt->setInt(self::TAG_Z, $this->z); + $this->writeSaveData($nbt); } public function getCleanedNBT() : ?CompoundTag{ - $this->saveNBT(); - $tag = clone $this->namedtag; - $tag->removeTag(self::TAG_X, self::TAG_Y, self::TAG_Z, self::TAG_ID); - if($tag->getCount() > 0){ - return $tag; - }else{ - return null; - } + $this->writeSaveData($tag = new CompoundTag()); + return $tag->getCount() > 0 ? $tag : null; } /** @@ -270,8 +273,6 @@ abstract class Tile extends Position{ $this->level->removeTile($this); $this->setLevel(null); } - - $this->namedtag = null; } }