diff --git a/.gitmodules b/.gitmodules index df60ddab7..8dc22a2d7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,10 +1,3 @@ -[submodule "src/raklib"] - path = src/raklib - url = https://github.com/pmmp/RakLib.git - branch = master -[submodule "src/spl"] - path = src/spl - url = https://github.com/pmmp/PocketMine-SPL.git [submodule "src/pocketmine/lang/locale"] path = src/pocketmine/lang/locale url = https://github.com/pmmp/PocketMine-Language.git diff --git a/composer.json b/composer.json index 3c5b01883..1087d4eff 100644 --- a/composer.json +++ b/composer.json @@ -5,7 +5,7 @@ "homepage": "https://pmmp.io", "license": "LGPL-3.0", "require": { - "php": ">=7.2", + "php": ">=7.2.0RC3", "ext-bcmath": "*", "ext-curl": "*", "ext-hash": "*", @@ -20,14 +20,23 @@ "ext-spl": "*", "ext-yaml": ">=2.0.0", "ext-zip": "*", - "ext-zlib": ">=1.2.11" + "ext-zlib": ">=1.2.11", + "pmmp/raklib": "^0.9.0", + "pmmp/pocketmine-spl": "^0.0.2" }, "autoload": { - "exclude-from-classmap": [ - "src/spl/stubs" - ], "psr-0": { - "": ["src", "src/spl"] + "": ["src"] } - } + }, + "repositories": [ + { + "type": "vcs", + "url": "https://github.com/pmmp/RakLib" + }, + { + "type": "vcs", + "url": "https://github.com/pmmp/PocketMine-SPL" + } + ] } diff --git a/composer.lock b/composer.lock index f23e45dd8..22090967c 100644 --- a/composer.lock +++ b/composer.lock @@ -4,18 +4,89 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "d4fecad9dce5314493052c870c8cf059", - "packages": [], + "content-hash": "55bdbaf13ac4ea71f0705f03f715172d", + "packages": [ + { + "name": "pmmp/pocketmine-spl", + "version": "0.0.2", + "source": { + "type": "git", + "url": "https://github.com/pmmp/PocketMine-SPL.git", + "reference": "065b631d63e2c4ddb3141f63a07a9ecbab8357d1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pmmp/PocketMine-SPL/zipball/065b631d63e2c4ddb3141f63a07a9ecbab8357d1", + "reference": "065b631d63e2c4ddb3141f63a07a9ecbab8357d1", + "shasum": "" + }, + "type": "library", + "autoload": { + "exclude-from-classmap": [ + "stubs" + ], + "classmap": [ + "./" + ] + }, + "license": [ + "LGPL-3.0" + ], + "description": "Standard library files required by PocketMine-MP and related projects", + "support": { + "source": "https://github.com/pmmp/PocketMine-SPL/tree/0.0.2" + }, + "time": "2017-11-14T18:56:38+00:00" + }, + { + "name": "pmmp/raklib", + "version": "0.9.0", + "source": { + "type": "git", + "url": "https://github.com/pmmp/RakLib.git", + "reference": "08470471eb16b4325fa02415fd12c5060eba9c34" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pmmp/RakLib/zipball/08470471eb16b4325fa02415fd12c5060eba9c34", + "reference": "08470471eb16b4325fa02415fd12c5060eba9c34", + "shasum": "" + }, + "require": { + "ext-bcmath": "*", + "ext-pthreads": ">=3.1.7dev", + "ext-sockets": "*", + "php": ">=7.2.0RC3", + "pmmp/pocketmine-spl": "^0.0.2" + }, + "type": "library", + "autoload": { + "classmap": [ + "./" + ] + }, + "license": [ + "GPL-3.0" + ], + "description": "A RakNet server implementation written in PHP", + "support": { + "source": "https://github.com/pmmp/RakLib/tree/0.9.0", + "issues": "https://github.com/pmmp/RakLib/issues" + }, + "time": "2017-11-14T19:03:14+00:00" + } + ], "packages-dev": [], "aliases": [], "minimum-stability": "stable", "stability-flags": { + "php": 5, "ext-pthreads": 20 }, "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=7.2", + "php": ">=7.2.0RC3", "ext-bcmath": "*", "ext-curl": "*", "ext-hash": "*", diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index 1375040a9..17f6ace46 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -97,9 +97,7 @@ use pocketmine\metadata\MetadataValue; use pocketmine\nbt\NBT; use pocketmine\nbt\tag\ByteTag; use pocketmine\nbt\tag\CompoundTag; -use pocketmine\nbt\tag\IntTag; -use pocketmine\nbt\tag\LongTag; -use pocketmine\nbt\tag\StringTag; +use pocketmine\nbt\tag\ListTag; use pocketmine\network\mcpe\PlayerNetworkSessionAdapter; use pocketmine\network\mcpe\protocol\AdventureSettingsPacket; use pocketmine\network\mcpe\protocol\AnimatePacket; @@ -1331,7 +1329,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ $this->resetFallDistance(); - $this->namedtag->playerGameType = new IntTag("playerGameType", $this->gamemode); + $this->namedtag->setInt("playerGameType", $this->gamemode); if(!$client){ //Gamemode changed by server, do not send for client changes $this->sendGamemode(); }else{ @@ -1893,15 +1891,12 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ $this->namedtag = $this->server->getOfflinePlayerData($this->username); $this->playedBefore = ($this->namedtag["lastPlayed"] - $this->namedtag["firstPlayed"]) > 1; // microtime(true) - microtime(true) may have less than one millisecond difference - if(!isset($this->namedtag->NameTag)){ - $this->namedtag->NameTag = new StringTag("NameTag", $this->username); - }else{ - $this->namedtag["NameTag"] = $this->username; - } - $this->gamemode = $this->namedtag["playerGameType"] & 0x03; + $this->namedtag->setString("NameTag", $this->username); + + $this->gamemode = $this->namedtag->getInt("playerGameType", self::SURVIVAL) & 0x03; if($this->server->getForceGamemode()){ $this->gamemode = $this->server->getGamemode(); - $this->namedtag->playerGameType = new IntTag("playerGameType", $this->gamemode); + $this->namedtag->setInt("playerGameType", $this->gamemode); } $this->allowFlight = $this->isCreative(); @@ -1918,12 +1913,13 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ $this->achievements = []; + $achievements = $this->namedtag->getCompoundTag("Achievements") ?? []; /** @var ByteTag $achievement */ - foreach($this->namedtag->Achievements as $achievement){ + foreach($achievements as $achievement){ $this->achievements[$achievement->getName()] = $achievement->getValue() !== 0; } - $this->namedtag->lastPlayed = new LongTag("lastPlayed", (int) floor(microtime(true) * 1000)); + $this->namedtag->setLong("lastPlayed", (int) floor(microtime(true) * 1000)); if($this->server->getAutoSave()){ $this->server->saveOfflinePlayerData($this->username, $this->namedtag, true); } @@ -1950,8 +1946,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ } if(!$this->hasValidSpawnPosition()){ - if(isset($this->namedtag->SpawnLevel) and ($level = $this->server->getLevelByName((string) $this->namedtag["SpawnLevel"])) instanceof Level){ - $this->spawnPosition = new WeakPosition($this->namedtag["SpawnX"], $this->namedtag["SpawnY"], $this->namedtag["SpawnZ"], $level); + if(($level = $this->server->getLevelByName($this->namedtag->getString("SpawnLevel", ""))) instanceof Level){ + $this->spawnPosition = new WeakPosition($this->namedtag->getInt("SpawnX"), $this->namedtag->getInt("SpawnY"), $this->namedtag->getInt("SpawnZ"), $level); }else{ $this->spawnPosition = WeakPosition::fromObject($this->level->getSafeSpawn()); } @@ -3499,22 +3495,24 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ parent::saveNBT(); if($this->isValid()){ - $this->namedtag->Level = new StringTag("Level", $this->level->getFolderName()); + $this->namedtag->setString("Level", $this->level->getFolderName()); } if($this->hasValidSpawnPosition()){ - $this->namedtag->SpawnLevel = new StringTag("SpawnLevel", $this->spawnPosition->getLevel()->getFolderName()); - $this->namedtag->SpawnX = new IntTag("SpawnX", (int) $this->spawnPosition->x); - $this->namedtag->SpawnY = new IntTag("SpawnY", (int) $this->spawnPosition->y); - $this->namedtag->SpawnZ = new IntTag("SpawnZ", (int) $this->spawnPosition->z); + $this->namedtag->setString("SpawnLevel", $this->spawnPosition->getLevel()->getFolderName()); + $this->namedtag->setInt("SpawnX", (int) $this->spawnPosition->x); + $this->namedtag->setInt("SpawnY", (int) $this->spawnPosition->y); + $this->namedtag->setInt("SpawnZ", (int) $this->spawnPosition->z); } + $achievements = new CompoundTag("Achievements"); foreach($this->achievements as $achievement => $status){ - $this->namedtag->Achievements[$achievement] = new ByteTag($achievement, $status === true ? 1 : 0); + $achievements->setByte($achievement, $status === true ? 1 : 0); } + $this->namedtag->setTag($achievements); - $this->namedtag["playerGameType"] = $this->gamemode; - $this->namedtag["lastPlayed"] = (int) floor(microtime(true) * 1000); + $this->namedtag->setInt("playerGameType", $this->gamemode); + $this->namedtag->setLong("lastPlayed", (int) floor(microtime(true) * 1000)); if($this->username != "" and $this->namedtag instanceof CompoundTag){ $this->server->saveOfflinePlayerData($this->username, $this->namedtag, $async); diff --git a/src/pocketmine/PocketMine.php b/src/pocketmine/PocketMine.php index 5c28a70b1..1b5b774d0 100644 --- a/src/pocketmine/PocketMine.php +++ b/src/pocketmine/PocketMine.php @@ -129,30 +129,16 @@ namespace pocketmine { define('pocketmine\PATH', dirname(__FILE__, 3) . DIRECTORY_SEPARATOR); } - $requiredSplVer = "0.0.1"; - if(!is_file(\pocketmine\PATH . "src/spl/version.php")){ - echo "[CRITICAL] Cannot find PocketMine-SPL or incompatible version." . PHP_EOL; - echo "[CRITICAL] Please update your submodules or use provided builds." . PHP_EOL; - exit(1); - }elseif(version_compare($requiredSplVer, require(\pocketmine\PATH . "src/spl/version.php")) > 0){ - echo "[CRITICAL] Incompatible PocketMine-SPL submodule version ($requiredSplVer is required)." . PHP_EOL; - echo "[CRITICAL] Please update your submodules or use provided builds." . PHP_EOL; - exit(1); - } + define('pocketmine\COMPOSER_AUTOLOADER_PATH', \pocketmine\PATH . 'vendor/autoload.php'); - if(is_file(\pocketmine\PATH . "vendor/autoload.php")){ - require_once(\pocketmine\PATH . "vendor/autoload.php"); + if(is_file(\pocketmine\COMPOSER_AUTOLOADER_PATH)){ + require_once(\pocketmine\COMPOSER_AUTOLOADER_PATH); }else{ echo "[CRITICAL] Composer autoloader not found" . PHP_EOL; echo "[CRITICAL] Please initialize composer dependencies before running." . PHP_EOL; exit(1); } - if(!class_exists("ClassLoader", false)){ - require_once(\pocketmine\PATH . "src/spl/ClassLoader.php"); - require_once(\pocketmine\PATH . "src/spl/BaseClassLoader.php"); - } - /* * We now use the Composer autoloader, but this autoloader is still used by RakLib and for loading plugins. */ diff --git a/src/pocketmine/block/BurningFurnace.php b/src/pocketmine/block/BurningFurnace.php index fa652b8dd..6c396aff0 100644 --- a/src/pocketmine/block/BurningFurnace.php +++ b/src/pocketmine/block/BurningFurnace.php @@ -77,10 +77,8 @@ class BurningFurnace extends Solid{ $furnace = Tile::createTile(Tile::FURNACE, $this->getLevel(), TileFurnace::createNBT($this)); } - if(isset($furnace->namedtag->Lock) and $furnace->namedtag->Lock instanceof StringTag){ - if($furnace->namedtag->Lock->getValue() !== $item->getCustomName()){ - return true; - } + if($furnace->namedtag->hasTag("Lock", StringTag::class) and $furnace->namedtag->getString("Lock") !== $item->getCustomName()){ + return true; } $player->addWindow($furnace->getInventory()); diff --git a/src/pocketmine/block/Chest.php b/src/pocketmine/block/Chest.php index dd413e737..b318bf25a 100644 --- a/src/pocketmine/block/Chest.php +++ b/src/pocketmine/block/Chest.php @@ -126,7 +126,7 @@ class Chest extends Transparent{ if( !$this->getSide(Vector3::SIDE_UP)->isTransparent() or ($chest->isPaired() and !$chest->getPair()->getBlock()->getSide(Vector3::SIDE_UP)->isTransparent()) or - (isset($chest->namedtag->Lock) and $chest->namedtag->Lock instanceof StringTag and $chest->namedtag->Lock->getValue() !== $item->getCustomName()) + ($chest->namedtag->hasTag("Lock", StringTag::class) and $chest->namedtag->getString("Lock") !== $item->getCustomName()) ){ return true; } diff --git a/src/pocketmine/entity/Entity.php b/src/pocketmine/entity/Entity.php index 8916ccb87..be19f187c 100644 --- a/src/pocketmine/entity/Entity.php +++ b/src/pocketmine/entity/Entity.php @@ -51,12 +51,10 @@ use pocketmine\math\Vector2; use pocketmine\math\Vector3; use pocketmine\metadata\Metadatable; use pocketmine\metadata\MetadataValue; -use pocketmine\nbt\tag\ByteTag; use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\DoubleTag; use pocketmine\nbt\tag\FloatTag; use pocketmine\nbt\tag\ListTag; -use pocketmine\nbt\tag\ShortTag; use pocketmine\nbt\tag\StringTag; use pocketmine\network\mcpe\protocol\AddEntityPacket; use pocketmine\network\mcpe\protocol\EntityEventPacket; @@ -504,53 +502,36 @@ abstract class Entity extends Location implements Metadatable, EntityIds{ $this->server = $level->getServer(); $this->boundingBox = new AxisAlignedBB(0, 0, 0, 0, 0, 0); - $this->setPositionAndRotation( - $this->temporalVector->setComponents( - $this->namedtag["Pos"][0], - $this->namedtag["Pos"][1], - $this->namedtag["Pos"][2] - ), - $this->namedtag->Rotation[0], - $this->namedtag->Rotation[1] - ); - if(isset($this->namedtag->Motion)){ - $this->setMotion($this->temporalVector->setComponents($this->namedtag["Motion"][0], $this->namedtag["Motion"][1], $this->namedtag["Motion"][2])); - }else{ - $this->setMotion($this->temporalVector->setComponents(0, 0, 0)); + /** @var float[] $pos */ + $pos = $this->namedtag->getListTag("Pos")->getAllValues(); + /** @var float[] $rotation */ + $rotation = $this->namedtag->getListTag("Rotation")->getAllValues(); + + $this->setPositionAndRotation($this->temporalVector->setComponents(...$pos), ...$rotation); + + /** @var float[] $motion */ + $motion = [0, 0, 0]; + if($this->namedtag->hasTag("Motion", ListTag::class)){ + $motion = $this->namedtag->getListTag("Motion")->getAllValues(); } + $this->setMotion($this->temporalVector->setComponents(...$motion)); + $this->resetLastMovements(); 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)); - if(!isset($this->namedtag->FallDistance)){ - $this->namedtag->FallDistance = new FloatTag("FallDistance", 0); - } - $this->fallDistance = $this->namedtag["FallDistance"]; + $this->fallDistance = $this->namedtag->getFloat("FallDistance", 0); - if(!isset($this->namedtag->Fire)){ - $this->namedtag->Fire = new ShortTag("Fire", 0); - } - $this->fireTicks = (int) $this->namedtag["Fire"]; + $this->fireTicks = $this->namedtag->getShort("Fire", 0); if($this->isOnFire()){ $this->setGenericFlag(self::DATA_FLAG_ONFIRE); } - if(!isset($this->namedtag->Air)){ - $this->namedtag->Air = new ShortTag("Air", 300); - } - $this->setDataProperty(self::DATA_AIR, self::DATA_TYPE_SHORT, $this->namedtag["Air"], false); - - if(!isset($this->namedtag->OnGround)){ - $this->namedtag->OnGround = new ByteTag("OnGround", 0); - } - $this->onGround = $this->namedtag["OnGround"] !== 0; - - if(!isset($this->namedtag->Invulnerable)){ - $this->namedtag->Invulnerable = new ByteTag("Invulnerable", 0); - } - $this->invulnerable = $this->namedtag["Invulnerable"] !== 0; + $this->setDataProperty(self::DATA_AIR, self::DATA_TYPE_SHORT, $this->namedtag->getShort("Air", 300), false); + $this->onGround = $this->namedtag->getByte("OnGround", 0) !== 0; + $this->invulnerable = $this->namedtag->getByte("Invulnerable", 0) !== 0; $this->attributeMap = new AttributeMap(); $this->addAttributes(); @@ -816,49 +797,46 @@ abstract class Entity extends Location implements Metadatable, EntityIds{ public function saveNBT(){ if(!($this instanceof Player)){ - $this->namedtag->id = new StringTag("id", $this->getSaveId()); + $this->namedtag->setString("id", $this->getSaveId(), true); if($this->getNameTag() !== ""){ - $this->namedtag->CustomName = new StringTag("CustomName", $this->getNameTag()); - $this->namedtag->CustomNameVisible = new ByteTag("CustomNameVisible", $this->isNameTagVisible() ? 1 : 0); + $this->namedtag->setString("CustomName", $this->getNameTag()); + $this->namedtag->setByte("CustomNameVisible", $this->isNameTagVisible() ? 1 : 0); }else{ - unset($this->namedtag->CustomName); - unset($this->namedtag->CustomNameVisible); + $this->namedtag->removeTag("CustomName", "CustomNameVisible"); } } - $this->namedtag->Pos = new ListTag("Pos", [ + $this->namedtag->setTag(new ListTag("Pos", [ new DoubleTag("", $this->x), new DoubleTag("", $this->y), new DoubleTag("", $this->z) - ]); + ])); - $this->namedtag->Motion = new ListTag("Motion", [ + $this->namedtag->setTag(new ListTag("Motion", [ new DoubleTag("", $this->motionX), new DoubleTag("", $this->motionY), new DoubleTag("", $this->motionZ) - ]); + ])); - $this->namedtag->Rotation = new ListTag("Rotation", [ + $this->namedtag->setTag(new ListTag("Rotation", [ new FloatTag("", $this->yaw), new FloatTag("", $this->pitch) - ]); + ])); - $this->namedtag->FallDistance = new FloatTag("FallDistance", $this->fallDistance); - $this->namedtag->Fire = new ShortTag("Fire", $this->fireTicks); - $this->namedtag->Air = new ShortTag("Air", $this->getDataProperty(self::DATA_AIR)); - $this->namedtag->OnGround = new ByteTag("OnGround", $this->onGround ? 1 : 0); - $this->namedtag->Invulnerable = new ByteTag("Invulnerable", $this->invulnerable ? 1 : 0); + $this->namedtag->setFloat("FallDistance", $this->fallDistance); + $this->namedtag->setShort("Fire", $this->fireTicks); + $this->namedtag->setShort("Air", $this->getDataProperty(self::DATA_AIR)); + $this->namedtag->setByte("OnGround", $this->onGround ? 1 : 0); + $this->namedtag->setByte("Invulnerable", $this->invulnerable ? 1 : 0); } protected function initEntity(){ assert($this->namedtag instanceof CompoundTag); - if(isset($this->namedtag->CustomName)){ - $this->setNameTag($this->namedtag["CustomName"]); - if(isset($this->namedtag->CustomNameVisible)){ - $this->setNameTagVisible($this->namedtag["CustomNameVisible"] > 0); - } + if($this->namedtag->hasTag("CustomName", StringTag::class)){ + $this->setNameTag($this->namedtag->getString("CustomName")); + $this->setNameTagVisible($this->namedtag->getByte("CustomNameVisible", 1) !== 0); } $this->scheduleUpdate(); @@ -1709,6 +1687,8 @@ abstract class Entity extends Location implements Metadatable, EntityIds{ $radius = $this->width / 2; $this->boundingBox->setBounds($pos->x - $radius, $pos->y, $pos->z - $radius, $pos->x + $radius, $pos->y + $this->height, $pos->z + $radius); + $this->blocksAround = null; + $this->checkChunks(); return true; diff --git a/src/pocketmine/entity/FallingSand.php b/src/pocketmine/entity/FallingSand.php index 7ce9f7200..92be9c3d5 100644 --- a/src/pocketmine/entity/FallingSand.php +++ b/src/pocketmine/entity/FallingSand.php @@ -53,17 +53,13 @@ class FallingSand extends Entity{ parent::initEntity(); $blockId = 0; - $damage = 0; - if(isset($this->namedtag->TileID)){ - $blockId = (int) $this->namedtag["TileID"]; - }elseif(isset($this->namedtag->Tile)){ - $blockId = (int) $this->namedtag["Tile"]; - $this->namedtag["TileID"] = new IntTag("TileID", $blockId); - } - - if(isset($this->namedtag->Data)){ - $damage = (int) $this->namedtag["Data"]; + //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($blockId === 0){ @@ -71,6 +67,8 @@ class FallingSand extends Entity{ return; } + $damage = $this->namedtag->getByte("Data", 0); + $this->block = BlockFactory::get($blockId, $damage); $this->setDataProperty(self::DATA_VARIANT, self::DATA_TYPE_INT, $this->block->getId() | ($this->block->getDamage() << 8)); @@ -132,7 +130,7 @@ class FallingSand extends Entity{ } public function saveNBT(){ - $this->namedtag->TileID = new IntTag("TileID", $this->block->getId()); - $this->namedtag->Data = new ByteTag("Data", $this->block->getDamage()); + $this->namedtag->setInt("TileID", $this->block->getId(), true); + $this->namedtag->setByte("Data", $this->block->getDamage()); } } diff --git a/src/pocketmine/entity/Human.php b/src/pocketmine/entity/Human.php index f53c494eb..04a8c943a 100644 --- a/src/pocketmine/entity/Human.php +++ b/src/pocketmine/entity/Human.php @@ -34,7 +34,6 @@ use pocketmine\item\Item as ItemItem; use pocketmine\level\Level; use pocketmine\nbt\NBT; use pocketmine\nbt\tag\CompoundTag; -use pocketmine\nbt\tag\FloatTag; use pocketmine\nbt\tag\IntTag; use pocketmine\nbt\tag\ListTag; use pocketmine\nbt\tag\StringTag; @@ -311,14 +310,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. */ protected function initHumanData(){ - if(isset($this->namedtag->NameTag)){ - $this->setNameTag($this->namedtag["NameTag"]); + if($this->namedtag->hasTag("NameTag", StringTag::class)){ + $this->setNameTag($this->namedtag->getString("NameTag")); } - if(isset($this->namedtag->Skin) and $this->namedtag->Skin instanceof CompoundTag){ + $skin = $this->namedtag->getCompoundTag("Skin"); + if($skin !== null){ $this->setSkin(new Skin( - $this->namedtag->Skin["Name"], - $this->namedtag->Skin["Data"] + $skin->getString("Name"), + $skin->getString("Data") )); } @@ -333,71 +333,39 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ $this->inventory = new PlayerInventory($this); $this->initHumanData(); - if(isset($this->namedtag->Inventory) and $this->namedtag->Inventory instanceof ListTag){ - foreach($this->namedtag->Inventory as $i => $item){ - if($item["Slot"] >= 0 and $item["Slot"] < 9){ //Hotbar + $inventoryTag = $this->namedtag->getListTag("Inventory"); + if($inventoryTag !== null){ + /** @var CompoundTag $item */ + foreach($inventoryTag as $i => $item){ + $slot = $item->getByte("Slot"); + if($slot >= 0 and $slot < 9){ //Hotbar //Old hotbar saving stuff, remove it (useless now) - unset($this->namedtag->Inventory->{$i}); - }elseif($item["Slot"] >= 100 and $item["Slot"] < 104){ //Armor - $this->inventory->setItem($this->inventory->getSize() + $item["Slot"] - 100, ItemItem::nbtDeserialize($item)); + unset($inventoryTag[$i]); + }elseif($slot >= 100 and $slot < 104){ //Armor + $this->inventory->setItem($this->inventory->getSize() + $slot - 100, ItemItem::nbtDeserialize($item)); }else{ - $this->inventory->setItem($item["Slot"] - 9, ItemItem::nbtDeserialize($item)); + $this->inventory->setItem($slot - 9, ItemItem::nbtDeserialize($item)); } } } - if(isset($this->namedtag->SelectedInventorySlot) and $this->namedtag->SelectedInventorySlot instanceof IntTag){ - $this->inventory->setHeldItemIndex($this->namedtag->SelectedInventorySlot->getValue(), false); - }else{ - $this->inventory->setHeldItemIndex(0, false); - } + $this->inventory->setHeldItemIndex($this->namedtag->getInt("SelectedInventorySlot", 0), false); parent::initEntity(); - if(!isset($this->namedtag->foodLevel) or !($this->namedtag->foodLevel instanceof IntTag)){ - $this->namedtag->foodLevel = new IntTag("foodLevel", (int) $this->getFood()); - }else{ - $this->setFood((float) $this->namedtag["foodLevel"]); - } + $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); - if(!isset($this->namedtag->foodExhaustionLevel) or !($this->namedtag->foodExhaustionLevel instanceof FloatTag)){ - $this->namedtag->foodExhaustionLevel = new FloatTag("foodExhaustionLevel", $this->getExhaustion()); - }else{ - $this->setExhaustion((float) $this->namedtag["foodExhaustionLevel"]); - } + $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); - if(!isset($this->namedtag->foodSaturationLevel) or !($this->namedtag->foodSaturationLevel instanceof FloatTag)){ - $this->namedtag->foodSaturationLevel = new FloatTag("foodSaturationLevel", $this->getSaturation()); + if($this->namedtag->hasTag("XpSeed", IntTag::class)){ + $this->xpSeed = $this->namedtag->getInt("XpSeed"); }else{ - $this->setSaturation((float) $this->namedtag["foodSaturationLevel"]); - } - - if(!isset($this->namedtag->foodTickTimer) or !($this->namedtag->foodTickTimer instanceof IntTag)){ - $this->namedtag->foodTickTimer = new IntTag("foodTickTimer", $this->foodTickTimer); - }else{ - $this->foodTickTimer = $this->namedtag["foodTickTimer"]; - } - - if(!isset($this->namedtag->XpLevel) or !($this->namedtag->XpLevel instanceof IntTag)){ - $this->namedtag->XpLevel = new IntTag("XpLevel", $this->getXpLevel()); - }else{ - $this->setXpLevel((int) $this->namedtag["XpLevel"]); - } - - if(!isset($this->namedtag->XpP) or !($this->namedtag->XpP instanceof FloatTag)){ - $this->namedtag->XpP = new FloatTag("XpP", $this->getXpProgress()); - } - - if(!isset($this->namedtag->XpTotal) or !($this->namedtag->XpTotal instanceof IntTag)){ - $this->namedtag->XpTotal = new IntTag("XpTotal", $this->totalXp); - }else{ - $this->totalXp = $this->namedtag["XpTotal"]; - } - - if(!isset($this->namedtag->XpSeed) or !($this->namedtag->XpSeed instanceof IntTag)){ - $this->namedtag->XpSeed = new IntTag("XpSeed", $this->xpSeed ?? ($this->xpSeed = mt_rand(-0x80000000, 0x7fffffff))); - }else{ - $this->xpSeed = $this->namedtag["XpSeed"]; + $this->xpSeed = random_int(INT32_MIN, INT32_MAX); } } @@ -479,19 +447,25 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ public function saveNBT(){ parent::saveNBT(); - $this->namedtag->foodLevel = new IntTag("foodLevel", (int) $this->getFood()); - $this->namedtag->foodExhaustionLevel = new FloatTag("foodExhaustionLevel", $this->getExhaustion()); - $this->namedtag->foodSaturationLevel = new FloatTag("foodSaturationLevel", $this->getSaturation()); - $this->namedtag->foodTickTimer = new IntTag("foodTickTimer", $this->foodTickTimer); + $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); - $this->namedtag->Inventory = new ListTag("Inventory", [], NBT::TAG_Compound); + $this->namedtag->setInt("XpLevel", $this->getXpLevel()); + $this->namedtag->setFloat("XpP", $this->getXpProgress()); + $this->namedtag->setInt("XpTotal", $this->totalXp); + $this->namedtag->setInt("XpSeed", $this->xpSeed); + + $inventoryTag = new ListTag("Inventory", [], NBT::TAG_Compound); + $this->namedtag->setTag($inventoryTag); if($this->inventory !== null){ //Normal inventory $slotCount = $this->inventory->getSize() + $this->inventory->getHotbarSize(); for($slot = $this->inventory->getHotbarSize(); $slot < $slotCount; ++$slot){ $item = $this->inventory->getItem($slot - 9); if(!$item->isNull()){ - $this->namedtag->Inventory[$slot] = $item->nbtSerialize($slot); + $inventoryTag[$slot] = $item->nbtSerialize($slot); } } @@ -499,19 +473,19 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ for($slot = 100; $slot < 104; ++$slot){ $item = $this->inventory->getItem($this->inventory->getSize() + $slot - 100); if(!$item->isNull()){ - $this->namedtag->Inventory[$slot] = $item->nbtSerialize($slot); + $inventoryTag[$slot] = $item->nbtSerialize($slot); } } - $this->namedtag->SelectedInventorySlot = new IntTag("SelectedInventorySlot", $this->inventory->getHeldItemIndex()); + $this->namedtag->setInt("SelectedInventorySlot", $this->inventory->getHeldItemIndex()); } if($this->skin !== null){ - $this->namedtag->Skin = new CompoundTag("Skin", [ + $this->namedtag->setTag(new CompoundTag("Skin", [ //TODO: save cape & geometry new StringTag("Data", $this->skin->getSkinData()), new StringTag("Name", $this->skin->getSkinId()) - ]); + ])); } } diff --git a/src/pocketmine/entity/Item.php b/src/pocketmine/entity/Item.php index e8b0b4baf..16536bc2c 100644 --- a/src/pocketmine/entity/Item.php +++ b/src/pocketmine/entity/Item.php @@ -27,9 +27,6 @@ use pocketmine\event\entity\EntityDamageEvent; use pocketmine\event\entity\ItemDespawnEvent; use pocketmine\event\entity\ItemSpawnEvent; use pocketmine\item\Item as ItemItem; -use pocketmine\nbt\tag\CompoundTag; -use pocketmine\nbt\tag\ShortTag; -use pocketmine\nbt\tag\StringTag; use pocketmine\network\mcpe\protocol\AddItemEntityPacket; use pocketmine\Player; @@ -59,28 +56,19 @@ class Item extends Entity{ $this->setMaxHealth(5); $this->setHealth((int) $this->namedtag["Health"]); - if(isset($this->namedtag->Age)){ - $this->age = $this->namedtag["Age"]; - } - if(isset($this->namedtag->PickupDelay)){ - $this->pickupDelay = $this->namedtag["PickupDelay"]; - } - if(isset($this->namedtag->Owner)){ - $this->owner = $this->namedtag["Owner"]; - } - if(isset($this->namedtag->Thrower)){ - $this->thrower = $this->namedtag["Thrower"]; - } + $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); - if(!isset($this->namedtag->Item)){ + $itemTag = $this->namedtag->getCompoundTag("Item"); + if($itemTag === null){ $this->close(); return; } - assert($this->namedtag->Item instanceof CompoundTag); - - $this->item = ItemItem::nbtDeserialize($this->namedtag->Item); + $this->item = ItemItem::nbtDeserialize($itemTag); $this->server->getPluginManager()->callEvent(new ItemSpawnEvent($this)); @@ -139,15 +127,15 @@ class Item extends Entity{ public function saveNBT(){ parent::saveNBT(); - $this->namedtag->Item = $this->item->nbtSerialize(-1, "Item"); - $this->namedtag->Health = new ShortTag("Health", (int) $this->getHealth()); - $this->namedtag->Age = new ShortTag("Age", $this->age); - $this->namedtag->PickupDelay = new ShortTag("PickupDelay", $this->pickupDelay); + $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); if($this->owner !== null){ - $this->namedtag->Owner = new StringTag("Owner", $this->owner); + $this->namedtag->setString("Owner", $this->owner); } if($this->thrower !== null){ - $this->namedtag->Thrower = new StringTag("Thrower", $this->thrower); + $this->namedtag->setString("Thrower", $this->thrower); } } diff --git a/src/pocketmine/entity/Living.php b/src/pocketmine/entity/Living.php index 520e5f7ee..af30d026a 100644 --- a/src/pocketmine/entity/Living.php +++ b/src/pocketmine/entity/Living.php @@ -65,29 +65,33 @@ abstract class Living extends Entity implements Damageable{ protected function initEntity(){ parent::initEntity(); - if(isset($this->namedtag->HealF)){ - $this->namedtag->Health = new FloatTag("Health", (float) $this->namedtag["HealF"]); - unset($this->namedtag->HealF); - }elseif(isset($this->namedtag->Health)){ - if(!($this->namedtag->Health instanceof FloatTag)){ - $this->namedtag->Health = new FloatTag("Health", (float) $this->namedtag->Health->getValue()); + $health = $this->getMaxHealth(); + + if($this->namedtag->hasTag("HealF", FloatTag::class)){ + $health = new FloatTag("Health", (float) $this->namedtag["HealF"]); + $this->namedtag->removeTag("HealF"); + }elseif($this->namedtag->hasTag("Health")){ + $healthTag = $this->namedtag->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"); } - }else{ - $this->namedtag->Health = new FloatTag("Health", (float) $this->getMaxHealth()); } - $this->setHealth((float) $this->namedtag["Health"]); + $this->setHealth($health); - if(isset($this->namedtag->ActiveEffects)){ - foreach($this->namedtag->ActiveEffects->getValue() as $e){ - $amplifier = Binary::unsignByte($e->Amplifier->getValue()); //0-255 only + /** @var CompoundTag[]|ListTag $activeEffectsTag */ + $activeEffectsTag = $this->namedtag->getListTag("ActiveEffects"); + if($activeEffectsTag !== null){ + foreach($activeEffectsTag as $e){ + $amplifier = Binary::unsignByte($e->getByte("Amplifier")); //0-255 only - $effect = Effect::getEffect($e["Id"]); + $effect = Effect::getEffect($e->getByte("Id")); if($effect === null){ continue; } - $effect->setAmplifier($amplifier)->setDuration($e["Duration"])->setVisible($e["ShowParticles"] > 0); + $effect->setAmplifier($amplifier)->setDuration($e->getInt("Duration"))->setVisible($e->getByte("ShowParticles", 1) > 0); $this->addEffect($effect); } @@ -130,7 +134,7 @@ abstract class Living extends Entity implements Damageable{ public function saveNBT(){ parent::saveNBT(); - $this->namedtag->Health = new FloatTag("Health", $this->getHealth()); + $this->namedtag->setFloat("Health", $this->getHealth(), true); if(count($this->effects) > 0){ $effects = []; @@ -144,9 +148,9 @@ abstract class Living extends Entity implements Damageable{ ]); } - $this->namedtag->ActiveEffects = new ListTag("ActiveEffects", $effects); + $this->namedtag->setTag(new ListTag("ActiveEffects", $effects)); }else{ - unset($this->namedtag->ActiveEffects); + $this->namedtag->removeTag("ActiveEffects"); } } diff --git a/src/pocketmine/entity/PrimedTNT.php b/src/pocketmine/entity/PrimedTNT.php index 783067bbc..3b6489456 100644 --- a/src/pocketmine/entity/PrimedTNT.php +++ b/src/pocketmine/entity/PrimedTNT.php @@ -26,7 +26,7 @@ namespace pocketmine\entity; use pocketmine\event\entity\EntityDamageEvent; use pocketmine\event\entity\ExplosionPrimeEvent; use pocketmine\level\Explosion; -use pocketmine\nbt\tag\ByteTag; +use pocketmine\nbt\tag\ShortTag; use pocketmine\network\mcpe\protocol\LevelEventPacket; class PrimedTNT extends Entity implements Explosive{ @@ -54,8 +54,8 @@ class PrimedTNT extends Entity implements Explosive{ protected function initEntity(){ parent::initEntity(); - if(isset($this->namedtag->Fuse)){ - $this->fuse = $this->namedtag["Fuse"]; + if($this->namedtag->hasTag("Fuse", ShortTag::class)){ + $this->fuse = $this->namedtag->getShort("Fuse"); }else{ $this->fuse = 80; } @@ -73,7 +73,7 @@ class PrimedTNT extends Entity implements Explosive{ public function saveNBT(){ parent::saveNBT(); - $this->namedtag->Fuse = new ByteTag("Fuse", $this->fuse); + $this->namedtag->setShort("Fuse", $this->fuse, true); //older versions incorrectly saved this as a byte } public function entityBaseTick(int $tickDiff = 1) : bool{ diff --git a/src/pocketmine/entity/Villager.php b/src/pocketmine/entity/Villager.php index f50a6a979..87c3ab1d2 100644 --- a/src/pocketmine/entity/Villager.php +++ b/src/pocketmine/entity/Villager.php @@ -23,8 +23,6 @@ declare(strict_types=1); namespace pocketmine\entity; -use pocketmine\nbt\tag\IntTag; - class Villager extends Creature implements NPC, Ageable{ const PROFESSION_FARMER = 0; const PROFESSION_LIBRARIAN = 1; @@ -45,7 +43,7 @@ class Villager extends Creature implements NPC, Ageable{ parent::initEntity(); /** @var int $profession */ - $profession = $this->namedtag["Profession"] ?? self::PROFESSION_FARMER; + $profession = $this->namedtag->getInt("Profession", self::PROFESSION_FARMER); if($profession > 4 or $profession < 0){ $profession = self::PROFESSION_FARMER; @@ -56,7 +54,7 @@ class Villager extends Creature implements NPC, Ageable{ public function saveNBT(){ parent::saveNBT(); - $this->namedtag->Profession = new IntTag("Profession", $this->getProfession()); + $this->namedtag->setInt("Profession", $this->getProfession()); } /** diff --git a/src/pocketmine/entity/projectile/Projectile.php b/src/pocketmine/entity/projectile/Projectile.php index 7ec665d62..96b23deb1 100644 --- a/src/pocketmine/entity/projectile/Projectile.php +++ b/src/pocketmine/entity/projectile/Projectile.php @@ -34,7 +34,6 @@ use pocketmine\level\Level; use pocketmine\level\MovingObjectPosition; use pocketmine\math\Vector3; use pocketmine\nbt\tag\CompoundTag; -use pocketmine\nbt\tag\ShortTag; abstract class Projectile extends Entity{ @@ -62,9 +61,7 @@ abstract class Projectile extends Entity{ $this->setMaxHealth(1); $this->setHealth(1); - if(isset($this->namedtag->Age)){ - $this->age = $this->namedtag["Age"]; - } + $this->age = $this->namedtag->getShort("Age", $this->age); } public function canCollideWith(Entity $entity) : bool{ @@ -107,7 +104,7 @@ abstract class Projectile extends Entity{ public function saveNBT(){ parent::saveNBT(); - $this->namedtag->Age = new ShortTag("Age", $this->age); + $this->namedtag->setShort("Age", $this->age); } protected function applyDragBeforeGravity() : bool{ diff --git a/src/pocketmine/item/Item.php b/src/pocketmine/item/Item.php index dcaacae67..fffb09628 100644 --- a/src/pocketmine/item/Item.php +++ b/src/pocketmine/item/Item.php @@ -481,9 +481,7 @@ class Item implements ItemIds, \JsonSerializable{ public function getLore() : array{ $display = $this->getNamedTagEntry(self::TAG_DISPLAY); if($display instanceof CompoundTag and ($lore = $display->getListTag(self::TAG_DISPLAY_LORE)) !== null){ - return array_map(function(StringTag $tag) : string{ - return $tag->getValue(); - }, $lore->getValue()); + return $lore->getAllValues(); } return []; diff --git a/src/pocketmine/item/WritableBook.php b/src/pocketmine/item/WritableBook.php index 907d7188d..16a27ba9d 100644 --- a/src/pocketmine/item/WritableBook.php +++ b/src/pocketmine/item/WritableBook.php @@ -23,12 +23,15 @@ declare(strict_types=1); 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{ + const TAG_PAGES = "pages"; //TAG_List + public function __construct(int $meta = 0){ parent::__construct(self::WRITABLE_BOOK, $meta, "Book & Quill"); } @@ -41,7 +44,8 @@ class WritableBook extends Item{ * @return bool */ public function pageExists(int $pageId) : bool{ - return isset($this->getNamedTag()->pages->{$pageId}); + $pages = $this->getNamedTag()->getListTag(self::TAG_PAGES); + return $pages !== null and isset($pages[$pageId]); } /** @@ -52,10 +56,17 @@ class WritableBook extends Item{ * @return string|null */ public function getPageText(int $pageId) : ?string{ - if(!$this->pageExists($pageId)){ + $pages = $this->getNamedTag()->getListTag(self::TAG_PAGES); + if($pages === null){ return null; } - return $this->getNamedTag()->pages->{$pageId}->text->getValue(); + + $page = $pages[$pageId] ?? null; + if($page instanceof CompoundTag){ + return $page->getString("text", ""); + } + + return null; } /** @@ -74,7 +85,11 @@ class WritableBook extends Item{ } $namedTag = $this->getNamedTag(); - $namedTag->pages->{$pageId}->text->setValue($pageText); + /** @var CompoundTag[]|ListTag $pages */ + $pages = $namedTag->getListTag(self::TAG_PAGES); + assert($pages instanceof ListTag); + $pages[$pageId]->setString("text", $pageText); + $this->setNamedTag($namedTag); return $created; @@ -92,19 +107,19 @@ class WritableBook extends Item{ } $namedTag = $this->getNamedTag(); - if(!isset($namedTag->pages) or !($namedTag->pages instanceof ListTag)){ - $namedTag->pages = new ListTag("pages", []); - } + /** @var CompoundTag[]|ListTag $pages */ + $pages = $namedTag->getListTag(self::TAG_PAGES) ?? new ListTag(self::TAG_PAGES, [], NBT::TAG_Compound); for($id = 0; $id <= $pageId; $id++){ if(!$this->pageExists($id)){ - $namedTag->pages->{$id} = new CompoundTag("", [ + $pages[$id] = new CompoundTag("", [ new StringTag("text", ""), new StringTag("photoname", "") ]); } } + $namedTag->setTag($pages); $this->setNamedTag($namedTag); } @@ -121,7 +136,7 @@ class WritableBook extends Item{ } $namedTag = $this->getNamedTag(); - unset($namedTag->pages->{$pageId}); + unset($namedTag->getListTag(self::TAG_PAGES)[$pageId]); $this->pushPages($pageId, $namedTag); $this->setNamedTag($namedTag); @@ -186,6 +201,9 @@ class WritableBook extends Item{ return false; } + $pagesTag = $namedTag->getListTag(self::TAG_PAGES); + assert($pagesTag !== null); + $type = $downwards ? -1 : 1; foreach($pages as $key => $page){ if(($key <= $pageId and $downwards) or ($key < $pageId and !$downwards)){ @@ -193,9 +211,9 @@ class WritableBook extends Item{ } if($downwards){ - unset($namedTag->pages->{$key}); + unset($pagesTag[$key]); } - $namedTag->pages->{$key + $type} = new CompoundTag("", [ + $pagesTag[$key + $type] = new CompoundTag("", [ new StringTag("text", $page->text->getValue()), new StringTag("photoname", "") ]); diff --git a/src/pocketmine/item/WrittenBook.php b/src/pocketmine/item/WrittenBook.php index 29303fac5..22ff953c1 100644 --- a/src/pocketmine/item/WrittenBook.php +++ b/src/pocketmine/item/WrittenBook.php @@ -23,9 +23,6 @@ declare(strict_types=1); namespace pocketmine\item; -use pocketmine\nbt\tag\IntTag; -use pocketmine\nbt\tag\StringTag; - class WrittenBook extends WritableBook{ const GENERATION_ORIGINAL = 0; @@ -33,6 +30,10 @@ class WrittenBook extends WritableBook{ const GENERATION_COPY_OF_COPY = 2; const GENERATION_TATTERED = 3; + const TAG_GENERATION = "generation"; //TAG_Int + const TAG_AUTHOR = "author"; //TAG_String + const TAG_TITLE = "title"; //TAG_String + public function __construct(int $meta = 0){ Item::__construct(self::WRITTEN_BOOK, $meta, "Written Book"); } @@ -48,10 +49,7 @@ class WrittenBook extends WritableBook{ * @return int */ public function getGeneration() : int{ - if(!isset($this->getNamedTag()->generation)) { - return -1; - } - return $this->getNamedTag()->generation->getValue(); + return $this->getNamedTag()->getInt(self::TAG_GENERATION, -1); } /** @@ -64,12 +62,7 @@ class WrittenBook extends WritableBook{ throw new \InvalidArgumentException("Generation \"$generation\" is out of range"); } $namedTag = $this->getNamedTag(); - - if(isset($namedTag->generation)){ - $namedTag->generation->setValue($generation); - }else{ - $namedTag->generation = new IntTag("generation", $generation); - } + $namedTag->setInt(self::TAG_GENERATION, $generation); $this->setNamedTag($namedTag); } @@ -81,10 +74,7 @@ class WrittenBook extends WritableBook{ * @return string */ public function getAuthor() : string{ - if(!isset($this->getNamedTag()->author)){ - return ""; - } - return $this->getNamedTag()->author->getValue(); + return $this->getNamedTag()->getString(self::TAG_AUTHOR, ""); } /** @@ -94,11 +84,7 @@ class WrittenBook extends WritableBook{ */ public function setAuthor(string $authorName) : void{ $namedTag = $this->getNamedTag(); - if(isset($namedTag->author)){ - $namedTag->author->setValue($authorName); - }else{ - $namedTag->author = new StringTag("author", $authorName); - } + $namedTag->setString(self::TAG_AUTHOR, $authorName); $this->setNamedTag($namedTag); } @@ -108,10 +94,7 @@ class WrittenBook extends WritableBook{ * @return string */ public function getTitle() : string{ - if(!isset($this->getNamedTag()->title)){ - return ""; - } - return $this->getNamedTag()->title->getValue(); + return $this->getNamedTag()->getString(self::TAG_TITLE, ""); } /** @@ -121,11 +104,7 @@ class WrittenBook extends WritableBook{ */ public function setTitle(string $title) : void{ $namedTag = $this->getNamedTag(); - if(isset($namedTag->title)){ - $namedTag->title->setValue($title); - }else{ - $namedTag->title = new StringTag("title", $title); - } + $namedTag->setString(self::TAG_TITLE, $title); $this->setNamedTag($namedTag); } } \ No newline at end of file diff --git a/src/pocketmine/level/format/io/BaseLevelProvider.php b/src/pocketmine/level/format/io/BaseLevelProvider.php index eefe7ea98..806f1f0db 100644 --- a/src/pocketmine/level/format/io/BaseLevelProvider.php +++ b/src/pocketmine/level/format/io/BaseLevelProvider.php @@ -31,8 +31,6 @@ use pocketmine\level\LevelException; use pocketmine\math\Vector3; use pocketmine\nbt\NBT; use pocketmine\nbt\tag\CompoundTag; -use pocketmine\nbt\tag\IntTag; -use pocketmine\nbt\tag\LongTag; use pocketmine\nbt\tag\StringTag; use pocketmine\scheduler\AsyncTask; @@ -52,19 +50,19 @@ abstract class BaseLevelProvider implements LevelProvider{ } $nbt = new NBT(NBT::BIG_ENDIAN); $nbt->readCompressed(file_get_contents($this->getPath() . "level.dat")); - $levelData = $nbt->getData(); - if($levelData->Data instanceof CompoundTag){ - $this->levelData = $levelData->Data; + $levelData = $nbt->getData()->getCompoundTag("Data"); + if($levelData !== null){ + $this->levelData = $levelData; }else{ throw new LevelException("Invalid level.dat"); } - if(!isset($this->levelData->generatorName)){ - $this->levelData->generatorName = new StringTag("generatorName", (string) Generator::getGenerator("DEFAULT")); + if(!$this->levelData->hasTag("generatorName", StringTag::class)){ + $this->levelData->setString("generatorName", (string) Generator::getGenerator("DEFAULT"), true); } - if(!isset($this->levelData->generatorOptions)){ - $this->levelData->generatorOptions = new StringTag("generatorOptions", ""); + if(!$this->levelData->hasTag("generatorOptions", StringTag::class)){ + $this->levelData->setString("generatorOptions", ""); } } @@ -81,33 +79,33 @@ abstract class BaseLevelProvider implements LevelProvider{ } public function getName() : string{ - return (string) $this->levelData["LevelName"]; + return $this->levelData->getString("LevelName"); } public function getTime() : int{ - return $this->levelData["Time"]; + return $this->levelData->getLong("Time", 0, true); } public function setTime(int $value){ - $this->levelData->Time = new LongTag("Time", $value); + $this->levelData->setLong("Time", $value, true); //some older PM worlds had this in the wrong format } public function getSeed() : int{ - return $this->levelData["RandomSeed"]; + return $this->levelData->getLong("RandomSeed"); } public function setSeed(int $value){ - $this->levelData->RandomSeed = new LongTag("RandomSeed", $value); + $this->levelData->setLong("RandomSeed", $value); } public function getSpawn() : Vector3{ - return new Vector3((float) $this->levelData["SpawnX"], (float) $this->levelData["SpawnY"], (float) $this->levelData["SpawnZ"]); + return new Vector3($this->levelData->getInt("SpawnX"), $this->levelData->getInt("SpawnY"), $this->levelData->getInt("SpawnZ")); } public function setSpawn(Vector3 $pos){ - $this->levelData->SpawnX = new IntTag("SpawnX", (int) $pos->x); - $this->levelData->SpawnY = new IntTag("SpawnY", (int) $pos->y); - $this->levelData->SpawnZ = new IntTag("SpawnZ", (int) $pos->z); + $this->levelData->setInt("SpawnX", (int) $pos->x); + $this->levelData->setInt("SpawnY", (int) $pos->y); + $this->levelData->setInt("SpawnZ", (int) $pos->z); } public function doGarbageCollection(){ diff --git a/src/pocketmine/level/format/io/leveldb/LevelDB.php b/src/pocketmine/level/format/io/leveldb/LevelDB.php index 124e52185..0008eddec 100644 --- a/src/pocketmine/level/format/io/leveldb/LevelDB.php +++ b/src/pocketmine/level/format/io/leveldb/LevelDB.php @@ -96,26 +96,26 @@ class LevelDB extends BaseLevelProvider{ "compression" => LEVELDB_ZLIB_COMPRESSION ]); - if(isset($this->levelData->StorageVersion) and $this->levelData->StorageVersion->getValue() > self::CURRENT_STORAGE_VERSION){ - throw new LevelException("Specified LevelDB world format version is newer than the version supported by the server"); + if($this->levelData->getInt("StorageVersion", INT32_MAX, true) > self::CURRENT_STORAGE_VERSION){ + throw new LevelException("Specified LevelDB world format version is not supported by " . \pocketmine\NAME); } - if(!isset($this->levelData->generatorName)){ - if(isset($this->levelData->Generator)){ - switch((int) $this->levelData->Generator->getValue()){ //Detect correct generator from MCPE data + if(!$this->levelData->hasTag("generatorName", StringTag::class)){ + if($this->levelData->hasTag("Generator", IntTag::class)){ + switch($this->levelData->getInt("Generator")){ //Detect correct generator from MCPE data case self::GENERATOR_FLAT: - $this->levelData->generatorName = new StringTag("generatorName", (string) Generator::getGenerator("FLAT")); + $this->levelData->setString("generatorName", (string) Generator::getGenerator("FLAT")); if(($layers = $this->db->get(self::ENTRY_FLAT_WORLD_LAYERS)) !== false){ //Detect existing custom flat layers $layers = trim($layers, "[]"); }else{ $layers = "7,3,3,2"; } - $this->levelData->generatorOptions = new StringTag("generatorOptions", "2;" . $layers . ";1"); + $this->levelData->setString("generatorOptions", "2;" . $layers . ";1"); break; case self::GENERATOR_INFINITE: //TODO: add a null generator which does not generate missing chunks (to allow importing back to MCPE and generating more normal terrain without PocketMine messing things up) - $this->levelData->generatorName = new StringTag("generatorName", (string) Generator::getGenerator("DEFAULT")); - $this->levelData->generatorOptions = new StringTag("generatorOptions", ""); + $this->levelData->setString("generatorName", (string) Generator::getGenerator("DEFAULT")); + $this->levelData->setString("generatorOptions", ""); break; case self::GENERATOR_LIMITED: throw new LevelException("Limited worlds are not currently supported"); @@ -123,12 +123,12 @@ class LevelDB extends BaseLevelProvider{ throw new LevelException("Unknown LevelDB world format type, this level cannot be loaded"); } }else{ - $this->levelData->generatorName = new StringTag("generatorName", (string) Generator::getGenerator("DEFAULT")); + $this->levelData->setString("generatorName", (string) Generator::getGenerator("DEFAULT")); } } - if(!isset($this->levelData->generatorOptions)){ - $this->levelData->generatorOptions = new StringTag("generatorOptions", ""); + if(!$this->levelData->hasTag("generatorOptions", StringTag::class)){ + $this->levelData->setString("generatorOptions", ""); } } @@ -226,8 +226,8 @@ class LevelDB extends BaseLevelProvider{ } public function saveLevelData(){ - $this->levelData->NetworkVersion = new IntTag("NetworkVersion", ProtocolInfo::CURRENT_PROTOCOL); - $this->levelData->StorageVersion = new IntTag("StorageVersion", self::CURRENT_STORAGE_VERSION); + $this->levelData->setInt("NetworkVersion", ProtocolInfo::CURRENT_PROTOCOL); + $this->levelData->setInt("StorageVersion", self::CURRENT_STORAGE_VERSION); $nbt = new NBT(NBT::LITTLE_ENDIAN); $nbt->setData($this->levelData); @@ -251,11 +251,11 @@ class LevelDB extends BaseLevelProvider{ } public function getDifficulty() : int{ - return isset($this->levelData->Difficulty) ? $this->levelData->Difficulty->getValue() : Level::DIFFICULTY_NORMAL; + return $this->levelData->getInt("Difficulty", Level::DIFFICULTY_NORMAL); } public function setDifficulty(int $difficulty){ - $this->levelData->Difficulty = new IntTag("Difficulty", $difficulty); + $this->levelData->setInt("Difficulty", $difficulty); //yes, this is intended! (in PE: int, PC: byte) } public function getLoadedChunks() : array{ diff --git a/src/pocketmine/level/format/io/region/Anvil.php b/src/pocketmine/level/format/io/region/Anvil.php index 7e7268a04..56f7c085c 100644 --- a/src/pocketmine/level/format/io/region/Anvil.php +++ b/src/pocketmine/level/format/io/region/Anvil.php @@ -28,9 +28,10 @@ use pocketmine\level\format\ChunkException; use pocketmine\level\format\io\ChunkUtils; use pocketmine\level\format\SubChunk; use pocketmine\nbt\NBT; -use pocketmine\nbt\tag\{ - ByteArrayTag, ByteTag, CompoundTag, IntArrayTag, IntTag, ListTag, LongTag -}; +use pocketmine\nbt\tag\ByteArrayTag; +use pocketmine\nbt\tag\CompoundTag; +use pocketmine\nbt\tag\IntArrayTag; +use pocketmine\nbt\tag\ListTag; use pocketmine\utils\MainLogger; class Anvil extends McRegion{ @@ -39,28 +40,29 @@ class Anvil extends McRegion{ public function nbtSerialize(Chunk $chunk) : string{ $nbt = new CompoundTag("Level", []); - $nbt->xPos = new IntTag("xPos", $chunk->getX()); - $nbt->zPos = new IntTag("zPos", $chunk->getZ()); + $nbt->setInt("xPos", $chunk->getX()); + $nbt->setInt("zPos", $chunk->getZ()); - $nbt->V = new ByteTag("V", 1); - $nbt->LastUpdate = new LongTag("LastUpdate", 0); //TODO - $nbt->InhabitedTime = new LongTag("InhabitedTime", 0); //TODO - $nbt->TerrainPopulated = new ByteTag("TerrainPopulated", $chunk->isPopulated() ? 1 : 0); - $nbt->LightPopulated = new ByteTag("LightPopulated", $chunk->isLightPopulated() ? 1 : 0); + $nbt->setByte("V", 1); + $nbt->setLong("LastUpdate", 0); //TODO + $nbt->setLong("InhabitedTime", 0); //TODO + $nbt->setByte("TerrainPopulated", $chunk->isPopulated() ? 1 : 0); + $nbt->setByte("LightPopulated", $chunk->isLightPopulated() ? 1 : 0); - $nbt->Sections = new ListTag("Sections", [], NBT::TAG_Compound); - $subChunks = -1; + $subChunks = []; foreach($chunk->getSubChunks() as $y => $subChunk){ if($subChunk->isEmpty()){ continue; } + $tag = $this->serializeSubChunk($subChunk); $tag->setByte("Y", $y); - $nbt->Sections[++$subChunks] = $tag; + $subChunks[] = $tag; } + $nbt->setTag(new ListTag("Sections", $subChunks, NBT::TAG_Compound)); - $nbt->Biomes = new ByteArrayTag("Biomes", $chunk->getBiomeIdArray()); - $nbt->HeightMap = new IntArrayTag("HeightMap", $chunk->getHeightMapArray()); + $nbt->setByteArray("Biomes", $chunk->getBiomeIdArray()); + $nbt->setIntArray("HeightMap", $chunk->getHeightMapArray()); $entities = []; @@ -71,7 +73,7 @@ class Anvil extends McRegion{ } } - $nbt->Entities = new ListTag("Entities", $entities, NBT::TAG_Compound); + $nbt->setTag(new ListTag("Entities", $entities, NBT::TAG_Compound)); $tiles = []; foreach($chunk->getTiles() as $tile){ @@ -79,7 +81,7 @@ class Anvil extends McRegion{ $tiles[] = $tile->namedtag; } - $nbt->TileEntities = new ListTag("TileEntities", $tiles, NBT::TAG_Compound); + $nbt->setTag(new ListTag("TileEntities", $tiles, NBT::TAG_Compound)); //TODO: TileTicks @@ -104,43 +106,38 @@ class Anvil extends McRegion{ try{ $nbt->readCompressed($data); - $chunk = $nbt->getData(); + $chunk = $nbt->getData()->getCompoundTag("Level"); - if(!isset($chunk->Level) or !($chunk->Level instanceof CompoundTag)){ + if($chunk === null){ throw new ChunkException("Invalid NBT format"); } - $chunk = $chunk->Level; - $subChunks = []; - if($chunk->Sections instanceof ListTag){ - foreach($chunk->Sections as $subChunk){ - if($subChunk instanceof CompoundTag){ - $subChunks[$subChunk->Y->getValue()] = $this->deserializeSubChunk($subChunk); - } + $subChunksTag = $chunk->getListTag("Sections") ?? []; + foreach($subChunksTag as $subChunk){ + if($subChunk instanceof CompoundTag){ + $subChunks[$subChunk->getByte("Y")] = $this->deserializeSubChunk($subChunk); } } - if(isset($chunk->BiomeColors)){ - $biomeIds = ChunkUtils::convertBiomeColors($chunk->BiomeColors->getValue()); //Convert back to original format - }elseif(isset($chunk->Biomes)){ - $biomeIds = $chunk->Biomes->getValue(); + if($chunk->hasTag("BiomeColors", IntArrayTag::class)){ + $biomeIds = ChunkUtils::convertBiomeColors($chunk->getIntArray("BiomeColors")); //Convert back to original format }else{ - $biomeIds = ""; + $biomeIds = $chunk->getByteArray("Biomes", "", true); } $result = new Chunk( - $chunk["xPos"], - $chunk["zPos"], + $chunk->getInt("xPos"), + $chunk->getInt("zPos"), $subChunks, - isset($chunk->Entities) ? $chunk->Entities->getValue() : [], - isset($chunk->TileEntities) ? $chunk->TileEntities->getValue() : [], + $chunk->hasTag("Entities", ListTag::class) ? $chunk->getListTag("Entities")->getValue() : [], + $chunk->hasTag("TileEntities", ListTag::class) ? $chunk->getListTag("TileEntities")->getValue() : [], $biomeIds, - isset($chunk->HeightMap) ? $chunk->HeightMap->getValue() : [] + $chunk->getIntArray("HeightMap", []) ); - $result->setLightPopulated(isset($chunk->LightPopulated) ? ((bool) $chunk->LightPopulated->getValue()) : false); - $result->setPopulated(isset($chunk->TerrainPopulated) ? ((bool) $chunk->TerrainPopulated->getValue()) : false); - $result->setGenerated(true); + $result->setLightPopulated($chunk->getByte("LightPopulated", 0) !== 0); + $result->setPopulated($chunk->getByte("TerrainPopulated", 0) !== 0); + $result->setGenerated(); return $result; }catch(\Throwable $e){ MainLogger::getLogger()->logException($e); @@ -150,10 +147,10 @@ class Anvil extends McRegion{ protected function deserializeSubChunk(CompoundTag $subChunk) : SubChunk{ return new SubChunk( - ChunkUtils::reorderByteArray($subChunk->Blocks->getValue()), - ChunkUtils::reorderNibbleArray($subChunk->Data->getValue()), - ChunkUtils::reorderNibbleArray($subChunk->SkyLight->getValue(), "\xff"), - ChunkUtils::reorderNibbleArray($subChunk->BlockLight->getValue()) + ChunkUtils::reorderByteArray($subChunk->getByteArray("Blocks")), + ChunkUtils::reorderNibbleArray($subChunk->getByteArray("Data")), + ChunkUtils::reorderNibbleArray($subChunk->getByteArray("SkyLight"), "\xff"), + ChunkUtils::reorderNibbleArray($subChunk->getByteArray("BlockLight")) ); } diff --git a/src/pocketmine/level/format/io/region/McRegion.php b/src/pocketmine/level/format/io/region/McRegion.php index 2c505ce03..c5dd16505 100644 --- a/src/pocketmine/level/format/io/region/McRegion.php +++ b/src/pocketmine/level/format/io/region/McRegion.php @@ -53,12 +53,12 @@ class McRegion extends BaseLevelProvider{ */ public function nbtSerialize(Chunk $chunk) : string{ $nbt = new CompoundTag("Level", []); - $nbt->xPos = new IntTag("xPos", $chunk->getX()); - $nbt->zPos = new IntTag("zPos", $chunk->getZ()); + $nbt->setInt("xPos", $chunk->getX()); + $nbt->setInt("zPos", $chunk->getZ()); - $nbt->LastUpdate = new LongTag("LastUpdate", 0); //TODO - $nbt->TerrainPopulated = new ByteTag("TerrainPopulated", $chunk->isPopulated() ? 1 : 0); - $nbt->LightPopulated = new ByteTag("LightPopulated", $chunk->isLightPopulated() ? 1 : 0); + $nbt->setLong("LastUpdate", 0); //TODO + $nbt->setByte("TerrainPopulated", $chunk->isPopulated() ? 1 : 0); + $nbt->setByte("LightPopulated", $chunk->isLightPopulated() ? 1 : 0); $ids = ""; $data = ""; @@ -77,13 +77,13 @@ class McRegion extends BaseLevelProvider{ } } - $nbt->Blocks = new ByteArrayTag("Blocks", $ids); - $nbt->Data = new ByteArrayTag("Data", $data); - $nbt->SkyLight = new ByteArrayTag("SkyLight", $skyLight); - $nbt->BlockLight = new ByteArrayTag("BlockLight", $blockLight); + $nbt->setByteArray("Blocks", $ids); + $nbt->setByteArray("Data", $data); + $nbt->setByteArray("SkyLight", $skyLight); + $nbt->setByteArray("BlockLight", $blockLight); - $nbt->Biomes = new ByteArrayTag("Biomes", $chunk->getBiomeIdArray()); //doesn't exist in regular McRegion, this is here for PocketMine-MP only - $nbt->HeightMap = new ByteArrayTag("HeightMap", pack("C*", ...$chunk->getHeightMapArray())); + $nbt->setByteArray("Biomes", $chunk->getBiomeIdArray()); //doesn't exist in regular McRegion, this is here for PocketMine-MP only + $nbt->setByteArray("HeightMap", pack("C*", ...$chunk->getHeightMapArray())); //this is ByteArray in McRegion, but IntArray in Anvil (due to raised build height) $entities = []; @@ -94,7 +94,7 @@ class McRegion extends BaseLevelProvider{ } } - $nbt->Entities = new ListTag("Entities", $entities, NBT::TAG_Compound); + $nbt->setTag(new ListTag("Entities", $entities, NBT::TAG_Compound)); $tiles = []; foreach($chunk->getTiles() as $tile){ @@ -102,7 +102,7 @@ class McRegion extends BaseLevelProvider{ $tiles[] = $tile->namedtag; } - $nbt->TileEntities = new ListTag("TileEntities", $tiles, NBT::TAG_Compound); + $nbt->setTag(new ListTag("TileEntities", $tiles, NBT::TAG_Compound)); $writer = new NBT(NBT::BIG_ENDIAN); $nbt->setName("Level"); @@ -281,11 +281,11 @@ class McRegion extends BaseLevelProvider{ } public function getDifficulty() : int{ - return isset($this->levelData->Difficulty) ? $this->levelData->Difficulty->getValue() : Level::DIFFICULTY_NORMAL; + return $this->levelData->getByte("Difficulty", Level::DIFFICULTY_NORMAL); } public function setDifficulty(int $difficulty){ - $this->levelData->Difficulty = new ByteTag("Difficulty", $difficulty); + $this->levelData->setByte("Difficulty", $difficulty); } public function getChunk(int $chunkX, int $chunkZ, bool $create = false){ diff --git a/src/pocketmine/level/format/io/region/PMAnvil.php b/src/pocketmine/level/format/io/region/PMAnvil.php index 6e7cef20d..9b6a88749 100644 --- a/src/pocketmine/level/format/io/region/PMAnvil.php +++ b/src/pocketmine/level/format/io/region/PMAnvil.php @@ -23,14 +23,9 @@ declare(strict_types=1); namespace pocketmine\level\format\io\region; -use pocketmine\level\format\Chunk; -use pocketmine\level\format\ChunkException; use pocketmine\level\format\SubChunk; -use pocketmine\nbt\NBT; -use pocketmine\nbt\tag\{ - ByteArrayTag, ByteTag, CompoundTag, IntArrayTag, IntTag, ListTag, LongTag -}; -use pocketmine\utils\MainLogger; +use pocketmine\nbt\tag\ByteArrayTag; +use pocketmine\nbt\tag\CompoundTag; /** * This format is exactly the same as the PC Anvil format, with the only difference being that the stored data order @@ -51,10 +46,10 @@ class PMAnvil extends Anvil{ protected function deserializeSubChunk(CompoundTag $subChunk) : SubChunk{ return new SubChunk( - $subChunk->Blocks->getValue(), - $subChunk->Data->getValue(), - $subChunk->SkyLight->getValue(), - $subChunk->BlockLight->getValue() + $subChunk->getByteArray("Blocks"), + $subChunk->getByteArray("Data"), + $subChunk->getByteArray("SkyLight"), + $subChunk->getByteArray("BlockLight") ); } diff --git a/src/pocketmine/nbt/tag/ListTag.php b/src/pocketmine/nbt/tag/ListTag.php index bb0501ce5..ebff8ab11 100644 --- a/src/pocketmine/nbt/tag/ListTag.php +++ b/src/pocketmine/nbt/tag/ListTag.php @@ -88,6 +88,23 @@ class ListTag extends NamedTag implements \ArrayAccess, \Countable{ return $count; } + public function getAllValues() : array{ + $result = []; + foreach($this as $tag){ + if(!($tag instanceof NamedTag)){ + continue; + } + + if($tag instanceof \ArrayAccess){ + $result[] = $tag; + }else{ + $result[] = $tag->getValue(); + } + } + + return $result; + } + public function offsetExists($offset){ return isset($this->{$offset}); } diff --git a/src/pocketmine/network/mcpe/RakLibInterface.php b/src/pocketmine/network/mcpe/RakLibInterface.php index 7d888b448..dd9ece852 100644 --- a/src/pocketmine/network/mcpe/RakLibInterface.php +++ b/src/pocketmine/network/mcpe/RakLibInterface.php @@ -65,7 +65,7 @@ class RakLibInterface implements ServerInstance, AdvancedSourceInterface{ public function __construct(Server $server){ $this->server = $server; - $this->rakLib = new RakLibServer($this->server->getLogger(), $this->server->getLoader(), $this->server->getPort(), $this->server->getIp() === "" ? "0.0.0.0" : $this->server->getIp(), false); + $this->rakLib = new RakLibServer($this->server->getLogger(), \pocketmine\COMPOSER_AUTOLOADER_PATH, $this->server->getPort(), $this->server->getIp() === "" ? "0.0.0.0" : $this->server->getIp(), false); $this->interface = new ServerHandler($this->rakLib, $this); } diff --git a/src/pocketmine/tile/Spawnable.php b/src/pocketmine/tile/Spawnable.php index 076ce3412..598f6211c 100644 --- a/src/pocketmine/tile/Spawnable.php +++ b/src/pocketmine/tile/Spawnable.php @@ -107,10 +107,10 @@ abstract class Spawnable extends Tile{ */ final public function getSpawnCompound() : CompoundTag{ $nbt = new CompoundTag("", [ - $this->namedtag->getTag("id"), - $this->namedtag->getTag("x"), - $this->namedtag->getTag("y"), - $this->namedtag->getTag("z") + $this->namedtag->getTag(self::TAG_ID), + $this->namedtag->getTag(self::TAG_X), + $this->namedtag->getTag(self::TAG_Y), + $this->namedtag->getTag(self::TAG_Z) ]); $this->addAdditionalSpawnData($nbt); return $nbt; diff --git a/src/pocketmine/tile/Tile.php b/src/pocketmine/tile/Tile.php index 5e1efeeb3..a03134d5a 100644 --- a/src/pocketmine/tile/Tile.php +++ b/src/pocketmine/tile/Tile.php @@ -44,6 +44,11 @@ use pocketmine\Server; abstract class Tile extends Position{ + const TAG_ID = "id"; + const TAG_X = "x"; + const TAG_Y = "y"; + const TAG_Z = "z"; + const BREWING_STAND = "BrewingStand"; const CHEST = "Chest"; const ENCHANT_TABLE = "EnchantTable"; @@ -136,14 +141,14 @@ abstract class Tile extends Position{ $this->namedtag = $nbt; $this->server = $level->getServer(); $this->setLevel($level); - $this->chunk = $level->getChunk($this->namedtag->getInt("x") >> 4, $this->namedtag->getInt("z") >> 4, false); + $this->chunk = $level->getChunk($this->namedtag->getInt(self::TAG_X) >> 4, $this->namedtag->getInt(self::TAG_Z) >> 4, false); assert($this->chunk !== null); $this->name = ""; $this->id = Tile::$tileCount++; - $this->x = $this->namedtag->getInt("x"); - $this->y = $this->namedtag->getInt("y"); - $this->z = $this->namedtag->getInt("z"); + $this->x = $this->namedtag->getInt(self::TAG_X); + $this->y = $this->namedtag->getInt(self::TAG_Y); + $this->z = $this->namedtag->getInt(self::TAG_Z); $this->chunk->addTile($this); $this->getLevel()->addTile($this); @@ -154,10 +159,10 @@ abstract class Tile extends Position{ } public function saveNBT() : void{ - $this->namedtag->setString("id", static::getSaveId()); - $this->namedtag->setInt("x", $this->x); - $this->namedtag->setInt("y", $this->y); - $this->namedtag->setInt("z", $this->z); + $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); } public function getNBT() : CompoundTag{ @@ -167,7 +172,7 @@ abstract class Tile extends Position{ public function getCleanedNBT() : ?CompoundTag{ $this->saveNBT(); $tag = clone $this->namedtag; - $tag->removeTag("x", "y", "z", "id"); + $tag->removeTag(self::TAG_X, self::TAG_Y, self::TAG_Z, self::TAG_ID); if($tag->getCount() > 0){ return $tag; }else{ @@ -187,10 +192,10 @@ abstract class Tile extends Position{ */ public static function createNBT(Vector3 $pos, ?int $face = null, ?Item $item = null, ?Player $player = null) : CompoundTag{ $nbt = new CompoundTag("", [ - new StringTag("id", static::getSaveId()), - new IntTag("x", (int) $pos->x), - new IntTag("y", (int) $pos->y), - new IntTag("z", (int) $pos->z) + new StringTag(self::TAG_ID, static::getSaveId()), + new IntTag(self::TAG_X, (int) $pos->x), + new IntTag(self::TAG_Y, (int) $pos->y), + new IntTag(self::TAG_Z, (int) $pos->z) ]); static::createAdditionalNBT($nbt, $pos, $face, $item, $player); diff --git a/src/raklib b/src/raklib deleted file mode 160000 index 0e2611533..000000000 --- a/src/raklib +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0e26115330808b91ac3ab0b39e54fc9f9f679189 diff --git a/src/spl b/src/spl deleted file mode 160000 index cf7738721..000000000 --- a/src/spl +++ /dev/null @@ -1 +0,0 @@ -Subproject commit cf7738721e7342c018a91ad300108b2dd95c7224