From 02f23939f533f39fd5781d786de4462f137b5f3b Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 20 Feb 2026 15:28:15 +0200 Subject: [PATCH] fix: parse world_gen_settings.dat for seed fixes #5064 Minecraft moved the world gen settins outside the level.dat file. So now we need to check data/minecraft/world_gen_settings.dat for the seed. I did not bother with zip files(I did not even see the zip file in the launcher so I will not bother with it) Signed-off-by: Trial97 (cherry picked from commit e0139185c8e01574566c513032dc7f8a7fdb0079) --- launcher/minecraft/World.cpp | 57 ++++++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/launcher/minecraft/World.cpp b/launcher/minecraft/World.cpp index fca45fb99..a365eafc3 100644 --- a/launcher/minecraft/World.cpp +++ b/launcher/minecraft/World.cpp @@ -153,18 +153,23 @@ QByteArray serializeLevelDat(nbt::tag_compound* levelInfo) return val; } -QString getLevelDatFromFS(const QFileInfo& file) +QString getDatFromFS(const QFileInfo& root, QString file) { - QDir worldDir(file.filePath()); - if (!file.isDir() || !worldDir.exists("level.dat")) { + QDir worldDir(root.filePath()); + if (!root.isDir() || !worldDir.exists(file)) { return QString(); } - return worldDir.absoluteFilePath("level.dat"); + return worldDir.absoluteFilePath(file); } -QByteArray getLevelDatDataFromFS(const QFileInfo& file) +QString getLevelDatFromFS(const QFileInfo& file) { - auto fullFilePath = getLevelDatFromFS(file); + return getDatFromFS(file, "level.dat"); +} + +QByteArray getDatDataFromFS(const QFileInfo& root, QString file) +{ + auto fullFilePath = getDatFromFS(root, file); if (fullFilePath.isNull()) { return QByteArray(); } @@ -175,6 +180,16 @@ QByteArray getLevelDatDataFromFS(const QFileInfo& file) return f.readAll(); } +QByteArray getLevelDatDataFromFS(const QFileInfo& file) +{ + return getDatDataFromFS(file, "level.dat"); +} + +QByteArray getWorldGenDataFromFS(const QFileInfo& file) +{ + return getDatDataFromFS(file, "data/minecraft/world_gen_settings.dat"); +} + bool putLevelDatDataToFS(const QFileInfo& file, QByteArray& data) { auto fullFilePath = getLevelDatFromFS(file); @@ -229,6 +244,8 @@ bool World::resetIcon() return false; } +int64_t loadSeed(QByteArray data); + void World::readFromFS(const QFileInfo& file) { auto bytes = getLevelDatDataFromFS(file); @@ -238,6 +255,12 @@ void World::readFromFS(const QFileInfo& file) } loadFromLevelDat(bytes); m_levelDatTime = file.lastModified(); + if (m_randomSeed == 0) { + auto bytes = getWorldGenDataFromFS(file); + if (!bytes.isEmpty()) { + m_randomSeed = loadSeed(bytes); + } + } } void World::readFromZip(const QFileInfo& file) @@ -393,6 +416,28 @@ GameType read_gametype(nbt::value& parent, const char* name) } // namespace +int64_t loadSeed(QByteArray data) +{ + auto levelData = parseLevelDat(data); + if (!levelData) { + return 0; + } + + nbt::value* valPtr = nullptr; + try { + valPtr = &levelData->at("data"); + } catch (const std::out_of_range& e) { + return 0; + } + nbt::value& val = *valPtr; + + try { + return read_long(val, "seed").value_or(0); + } catch (const std::out_of_range&) { + } + return 0; +} + void World::loadFromLevelDat(QByteArray data) { auto levelData = parseLevelDat(data);