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.cpp126
1 files changed, 121 insertions, 5 deletions
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 <QDir>
#include <QString>
+#include <QDebug>
#include "World.h"
#include <pathutils.h>
+#include "GZip.h"
+#include <sstream>
+#include <io/stream_reader.h>
+#include <tag_string.h>
+#include <tag_primitive.h>
+
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<nbt::tag_string>();
+ 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<nbt::tag_long>();
+ 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();
}