From 38693e1d6ca7f05d9488348ddf298488d1cc0995 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sun, 6 Sep 2015 23:35:58 +0200 Subject: GH-1047 parse world files and integrate MCEdit with world page --- logic/minecraft/World.cpp | 126 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 121 insertions(+), 5 deletions(-) (limited to 'logic/minecraft/World.cpp') diff --git a/logic/minecraft/World.cpp b/logic/minecraft/World.cpp index 3443fb45..4ef7845f 100644 --- a/logic/minecraft/World.cpp +++ b/logic/minecraft/World.cpp @@ -15,9 +15,16 @@ #include #include +#include #include "World.h" #include +#include "GZip.h" +#include +#include +#include +#include + World::World(const QFileInfo &file) { repath(file); @@ -26,8 +33,117 @@ World::World(const QFileInfo &file) void World::repath(const QFileInfo &file) { m_file = file; - m_name = file.fileName(); - is_valid = file.isDir() && QDir(file.filePath()).exists("level.dat"); + m_folderName = file.fileName(); + QDir worldDir(file.filePath()); + is_valid = file.isDir() && worldDir.exists("level.dat"); + if(!is_valid) + { + return; + } + + auto fullFilePath = worldDir.absoluteFilePath("level.dat"); + QFile f(fullFilePath); + is_valid = f.open(QIODevice::ReadOnly); + if(!is_valid) + { + return; + } + + QByteArray output; + is_valid = GZip::inflate(f.readAll(), output); + if(!is_valid) + { + return; + } + f.close(); + + auto read_string = [](nbt::value& parent, const char * name, const QString & fallback = QString()) -> QString + { + try + { + auto &namedValue = parent.at(name); + if(namedValue.get_type() != nbt::tag_type::String) + { + return fallback; + } + auto & tag_str = namedValue.as(); + return QString::fromStdString(tag_str.get()); + } + catch(std::out_of_range e) + { + // fallback for old world formats + return fallback; + } + }; + + auto read_long = [](nbt::value& parent, const char * name, const int64_t & fallback = 0) -> int64_t + { + try + { + auto &namedValue = parent.at(name); + if(namedValue.get_type() != nbt::tag_type::Long) + { + return fallback; + } + auto & tag_str = namedValue.as(); + return tag_str.get(); + } + catch(std::out_of_range e) + { + // fallback for old world formats + return fallback; + } + }; + + try + { + std::istringstream foo(std::string(output.constData(), output.size())); + auto pair = nbt::io::read_compound(foo); + is_valid = pair.first == ""; + + if(!is_valid) + { + return; + } + std::ostringstream ostr; + is_valid = pair.second != nullptr; + if(!is_valid) + { + qDebug() << "FAIL~!!!"; + return; + } + + auto &val = pair.second->at("Data"); + is_valid = val.get_type() == nbt::tag_type::Compound; + if(!is_valid) + return; + + m_actualName = read_string(val, "LevelName", m_folderName); + + + int64_t temp = read_long(val, "LastPlayed", 0); + if(temp == 0) + { + QFileInfo finfo(fullFilePath); + m_lastPlayed = finfo.lastModified(); + } + else + { + m_lastPlayed = QDateTime::fromMSecsSinceEpoch(temp); + } + + m_randomSeed = read_long(val, "RandomSeed", 0); + + qDebug() << "World Name:" << m_actualName; + qDebug() << "Last Played:" << m_lastPlayed.toString(); + qDebug() << "Seed:" << m_randomSeed; + } + catch (nbt::io::input_error e) + { + qWarning() << "Unable to load" << m_folderName << ":" << e.what(); + is_valid = false; + return; + } } bool World::replace(World &with) @@ -37,7 +153,7 @@ bool World::replace(World &with) bool success = copyPath(with.m_file.filePath(), m_file.path()); if (success) { - m_name = with.m_name; + m_folderName = with.m_folderName; m_file.refresh(); } return success; @@ -64,9 +180,9 @@ bool World::destroy() bool World::operator==(const World &other) const { - return is_valid == other.is_valid && name() == other.name(); + return is_valid == other.is_valid && folderName() == other.folderName(); } bool World::strongCompare(const World &other) const { - return is_valid == other.is_valid && name() == other.name(); + return is_valid == other.is_valid && folderName() == other.folderName(); } -- cgit v1.2.3