summaryrefslogtreecommitdiffstats
path: root/logic/minecraft/World.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'logic/minecraft/World.cpp')
-rw-r--r--logic/minecraft/World.cpp188
1 files changed, 128 insertions, 60 deletions
diff --git a/logic/minecraft/World.cpp b/logic/minecraft/World.cpp
index 977a03cf..3b66f113 100644
--- a/logic/minecraft/World.cpp
+++ b/logic/minecraft/World.cpp
@@ -20,10 +20,13 @@
#include <pathutils.h>
#include "GZip.h"
+#include <MMCZip.h>
#include <sstream>
#include <io/stream_reader.h>
#include <tag_string.h>
#include <tag_primitive.h>
+#include <quazip.h>
+#include <quazipfile.h>
World::World(const QFileInfo &file)
{
@@ -32,8 +35,20 @@ World::World(const QFileInfo &file)
void World::repath(const QFileInfo &file)
{
- m_file = file;
+ m_containerFile = file;
m_folderName = file.fileName();
+ if(file.isFile() && file.suffix() == "zip")
+ {
+ readFromZip(file);
+ }
+ else if(file.isDir())
+ {
+ readFromFS(file);
+ }
+}
+
+void World::readFromFS(const QFileInfo &file)
+{
QDir worldDir(file.filePath());
is_valid = file.isDir() && worldDir.exists("level.dat");
if(!is_valid)
@@ -48,66 +63,123 @@ void World::repath(const QFileInfo &file)
{
return;
}
+ QFileInfo finfo(fullFilePath);
+ levelDatTime = finfo.lastModified();
+ parseLevelDat(f.readAll());
+}
- QByteArray output;
- is_valid = GZip::inflate(f.readAll(), output);
- if(!is_valid)
+void World::readFromZip(const QFileInfo &file)
+{
+ QuaZip zip(file.absoluteFilePath());
+ is_valid = zip.open(QuaZip::mdUnzip);
+ if (!is_valid)
+ {
+ return;
+ }
+ QuaZipFile zippedFile(&zip);
+ // read the install profile
+ is_valid = zip.setCurrentFile("level.dat");
+ if (!is_valid)
{
return;
}
- f.close();
+ is_valid = zippedFile.open(QIODevice::ReadOnly);
+ QuaZipFileInfo64 levelDatInfo;
+ zippedFile.getFileInfo(&levelDatInfo);
+ auto modTime = levelDatInfo.getNTFSmTime();
+ if(!modTime.isValid())
+ {
+ modTime = levelDatInfo.dateTime;
+ }
+ levelDatTime = modTime;
+ if (!is_valid)
+ {
+ return;
+ }
+ parseLevelDat(zippedFile.readAll());
+ zippedFile.close();
+}
- auto read_string = [](nbt::value& parent, const char * name, const QString & fallback = QString()) -> QString
+bool World::install(QString to)
+{
+ auto finalPath = PathCombine(to, DirNameFromString(m_actualName, to));
+ if(!ensureFolderPathExists(finalPath))
{
- try
- {
- auto &namedValue = parent.at(name);
- if(namedValue.get_type() != nbt::tag_type::String)
- {
- return fallback;
- }
- auto & tag_str = namedValue.as<nbt::tag_string>();
- return QString::fromStdString(tag_str.get());
- }
- catch(std::out_of_range e)
- {
- // fallback for old world formats
- qWarning() << "String NBT tag" << name << "could not be found. Defaulting to" << fallback;
- return fallback;
- }
- catch(std::bad_cast e)
- {
- // type mismatch
- qWarning() << "NBT tag" << name << "could not be converted to string. Defaulting to" << fallback;
- return fallback;
- }
- };
+ return false;
+ }
+ if(m_containerFile.isFile())
+ {
+ // FIXME: check if this is OK.
+ return !MMCZip::extractDir(m_containerFile.absoluteFilePath(), finalPath).isEmpty();
+ }
+ else if(m_containerFile.isDir())
+ {
+ QString from = m_containerFile.filePath();
+ return copyPath(from, finalPath);
+ }
+ return false;
+}
- auto read_long = [](nbt::value& parent, const char * name, const int64_t & fallback = 0) -> int64_t
+static QString read_string (nbt::value& parent, const char * name, const QString & fallback = QString())
+{
+ try
{
- try
- {
- auto &namedValue = parent.at(name);
- if(namedValue.get_type() != nbt::tag_type::Long)
- {
- return fallback;
- }
- auto & tag_str = namedValue.as<nbt::tag_long>();
- return tag_str.get();
- }
- catch(std::out_of_range e)
+ auto &namedValue = parent.at(name);
+ if(namedValue.get_type() != nbt::tag_type::String)
{
- // fallback for old world formats
- qWarning() << "Long NBT tag" << name << "could not be found. Defaulting to" << fallback;
return fallback;
}
- catch(std::bad_cast e)
+ auto & tag_str = namedValue.as<nbt::tag_string>();
+ return QString::fromStdString(tag_str.get());
+ }
+ catch(std::out_of_range e)
+ {
+ // fallback for old world formats
+ qWarning() << "String NBT tag" << name << "could not be found. Defaulting to" << fallback;
+ return fallback;
+ }
+ catch(std::bad_cast e)
+ {
+ // type mismatch
+ qWarning() << "NBT tag" << name << "could not be converted to string. Defaulting to" << fallback;
+ return fallback;
+ }
+};
+
+static int64_t read_long (nbt::value& parent, const char * name, const int64_t & fallback = 0)
+{
+ try
+ {
+ auto &namedValue = parent.at(name);
+ if(namedValue.get_type() != nbt::tag_type::Long)
{
- // type mismatch
- qWarning() << "NBT tag" << name << "could not be converted to long. Defaulting to" << fallback;
return fallback;
}
- };
+ auto & tag_str = namedValue.as<nbt::tag_long>();
+ return tag_str.get();
+ }
+ catch(std::out_of_range e)
+ {
+ // fallback for old world formats
+ qWarning() << "Long NBT tag" << name << "could not be found. Defaulting to" << fallback;
+ return fallback;
+ }
+ catch(std::bad_cast e)
+ {
+ // type mismatch
+ qWarning() << "NBT tag" << name << "could not be converted to long. Defaulting to" << fallback;
+ return fallback;
+ }
+};
+
+void World::parseLevelDat(QByteArray data)
+{
+ QByteArray output;
+ is_valid = GZip::inflate(data, output);
+ if(!is_valid)
+ {
+ return;
+ }
try
{
@@ -138,8 +210,7 @@ void World::repath(const QFileInfo &file)
int64_t temp = read_long(val, "LastPlayed", 0);
if(temp == 0)
{
- QFileInfo finfo(fullFilePath);
- m_lastPlayed = finfo.lastModified();
+ m_lastPlayed = levelDatTime;
}
else
{
@@ -164,11 +235,11 @@ bool World::replace(World &with)
{
if (!destroy())
return false;
- bool success = copyPath(with.m_file.filePath(), m_file.path());
+ bool success = copyPath(with.m_containerFile.filePath(), m_containerFile.path());
if (success)
{
m_folderName = with.m_folderName;
- m_file.refresh();
+ m_containerFile.refresh();
}
return success;
}
@@ -176,18 +247,15 @@ bool World::replace(World &with)
bool World::destroy()
{
if(!is_valid) return false;
- if (m_file.isDir())
+ if (m_containerFile.isDir())
{
- QDir d(m_file.filePath());
- if (d.removeRecursively())
- {
- return true;
- }
- return false;
+ QDir d(m_containerFile.filePath());
+ return d.removeRecursively();
}
- else
+ else if(m_containerFile.isFile())
{
- return false;
+ QFile file(m_containerFile.absoluteFilePath());
+ return file.remove();
}
return true;
}