diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index 7aa78cb65..50b00cfb7 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -1885,18 +1885,18 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ $this->server->addOnlinePlayer($this); } - protected function initHumanData() : void{ + protected function initHumanData(CompoundTag $nbt) : void{ $this->setNameTag($this->username); } - protected function initEntity() : void{ - parent::initEntity(); + protected function initEntity(CompoundTag $nbt) : void{ + parent::initEntity($nbt); $this->addDefaultWindows(); - $this->firstPlayed = $this->namedtag->getLong("firstPlayed", $now = (int) (microtime(true) * 1000)); - $this->lastPlayed = $this->namedtag->getLong("lastPlayed", $now); + $this->firstPlayed = $nbt->getLong("firstPlayed", $now = (int) (microtime(true) * 1000)); + $this->lastPlayed = $nbt->getLong("lastPlayed", $now); - $this->gamemode = $this->namedtag->getInt("playerGameType", self::SURVIVAL) & 0x03; + $this->gamemode = $nbt->getInt("playerGameType", self::SURVIVAL) & 0x03; if($this->server->getForceGamemode()){ $this->gamemode = $this->server->getGamemode(); } @@ -1912,15 +1912,15 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ $this->setCanClimb(); $this->achievements = []; - $achievements = $this->namedtag->getCompoundTag("Achievements") ?? []; + $achievements = $nbt->getCompoundTag("Achievements") ?? []; /** @var ByteTag $achievement */ foreach($achievements as $achievement){ $this->achievements[$achievement->getName()] = $achievement->getValue() !== 0; } if(!$this->hasValidSpawnPosition()){ - if(($level = $this->server->getLevelByName($this->namedtag->getString("SpawnLevel", ""))) instanceof Level){ - $this->spawnPosition = new Position($this->namedtag->getInt("SpawnX"), $this->namedtag->getInt("SpawnY"), $this->namedtag->getInt("SpawnZ"), $level); + if(($level = $this->server->getLevelByName($nbt->getString("SpawnLevel", ""))) instanceof Level){ + $this->spawnPosition = new Position($nbt->getInt("SpawnX"), $nbt->getInt("SpawnY"), $nbt->getInt("SpawnZ"), $level); }else{ $this->spawnPosition = $this->level->getSafeSpawn(); } @@ -2916,21 +2916,21 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ throw new \InvalidStateException("Tried to save closed player"); } - parent::saveNBT(); + $nbt = $this->saveNBT(); if($this->isValid()){ - $this->namedtag->setString("Level", $this->level->getFolderName()); + $nbt->setString("Level", $this->level->getFolderName()); } if($this->hasValidSpawnPosition()){ - $this->namedtag->setString("SpawnLevel", $this->spawnPosition->getLevel()->getFolderName()); - $this->namedtag->setInt("SpawnX", $this->spawnPosition->getFloorX()); - $this->namedtag->setInt("SpawnY", $this->spawnPosition->getFloorY()); - $this->namedtag->setInt("SpawnZ", $this->spawnPosition->getFloorZ()); + $nbt->setString("SpawnLevel", $this->spawnPosition->getLevel()->getFolderName()); + $nbt->setInt("SpawnX", $this->spawnPosition->getFloorX()); + $nbt->setInt("SpawnY", $this->spawnPosition->getFloorY()); + $nbt->setInt("SpawnZ", $this->spawnPosition->getFloorZ()); if(!$this->isAlive()){ //hack for respawn after quit - $this->namedtag->setTag(new ListTag("Pos", [ + $nbt->setTag(new ListTag("Pos", [ new DoubleTag("", $this->spawnPosition->x), new DoubleTag("", $this->spawnPosition->y), new DoubleTag("", $this->spawnPosition->z) @@ -2942,13 +2942,13 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ foreach($this->achievements as $achievement => $status){ $achievements->setByte($achievement, $status ? 1 : 0); } - $this->namedtag->setTag($achievements); + $nbt->setTag($achievements); - $this->namedtag->setInt("playerGameType", $this->gamemode); - $this->namedtag->setLong("firstPlayed", $this->firstPlayed); - $this->namedtag->setLong("lastPlayed", (int) floor(microtime(true) * 1000)); + $nbt->setInt("playerGameType", $this->gamemode); + $nbt->setLong("firstPlayed", $this->firstPlayed); + $nbt->setLong("lastPlayed", (int) floor(microtime(true) * 1000)); - $this->server->saveOfflinePlayerData($this->username, $this->namedtag, $async); + $this->server->saveOfflinePlayerData($this->username, $nbt, $async); } public function kill() : void{ diff --git a/src/pocketmine/entity/Entity.php b/src/pocketmine/entity/Entity.php index 847182cc5..1a909f0fe 100644 --- a/src/pocketmine/entity/Entity.php +++ b/src/pocketmine/entity/Entity.php @@ -436,8 +436,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{ public $lastUpdate; /** @var int */ public $fireTicks = 0; - /** @var CompoundTag */ - public $namedtag; /** @var bool */ public $canCollide = true; @@ -495,13 +493,12 @@ abstract class Entity extends Location implements Metadatable, EntityIds{ } $this->id = Entity::$entityCount++; - $this->namedtag = $nbt; $this->server = $level->getServer(); /** @var float[] $pos */ - $pos = $this->namedtag->getListTag("Pos")->getAllValues(); + $pos = $nbt->getListTag("Pos")->getAllValues(); /** @var float[] $rotation */ - $rotation = $this->namedtag->getListTag("Rotation")->getAllValues(); + $rotation = $nbt->getListTag("Rotation")->getAllValues(); parent::__construct($pos[0], $pos[1], $pos[2], $rotation[0], $rotation[1], $level); assert(!is_nan($this->x) and !is_infinite($this->x) and !is_nan($this->y) and !is_infinite($this->y) and !is_nan($this->z) and !is_infinite($this->z)); @@ -514,15 +511,15 @@ abstract class Entity extends Location implements Metadatable, EntityIds{ throw new \InvalidStateException("Cannot create entities in unloaded chunks"); } - if($this->namedtag->hasTag("Motion", ListTag::class)){ + if($nbt->hasTag("Motion", ListTag::class)){ /** @var float[] $motion */ - $motion = $this->namedtag->getListTag("Motion")->getAllValues(); + $motion = $nbt->getListTag("Motion")->getAllValues(); $this->setMotion($this->temporalVector->setComponents(...$motion)); } $this->resetLastMovements(); - $this->fallDistance = $this->namedtag->getFloat("FallDistance", 0.0); + $this->fallDistance = $nbt->getFloat("FallDistance", 0.0); $this->propertyManager = new DataPropertyManager(); @@ -534,14 +531,14 @@ abstract class Entity extends Location implements Metadatable, EntityIds{ $this->propertyManager->setFloat(self::DATA_BOUNDING_BOX_WIDTH, $this->width); $this->propertyManager->setFloat(self::DATA_BOUNDING_BOX_HEIGHT, $this->height); - $this->fireTicks = $this->namedtag->getShort("Fire", 0); + $this->fireTicks = $nbt->getShort("Fire", 0); if($this->isOnFire()){ $this->setGenericFlag(self::DATA_FLAG_ONFIRE); } - $this->propertyManager->setShort(self::DATA_AIR, $this->namedtag->getShort("Air", 300)); - $this->onGround = $this->namedtag->getByte("OnGround", 0) !== 0; - $this->invulnerable = $this->namedtag->getByte("Invulnerable", 0) !== 0; + $this->propertyManager->setShort(self::DATA_AIR, $nbt->getShort("Air", 300)); + $this->onGround = $nbt->getByte("OnGround", 0) !== 0; + $this->invulnerable = $nbt->getByte("Invulnerable", 0) !== 0; $this->attributeMap = new AttributeMap(); $this->addAttributes(); @@ -549,7 +546,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{ $this->setGenericFlag(self::DATA_FLAG_AFFECTED_BY_GRAVITY, true); $this->setGenericFlag(self::DATA_FLAG_HAS_COLLISION, true); - $this->initEntity(); + $this->initEntity($nbt); $this->propertyManager->clearDirtyProperties(); //Prevents resending properties that were set during construction $this->chunk->addEntity($this); @@ -838,54 +835,52 @@ abstract class Entity extends Location implements Metadatable, EntityIds{ return current(self::$saveNames[static::class]); } - public function saveNBT() : void{ + public function saveNBT() : CompoundTag{ + $nbt = new CompoundTag(); if(!($this instanceof Player)){ - $this->namedtag->setString("id", $this->getSaveId(), true); + $nbt->setString("id", $this->getSaveId(), true); if($this->getNameTag() !== ""){ - $this->namedtag->setString("CustomName", $this->getNameTag()); - $this->namedtag->setByte("CustomNameVisible", $this->isNameTagVisible() ? 1 : 0); - }else{ - $this->namedtag->removeTag("CustomName", "CustomNameVisible"); + $nbt->setString("CustomName", $this->getNameTag()); + $nbt->setByte("CustomNameVisible", $this->isNameTagVisible() ? 1 : 0); } } - $this->namedtag->setTag(new ListTag("Pos", [ + $nbt->setTag(new ListTag("Pos", [ new DoubleTag("", $this->x), new DoubleTag("", $this->y), new DoubleTag("", $this->z) ])); - $this->namedtag->setTag(new ListTag("Motion", [ + $nbt->setTag(new ListTag("Motion", [ new DoubleTag("", $this->motion->x), new DoubleTag("", $this->motion->y), new DoubleTag("", $this->motion->z) ])); - $this->namedtag->setTag(new ListTag("Rotation", [ + $nbt->setTag(new ListTag("Rotation", [ new FloatTag("", $this->yaw), new FloatTag("", $this->pitch) ])); - $this->namedtag->setFloat("FallDistance", $this->fallDistance); - $this->namedtag->setShort("Fire", $this->fireTicks); - $this->namedtag->setShort("Air", $this->propertyManager->getShort(self::DATA_AIR)); - $this->namedtag->setByte("OnGround", $this->onGround ? 1 : 0); - $this->namedtag->setByte("Invulnerable", $this->invulnerable ? 1 : 0); + $nbt->setFloat("FallDistance", $this->fallDistance); + $nbt->setShort("Fire", $this->fireTicks); + $nbt->setShort("Air", $this->propertyManager->getShort(self::DATA_AIR)); + $nbt->setByte("OnGround", $this->onGround ? 1 : 0); + $nbt->setByte("Invulnerable", $this->invulnerable ? 1 : 0); + + return $nbt; } - protected function initEntity() : void{ - assert($this->namedtag instanceof CompoundTag); + protected function initEntity(CompoundTag $nbt) : void{ + if($nbt->hasTag("CustomName", StringTag::class)){ + $this->setNameTag($nbt->getString("CustomName")); - if($this->namedtag->hasTag("CustomName", StringTag::class)){ - $this->setNameTag($this->namedtag->getString("CustomName")); - - if($this->namedtag->hasTag("CustomNameVisible", StringTag::class)){ + if($nbt->hasTag("CustomNameVisible", StringTag::class)){ //Older versions incorrectly saved this as a string (see 890f72dbf23a77f294169b79590770470041adc4) - $this->setNameTagVisible($this->namedtag->getString("CustomNameVisible") !== ""); - $this->namedtag->removeTag("CustomNameVisible"); + $this->setNameTagVisible($nbt->getString("CustomNameVisible") !== ""); }else{ - $this->setNameTagVisible($this->namedtag->getByte("CustomNameVisible", 1) !== 0); + $this->setNameTagVisible($nbt->getByte("CustomNameVisible", 1) !== 0); } } } @@ -2036,7 +2031,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{ $this->setLevel(null); } - $this->namedtag = null; $this->lastDamageCause = null; } } diff --git a/src/pocketmine/entity/Human.php b/src/pocketmine/entity/Human.php index 7aa322ad2..68d99d7e0 100644 --- a/src/pocketmine/entity/Human.php +++ b/src/pocketmine/entity/Human.php @@ -578,13 +578,15 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ /** * For Human entities which are not players, sets their properties such as nametag, skin and UUID from NBT. + * + * @param CompoundTag $nbt */ - protected function initHumanData() : void{ - if($this->namedtag->hasTag("NameTag", StringTag::class)){ - $this->setNameTag($this->namedtag->getString("NameTag")); + protected function initHumanData(CompoundTag $nbt) : void{ + if($nbt->hasTag("NameTag", StringTag::class)){ + $this->setNameTag($nbt->getString("NameTag")); } - $skin = $this->namedtag->getCompoundTag("Skin"); + $skin = $nbt->getCompoundTag("Skin"); if($skin !== null){ $this->setSkin(new Skin( $skin->getString("Name"), @@ -598,17 +600,17 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ $this->uuid = UUID::fromData((string) $this->getId(), $this->skin->getSkinData(), $this->getNameTag()); } - protected function initEntity() : void{ - parent::initEntity(); + protected function initEntity(CompoundTag $nbt) : void{ + parent::initEntity($nbt); $this->setPlayerFlag(self::DATA_PLAYER_FLAG_SLEEP, false); $this->propertyManager->setBlockPos(self::DATA_PLAYER_BED_POSITION, null); $this->inventory = new PlayerInventory($this); $this->enderChestInventory = new EnderChestInventory(); - $this->initHumanData(); + $this->initHumanData($nbt); - $inventoryTag = $this->namedtag->getListTag("Inventory"); + $inventoryTag = $nbt->getListTag("Inventory"); if($inventoryTag !== null){ $armorListener = $this->armorInventory->getEventProcessor(); $this->armorInventory->setEventProcessor(null); @@ -628,7 +630,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ $this->armorInventory->setEventProcessor($armorListener); } - $enderChestInventoryTag = $this->namedtag->getListTag("EnderChestInventory"); + $enderChestInventoryTag = $nbt->getListTag("EnderChestInventory"); if($enderChestInventoryTag !== null){ /** @var CompoundTag $item */ foreach($enderChestInventoryTag as $i => $item){ @@ -636,21 +638,21 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ } } - $this->inventory->setHeldItemIndex($this->namedtag->getInt("SelectedInventorySlot", 0), false); + $this->inventory->setHeldItemIndex($nbt->getInt("SelectedInventorySlot", 0), false); $this->inventory->setEventProcessor(new EntityInventoryEventProcessor($this)); - $this->setFood((float) $this->namedtag->getInt("foodLevel", (int) $this->getFood(), true)); - $this->setExhaustion($this->namedtag->getFloat("foodExhaustionLevel", $this->getExhaustion(), true)); - $this->setSaturation($this->namedtag->getFloat("foodSaturationLevel", $this->getSaturation(), true)); - $this->foodTickTimer = $this->namedtag->getInt("foodTickTimer", $this->foodTickTimer, true); + $this->setFood((float) $nbt->getInt("foodLevel", (int) $this->getFood(), true)); + $this->setExhaustion($nbt->getFloat("foodExhaustionLevel", $this->getExhaustion(), true)); + $this->setSaturation($nbt->getFloat("foodSaturationLevel", $this->getSaturation(), true)); + $this->foodTickTimer = $nbt->getInt("foodTickTimer", $this->foodTickTimer, true); - $this->setXpLevel($this->namedtag->getInt("XpLevel", $this->getXpLevel(), true)); - $this->setXpProgress($this->namedtag->getFloat("XpP", $this->getXpProgress(), true)); - $this->totalXp = $this->namedtag->getInt("XpTotal", $this->totalXp, true); + $this->setXpLevel($nbt->getInt("XpLevel", $this->getXpLevel(), true)); + $this->setXpProgress($nbt->getFloat("XpP", $this->getXpProgress(), true)); + $this->totalXp = $nbt->getInt("XpTotal", $this->totalXp, true); - if($this->namedtag->hasTag("XpSeed", IntTag::class)){ - $this->xpSeed = $this->namedtag->getInt("XpSeed"); + if($nbt->hasTag("XpSeed", IntTag::class)){ + $this->xpSeed = $nbt->getInt("XpSeed"); }else{ $this->xpSeed = random_int(INT32_MIN, INT32_MAX); } @@ -764,21 +766,21 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ ), function(Item $item) : bool{ return !$item->hasEnchantment(Enchantment::VANISHING); }); } - public function saveNBT() : void{ - parent::saveNBT(); + public function saveNBT() : CompoundTag{ + $nbt = parent::saveNBT(); - $this->namedtag->setInt("foodLevel", (int) $this->getFood(), true); - $this->namedtag->setFloat("foodExhaustionLevel", $this->getExhaustion(), true); - $this->namedtag->setFloat("foodSaturationLevel", $this->getSaturation(), true); - $this->namedtag->setInt("foodTickTimer", $this->foodTickTimer); + $nbt->setInt("foodLevel", (int) $this->getFood(), true); + $nbt->setFloat("foodExhaustionLevel", $this->getExhaustion(), true); + $nbt->setFloat("foodSaturationLevel", $this->getSaturation(), true); + $nbt->setInt("foodTickTimer", $this->foodTickTimer); - $this->namedtag->setInt("XpLevel", $this->getXpLevel()); - $this->namedtag->setFloat("XpP", $this->getXpProgress()); - $this->namedtag->setInt("XpTotal", $this->totalXp); - $this->namedtag->setInt("XpSeed", $this->xpSeed); + $nbt->setInt("XpLevel", $this->getXpLevel()); + $nbt->setFloat("XpP", $this->getXpProgress()); + $nbt->setInt("XpTotal", $this->totalXp); + $nbt->setInt("XpSeed", $this->xpSeed); $inventoryTag = new ListTag("Inventory", [], NBT::TAG_Compound); - $this->namedtag->setTag($inventoryTag); + $nbt->setTag($inventoryTag); if($this->inventory !== null){ //Normal inventory $slotCount = $this->inventory->getSize() + $this->inventory->getHotbarSize(); @@ -797,7 +799,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ } } - $this->namedtag->setInt("SelectedInventorySlot", $this->inventory->getHeldItemIndex()); + $nbt->setInt("SelectedInventorySlot", $this->inventory->getHeldItemIndex()); } if($this->enderChestInventory !== null){ @@ -812,11 +814,11 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ } } - $this->namedtag->setTag(new ListTag("EnderChestInventory", $items, NBT::TAG_Compound)); + $nbt->setTag(new ListTag("EnderChestInventory", $items, NBT::TAG_Compound)); } if($this->skin !== null){ - $this->namedtag->setTag(new CompoundTag("Skin", [ + $nbt->setTag(new CompoundTag("Skin", [ new StringTag("Name", $this->skin->getSkinId()), new ByteArrayTag("Data", $this->skin->getSkinData()), new ByteArrayTag("CapeData", $this->skin->getCapeData()), @@ -824,6 +826,8 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ new ByteArrayTag("GeometryData", $this->skin->getGeometryData()) ])); } + + return $nbt; } public function spawnTo(Player $player) : void{ diff --git a/src/pocketmine/entity/Living.php b/src/pocketmine/entity/Living.php index 1ebea73b6..1c0e12b47 100644 --- a/src/pocketmine/entity/Living.php +++ b/src/pocketmine/entity/Living.php @@ -74,8 +74,8 @@ abstract class Living extends Entity implements Damageable{ abstract public function getName() : string; - protected function initEntity() : void{ - parent::initEntity(); + protected function initEntity(CompoundTag $nbt) : void{ + parent::initEntity($nbt); $this->armorInventory = new ArmorInventory($this); //TODO: load/save armor inventory contents @@ -83,21 +83,17 @@ abstract class Living extends Entity implements Damageable{ $health = $this->getMaxHealth(); - if($this->namedtag->hasTag("HealF", FloatTag::class)){ - $health = $this->namedtag->getFloat("HealF"); - $this->namedtag->removeTag("HealF"); - }elseif($this->namedtag->hasTag("Health")){ - $healthTag = $this->namedtag->getTag("Health"); + if($nbt->hasTag("HealF", FloatTag::class)){ + $health = $nbt->getFloat("HealF"); + }elseif($nbt->hasTag("Health")){ + $healthTag = $nbt->getTag("Health"); $health = (float) $healthTag->getValue(); //Older versions of PocketMine-MP incorrectly saved this as a short instead of a float - if(!($healthTag instanceof FloatTag)){ - $this->namedtag->removeTag("Health"); - } } $this->setHealth($health); /** @var CompoundTag[]|ListTag $activeEffectsTag */ - $activeEffectsTag = $this->namedtag->getListTag("ActiveEffects"); + $activeEffectsTag = $nbt->getListTag("ActiveEffects"); if($activeEffectsTag !== null){ foreach($activeEffectsTag as $e){ $effect = Effect::getEffect($e->getByte("Id")); @@ -150,9 +146,9 @@ abstract class Living extends Entity implements Damageable{ $this->attributeMap->getAttribute(Attribute::ABSORPTION)->setValue($absorption); } - public function saveNBT() : void{ - parent::saveNBT(); - $this->namedtag->setFloat("Health", $this->getHealth(), true); + public function saveNBT() : CompoundTag{ + $nbt = parent::saveNBT(); + $nbt->setFloat("Health", $this->getHealth(), true); if(count($this->effects) > 0){ $effects = []; @@ -166,10 +162,10 @@ abstract class Living extends Entity implements Damageable{ ]); } - $this->namedtag->setTag(new ListTag("ActiveEffects", $effects)); - }else{ - $this->namedtag->removeTag("ActiveEffects"); + $nbt->setTag(new ListTag("ActiveEffects", $effects)); } + + return $nbt; } diff --git a/src/pocketmine/entity/Squid.php b/src/pocketmine/entity/Squid.php index 2d2c08e26..24d97340b 100644 --- a/src/pocketmine/entity/Squid.php +++ b/src/pocketmine/entity/Squid.php @@ -28,6 +28,7 @@ use pocketmine\event\entity\EntityDamageEvent; use pocketmine\item\Item; use pocketmine\item\ItemFactory; use pocketmine\math\Vector3; +use pocketmine\nbt\tag\CompoundTag; use pocketmine\network\mcpe\protocol\EntityEventPacket; class Squid extends WaterAnimal{ @@ -42,9 +43,9 @@ class Squid extends WaterAnimal{ private $switchDirectionTicker = 0; - public function initEntity() : void{ + public function initEntity(CompoundTag $nbt) : void{ $this->setMaxHealth(10); - parent::initEntity(); + parent::initEntity($nbt); } public function getName() : string{ diff --git a/src/pocketmine/entity/Villager.php b/src/pocketmine/entity/Villager.php index 233690ca9..52b0d1bdd 100644 --- a/src/pocketmine/entity/Villager.php +++ b/src/pocketmine/entity/Villager.php @@ -23,6 +23,8 @@ declare(strict_types=1); namespace pocketmine\entity; +use pocketmine\nbt\tag\CompoundTag; + class Villager extends Creature implements NPC, Ageable{ public const PROFESSION_FARMER = 0; public const PROFESSION_LIBRARIAN = 1; @@ -39,11 +41,11 @@ class Villager extends Creature implements NPC, Ageable{ return "Villager"; } - protected function initEntity() : void{ - parent::initEntity(); + protected function initEntity(CompoundTag $nbt) : void{ + parent::initEntity($nbt); /** @var int $profession */ - $profession = $this->namedtag->getInt("Profession", self::PROFESSION_FARMER); + $profession = $nbt->getInt("Profession", self::PROFESSION_FARMER); if($profession > 4 or $profession < 0){ $profession = self::PROFESSION_FARMER; @@ -52,9 +54,11 @@ class Villager extends Creature implements NPC, Ageable{ $this->setProfession($profession); } - public function saveNBT() : void{ - parent::saveNBT(); - $this->namedtag->setInt("Profession", $this->getProfession()); + public function saveNBT() : CompoundTag{ + $nbt = parent::saveNBT(); + $nbt->setInt("Profession", $this->getProfession()); + + return $nbt; } /** diff --git a/src/pocketmine/entity/object/ExperienceOrb.php b/src/pocketmine/entity/object/ExperienceOrb.php index 93cd69256..44d30ee76 100644 --- a/src/pocketmine/entity/object/ExperienceOrb.php +++ b/src/pocketmine/entity/object/ExperienceOrb.php @@ -25,6 +25,7 @@ namespace pocketmine\entity\object; use pocketmine\entity\Entity; use pocketmine\entity\Human; +use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\IntTag; use pocketmine\nbt\tag\ShortTag; use pocketmine\Player; @@ -100,28 +101,30 @@ class ExperienceOrb extends Entity{ */ protected $targetPlayerRuntimeId = null; - protected function initEntity() : void{ - parent::initEntity(); + protected function initEntity(CompoundTag $nbt) : void{ + parent::initEntity($nbt); - $this->age = $this->namedtag->getShort("Age", 0); + $this->age = $nbt->getShort("Age", 0); $value = 0; - if($this->namedtag->hasTag(self::TAG_VALUE_PC, ShortTag::class)){ //PC - $value = $this->namedtag->getShort(self::TAG_VALUE_PC); - }elseif($this->namedtag->hasTag(self::TAG_VALUE_PE, IntTag::class)){ //PE save format - $value = $this->namedtag->getInt(self::TAG_VALUE_PE); + if($nbt->hasTag(self::TAG_VALUE_PC, ShortTag::class)){ //PC + $value = $nbt->getShort(self::TAG_VALUE_PC); + }elseif($nbt->hasTag(self::TAG_VALUE_PE, IntTag::class)){ //PE save format + $value = $nbt->getInt(self::TAG_VALUE_PE); } $this->setXpValue($value); } - public function saveNBT() : void{ - parent::saveNBT(); + public function saveNBT() : CompoundTag{ + $nbt = parent::saveNBT(); - $this->namedtag->setShort("Age", $this->age); + $nbt->setShort("Age", $this->age); - $this->namedtag->setShort(self::TAG_VALUE_PC, $this->getXpValue()); - $this->namedtag->setInt(self::TAG_VALUE_PE, $this->getXpValue()); + $nbt->setShort(self::TAG_VALUE_PC, $this->getXpValue()); + $nbt->setInt(self::TAG_VALUE_PE, $this->getXpValue()); + + return $nbt; } public function getXpValue() : int{ diff --git a/src/pocketmine/entity/object/FallingBlock.php b/src/pocketmine/entity/object/FallingBlock.php index a2dfa4ad4..4db9c18dc 100644 --- a/src/pocketmine/entity/object/FallingBlock.php +++ b/src/pocketmine/entity/object/FallingBlock.php @@ -32,6 +32,7 @@ use pocketmine\event\entity\EntityDamageEvent; use pocketmine\item\ItemFactory; use pocketmine\level\Position; use pocketmine\nbt\tag\ByteTag; +use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\IntTag; class FallingBlock extends Entity{ @@ -50,24 +51,23 @@ class FallingBlock extends Entity{ public $canCollide = false; - protected function initEntity() : void{ - parent::initEntity(); + protected function initEntity(CompoundTag $nbt) : void{ + parent::initEntity($nbt); $blockId = 0; //TODO: 1.8+ save format - if($this->namedtag->hasTag("TileID", IntTag::class)){ - $blockId = $this->namedtag->getInt("TileID"); - }elseif($this->namedtag->hasTag("Tile", ByteTag::class)){ - $blockId = $this->namedtag->getByte("Tile"); - $this->namedtag->removeTag("Tile"); + if($nbt->hasTag("TileID", IntTag::class)){ + $blockId = $nbt->getInt("TileID"); + }elseif($nbt->hasTag("Tile", ByteTag::class)){ + $blockId = $nbt->getByte("Tile"); } if($blockId === 0){ throw new \UnexpectedValueException("Invalid " . get_class($this) . " entity: block ID is 0 or missing"); } - $damage = $this->namedtag->getByte("Data", 0); + $damage = $nbt->getByte("Data", 0); $this->block = BlockFactory::get($blockId, $damage); @@ -133,9 +133,11 @@ class FallingBlock extends Entity{ return $this->block->getDamage(); } - public function saveNBT() : void{ - parent::saveNBT(); - $this->namedtag->setInt("TileID", $this->block->getId(), true); - $this->namedtag->setByte("Data", $this->block->getDamage()); + public function saveNBT() : CompoundTag{ + $nbt = parent::saveNBT(); + $nbt->setInt("TileID", $this->block->getId(), true); + $nbt->setByte("Data", $this->block->getDamage()); + + return $nbt; } } diff --git a/src/pocketmine/entity/object/ItemEntity.php b/src/pocketmine/entity/object/ItemEntity.php index 708087e7e..103f9a45f 100644 --- a/src/pocketmine/entity/object/ItemEntity.php +++ b/src/pocketmine/entity/object/ItemEntity.php @@ -28,6 +28,7 @@ use pocketmine\event\entity\ItemDespawnEvent; use pocketmine\event\entity\ItemSpawnEvent; use pocketmine\event\inventory\InventoryPickupItemEvent; use pocketmine\item\Item; +use pocketmine\nbt\tag\CompoundTag; use pocketmine\network\mcpe\protocol\AddItemEntityPacket; use pocketmine\network\mcpe\protocol\TakeItemEntityPacket; use pocketmine\Player; @@ -53,18 +54,18 @@ class ItemEntity extends Entity{ public $canCollide = false; - protected function initEntity() : void{ - parent::initEntity(); + protected function initEntity(CompoundTag $nbt) : void{ + parent::initEntity($nbt); $this->setMaxHealth(5); - $this->setHealth($this->namedtag->getShort("Health", (int) $this->getHealth())); - $this->age = $this->namedtag->getShort("Age", $this->age); - $this->pickupDelay = $this->namedtag->getShort("PickupDelay", $this->pickupDelay); - $this->owner = $this->namedtag->getString("Owner", $this->owner); - $this->thrower = $this->namedtag->getString("Thrower", $this->thrower); + $this->setHealth($nbt->getShort("Health", (int) $this->getHealth())); + $this->age = $nbt->getShort("Age", $this->age); + $this->pickupDelay = $nbt->getShort("PickupDelay", $this->pickupDelay); + $this->owner = $nbt->getString("Owner", $this->owner); + $this->thrower = $nbt->getString("Thrower", $this->thrower); - $itemTag = $this->namedtag->getCompoundTag("Item"); + $itemTag = $nbt->getCompoundTag("Item"); if($itemTag === null){ throw new \UnexpectedValueException("Invalid " . get_class($this) . " entity: expected \"Item\" NBT tag not found"); } @@ -114,18 +115,20 @@ class ItemEntity extends Entity{ return true; } - public function saveNBT() : void{ - parent::saveNBT(); - $this->namedtag->setTag($this->item->nbtSerialize(-1, "Item")); - $this->namedtag->setShort("Health", (int) $this->getHealth()); - $this->namedtag->setShort("Age", $this->age); - $this->namedtag->setShort("PickupDelay", $this->pickupDelay); + public function saveNBT() : CompoundTag{ + $nbt = parent::saveNBT(); + $nbt->setTag($this->item->nbtSerialize(-1, "Item")); + $nbt->setShort("Health", (int) $this->getHealth()); + $nbt->setShort("Age", $this->age); + $nbt->setShort("PickupDelay", $this->pickupDelay); if($this->owner !== null){ - $this->namedtag->setString("Owner", $this->owner); + $nbt->setString("Owner", $this->owner); } if($this->thrower !== null){ - $this->namedtag->setString("Thrower", $this->thrower); + $nbt->setString("Thrower", $this->thrower); } + + return $nbt; } /** diff --git a/src/pocketmine/entity/object/Painting.php b/src/pocketmine/entity/object/Painting.php index 4dfa7ddcd..6faafac8d 100644 --- a/src/pocketmine/entity/object/Painting.php +++ b/src/pocketmine/entity/object/Painting.php @@ -70,20 +70,22 @@ class Painting extends Entity{ parent::__construct($level, $nbt); } - protected function initEntity() : void{ + protected function initEntity(CompoundTag $nbt) : void{ $this->setMaxHealth(1); $this->setHealth(1); - parent::initEntity(); + parent::initEntity($nbt); } - public function saveNBT() : void{ - parent::saveNBT(); - $this->namedtag->setInt("TileX", (int) $this->blockIn->x); - $this->namedtag->setInt("TileY", (int) $this->blockIn->y); - $this->namedtag->setInt("TileZ", (int) $this->blockIn->z); + public function saveNBT() : CompoundTag{ + $nbt = parent::saveNBT(); + $nbt->setInt("TileX", (int) $this->blockIn->x); + $nbt->setInt("TileY", (int) $this->blockIn->y); + $nbt->setInt("TileZ", (int) $this->blockIn->z); - $this->namedtag->setByte("Facing", (int) $this->direction); - $this->namedtag->setByte("Direction", (int) $this->direction); //Save both for full compatibility + $nbt->setByte("Facing", (int) $this->direction); + $nbt->setByte("Direction", (int) $this->direction); //Save both for full compatibility + + return $nbt; } public function kill() : void{ diff --git a/src/pocketmine/entity/object/PrimedTNT.php b/src/pocketmine/entity/object/PrimedTNT.php index b7839c2b3..5db3438fa 100644 --- a/src/pocketmine/entity/object/PrimedTNT.php +++ b/src/pocketmine/entity/object/PrimedTNT.php @@ -28,6 +28,7 @@ use pocketmine\entity\Explosive; use pocketmine\event\entity\EntityDamageEvent; use pocketmine\event\entity\ExplosionPrimeEvent; use pocketmine\level\Explosion; +use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\ShortTag; use pocketmine\network\mcpe\protocol\LevelEventPacket; @@ -53,11 +54,11 @@ class PrimedTNT extends Entity implements Explosive{ } } - protected function initEntity() : void{ - parent::initEntity(); + protected function initEntity(CompoundTag $nbt) : void{ + parent::initEntity($nbt); - if($this->namedtag->hasTag("Fuse", ShortTag::class)){ - $this->fuse = $this->namedtag->getShort("Fuse"); + if($nbt->hasTag("Fuse", ShortTag::class)){ + $this->fuse = $nbt->getShort("Fuse"); }else{ $this->fuse = 80; } @@ -73,9 +74,11 @@ class PrimedTNT extends Entity implements Explosive{ return false; } - public function saveNBT() : void{ - parent::saveNBT(); - $this->namedtag->setShort("Fuse", $this->fuse, true); //older versions incorrectly saved this as a byte + public function saveNBT() : CompoundTag{ + $nbt = parent::saveNBT(); + $nbt->setShort("Fuse", $this->fuse, true); //older versions incorrectly saved this as a byte + + return $nbt; } public function entityBaseTick(int $tickDiff = 1) : bool{ diff --git a/src/pocketmine/entity/projectile/Arrow.php b/src/pocketmine/entity/projectile/Arrow.php index ee2716e5a..92409071e 100644 --- a/src/pocketmine/entity/projectile/Arrow.php +++ b/src/pocketmine/entity/projectile/Arrow.php @@ -66,16 +66,16 @@ class Arrow extends Projectile{ $this->setCritical($critical); } - protected function initEntity() : void{ - parent::initEntity(); + protected function initEntity(CompoundTag $nbt) : void{ + parent::initEntity($nbt); - $this->pickupMode = $this->namedtag->getByte(self::TAG_PICKUP, self::PICKUP_ANY, true); + $this->pickupMode = $nbt->getByte(self::TAG_PICKUP, self::PICKUP_ANY, true); } - public function saveNBT() : void{ - parent::saveNBT(); - - $this->namedtag->setByte(self::TAG_PICKUP, $this->pickupMode, true); + public function saveNBT() : CompoundTag{ + $nbt = parent::saveNBT(); + $nbt->setByte(self::TAG_PICKUP, $this->pickupMode); + return $nbt; } public function isCritical() : bool{ diff --git a/src/pocketmine/entity/projectile/Projectile.php b/src/pocketmine/entity/projectile/Projectile.php index 66c0a1433..d6553cacd 100644 --- a/src/pocketmine/entity/projectile/Projectile.php +++ b/src/pocketmine/entity/projectile/Projectile.php @@ -69,33 +69,33 @@ abstract class Projectile extends Entity{ } } - protected function initEntity() : void{ - parent::initEntity(); + protected function initEntity(CompoundTag $nbt) : void{ + parent::initEntity($nbt); $this->setMaxHealth(1); $this->setHealth(1); - $this->age = $this->namedtag->getShort("Age", $this->age); - $this->damage = $this->namedtag->getDouble("damage", $this->damage); + $this->age = $nbt->getShort("Age", $this->age); + $this->damage = $nbt->getDouble("damage", $this->damage); do{ $blockHit = null; $blockId = null; $blockData = null; - if($this->namedtag->hasTag("tileX", IntTag::class) and $this->namedtag->hasTag("tileY", IntTag::class) and $this->namedtag->hasTag("tileZ", IntTag::class)){ - $blockHit = new Vector3($this->namedtag->getInt("tileX"), $this->namedtag->getInt("tileY"), $this->namedtag->getInt("tileZ")); + if($nbt->hasTag("tileX", IntTag::class) and $nbt->hasTag("tileY", IntTag::class) and $nbt->hasTag("tileZ", IntTag::class)){ + $blockHit = new Vector3($nbt->getInt("tileX"), $nbt->getInt("tileY"), $nbt->getInt("tileZ")); }else{ break; } - if($this->namedtag->hasTag("blockId", IntTag::class)){ - $blockId = $this->namedtag->getInt("blockId"); + if($nbt->hasTag("blockId", IntTag::class)){ + $blockId = $nbt->getInt("blockId"); }else{ break; } - if($this->namedtag->hasTag("blockData", ByteTag::class)){ - $blockData = $this->namedtag->getByte("blockData"); + if($nbt->hasTag("blockData", ByteTag::class)){ + $blockData = $nbt->getByte("blockData"); }else{ break; } @@ -141,21 +141,23 @@ abstract class Projectile extends Entity{ return (int) ceil($this->motion->length() * $this->damage); } - public function saveNBT() : void{ - parent::saveNBT(); + public function saveNBT() : CompoundTag{ + $nbt = parent::saveNBT(); - $this->namedtag->setShort("Age", $this->age); - $this->namedtag->setDouble("damage", $this->damage); + $nbt->setShort("Age", $this->age); + $nbt->setDouble("damage", $this->damage); if($this->blockHit !== null){ - $this->namedtag->setInt("tileX", $this->blockHit->x); - $this->namedtag->setInt("tileY", $this->blockHit->y); - $this->namedtag->setInt("tileZ", $this->blockHit->z); + $nbt->setInt("tileX", $this->blockHit->x); + $nbt->setInt("tileY", $this->blockHit->y); + $nbt->setInt("tileZ", $this->blockHit->z); //we intentionally use different ones to PC because we don't have stringy IDs - $this->namedtag->setInt("blockId", $this->blockHitId); - $this->namedtag->setByte("blockData", $this->blockHitData); + $nbt->setInt("blockId", $this->blockHitId); + $nbt->setByte("blockData", $this->blockHitData); } + + return $nbt; } protected function applyDragBeforeGravity() : bool{ diff --git a/src/pocketmine/entity/projectile/SplashPotion.php b/src/pocketmine/entity/projectile/SplashPotion.php index 4720a5c28..7ad93b639 100644 --- a/src/pocketmine/entity/projectile/SplashPotion.php +++ b/src/pocketmine/entity/projectile/SplashPotion.php @@ -31,6 +31,7 @@ use pocketmine\event\entity\ProjectileHitEntityEvent; use pocketmine\event\entity\ProjectileHitBlockEvent; use pocketmine\event\entity\ProjectileHitEvent; use pocketmine\item\Potion; +use pocketmine\nbt\tag\CompoundTag; use pocketmine\network\mcpe\protocol\LevelEventPacket; use pocketmine\network\mcpe\protocol\LevelSoundEventPacket; use pocketmine\utils\Color; @@ -42,15 +43,17 @@ class SplashPotion extends Throwable{ protected $gravity = 0.05; protected $drag = 0.01; - protected function initEntity() : void{ - parent::initEntity(); + protected function initEntity(CompoundTag $nbt) : void{ + parent::initEntity($nbt); - $this->setPotionId($this->namedtag->getShort("PotionId", 0)); + $this->setPotionId($nbt->getShort("PotionId", 0)); } - public function saveNBT() : void{ - parent::saveNBT(); - $this->namedtag->setShort("PotionId", $this->getPotionId()); + public function saveNBT() : CompoundTag{ + $nbt = parent::saveNBT(); + $nbt->setShort("PotionId", $this->getPotionId()); + + return $nbt; } public function getResultDamage() : int{ diff --git a/src/pocketmine/level/format/io/leveldb/LevelDB.php b/src/pocketmine/level/format/io/leveldb/LevelDB.php index 5b94d0f4c..71dbcb94f 100644 --- a/src/pocketmine/level/format/io/leveldb/LevelDB.php +++ b/src/pocketmine/level/format/io/leveldb/LevelDB.php @@ -464,8 +464,7 @@ class LevelDB extends BaseLevelProvider{ /** @var CompoundTag[] $entities */ $entities = []; foreach($chunk->getSavableEntities() as $entity){ - $entity->saveNBT(); - $entities[] = $entity->namedtag; + $entities[] = $entity->saveNBT(); } $this->writeTags($entities, $index . self::TAG_ENTITY); diff --git a/src/pocketmine/level/format/io/region/Anvil.php b/src/pocketmine/level/format/io/region/Anvil.php index 9cd69599f..5864d30f7 100644 --- a/src/pocketmine/level/format/io/region/Anvil.php +++ b/src/pocketmine/level/format/io/region/Anvil.php @@ -67,8 +67,7 @@ class Anvil extends McRegion{ $entities = []; foreach($chunk->getSavableEntities() as $entity){ - $entity->saveNBT(); - $entities[] = $entity->namedtag; + $entities[] = $entity->saveNBT(); } $nbt->setTag(new ListTag("Entities", $entities, NBT::TAG_Compound)); diff --git a/src/pocketmine/level/format/io/region/McRegion.php b/src/pocketmine/level/format/io/region/McRegion.php index c080b79a4..1f3f77bfc 100644 --- a/src/pocketmine/level/format/io/region/McRegion.php +++ b/src/pocketmine/level/format/io/region/McRegion.php @@ -86,8 +86,7 @@ class McRegion extends BaseLevelProvider{ $entities = []; foreach($chunk->getSavableEntities() as $entity){ - $entity->saveNBT(); - $entities[] = $entity->namedtag; + $entities[] = $entity->saveNBT(); } $nbt->setTag(new ListTag("Entities", $entities, NBT::TAG_Compound));