private static function parseCompoundTag(string $tag) : CompoundTag { if (self::$cachedParser === null) { self::$cachedParser = new NBT(NBT::LITTLE_ENDIAN); } self::$cachedParser->read($tag); return self::$cachedParser->getData(); }
public function __construct(Level $level, $path) { $this->level = $level; $this->path = $path; if (!file_exists($this->path)) { mkdir($this->path, 0777, true); } $nbt = new NBT(NBT::LITTLE_ENDIAN); $nbt->read(substr(file_get_contents($this->getPath() . "level.dat"), 8)); $levelData = $nbt->getData(); if ($levelData instanceof CompoundTag) { $this->levelData = $levelData; if (!isset($this->levelData["GameRules"])) { $this->levelData["GameRules"] = (new GameRules())->getRules(); } } else { throw new LevelException("Invalid level.dat"); } if (!isset($this->levelData->generatorName)) { $this->levelData->generatorName = new StringTag("generatorName", Generator::getGenerator("DEFAULT")); } if (!isset($this->levelData->generatorOptions)) { $this->levelData->generatorOptions = new StringTag("generatorOptions", ""); } $this->db = new \LevelDB($this->path . "db", ["compression" => LEVELDB_ZLIB_COMPRESSION]); }
public function readMacro($name) { if (!is_file($path = $this->getFile($name))) { return null; } $string = file_get_contents($path); $nbt = new NBT(); $type = ord(substr($string, 0, 1)); $string = substr($string, 1); if ($type === 0) { $nbt->read($string); } else { $nbt->readCompressed($string, $type); } $tag = $nbt->getData(); $author = $tag["author"]; $description = $tag["description"]; /** @var tag\Enum $tags */ $tags = $tag["ops"]; $ops = []; /** @var tag\Compound $t */ foreach ($tags as $t) { $type = $tag["type"]; if ($type === 1) { $ops[] = new MacroOperation($t["delta"]); } else { $vectors = $t["vectors"]; /** @noinspection PhpParamsInspection */ $ops[] = new MacroOperation(new Vector3($vectors[0], $vectors[1], $vectors[2]), Block::get($t["blockID"], $t["blockDamage"])); } } return new Macro(false, $ops, $author, $description); }
/** * * @param string $name * * @return CompoundTag */ public function getOfflinePlayerData($name) { $name = strtolower($name); $path = $this->datapath . "players/"; if (file_exists($path . "{$name}.dat")) { try { $nbt = new NBT(NBT::BIG_ENDIAN); $nbt->readCompressed(file_get_contents($path . "{$name}.dat")); return $nbt->getData(); } catch (\Throwable $e) { // zlib decode error / corrupt data rename($path . "{$name}.dat", $path . "{$name}.dat.bak"); } } $spawn = explode(':', $this->spawn); $nbt = new CompoundTag("", [new LongTag("firstPlayed", floor(microtime(true) * 1000)), new LongTag("lastPlayed", floor(microtime(true) * 1000)), new ListTag("Pos", [new DoubleTag(0, $spawn[0]), new DoubleTag(1, $spawn[1]), new DoubleTag(2, $spawn[2])]), new StringTag("Level", $spawn[3]), new ListTag("Inventory", []), new CompoundTag("Achievements", []), new IntTag("playerGameType", $this->gamemode), new ListTag("Motion", [new DoubleTag(0, 0.0), new DoubleTag(1, 0.0), new DoubleTag(2, 0.0)]), new ListTag("Rotation", [new FloatTag(0, 0.0), new FloatTag(1, 0.0)]), new FloatTag("FallDistance", 0.0), new ShortTag("Fire", 0), new ShortTag("Air", 300), new ByteTag("OnGround", 1), new ByteTag("Invulnerable", 0), new StringTag("NameTag", $name)]); $nbt->Pos->setTagType(NBT::TAG_Double); $nbt->Inventory->setTagType(NBT::TAG_Compound); $nbt->Motion->setTagType(NBT::TAG_Double); $nbt->Rotation->setTagType(NBT::TAG_Float); if (file_exists($path . "{$name}.yml")) { // Importing old PocketMine-MP files $data = new Config($path . "{$name}.yml", Config::YAML, []); $nbt["playerGameType"] = (int) $data->get("gamemode"); $nbt["Level"] = $data->get("position")["level"]; $nbt["Pos"][0] = $data->get("position")["x"]; $nbt["Pos"][1] = $data->get("position")["y"]; $nbt["Pos"][2] = $data->get("position")["z"]; $nbt["SpawnLevel"] = $data->get("spawn")["level"]; $nbt["SpawnX"] = (int) $data->get("spawn")["x"]; $nbt["SpawnY"] = (int) $data->get("spawn")["y"]; $nbt["SpawnZ"] = (int) $data->get("spawn")["z"]; foreach ($data->get("inventory") as $slot => $item) { if (count($item) === 3) { $nbt->Inventory[$slot + 9] = new CompoundTag("", [new ShortTag("id", $item[0]), new ShortTag("Damage", $item[1]), new ByteTag("Count", $item[2]), new ByteTag("Slot", $slot + 9), new ByteTag("TrueSlot", $slot + 9)]); } } foreach ($data->get("hotbar") as $slot => $itemSlot) { if (isset($nbt->Inventory[$itemSlot + 9])) { $item = $nbt->Inventory[$itemSlot + 9]; $nbt->Inventory[$slot] = new CompoundTag("", [new ShortTag("id", $item["id"]), new ShortTag("Damage", $item["Damage"]), new ByteTag("Count", $item["Count"]), new ByteTag("Slot", $slot), new ByteTag("TrueSlot", $item["TrueSlot"])]); } } foreach ($data->get("armor") as $slot => $item) { if (count($item) === 2) { $nbt->Inventory[$slot + 100] = new CompoundTag("", [new ShortTag("id", $item[0]), new ShortTag("Damage", $item[1]), new ByteTag("Count", 1), new ByteTag("Slot", $slot + 100)]); } } foreach ($data->get("achievements") as $achievement => $status) { $nbt->Achievements[$achievement] = new ByteTag($achievement, $status == true ? 1 : 0); } unlink($path . "{$name}.yml"); } return $nbt; }
public function __construct(Level $level, $path) { $this->level = $level; $this->path = $path; @mkdir($this->path, 0777, true); $nbt = new NBT(NBT::BIG_ENDIAN); $nbt->readCompressed(file_get_contents($this->getPath() . "level.dat")); $levelData = $nbt->getData(); if ($levelData->Data instanceof Compound) { $this->levelData = $levelData->Data; } else { throw new \Exception("Invalid level.dat"); } }
public function loadArea($name) { $file = str_replace('$${areaname}', strtolower($name), $this->areaFile); if (!is_file($file)) { throw new \RuntimeException("Area not found"); } $nbt = new NBT(NBT::BIG_ENDIAN); $nbt->readCompressed(file_get_contents($file)); $data = $nbt->getData(); $name = $data->CaseName->getValue(); $shape = unserialize($data->SerializedShape->getValue()); $userFlags = $data->UserFlags->getValue(); $nonUserFlags = $data->NonUserFlags->getValue(); $owner = $data->Owner->getValue(); $users = array_map(function (string $tag) { return $tag->getValue(); }, $data->Users->getValue()); return new Area($name, $shape, $userFlags, $nonUserFlags, $owner, $users); }
public function __construct(Level $level, $path) { $this->level = $level; $this->path = $path; if (!file_exists($this->path)) { mkdir($this->path, 0777, true); } $nbt = new NBT(NBT::BIG_ENDIAN); $nbt->readCompressed(file_get_contents($this->getPath() . "level.dat")); $levelData = $nbt->getData(); if ($levelData->Data instanceof Compound) { $this->levelData = $levelData->Data; } else { throw new LevelException("Invalid level.dat"); } if (!isset($this->levelData->generatorName)) { $this->levelData->generatorName = new String("generatorName", Generator::getGenerator("DEFAULT")); } if (!isset($this->levelData->generatorOptions)) { $this->levelData->generatorOptions = new String("generatorOptions", ""); } }
/** * @param string $name * * @return Compound */ public function getOfflinePlayerData($name) { $name = strtolower($name); $path = $this->getDataPath() . "players/"; if (file_exists($path . "{$name}.dat")) { try { $nbt = new NBT(NBT::BIG_ENDIAN); $nbt->readCompressed(file_get_contents($path . "{$name}.dat")); return $nbt->getData(); } catch (\Exception $e) { //zlib decode error / corrupt data rename($path . "{$name}.dat", $path . "{$name}.dat.bak"); $this->logger->notice($this->getLanguage()->translateString("pocketmine.data.playerCorrupted", [$name])); } } else { $this->logger->notice($this->getLanguage()->translateString("pocketmine.data.playerNotFound", [$name])); } $spawn = $this->getDefaultLevel()->getSafeSpawn(); $nbt = new Compound("", [new Long("firstPlayed", floor(microtime(true) * 1000)), new Long("lastPlayed", floor(microtime(true) * 1000)), new Enum("Pos", [new Double(0, $spawn->x), new Double(1, $spawn->y), new Double(2, $spawn->z)]), new String("Level", $this->getDefaultLevel()->getName()), new Enum("Inventory", []), new Compound("Achievements", []), new Int("playerGameType", $this->getGamemode()), new Enum("Motion", [new Double(0, 0.0), new Double(1, 0.0), new Double(2, 0.0)]), new Enum("Rotation", [new Float(0, 0.0), new Float(1, 0.0)]), new Float("FallDistance", 0.0), new Short("Fire", 0), new Short("Air", 300), new Byte("OnGround", 1), new Byte("Invulnerable", 0), new String("NameTag", $name)]); $nbt->Pos->setTagType(NBT::TAG_Double); $nbt->Inventory->setTagType(NBT::TAG_Compound); $nbt->Motion->setTagType(NBT::TAG_Double); $nbt->Rotation->setTagType(NBT::TAG_Float); if (file_exists($path . "{$name}.yml")) { //Importing old PocketMine-MP files $data = new Config($path . "{$name}.yml", Config::YAML, []); $nbt["playerGameType"] = (int) $data->get("gamemode"); $nbt["Level"] = $data->get("position")["level"]; $nbt["Pos"][0] = $data->get("position")["x"]; $nbt["Pos"][1] = $data->get("position")["y"]; $nbt["Pos"][2] = $data->get("position")["z"]; $nbt["SpawnLevel"] = $data->get("spawn")["level"]; $nbt["SpawnX"] = (int) $data->get("spawn")["x"]; $nbt["SpawnY"] = (int) $data->get("spawn")["y"]; $nbt["SpawnZ"] = (int) $data->get("spawn")["z"]; $this->logger->notice($this->getLanguage()->translateString("pocketmine.data.playerOld", [$name])); foreach ($data->get("inventory") as $slot => $item) { if (count($item) === 3) { $nbt->Inventory[$slot + 9] = new Compound("", [new Short("id", $item[0]), new Short("Damage", $item[1]), new Byte("Count", $item[2]), new Byte("Slot", $slot + 9), new Byte("TrueSlot", $slot + 9)]); } } foreach ($data->get("hotbar") as $slot => $itemSlot) { if (isset($nbt->Inventory[$itemSlot + 9])) { $item = $nbt->Inventory[$itemSlot + 9]; $nbt->Inventory[$slot] = new Compound("", [new Short("id", $item["id"]), new Short("Damage", $item["Damage"]), new Byte("Count", $item["Count"]), new Byte("Slot", $slot), new Byte("TrueSlot", $item["TrueSlot"])]); } } foreach ($data->get("armor") as $slot => $item) { if (count($item) === 2) { $nbt->Inventory[$slot + 100] = new Compound("", [new Short("id", $item[0]), new Short("Damage", $item[1]), new Byte("Count", 1), new Byte("Slot", $slot + 100)]); } } foreach ($data->get("achievements") as $achievement => $status) { $nbt->Achievements[$achievement] = new Byte($achievement, $status == true ? 1 : 0); } unlink($path . "{$name}.yml"); } $this->saveOfflinePlayerData($name, $nbt); return $nbt; }
/** * @param string $data * @param LevelProvider $provider * * @return Chunk */ public static function fromBinary($data, LevelProvider $provider = \null) { $nbt = new NBT(NBT::BIG_ENDIAN); try { $nbt->readCompressed($data, ZLIB_ENCODING_DEFLATE); $chunk = $nbt->getData(); if (!isset($chunk->Level) or !$chunk->Level instanceof Compound) { return \null; } return new Chunk($provider instanceof LevelProvider ? $provider : McRegion::class, $chunk->Level); } catch (\Exception $e) { return \null; } }
/** * @param string $data * @param LevelProvider $provider * * @return Chunk */ public static function fromFastBinary($data, LevelProvider $provider = \null) { $nbt = new NBT(NBT::BIG_ENDIAN); try { $nbt->read($data); $chunk = $nbt->getData(); if (!isset($chunk->Level) or !$chunk->Level instanceof Compound) { return \null; } return new Chunk($provider instanceof LevelProvider ? $provider : Anvil::class, $chunk->Level); } catch (\Exception $e) { return \null; } }
/** * @param string $data * @param LevelProvider $provider * * @return Chunk */ public static function fromBinary($data, LevelProvider $provider = null) { try { $chunkX = PHP_INT_SIZE === 8 ? unpack("V", substr($data, 0, 4))[1] << 32 >> 32 : unpack("V", substr($data, 0, 4))[1]; $chunkZ = PHP_INT_SIZE === 8 ? unpack("V", substr($data, 4, 4))[1] << 32 >> 32 : unpack("V", substr($data, 4, 4))[1]; $chunkData = substr($data, 8, -1); $flags = ord(substr($data, -1)); $entities = null; $tiles = null; if ($provider instanceof LevelDB) { $nbt = new NBT(NBT::LITTLE_ENDIAN); $entityData = $provider->getDatabase()->get(substr($data, 0, 8) . "2"); if ($entityData !== false and strlen($entityData) > 0) { $nbt->read($entityData, true); $entities = $nbt->getData(); if (!is_array($entities)) { $entities = [$entities]; } } $tileData = $provider->getDatabase()->get(substr($data, 0, 8) . "1"); if ($tileData !== false and strlen($tileData) > 0) { $nbt->read($tileData, true); $tiles = $nbt->getData(); if (!is_array($tiles)) { $tiles = [$tiles]; } } } $chunk = new Chunk($provider instanceof LevelProvider ? $provider : LevelDB::class, $chunkX, $chunkZ, $chunkData, $entities, $tiles); if ($flags & 0x1) { $chunk->setGenerated(); } if ($flags & 0x2) { $chunk->setPopulated(); } return $chunk; } catch (\Exception $e) { return null; } }
public function getPlayerData($name, $data) { $name = \strtolower($name); $path = $this->plugin->getServer()->getDataPath() . "players/"; if ($data !== null) { $data = mb_convert_encoding($data, "ISO-8859-1", "UTF-8"); try { $nbt = new NBT(NBT::BIG_ENDIAN); $nbt->readCompressed($data); return $nbt->getData(); } catch (\Exception $e) { // zlib decode error / corrupt data return null; } } else { $this->plugin->getLogger()->notice($this->plugin->getServer()->getLanguage()->translateString("pocketmine.data.playerNotFound", [$name])); } $spawn = $this->plugin->getServer()->getDefaultLevel()->getSafeSpawn(); $nbt = new Compound("", [new Long("firstPlayed", \floor(\microtime(\true) * 1000)), new Long("lastPlayed", \floor(\microtime(\true) * 1000)), new Enum("Pos", [new Double(0, $spawn->x), new Double(1, $spawn->y), new Double(2, $spawn->z)]), new String("Level", $this->plugin->getServer()->getDefaultLevel()->getName()), new Enum("Inventory", []), new Compound("Achievements", []), new Int("playerGameType", $this->plugin->getServer()->getGamemode()), new Enum("Motion", [new Double(0, 0.0), new Double(1, 0.0), new Double(2, 0.0)]), new Enum("Rotation", [new Float(0, 0.0), new Float(1, 0.0)]), new Float("FallDistance", 0.0), new Short("Fire", 0), new Short("Air", 300), new Byte("OnGround", 1), new Byte("Invulnerable", 0), new String("NameTag", $name)]); $nbt->Pos->setTagType(NBT::TAG_Double); $nbt->Inventory->setTagType(NBT::TAG_Compound); $nbt->Motion->setTagType(NBT::TAG_Double); $nbt->Rotation->setTagType(NBT::TAG_Float); return $nbt; }
public function import() { if (file_exists($this->path . "tileEntities.dat")) { //OldPM $level = unserialize(file_get_contents($this->path . "level.dat")); MainLogger::getLogger()->info("Importing OldPM level \"" . $level["LevelName"] . "\" to PMF format"); $entities = new Config($this->path . "entities.yml", Config::YAML, unserialize(file_get_contents($this->path . "entities.dat"))); $entities->save(); $tiles = new Config($this->path . "tiles.yml", Config::YAML, unserialize(file_get_contents($this->path . "tileEntities.dat"))); $tiles->save(); } elseif (file_exists($this->path . "chunks.dat") and file_exists($this->path . "level.dat")) { //Pocket $nbt = new NBT(NBT::LITTLE_ENDIAN); $nbt->read(substr(file_get_contents($this->path . "level.dat"), 8)); $level = $nbt->getData(); if ($level["LevelName"] == "") { $level["LevelName"] = "world" . time(); } MainLogger::getLogger()->info("Importing Pocket level \"" . $level->LevelName . "\" to PMF format"); unset($level->Player); $nbt->read(substr(file_get_contents($this->path . "entities.dat"), 12)); $entities = $nbt->getData(); if (!isset($entities->TileEntities)) { $entities->TileEntities = []; } $tiles = $entities->TileEntities; $entities = $entities->Entities; $entities = new Config($this->path . "entities.yml", Config::YAML, $entities); $entities->save(); $tiles = new Config($this->path . "tiles.yml", Config::YAML, $tiles); $tiles->save(); } else { return false; } $pmf = new LevelFormat($this->path . "level.pmf", ["name" => $level->LevelName, "seed" => $level->RandomSeed, "time" => $level->Time, "spawnX" => $level->SpawnX, "spawnY" => $level->SpawnY, "spawnZ" => $level->SpawnZ, "height" => 8, "generator" => "default", "generatorSettings" => "", "extra" => ""]); $chunks = new PocketChunkParser(); $chunks->loadFile($this->path . "chunks.dat"); $chunks->loadMap(); for ($Z = 0; $Z < 16; ++$Z) { for ($X = 0; $X < 16; ++$X) { $chunk = [0 => "", 1 => "", 2 => "", 3 => "", 4 => "", 5 => "", 6 => "", 7 => ""]; $pmf->initCleanChunk($X, $Z); for ($z = 0; $z < 16; ++$z) { for ($x = 0; $x < 16; ++$x) { $block = $chunks->getChunkColumn($X, $Z, $x, $z, 0); $meta = $chunks->getChunkColumn($X, $Z, $x, $z, 1); for ($Y = 0; $Y < 8; ++$Y) { $chunk[$Y] .= substr($block, $Y << 4, 16); $chunk[$Y] .= substr($meta, $Y << 3, 8); $chunk[$Y] .= ""; } } } foreach ($chunk as $Y => $data) { $pmf->setMiniChunk($X, $Z, $Y, $data); } $pmf->setPopulated($X, $Z); $pmf->saveChunk($X, $Z); } MainLogger::getLogger()->notice("Importing level " . ceil(($Z + 1) / 0.16) . "%"); } $chunks->map = null; $chunks = null; @unlink($this->path . "level.dat"); @unlink($this->path . "level.dat_old"); @unlink($this->path . "player.dat"); @unlink($this->path . "entities.dat"); @unlink($this->path . "chunks.dat"); @unlink($this->path . "chunks.dat.gz"); @unlink($this->path . "tiles.dat"); unset($chunks, $level, $entities, $tiles, $nbt); return true; }
/** * Creates a new clip using data from database for reading * * @param string $compressed * * @return Clip */ public static function createFromSaved($compressed) { $nbt = new NBT(); $nbt->readCompressed($compressed); $data = $nbt->getData(); $instance = new Clip($data["Name"], false); $instance->owner = $data["Owner"]; $instance->creationTime = $data["Creation"]; /** @var Enum $entriesTag */ $entriesTag = $data["Entries"]; for ($i = 0; $i < $entriesTag->getCount(); $i++) { $blockTag = $entriesTag[$i]; $block = Block::get($blockTag["Id"], $blockTag["Damage"], new Position($blockTag["X"], $blockTag["Y"], $blockTag["Z"])); $instance->entries[] = $block; } return $instance; }
public function loadChunk($X, $Z) { if ($this->isChunkLoaded($X, $Z)) { return true; } $index = self::getIndex($X, $Z); $path = $this->getChunkPath($X, $Z); if (!file_exists($path)) { if ($this->generateChunk($X, $Z) === false) { return false; } if ($this->isGenerating === 0) { $this->populateChunk($X, $Z); } return true; } $chunk = file_get_contents($path); if ($chunk === false) { return false; } $chunk = zlib_decode($chunk); $offset = 0; $this->chunkInfo[$index] = [0 => ord($chunk[0]), 1 => Binary::readInt(substr($chunk, 1, 4))]; $offset += 5; $len = Binary::readInt(substr($chunk, $offset, 4)); $offset += 4; $nbt = new NBT(NBT::BIG_ENDIAN); $nbt->read(substr($chunk, $offset, $len)); $this->chunkInfo[$index][2] = $nbt->getData(); $offset += $len; $this->chunks[$index] = []; $this->chunkChange[$index] = [-1 => false]; $this->chunkInfo[$index][3] = substr($chunk, $offset, 256); //Biome data $offset += 256; for ($Y = 0; $Y < 8; ++$Y) { if (($this->chunkInfo[$index][0] & 1 << $Y) !== 0) { // 4096 + 2048 + 2048, Block Data, Meta, Light if (strlen($this->chunks[$index][$Y] = substr($chunk, $offset, 8192)) < 8192) { MainLogger::getLogger()->notice("Empty corrupt chunk detected [{$X},{$Z},:{$Y}], recovering contents"); $this->fillMiniChunk($X, $Z, $Y); } $offset += 8192; } else { $this->chunks[$index][$Y] = false; } } if ($this->isGenerating === 0 and !$this->isPopulated($X, $Z)) { $this->populateChunk($X, $Z); } return true; }
/** * @param string $name * * @return Compound */ public function getOfflinePlayerData($name) { $name = strtolower($name); if ($this->katana->getProperty("console.save-player.data", false)) { $path = $this->getDataPath() . "players/"; if (file_exists($path . "{$name}.dat")) { try { $nbt = new NBT(NBT::BIG_ENDIAN); $nbt->readCompressed(file_get_contents($path . "{$name}.dat")); return $nbt->getData(); } catch (\Exception $e) { //zlib decode error / corrupt data rename($path . "{$name}.dat", $path . "{$name}.dat.bak"); $this->logger->notice($this->getLanguage()->translateString("pocketmine.data.playerCorrupted", [$name])); } } else { $this->logger->notice($this->getLanguage()->translateString("pocketmine.data.playerNotFound", [$name])); } } $spawn = $this->getDefaultLevel()->getSafeSpawn(); $nbt = new Compound("", [new Long("firstPlayed", floor(microtime(true) * 1000)), new Long("lastPlayed", floor(microtime(true) * 1000)), new Enum("Pos", [new Double(0, $spawn->x), new Double(1, $spawn->y), new Double(2, $spawn->z)]), new String("Level", $this->getDefaultLevel()->getName()), new Enum("Inventory", []), new Compound("Achievements", []), new Int("playerGameType", $this->getGamemode()), new Enum("Motion", [new Double(0, 0.0), new Double(1, 0.0), new Double(2, 0.0)]), new Enum("Rotation", [new Float(0, 0.0), new Float(1, 0.0)]), new Float("FallDistance", 0.0), new Short("Fire", 0), new Short("Air", 300), new Byte("OnGround", 1), new Byte("Invulnerable", 0), new String("NameTag", $name)]); $nbt->Pos->setTagType(NBT::TAG_Double); $nbt->Inventory->setTagType(NBT::TAG_Compound); $nbt->Motion->setTagType(NBT::TAG_Double); $nbt->Rotation->setTagType(NBT::TAG_Float); $this->saveOfflinePlayerData($name, $nbt); return $nbt; }
/** * @param string $data * @param LevelProvider $provider * * @return Chunk */ public static function fromBinary($data, LevelProvider $provider = \null) { try { $chunkX = \unpack("V", \substr($data, 0, 4))[1]; $chunkZ = \unpack("V", \substr($data, 4, 4))[1]; $chunkData = \substr($data, 8, -1); $flags = \ord(\substr($data, -1)); $entities = \null; $tiles = \null; $extraData = []; if ($provider instanceof LevelDB) { $nbt = new NBT(NBT::LITTLE_ENDIAN); $entityData = $provider->getDatabase()->get(\substr($data, 0, 8) . LevelDB::ENTRY_ENTITIES); if ($entityData !== \false and \strlen($entityData) > 0) { $nbt->read($entityData, \true); $entities = $nbt->getData(); if (!\is_array($entities)) { $entities = [$entities]; } } $tileData = $provider->getDatabase()->get(\substr($data, 0, 8) . LevelDB::ENTRY_TILES); if ($tileData !== \false and \strlen($tileData) > 0) { $nbt->read($tileData, \true); $tiles = $nbt->getData(); if (!\is_array($tiles)) { $tiles = [$tiles]; } } $tileData = $provider->getDatabase()->get(\substr($data, 0, 8) . LevelDB::ENTRY_EXTRA_DATA); if ($tileData !== \false and \strlen($tileData) > 0) { $stream = new BinaryStream($tileData); $count = $stream->getInt(); for ($i = 0; $i < $count; ++$i) { $key = $stream->getInt(); $value = $stream->getShort(\false); $extraData[$key] = $value; } } } $chunk = new Chunk($provider instanceof LevelProvider ? $provider : LevelDB::class, $chunkX, $chunkZ, $chunkData, $entities, $tiles); if ($flags & 0x1) { $chunk->setGenerated(); } if ($flags & 0x2) { $chunk->setPopulated(); } if ($flags & 0x4) { $chunk->setLightPopulated(); } return $chunk; } catch (\Exception $e) { return \null; } }